using AccountsBLL.AccountReports; using AccountsBLL.AccountReports.AccountRegister; using AccountsDAL.CustomCode.AccountReports.Register; using AccountsDAL.DTO.AccountsReports; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.Telemetry; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading.Tasks; namespace AccountsBLL.AccountReports.AccountRegister { public class AccountRegisterReportBLL : IAccountRegisterReportBLL { private const int DEFAULT_MAX_RESULT_CAP = 500; private readonly IAccountRegisterReportDAL _accountRegisterReportDAL; private readonly IAccountReportAccessControlBLL _accessControlBLL; public AccountRegisterReportBLL( IAccountRegisterReportDAL accountRegisterReportDAL, IAccountReportAccessControlBLL accessControlBLL) { _accountRegisterReportDAL = accountRegisterReportDAL; _accessControlBLL = accessControlBLL; } // UI paged result public async TaskGetAccountRegisterDetailReport(int firstNumber,int maxResult,CriteriaDTO criteriaDTO,List sortBy,int menuId,LoginDTO loginDTO,CancellationToken ct = default) { try { GB5Trace.Step("parse-criteria-account-register-detail", new { firstNumber, maxResult, menuId }); var criteria = AccountReportCriteriaParser.Parse(criteriaDTO, loginDTO); // Voucher Register Detail always shows Instrument/TDS/Bill Allocation for each line // when that line has one — no caller opt-in needed for these 3. This overrides // whatever the parser produced from caller input; it's scoped to THIS report's own // criteria instance only, not a change to AccountReportCriteria's own defaults (which // would also silently affect AccountLedgerReportBLL). CostCenter/Addon stay // caller-opt-in, unchanged. criteria.NeedBillAllocation = 1; criteria.NeedInstrument = 1; criteria.NeedTDS = 1; int cappedMaxResult = maxResult > 0? Math.Min(maxResult,DEFAULT_MAX_RESULT_CAP): DEFAULT_MAX_RESULT_CAP; await _accessControlBLL.EnforceAsync(criteria,cappedMaxResult,menuId,loginDTO).ConfigureAwait(false); GB5Trace.Step("query-account-register-detail", new { firstNumber, cappedMaxResult }); return await _accountRegisterReportDAL.GetAccountRegisterDetailReport(firstNumber,cappedMaxResult,criteria,sortBy,loginDTO,ct).ConfigureAwait(false); } catch (Exception ex) { GB5Trace.MarkFailed("account-register-detail-failed",ex); throw; } } // Report streaming result public async IAsyncEnumerableGetAccountRegisterDetailReportStream(int firstNumber,int maxResult,CriteriaDTO criteriaDTO,List sortBy,int menuId,LoginDTO loginDTO, [EnumeratorCancellation] CancellationToken ct = default) { GB5Trace.Step("stream-account-register-detail", new { firstNumber, maxResult, menuId }); var criteria = AccountReportCriteriaParser.Parse(criteriaDTO, loginDTO); // Same always-on override as the paged method above — keep both in sync. criteria.NeedBillAllocation = 1; criteria.NeedInstrument = 1; criteria.NeedTDS = 1; int cappedMaxResult = maxResult > 0 ? Math.Min( maxResult, DEFAULT_MAX_RESULT_CAP) : DEFAULT_MAX_RESULT_CAP; await _accessControlBLL.EnforceAsync(criteria,cappedMaxResult,menuId,loginDTO).ConfigureAwait(false); await foreach (var row in _accountRegisterReportDAL.GetAccountRegisterDetailReportStream(firstNumber,cappedMaxResult,criteria,sortBy,loginDTO,ct).ConfigureAwait(false)) { yield return row; } } } }