105 lines
4.2 KiB
TypeScript
105 lines
4.2 KiB
TypeScript
/**
|
|
* Amplía la inspección: lista TODOS los CFDIs de mayo-2025 donde Horux 360
|
|
* aparece como emisor o receptor, marcando cuáles entran al bucket ingresos
|
|
* y cuáles no + por qué.
|
|
*/
|
|
import { prisma, tenantDb } from '../src/config/database.js';
|
|
import { resolveContribuyenteContext } from '../src/utils/contribuyente-context.js';
|
|
|
|
const TENANT_RFC = 'DESPACHO_MO3NI6U8_B9VGG';
|
|
const CONTRIB_ID = 'b3761db6-0b8d-4251-8078-4ddc31e9c75b';
|
|
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=== TODOS los CFDIs de Horux 360 en mayo-2025 (como emisor o receptor) ===\n`);
|
|
|
|
const { rows } = await pool.query(
|
|
`SELECT uuid, type, tipo_comprobante, metodo_pago, status,
|
|
regimen_fiscal_emisor, regimen_fiscal_receptor,
|
|
rfc_emisor, rfc_receptor, nombre_receptor, nombre_emisor,
|
|
total_mxn, monto_pago_mxn, cfdi_tipo_relacion, fecha_emision, source
|
|
FROM cfdis
|
|
WHERE ((${ctx.esEmisor}) OR (${ctx.esReceptor}))
|
|
AND fecha_emision >= $1::date
|
|
AND fecha_emision < ($2::date + interval '1 day')
|
|
ORDER BY fecha_emision, tipo_comprobante, total_mxn DESC`,
|
|
[FI, FF],
|
|
);
|
|
|
|
console.log(`Total CFDIs encontrados: ${rows.length}\n`);
|
|
|
|
const buckets: Record<string, any[]> = {
|
|
ingresosG1: [],
|
|
ingresosG3: [],
|
|
ingresosSueldos: [],
|
|
noIncluye_canceladoOinvalido: [],
|
|
noIncluye_regimenFuera: [],
|
|
noIncluye_comoReceptor: [],
|
|
noIncluye_otroMotivo: [],
|
|
};
|
|
|
|
const G1 = ['606', '612', '621', '625', '626'];
|
|
const G3 = ['601', '603', '607', '608', '610', '611', '614', '615', '620', '622', '623', '624'];
|
|
|
|
for (const r of rows) {
|
|
const cancel = ['Cancelado', '0'].includes(r.status);
|
|
const esEmisorRow = String(r.rfc_emisor).toUpperCase() === 'HTS240708LJA';
|
|
const regE = r.regimen_fiscal_emisor;
|
|
const regR = r.regimen_fiscal_receptor;
|
|
|
|
if (cancel) { buckets.noIncluye_canceladoOinvalido.push(r); continue; }
|
|
|
|
if (esEmisorRow) {
|
|
if (G1.includes(regE)) {
|
|
if ((r.tipo_comprobante === 'I' && r.metodo_pago === 'PUE') ||
|
|
(r.tipo_comprobante === 'P') ||
|
|
(r.tipo_comprobante === 'E' && r.metodo_pago === 'PUE')) {
|
|
buckets.ingresosG1.push(r); continue;
|
|
}
|
|
}
|
|
if (G3.includes(regE)) {
|
|
if ((r.tipo_comprobante === 'I' && ['PUE', 'PPD'].includes(r.metodo_pago)) ||
|
|
(r.tipo_comprobante === 'E' && r.metodo_pago === 'PUE')) {
|
|
buckets.ingresosG3.push(r); continue;
|
|
}
|
|
}
|
|
if (!G1.includes(regE) && !G3.includes(regE)) {
|
|
buckets.noIncluye_regimenFuera.push({ ...r, reason: `emisor régimen ${regE} fuera de grupo` });
|
|
continue;
|
|
}
|
|
buckets.noIncluye_otroMotivo.push({ ...r, reason: `emisor tipo=${r.tipo_comprobante}/${r.metodo_pago} no matchea` });
|
|
continue;
|
|
}
|
|
|
|
// No emisor → receptor
|
|
if (r.tipo_comprobante === 'N' && r.metodo_pago === 'PUE' && regR === '605') {
|
|
buckets.ingresosSueldos.push(r); continue;
|
|
}
|
|
buckets.noIncluye_comoReceptor.push({ ...r, reason: 'es receptor, no cuenta como ingreso (salvo N/605)' });
|
|
}
|
|
|
|
const fmt = (n: any) => Number(n || 0).toFixed(2);
|
|
|
|
for (const [name, list] of Object.entries(buckets)) {
|
|
if (list.length === 0) continue;
|
|
console.log(`\n--- ${name} (${list.length}) ---`);
|
|
for (const r of list) {
|
|
const fe = r.fecha_emision?.toISOString?.()?.slice(0, 10) || r.fecha_emision;
|
|
const reason = r.reason ? ` | ${r.reason}` : '';
|
|
console.log(` ${fe} ${r.tipo_comprobante}/${r.metodo_pago || '-'} status=${r.status} regE=${r.regimen_fiscal_emisor} regR=${r.regimen_fiscal_receptor} ${r.rfc_emisor}→${r.rfc_receptor} total=${fmt(r.total_mxn)} mp=${fmt(r.monto_pago_mxn)} ${r.uuid.substring(0,8)}${reason}`);
|
|
}
|
|
}
|
|
|
|
await prisma.$disconnect();
|
|
}
|
|
|
|
main().catch(async e => { console.error(e); await prisma.$disconnect().catch(() => {}); process.exit(1); });
|