using System.Text.Json; using ComplianceDAL.CustomCode.ComplianceAlert; using ComplianceDAL.DTO.Analytics; using GB5Shared.DTO.Framework.Login; using GB5Shared.Resource.Response; using Microsoft.Extensions.Logging; namespace ComplianceBLL.ComplianceAlert; public class ComplianceAlertBLL( IComplianceAlertDAL dal, ILogger logger) : IComplianceAlertBLL { public async Task GetActiveAlertsAsync( string gstin, int page, int pageSize, LoginDTO login, CancellationToken ct) { var (items, total) = await dal.GetActiveAlertsAsync(gstin, page, pageSize, login, ct); return JsonSerializer.Serialize(new { Items = items, Total = total, Page = page, PageSize = pageSize }); } public async Task DismissAlertAsync(int alertId, LoginDTO login, CancellationToken ct) { await dal.DismissAlertAsync(alertId, login.UserId, login, ct); logger.LogInformation("Alert {AlertId} dismissed by user {UserId}", alertId, login.UserId); return JsonSerializer.Serialize(new { Message = SuccessResponse.UpdateSuccess }); } public async Task GetAlertConfigAsync(string gstin, LoginDTO login, CancellationToken ct) { var config = await dal.GetAlertConfigAsync(gstin, login, ct) ?? new AlertConfigDTO { GSTIN = gstin }; return JsonSerializer.Serialize(config); } public async Task SaveAlertConfigAsync(AlertConfigDTO dto, LoginDTO login, CancellationToken ct) { var id = await dal.UpsertAlertConfigAsync(dto, login, ct); logger.LogInformation("Alert config {Id} saved for GSTIN {GSTIN}", id, dto.GSTIN); return JsonSerializer.Serialize(new { AlertConfigId = id, Message = SuccessResponse.SaveSuccess }); } public async Task RunAlertCheckAsync(LoginDTO login, CancellationToken ct) { logger.LogInformation("Running compliance alert check for client {ClientId}", login.ClientId); await Task.WhenAll( CheckFilingDeadlinesAsync(login, ct), CheckEWBExpiriesAsync(login, ct), CheckMissingIRNsAsync(login, ct), CheckRejectedArtifactsAsync(login, ct) ); logger.LogInformation("Compliance alert check completed for client {ClientId}", login.ClientId); } private async Task CheckFilingDeadlinesAsync(LoginDTO login, CancellationToken ct) { var pending = await dal.GetPendingFilingGSTINsAsync(login, ct); foreach (var row in pending) { var alert = new ComplianceAlertDTO { AlertType = "FilingDeadline", GSTIN = (string)row.GSTIN, ReturnPeriod = $"{(int)row.PERIODMONTH:D2}{(int)row.PERIODYEAR}", AlertMessage = $"{(string)row.RETURNTYPE} filing deadline approaching for period {(int)row.PERIODMONTH:D2}/{(int)row.PERIODYEAR}", Severity = "Warning" }; await dal.UpsertAlertAsync(alert, login, ct); } logger.LogInformation("Filing deadline alerts processed: {Count}", pending.Count); } private async Task CheckEWBExpiriesAsync(LoginDTO login, CancellationToken ct) { var expiring = await dal.GetExpiringEWBsAsync(login, ct); foreach (var row in expiring) { var alert = new ComplianceAlertDTO { AlertType = "EWBExpiry", GSTIN = (string)row.GSTIN, AlertMessage = $"E-Way Bill {(string)row.EWAYBILLNUMBER} expires on {((DateTime)row.VALIDUPTO):dd-MMM-yyyy HH:mm}", Severity = "Critical" }; await dal.UpsertAlertAsync(alert, login, ct); } logger.LogInformation("EWB expiry alerts processed: {Count}", expiring.Count); } private async Task CheckMissingIRNsAsync(LoginDTO login, CancellationToken ct) { var missing = await dal.GetInvoicesWithoutIRNAsync(login, ct); foreach (var row in missing) { var alert = new ComplianceAlertDTO { AlertType = "IRNPending", GSTIN = (string)row.GSTIN, ReturnPeriod = (string)row.RETURNPERIOD, AlertMessage = $"Invoice {(string)row.INVOICENUMBER} dated {((DateTime)row.INVOICEDATE):dd-MMM-yyyy} has no IRN", Severity = "Warning" }; await dal.UpsertAlertAsync(alert, login, ct); } logger.LogInformation("Missing IRN alerts processed: {Count}", missing.Count); } private async Task CheckRejectedArtifactsAsync(LoginDTO login, CancellationToken ct) { var rejected = await dal.GetOldRejectedArtifactsAsync(login, ct); foreach (var row in rejected) { var alert = new ComplianceAlertDTO { AlertType = "SubmissionFailed", GSTIN = (string)row.GSTIN, ReturnPeriod = (string?)row.RETURNPERIOD, ArtifactId = (int)row.ARTIFACTID, AlertMessage = $"Compliance submission failed and remains in REJECTED state since {((DateTime)row.CREATEDON):dd-MMM-yyyy}", Severity = "Critical" }; await dal.UpsertAlertAsync(alert, login, ct); } logger.LogInformation("Submission failed alerts processed: {Count}", rejected.Count); } }