using FLSDAL.CustomCode.Bridge; using FLSDAL.CustomCode.Instance; using FLSDAL.CustomCode.Respondent; using FLSDAL.DTO.Respondent; using GB5Shared.DTO.Framework.Login; using GB5Shared.Telemetry; using Microsoft.Extensions.Logging; namespace FLSBLL.Dispatch; public class FlsDispatchBLL : IFlsDispatchBLL { private readonly IFlsRespondentDAL _respondentDal; private readonly IFlsBridgeDAL _bridgeDal; private readonly IFlsInstanceDAL _instanceDal; private readonly ILogger _logger; public FlsDispatchBLL( IFlsRespondentDAL respondentDal, IFlsBridgeDAL bridgeDal, IFlsInstanceDAL instanceDal, ILogger logger) { _respondentDal = respondentDal; _bridgeDal = bridgeDal; _instanceDal = instanceDal; _logger = logger; } public async Task DispatchInitialAsync(int flsInstanceId, int groupId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("dispatch-fls-initial", new { flsInstanceId, groupId }); // Get NOT_STARTED respondents only (status=0) var respondents = await _respondentDal.GetByInstanceAsync( flsInstanceId, groupId, statusFilter: 0, pageNo: 1, pageSize: 5000, login, ct).ConfigureAwait(false); var instance = await _instanceDal.GetByIdAsync(flsInstanceId, login, ct).ConfigureAwait(false); if (instance is null) return; foreach (var r in respondents) { if (r.DeliveryStatus != 0) // skip already dispatched continue; await DispatchToRespondentAsync(r, instance.DefaultEipTemplCode, login, ct) .ConfigureAwait(false); } } catch (Exception ex) { GB5Trace.MarkFailed("dispatch-fls-initial-failed", ex); _logger.LogError(ex, "DispatchInitial failed for instance {Id} group {GroupId}", flsInstanceId, groupId); throw; } } public async Task DispatchNudgeAsync(int flsRespondentId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("dispatch-fls-nudge", new { flsRespondentId }); var respondent = await _respondentDal.GetByIdAsync(flsRespondentId, login, ct).ConfigureAwait(false); if (respondent is null) return; await _bridgeDal.LogDispatchAsync( respondent.FlsInstanceId, respondent.GroupId, respondent.FlsRespondentId, dispatchType: 2, // Nudge channel: 0, // Email by default eipTemplCode: null, eipCommandRef: null, recipientMail: respondent.RespondentMail, deliveryStatus: 0, // Pending login, ct).ConfigureAwait(false); _logger.LogInformation("Nudge dispatched for respondent {RespondentId}", flsRespondentId); } catch (Exception ex) { GB5Trace.MarkFailed("dispatch-fls-nudge-failed", ex); _logger.LogError(ex, "DispatchNudge failed for respondent {Id}", flsRespondentId); throw; } } public async Task DispatchReminderAsync(int flsInstanceId, int groupId, string eipTemplCode, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("dispatch-fls-reminder", new { flsInstanceId, groupId, eipTemplCode }); // Dispatch to all IN_PROGRESS (status=1,2) respondents who haven't submitted var respondents = await _respondentDal.GetByInstanceAsync( flsInstanceId, groupId, statusFilter: null, pageNo: 1, pageSize: 5000, login, ct).ConfigureAwait(false); foreach (var r in respondents.Where(r => r.RespondentSts is 1 or 2)) { await _bridgeDal.LogDispatchAsync( flsInstanceId, groupId, r.FlsRespondentId, dispatchType: 1, // Reminder channel: 0, eipTemplCode: eipTemplCode, eipCommandRef: null, recipientMail: r.RespondentMail, deliveryStatus: 0, login, ct).ConfigureAwait(false); } } catch (Exception ex) { GB5Trace.MarkFailed("dispatch-fls-reminder-failed", ex); _logger.LogError(ex, "DispatchReminder failed for instance {Id}", flsInstanceId); throw; } } private async Task DispatchToRespondentAsync( FlsRespondentRow respondent, string? defaultEipTemplCode, LoginDTO login, CancellationToken ct) { await _bridgeDal.LogDispatchAsync( respondent.FlsInstanceId, respondent.GroupId, respondent.FlsRespondentId, dispatchType: 0, // Initial channel: 0, eipTemplCode: defaultEipTemplCode, eipCommandRef: null, recipientMail: respondent.RespondentMail, deliveryStatus: 0, login, ct).ConfigureAwait(false); } }