using MediatR; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using TakeoutSaaS.Application.App.Subscriptions.Commands; using TakeoutSaaS.Domain.Tenants.Repositories; using TakeoutSaaS.Module.Scheduler.Options; using TakeoutSaaS.Shared.Abstractions.Tenancy; namespace TakeoutSaaS.Module.Scheduler.Jobs; /// /// 订阅续费提醒任务:到期前 7/3/1 天发送站内提醒。 /// public sealed class SubscriptionRenewalReminderJob( IMediator mediator, ITenantRepository tenantRepository, ITenantContextAccessor tenantContextAccessor, IOptionsMonitor optionsMonitor, ILogger logger) { /// /// 执行续费提醒扫描与发送。 /// public async Task ExecuteAsync() { // 1. 读取配置 var options = optionsMonitor.CurrentValue; // 2. (空行后) 获取需要处理的租户列表(排除系统租户) var tenants = await tenantRepository.SearchAsync(null, null, CancellationToken.None); var targets = tenants.Where(x => x.Id > 0).ToList(); // 3. (空行后) 按租户逐个执行续费提醒 var candidateCount = 0; var createdReminderCount = 0; var previousContext = tenantContextAccessor.Current; try { foreach (var tenant in targets) { tenantContextAccessor.Current = new TenantContext(tenant.Id, tenant.Code, "scheduler"); try { var result = await mediator.Send(new ProcessRenewalRemindersCommand { ReminderDaysBeforeExpiry = options.ReminderDaysBeforeExpiry }); candidateCount += result.CandidateCount; createdReminderCount += result.CreatedReminderCount; } catch (Exception ex) { logger.LogError(ex, "定时任务:续费提醒执行失败 TenantId={TenantId}", tenant.Id); } } } finally { tenantContextAccessor.Current = previousContext; } // 4. (空行后) 记录执行结果 logger.LogInformation( "定时任务:续费提醒处理完成,处理租户 {TenantCount},候选 {CandidateCount},创建 {CreatedReminderCount}", targets.Count, candidateCount, createdReminderCount); } }