From 58a9761b50ccdbe35cb6899c080a1c995c90cbf6 Mon Sep 17 00:00:00 2001 From: Stuart Ferguson Date: Wed, 11 Mar 2026 17:52:35 +0000 Subject: [PATCH] Add reporting IDs to contract products and fees Introduced ContractProductReportingId and ContractProductTransactionFeeReportingId properties to the relevant models. Updated data mapping, JSON serialization, and query logic to ensure these reporting IDs are included throughout the data flow, from database to API response. This enables more robust reporting and traceability for contract products and their transaction fees. --- .../ReportingManager.cs | 15 +++++++++++++-- EstateReportingAPI.DataTrasferObjects/Contract.cs | 6 ++++++ .../ContractEndPointTests.cs | 9 +++++++-- EstateReportingAPI.Models/ContractProduct.cs | 1 + .../ContractProductTransactionFee.cs | 1 + EstateReportingAPI/Handlers/ContractHandler.cs | 8 ++++++-- 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/EstateReportingAPI.BusinessLogic/ReportingManager.cs b/EstateReportingAPI.BusinessLogic/ReportingManager.cs index cbb39ae..b5e13c0 100644 --- a/EstateReportingAPI.BusinessLogic/ReportingManager.cs +++ b/EstateReportingAPI.BusinessLogic/ReportingManager.cs @@ -287,6 +287,7 @@ from o in ops.DefaultIfEmpty() CancellationToken cancellationToken) { var productsQuery = context.ContractProducts.Where(cp => cp.ContractId == contractId).Select(cp => new { cp.ContractProductId, + cp.ContractProductReportingId, cp.ContractId, cp.DisplayText, cp.ProductName, @@ -305,6 +306,7 @@ from o in ops.DefaultIfEmpty() var feesQuery = context.ContractProductTransactionFees.Where(tf => productIds.Contains(tf.ContractProductId)).Select(tf => new { tf.CalculationType, tf.ContractProductTransactionFeeId, + tf.ContractProductTransactionFeeReportingId, tf.FeeType, tf.Value, tf.ContractProductId, @@ -326,12 +328,14 @@ from o in ops.DefaultIfEmpty() ProductName = p.ProductName, ProductType = p.ProductType, Value = p.Value, + ContractProductReportingId = p.ContractProductReportingId, TransactionFees = feesLookup[p.ContractProductId].Select(f => new ContractProductTransactionFee { Description = f.Description, Value = f.Value, CalculationType = f.CalculationType, FeeType = f.FeeType, - TransactionFeeId = f.ContractProductTransactionFeeId + TransactionFeeId = f.ContractProductTransactionFeeId, + ContractProductTransactionFeeReportingId = f.ContractProductTransactionFeeReportingId }).ToList() }).ToList()); } @@ -1362,6 +1366,7 @@ private static async Task>> LoadProductsAsync(E string stepName) { var query = context.ContractProducts.Where(cp => contractIds.Contains(cp.ContractId)).Select(cp => new ContractProductData { ContractProductId = cp.ContractProductId, + ContractProductReportingId = cp.ContractProductReportingId, ContractId = cp.ContractId, DisplayText = cp.DisplayText, ProductName = cp.ProductName, @@ -1377,6 +1382,7 @@ private static async Task>> LoadFeesAsync(EstateMan string stepName) { var query = context.ContractProductTransactionFees.Where(tf => productIds.Contains(tf.ContractProductId)).Select(tf => new ContractFeeData { ContractProductTransactionFeeId = tf.ContractProductTransactionFeeId, + ContractProducTransactionFeeReportingId = tf.ContractProductTransactionFeeReportingId, ContractProductId = tf.ContractProductId, Description = tf.Description, CalculationType = tf.CalculationType, @@ -1400,6 +1406,7 @@ private static List BuildContracts(List baseContract Products = products.Where(p => p.ContractId == b.ContractId).Select(p => new Models.ContractProduct { ContractId = p.ContractId, ProductId = p.ContractProductId, + ContractProductReportingId = p.ContractProductReportingId, DisplayText = p.DisplayText, ProductName = p.ProductName, ProductType = p.ProductType, @@ -1409,7 +1416,8 @@ private static List BuildContracts(List baseContract Value = f.Value, CalculationType = f.CalculationType, FeeType = f.FeeType, - TransactionFeeId = f.ContractProductTransactionFeeId + TransactionFeeId = f.ContractProductTransactionFeeId, + ContractProductTransactionFeeReportingId = f.ContractProducTransactionFeeReportingId }).ToList() }).ToList() }).ToList(); @@ -1494,6 +1502,7 @@ private sealed class ContractBaseData { private sealed class ContractProductData { public Guid ContractProductId { get; init; } + public int ContractProductReportingId { get; init; } public Guid ContractId { get; init; } public string? DisplayText { get; init; } public string? ProductName { get; init; } @@ -1503,6 +1512,7 @@ private sealed class ContractProductData { private sealed class ContractFeeData { public Guid ContractProductTransactionFeeId { get; init; } + public int ContractProducTransactionFeeReportingId { get; init; } public Guid ContractProductId { get; init; } public string? Description { get; init; } public int CalculationType { get; init; } @@ -1525,3 +1535,4 @@ private sealed class ProductPerformanceItemData { #endregion } + diff --git a/EstateReportingAPI.DataTrasferObjects/Contract.cs b/EstateReportingAPI.DataTrasferObjects/Contract.cs index d9b5682..0923687 100644 --- a/EstateReportingAPI.DataTrasferObjects/Contract.cs +++ b/EstateReportingAPI.DataTrasferObjects/Contract.cs @@ -32,6 +32,9 @@ public class ContractProduct { [JsonProperty("contract_id")] public Guid ContractId { get; set; } + [JsonProperty("contract_product_reporting_id")] + public Int32 ContractProductReportingId { get; set; } + [JsonProperty("product_id")] public Guid ProductId { get; set; } [JsonProperty("product_name")] @@ -49,6 +52,9 @@ public class ContractProduct public class ContractProductTransactionFee { [JsonProperty("transaction_fee_id")] public Guid TransactionFeeId { get; set; } + [JsonProperty("contract_product_transaction_fee_reporting_id")] + public Int32 ContractProductTransactionFeeReportingId { get; set; } + [JsonProperty("description")] public string? Description { get; set; } [JsonProperty("calculation_type")] diff --git a/EstateReportingAPI.IntegrationTests/ContractEndPointTests.cs b/EstateReportingAPI.IntegrationTests/ContractEndPointTests.cs index 9ce619a..f59ab1c 100644 --- a/EstateReportingAPI.IntegrationTests/ContractEndPointTests.cs +++ b/EstateReportingAPI.IntegrationTests/ContractEndPointTests.cs @@ -79,7 +79,10 @@ public async Task ContractEndpoint_GetContracts_ContractsReturned() { contracts.SingleOrDefault(c => c.Description == "Healthcare Centre 1 Contract").ShouldNotBeNull(); contracts.SingleOrDefault(c => c.Description == "PataPawa PostPay Contract").ShouldNotBeNull(); contracts.SingleOrDefault(c => c.Description == "PataPawa PrePay Contract").ShouldNotBeNull(); - + foreach (Contract contract in contracts) { + contract.Products.Any(cp => cp.ContractProductReportingId != 0).ShouldBeTrue(); + contract.Products.ToList().ForEach(cp => cp.TransactionFees.Any(t => t.ContractProductTransactionFeeReportingId != 0).ShouldBeTrue()); + } } [Fact] @@ -111,7 +114,9 @@ public async Task ContractEndpoint_GetContract_ContractReturned() { Contract contract = result.Data; contract.ShouldNotBeNull(); contract.Description.ShouldBe("PataPawa PrePay Contract"); - + contract.ContractReportingId.ShouldNotBe(0); + contract.Products.Any(cp => cp.ContractProductReportingId != 0).ShouldBeTrue(); + contract.Products.ToList().ForEach(cp => cp.TransactionFees.Any(t => t.ContractProductTransactionFeeReportingId != 0).ShouldBeTrue()); } protected override async Task ClearStandingData() { diff --git a/EstateReportingAPI.Models/ContractProduct.cs b/EstateReportingAPI.Models/ContractProduct.cs index 3e35e4b..5e73cf6 100644 --- a/EstateReportingAPI.Models/ContractProduct.cs +++ b/EstateReportingAPI.Models/ContractProduct.cs @@ -3,6 +3,7 @@ public class ContractProduct { public Guid ContractId { get; set; } public Guid ProductId { get; set; } + public Int32 ContractProductReportingId { get; set; } public String ProductName { get; set; } public String DisplayText { get; set; } public Int32 ProductType { get; set; } diff --git a/EstateReportingAPI.Models/ContractProductTransactionFee.cs b/EstateReportingAPI.Models/ContractProductTransactionFee.cs index 35f18ab..84cad52 100644 --- a/EstateReportingAPI.Models/ContractProductTransactionFee.cs +++ b/EstateReportingAPI.Models/ContractProductTransactionFee.cs @@ -2,6 +2,7 @@ public class ContractProductTransactionFee { + public Int32 ContractProductTransactionFeeReportingId { get; set; } public Guid TransactionFeeId { get; set; } public string? Description { get; set; } public Int32 CalculationType { get; set; } diff --git a/EstateReportingAPI/Handlers/ContractHandler.cs b/EstateReportingAPI/Handlers/ContractHandler.cs index d338a56..68db54e 100644 --- a/EstateReportingAPI/Handlers/ContractHandler.cs +++ b/EstateReportingAPI/Handlers/ContractHandler.cs @@ -51,12 +51,14 @@ public static async Task GetContracts([FromHeader] Guid estateId, ProductName = p.ProductName, ProductType = p.ProductType, Value = p.Value, + ContractProductReportingId = p.ContractProductReportingId, TransactionFees = p.TransactionFees.Select(f => new DataTransferObjects.ContractProductTransactionFee { Description = f.Description, Value = f.Value, CalculationType = f.CalculationType, FeeType = f.FeeType, - TransactionFeeId = f.TransactionFeeId + TransactionFeeId = f.TransactionFeeId, + ContractProductTransactionFeeReportingId = f.ContractProductTransactionFeeReportingId }).ToList() }).ToList() }).ToList()); @@ -87,13 +89,15 @@ public static async Task GetContract([FromHeader] Guid estateId, ProductName = p.ProductName, ProductType = p.ProductType, Value = p.Value, + ContractProductReportingId = p.ContractProductReportingId, TransactionFees = p.TransactionFees.Select(f => new DataTransferObjects.ContractProductTransactionFee { Description = f.Description, Value = f.Value, CalculationType = f.CalculationType, FeeType = f.FeeType, - TransactionFeeId = f.TransactionFeeId + TransactionFeeId = f.TransactionFeeId, + ContractProductTransactionFeeReportingId = f.ContractProductTransactionFeeReportingId }).ToList() }).ToList() });