using System.Linq; using AccountsBLL.AccountReports.AccountBudgetVsComparison; using AccountsDAL.DTO.AccountsReports; using FastEndpoints; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.DTO.Report; using GB5Shared.FastEndPoint; namespace AccountsSL.EndPoints.AccountReports { // Budget vs Actual Comparison (Finance Dashboard Migration Phase 2) -- BudgetId/ComparisonType // read directly from CriteriaDTO, same "dedicated criteria field, not a bespoke request shape" // convention as AccountProfitLossDashboardReport's own DashboardPeriodType field. Small, bounded // result set (one row per budget line, or per OU for the rollup) -- ExecutePagedAsync overridden // to return the full list directly, same pattern as every other dashboard this session. public class AccountBudgetVsComparisonReport : BaseReportEndpoint { private readonly IAccountBudgetVsComparisonReportBLL _bll; public AccountBudgetVsComparisonReport(IAccountBudgetVsComparisonReportBLL bll) { _bll = bll; } public override void Configure() { Post("/AccountReports/AccountBudgetVsComparisonReport"); AllowAnonymous(); } public record AccountBudgetVsComparisonReportParameter( [property: FromHeader] string Login, [property: FromBody] ReportCallingDTO ReportCallingDTO ); // ViewLevel/OuAxis/AccountNature only matter for ComparisonType=1 (the pivot) -- see // AccountBudgetVsComparisonReportDAL's OuAxisMap/ViewLevelMap for what each value selects. // ViewLevel: 0=Account,2=AccountGroup,3=AccountScheduleNature,4=AccountGroupNature,9=Overall. // OuAxis (legacy "SubType"/"outype"): 0=OU,1=Company,2=Branch,3=Division,9=Overall. // AccountNature: 0=All,1=P&L (schedule nature not in Asset/Liability),2=BS (Asset/Liability only). private static (int BudgetId, byte ComparisonType, byte ViewLevel, byte OuAxis, byte AccountNature, List? OuIds, int OuGroupId) ParseParams(CriteriaDTO? criteriaDTO) { int budgetId = 0; byte comparisonType = 0; byte viewLevel = 0; byte ouAxis = 0; byte accountNature = 0; List? ouIds = null; int ouGroupId = -1; if (criteriaDTO?.SectionCriteriaList == null) return (budgetId, comparisonType, viewLevel, ouAxis, accountNature, ouIds, ouGroupId); foreach (var section in criteriaDTO.SectionCriteriaList) { if (section.AttributesCriteriaList == null) continue; foreach (var attr in section.AttributesCriteriaList) { var field = attr.FieldName?.ToLowerInvariant(); if (field == "budgetid" && int.TryParse(attr.FieldValue?.ToString(), out var bId)) budgetId = bId; else if (field == "comparisontype" && byte.TryParse(attr.FieldValue?.ToString(), out var cType)) comparisonType = cType; else if (field == "viewlevel" && byte.TryParse(attr.FieldValue?.ToString(), out var vLevel)) viewLevel = vLevel; else if (field == "ouaxis" && byte.TryParse(attr.FieldValue?.ToString(), out var oAxis)) ouAxis = oAxis; else if (field == "accountnature" && byte.TryParse(attr.FieldValue?.ToString(), out var aNature)) accountNature = aNature; else if (field == "ouid" && attr.FieldValue != null) ouIds = attr.FieldValue.ToString()?.Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(s => int.TryParse(s.Trim(), out var v) ? v : 0).Where(v => v != 0).ToList(); else if (field == "ougroupid" && int.TryParse(attr.FieldValue?.ToString(), out var gId)) ouGroupId = gId; } } return (budgetId, comparisonType, viewLevel, ouAxis, accountNature, ouIds, ouGroupId); } protected override async IAsyncEnumerable ExecuteReportAsync( AccountBudgetVsComparisonReportParameter req, LoginDTO login, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken ct) { var (budgetId, comparisonType, viewLevel, ouAxis, accountNature, ouIds, ouGroupId) = ParseParams(req.ReportCallingDTO.CriteriaDTO); var result = await _bll.GetBudgetVsComparisonReport(budgetId, comparisonType, viewLevel, ouAxis, accountNature, ouIds, ouGroupId, login, ct).ConfigureAwait(false); foreach (var row in result) { ct.ThrowIfCancellationRequested(); yield return row; } } protected override async Task> ExecutePagedAsync( AccountBudgetVsComparisonReportParameter req, LoginDTO login, CancellationToken ct) { try { var (budgetId, comparisonType, viewLevel, ouAxis, accountNature, ouIds, ouGroupId) = ParseParams(req.ReportCallingDTO.CriteriaDTO); var result = await _bll.GetBudgetVsComparisonReport(budgetId, comparisonType, viewLevel, ouAxis, accountNature, ouIds, ouGroupId, login, ct).ConfigureAwait(false); return await GB5Shared.ResponseStandard.Response.CreateSuccessResponse( result, GB5Shared.GB5Constant.Constant.CacheKeyLevel.NOT_REQUIRED, login); } catch (Exception ex) { return await GB5Shared.ResponseStandard.Response.CreateExceptionError( ex, GB5Shared.GB5Constant.Constant.CacheKeyLevel.NOT_REQUIRED, login, ex.Message, 500); } } } }