From b939a8e1733188e54fcdc8647e3e306349afbb7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 19:32:43 +0000 Subject: [PATCH 1/3] Initial plan From 53e247f583ff0b0cd502b147089923228bfa08b8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 19:45:14 +0000 Subject: [PATCH 2/3] Refactor: Extract helper methods to reduce GetTransactionSummaryByOperatorReport complexity Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com> --- .../ReportingManager.cs | 120 ++++++++++++------ 1 file changed, 78 insertions(+), 42 deletions(-) diff --git a/EstateReportingAPI.BusinessLogic/ReportingManager.cs b/EstateReportingAPI.BusinessLogic/ReportingManager.cs index aaad86e..fe5c020 100644 --- a/EstateReportingAPI.BusinessLogic/ReportingManager.cs +++ b/EstateReportingAPI.BusinessLogic/ReportingManager.cs @@ -836,10 +836,27 @@ into g public async Task> GetTransactionSummaryByOperatorReport(TransactionQueries.TransactionSummaryByOperatorQuery request, CancellationToken cancellationToken) { - TransactionSummaryByOperatorResponse response = null; using ResolvedDbContext? resolvedContext = this.Resolver.Resolve(EstateManagementDatabaseName, request.EstateId.ToString()); await using EstateManagementContext context = resolvedContext.Context; + var baseQuery = BuildOperatorTransactionBaseQuery(context, request); + var finalQuery = BuildOperatorFinalSummaryQuery(baseQuery); + + var queryResult = await ExecuteQuerySafeToList(finalQuery, cancellationToken, "Error retrieving transaction summary by operator report"); + + if (queryResult.IsFailed) + return ResultHelpers.CreateFailure(queryResult); + + var queryResults = queryResult.Data; + + if (queryResults.Any() == false) + return new TransactionSummaryByOperatorResponse { Summary = new OperatorDetailSummary(), Operators = new List() }; + + return BuildOperatorSummaryResponse(queryResults); + } + + private static IQueryable BuildOperatorTransactionBaseQuery(EstateManagementContext context, + TransactionQueries.TransactionSummaryByOperatorQuery request) { var query = from t in context.Transactions join m in context.Merchants on t.MerchantId equals m.MerchantId join o in context.Operators on t.OperatorId equals o.OperatorId @@ -853,56 +870,47 @@ join o in context.Operators on t.OperatorId equals o.OperatorId OperatorName = o.Name } into g - select new { - g.Key.MerchantId, - g.Key.MerchantReportingId, - g.Key.MerchantName, - g.Key.OperatorId, - g.Key.OperatorReportingId, - g.Key.OperatorName, + select new OperatorTransactionData { + MerchantId = g.Key.MerchantId, + MerchantReportingId = g.Key.MerchantReportingId, + MerchantName = g.Key.MerchantName, + OperatorId = g.Key.OperatorId, + OperatorReportingId = g.Key.OperatorReportingId, + OperatorName = g.Key.OperatorName, TotalCount = g.Count(), TotalValue = g.Sum(x => x.TransactionAmount), AuthorisedCount = g.Sum(x => x.IsAuthorised ? 1 : 0), DeclinedCount = g.Sum(x => x.IsAuthorised ? 0 : 1) }; - // Now apply the filters - if (request.Request.Merchants != null && request.Request.Merchants.Any()) { + if (request.Request.Merchants != null && request.Request.Merchants.Any()) query = query.Where(q => request.Request.Merchants.Contains(q.MerchantReportingId)); - } - if (request.Request.Operators != null && request.Request.Operators.Any()) { + if (request.Request.Operators != null && request.Request.Operators.Any()) query = query.Where(q => request.Request.Operators.Contains(q.OperatorReportingId)); - } - - var finalQuery = from x in query - group x by new { x.OperatorId, x.OperatorReportingId, OperatorName = x.OperatorName, } - into g - select new { - g.Key.OperatorId, - g.Key.OperatorReportingId, - g.Key.OperatorName, - TotalCount = g.Sum(x => x.TotalCount), - TotalValue = g.Sum(x => x.TotalValue), - AverageValue = g.Count() > 0 ? g.Sum(x => x.TotalValue) / g.Count() : 0m, - AuthorisedCount = g.Sum(x => x.AuthorisedCount), - DeclinedCount = g.Sum(x => x.DeclinedCount), - AuthorisedPercentage = g.Sum(x => x.TotalCount) > 0 ? (decimal)g.Sum(x => x.AuthorisedCount) / (decimal)g.Sum(x => x.TotalCount) : 0m - }; - - var queryResult = await ExecuteQuerySafeToList(finalQuery, cancellationToken, "Error retrieving transaction summary by operator report"); - if (queryResult.IsFailed) - return ResultHelpers.CreateFailure(queryResult); - - // Ok now enumerate the results - var queryResults = queryResult.Data; + return query; + } - if (queryResults.Any() == false) - return new TransactionSummaryByOperatorResponse { Summary = new OperatorDetailSummary(), Operators = new List() }; + private static IQueryable BuildOperatorFinalSummaryQuery(IQueryable query) { + return from x in query + group x by new { x.OperatorId, x.OperatorReportingId, x.OperatorName } + into g + select new OperatorSummaryData { + OperatorId = g.Key.OperatorId, + OperatorReportingId = g.Key.OperatorReportingId, + OperatorName = g.Key.OperatorName, + TotalCount = g.Sum(x => x.TotalCount), + TotalValue = g.Sum(x => x.TotalValue), + AverageValue = g.Count() > 0 ? g.Sum(x => x.TotalValue) / g.Count() : 0m, + AuthorisedCount = g.Sum(x => x.AuthorisedCount), + DeclinedCount = g.Sum(x => x.DeclinedCount), + AuthorisedPercentage = g.Sum(x => x.TotalCount) > 0 ? (decimal)g.Sum(x => x.AuthorisedCount) / (decimal)g.Sum(x => x.TotalCount) : 0m + }; + } - // Now to translate the results - response = new TransactionSummaryByOperatorResponse { + private TransactionSummaryByOperatorResponse BuildOperatorSummaryResponse(List queryResults) { + return new TransactionSummaryByOperatorResponse { Operators = queryResults.Select(q => new OperatorDetail { OperatorId = q.OperatorId, OperatorReportingId = q.OperatorReportingId, @@ -914,10 +922,13 @@ into g TotalCount = q.TotalCount, TotalValue = q.TotalValue }).ToList(), - Summary = new OperatorDetailSummary { TotalCount = queryResults.Sum(q => q.TotalCount), TotalValue = queryResults.Sum(q => q.TotalValue), AverageValue = this.SafeDivide(queryResults.Sum(q => q.TotalValue), queryResults.Sum(q => q.TotalCount)), TotalOperators = queryResults.Count() } + Summary = new OperatorDetailSummary { + TotalCount = queryResults.Sum(q => q.TotalCount), + TotalValue = queryResults.Sum(q => q.TotalValue), + AverageValue = this.SafeDivide(queryResults.Sum(q => q.TotalValue), queryResults.Sum(q => q.TotalCount)), + TotalOperators = queryResults.Count() + } }; - - return response; } public async Task>> GetMerchants(MerchantQueries.GetMerchantsQuery request, @@ -1396,6 +1407,31 @@ private static List BuildContracts(List baseContract }).ToList(); } + private sealed class OperatorTransactionData { + public Guid MerchantId { get; init; } + public int MerchantReportingId { get; init; } + public string? MerchantName { get; init; } + public Guid OperatorId { get; init; } + public int OperatorReportingId { get; init; } + public string? OperatorName { get; init; } + public int TotalCount { get; init; } + public decimal TotalValue { get; init; } + public int AuthorisedCount { get; init; } + public int DeclinedCount { get; init; } + } + + private sealed class OperatorSummaryData { + public Guid OperatorId { get; init; } + public int OperatorReportingId { get; init; } + public string? OperatorName { get; init; } + public int TotalCount { get; init; } + public decimal TotalValue { get; init; } + public decimal AverageValue { get; init; } + public int AuthorisedCount { get; init; } + public int DeclinedCount { get; init; } + public decimal AuthorisedPercentage { get; init; } + } + private sealed class ContractBaseData { public Guid ContractId { get; init; } public int ContractReportingId { get; init; } From 8af97d33b434b55795e4b11fa8efa1fa86ba3474 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 21:55:25 +0000 Subject: [PATCH 3/3] Refactor: Extract ApplyOperatorTransactionFilters to reduce BuildOperatorTransactionBaseQuery complexity Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com> --- .../ReportingManager.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/EstateReportingAPI.BusinessLogic/ReportingManager.cs b/EstateReportingAPI.BusinessLogic/ReportingManager.cs index 7e95585..0ff7b0e 100644 --- a/EstateReportingAPI.BusinessLogic/ReportingManager.cs +++ b/EstateReportingAPI.BusinessLogic/ReportingManager.cs @@ -871,11 +871,16 @@ into g DeclinedCount = g.Sum(x => x.IsAuthorised ? 0 : 1) }; - if (request.Request.Merchants != null && request.Request.Merchants.Any()) - query = query.Where(q => request.Request.Merchants.Contains(q.MerchantReportingId)); + return ApplyOperatorTransactionFilters(query, request.Request); + } - if (request.Request.Operators != null && request.Request.Operators.Any()) - query = query.Where(q => request.Request.Operators.Contains(q.OperatorReportingId)); + private static IQueryable ApplyOperatorTransactionFilters(IQueryable query, + Models.TransactionSummaryByOperatorRequest request) { + if (request.Merchants != null && request.Merchants.Any()) + query = query.Where(q => request.Merchants.Contains(q.MerchantReportingId)); + + if (request.Operators != null && request.Operators.Any()) + query = query.Where(q => request.Operators.Contains(q.OperatorReportingId)); return query; }