Layout de Gastos — modelo de datos

Cadena de tablas

Un gasto en MPRO se registra en Gasto_Registro (folio, fecha, sucursal, Gr_Tabla — ver más abajo) con una o más líneas en Gasto_Registro_Documento (Grd_ID, importe, proveedor, tipo de gasto). El lado contable vive en una cadena aparte: Poliza_Control (Pc_Tabla='GASTO_REGISTRO', Pc_Documento=Gr_Folio) → Poliza → Poliza_Detalle (Pd_Referencia=Gr_Folio, Pd_Tipo 1=Cargo/2=Abono, Pd_Centro_Costo, Cc_Cve_Cuenta_Contable).

Poliza_Detalle.Pd_Referencia solo identifica el folio, nunca el documento (Grd_ID) específico — es la raíz de por qué atribuir Cargo/Abono a un documento individual dentro de un folio con 2+ documentos no es un join directo. Ver Atribución de Cargo/Abono por documento.

Gasto_Registro_Control — el desglose por documento que no es obvio

Tabla poco evidente pero clave: Gasto_Registro_Control (Gr_Folio, Grd_ID, Cc_Cve_Centro_Costo, Grc_Importe) sí desglosa cada documento por centro de costo — es lo que permite recuperar la granularidad que Poliza_Detalle no da directamente. Grc_ID (la clave de línea dentro de esta tabla) no identifica un documento distinto — identifica una sub-línea dentro del mismo documento y mismo centro de costo (ej. varios activos fijos de un documento de depreciación en el mismo centro); hay que colapsarla a 1 fila por (Gr_Folio, Grd_ID, Cc_Cve_Centro_Costo) sumando Grc_Importe antes de usarla, o se sobrecuenta.

Moneda: los importes NO están en pesos

Gasto_Registro_Documento guarda los importes en la moneda original del documento (Mn_Cve_Moneda), no en MXN. Hay que multiplicar Grd_Precio_Descontado_Importe / Grd_Impuesto_Importe / Grd_Precio_Neto_Importe por Grd_Tipo_Cambio para obtener el equivalente en pesos (para documentos en MXN, Grd_Tipo_Cambio = 1, no afecta). El reporte nativo de MPRO aplica esta conversión — sin ella, los documentos en moneda extranjera salen varias veces más chicos de lo real.

Gr_Tabla (“origen”) y sus mecanismos especiales

Gasto_Registro.Gr_Tabla identifica el subsistema que generó el folio. La mayoría de valores (VIAJE, ORDEN_COMPRA, CONTROL_COMBUSTIBLE, o vacío/manual) siguen el join normal de póliza de arriba, pero dos son excepciones estructurales:

  • CONSUMO_INTERNO / GASTO_REGISTRO_NOMINA: sí generan filas dentro de Gasto_Registro (no están en tablas separadas como se asumía originalmente en una primera versión del reporte) — pero por decisión de negocio no se les intenta ningún join de póliza; Cargo/Abono/Cuenta quedan vacíos a propósito.
  • GASTO_RECLASIFICACION: no tiene póliza real (Poliza_Control da 0 filas para estos folios). El Cargo/Abono real vive directo en Gasto_Registro_Documento: cada folio trae N filas “Reclasificación de gastos (Cargos)” (importe positivo) más las mismas N en espejo “(Abonos)” (importe negativo), cada una con su propio Tg_Cve_Tipo_Gasto → Tipo_Gasto.Tg_Cuenta_Contable.

Bugs de datos encontrados (y cómo se corrigieron)

  • Comprobante_Digital con LIKE duplica filas: un join tipo Cd_Documento LIKE Gr_Folio + Grd_ID + '%' no es único — algunos documentos matchean 2 UUID de CFDI distintos con el mismo prefijo, duplicando la fila entera (y por tanto sobre-contando su importe/cargo). Fix: OUTER APPLY (SELECT TOP 1 ... ORDER BY Cd_Documento) en vez de LEFT JOIN ... LIKE.
  • Poliza_Detalle_Comprobante no sirve para ligar un documento a su línea de póliza de registro: liga UUID de complemento de pago, no el UUID del CFDI original — verificado con un folio de 9 documentos donde la misma línea de póliza aparecía ligada a los 9 UUID por igual (irrelevante para esta atribución, aunque se ve usada con ese propósito en implementaciones de referencia de terceros).
  • Es_Cve_Estado = 'AP' excluye la mayoría de los folios: el estado real más común de un folio activo es AC, no AP — un filtro = 'AP' (visto en una implementación de referencia externa) excluía ~78% de los folios de un mes típico. La regla correcta es <> 'CA' (excluir solo cancelados).
  • Cuentas contables sin Cc_Grupo_Cuenta_Contable asignado: el árbol de Grupo_Cuenta_Contable (usado para decidir si una cuenta es raíz 'F' = Gastos, y por tanto si un Pd_Tipo=2 cuenta como Abono real) no está completo — varias cuentas de gasto legítimas no tienen grupo asignado. Dos familias confirmadas necesitan fallback explícito: cuentas 6xxx sin grupo, y la familia de costeo estándar 2120.010.xxx sufijo .002 (“Gastos a cuenta de costo estandar” — el sufijo .001, “Provision de costo estandar”, es la contrapartida/pasivo y sí se excluye correctamente). Ver Atribución de Cargo/Abono para la regla completa.

Véase también