Los ajustes corrigen el stock de un SKU en una ubicación, con una razón de negocio auditable (merma, daño, corrección de conteo, etc.). Todos los endpoints de este recurso requieren el permiso inventory:adjust.
El ajuste aplica el cambio de stock AL CREARSE, no al aprobarse
A diferencia de lo que el nombre approve/reject sugiere, la creación de un ajuste ya modificó el stock. La aprobación es hoy, en la práctica, un no-op sobre el stock — solo cambia el campo status. El rechazo sí tiene efecto: revierte el stock. Lee la sección "Semántica de escritura" completa antes de construir tu flujo de aprobación.
reason acepta 11 valores — 'sale' NO es uno de ellos
El endpoint público valida reason contra esta lista exacta: count_correction, damage, theft, expired, found, return, supplier_error, restock, shrinkage, sample, other. El valor sale (venta) existe en el modelo de datos pero está reservado para el decremento automático que genera el sistema al procesar una orden — pasar reason: "sale" a este endpoint responde 400 bad-request/invalid-reason.
Puntos clave sobre la creación:
oldQuantity no lo defines tú. El servidor siempre lee el stock actual del registro de inventario en el momento de crear el ajuste, ignorando cualquier oldQuantity que envíes en el body.
adjustmentQuantity se calcula en el servidor como newQuantity − oldQuantity.
Si omites productSku, el servidor lo resuelve en este orden: (1) el productSku ya existente en el registro de inventario de ese SKU/ubicación, (2) una búsqueda en el catálogo de productos, (3) usa el sku tal cual como último recurso.
Este es el patrón de negocio más importante del recurso:
La creación (POST /inventory/adjustments) aplica el cambio de stock de inmediato. El registro nace con status: 'pending_review', pero el stock ya fue modificado en ese momento — no cuando alguien lo aprueba. Este POSTsí dispara el evento Inventory Updated (y una posible Low Stock Alert), porque internamente usa la misma ruta de escritura que PUT de stock.
approve sobre un ajuste pending_review (el flujo normal hoy) no vuelve a tocar el stock. Solo cambia status → approved y estampa los campos de auditoría (approvedBy, approvedAt). El stock ya se movió en el paso 1.
reject sí tiene efecto sobre el stock: lo revierte a oldQuantity (disparando otro evento Inventory Updated por la reversión), y además crea automáticamente un segundo registro de ajuste: reason: 'count_correction', sourceType: 'reversal', sourceId apuntando al ajuste original, adjustedBy: 'system', ya en estado approved.
Rechazar un ajuste crea DOS registros, no uno
Si listas ajustes esperando ver únicamente el que rechazaste, verás dos: el original (ahora status: 'rejected') y un ajuste sintético de reversión generado por el sistema. Ambos cuentan en GET /inventory/adjustments y en /summary.