Unidades contadas, peso por piezas y sustitución por cambio de unidad base
Vende en paquetes, cajas o piezas un producto medido en kilos o litros, registra las piezas en las líneas de peso variable, sustituye un producto por otro con distinta unidad base con vista previa y ejecución irreversible, y lee la unidad real en FacturaE y UBL. Dos operaciones nuevas, dos tools MCP, el evento product.replaced y campos nuevos en productos y líneas de documento.
15 de octubre de 2026 — Un producto medido en kilos, litros o metros ahora se puede vender en unidades contadas como paquetes, cajas o piezas, y un producto que ya tiene historial puede cambiar de unidad base sustituyéndolo por uno nuevo. Todo es aditivo: ningún campo existente cambia de significado.
Unidades contadas
Hay 22 códigos de unidad en total: 9 unidades de medida y 13 unidades contadas.
| Clase | Unidades (código UN/ECE) | Dónde se pueden usar |
|---|---|---|
| Medida | unidad C62, kilogramo KGM, gramo GRM, litro LTR, mililitro MLT, metro MTR, metro cuadrado MTK, hora HUR, día DAY | Unidad base, presentaciones, ofertas de proveedor, tarifas y líneas de documento |
| Contada | pieza H87, paquete XPK, caja XBX, bandeja XDS, bolsa XBG, botella XBO, garrafa XDJ, lata XCA, tarrina XTB, bote XCI, bidón XJY, sobre XEN, estuche XCS | Presentaciones, ofertas de proveedor, tarifas y líneas de documento |
base_unit solo admite las 9 unidades de medida; las unidades contadas son unidades
comerciales.
- Presentaciones y ofertas de proveedor. Una presentación fija en una unidad contada
puede apoyarse en una base medida si declara su equivalencia (
conversion_factoronominal_base_quantity): «1 paquete = 0,5 kg». Una unidad de medida debe pertenecer a la misma familia que la base. Una presentación o una oferta cuya unidad no se puede expresar sobre la unidad base del producto se rechaza con422 unit_not_expressible. - Peso por piezas. Una presentación de peso variable cuya unidad es una unidad
contada acepta en
counted_quantitylas piezas que pidió el cliente. La línea se sigue cobrando, y el stock se sigue descontando, porquantity, el peso real en la unidad base; las piezas son informativas. - Documentos. Las líneas de factura, presupuesto, proforma, albarán y factura
recurrente llevan
counted_quantityycounted_unit, ambosnullcuando la línea no tiene piezas contadas. El editor, el PDF, el ticket y el enlace público muestran «4 paquetes = 2 kg» o «3 piezas · 1,520 kg × 4,55 €/kg». - FacturaE y UBL. FacturaE declara el
UnitOfMeasurereal de cada línea y UBL envía suunitCodeUN/ECE real.
Sustitución por cambio de unidad base
La unidad base de un producto con historial (stock, movimientos, presentaciones, ofertas
de proveedor o variantes con stock) no se edita en el sitio. El producto lo indica ahora
en base_unit_change, y el cambio se hace sustituyendo el producto por uno nuevo.
- Vista previa de la sustitución por cambio de unidad base
calcula, sin escribir nada, el plan y un
impact_tokenque confirma ese plan exacto. Envías la unidad base nueva (target_base_unit, una de las 9 unidades de medida), laequivalenceentre ambas unidades, unbase_priceopcional y una decisiónkeeporetirepor presentación. - Sustituir un producto cambiando su unidad base
la ejecuta y responde
201con el producto nuevo. Es irreversible, así queIdempotency-Keyes obligatoria. El stock, las presentaciones que conservas, las variantes, las ofertas de proveedor, las entradas de tarifa y los componentes de pack pasan al producto nuevo, convertidos a su unidad. El producto anterior se desactiva, conserva todo su historial y no se puede reactivar nunca. No consume cuota del plan. - Si la conversión pierde precisión o no hay equivalencia, hay que confirmar
base_price(422 base_unit_replacement_price_confirmation_required). Si el catálogo, las tarifas o los packs cambian después de la vista previa, la confirmación se rechaza con422 base_unit_replacement_preview_staley se pide una vista previa nueva. - Los demás rechazos de la sustitución son
422 business_rule_violationcon subcódigoproduct_already_replaced,base_unit_replacement_conversion_unavailableobase_unit_replacement_blocked_by_packs, y422 parameter_invalid_valuecon subcódigobase_unit_replacement_same_unit(el destino ya es la unidad base del producto),base_unit_replacement_equivalence_invalidobase_unit_replacement_decision_invalid. - La
equivalencees el número de unidades de la base actual que equivalen a una unidad de la nueva. Es obligatoria entre una unidad de recuento y una de medida, en cualquier sentido; dentro de la misma familia de medida se calcula sola, y entre dos familias de medida distintas no existe. - Un producto que participa en una sustitución, como producto anterior o como nuevo, no
se puede eliminar: Elimina un producto
y Elimina varios productos de forma masiva
responden
422con subcódigoproduct_in_base_unit_replacement, y en la operación en bloque el producto figura enfailed[]con ese motivo. Las tools MCPdelete_productybulk_delete_productsaplican la misma regla. - Editar
base_uniten un producto cuyobase_unit_change.modeesreplacementresponde422 business_rule_violationcon subcódigoproduct_base_unit_locked.
Campos, eventos y MCP
- Producto.
base_unit_change(modey losblockerscuantificados),replacesyreplaced_by(id,name,base_unit,replaced_at,equivalenceystock_transferred). Se devuelven en las lecturas de un solo producto y se omiten en los listados. - Evento.
product.replacedse publica con el producto nuevo como objeto. Consulta Eventos. - Movimientos de stock. Los motivos
base_unit_replacement_outybase_unit_replacement_iny el origenbase_unit_replacementregistran el traspaso entre ambos productos. - Tarifas. El motivo de retirada
product_replacedidentifica las entradas del producto sustituido. - MCP. Dos tools nuevas,
preview_product_base_unit_replacementyreplace_product_base_unit, ambas con el scopeproducts:write; la segunda es irreversible y aceptaidempotency_key. Consulta el catálogo de tools.
Los componentes de un pack no admiten piezas: components.*.counted_quantity responde
422 si llega con valor, porque las piezas pertenecen a las líneas de los documentos de
venta.
Las operaciones que leen o escriben productos, presentaciones, ofertas de proveedor, tarifas y documentos de venta conservan sus scopes, y sus respuestas y cuerpos incorporan los campos y códigos de unidad descritos.
Nuevos endpoints2
| Endpoint | Descripción |
|---|---|
POST/v1/products/{product}/base_unit_replacement/preview | Vista previa de la sustitución por cambio de unidad base |
POST/v1/products/{product}/base_unit_replacement | Sustituir un producto cambiando su unidad base |