import { prisma, tenantDb } from '../src/config/database.js'; const yearMonth = '2025-02'; const contribuyenteId = 'd745a915-6a23-4818-944b-a7e1e18e536a'; const tenantRfc = 'DESPACHO_MO3NI6U8_B9VGG'; async function main() { const tenant = await prisma.tenant.findFirst({ where: { rfc: tenantRfc }, select: { id: true, databaseName: true } }); if (!tenant) return; const pool = await tenantDb.getPool(tenant.id, tenant.databaseName); const [anio, mes] = yearMonth.split('-').map(Number); const lastDay = new Date(anio, mes, 0).getDate(); const fi = `${yearMonth}-01`; const ff = `${yearMonth}-${String(lastDay).padStart(2, '0')}`; 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 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 ('84121603','93161608','85101501','85121800')), 0)`; // Drill desglosado por régimen del receptor const { rows } = await pool.query( `SELECT COALESCE(regimen_fiscal_receptor, 'null') AS regimen_rec, type, tipo_comprobante, metodo_pago, COALESCE(cfdi_tipo_relacion, '') AS tipo_rel, COUNT(*)::int AS n, SUM(total_mxn) AS total_bruto, SUM(COALESCE(total_mxn,0) - (${IMP_TRAS}) - (${EXCL_MONTO})) AS total_neto, SUM(COALESCE(monto_pago_mxn,0) - (${IMP_TRAS_PAGO})) AS pago_neto FROM cfdis WHERE ( (type='RECIBIDO' AND tipo_comprobante='I' AND metodo_pago='PUE') OR (type='RECIBIDO' AND tipo_comprobante='P') OR (type='RECIBIDO' AND tipo_comprobante='E' AND metodo_pago='PUE' AND COALESCE(cfdi_tipo_relacion,'')<>'07') ) AND status NOT IN ('Cancelado','0') AND ((tipo_comprobante='P' AND fecha_pago_p >= $1::date AND fecha_pago_p < ($2::date + interval '1 day')) OR (tipo_comprobante!='P' AND fecha_emision >= $1::date AND fecha_emision < ($2::date + interval '1 day'))) AND contribuyente_id = $3 GROUP BY regimen_rec, type, tipo_comprobante, metodo_pago, tipo_rel ORDER BY regimen_rec, tipo_comprobante, metodo_pago`, [fi, ff, contribuyenteId], ); const byReg: Record = {}; for (const r of rows) { const reg = r.regimen_rec; if (!byReg[reg]) byReg[reg] = { fact: 0, pago: 0, nc: 0, detalle: [] }; const v = r.tipo_comprobante === 'P' ? Number(r.pago_neto) : Number(r.total_neto); byReg[reg].detalle.push({ tc: r.tipo_comprobante, mp: r.metodo_pago, rel: r.tipo_rel, n: r.n, valor: v, bruto: Number(r.total_bruto) }); if (r.tipo_comprobante === 'I') byReg[reg].fact += v; else if (r.tipo_comprobante === 'P') byReg[reg].pago += v; else if (r.tipo_comprobante === 'E') byReg[reg].nc += v; } console.log(`\n=== DRILL-DOWN por régimen del receptor — ${fi} a ${ff} ===\n`); let totalAll = 0; const TODOS_REGS = new Set(['605','606','612','621','625','626','601','603','607','608','610','611','614','615','620','622','623','624']); for (const [reg, v] of Object.entries(byReg).sort()) { const subtot = v.fact + v.pago - v.nc; totalAll += subtot; const inTodos = TODOS_REGS.has(reg) ? '✓' : '✗ (excluido de TODOS_REGIMENES)'; console.log(`Régimen ${reg} ${inTodos}`); console.log(` fact=${v.fact.toFixed(2)} pago=${v.pago.toFixed(2)} NC=${v.nc.toFixed(2)} → subtotal=${subtot.toFixed(2)}`); for (const d of v.detalle) { console.log(` ${d.tc} ${d.mp || '-'} rel=${d.rel || '-'} n=${d.n} bruto=${d.bruto.toFixed(2)} neto=${d.valor.toFixed(2)}`); } } console.log(`\nTotal todos regímenes: ${totalAll.toFixed(2)}`); const inTodos = Object.entries(byReg).filter(([r]) => TODOS_REGS.has(r)).reduce((s, [, v]) => s + (v.fact + v.pago - v.nc), 0); console.log(`Total solo en TODOS_REGIMENES: ${inTodos.toFixed(2)}`); await prisma.$disconnect(); } main().catch(async e => { console.error(e); await prisma.$disconnect().catch(() => {}); process.exit(1); });