Inventario Documentación
Visión general
Reposición, aging, exceso, transferencias entre sucursales y promociones por vencimiento.
Esta referencia cubre 9 engines. Cada endpoint trae ruta, permiso, parámetros, respuesta y los errores posibles.
Exceso de inventario (reporte)
Propósito
Reporte de exceso de inventario: LLM primero, con fallback basado en reglas cuando el LLM no está disponible o falla.
¿Por qué? Genera el informe de inventario en exceso con garantía de entrega: el informe siempre se produce, incluso cuando el proveedor de lenguaje no está disponible. El resultado es una lectura siempre accesible del exceso de inventario para apoyar decisiones de liquidación y compra.
¿Cómo? El intento primario genera el informe narrativo a través del proveedor de LLM configurado en la plataforma. Si no está disponible, un respaldo basado en reglas agrega los datos estadísticamente (suma, promedio, ranking), clasifica los ítems en rangos de antigüedad y arma un texto estructurado sin LLM.
Origen El enfoque de generación de lenguaje se apoya en Brown et al. (2020), "Language Models are Few-Shot Learners", NeurIPS.
Literatura de referencia
- Brown, T. et al. (2020). "Language Models are Few-Shot Learners." NeurIPS.
Parámetros (params)
| Campo | Tipo | Obligatorio | Por defecto | Descripción |
|---|---|---|---|---|
max_items | integer | no | 50 | Número máximo de ítems en el tope del reporte (usado tanto por el camino LLM como por el de reglas). |
language | string | no | "en" | Código del idioma del reporte (solo camino LLM, ej.: "pt", "pt-BR", "en"). |
temperature | number | no | 0.3 | Temperatura de muestreo del LLM (solo camino LLM). |
Columnas de data[]
| Columna | Tipo | Obligatoria | Descripción |
|---|---|---|---|
quantity | number | sí | Cantidad en stock. Acepta aliases: stock, qty, units, on_hand. Las filas con cantidad o costo nulos/negativos se descartan/rechazan. |
cost | number | sí | Costo unitario. Acepta aliases: unit_cost, price, unit_price. |
product_id | string | no | Identificador del producto. Acepta aliases: item_id, sku, id. |
product_name | string | no | Descripción del producto, mostrada en el reporte por reglas cuando está presente. |
days_in_stock | integer | no | Días desde el último movimiento; habilita el análisis por rangos de aging (0-30/31-90/91-180/180+ días) en el camino por reglas. |
category | string | no | Categoría del producto; habilita el detalle por categoría en el camino por reglas. |
Respuesta
En modo asíncrono (por defecto), 202 Accepted con {"process_uuid", "result_url"}; el resultado sale en GET /api/v1/results/{process_uuid}. Con ?sync=true o ?dry_run=true la respuesta es 200 con el resultado inline (y 504 con el process_uuid si el worker no responde a tiempo).
Errores
403- la engine no está enallowed_enginesde tu suscripción.413- subida por encima demax_upload_mb.422- engine desconocida o inactiva en el catálogo.429- cuota diaria (max_jobs_per_day) o por minuto excedida.
La validación es fail-fast: un envío rechazado no tiene ningún efecto secundario.
curl -X POST "https://intelligence.echosistema.live/api/v1/excess_inventory_nlp/process?dry_run=true&playground=true" \
-H "X-TENANT-KEY: $TENANT_KEY"Promoción por vencimiento
Propósito
Calculadora de descuento óptimo de remarcación para productos próximos a vencer.
Para cada producto, evalúa cada escalón de descuento desde 0 (no promocionar) hasta max_discount_pct y elige el que maximiza el resultado total del período, usando un modelo lineal de aumento de demanda. Toda unidad que sale durante la ventana restante se vende con el descuento, incluida la demanda base que saldría a precio lleno, así que el objetivo es units_sold_at_promo * precio * (1 - d) - unit_cost * current_stock, y esa canibalización de la demanda base se reporta como cannibalization_cost. Sin un tope de stock que limite, el óptimo queda en (demand_elasticity - 1) / (2 * demand_elasticity), es decir, en cero o por debajo para un producto inelástico, donde la respuesta honesta es no tocar el precio. Los productos que no reciben recomendación aparecen en full.skipped con un motivo (missing_expiration_date, expired, below_min_days_before_expiry, no_qty_at_risk); un producto con demanda base cero permanece en los resultados con optimal_discount_pct: null y recommendation_reason: "no_demand_signal", porque un modelo multiplicativo de aumento no puede pronosticar demanda para un ítem que nunca rotó. Cada resultado lleva un nivel de urgencia, el outcome_vs_no_promo (la comparación legible contra no promocionar) y hasta dos alternativas vecinas de descuento.
Parámetros (params)
| Campo | Tipo | Obligatorio | Por defecto | Descripción |
|---|---|---|---|---|
reference_date | string | no | Fecha de referencia (YYYY-MM-DD) para calcular días hasta el vencimiento. Por defecto: hoy (UTC). | |
max_discount_pct | number | no | 70 | Porcentaje máximo de descuento evaluado. |
discount_step_pct | number | no | 5 | Incremento del escalón de descuento en porcentaje. Número positivo y finito. |
demand_elasticity | number | no | 2 | Multiplicador lineal de aumento de demanda: demanda(d) = avg_daily_demand * (1 + demand_elasticity * d / 100), de modo que 2.0 significa que 50% de descuento duplica la demanda diaria. NO es elasticidad-precio en el sentido económico: la elasticidad constante clásica (Q ∝ P^-ε) se cita entre -0,5 y -3,0, y un valor leído en esa escala modela otra cosa sin avisar. Debe ser finito y no negativo; cero es válido y resulta en la recomendación de no descontar. |
min_margin_pct | number | no | -100 | Margen mínimo aceptable en porcentaje (puede ser negativo); los escalones que lo violan se saltan. |
min_days_before_expiry | integer | no | 0 | Mínimo de días antes del vencimiento para que una promo sea considerada viable. |
Columnas de data[]
| Columna | Tipo | Obligatoria | Descripción |
|---|---|---|---|
product_id | string | sí | Identificador del producto. |
current_stock | number | sí | Cantidad actual en stock. |
avg_daily_demand | number | sí | Promedio de unidades vendidas por día al precio actual. |
unit_cost | number | sí | Costo unitario del producto. |
unit_price | number | sí | Precio unitario de venta actual (antes del descuento). |
expiration_date | string | sí | Fecha de vencimiento del lote. |
Respuesta
En modo asíncrono (por defecto), 202 Accepted con {"process_uuid", "result_url"}; el resultado sale en GET /api/v1/results/{process_uuid}. Con ?sync=true o ?dry_run=true la respuesta es 200 con el resultado inline (y 504 con el process_uuid si el worker no responde a tiempo).
Errores
403- la engine no está enallowed_enginesde tu suscripción.413- subida por encima demax_upload_mb.422- engine desconocida o inactiva en el catálogo.429- cuota diaria (max_jobs_per_day) o por minuto excedida.
La validación es fail-fast: un envío rechazado no tiene ningún efecto secundario.
curl -X POST "https://intelligence.echosistema.live/api/v1/expiry_promo/process?dry_run=true&playground=true" \
-H "X-TENANT-KEY: $TENANT_KEY"Optimizador entre sucursales
Propósito
Detecta desequilibrios de stock entre sucursales por producto y recomienda transferencias.
Agrupa las filas por product_id, calcula días de cobertura (DOS) por sucursal y rebalancea el stock hacia un objetivo de cobertura efectivo, el coverage_target, degradado al propio DOS de la red cuando la red no logra alcanzarlo. AMBOS lados de la asignación se miden contra ese objetivo único: toda sucursal por encima de él dona, toda sucursal por debajo recibe. El status de exceso/déficit/equilibrio es relativo a la red y se reporta, NO se usa para asignar; seleccionar por esa etiqueta dejaba stock varado dos veces, pasando por alto una sucursal con unidades de sobra porque la banda relativa no la llamaba exceso, y una sucursal por debajo del objetivo porque, con toda la red corta, la misma banda la llamaba equilibrada. Cada sucursal lleva también status_vs_target, la lectura absoluta. Una sucursal sin demanda reporta dos: null y no_demand: true, en vez de un valor centinela interno. Los candidatos rechazados aparecen en skipped_transfers del producto, con el motivo. unit_cost opcional más holding_cost_pct habilitan la economía de costo de mantención por transferencia y el total_net_benefit en el resumen.
Parámetros (params)
| Campo | Tipo | Obligatorio | Por defecto | Descripción |
|---|---|---|---|---|
min_transfer_qty | number | no | 1 | Cantidad mínima que justifica una transferencia; montos menores se saltan. |
coverage_target | number | no | 30 | Días de cobertura objetivo por sucursal tras las transferencias: un número fijo de días, o el string "equalize" para igualar al DOS de la red (acepta número o el literal "equalize"). |
transfer_cost_per_unit | number | no | 0 | Costo por unidad transferida, deducido del beneficio neto cuando unit_cost está presente. |
holding_cost_pct | number | no | 0 | Costo anual de mantención como fracción del costo unitario. 0 desactiva la economía de mantención; exige la columna unit_cost para tener efecto. |
require_positive_net_benefit | boolean | no | false | Suprime las transferencias cuya economía de costo de mantención no cubre su propio costo de transferencia, reportándolas en skipped_transfers del producto con reason: "non_positive_net_benefit". Apagado por defecto: una transferencia de beneficio neto negativo suele ser igual la decisión correcta, porque evita un quiebre en el destino, y la venta perdida no entra en esa cuenta. Exige holding_cost_pct > 0 y una columna unit_cost; sin la economía, el filtro no hace nada. |
Columnas de data[]
| Columna | Tipo | Obligatoria | Descripción |
|---|---|---|---|
product_id | string | sí | Identificador del producto. |
branch_id | string | sí | Identificador de la sucursal/tienda. |
current_stock | number | sí | Stock actual en la sucursal. |
avg_daily_demand | number | sí | Demanda promedio diaria en la sucursal. |
unit_cost | number | no | Costo unitario, usado en los cálculos de ahorro de mantención cuando holding_cost_pct > 0. |
Respuesta
En modo asíncrono (por defecto), 202 Accepted con {"process_uuid", "result_url"}; el resultado sale en GET /api/v1/results/{process_uuid}. Con ?sync=true o ?dry_run=true la respuesta es 200 con el resultado inline (y 504 con el process_uuid si el worker no responde a tiempo).
Errores
403- la engine no está enallowed_enginesde tu suscripción.413- subida por encima demax_upload_mb.422- engine desconocida o inactiva en el catálogo.429- cuota diaria (max_jobs_per_day) o por minuto excedida.
La validación es fail-fast: un envío rechazado no tiene ningún efecto secundario.
curl -X POST "https://intelligence.echosistema.live/api/v1/inter_branch_optimizer/process?dry_run=true&playground=true" \
-H "X-TENANT-KEY: $TENANT_KEY"Historial de inventario
Propósito
Análisis de movimientos de inventario por producto con 15+ métricas: rotación, volatilidad, clase ABC, aging FIFO y riesgo.
¿Por qué? Análisis integral de inventario por producto, con más de 40 métricas en siete categorías: movimientos, compras, ventas y promedios diarios, estadísticas de variabilidad, eficiencia (rotación, días en stock, days of supply), clasificaciones (estacionalidad, intensidad de actividad, ciclo de vida, curva ABC, tendencia de ventas), riesgos de quiebre y exceso, métricas opcionales de rentabilidad, reposición y stock de seguridad, y envejecimiento FIFO en rangos de 0-30, 31-60, 61-90 y 90+ días. Es la radiografía completa del comportamiento de cada producto para decisiones de compra, precios y obsolescencia.
¿Cómo? Reconstruye la posición de stock a lo largo del tiempo por simulación FIFO: las entradas crean lotes en cola y las salidas consumen del lote más antiguo al más reciente. Sobre la serie resultante calcula agregaciones y estadísticas (desviación estándar, varianza, mediana, percentiles), rotación y días en stock, y clasificaciones vía coeficiente de variación de las ventas mensuales, razón de días activos, regresión lineal para ciclo de vida y tendencia, y Pareto acumulado para ABC. Los riesgos de quiebre y exceso se señalan cuando los días en esa condición superan el 10% del período, y el aging distribuye los lotes remanentes por edad, contada desde el movimiento más reciente del conjunto de datos, y no desde el último movimiento de cada producto.
Origen Se fundamenta en Silver, Pyke y Thomas (2016), "Inventory and Production Management in Supply Chains", 4.ª edición, CRC Press.
Literatura de referencia
- Silver, E. A., Pyke, D. F. & Thomas, D. J. (2016). "Inventory and Production Management in Supply Chains." 4th ed., CRC Press.
Parámetros (params)
| Campo | Tipo | Obligatorio | Por defecto | Descripción |
|---|---|---|---|---|
period_days | integer | no | 365 | Tamaño de la ventana de análisis en días. Es el denominador de todo promedio diario, así que dos productos con la misma venta se normalizan por el mismo reloj, sin importar hace cuánto está activo cada uno. |
stockout_threshold | integer | no | 0 | Nivel de stock igual o por debajo del cual un día cuenta como evento de quiebre, reportado en stockout_days, y cuenta para el conteo de episodios en stockout_count. |
overstock_threshold | integer | no | Nivel de inventario por encima del cual un día cuenta como exceso. Por defecto: max(inventario_promedio * 3, 1000) por producto cuando se omite. | |
lead_time_days | number | no | 7 | Lead time en días usado en los cálculos de nivel de reposición y stock de seguridad (aplicado solo cuando las columnas de precio están presentes). El nivel de reposición es la demanda en el lead time MÁS el stock de seguridad. |
safety_stock_z | number | no | 1.65 | Z-score del cálculo de stock de seguridad (el valor por defecto corresponde a un nivel de servicio de ~95%). |
Columnas de data[]
| Columna | Tipo | Obligatoria | Descripción |
|---|---|---|---|
product_id | string | sí | Identificador del producto. |
movement_date | string | sí | Fecha del movimiento de inventario. |
quantity | integer | sí | Cantidad del movimiento: positiva para compras/entradas, negativa para ventas/salidas. |
unit_cost | number | no | Costo unitario del movimiento. Habilita métricas de rentabilidad/margen/reposición en par con unit_price. |
unit_price | number | no | Precio unitario de venta del movimiento. Habilita métricas de rentabilidad/margen/reposición en par con unit_cost. |
Respuesta
En modo asíncrono (por defecto), 202 Accepted con {"process_uuid", "result_url"}; el resultado sale en GET /api/v1/results/{process_uuid}. Con ?sync=true o ?dry_run=true la respuesta es 200 con el resultado inline (y 504 con el process_uuid si el worker no responde a tiempo).
Errores
403- la engine no está enallowed_enginesde tu suscripción.413- subida por encima demax_upload_mb.422- engine desconocida o inactiva en el catálogo.429- cuota diaria (max_jobs_per_day) o por minuto excedida.
La validación es fail-fast: un envío rechazado no tiene ningún efecto secundario.
curl -X POST "https://intelligence.echosistema.live/api/v1/inventory_history/process?dry_run=true&playground=true" \
-H "X-TENANT-KEY: $TENANT_KEY"Optimización de inventario
Propósito
Calculadora de EOQ y stock de seguridad con análisis de sensibilidad.
¿Por qué? Calcula los niveles óptimos de inventario a partir de las estadísticas de demanda y del nivel de servicio deseado, entregando la cantidad económica de pedido (EOQ), el stock de seguridad y el punto de reposición de cada ítem. El resultado responde directamente cuánto pedir y cuándo pedir, equilibrando el costo de inventario y el riesgo de quiebre.
¿Cómo? Aplica la fórmula clásica de EOQ, Q* = raíz de (2DS/H), sobre demanda, costo de pedido y costo de mantención. El safety stock se dimensiona por el Z-score del nivel de servicio deseado, multiplicado por la desviación estándar de la demanda y por la raíz del lead time, o por la forma general cuando el propio lead time varía. El punto de reposición suma la demanda promedio durante el lead time al safety stock. El costo anual de mantención reportado incluye el safety stock todo el año, y viene repartido en parte de ciclo y parte de seguridad, porque es la de ciclo la que se iguala al costo de pedido en el óptimo.
Origen La fórmula de EOQ se remonta a Harris (1913), "How Many Parts to Make at Once", Factory, The Magazine of Management, 10(2), 135-136, con el tratamiento moderno de Silver, Pyke y Thomas (2016), "Inventory and Production Management in Supply Chains".
Literatura de referencia
- Harris, F. W. (1913). "How Many Parts to Make at Once." Factory, The Magazine of Management, 10(2), 135-136.
- Silver, E. A., Pyke, D. F. & Thomas, D. J. (2016). "Inventory and Production Management in Supply Chains."
Parámetros (params)
| Campo | Tipo | Obligatorio | Por defecto | Descripción |
|---|---|---|---|---|
demand_mean | number | sí | Demanda promedio diaria/semanal. Positiva. Ignorada si se entrega una serie demand utilizable. | |
demand_std | number | sí | Desviación estándar de la demanda. No negativa. Ignorada si se entrega una serie demand utilizable. | |
lead_time_days | number | sí | Lead time en días. Positivo. | |
ordering_cost | number | sí | Costo por pedido (S). Positivo. | |
holding_cost | number | sí | Costo anual de mantención por unidad (H). Positivo. | |
service_level | number | sí | Nivel de servicio objetivo, estrictamente entre 0 y 1 (ej.: 0.95 para 95%). | |
periods_per_year | integer | no | 365 | Número de períodos de demanda por año, usado para anualizar demand_mean. |
annual_demand | number | no | Override de la demanda anual. Por defecto: demand_mean * periods_per_year. | |
use_demand_series | boolean | no | true | Cuando es true y hay columna demand en las filas, calcula demand_mean/demand_std de esa serie (mínimo 2 filas) en vez de los params. |
lead_time_std_days | number | no | 0 | Desviación estándar del propio lead time, en días. No negativa. Cero (por defecto) da el stock de seguridad determinístico clásico z*sigma_d*sqrt(L); un valor positivo usa la forma general z*sqrt(L*sigma_d^2 + mean_d^2*sigma_L^2), que es lo que un proveedor irregular exige. |
Columnas de data[]
| Columna | Tipo | Obligatoria | Descripción |
|---|---|---|---|
demand | number | no | Serie histórica de demanda opcional. Cuando está presente (y use_demand_series no es false), anula los params demand_mean/demand_std; exige al menos 2 filas. |
Respuesta
En modo asíncrono (por defecto), 202 Accepted con {"process_uuid", "result_url"}; el resultado sale en GET /api/v1/results/{process_uuid}. Con ?sync=true o ?dry_run=true la respuesta es 200 con el resultado inline (y 504 con el process_uuid si el worker no responde a tiempo).
Errores
403- la engine no está enallowed_enginesde tu suscripción.413- subida por encima demax_upload_mb.422- engine desconocida o inactiva en el catálogo.429- cuota diaria (max_jobs_per_day) o por minuto excedida.
La validación es fail-fast: un envío rechazado no tiene ningún efecto secundario.
curl -X POST "https://intelligence.echosistema.live/api/v1/inventory_optimization/process?dry_run=true&playground=true" \
-H "X-TENANT-KEY: $TENANT_KEY"Exceso de inventario (LLM)
Propósito
Reporte en lenguaje natural generado por LLM sobre exceso de inventario (resumen ejecutivo, principales ítems, aging, recomendaciones).
¿Por qué? Transforma datos tabulares de inventario en exceso en informes en lenguaje natural, con resumen ejecutivo, principales ítems, análisis de antigüedad y recomendaciones accionables. El objetivo es hacer comprensible la situación del inventario para interesados no técnicos, sin exigir la lectura de planillas.
¿Cómo? Los datos de inventario se formatean como contexto y se envían al proveedor de LLM configurado en la plataforma, con ingeniería de prompts estructurados. El modelo genera el análisis narrativo en secciones predefinidas.
Origen El enfoque de generación de lenguaje se apoya en Brown et al. (2020), "Language Models are Few-Shot Learners", NeurIPS.
Literatura de referencia
- Brown, T. et al. (2020). "Language Models are Few-Shot Learners." NeurIPS.
Parámetros (params)
| Campo | Tipo | Obligatorio | Por defecto | Descripción |
|---|---|---|---|---|
max_items | integer | no | 50 | Número máximo de ítems en la tabla del prompt del LLM (reducido automáticamente si la estimación de tokens del prompt supera ~6000). |
language | string | no | "en" | Código del idioma del reporte, ej.: "pt", "pt-BR", "en". Normalizado a ISO 639-1. |
response_format | string | no | "markdown" | Formato de la salida: "markdown" (string markdown) o "json" (array de objetos de sección {t, p}). |
temperature | number | no | 0.3 | Temperatura de muestreo del LLM. |
Columnas de data[]
| Columna | Tipo | Obligatoria | Descripción |
|---|---|---|---|
quantity | number | sí | Cantidad actual en stock. Acepta aliases: stock, qty, units, on_hand. |
cost | number | sí | Costo unitario o total. Acepta aliases: unit_cost, price, unit_price. Las filas con cantidad o costo nulos/negativos se descartan/rechazan. |
product_id | string | no | Identificador del producto. Acepta aliases: item_id, sku, id. Etiqueta las filas en la tabla del prompt. |
product_name | string | no | Descripción del producto, incluida como columna extra en la tabla del prompt cuando está presente. |
days_in_stock | integer | no | Días desde el último movimiento del ítem, incluido como columna extra cuando está presente. |
category | string | no | Categoría del producto, incluida como columna extra cuando está presente. |
avg_daily_sales | number | no | Ritmo promedio de ventas diarias, incluido como columna extra cuando está presente. |
Respuesta
En modo asíncrono (por defecto), 202 Accepted con {"process_uuid", "result_url"}; el resultado sale en GET /api/v1/results/{process_uuid}. Con ?sync=true o ?dry_run=true la respuesta es 200 con el resultado inline (y 504 con el process_uuid si el worker no responde a tiempo).
Errores
403- la engine no está enallowed_enginesde tu suscripción.413- subida por encima demax_upload_mb.422- engine desconocida o inactiva en el catálogo.429- cuota diaria (max_jobs_per_day) o por minuto excedida.
La validación es fail-fast: un envío rechazado no tiene ningún efecto secundario.
curl -X POST "https://intelligence.echosistema.live/api/v1/nlp_llm_excess_inventory/process?dry_run=true&playground=true" \
-H "X-TENANT-KEY: $TENANT_KEY"Predictor de recompra
Propósito
Predice la fecha de la próxima recompra de productos de uso continuo a partir del historial de compras del cliente.
Agrupa compras por (customer_id, product_id), calcula los intervalos entre compras y un promedio móvil ponderado para predecir la próxima fecha de compra, un score de regularidad, clasificación de adherencia basada en MPR y una tendencia (stable/decreasing/slightly_increasing/increasing). El mpr sigue limitado a 100 por convención de reporte de adherencia, con el número real en mpr_uncapped; como el MPR cuenta n compras contra un intervalo que cubre n-1 períodos, está sesgado hacia arriba en series cortas, así que el flag stockpiling lee supply_per_interval_pct (suministro promedio sobre intervalo promedio): 100% para un cliente que compra exactamente al ritmo, 150% para quien compra 30 días de suministro cada 20 días. Los pares con menos de min_purchases compras, o con regularidad por debajo de 0.3, se excluyen a menos que include_irregular sea true; cada par excluido aparece en full.excluded con un motivo, en vez de desaparecer sin aviso. El alerts_due separa overdue de today (que sigue incluyendo ambos).
Parámetros (params)
| Campo | Tipo | Obligatorio | Por defecto | Descripción |
|---|---|---|---|---|
alert_days_before | integer | no | 5 | Días antes de la fecha prevista de compra en que se dispara la alerta. |
min_purchases | integer | no | 3 | Mínimo de compras por par cliente-producto para ser incluido. |
max_interval_days | integer | no | 180 | Intervalo máximo en días entre compras considerado (filtro de outliers); los intervalos mayores salen de las estadísticas. |
reference_date | string | no | Fecha de referencia (YYYY-MM-DD) para days_until_predicted/alerta. Por defecto: hoy. | |
include_irregular | boolean | no | false | Incluye pares cliente-producto con score de regularidad bajo 0.3. |
Columnas de data[]
| Columna | Tipo | Obligatoria | Descripción |
|---|---|---|---|
customer_id | string | sí | Identificador del cliente. |
product_id | string | sí | Identificador del producto. |
purchase_date | string | sí | Fecha de la compra. |
product_name | string | no | Nombre legible del producto, incluido en la salida cuando está presente. |
days_supply | number | no | Días de suministro cubiertos por cada compra (ej.: pastillas por frasco / dosis diaria). Usado en el cálculo de MPR en lugar del intervalo promedio inferido. |
Respuesta
En modo asíncrono (por defecto), 202 Accepted con {"process_uuid", "result_url"}; el resultado sale en GET /api/v1/results/{process_uuid}. Con ?sync=true o ?dry_run=true la respuesta es 200 con el resultado inline (y 504 con el process_uuid si el worker no responde a tiempo).
Errores
403- la engine no está enallowed_enginesde tu suscripción.413- subida por encima demax_upload_mb.422- engine desconocida o inactiva en el catálogo.429- cuota diaria (max_jobs_per_day) o por minuto excedida.
La validación es fail-fast: un envío rechazado no tiene ningún efecto secundario.
curl -X POST "https://intelligence.echosistema.live/api/v1/refill_predictor/process?dry_run=true&playground=true" \
-H "X-TENANT-KEY: $TENANT_KEY"Aging de stock
Propósito
Clasifica los ítems de inventario en activos/lentos/muertos por días desde la última venta.
¿Por qué? Clasifica los ítems del inventario por la antigüedad desde la última venta, entregando rangos de envejecimiento (0-30, 31-60, 61-90 y 90+ días), la clasificación active, slow o dead por ítem, el valor en riesgo del stock muerto cuando hay datos de costo y la distribución de productos por rango. Es la herramienta esencial para la gestión de obsolescencia, señalando dónde está inmovilizado el capital y qué ítems merecen liquidación o promoción.
¿Cómo? Para cada producto calcula los días desde la última venta respecto de la fecha de referencia (o de la última venta más reciente, más un día, si no se informa) y lo ubica en los buckets de aging. La clasificación usa umbrales configurables: dead sobre 90 días y slow sobre 60, por defecto. El valor en riesgo (cantidad en mano por unit_cost) se calcula solo para ítems dead, y queda nulo cuando falta el costo, caso en que el ítem se cuenta aparte como de valor desconocido en vez de entrar al total como cero.
Origen Se basa en las prácticas descritas por Muller (2019), "Essentials of Inventory Management", 2.ª edición, AMACOM.
Literatura de referencia
- Muller, M. (2019). "Essentials of Inventory Management." 2nd ed., AMACOM.
Parámetros (params)
| Campo | Tipo | Obligatorio | Por defecto | Descripción |
|---|---|---|---|---|
reference_date | integer | no | Fecha de referencia del aging, aceptada como epoch en días/segundos/ms o YYYYMMDD (normalizada internamente). Por defecto: la mayor last_sale_date de los datos más 1 día. | |
dead_threshold | integer | no | 90 | Días desde la última venta por encima de los cuales el ítem se clasifica como "dead". |
slow_threshold | integer | no | 60 | Días desde la última venta por encima de los cuales el ítem se clasifica como "slow" (y por debajo de dead_threshold). |
Columnas de data[]
| Columna | Tipo | Obligatoria | Descripción |
|---|---|---|---|
product_id | string | sí | Identificador del producto. |
quantity_on_hand | number | sí | Cantidad actual en mano. |
last_sale_date | string | sí | Fecha de la última venta registrada del producto. |
unit_cost | number | no | Costo unitario. Habilita at_risk_value en los ítems de stock muerto cuando está presente. |
Respuesta
En modo asíncrono (por defecto), 202 Accepted con {"process_uuid", "result_url"}; el resultado sale en GET /api/v1/results/{process_uuid}. Con ?sync=true o ?dry_run=true la respuesta es 200 con el resultado inline (y 504 con el process_uuid si el worker no responde a tiempo).
Errores
403- la engine no está enallowed_enginesde tu suscripción.413- subida por encima demax_upload_mb.422- engine desconocida o inactiva en el catálogo.429- cuota diaria (max_jobs_per_day) o por minuto excedida.
La validación es fail-fast: un envío rechazado no tiene ningún efecto secundario.
curl -X POST "https://intelligence.echosistema.live/api/v1/stock_aging/process?dry_run=true&playground=true" \
-H "X-TENANT-KEY: $TENANT_KEY"Reposición de stock
Propósito
Calcula stock de seguridad, punto de reposición, EOQ y clasificación de demanda por producto, con alertas de reposición.
Agrega filas de movimiento (cantidad positiva = entrada, negativa = salida/demanda) por product_id, calcula stock de seguridad y punto de reposición a partir del cuantil normal del nivel de servicio, EOQ a partir de los costos de pedido y mantención, una clasificación de demanda Syntetos-Boylan (smooth/erratic/intermittent/lumpy) y un nivel de urgencia por los días de cobertura. Cuando el stock actual está en el punto de reposición o por debajo, reorder_now es true y reorder_quantity se completa. El eje de variabilidad de Syntetos-Boylan es el CV al cuadrado de los TAMAÑOS de demanda, no el de la serie diaria incluyendo los días sin salida: los vacíos ya son el otro eje (ADI), y contarlos dos veces volvía inalcanzable el cuadrante intermitente. El std_daily_demand sigue abarcando los días en cero, porque el stock de seguridad trata de la variación de un día a otro, que es otra pregunta. Un producto de demanda constante tiene desviación estándar 0 y, por lo tanto, stock de seguridad 0 y punto de reposición enteramente calculable. El eoq es nulo cuando no hay unit_cost disponible, en vez de asumir costo unitario 1.0; el days_of_supply es nulo cuando no hay demanda, en vez de un valor centinela; negative_stock_detected señala un producto que vendió más de lo que jamás recibió.
Parámetros (params)
| Campo | Tipo | Obligatorio | Por defecto | Descripción |
|---|---|---|---|---|
lead_time_days | number | no | 7 | Lead time del proveedor en días. |
service_level | number | no | 0.95 | Nivel de servicio objetivo como probabilidad, estrictamente entre 0 y 1. |
order_cost | number | no | 50 | Costo fijo por pedido, usado en la fórmula del EOQ. |
holding_cost_pct | number | no | 0.2 | Costo anual de mantención como fracción del costo unitario. Número positivo y finito. |
Columnas de data[]
| Columna | Tipo | Obligatoria | Descripción |
|---|---|---|---|
product_id | string | sí | Identificador del producto. |
movement_date | string | sí | Fecha del movimiento de inventario. |
quantity | number | sí | Cantidad del movimiento: positiva para entradas, negativa para salidas/demanda. |
unit_cost | number | no | Costo unitario. Cuando está presente, el costo unitario promedio por producto refina el denominador de mantención del EOQ. |
Respuesta
En modo asíncrono (por defecto), 202 Accepted con {"process_uuid", "result_url"}; el resultado sale en GET /api/v1/results/{process_uuid}. Con ?sync=true o ?dry_run=true la respuesta es 200 con el resultado inline (y 504 con el process_uuid si el worker no responde a tiempo).
Errores
403- la engine no está enallowed_enginesde tu suscripción.413- subida por encima demax_upload_mb.422- engine desconocida o inactiva en el catálogo.429- cuota diaria (max_jobs_per_day) o por minuto excedida.
La validación es fail-fast: un envío rechazado no tiene ningún efecto secundario.
curl -X POST "https://intelligence.echosistema.live/api/v1/stock_replenishment/process?dry_run=true&playground=true" \
-H "X-TENANT-KEY: $TENANT_KEY"