79 lines
2.8 KiB
TypeScript
79 lines
2.8 KiB
TypeScript
/**
|
|
* Backfill: re-parsea CFDIs tipo P emitidos vía Facturapi (source='facturapi')
|
|
* que tienen `monto_pago_mxn` o `fecha_pago_p` NULL, y popula esos campos
|
|
* desde el XML original. Bug histórico — el INSERT de facturapi.controller.ts
|
|
* no incluía los campos del complemento Pagos hasta el fix de hoy.
|
|
*
|
|
* Idempotente — solo actualiza si el XML tiene datos y el row tiene NULL.
|
|
*/
|
|
import { prisma, tenantDb } from '../src/config/database.js';
|
|
import { parseXml } from '../src/services/sat/sat-parser.service.js';
|
|
|
|
async function main() {
|
|
const tenants = await prisma.tenant.findMany({
|
|
where: { active: true },
|
|
select: { id: true, rfc: true, nombre: true, databaseName: true },
|
|
});
|
|
|
|
let totalUpdated = 0;
|
|
let totalChecked = 0;
|
|
|
|
for (const t of tenants) {
|
|
const pool = await tenantDb.getPool(t.id, t.databaseName);
|
|
const { rows } = await pool.query(`
|
|
SELECT uuid, xml_original
|
|
FROM cfdis
|
|
WHERE source = 'facturapi'
|
|
AND tipo_comprobante = 'P'
|
|
AND xml_original IS NOT NULL
|
|
AND (monto_pago_mxn IS NULL OR fecha_pago_p IS NULL)
|
|
`);
|
|
|
|
if (rows.length === 0) continue;
|
|
console.log(`\n>>> ${t.rfc} (${t.nombre}): ${rows.length} P por backfill`);
|
|
|
|
for (const r of rows) {
|
|
totalChecked++;
|
|
const parsed = parseXml(r.xml_original, 'emitidos');
|
|
if (!parsed || parsed.tipoComprobante !== 'P') continue;
|
|
|
|
const fechaPagoP = parsed.fechaPagoP
|
|
? new Date(String(parsed.fechaPagoP).split('|')[0])
|
|
: null;
|
|
|
|
if (!parsed.montoPago && !fechaPagoP) {
|
|
console.log(` ${r.uuid}: XML sin datos de Pago — skip`);
|
|
continue;
|
|
}
|
|
|
|
await pool.query(`
|
|
UPDATE cfdis SET
|
|
monto_pago = COALESCE(monto_pago, $1),
|
|
monto_pago_mxn = COALESCE(monto_pago_mxn, $1),
|
|
fecha_pago_p = COALESCE(fecha_pago_p, $2),
|
|
iva_traslado_pago = COALESCE(iva_traslado_pago, $3),
|
|
iva_traslado_pago_mxn = COALESCE(iva_traslado_pago_mxn, $3),
|
|
iva_retencion_pago = COALESCE(iva_retencion_pago, $4),
|
|
iva_retencion_pago_mxn = COALESCE(iva_retencion_pago_mxn, $4),
|
|
ieps_traslado_pago = COALESCE(ieps_traslado_pago, $5),
|
|
ieps_traslado_pago_mxn = COALESCE(ieps_traslado_pago_mxn, $5)
|
|
WHERE uuid = $6
|
|
`, [
|
|
parsed.montoPago || 0,
|
|
fechaPagoP,
|
|
parsed.ivaTrasladoPago || 0,
|
|
parsed.ivaRetencionPago || 0,
|
|
parsed.iepsTrasladoPago || 0,
|
|
r.uuid,
|
|
]);
|
|
totalUpdated++;
|
|
console.log(` ${r.uuid}: ✓ monto=$${parsed.montoPago} fecha_pago=${fechaPagoP?.toISOString().slice(0, 10)} iva=$${parsed.ivaTrasladoPago}`);
|
|
}
|
|
}
|
|
|
|
console.log(`\n[Backfill] Completado: ${totalUpdated}/${totalChecked} actualizadas`);
|
|
await prisma.$disconnect();
|
|
}
|
|
|
|
main().catch(e => { console.error(e); process.exit(1); });
|