Layout de Gastos por CECO — CONT-1
Página del app Contabilidad de streamlit-reportes (
reportes.frento.com.mx/contabilidad). Reemplaza, el 2026-09-03, al reporte "Layout de Gastos — Reconciliación CECO" original (mismo path de página, contenido rediseñado — ver "Rediseño" abajo). Ver también CONT-2, la misma reconciliación + el séptimo origen (GASTO_REGISTRO_NOMINA).
Compara, folio por folio y centro por centro, el reparto operativo del gasto
(Gasto_Registro_Control.Grc_Importe) contra lo que realmente quedó
contabilizado (Poliza_Detalle) — 6 orígenes de Gasto_Registro:
CONTROL_COMBUSTIBLE, ORDEN_COMPRA, VIAJE, GASTO_DIRECTO,
GASTO_RECLASIFICACION, CONSUMO_INTERNO. GASTO_REGISTRO_NOMINA en
CONT-2 aparte (técnica de emparejamiento distinta, ver ese .md).
Es un reporte de diagnóstico de calidad de dato, no el layout de gastos en
sí — Poliza_Detalle sola ya reconcilia al 100% contra el folio (ver
Layout de gastos). Este reporte responde una
pregunta distinta: ¿el reparto por centro de costo que trae
Gasto_Registro_Control coincide con lo que se contabilizó?
Origen completo del trabajo (scripts numerados 01-13, PROGRESS.md,
RESUMEN_CASOS.md): conciliacion-master/layout-gastos/ en
proyectos-bi — ese es el laboratorio de exploración; este reporte es la
promoción de 11_reporte_base_ceco.py/12_reporte_base_ceco_consumo_interno.py
a Streamlit, misma lógica.
Rediseño 2026-09-03 — sin máscara de reversión
La versión original de este reporte (promoción de
09_reconciliacion_completa_con_consumo_interno.py) decidía Cargo vs.
Abono con una regla de reversión por folio ("si IMPORTE del folio ≤
-$1, usar Abono"), calculada del lado operativo. Existía solo porque la
query de póliza (v03_detalle_cuenta_centro_costo.sql, heredada de
FlexMonster) colapsaba Pd_Tipo — el dato real, 1=Cargo/2=Abono — en dos
columnas sumadas antes de que el código pudiera ver cuál era la línea
real.
Esta versión agrupa por Pd_Tipo en vez de colapsarlo —
TIPO_MOVIMIENTO sale directo del dato, cero regla, cero máscara.
Validado no solo en agregado sino posición por posición dentro de
(FOLIO, CECO), contra el diseño viejo: cero diferencias en miles
de combinaciones (FOLIO, CENTRO) comparadas. Mismo resultado exacto,
mecanismo honesto.
Dos bugs reales encontrados al dejar de colapsar (ninguno cambió el %
final, sí la honestidad del mecanismo) — detalle completo en
PROGRESS.md del proyecto de origen (entrada 2026-09-03):
Gr_Tablaviene''(noNULL) paraGASTO_DIRECTO— se normaliza en el SQL, no con un.fillna()después del hecho.- Líneas de póliza sin
Pd_Centro_Costoreal (contrapartida normal de doble entrada — Abono a Proveedores/Provisión/Préstamos, cuentas de balance sin centro) se excluyen a propósito (AND pd.Pd_Centro_Costo <> ''), no por accidente.
Un tercer bug, específico del folio de display: Gr_Folio ya es el
folio completo tal cual lo ve el usuario en MPRO ("SS-NNNNNNN",
sucursal 2 dígitos + folio 7 dígitos, varchar(10) fijo) — no hacía
falta reconstruirlo concatenando Sc_Cve_Sucursal (ese catálogo guarda
la sucursal con 4 dígitos, "00"+2, un formato distinto que nunca
correspondió al folio de display). El código viejo (y los 13 scripts de
la exploración de origen) lo reconstruían sin necesidad — corregido en
todos.
Fuentes y grano
Grano del reporte: (FOLIO, CECO, TIPO_GASTO) — 1 fila por
combinación, con la línea real de póliza (CUENTA, TIPO_MOVIMIENTO,
IMPORTE) que le tocó por posición dentro de (FOLIO, CECO)
(rank-pairing — no existe llave real entre Grc_ID y Poliza_Detalle,
Poliza_Detalle no guarda Grd_ID). Confirmado que CARGO/ABONO
nunca coexisten !=0 en la misma fila, ni siquiera en el residual de
GASTO_RECLASIFICACION que mezcla signos en un mismo centro.
- Lado operativo:
Gasto_Registro_Control(Grc_Importe), colapsado por(Tg_Cve_Tipo_Gasto, Cc_Cve_Centro_Costo)— no porGrd_ID(documento). Confirmado con folio real01-0034885("TELEFONIA", 7 recibos/documentos): colapsado por documento da 53 filas, por tipo de gasto da 27, exacto el número de líneas reales de la póliza. - Lado contable:
Poliza_Detalle, agrupado por(Cc_Cve_Cuenta_Contable, Pd_Centro_Costo, Pd_Tipo)—Pd_Tiporeal decideTIPO_MOVIMIENTO, nunca inferido. ParaCONSUMO_INTERNO, query aparte (filtra la póliza de gasto real, excluye la memo de inventario). .205(no productiva), a propósito — toda la exploración de origen se construyó y validó contra esta instancia (verget_engine_205()encontabilidad/db.py).
Reconciliación — a nivel FOLIO, no fila (2026-09-03)
La pestaña "Reconciliación" compara, por folio, Cargo - Abono
(sumado sobre todas sus líneas de CECO x Tipo de Gasto) contra el
importe nativo del folio (Gasto_Registro_Documento, la misma cifra
que reporta MPRO — no Grc_Importe). Reemplaza la comprobación a nivel
fila (que dependía del rank-pairing y heredaba su residual) por una
pregunta más simple: "¿el folio completo cierra?", sin importar cómo se
repartieron sus líneas entre centros/tipos de gasto. Tolerancia < $1.
Reglas de negocio aplicadas
GASTO_RECLASIFICACION— par espejo Cargo=Abono dentro de la misma póliza. El signo deGrc_Importepor línea (no si el folio completo es negativo) decide si esa línea es Cargo (positivo) o Abono (negativo) — del lado operativo únicamente; del lado póliza no hace falta decidir nada,TIPO_MOVIMIENTOya viene dePd_Tipo.CONSUMO_INTERNO— genera dos pólizas paralelas por folio (memo de inventario10500/10600vs. gasto real). Se filtraPoliza.Pl_Comentario(excluir "CUENTAS DE ORDEN"/"CTS ORDEN"/"CUENTA ORDEN") para quedarse con la de gasto real. Confirmado 2026-09-03 conPd_Tiporeal (no asumido, a diferencia de la versión anterior de este reporte): 100% Cargo, 0% Abono con centro real.
Resultado de referencia (enero 2026, empresa 0001)
| Origen | Filas |
|---|---|
| CONTROL_COMBUSTIBLE | 591 |
| GASTO_DIRECTO | 6,531 |
| GASTO_RECLASIFICACION | 143 |
| ORDEN_COMPRA | 80 |
| VIAJE | 346 |
| CONSUMO_INTERNO | 3,072 |
| Total | 10,763 (4,395 folios) |
99.75% de las filas cuadran contra la estimación operativa;
Importe reporte MPRO (deduplicado por folio) coincide con el importe
nativo agregado del periodo. Detalle completo del residual conocido
(<0.06% del universo trimestral, causas identificadas en su mayoría) en
PROGRESS.md del proyecto de origen.
El Streamlit
Código:
contabilidad/pages/1_Layout_de_Gastos_por_CECO_CONT-1.py
+ lógica de negocio en
contabilidad/layout_gastos_ceco_lib.py
+ UI compartida con CONT-2 en
contabilidad/layout_gastos_ceco_ui.py
(patrón del skill trivasa-streamlit-reportes).
- Filtros: Periodo (rango de fechas, ambas inclusivas), Origen (multiselect, default = todos), Buscar (texto libre sobre folio/póliza/ CECO/cuenta/tipo de gasto).
- Métricas: Filas, Folios, % cuadra vs. lado operativo, Σ Cargo, Σ Abono, Importe reporte MPRO.
- Tabs: Datos (con descarga Excel) · Reconciliación (semáforo por origen + tabla de folios que no cuadran) · Documentación.
Pendiente
- ~~Implementar la rama de capitalización de activo fijo para
CONSUMO_INTERNO~~ — resuelto 2026-09-08 (verconciliacion-master/layout-gastos/PROGRESS.md, entrada de esa fecha). La hipótesis original (parsearGrd_Comentario"U-NNN") era incorrecta: el código corto ya vive tal cual enGasto_Registro.Gr_Referencia, yPoliza_Configuracion_Detalle.Pcd_Referenciade las configs0295/0414lo confirma (Pcd_Referencia = Gasto_Registro.Gr_Referencia, noGr_Folio— verconfiguracion-polizas.md, sección "Addendum 2026-09-08").Gr_Referenciano es único dentro de una póliza (colisiona en ~28% de las pólizas de esta rama) — se resuelve con la misma técnica de rank-pairing que el resto del proyecto, por(Pl_Folio, Referencia). Resultado:CONSUMO_INTERNOsube de 99.37% a 99.84% (enero-marzo 2026), 45/47 folios de activo fijo recuperados. Queda un residual de 2 folios que reparten el gasto en más de un centro de costo (no cubierto por el rank-pairing simple sin CECO en la llave). - Aplicar la regla de reversión de folio a
CONSUMO_INTERNOsi aplica (no investigado si tiene sus propios folios de reversión). - Mejorar el filtro de doble póliza de
CONSUMO_INTERNO(Pl_Comentario NOT LIKE '%CUENTAS DE ORDEN%', texto libre, frágil) por uno basado en cuenta contable. - Decidir qué hacer con las filas residuales del rank-pairing (<0.06%):
hoy quedan visibles marcadas
TIPO_GASTO/CUENTA=(residual).