using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using AccountsDAL.DTO.AccountsReports; using AccountsDAL.Query.AccountReports; using Dapper; using GB5Shared.DTO.Framework.Login; using GB5Shared.QueryExecutor; namespace AccountsDAL.CustomCode.AccountReports.AccountVoucherReport { public class AccountVoucherReportDAL : IAccountVoucherReportDAL { private readonly IQueryExecutor _queryExecutor; public AccountVoucherReportDAL(IQueryExecutor queryExecutor) { _queryExecutor = queryExecutor; } // Build()'s DynamicParameters aren't safe to blindly merge with BuildVoucherHeaderOnly's own // (both may add the same key -- e.g. InformationalClassId -- since Build() adds a filter's // parameter even when its filter TEXT is discarded) -- caught live via HTTP 400 "An item // with the same key has already been added." Header-scoped reports (Status/List-Class/ // PeriodType) get their date/user params directly instead of going through Build() at all. private static DynamicParameters BuildHeaderParameters(AccountReportCriteria criteria, LoginDTO loginDTO) { var p = new DynamicParameters(); p.Add("UserId", loginDTO.UserId); p.Add("PeriodFromDate", criteria.PeriodFromDate); p.Add("PeriodToDate", criteria.PeriodToDate); return p; } public async Task GetVoucherStatusReport( int firstNumber, int maxResult, AccountReportCriteria criteria, LoginDTO loginDTO, CancellationToken ct) { var parameters = BuildHeaderParameters(criteria, loginDTO); var (filter, headerParams) = AccountReportFilterBuilder.BuildVoucherHeaderOnly(criteria, hasAccountAlias: false); parameters.AddDynamicParams(headerParams); parameters.Add("Offset", System.Math.Max(0, firstNumber - 1)); parameters.Add("PageSize", maxResult); var sql = VoucherReportQB.GET_VOUCHER_STATUS_REPORT.Replace("{DynamicFilter}", filter); var paged = await _queryExecutor .QueryPagedAsync(loginDTO, sql, parameters) .ConfigureAwait(false); var totalsSql = VoucherReportQB.GET_VOUCHER_STATUS_REPORT_TOTALS.Replace("{DynamicFilter}", filter); var totals = await _queryExecutor .QuerySingleAsync(loginDTO, totalsSql, parameters, cancellationToken: ct) .ConfigureAwait(false); return new VoucherStatusReportResultDTO { Items = paged.Items ?? Enumerable.Empty(), TotalCount = paged.TotalCount, Totals = totals ?? new VoucherStatusReportTotalsDTO() }; } public async Task GetVoucherSummaryReport( int firstNumber, int maxResult, int groupType, AccountReportCriteria criteria, LoginDTO loginDTO, CancellationToken ct) { var (filter, parameters) = AccountReportFilterBuilder.Build(criteria, loginDTO); parameters.Add("Offset", System.Math.Max(0, firstNumber - 1)); parameters.Add("PageSize", maxResult); var (groupBySelect, groupByColumns) = VoucherSummaryGroupByBuilder.Build(groupType); var sql = VoucherReportQB.GET_VOUCHER_SUMMARY_REPORT .Replace("{GroupBySelect}", groupBySelect) .Replace("{GroupByColumns}", groupByColumns) .Replace("{DynamicFilter}", filter); var paged = await _queryExecutor .QueryPagedAsync(loginDTO, sql, parameters) .ConfigureAwait(false); var totalsSql = VoucherReportQB.GET_VOUCHER_SUMMARY_REPORT_TOTALS.Replace("{DynamicFilter}", filter); var totals = await _queryExecutor .QuerySingleAsync(loginDTO, totalsSql, parameters, cancellationToken: ct) .ConfigureAwait(false); return new VoucherSummaryReportResultDTO { Items = paged.Items ?? Enumerable.Empty(), TotalCount = paged.TotalCount, TotalActiveNumber = totals?.TotalActiveNumber ?? 0, TotalUnApprovedNumber = totals?.TotalUnApprovedNumber ?? 0, TotalDebit = totals?.TotalDebit ?? 0, TotalCredit = totals?.TotalCredit ?? 0 }; } public async Task GetVoucherListClassReport( int firstNumber, int maxResult, AccountReportCriteria criteria, LoginDTO loginDTO, CancellationToken ct) { var parameters = BuildHeaderParameters(criteria, loginDTO); var (filter, headerParams) = AccountReportFilterBuilder.BuildVoucherHeaderOnly(criteria, hasAccountAlias: true); parameters.AddDynamicParams(headerParams); parameters.Add("Offset", System.Math.Max(0, firstNumber - 1)); parameters.Add("PageSize", maxResult); var sql = VoucherReportQB.GET_VOUCHER_LIST_CLASS.Replace("{DynamicFilter}", filter); var paged = await _queryExecutor .QueryPagedAsync(loginDTO, sql, parameters) .ConfigureAwait(false); return new VoucherListClassReportResultDTO { Items = paged.Items ?? Enumerable.Empty(), TotalCount = paged.TotalCount }; } public async Task GetVoucherListAccountReport( int firstNumber, int maxResult, AccountReportCriteria criteria, LoginDTO loginDTO, CancellationToken ct) { var (filter, parameters) = AccountReportFilterBuilder.Build(criteria, loginDTO); parameters.Add("Offset", System.Math.Max(0, firstNumber - 1)); parameters.Add("PageSize", maxResult); var sql = VoucherReportQB.GET_VOUCHER_LIST_ACCOUNT.Replace("{DynamicFilter}", filter); var paged = await _queryExecutor .QueryPagedAsync(loginDTO, sql, parameters) .ConfigureAwait(false); return new VoucherListAccountReportResultDTO { Items = paged.Items ?? Enumerable.Empty(), TotalCount = paged.TotalCount }; } public async Task> GetVoucherPeriodTypeReport( AccountReportCriteria criteria, LoginDTO loginDTO, CancellationToken ct) { var parameters = BuildHeaderParameters(criteria, loginDTO); var (filter, headerParams) = AccountReportFilterBuilder.BuildVoucherHeaderOnly(criteria, hasAccountAlias: false); parameters.AddDynamicParams(headerParams); parameters.Add("PeriodType", criteria.PeriodType); var sql = VoucherReportQB.GET_VOUCHER_PERIODTYPE_REPORT.Replace("{DynamicFilter}", filter); var rows = await _queryExecutor .QueryAsync(loginDTO, sql, parameters, cancellationToken: ct) .ConfigureAwait(false); return rows.ToList(); } } }