diff --git a/apps/api/src/controllers/alertas.controller.ts b/apps/api/src/controllers/alertas.controller.ts index 7b75db3..9a12826 100644 --- a/apps/api/src/controllers/alertas.controller.ts +++ b/apps/api/src/controllers/alertas.controller.ts @@ -125,7 +125,9 @@ export async function resolverAlertaManual(req: Request, res: Response, next: Ne export async function getAlertasAutomaticas(req: Request, res: Response, next: NextFunction) { try { const contribuyenteId = req.query.contribuyenteId as string | undefined; + console.log(`[AlertasCtrl] GET /automaticas tenant=${req.user!.tenantId} contribuyente=${contribuyenteId || 'null'} user=${req.user!.userId} role=${req.user!.role}`); const alertas = await generarAlertasAutomaticas(req.tenantPool!, req.user!.tenantId, contribuyenteId || null); + console.log(`[AlertasCtrl] GET /automaticas devuelve ${alertas.length} alertas: ${alertas.map(a => a.id).join(', ') || 'ninguna'}`); res.json(alertas); } catch (error) { next(error); diff --git a/apps/api/src/services/alertas-auto.service.ts b/apps/api/src/services/alertas-auto.service.ts index c01bf13..532e151 100644 --- a/apps/api/src/services/alertas-auto.service.ts +++ b/apps/api/src/services/alertas-auto.service.ts @@ -609,30 +609,46 @@ async function alertaOpinionCumplimiento(pool: Pool, contribuyenteId?: string | /** * Genera todas las alertas automáticas para un tenant. + * Cada alerta se envuelve en try/catch para que un fallo en una no + * bloquee el resto (robustez ante timeouts o errores transitorios). */ export async function generarAlertasAutomaticas( pool: Pool, tenantId: string, contribuyenteId?: string | null, ): Promise { - const alertas = await Promise.all([ - alertaListaNegraPropia(pool, tenantId, contribuyenteId), - alertaClienteListaNegra(pool, contribuyenteId), - alertaProveedorListaNegra(pool, contribuyenteId), - alertaDiscrepanciaRegimen(pool, tenantId, contribuyenteId), - alertaConcentracionClientes(pool, contribuyenteId), - alertaConcentracionProveedores(pool, contribuyenteId), - alertaRiesgoCambiario(pool, contribuyenteId), - alertaRiesgoCancelaciones(pool, contribuyenteId), - alertaRiesgoTransaccional(pool, contribuyenteId), - alertaCancelacionPeriodoAnterior(pool, contribuyenteId), - alertaOpinionCumplimiento(pool, contribuyenteId), - alertaTipoRelacionSospechosa(pool, contribuyenteId), - alertaTareasProximasVencer(pool, contribuyenteId), - alertaResicoPfLimiteIngresos(pool, contribuyenteId), - ]); + const generadores: { name: string; fn: () => Promise }[] = [ + { name: 'lista-negra-propia', fn: () => alertaListaNegraPropia(pool, tenantId, contribuyenteId) }, + { name: 'lista-negra-clientes', fn: () => alertaClienteListaNegra(pool, contribuyenteId) }, + { name: 'lista-negra-proveedores', fn: () => alertaProveedorListaNegra(pool, contribuyenteId) }, + { name: 'discrepancia-regimen', fn: () => alertaDiscrepanciaRegimen(pool, tenantId, contribuyenteId) }, + { name: 'concentracion-clientes', fn: () => alertaConcentracionClientes(pool, contribuyenteId) }, + { name: 'concentracion-proveedores', fn: () => alertaConcentracionProveedores(pool, contribuyenteId) }, + { name: 'riesgo-cambiario', fn: () => alertaRiesgoCambiario(pool, contribuyenteId) }, + { name: 'riesgo-cancelaciones', fn: () => alertaRiesgoCancelaciones(pool, contribuyenteId) }, + { name: 'riesgo-transaccional', fn: () => alertaRiesgoTransaccional(pool, contribuyenteId) }, + { name: 'cancelacion-periodo-anterior', fn: () => alertaCancelacionPeriodoAnterior(pool, contribuyenteId) }, + { name: 'opinion-cumplimiento', fn: () => alertaOpinionCumplimiento(pool, contribuyenteId) }, + { name: 'tipo-relacion-sospechosa', fn: () => alertaTipoRelacionSospechosa(pool, contribuyenteId) }, + { name: 'tareas-proximas-vencer', fn: () => alertaTareasProximasVencer(pool, contribuyenteId) }, + { name: 'resico-pf-limite-ingresos', fn: () => alertaResicoPfLimiteIngresos(pool, contribuyenteId) }, + ]; - return alertas.filter((a): a is AlertaAuto => a !== null); + const alertas: AlertaAuto[] = []; + for (const g of generadores) { + try { + const a = await g.fn(); + if (a) alertas.push(a); + } catch (err: any) { + console.error(`[AlertasAuto] Fallo ${g.name} (tenant=${tenantId}, contribuyente=${contribuyenteId}):`, err.message || err); + } + } + + if (alertas.length > 0) { + console.log(`[AlertasAuto] tenant=${tenantId} contribuyente=${contribuyenteId || 'null'} generadas=${alertas.map(a => a.id).join(', ')}`); + } + + return alertas; } /**