feat(sat-sync): excluir tenant DEMO2501019X2 de sincronizaciones SAT
- Agrega SAT_SYNC_EXCLUDED_TENANTS en ecosystem.config.js con DEMO2501019X2. - Filtra tenants excluidos en getTenantsWithFiel() para crons automáticos. - Rechaza startSync() manual para tenants excluidos. - Incluye script check-daily-sync.js para monitorear cobertura diaria.
This commit is contained in:
143
apps/api/scripts/check-daily-sync.js
Normal file
143
apps/api/scripts/check-daily-sync.js
Normal file
@@ -0,0 +1,143 @@
|
||||
const { Client } = require('./node_modules/pg');
|
||||
|
||||
const HORUX_CONN = {
|
||||
host: 'localhost',
|
||||
port: 5432,
|
||||
user: 'postgres',
|
||||
password: 'ZxHMrmnwanvLfLDdNJdRthFjWF2Lj1Rb',
|
||||
database: 'horux360',
|
||||
};
|
||||
|
||||
const todayStart = new Date('2026-08-26T06:00:00.000Z'); // 00:00 CDMX approx
|
||||
const todayEnd = new Date('2026-08-27T06:00:00.000Z');
|
||||
|
||||
async function query(client, sql, params = []) {
|
||||
const res = await client.query(sql, params);
|
||||
return res.rows;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const client = new Client(HORUX_CONN);
|
||||
await client.connect();
|
||||
|
||||
// Tenants activos y su FIEL legacy (tenant-level, Horux 360 antiguo)
|
||||
// Se excluyen cuentas demo/ficticias configuradas en SAT_SYNC_EXCLUDED_TENANTS.
|
||||
const excluded = new Set(
|
||||
(process.env.SAT_SYNC_EXCLUDED_TENANTS || '')
|
||||
.split(',')
|
||||
.map(s => s.trim().toUpperCase())
|
||||
.filter(Boolean)
|
||||
);
|
||||
|
||||
const tenants = await query(client, `
|
||||
SELECT t.id, t.rfc, t.nombre, t.database_name,
|
||||
EXISTS (
|
||||
SELECT 1 FROM fiel_credentials fc
|
||||
WHERE fc.tenant_id = t.id AND fc.is_active = true AND fc.valid_until > NOW()
|
||||
) AS has_legacy_fiel
|
||||
FROM tenants t
|
||||
WHERE t.active = true
|
||||
ORDER BY t.rfc
|
||||
`);
|
||||
|
||||
const visibleTenants = tenants.filter(t => !excluded.has(t.id) && !excluded.has(t.rfc.toUpperCase()));
|
||||
|
||||
// Daily jobs de hoy
|
||||
const dailyJobs = await query(client, `
|
||||
SELECT tenant_id, contribuyente_id, cfdis_found, status, created_at
|
||||
FROM sat_sync_jobs
|
||||
WHERE type = 'daily'
|
||||
AND created_at >= $1
|
||||
AND created_at < $2
|
||||
`, [todayStart, todayEnd]);
|
||||
|
||||
const dailyByTenantContrib = new Map();
|
||||
for (const j of dailyJobs) {
|
||||
const key = j.contribuyente_id ? `${j.tenant_id}:${j.contribuyente_id}` : `${j.tenant_id}:`;
|
||||
dailyByTenantContrib.set(key, j);
|
||||
}
|
||||
|
||||
const hadDaily = [];
|
||||
const missing = [];
|
||||
const noFiel = [];
|
||||
|
||||
for (const t of visibleTenants) {
|
||||
if (!t.database_name) {
|
||||
// Legacy tenant-wide (sin contribuyentes)
|
||||
if (!t.has_legacy_fiel) {
|
||||
noFiel.push({ tenantRfc: t.rfc, tenantName: t.nombre });
|
||||
continue;
|
||||
}
|
||||
const key = `${t.id}:`;
|
||||
const job = dailyByTenantContrib.get(key);
|
||||
if (job) {
|
||||
hadDaily.push({ tenantRfc: t.rfc, tenantName: t.nombre, contribuyenteId: null, contribuyenteRfc: null, contribuyenteName: null, cfdisFound: job.cfdis_found, status: job.status });
|
||||
} else {
|
||||
missing.push({ tenantRfc: t.rfc, tenantName: t.nombre, contribuyenteId: null, contribuyenteRfc: null, contribuyenteName: null, reason: 'tenant legacy con FIEL pero sin daily' });
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Conectar a la BD del tenant
|
||||
const tenantClient = new Client({ ...HORUX_CONN, database: t.database_name });
|
||||
try {
|
||||
await tenantClient.connect();
|
||||
|
||||
// Todos los contribuyentes con info de FIEL (per-contribuyente o legacy)
|
||||
const contribuyentes = await query(tenantClient, `
|
||||
SELECT c.entidad_id, c.rfc, eg.nombre AS razon_social,
|
||||
EXISTS (
|
||||
SELECT 1 FROM fiel_contribuyente f
|
||||
WHERE f.contribuyente_id = c.entidad_id
|
||||
AND f.is_active = true AND f.valid_until > NOW()
|
||||
) AS has_fiel
|
||||
FROM contribuyentes c
|
||||
JOIN entidades_gestionadas eg ON eg.id = c.entidad_id
|
||||
ORDER BY eg.nombre
|
||||
`);
|
||||
|
||||
for (const c of contribuyentes) {
|
||||
const eligible = c.has_fiel || t.has_legacy_fiel;
|
||||
const key = `${t.id}:${c.entidad_id}`;
|
||||
const job = dailyByTenantContrib.get(key);
|
||||
|
||||
if (job) {
|
||||
hadDaily.push({ tenantRfc: t.rfc, tenantName: t.nombre, contribuyenteId: c.entidad_id, contribuyenteRfc: c.rfc, contribuyenteName: c.razon_social, cfdisFound: job.cfdis_found, status: job.status });
|
||||
} else if (eligible) {
|
||||
missing.push({ tenantRfc: t.rfc, tenantName: t.nombre, contribuyenteId: c.entidad_id, contribuyenteRfc: c.rfc, contribuyenteName: c.razon_social, reason: 'sin daily' });
|
||||
} else {
|
||||
noFiel.push({ tenantRfc: t.rfc, tenantName: t.nombre, contribuyenteId: c.entidad_id, contribuyenteRfc: c.rfc, contribuyenteName: c.razon_social });
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
missing.push({ tenantRfc: t.rfc, tenantName: t.nombre, contribuyenteId: null, contribuyenteRfc: null, contribuyenteName: null, reason: `error consultando BD: ${err.message}` });
|
||||
} finally {
|
||||
try { await tenantClient.end(); } catch {}
|
||||
}
|
||||
}
|
||||
|
||||
await client.end();
|
||||
|
||||
console.log('=== CONTRIBUYENTES/TENANTS CON DAILY HOY ===');
|
||||
console.log(`Total con daily: ${hadDaily.length}`);
|
||||
for (const h of hadDaily) {
|
||||
const name = h.contribuyenteName ? `${h.contribuyenteName} (${h.contribuyenteRfc})` : h.tenantName;
|
||||
console.log(`- ${h.tenantRfc}: ${name} | CFDIs: ${h.cfdisFound ?? 'N/A'} | status: ${h.status}`);
|
||||
}
|
||||
|
||||
console.log('\n=== CONTRIBUYENTES/TENANTS SIN DAILY HOY (con FIEL) ===');
|
||||
console.log(`Total sin daily: ${missing.length}`);
|
||||
for (const m of missing) {
|
||||
const name = m.contribuyenteName ? `${m.contribuyenteName} (${m.contribuyenteRfc})` : m.tenantName;
|
||||
console.log(`- ${m.tenantRfc}: ${name} [${m.reason}]`);
|
||||
}
|
||||
|
||||
console.log('\n=== CONTRIBUYENTES/TENANTS SIN FIEL CONFIGURADA ===');
|
||||
console.log(`Total sin FIEL: ${noFiel.length}`);
|
||||
for (const n of noFiel) {
|
||||
const name = n.contribuyenteName ? `${n.contribuyenteName} (${n.contribuyenteRfc})` : n.tenantName;
|
||||
console.log(`- ${n.tenantRfc}: ${name}`);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(err => { console.error(err); process.exit(1); });
|
||||
Reference in New Issue
Block a user