using GB5Shared.DTO.Framework.Login; using GoodBooks.PAY.PAYBLL.Cashback; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace GoodBooks.PAY.PAYSL.Services { // ───────────────────────────────────────────────────────────────────────── // CashbackPayoutJob // // .NET 9 BackgroundService using PeriodicTimer. // Polls TCASHBACKLEDGER every N minutes (default 15) for pending payouts. // Delegates to ICashbackLedgerBLL.ProcessPendingPayoutsAsync which handles: // Mode 1 — CreditNote: IFinanceIntegrationService.PostCreditNoteAsync // Mode 2 — GatewayPayout: NotImplementedException (Phase 2) // Mode 3 — Wallet: NotImplementedException (Phase 2) // Mode 4 — LoyaltyPoints: ICustomerLoyaltyBLL.EarnPointsAsync // ───────────────────────────────────────────────────────────────────────── public sealed class CashbackPayoutJob : BackgroundService { private readonly IServiceScopeFactory _scopeFactory; private readonly IConfiguration _config; private readonly ILogger _logger; public CashbackPayoutJob( IServiceScopeFactory scopeFactory, IConfiguration config, ILogger logger) { _scopeFactory = scopeFactory; _config = config; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { int intervalMins = _config.GetValue("PayJobs:CashbackPayoutIntervalMinutes", 15); _logger.LogInformation( "CashbackPayoutJob starting — interval {IntervalMins}m", intervalMins); using var timer = new PeriodicTimer(TimeSpan.FromMinutes(intervalMins)); while (await timer.WaitForNextTickAsync(stoppingToken)) { _logger.LogInformation("CashbackPayoutJob tick at {UtcNow:u}", DateTime.UtcNow); try { using var scope = _scopeFactory.CreateScope(); var bll = scope.ServiceProvider.GetRequiredService(); var systemLogin = BuildSystemLogin(); await bll.ProcessPendingPayoutsAsync(systemLogin, stoppingToken).ConfigureAwait(false); _logger.LogInformation("CashbackPayoutJob cycle completed at {UtcNow:u}", DateTime.UtcNow); } catch (Exception ex) when (ex is not OperationCanceledException) { _logger.LogError(ex, "CashbackPayoutJob cycle failed."); // Continue — next tick will retry } } } private LoginDTO BuildSystemLogin() => new() { ClientId = _config.GetValue("PayJobs:SystemTenantId", -1), DatabaseName = _config["PayJobs:SystemDatabaseName"] ?? "GoodBooks_Main", UserId = -1 }; } }