Trazabilidad Consumo Interno → Compras (FIFO)

El contador de Trivasa necesita rastrear, para cada consumo interno registrado en MPRO, a qué compra (y en última instancia a qué UUID de CFDI y qué línea de póliza) está ligado. El sistema opera con costo promedio, sin lotes reales, así que esta trazabilidad se reconstruye retroactivamente vía lógica FIFO sobre el historial de Movimiento — es una capa de auditoría construida aparte, no la valuación contable real del sistema. Vive en exploracion/consumo_interno_trazabilidad/ del repo trivasa-bi-dev; sigue en fase de prototipo Python/pandas, sin traducir todavía a dbt. Tiene, sin embargo, una interfaz Streamlit (streamlit_app.py) ya servida en producción vía el hub Streamlit compartido de Trivasa — la app está publicada aunque la lógica analítica de fondo siga en fase de prototipo.

Decisiones de diseño

  • Grano: por producto, sin ubicación. Sucursal/almacén no le importa al contador para este propósito — permite ignorar traspasos/transferencias, que se cancelan en pares a nivel producto.
  • FIFO, no prorrateo por promedio ponderado. El sistema fuente usa costo promedio, pero FIFO es un estándar de auditoría razonable para reconstruir de qué compra viene cada consumo, y es lo que el contador puede validar contra el reporte manual que ya usa (CTRL-1).
  • Se ataca por casos, de simple a complejo — no se intenta resolver los 4 casos a la vez:
    • Caso 1 (resuelto): productos de “puro consumo” (se compran y se consumen, sin producción ni venta propia). Universo definido por datos (todo producto con consumo interno + compra histórica neta > 0), no por una lista manual — la lista manual original quedó obsoleta como fuente al descubrirse que dejaba fuera 33 productos elegibles y de paso incluía productos sin respaldo de compra real.
    • Caso 2 (confirmado material, excluido del alcance): productos que también se venden. La cola FIFO de Caso 1 solo netea compra contra consumo interno; si también hay venta compitiendo por las mismas capas, el Co_Folio_origen asignado cambia por completo al incluirla — no hay forma confiable de saber cuánta compra histórica seguía disponible vs. ya se había vendido, porque el sistema no lleva lotes reales. Se decidió excluir Caso 2 del reporte en vez de intentar resolver su trazabilidad.
    • Caso 3 (fuera de alcance por ahora): productos que se compran y también entran a fórmulas de producción propia.
    • Caso 4 (fuera de alcance): productos producidos.

Hallazgos clave

  • El puente Movimiento → Compra es un join directo cuando Mv_Tabla='Compra'; las anulaciones (de compra o de consumo) requieren 2 saltos vía el Mv_Folio que anula.
  • El puente real hacia el UUID de CFDI de una compra no vive en Compra_Encabezado.Co_Tabla/Co_Documento (esa hipótesis inicial apuntaba a la orden de compra origen, no al CFDI) — es Comprobante_Digital.Cd_Tabla='COMPRA' con Cd_Documento = Co_Folio + sufijo de 4 dígitos.
  • El puente hacia la póliza contable de un consumo interno pasa por Gasto_Registro (Gr_Tabla='CONSUMO_INTERNO', Gr_Documento=Ci_Folio) → Poliza_Detalle (Pd_Referencia=Gr_Folio) → Poliza. La póliza de consumo interno es diaria y agregada (una póliza cubre todo el consumo interno de un día); cuando un equipo se reparte entre varios centros de costo, un mismo Gr_Folio genera varias filas de Poliza_Detalle que hay que sumar antes de comparar contra el total del folio. Validado sobre un mes completo: 100% de los folios quedan explicados (match, cancelado, o categoría de “cuenta de orden”/memo sin póliza contable real por diseño).
  • FIFO “on the fly”: versión más reciente y reusable del pipeline — consolida universo, semilla y asignación FIFO en un solo script autocontenido, parametrizado solo por fecha inicio/fin, sin depender de archivos históricos pre-calculados (a diferencia de las primeras iteraciones). Calcula la existencia a la fecha ancla al vuelo en vez de requerir un export manual de MPRO cada vez — ver Existencia a una fecha para el modelo reusable que hizo esto posible.

Estado actual

Reconstrucción histórica completa (2025-01-01 → presente) en progreso — universo y semilla ya calculados; falta el FIFO incremental mes a mes y su validación. La lógica validada (scripts de exploración/prototipo) todavía no se tradujo a modelos dbt; ese es el siguiente paso formal antes de considerar el reporte listo para producción (Metabase o hand-off a FlexMonster/Vue-Nuxt, según se decida con el contador).

Antecedente: antes del FIFO “on the fly”, hubo un intento más simple a nivel raíz del repo (reports/consumo_interno_reconciliation.md) que probó clasificar los 47 tipos de movimiento distintos que tocan productos con consumo interno, bajo una hipótesis de “whitelist” ({Compra, Traspaso, Transferencia, Consumo_Interno}, sin venta/merma/ producción). Quedó como hipótesis sin validar formalmente contra ground truth — el enfoque FIFO documentado arriba lo superó en rigor (valida contra Kardex/existencia real en vez de solo clasificar tipos de movimiento) y es el que sigue activo.

Véase también

  • Existencia a una fecha — el modelo reusable que calcula existencia a cualquier fecha ancla sin depender de un export manual de MPRO, usado por el FIFO “on the fly”.
  • Layout de Gastos — otro reporte de Trivasa que también recorre la cadena Gasto_Registro → Poliza_Detalle, con hallazgos de modelo de datos compartidos (ej. Poliza_Detalle.Pd_Referencia como llave de folio).
  • Hub Streamlit — hosting compartido — cómo se publica la interfaz de este proyecto junto con Layout de Gastos en explore.frento.com.mx.