Fix backend — Alta de ítems simples sin almacén (dropship) falla el pedido¶
Fecha: 2026-07-20. Audiencia: agente de backend (NestJS). Tipo: bug fix puntual. Estado: diagnosticado, listo para implementar.
Síntoma¶
Al guardar un pedido con un producto simple que aún no existe en SAP (dropship), el backend falla: el ítem no queda usable y el POST del pedido intenta agregar un ítem que "no existe" en el depósito de la línea. (Los combos no tienen este problema; su flujo crea con almacén explícito.)
Causa raíz¶
OrdersService.processOrderLines (src/modules/orders/orders.service.ts), paso 3 — creación del
ítem faltante (líneas ~128-171):
const createdItem = await this.itemsService.create(itemToCreate); // ← SIN opciones
Se llama a create sin warehouseCodes, pero el ítem se crea con InventoryItem: 'tYES'
(default de STATIC_ITEM_DATA_FOR_CREATION, items.service.ts:29-39).
El mapper solo agrega ItemWarehouseInfoCollection si recibe warehouseCodes
(src/modules/items/mappers/item.mapper.ts:167). Su propio comentario lo advierte:
"Almacenes a asignar explícitamente. Sin esto, el ítem queda sin filas de almacén cuando la parametrización de empresa no asigna todos los almacenes (dev), y la explosión del BOM en el pedido falla con
Internal error (-10)."
Resultado: el ítem simple se crea sin filas de almacén; la línea del pedido lo referencia en
WarehouseCode (p. ej. CEN), un depósito donde el ítem no tiene fila → SAP lo rechaza.
Es la misma trampa que ya documentó 03 §2 y que el flujo
de combos evita pasando almacenes explícitos. El flujo legacy de simples nunca lo hizo, por eso
solo se ve con ítems realmente nuevos (los que resuelven por SupplierCatalogNo a un ítem
existente no pasan por la creación).
Fix¶
Pasar el depósito de la línea al crear. itemsService.create ya acepta la opción
(items.service.ts:48-62; la usa el flujo de combos):
const createdItem = await this.itemsService.create(itemToCreate, {
warehouseCodes: [line.WarehouseCode ?? 'CEN'],
});
line.WarehouseCodeestá disponible enCreateOrderLineDto.- No requiere cambios de frontend: el front ya envía
WarehouseCode,ItemNameySupplierCatalogNoen la línea.
Corrección posterior (2026-07-20) — asignar TODOS los almacenes activos¶
El fix inicial pasaba solo el almacén de la línea. Eso desbloqueó el primer pedido pero
dejó un segundo bug: al pedir el mismo ítem desde otra sucursal, el ítem ya existía (no
pasa por la creación) y le faltaba la fila de ese depósito →
Enter a valid value in "Whse" field - MUL - 06581 [Message 173-62].
Solución: al crear se asignan todos los almacenes, replicando la parametrización de
empresa que producción ya tiene ("añadir todos los almacenes a artículos nuevos") y que dev
no tiene. itemsService.create sin warehouseCodes ahora resuelve la lista sola
(getAllWarehouseCodes(), cacheada 1h).
⚠ Hay que excluir los almacenes inactivos. SAP rechaza asignarlos y voltea el alta
entera con 1980000017 - Warehouse "01" is not active. En dev el almacén 01 (nombre
literal "INACTIVO") tiene Inactive: tYES; la query filtra por Inactive eq 'tNO'
(10 activos de 11).
Nota verificada: el PATCH de ItemWarehouseInfoCollection agrega filas sin borrar las
existentes (no hace falta el header de replace) — sirve para reparar ítems ya creados.
Qué NO hacer¶
- No expandir
/items/composite/syncpara simples. Ese endpoint es específico de combos (padre + componentes +ProductTree/BOM, comparando la receta contra Algolia). Un simple solo necesita "crear si falta"; meterlo ahí sobrecarga el endpoint con una responsabilidad ajena. La creación silenciosa en el POST es lo más simple y atómico (ítem + pedido juntos, server-side).
Verificación¶
- Dev
ZZ_COMPU_3. Armar un pedido con un ítem simple cuyo SKU no exista en SAP (ni porItemCodeni porSupplierCatalogNo) y conItemNamepresente. - Antes del fix: el POST del pedido falla (
-10/ ítem no disponible en el depósito). - Después del fix: el ítem se crea con
ItemWarehouseInfoCollectionen el depósito de la línea, y el pedido se crea OK. Confirmar en SAP que el ítem nuevo tiene fila de almacén en ese depósito (GET Items('<code>')?$select=ItemCode,ItemWarehouseInfoCollection).
Nota — otro pendiente de backend (aparte)¶
Está también el contrato de 10-endpoint-enriquecimiento-lineas.md:
extender serials-with-price/batch para que devuelva también existencia + stock + flags
(ItemWarehouseInfoCollection, ManageSerialNumbers, InventoryItem, found), unificando la
consulta y arreglando el bug de resolución SKU→ItemCode del single de stock. Son dos tareas
independientes; esta (alta de simples) es la que desbloquea el guardado ahora.