package services import ( "log" "github.com/robfig/cron/v3" "github.com/sujit-baniya/fiber-boilerplate/pkg/models" ) var cronScheduler *cron.Cron // IniciarCron arranca el scheduler de tareas. Llamar desde app.go o main.go. func IniciarCron() { cronScheduler = cron.New() // Ejecutar todos los días a las 8:00 AM _, err := cronScheduler.AddFunc("0 8 * * *", ProcesarVencimientos) if err != nil { log.Printf("[CRON] Error registrando tarea: %v", err) return } cronScheduler.Start() log.Println("[CRON] Scheduler iniciado — verificando vencimientos diariamente a las 8:00 AM") } // DetenerCron para graceful shutdown func DetenerCron() { if cronScheduler != nil { cronScheduler.Stop() } } // ProcesarVencimientos es la función principal del cron func ProcesarVencimientos() { log.Println("[CRON] Iniciando procesamiento de vencimientos...") reglas, err := models.GetReglasActivas() if err != nil { log.Printf("[CRON] Error obteniendo reglas: %v", err) return } for _, regla := range reglas { contratos, err := models.GetContratosProximosVencer(regla.DiasAntes) if err != nil { log.Printf("[CRON] Error obteniendo contratos para regla %d: %v", regla.ID, err) continue } if len(contratos) == 0 { continue } // Filtrar por AplicaA var filtrados []models.Contrato for _, c := range contratos { switch regla.AplicaA { case "renovable": if c.Servicio.Tipo == "renovable" { filtrados = append(filtrados, c) } case "unico": if c.Servicio.Tipo == "unico" { filtrados = append(filtrados, c) } default: filtrados = append(filtrados, c) } } if len(filtrados) == 0 { continue } // Agrupar contratos por cliente porCliente := make(map[uint][]models.Contrato) for _, c := range filtrados { porCliente[c.ClienteID] = append(porCliente[c.ClienteID], c) } for clienteID, grupoContratos := range porCliente { // Evitar duplicados: ya enviado hoy para esta regla + cliente if models.YaEnviadoHoy(clienteID, regla.ID) { log.Printf("[CRON] Ya enviado hoy a cliente %d para regla %d — saltando", clienteID, regla.ID) continue } cliente := &grupoContratos[0].Cliente if err := EnviarNotificacionGrupo(®la, cliente, grupoContratos); err != nil { log.Printf("[CRON] Error enviando a cliente %d: %v", clienteID, err) } else { log.Printf("[CRON] Enviado a cliente %d (%s) — %d contrato(s)", clienteID, cliente.Email, len(grupoContratos)) } } } log.Println("[CRON] Procesamiento de vencimientos finalizado") }