From 1faf9167b7c16f81086847dafba8343b03d0945c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 09:43:31 +0000 Subject: [PATCH 1/5] Initial plan From 9bab06d916ce8022f91a50622990891bfe3c5a7e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 09:47:51 +0000 Subject: [PATCH 2/5] Reduce GetMerchant method LOC Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com> --- EstateReportingAPI.BusinessLogic/ReportingManager.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/EstateReportingAPI.BusinessLogic/ReportingManager.cs b/EstateReportingAPI.BusinessLogic/ReportingManager.cs index c758ef9..889c3ea 100644 --- a/EstateReportingAPI.BusinessLogic/ReportingManager.cs +++ b/EstateReportingAPI.BusinessLogic/ReportingManager.cs @@ -1001,8 +1001,7 @@ public async Task>> GetMerchants(MerchantQueries.GetMercha return Result.Success(response); } - public async Task> GetMerchant(MerchantQueries.GetMerchantQuery request, - CancellationToken cancellationToken) { + public async Task> GetMerchant(MerchantQueries.GetMerchantQuery request, CancellationToken cancellationToken) { using ResolvedDbContext? resolvedContext = this.Resolver.Resolve(EstateManagementDatabaseName, request.EstateId.ToString()); await using EstateManagementContext context = resolvedContext.Context; @@ -1028,8 +1027,7 @@ public async Task> GetMerchant(MerchantQueries.GetMerchantQuery var merchantQueryResult = await ExecuteQuerySafeSingleOrDefault(merchantQuery, cancellationToken, "Error getting merchant"); - if (merchantQueryResult.IsFailed) - return ResultHelpers.CreateFailure(merchantQueryResult); + if (merchantQueryResult.IsFailed) return ResultHelpers.CreateFailure(merchantQueryResult); var merchant = merchantQueryResult.Data; From 87425eb7ccf3b3fbe05cc973bbb8e4ca7cf8d951 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 09:54:05 +0000 Subject: [PATCH 3/5] Extract GetMerchant helpers Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com> --- .../ReportingManager.cs | 107 ++++++++++++------ 1 file changed, 75 insertions(+), 32 deletions(-) diff --git a/EstateReportingAPI.BusinessLogic/ReportingManager.cs b/EstateReportingAPI.BusinessLogic/ReportingManager.cs index 889c3ea..a3744d1 100644 --- a/EstateReportingAPI.BusinessLogic/ReportingManager.cs +++ b/EstateReportingAPI.BusinessLogic/ReportingManager.cs @@ -1005,40 +1005,57 @@ public async Task> GetMerchant(MerchantQueries.GetMerchantQuery using ResolvedDbContext? resolvedContext = this.Resolver.Resolve(EstateManagementDatabaseName, request.EstateId.ToString()); await using EstateManagementContext context = resolvedContext.Context; - - var merchantQuery = context.Merchants.Select(m => new { - MerchantReportingId = m.MerchantReportingId, - Name = m.Name, - CreatedDateTime = m.CreatedDateTime, - MerchantId = m.MerchantId, - Reference = m.Reference, - m.SettlementSchedule, - AddressInfo = context.MerchantAddresses.Where(ma => ma.MerchantId == m.MerchantId).OrderByDescending(ma => ma.CreatedDateTime).Select(ma => new { - ma.AddressId, - ma.AddressLine1, - ma.AddressLine2, - ma.Country, - ma.PostalCode, - ma.Region, - ma.Town - }).FirstOrDefault(), - ContactInfo = context.MerchantContacts.Where(mc => mc.MerchantId == m.MerchantId).OrderByDescending(mc => mc.CreatedDateTime).Select(mc => new { mc.ContactId, mc.Name, mc.EmailAddress, mc.PhoneNumber }).FirstOrDefault() - }).Where(m => m.MerchantId == request.MerchantId); - + var merchantQuery = BuildMerchantQuery(context, request.MerchantId); var merchantQueryResult = await ExecuteQuerySafeSingleOrDefault(merchantQuery, cancellationToken, "Error getting merchant"); + if (merchantQueryResult.IsFailed) { + return ResultHelpers.CreateFailure(merchantQueryResult); + } - if (merchantQueryResult.IsFailed) return ResultHelpers.CreateFailure(merchantQueryResult); - - var merchant = merchantQueryResult.Data; - - // Get the merchant state to get the balance var merchantStateQueryResult = await ExecuteQuerySafeSingleOrDefault(context.MerchantBalanceProjectionState.Where(ms => ms.MerchantId == request.MerchantId), cancellationToken, "Error getting merchant state"); if (merchantStateQueryResult.IsFailed) return ResultHelpers.CreateFailure(merchantStateQueryResult); - var merchantState = merchantStateQueryResult.Data; - - // Ok now enumerate the results - Merchant result = new() { - Balance = merchantState.Balance, + + return Result.Success(MapMerchant(merchantQueryResult.Data, merchantStateQueryResult.Data.Balance)); + } + + private static IQueryable BuildMerchantQuery(EstateManagementContext context, + Guid merchantId) { + return context.Merchants + .Select(m => new MerchantData { + MerchantReportingId = m.MerchantReportingId, + Name = m.Name, + CreatedDateTime = m.CreatedDateTime, + MerchantId = m.MerchantId, + Reference = m.Reference, + SettlementSchedule = m.SettlementSchedule, + AddressInfo = context.MerchantAddresses.Where(ma => ma.MerchantId == m.MerchantId) + .OrderByDescending(ma => ma.CreatedDateTime) + .Select(ma => new MerchantAddressData { + AddressId = ma.AddressId, + AddressLine1 = ma.AddressLine1, + AddressLine2 = ma.AddressLine2, + Country = ma.Country, + PostalCode = ma.PostalCode, + Region = ma.Region, + Town = ma.Town + }) + .FirstOrDefault(), + ContactInfo = context.MerchantContacts.Where(mc => mc.MerchantId == m.MerchantId) + .OrderByDescending(mc => mc.CreatedDateTime) + .Select(mc => new MerchantContactData { + ContactId = mc.ContactId, + Name = mc.Name, + EmailAddress = mc.EmailAddress, + PhoneNumber = mc.PhoneNumber + }) + .FirstOrDefault() + }) + .Where(m => m.MerchantId == merchantId); + } + + private static Merchant MapMerchant(MerchantData merchant, + decimal balance) { + return new Merchant { + Balance = balance, CreatedDateTime = merchant.CreatedDateTime, Name = merchant.Name, Reference = merchant.Reference, @@ -1057,8 +1074,6 @@ public async Task> GetMerchant(MerchantQueries.GetMerchantQuery ContactEmail = merchant.ContactInfo.EmailAddress, ContactPhone = merchant.ContactInfo.PhoneNumber }; - - return Result.Success(result); } public async Task>> GetMerchantOperators(MerchantQueries.GetMerchantOperatorsQuery request, @@ -1524,6 +1539,34 @@ private sealed class ContractFeeData { public bool IsEnabled { get; init; } } + private sealed class MerchantData { + public Guid MerchantId { get; init; } + public int MerchantReportingId { get; init; } + public string? Name { get; init; } + public DateTime CreatedDateTime { get; init; } + public string? Reference { get; init; } + public int SettlementSchedule { get; init; } + public MerchantAddressData? AddressInfo { get; init; } + public MerchantContactData? ContactInfo { get; init; } + } + + private sealed class MerchantAddressData { + public Guid AddressId { get; init; } + public string? AddressLine1 { get; init; } + public string? AddressLine2 { get; init; } + public string? Country { get; init; } + public string? PostalCode { get; init; } + public string? Region { get; init; } + public string? Town { get; init; } + } + + private sealed class MerchantContactData { + public Guid ContactId { get; init; } + public string? Name { get; init; } + public string? EmailAddress { get; init; } + public string? PhoneNumber { get; init; } + } + private sealed class ProductPerformanceItemData { public string? ProductName { get; init; } public Guid ContractProductId { get; init; } From b1494d5ba5cdbccaaab63c5de35148771ab7814a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:09:51 +0000 Subject: [PATCH 4/5] Move merchant mapping to ModelFactory Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com> --- .../ModelFactory.cs | 58 +++++++++++++++++++ .../ReportingManager.cs | 56 +----------------- 2 files changed, 60 insertions(+), 54 deletions(-) create mode 100644 EstateReportingAPI.BusinessLogic/ModelFactory.cs diff --git a/EstateReportingAPI.BusinessLogic/ModelFactory.cs b/EstateReportingAPI.BusinessLogic/ModelFactory.cs new file mode 100644 index 0000000..460bc0d --- /dev/null +++ b/EstateReportingAPI.BusinessLogic/ModelFactory.cs @@ -0,0 +1,58 @@ +namespace EstateReportingAPI.BusinessLogic; + +using System; +using Merchant = EstateReportingAPI.Models.Merchant; + +internal static class ModelFactory { + internal static Merchant ConvertFrom(MerchantData merchant, + decimal balance) { + return new Merchant { + Balance = balance, + CreatedDateTime = merchant.CreatedDateTime, + Name = merchant.Name, + Reference = merchant.Reference, + MerchantId = merchant.MerchantId, + MerchantReportingId = merchant.MerchantReportingId, + SettlementSchedule = merchant.SettlementSchedule, + AddressId = merchant.AddressInfo.AddressId, + AddressLine1 = merchant.AddressInfo.AddressLine1, + AddressLine2 = merchant.AddressInfo.AddressLine2, + Town = merchant.AddressInfo.Town, + Region = merchant.AddressInfo.Region, + PostCode = merchant.AddressInfo.PostalCode, + Country = merchant.AddressInfo.Country, + ContactId = merchant.ContactInfo.ContactId, + ContactName = merchant.ContactInfo.Name, + ContactEmail = merchant.ContactInfo.EmailAddress, + ContactPhone = merchant.ContactInfo.PhoneNumber + }; + } +} + +internal sealed class MerchantData { + public Guid MerchantId { get; init; } + public int MerchantReportingId { get; init; } + public string? Name { get; init; } + public DateTime CreatedDateTime { get; init; } + public string? Reference { get; init; } + public int SettlementSchedule { get; init; } + public MerchantAddressData? AddressInfo { get; init; } + public MerchantContactData? ContactInfo { get; init; } +} + +internal sealed class MerchantAddressData { + public Guid AddressId { get; init; } + public string? AddressLine1 { get; init; } + public string? AddressLine2 { get; init; } + public string? Country { get; init; } + public string? PostalCode { get; init; } + public string? Region { get; init; } + public string? Town { get; init; } +} + +internal sealed class MerchantContactData { + public Guid ContactId { get; init; } + public string? Name { get; init; } + public string? EmailAddress { get; init; } + public string? PhoneNumber { get; init; } +} diff --git a/EstateReportingAPI.BusinessLogic/ReportingManager.cs b/EstateReportingAPI.BusinessLogic/ReportingManager.cs index a3744d1..a5896a2 100644 --- a/EstateReportingAPI.BusinessLogic/ReportingManager.cs +++ b/EstateReportingAPI.BusinessLogic/ReportingManager.cs @@ -1014,7 +1014,7 @@ public async Task> GetMerchant(MerchantQueries.GetMerchantQuery var merchantStateQueryResult = await ExecuteQuerySafeSingleOrDefault(context.MerchantBalanceProjectionState.Where(ms => ms.MerchantId == request.MerchantId), cancellationToken, "Error getting merchant state"); if (merchantStateQueryResult.IsFailed) return ResultHelpers.CreateFailure(merchantStateQueryResult); - return Result.Success(MapMerchant(merchantQueryResult.Data, merchantStateQueryResult.Data.Balance)); + return Result.Success(ModelFactory.ConvertFrom(merchantQueryResult.Data, merchantStateQueryResult.Data.Balance)); } private static IQueryable BuildMerchantQuery(EstateManagementContext context, @@ -1052,32 +1052,8 @@ private static IQueryable BuildMerchantQuery(EstateManagementConte .Where(m => m.MerchantId == merchantId); } - private static Merchant MapMerchant(MerchantData merchant, - decimal balance) { - return new Merchant { - Balance = balance, - CreatedDateTime = merchant.CreatedDateTime, - Name = merchant.Name, - Reference = merchant.Reference, - MerchantId = merchant.MerchantId, - MerchantReportingId = merchant.MerchantReportingId, - SettlementSchedule = merchant.SettlementSchedule, - AddressId = merchant.AddressInfo.AddressId, - AddressLine1 = merchant.AddressInfo.AddressLine1, - AddressLine2 = merchant.AddressInfo.AddressLine2, - Town = merchant.AddressInfo.Town, - Region = merchant.AddressInfo.Region, - PostCode = merchant.AddressInfo.PostalCode, - Country = merchant.AddressInfo.Country, - ContactId = merchant.ContactInfo.ContactId, - ContactName = merchant.ContactInfo.Name, - ContactEmail = merchant.ContactInfo.EmailAddress, - ContactPhone = merchant.ContactInfo.PhoneNumber - }; - } - public async Task>> GetMerchantOperators(MerchantQueries.GetMerchantOperatorsQuery request, - CancellationToken cancellationToken) { + CancellationToken cancellationToken) { using ResolvedDbContext? resolvedContext = this.Resolver.Resolve(EstateManagementDatabaseName, request.EstateId.ToString()); await using EstateManagementContext context = resolvedContext.Context; @@ -1539,34 +1515,6 @@ private sealed class ContractFeeData { public bool IsEnabled { get; init; } } - private sealed class MerchantData { - public Guid MerchantId { get; init; } - public int MerchantReportingId { get; init; } - public string? Name { get; init; } - public DateTime CreatedDateTime { get; init; } - public string? Reference { get; init; } - public int SettlementSchedule { get; init; } - public MerchantAddressData? AddressInfo { get; init; } - public MerchantContactData? ContactInfo { get; init; } - } - - private sealed class MerchantAddressData { - public Guid AddressId { get; init; } - public string? AddressLine1 { get; init; } - public string? AddressLine2 { get; init; } - public string? Country { get; init; } - public string? PostalCode { get; init; } - public string? Region { get; init; } - public string? Town { get; init; } - } - - private sealed class MerchantContactData { - public Guid ContactId { get; init; } - public string? Name { get; init; } - public string? EmailAddress { get; init; } - public string? PhoneNumber { get; init; } - } - private sealed class ProductPerformanceItemData { public string? ProductName { get; init; } public Guid ContractProductId { get; init; } From 7901a472f420f77e8a652adefda0a08efd521bdd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:17:00 +0000 Subject: [PATCH 5/5] Move merchant projections to DatabaseModels Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com> --- .../DatabaseModels.cs | 31 +++++++++++++++++++ .../ModelFactory.cs | 29 ----------------- 2 files changed, 31 insertions(+), 29 deletions(-) create mode 100644 EstateReportingAPI.BusinessLogic/DatabaseModels.cs diff --git a/EstateReportingAPI.BusinessLogic/DatabaseModels.cs b/EstateReportingAPI.BusinessLogic/DatabaseModels.cs new file mode 100644 index 0000000..11ff3f3 --- /dev/null +++ b/EstateReportingAPI.BusinessLogic/DatabaseModels.cs @@ -0,0 +1,31 @@ +namespace EstateReportingAPI.BusinessLogic; + +using System; + +internal sealed class MerchantData { + public Guid MerchantId { get; init; } + public int MerchantReportingId { get; init; } + public string? Name { get; init; } + public DateTime CreatedDateTime { get; init; } + public string? Reference { get; init; } + public int SettlementSchedule { get; init; } + public MerchantAddressData? AddressInfo { get; init; } + public MerchantContactData? ContactInfo { get; init; } +} + +internal sealed class MerchantAddressData { + public Guid AddressId { get; init; } + public string? AddressLine1 { get; init; } + public string? AddressLine2 { get; init; } + public string? Country { get; init; } + public string? PostalCode { get; init; } + public string? Region { get; init; } + public string? Town { get; init; } +} + +internal sealed class MerchantContactData { + public Guid ContactId { get; init; } + public string? Name { get; init; } + public string? EmailAddress { get; init; } + public string? PhoneNumber { get; init; } +} diff --git a/EstateReportingAPI.BusinessLogic/ModelFactory.cs b/EstateReportingAPI.BusinessLogic/ModelFactory.cs index 460bc0d..888007f 100644 --- a/EstateReportingAPI.BusinessLogic/ModelFactory.cs +++ b/EstateReportingAPI.BusinessLogic/ModelFactory.cs @@ -1,6 +1,5 @@ namespace EstateReportingAPI.BusinessLogic; -using System; using Merchant = EstateReportingAPI.Models.Merchant; internal static class ModelFactory { @@ -28,31 +27,3 @@ internal static Merchant ConvertFrom(MerchantData merchant, }; } } - -internal sealed class MerchantData { - public Guid MerchantId { get; init; } - public int MerchantReportingId { get; init; } - public string? Name { get; init; } - public DateTime CreatedDateTime { get; init; } - public string? Reference { get; init; } - public int SettlementSchedule { get; init; } - public MerchantAddressData? AddressInfo { get; init; } - public MerchantContactData? ContactInfo { get; init; } -} - -internal sealed class MerchantAddressData { - public Guid AddressId { get; init; } - public string? AddressLine1 { get; init; } - public string? AddressLine2 { get; init; } - public string? Country { get; init; } - public string? PostalCode { get; init; } - public string? Region { get; init; } - public string? Town { get; init; } -} - -internal sealed class MerchantContactData { - public Guid ContactId { get; init; } - public string? Name { get; init; } - public string? EmailAddress { get; init; } - public string? PhoneNumber { get; init; } -}