using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text.Json; using AccountsDAL.DTO.AccountsReports; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.GB5CommonFunction; namespace AccountsBLL.AccountReports { // Shared CriteriaDTO -> AccountReportCriteria parsing for the AccountRegister/AccountRegisterSummary // reports (and future voucher-register-style reports in this family), replacing the copy of this // switch statement that would otherwise be duplicated per report. public static class AccountReportCriteriaParser { public static AccountReportCriteria Parse(CriteriaDTO criteriaDTO, LoginDTO loginDTO) { var result = new AccountReportCriteria { FinanceBookId = loginDTO.WorkFinanceBookId, PeriodFromDate = DateTime.MinValue, PeriodToDate = DateTime.MinValue, AsOnDate = DateTime.UtcNow.Date }; if (criteriaDTO?.SectionCriteriaList == null) return result; var fn = new GB5CommonFunction(); foreach (var section in criteriaDTO.SectionCriteriaList) { if (section?.AttributesCriteriaList == null) continue; foreach (var attr in section.AttributesCriteriaList) { if (attr.FieldValue == null) continue; var field = attr.FieldName?.ToLowerInvariant() ?? string.Empty; switch (field) { case "periodfromdate": result.PeriodFromDate = ParseEpochToDate(attr.FieldValue, fn); break; case "periodtodate": result.PeriodToDate = ParseEpochToDate(attr.FieldValue, fn); break; case "voucherdetailaccountid": result.VoucherDetailAccountIds = ParseIntList(attr.FieldValue); break; case "ouid": result.OUIds = ParseIntList(attr.FieldValue); break; case "ougroupid": result.OUGroupId = ParseInt(attr.FieldValue); break; case "biztransactiontypeid": result.BizTransactionTypeId = ParseInt(attr.FieldValue); break; case "biztransactionclassid": result.BizTransactionClassId = ParseInt(attr.FieldValue); break; case "biztransactionsubclassid": result.BizTransactionSubClassId = ParseInt(attr.FieldValue); break; case "detailtype": result.DetailType = ParseInt(attr.FieldValue); break; case "costcenterid": result.CostCenterId = ParseInt(attr.FieldValue); break; case "includeinformational": result.IncludeInformational = ParseBool(attr.FieldValue); break; case "needbillallocation": result.NeedBillAllocation = ParseInt(attr.FieldValue); break; case "needcostcenter": result.NeedCostCenter = ParseInt(attr.FieldValue); break; case "needinstrument": result.NeedInstrument = ParseInt(attr.FieldValue); break; case "needaddon": result.NeedAddon = ParseInt(attr.FieldValue); break; case "needtds": result.NeedTDS = ParseInt(attr.FieldValue); break; case "financebookid": var fbId = ParseInt(attr.FieldValue); if (fbId > 0) result.FinanceBookId = fbId; break; case "currencyid": result.CurrencyId = ParseInt(attr.FieldValue); break; case "periodid": result.PeriodId = ParseInt(attr.FieldValue); break; case "fromdocumentnumber": result.FromDocumentNumber = RawString(attr.FieldValue); break; case "todocumentnumber": result.ToDocumentNumber = RawString(attr.FieldValue); break; case "fromdocumentid": result.FromDocumentId = ParseInt(attr.FieldValue); break; case "todocumentid": result.ToDocumentId = ParseInt(attr.FieldValue); break; case "fromamount": result.FromAmount = ParseDecimal(attr.FieldValue); break; case "toamount": result.ToAmount = ParseDecimal(attr.FieldValue); break; case "v1": result.V1Id = ParseInt(attr.FieldValue); break; case "v2": result.V2Id = ParseInt(attr.FieldValue); break; case "v3": result.V3Id = ParseInt(attr.FieldValue); break; case "v4": result.V4Id = ParseInt(attr.FieldValue); break; case "v5": result.V5Id = ParseInt(attr.FieldValue); break; case "voucherstatus": result.VoucherStatus = ParseInt(attr.FieldValue); break; case "billtype": case "modeofpayment": result.ModeOfPayment = ParseIntList(attr.FieldValue); break; case "controlaccountid": result.ControlAccountId = ParseInt(attr.FieldValue); break; case "accountgroupid": result.AccountGroupId = ParseInt(attr.FieldValue); break; case "currencybasis": result.CurrencyBasis = ParseInt(attr.FieldValue); break; case "reportcurrencyid": result.ReportCurrencyId = ParseInt(attr.FieldValue); break; case "asondate": result.AsOnDate = ParseEpochToDate(attr.FieldValue, fn); break; case "grouptype": result.GroupType = ParseInt(attr.FieldValue); break; case "overdue": result.Overdue = ParseInt(attr.FieldValue); break; case "outstandingreporttype": result.ReportType = ParseInt(attr.FieldValue); break; case "outstandingreportmode": result.OutstandingReportMode = ParseInt(attr.FieldValue); break; case "inchargeid": result.InChargeId = ParseInt(attr.FieldValue); break; case "pricecategoryid": result.PriceCategoryId = ParseInt(attr.FieldValue); break; case "routeid": result.RouteId = ParseInt(attr.FieldValue); break; case "numberofage": var n = ParseInt(attr.FieldValue); if (n >= 1 && n <= 9) result.NumberOfAge = n; break; case "age1": result.AgeBoundaries[0] = ParseInt(attr.FieldValue); break; case "age2": result.AgeBoundaries[1] = ParseInt(attr.FieldValue); break; case "age3": result.AgeBoundaries[2] = ParseInt(attr.FieldValue); break; case "age4": result.AgeBoundaries[3] = ParseInt(attr.FieldValue); break; case "age5": result.AgeBoundaries[4] = ParseInt(attr.FieldValue); break; case "age6": result.AgeBoundaries[5] = ParseInt(attr.FieldValue); break; case "age7": result.AgeBoundaries[6] = ParseInt(attr.FieldValue); break; case "age8": result.AgeBoundaries[7] = ParseInt(attr.FieldValue); break; case "age9": result.AgeBoundaries[8] = ParseInt(attr.FieldValue); break; case "billallocationid": case "billallocationlineid": result.BillAllocationLineId = ParseInt(attr.FieldValue); break; case "overalldays": var od = ParseInt(attr.FieldValue); if (od > 0) result.OverallDays = od; break; case "periodtype": result.PeriodType = (byte)ParseInt(attr.FieldValue); break; case "comparativeaxis": result.ComparativeAxis = (byte)ParseInt(attr.FieldValue); break; case "naturecolumntype": result.NatureColumnType = (byte)ParseInt(attr.FieldValue); break; case "naturevalues": result.NatureValues = ParseIntList(attr.FieldValue); break; } } } return result; } private static DateTime ParseEpochToDate(object fieldValue, IGB5CommonFunction fn) { var raw = RawString(fieldValue); if (long.TryParse(raw, out var epoch)) return fn.FromEpoch(epoch).GetAwaiter().GetResult(); if (DateTime.TryParse(raw, null, DateTimeStyles.None, out var dt)) return dt; throw new FormatException($"Cannot parse '{raw}' as a date or epoch timestamp."); } private static List ParseIntList(object fieldValue) { var raw = RawString(fieldValue); if (string.IsNullOrWhiteSpace(raw)) return new List(); return raw.Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(s => int.TryParse(s.Trim(), out var v) ? v : 0) .Where(v => v != 0) .ToList(); } private static int ParseInt(object fieldValue) { var raw = RawString(fieldValue); return int.TryParse(raw, out var v) ? v : 0; } private static bool ParseBool(object fieldValue) { var raw = RawString(fieldValue); if (bool.TryParse(raw, out var b)) return b; return raw == "1"; } private static decimal? ParseDecimal(object fieldValue) { var raw = RawString(fieldValue); return decimal.TryParse(raw, out var v) ? v : null; } private static string RawString(object fieldValue) { return fieldValue is JsonElement je ? (je.ValueKind == JsonValueKind.Number ? je.GetRawText() : je.GetString() ?? string.Empty) : fieldValue?.ToString() ?? string.Empty; } } }