Existencia a una fecha y movimientos en un periodo
Modelo reusable que calcula la existencia de un producto a una fecha ancla pasada sin
depender de un export manual de MPRO cada vez, más los reportes de movimientos que se
construyeron encima. Vive en exploracion/existencia_a_una_fecha/ del repo
trivasa-bi-dev; surgió como necesidad de
Trazabilidad Consumo Interno → Compras (su FIFO “on
the fly” necesita una semilla de existencia confiable) pero se separó a propósito porque
es reusable para cualquier caso futuro que necesite existencia a una fecha.
Tres métodos comparados, uno elegido
Se compararon contra el ground truth real de MPRO (export “Existencias a una fecha”, columna CANTIDAD CTRL-1):
- Método A (
Existencia.Ex_Cantidad_Control_1actual − suma deMovimientoposteriores a la fecha): 99.3% de match sobre 5,845 productos. Robusto porque parte deExistencia, mantenida en vivo e íntegra por el sistema transaccional, y solo resta el neto de movimientos posteriores — no depende de re-derivar el emparejamiento completo de anulaciones de toda la historia. - Método B (réplica literal del
.aspde MPRO que genera ese mismo reporte, sumando desde el origen con filtroEs_Cve_Estado='AC' AND Tm_Anulacion='NO'): 98.9%. Resuelve parte de los fallos de A, pero introduce 33 fallos nuevos en productos de alto volumen (BLOCK/VIGA/BOVEDILLA) — la causa raíz es que asume que cada cancelación empata 1:1 con su reverso, y cuando no empatan exacto (drift por correcciones históricas) el resultado se desvía. - Método C (variante de B: suma desde el origen, pero sin el filtro de
estado/anulación — se obtuvo la consulta SQL exacta que usa MPRO cuando se activa
“considera cancelaciones/anulaciones”): 100.00% de match en las 3 fechas ancla
probadas (2025-01-01, 2026-01-01, 2025-03-31). Al no excluir nada por estado, nunca
depende de que una cancelación y su reverso empaten 1:1 — es el método vigente que usan
los reportes construidos después de este hallazgo (
movimientos_periodo, FIFO “on the fly”), aunque formalmente sigue abierto validarlo contra más fechas antes de reemplazar a A como “oficial” en el sentido estricto del ADR original.
Detalle completo, incluida la causa raíz exacta del fallo de B, en
docs/decisions/2026-07-existencia-a-fecha-metodo-resta-vs-suma.md (raíz del repo).
Movimientos en un periodo
Reporte que lista los movimientos “efectivos” de inventario en un rango de fechas, reconciliado 100% contra existencia inicial/final (Método C). Clave: se excluyen del listado los tipos de movimiento que son puro traspaso/transferencia interna (sucursal-a-sucursal, entre almacenes, a producción) — se verificó que netean exactamente a 0 por producto en el periodo, no son negocio, son reacomodos. Las cancelaciones/anulaciones se excluyen por default y solo se reactivan automáticamente para los productos donde la reconciliación no cuadre sin ellas — evita repetir el mismo error que rompía al Método B (excluir cancelación+reverso a ciegas asumiendo que siempre empatan 1:1).
Bug encontrado en el camino: comparar movimientos contra existencia requiere usar
Mv_Cantidad_Control_1 en ambos lados — mezclar con Mv_Cantidad_1 (que difiere en
la inmensa mayoría de los casos, pero no en todos) rompe la reconciliación para productos
específicos con un factor de conversión de unidad distinto.
V2 — movimientos con UUID de compra vía FIFO
Extensión que, para cada salida del reporte de movimientos, encuentra el UUID del CFDI
de compra que la respalda — reusa íntegra la lógica FIFO “on the fly” de
Trazabilidad Consumo Interno (fifo_lib.py) en vez de
reescribirla. Cobertura sobre enero 2026: 100% de las salidas asignadas sin descuadre
(algunas se parten en 2+ filas al cruzar más de una capa de compra); del volumen total,
~52% tiene respaldo de compra real con UUID resuelto — el resto es dominado por venta de
producto fabricado internamente (BLOCK/BOVEDILLA/VIGA), consistente con que Trivasa
produce además de revender.
Nota técnica para quien reuse fifo_lib.py: la función que arma la cola FIFO no ordena
el DataFrame que recibe por fecha de compra — asume que el caller ya lo entrega
ordenado. No se modificó la librería (la usan reportes ya publicados); el caller nuevo
ordena explícitamente antes de invocarla.
Véase también
- Trazabilidad Consumo Interno → Compras — el proyecto que motivó este modelo reusable, y dueño de la lógica FIFO que V2 reusa.