/** * Inspecciona un CFDI específico para entender por qué el filtro de * "Considerar activos" no lo captura. Imprime los campos relevantes y * cualquier CFDI relacionado. */ import { prisma, tenantDb } from '../src/config/database.js'; async function main() { const uuid = process.argv[2] || '8ec2eaf3-7879-11f0-81a8-8daae9822b10'; // Buscar en TODOS los tenants const tenants = await prisma.tenant.findMany({ where: { active: true }, select: { id: true, rfc: true, nombre: true, databaseName: true }, }); for (const t of tenants) { const pool = await tenantDb.getPool(t.id, t.databaseName); const { rows } = await pool.query(` SELECT uuid, type, tipo_comprobante, metodo_pago, forma_pago, uso_cfdi, cfdi_tipo_relacion, rfc_emisor, nombre_emisor, regimen_fiscal_emisor, rfc_receptor, nombre_receptor, regimen_fiscal_receptor, total_mxn, monto_pago_mxn, fecha_emision, fecha_pago_p, status, uuid_relacionado, cfdis_relacionados FROM cfdis WHERE uuid = $1 `, [uuid]); if (rows.length === 0) continue; console.log(`\n═══ Tenant: ${t.rfc} (${t.nombre}) ═══`); const r = rows[0]; for (const [k, v] of Object.entries(r)) { console.log(` ${k.padEnd(28)} ${v}`); } // Si hay uuid_relacionado o cfdis_relacionados, traer esos también if (r.uuid_relacionado) { const { rows: rel } = await pool.query( `SELECT uuid, tipo_comprobante, uso_cfdi, total_mxn FROM cfdis WHERE LOWER(uuid) = LOWER($1)`, [r.uuid_relacionado], ); console.log(`\n Relacionado vía uuid_relacionado (${r.uuid_relacionado}):`); console.log(rel[0] || '(no encontrado)'); } if (r.cfdis_relacionados) { const uuids = String(r.cfdis_relacionados).split('|').map(s => s.trim()).filter(Boolean); console.log(`\n Relacionados vía cfdis_relacionados (${uuids.length}):`); for (const u of uuids) { const { rows: rel } = await pool.query( `SELECT uuid, tipo_comprobante, uso_cfdi, total_mxn FROM cfdis WHERE LOWER(uuid) = LOWER($1)`, [u], ); console.log(` ${u} →`, rel[0] || '(no encontrado)'); } } // Test del filtro: aplica activosExclusionNoAlias y verifica const ACTIVOS_USOS = "('I01','I02','I03','I04','I05','I06','I07','I08')"; const test = await pool.query(` SELECT (tipo_comprobante = 'I' AND uso_cfdi IN ${ACTIVOS_USOS}) AS regla1_directo, (tipo_comprobante = 'P' AND EXISTS ( SELECT 1 FROM cfdis i_act WHERE LOWER(i_act.uuid) = LOWER(cfdis.uuid_relacionado) AND i_act.tipo_comprobante = 'I' AND i_act.uso_cfdi IN ${ACTIVOS_USOS} )) AS regla2_p_paga_activo, (tipo_comprobante = 'E' AND cfdis.cfdis_relacionados IS NOT NULL AND EXISTS ( SELECT 1 FROM cfdis r_act WHERE LOWER(r_act.uuid) = ANY(string_to_array(LOWER(cfdis.cfdis_relacionados), '|')) AND (r_act.tipo_comprobante = 'I' AND r_act.uso_cfdi IN ${ACTIVOS_USOS}) )) AS regla3_e_referencia_activo, (tipo_comprobante = 'I' AND EXISTS ( SELECT 1 FROM cfdis i07_act WHERE i07_act.tipo_comprobante = 'I' AND i07_act.metodo_pago = 'PPD' AND COALESCE(i07_act.cfdi_tipo_relacion, '') = '07' AND i07_act.uso_cfdi IN ${ACTIVOS_USOS} AND i07_act.status NOT IN ('Cancelado', '0') AND i07_act.cfdis_relacionados IS NOT NULL AND LOWER(cfdis.uuid) = ANY(string_to_array(LOWER(i07_act.cfdis_relacionados), '|')) )) AS regla4_anticipo_activo FROM cfdis WHERE uuid = $1 `, [uuid]); console.log(`\n Filtro activos:`); console.log(` regla1 (I directo activo): ${test.rows[0].regla1_directo}`); console.log(` regla2 (P paga I activo): ${test.rows[0].regla2_p_paga_activo}`); console.log(` regla3 (E ref. I/P activo): ${test.rows[0].regla3_e_referencia_activo}`); console.log(` regla4 (anticipo de I/07 act): ${test.rows[0].regla4_anticipo_activo}`); const filtrado = test.rows[0].regla1_directo || test.rows[0].regla2_p_paga_activo || test.rows[0].regla3_e_referencia_activo || test.rows[0].regla4_anticipo_activo; console.log(` → ${filtrado ? '🔴 FILTRADO (excluido del cálculo)' : '🟢 PASA (incluido en cálculo)'}`); } await prisma.$disconnect(); } main().catch(e => { console.error(e); process.exit(1); });