diff --git a/apps/api/src/jobs/sat-sync.job.ts b/apps/api/src/jobs/sat-sync.job.ts index 0a9bfac..8c27178 100644 --- a/apps/api/src/jobs/sat-sync.job.ts +++ b/apps/api/src/jobs/sat-sync.job.ts @@ -58,18 +58,66 @@ async function needsInitialSync(tenantId: string): Promise { } /** - * 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 { 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';