using Microsoft.EntityFrameworkCore; using vendorApproverBackend.Data; using vendorApproverBackend.Entities; using vendorApproverBackend.Enums; using vendorApproverBackend.Interfaces; public class AuditDeadlineJob : CronJobService { private readonly IServiceProvider _serviceProvider; private const string CronSchedule = "0 0 * * *"; // Every midnight public AuditDeadlineJob(IServiceProvider serviceProvider) : base(CronSchedule, TimeZoneInfo.Utc) { _serviceProvider = serviceProvider; } protected override async Task ExecuteAsync(CancellationToken cancellationToken) { using (var scope = _serviceProvider.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService(); var emailService = scope.ServiceProvider.GetRequiredService(); var logger = scope.ServiceProvider.GetRequiredService>(); // Logic: If deadline is 30 days, and 7 days are left, // we are looking for requests assigned exactly 23 days ago. var targetDate = DateTime.UtcNow.Date.AddDays(-23); var pendingAudits = await context.PrequalificationRequests .Include(p => p.AssignedTo) // The Auditor .Where(p => p.Status == RequestStatus.UNDER_REVIEW) .Where(p => p.AssignmentDate != null && p.AssignmentDate.Value.Date == targetDate) .ToListAsync(cancellationToken); foreach (var request in pendingAudits) { if (request.AssignedTo != null && !string.IsNullOrEmpty(request.AssignedTo.Email)) { try { await emailService.SendAuditDeadlineReminderAsync( request.AssignedTo.Email, request.AssignedTo, request, 7); logger.LogInformation("Deadline reminder sent to {Email} for PQ {Id}", request.AssignedTo.Email, request.Id); } catch (Exception ex) { logger.LogError(ex, "Error sending reminder for PQ {Id}", request.Id); } } } } } }