112 lines
5.2 KiB
TypeScript
112 lines
5.2 KiB
TypeScript
/**
|
||
* Debug ingresos Horux 360 mayo-2025 post-Método A:
|
||
* - Llama al KPI (calcularIngresosPorRegimen)
|
||
* - Lista los CFDIs que entran al drill-down (mismos filtros del controller)
|
||
* - Suma manualmente para ver dónde está la discrepancia
|
||
*/
|
||
process.env.METRICAS_BYPASS_CACHE = '1';
|
||
import { prisma, tenantDb } from '../src/config/database.js';
|
||
import { calcularIngresosPorRegimen, GRUPO_PF_EMPRESARIAL, GRUPO_PM_OTROS } from '../src/services/dashboard.service.js';
|
||
import { resolveContribuyenteContext } from '../src/utils/contribuyente-context.js';
|
||
|
||
const TENANT_RFC = 'DESPACHO_MO3NI6U8_B9VGG';
|
||
const CONTRIB_ID = 'b3761db6-0b8d-4251-8078-4ddc31e9c75b'; // Horux 360
|
||
const FI = '2025-05-01';
|
||
const FF = '2025-05-31';
|
||
|
||
async function main() {
|
||
const tenant = await prisma.tenant.findFirst({
|
||
where: { rfc: TENANT_RFC },
|
||
select: { id: true, databaseName: true },
|
||
});
|
||
if (!tenant) return;
|
||
const pool = await tenantDb.getPool(tenant.id, tenant.databaseName);
|
||
const ctx = await resolveContribuyenteContext(pool, tenant.id, CONTRIB_ID);
|
||
|
||
console.log(`\n=== KPI calcularIngresosPorRegimen ===`);
|
||
const kpi = await calcularIngresosPorRegimen(
|
||
pool, tenant.id, FI, FF, undefined, undefined, false, CONTRIB_ID,
|
||
);
|
||
console.log(`Total KPI: ${kpi.total.toFixed(2)}`);
|
||
for (const r of kpi.porRegimen) {
|
||
console.log(` ${r.regimenClave} ${r.regimenDescripcion.substring(0, 40).padEnd(40)} ${r.monto.toFixed(2)}`);
|
||
}
|
||
|
||
// Replica de los filtros del drill-down bucket 'ingresos' (cfdi.controller.ts:163-187)
|
||
const IMP_TRAS = `COALESCE(iva_traslado_mxn,0) + COALESCE(ieps_traslado_mxn,0) + COALESCE(impuestos_locales_trasladado_mxn,0)`;
|
||
const IMP_TRAS_PAGO = `COALESCE(iva_traslado_pago_mxn,0) + COALESCE(ieps_traslado_pago_mxn,0)`;
|
||
const VIGENTE = `status NOT IN ('Cancelado', '0')`;
|
||
const CLAVES = `('84121603','93161608','85101501','85121800')`;
|
||
const EXCL_MONTO = `COALESCE((SELECT SUM(COALESCE(cc.importe_mxn,0)-COALESCE(cc.descuento_mxn,0)) FROM cfdi_conceptos cc WHERE cc.cfdi_id = cfdis.id AND cc.clave_prod_serv IN ${CLAVES}),0)`;
|
||
|
||
const g1 = GRUPO_PF_EMPRESARIAL.map(r => `'${r}'`).join(',');
|
||
const g3 = GRUPO_PM_OTROS.map(r => `'${r}'`).join(',');
|
||
|
||
const drillSql = `
|
||
SELECT id, uuid, type, tipo_comprobante, metodo_pago, regimen_fiscal_emisor,
|
||
regimen_fiscal_receptor, rfc_emisor, rfc_receptor, nombre_receptor,
|
||
total_mxn, iva_traslado_mxn, ieps_traslado_mxn, impuestos_locales_trasladado_mxn,
|
||
monto_pago_mxn, iva_traslado_pago_mxn, ieps_traslado_pago_mxn,
|
||
cfdi_tipo_relacion, fecha_emision, fecha_pago_p, source,
|
||
-- neto (lo que "contribuye" a ingresos según grupo)
|
||
CASE
|
||
WHEN tipo_comprobante='I' THEN (COALESCE(total_mxn,0) - (${IMP_TRAS}) - (${EXCL_MONTO}))
|
||
WHEN tipo_comprobante='E' THEN -(COALESCE(total_mxn,0) - (${IMP_TRAS}) - (${EXCL_MONTO}))
|
||
WHEN tipo_comprobante='P' THEN (COALESCE(monto_pago_mxn,0) - (${IMP_TRAS_PAGO}))
|
||
WHEN tipo_comprobante='N' THEN COALESCE(total_mxn,0)
|
||
ELSE 0
|
||
END AS aporte
|
||
FROM cfdis
|
||
WHERE ${VIGENTE}
|
||
AND fecha_emision >= $1::date AND fecha_emision < ($2::date + interval '1 day')
|
||
AND (
|
||
(${ctx.esEmisor} AND regimen_fiscal_emisor IN (${g1}) AND (
|
||
(tipo_comprobante='I' AND metodo_pago='PUE')
|
||
OR (tipo_comprobante='P')
|
||
OR (tipo_comprobante='E' AND metodo_pago='PUE')
|
||
))
|
||
OR (${ctx.esReceptor} AND tipo_comprobante='N' AND metodo_pago='PUE' AND regimen_fiscal_receptor='605')
|
||
OR (${ctx.esEmisor} AND regimen_fiscal_emisor IN (${g3}) AND (
|
||
(tipo_comprobante='I' AND metodo_pago IN ('PUE','PPD'))
|
||
OR (tipo_comprobante='E' AND metodo_pago='PUE')
|
||
))
|
||
)
|
||
ORDER BY fecha_emision, tipo_comprobante, total_mxn DESC
|
||
`;
|
||
|
||
const { rows } = await pool.query(drillSql, [FI, FF]);
|
||
console.log(`\n=== Drill-down (${rows.length} CFDIs) ===`);
|
||
|
||
let sumDrill = 0;
|
||
const perRegimen: Record<string, number> = {};
|
||
|
||
for (const r of rows) {
|
||
const aporte = Number(r.aporte || 0);
|
||
sumDrill += aporte;
|
||
const reg = r.regimen_fiscal_emisor || r.regimen_fiscal_receptor || '?';
|
||
perRegimen[reg] = (perRegimen[reg] || 0) + aporte;
|
||
|
||
const fe = r.fecha_emision?.toISOString?.()?.slice(0, 10) || r.fecha_emision;
|
||
const rel07 = r.cfdi_tipo_relacion === '07' ? ' [07]' : '';
|
||
const src = r.source === 'facturapi' ? ' [facturapi]' : '';
|
||
console.log(
|
||
` ${fe} ${r.tipo_comprobante}/${r.metodo_pago}${rel07}${src} ` +
|
||
`reg=${reg} ${String(r.rfc_emisor).padEnd(14)}→${String(r.rfc_receptor).padEnd(14)} ` +
|
||
`total=${Number(r.total_mxn || 0).toFixed(2).padStart(10)} ` +
|
||
`aporte=${aporte.toFixed(2).padStart(10)} ${r.uuid.substring(0,8)}`
|
||
);
|
||
}
|
||
|
||
console.log(`\n=== Suma de aportes del drill-down: ${sumDrill.toFixed(2)} ===`);
|
||
console.log(`Por régimen (drill-down):`);
|
||
for (const [reg, monto] of Object.entries(perRegimen).sort()) {
|
||
console.log(` ${reg}: ${monto.toFixed(2)}`);
|
||
}
|
||
|
||
console.log(`\n=== Diferencia KPI − drill: ${(kpi.total - sumDrill).toFixed(2)} ===`);
|
||
|
||
await prisma.$disconnect();
|
||
}
|
||
|
||
main().catch(async e => { console.error(e); await prisma.$disconnect().catch(() => {}); process.exit(1); });
|