/** * Inspecciona el estado de un CFDI y sus relacionados (pagos + E/07) en todos * los tenants. Útil para debug de saldos pendientes. * * Uso: * pnpm --filter @horux/api exec tsx scripts/inspect-cfdi.ts */ import { prisma, tenantDb } from '../src/config/database.js'; const rawUuid = process.argv[2]; if (!rawUuid) { console.error('Usage: tsx scripts/inspect-cfdi.ts '); process.exit(1); } const uuid = rawUuid.toLowerCase(); async function main() { const tenants = await prisma.tenant.findMany({ where: { active: true }, select: { id: true, rfc: true, databaseName: true }, orderBy: { rfc: 'asc' }, }); for (const t of tenants) { const pool = await tenantDb.getPool(t.id, t.databaseName); const { rows: base } = await pool.query( `SELECT id, uuid, type, tipo_comprobante, metodo_pago, status, fecha_emision, total, total_mxn, monto_pago, monto_pago_mxn, saldo_insoluto, saldo_pendiente, saldo_pendiente_mxn, uuid_relacionado, cfdi_tipo_relacion, cfdis_relacionados, rfc_emisor, rfc_receptor, conciliado, id_conciliacion, source, facturapi_id FROM cfdis WHERE LOWER(uuid) = $1`, [uuid], ); if (base.length === 0) continue; console.log(`\n=== Tenant ${t.rfc} (${t.databaseName}) ===`); console.log('CFDI base:'); console.log(base[0]); // P complements que apuntan a este UUID via uuid_relacionado (DoctoRelacionado) const { rows: pagosP } = await pool.query( `SELECT id, uuid, type, tipo_comprobante, fecha_emision, fecha_pago_p, monto_pago, monto_pago_mxn, num_parcialidad, uuid_relacionado, status FROM cfdis WHERE tipo_comprobante = 'P' AND LOWER(uuid_relacionado) = $1 ORDER BY fecha_pago_p NULLS LAST, id`, [uuid], ); console.log(`\nComplementos P que referencian este UUID (DoctoRelacionado): ${pagosP.length}`); for (const r of pagosP) console.log(' ', r); // E CFDIs con cfdis_relacionados que contengan este UUID (TipoRelacion=07 típicamente) const { rows: ecfdis } = await pool.query( `SELECT id, uuid, type, tipo_comprobante, metodo_pago, fecha_emision, total, total_mxn, cfdi_tipo_relacion, cfdis_relacionados, status FROM cfdis WHERE tipo_comprobante = 'E' AND cfdis_relacionados IS NOT NULL AND LOWER(cfdis_relacionados) LIKE $1 ORDER BY fecha_emision, id`, [`%${uuid}%`], ); console.log(`\nCFDIs tipo E con este UUID en cfdis_relacionados: ${ecfdis.length}`); for (const r of ecfdis) console.log(' ', r); // Si el base está conciliado, traer la fila if (base[0].id_conciliacion) { const { rows: conc } = await pool.query( `SELECT * FROM conciliaciones WHERE id = $1`, [base[0].id_conciliacion], ); console.log(`\nConciliación vinculada:`); for (const r of conc) console.log(' ', r); } } await prisma.$disconnect(); } main().catch(async (err) => { console.error('Fatal:', err); await prisma.$disconnect().catch(() => {}); process.exit(1); });