feat(sat-sync): iterate contribuyentes for despacho tenants in daily sync

syncTenant now handles despacho mode by:
1. Querying fiel_contribuyente for active FIELs in the tenant DB
2. Running startSync per-contribuyente with contribuyenteId
3. Keeping legacy mode (tenant-wide sync) for Horux 360 tenants
This commit is contained in:
Horux Dev
2026-04-30 04:20:36 +00:00
parent 67cf2ae6fe
commit dd8484a800

View File

@@ -58,18 +58,66 @@ async function needsInitialSync(tenantId: string): Promise<boolean> {
}
/**
* Ejecuta sincronización para un tenant
* Ejecuta sincronización para un tenant.
* Para despachos, itera cada contribuyente con FIEL activa.
* Para legacy (Horux 360), sync a nivel de tenant.
*/
async function syncTenant(tenantId: string): Promise<void> {
try {
// Verificar si hay sync activo
const tenant = await prisma.tenant.findUnique({
where: { id: tenantId },
select: { rfc: true, databaseName: true },
});
if (!tenant) {
console.log(`[SAT Cron] Tenant ${tenantId} no encontrado, omitiendo`);
return;
}
const isDespacho = isDespachoTenant(tenant.rfc);
if (isDespacho) {
// Modo despacho: iterar contribuyentes con FIEL
const pool = await tenantDb.getPool(tenantId, tenant.databaseName);
const { rows: contribuyentes } = await pool.query(`
SELECT c.entidad_id as id, c.rfc
FROM contribuyentes c
JOIN fiel_contribuyente f ON f.contribuyente_id = c.entidad_id
WHERE f.is_active = true AND f.valid_until > NOW()
`);
if (contribuyentes.length === 0) {
console.log(`[SAT Cron] Tenant ${tenantId} (despacho) sin contribuyentes con FIEL, omitiendo`);
return;
}
for (const contrib of contribuyentes) {
try {
const status = await getSyncStatus(tenantId);
if (status.hasActiveSync) {
console.log(`[SAT Cron] Tenant ${tenantId} ya tiene sync activo, omitiendo contribuyente ${contrib.rfc}`);
continue;
}
const needsInitial = await needsInitialSync(tenantId);
const syncType = needsInitial ? 'initial' : 'daily';
console.log(`[SAT Cron] Iniciando sync ${syncType} para contribuyente ${contrib.rfc} (tenant ${tenantId})`);
const jobId = await startSync(tenantId, syncType, undefined, undefined, contrib.id);
console.log(`[SAT Cron] Job ${jobId} iniciado para contribuyente ${contrib.rfc}`);
} catch (error: any) {
console.error(`[SAT Cron] Error sincronizando contribuyente ${contrib.rfc} (tenant ${tenantId}):`, error.message);
}
}
return;
}
// Modo legacy (Horux 360)
const status = await getSyncStatus(tenantId);
if (status.hasActiveSync) {
console.log(`[SAT Cron] Tenant ${tenantId} ya tiene sync activo, omitiendo`);
return;
}
// Determinar tipo de sync
const needsInitial = await needsInitialSync(tenantId);
const syncType = needsInitial ? 'initial' : 'daily';