From 60641e52fc4cd8d65f5ceb72d6f6f47100c96732 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 10:18:48 +0000 Subject: [PATCH 1/5] Initial plan From 7f0e4e7722e7a2077026de013030d524016dcbfa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 10:31:05 +0000 Subject: [PATCH 2/5] refactor: split MerchantHandlers contract mapping Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com> --- .../Handlers/MerchantHandlers.cs | 106 ++++++++---------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/TransactionProcessorACL/Handlers/MerchantHandlers.cs b/TransactionProcessorACL/Handlers/MerchantHandlers.cs index 397bc8b..888b61d 100644 --- a/TransactionProcessorACL/Handlers/MerchantHandlers.cs +++ b/TransactionProcessorACL/Handlers/MerchantHandlers.cs @@ -28,64 +28,56 @@ public static async Task GetMerchantContracts(IMediator mediator, Claim MerchantQueries.GetMerchantContractsQuery query = new(claimsResult.Data.estateId, claimsResult.Data.merchantId); Result> result = await mediator.Send(query, cancellationToken); - return ResponseFactory.FromResult(result, list => { - List responses = new(); - foreach (ContractResponse contractModel in result.Data) { - DataTransferObjects.Responses.ContractResponse contractResponse = new() { - ContractId = contractModel.ContractId, - ContractReportingId = contractModel.ContractReportingId, - Description = contractModel.Description, - EstateId = contractModel.EstateId, - EstateReportingId = contractModel.EstateReportingId, - OperatorId = contractModel.OperatorId, - OperatorName = contractModel.OperatorName, - Products = new() - }; - - foreach (ContractProduct contractModelProduct in contractModel.Products) { - DataTransferObjects.Responses.ContractProduct productResponse = new() { - Value = contractModelProduct.Value, - DisplayText = contractModelProduct.DisplayText, - Name = contractModelProduct.Name, - ProductId = contractModelProduct.ProductId, - ProductReportingId = contractModelProduct.ProductReportingId, - ProductType = contractModelProduct.ProductType switch { - ProductType.BillPayment => DataTransferObjects.Responses.ProductType.BillPayment, - ProductType.MobileTopup => DataTransferObjects.Responses.ProductType.MobileTopup, - ProductType.Voucher => DataTransferObjects.Responses.ProductType.Voucher, - _ => DataTransferObjects.Responses.ProductType.NotSet - }, - TransactionFees = new() - }; - - foreach (ContractProductTransactionFee contractProductTransactionFeeModel in contractModelProduct.TransactionFees) { - DataTransferObjects.Responses.ContractProductTransactionFee transactionFeeModel = new() { - Value = contractProductTransactionFeeModel.Value, - Description = contractProductTransactionFeeModel.Description, - CalculationType = contractProductTransactionFeeModel.CalculationType switch { - CalculationType.Fixed => DataTransferObjects.Responses.CalculationType.Fixed, - _ => DataTransferObjects.Responses.CalculationType.Percentage, - }, - FeeType = contractProductTransactionFeeModel.FeeType switch { - FeeType.Merchant => DataTransferObjects.Responses.FeeType.Merchant, - _ => DataTransferObjects.Responses.FeeType.ServiceProvider, - }, - TransactionFeeId = contractProductTransactionFeeModel.TransactionFeeId, - TransactionFeeReportingId = contractProductTransactionFeeModel.TransactionFeeReportingId - }; - productResponse.TransactionFees.Add(transactionFeeModel); - } - - contractResponse.Products.Add(productResponse); - } - - responses.Add(contractResponse); - } - - return responses; - }); + return ResponseFactory.FromResult(result, list => MapContractResponses(list)); } + private static List MapContractResponses(List contractResponses) => + contractResponses.Select(MapContractResponse).ToList(); + + private static DataTransferObjects.Responses.ContractResponse MapContractResponse(ContractResponse contractModel) => + new() { + ContractId = contractModel.ContractId, + ContractReportingId = contractModel.ContractReportingId, + Description = contractModel.Description, + EstateId = contractModel.EstateId, + EstateReportingId = contractModel.EstateReportingId, + OperatorId = contractModel.OperatorId, + OperatorName = contractModel.OperatorName, + Products = contractModel.Products.Select(MapContractProductResponse).ToList() + }; + + private static DataTransferObjects.Responses.ContractProduct MapContractProductResponse(ContractProduct contractModelProduct) => + new() { + Value = contractModelProduct.Value, + DisplayText = contractModelProduct.DisplayText, + Name = contractModelProduct.Name, + ProductId = contractModelProduct.ProductId, + ProductReportingId = contractModelProduct.ProductReportingId, + ProductType = contractModelProduct.ProductType switch { + ProductType.BillPayment => DataTransferObjects.Responses.ProductType.BillPayment, + ProductType.MobileTopup => DataTransferObjects.Responses.ProductType.MobileTopup, + ProductType.Voucher => DataTransferObjects.Responses.ProductType.Voucher, + _ => DataTransferObjects.Responses.ProductType.NotSet + }, + TransactionFees = contractModelProduct.TransactionFees.Select(MapContractProductTransactionFeeResponse).ToList() + }; + + private static DataTransferObjects.Responses.ContractProductTransactionFee MapContractProductTransactionFeeResponse(ContractProductTransactionFee contractProductTransactionFeeModel) => + new() { + Value = contractProductTransactionFeeModel.Value, + Description = contractProductTransactionFeeModel.Description, + CalculationType = contractProductTransactionFeeModel.CalculationType switch { + CalculationType.Fixed => DataTransferObjects.Responses.CalculationType.Fixed, + _ => DataTransferObjects.Responses.CalculationType.Percentage, + }, + FeeType = contractProductTransactionFeeModel.FeeType switch { + FeeType.Merchant => DataTransferObjects.Responses.FeeType.Merchant, + _ => DataTransferObjects.Responses.FeeType.ServiceProvider, + }, + TransactionFeeId = contractProductTransactionFeeModel.TransactionFeeId, + TransactionFeeReportingId = contractProductTransactionFeeModel.TransactionFeeReportingId + }; + public static async Task GetMerchant(IMediator mediator, ClaimsPrincipal user, string applicationVersion, CancellationToken cancellationToken) { Logger.LogWarning("In GetMerchant Handler"); @@ -183,4 +175,4 @@ protected override Task HandleRequirementAsync( return Task.CompletedTask; } } -} \ No newline at end of file +} From b911b9b8437aa565057402262ecfde313ccfb6b5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 12:25:01 +0000 Subject: [PATCH 3/5] fix: align merchant handlers with master changes Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com> --- .../General/ModelFactoryTests.cs | 99 +++++++++++++++++++ .../Factories/IModelFactory.cs | 4 +- .../Factories/ModelFactory.cs | 94 +++++++++++++++++- .../Handlers/MerchantHandlers.cs | 80 ++------------- 4 files changed, 204 insertions(+), 73 deletions(-) diff --git a/TransactionProcessorACL.Tests/General/ModelFactoryTests.cs b/TransactionProcessorACL.Tests/General/ModelFactoryTests.cs index dac7a90..5e643fd 100644 --- a/TransactionProcessorACL.Tests/General/ModelFactoryTests.cs +++ b/TransactionProcessorACL.Tests/General/ModelFactoryTests.cs @@ -156,5 +156,104 @@ public void ModelFactory_ConvertFrom_RedeemVoucherResponse_NullValue_IsConverted dto.ShouldBeNull(); } + + [Fact] + public void ModelFactory_ConvertFrom_MerchantResponse_IsConverted() + { + ModelFactory modelFactory = new ModelFactory(); + + Models.MerchantResponse model = new Models.MerchantResponse + { + EstateId = TestData.EstateId, + MerchantId = TestData.MerchantId, + EstateReportingId = 123, + MerchantReportingId = 456, + MerchantName = TestData.MerchantName, + MerchantReference = "Reference", + NextStatementDate = TestData.GeneratedDateTime, + SettlementSchedule = Models.SettlementSchedule.Monthly, + Addresses = new List + { + new Models.AddressResponse + { + AddressId = Guid.NewGuid(), + AddressLine1 = TestData.AddressLine1, + AddressLine2 = TestData.AddressLine2, + AddressLine3 = TestData.AddressLine3, + AddressLine4 = TestData.AddressLine4, + Country = TestData.Country, + PostalCode = TestData.PostCode, + Region = TestData.Region, + Town = TestData.Town + } + }, + Contacts = new List + { + new Models.ContactResponse + { + ContactId = Guid.NewGuid(), + ContactName = TestData.ContactName, + ContactPhoneNumber = TestData.ContactPhone, + ContactEmailAddress = TestData.ContactEmail + } + }, + Contracts = new List + { + new Models.MerchantContractResponse + { + ContractId = TestData.ContractId, + IsDeleted = true, + ContractProducts = new List { TestData.ProductId } + } + }, + Devices = new Dictionary + { + { TestData.DeviceId, TestData.DeviceIdentifier } + }, + Operators = new List + { + new Models.MerchantOperatorResponse + { + OperatorId = TestData.OperatorId, + IsDeleted = true, + MerchantNumber = TestData.MerchantNumber, + Name = "Operator Name", + TerminalNumber = TestData.TerminalNumber + } + } + }; + + DataTransferObjects.Responses.MerchantResponse dto = modelFactory.ConvertFrom(model); + + dto.ShouldNotBeNull(); + dto.EstateId.ShouldBe(model.EstateId); + dto.MerchantId.ShouldBe(model.MerchantId); + dto.EstateReportingId.ShouldBe(model.EstateReportingId); + dto.MerchantReportingId.ShouldBe(model.MerchantReportingId); + dto.MerchantName.ShouldBe(model.MerchantName); + dto.MerchantReference.ShouldBe(model.MerchantReference); + dto.NextStatementDate.ShouldBe(model.NextStatementDate); + dto.SettlementSchedule.ShouldBe(DataTransferObjects.Responses.SettlementSchedule.Monthly); + dto.Addresses.Count.ShouldBe(1); + dto.Addresses[0].Town.ShouldBe(TestData.Town); + dto.Contacts.Count.ShouldBe(1); + dto.Contacts[0].ContactEmailAddress.ShouldBe(TestData.ContactEmail); + dto.Contracts.Count.ShouldBe(1); + dto.Contracts[0].ContractProducts.ShouldContain(TestData.ProductId); + dto.Devices[TestData.DeviceId].ShouldBe(TestData.DeviceIdentifier); + dto.Operators.Count.ShouldBe(1); + dto.Operators[0].TerminalNumber.ShouldBe(TestData.TerminalNumber); + } + + [Fact] + public void ModelFactory_ConvertFrom_MerchantResponse_NullValue_IsConverted() + { + ModelFactory modelFactory = new ModelFactory(); + + Models.MerchantResponse model = null; + DataTransferObjects.Responses.MerchantResponse dto = modelFactory.ConvertFrom(model); + + dto.ShouldBeNull(); + } } } diff --git a/TransactionProcessorACL/Factories/IModelFactory.cs b/TransactionProcessorACL/Factories/IModelFactory.cs index 4ea3a5b..44c148a 100644 --- a/TransactionProcessorACL/Factories/IModelFactory.cs +++ b/TransactionProcessorACL/Factories/IModelFactory.cs @@ -20,6 +20,8 @@ public interface IModelFactory GetVoucherResponseMessage ConvertFrom(GetVoucherResponse model); + DataTransferObjects.Responses.MerchantResponse ConvertFrom(Models.MerchantResponse model); + #endregion } -} \ No newline at end of file +} diff --git a/TransactionProcessorACL/Factories/ModelFactory.cs b/TransactionProcessorACL/Factories/ModelFactory.cs index 3ac54d6..fdd538b 100644 --- a/TransactionProcessorACL/Factories/ModelFactory.cs +++ b/TransactionProcessorACL/Factories/ModelFactory.cs @@ -1,5 +1,7 @@ -namespace TransactionProcessorACL.Factories +namespace TransactionProcessorACL.Factories { + using System; + using System.Collections.Generic; using DataTransferObjects.Responses; using Models; @@ -90,6 +92,94 @@ public GetVoucherResponseMessage ConvertFrom(GetVoucherResponse model) return responseMessage; } + public DataTransferObjects.Responses.MerchantResponse ConvertFrom(Models.MerchantResponse model) + { + if (model == null) + { + return null; + } + + DataTransferObjects.Responses.MerchantResponse merchantResponse = new DataTransferObjects.Responses.MerchantResponse + { + EstateId = model.EstateId, + MerchantId = model.MerchantId, + EstateReportingId = model.EstateReportingId, + MerchantName = model.MerchantName, + MerchantReference = model.MerchantReference, + MerchantReportingId = model.MerchantReportingId, + NextStatementDate = model.NextStatementDate, + SettlementSchedule = model.SettlementSchedule switch + { + Models.SettlementSchedule.Weekly => DataTransferObjects.Responses.SettlementSchedule.Weekly, + Models.SettlementSchedule.Monthly => DataTransferObjects.Responses.SettlementSchedule.Monthly, + _ => DataTransferObjects.Responses.SettlementSchedule.NotSet + }, + Addresses = new List(), + Contacts = new List(), + Contracts = new List(), + Devices = new Dictionary(), + Operators = new List() + }; + + foreach (Models.AddressResponse addressModel in model.Addresses) + { + merchantResponse.Addresses.Add(new DataTransferObjects.Responses.AddressResponse + { + AddressId = addressModel.AddressId, + AddressLine1 = addressModel.AddressLine1, + AddressLine2 = addressModel.AddressLine2, + AddressLine3 = addressModel.AddressLine3, + AddressLine4 = addressModel.AddressLine4, + Country = addressModel.Country, + PostalCode = addressModel.PostalCode, + Region = addressModel.Region, + Town = addressModel.Town + }); + } + + foreach (Models.ContactResponse contactModel in model.Contacts) + { + merchantResponse.Contacts.Add(new DataTransferObjects.Responses.ContactResponse + { + ContactId = contactModel.ContactId, + ContactName = contactModel.ContactName, + ContactPhoneNumber = contactModel.ContactPhoneNumber, + ContactEmailAddress = contactModel.ContactEmailAddress + }); + } + + foreach (Models.MerchantContractResponse merchantContractResponse in model.Contracts) + { + DataTransferObjects.Responses.MerchantContractResponse contract = new DataTransferObjects.Responses.MerchantContractResponse + { + ContractId = merchantContractResponse.ContractId, + IsDeleted = merchantContractResponse.IsDeleted, + ContractProducts = new List(merchantContractResponse.ContractProducts) + }; + + merchantResponse.Contracts.Add(contract); + } + + foreach (KeyValuePair device in model.Devices) + { + merchantResponse.Devices.Add(device.Key, device.Value); + } + + foreach (Models.MerchantOperatorResponse merchantOperatorResponse in model.Operators) + { + merchantResponse.Operators.Add(new DataTransferObjects.Responses.MerchantOperatorResponse + { + OperatorId = merchantOperatorResponse.OperatorId, + IsDeleted = merchantOperatorResponse.IsDeleted, + MerchantNumber = merchantOperatorResponse.MerchantNumber, + Name = merchantOperatorResponse.Name, + TerminalNumber = merchantOperatorResponse.TerminalNumber + }); + } + + return merchantResponse; + } + public RedeemVoucherResponseMessage ConvertFrom(RedeemVoucherResponse model) { if (model == null) @@ -113,4 +203,4 @@ public RedeemVoucherResponseMessage ConvertFrom(RedeemVoucherResponse model) #endregion } -} \ No newline at end of file +} diff --git a/TransactionProcessorACL/Handlers/MerchantHandlers.cs b/TransactionProcessorACL/Handlers/MerchantHandlers.cs index 888b61d..19e0d38 100644 --- a/TransactionProcessorACL/Handlers/MerchantHandlers.cs +++ b/TransactionProcessorACL/Handlers/MerchantHandlers.cs @@ -11,6 +11,7 @@ using Shared.Results.Web; using SimpleResults; using TransactionProcessorACL.BusinessLogic.Requests; +using TransactionProcessorACL.Factories; using TransactionProcessorACL.Models; namespace TransactionProcessorACL.Handlers @@ -78,7 +79,11 @@ private static DataTransferObjects.Responses.ContractProductTransactionFee MapCo TransactionFeeReportingId = contractProductTransactionFeeModel.TransactionFeeReportingId }; - public static async Task GetMerchant(IMediator mediator, ClaimsPrincipal user, string applicationVersion, CancellationToken cancellationToken) + public static async Task GetMerchant(IMediator mediator, + IModelFactory modelFactory, + ClaimsPrincipal user, + string applicationVersion, + CancellationToken cancellationToken) { Logger.LogWarning("In GetMerchant Handler"); @@ -89,82 +94,17 @@ public static async Task GetMerchant(IMediator mediator, ClaimsPrincipa MerchantQueries.GetMerchantQuery query = new(claimsResult.Data.estateId, claimsResult.Data.merchantId); Result result = await mediator.Send(query, cancellationToken); - return ResponseFactory.FromResult(result, response => { - - DataTransferObjects.Responses.MerchantResponse merchantResponse = new() { - EstateId = result.Data.EstateId, - MerchantId = result.Data.MerchantId, - EstateReportingId = result.Data.EstateReportingId, - MerchantName = result.Data.MerchantName, - MerchantReference = result.Data.MerchantReference, - MerchantReportingId = result.Data.MerchantReportingId, - NextStatementDate = result.Data.NextStatementDate, - SettlementSchedule = result.Data.SettlementSchedule switch { - SettlementSchedule.Weekly => DataTransferObjects.Responses.SettlementSchedule.Weekly, - SettlementSchedule.Monthly => DataTransferObjects.Responses.SettlementSchedule.Monthly, - _ => DataTransferObjects.Responses.SettlementSchedule.NotSet - }, - Addresses = new(), - Contacts = new(), - Contracts = new(), - Devices = new(), - Operators = new() - }; - - foreach (AddressResponse addressModel in result.Data.Addresses) { - DataTransferObjects.Responses.AddressResponse addressResponse = new() { - AddressId = addressModel.AddressId, - AddressLine1 = addressModel.AddressLine1, - AddressLine2 = addressModel.AddressLine2, - AddressLine3 = addressModel.AddressLine3, - AddressLine4 = addressModel.AddressLine4, - Country = addressModel.Country, - PostalCode = addressModel.PostalCode, - Region = addressModel.Region, - Town = addressModel.Town - }; - merchantResponse.Addresses.Add(addressResponse); - } - - foreach (ContactResponse contactResponse in result.Data.Contacts) { - merchantResponse.Contacts.Add(new DataTransferObjects.Responses.ContactResponse { ContactId = contactResponse.ContactId, ContactName = contactResponse.ContactName, ContactPhoneNumber = contactResponse.ContactPhoneNumber, ContactEmailAddress = contactResponse.ContactEmailAddress }); - } - - foreach (MerchantContractResponse merchantContractResponse in result.Data.Contracts) { - DataTransferObjects.Responses.MerchantContractResponse contract = new() { ContractId = merchantContractResponse.ContractId, IsDeleted = merchantContractResponse.IsDeleted, ContractProducts = new() }; - foreach (Guid contractProduct in merchantContractResponse.ContractProducts) { - contract.ContractProducts.Add(contractProduct); - } - - merchantResponse.Contracts.Add(contract); - } - - foreach (KeyValuePair device in result.Data.Devices) { - merchantResponse.Devices.Add(device.Key, device.Value); - } - - foreach (MerchantOperatorResponse merchantOperatorResponse in result.Data.Operators) { - merchantResponse.Operators.Add(new DataTransferObjects.Responses.MerchantOperatorResponse { - OperatorId = merchantOperatorResponse.OperatorId, - IsDeleted = merchantOperatorResponse.IsDeleted, - MerchantNumber = merchantOperatorResponse.MerchantNumber, - Name = merchantOperatorResponse.Name, - TerminalNumber = merchantOperatorResponse.TerminalNumber - }); - } - - return merchantResponse; - }); + return ResponseFactory.FromResult(result, modelFactory.ConvertFrom); } } - public class PasswordTokenRequirement : IAuthorizationRequirement { } + public class ClaimsIdentityRequirement : IAuthorizationRequirement { } - public class PasswordTokenHandler : AuthorizationHandler + public class ClaimsIdentityHandler : AuthorizationHandler { protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, - PasswordTokenRequirement requirement) + ClaimsIdentityRequirement requirement) { var hasClaim = context.User.Claims .Any(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"); From f67ca3c87fcc00fd3735eb759cd67468407d8e3a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 13:02:22 +0000 Subject: [PATCH 4/5] merge: bring latest master into merchant contracts refactor Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com> --- ...ansactionProcessorACLApplicationService.cs | 83 ++++++++++++------- .../General/ModelFactoryTests.cs | 2 +- 2 files changed, 52 insertions(+), 33 deletions(-) diff --git a/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs b/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs index bca4ac1..e79e308 100644 --- a/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs +++ b/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs @@ -282,51 +282,25 @@ public async Task GetVoucher(Guid estateId, Result accessTokenResult = await this.SecurityServiceClient.GetToken(clientId, clientSecret, cancellationToken); if (accessTokenResult.IsFailed) { - return new GetVoucherResponse { - ResponseCode = "0004", // Token error - ResponseMessage = "Token Error", - }; + return CreateGetVoucherTokenErrorResponse(); } - TokenResponse accessToken = accessTokenResult.Data; - GetVoucherResponse response = null; + TokenResponse accessToken = accessTokenResult.Data; try { Result getVoucherResult = await this.TransactionProcessorClient.GetVoucherByCode(accessToken.AccessToken, estateId, voucherCode, cancellationToken); if (getVoucherResult.IsFailed) { - return new GetVoucherResponse - { - ResponseCode = "0005", // Voucher not found - ResponseMessage = getVoucherResult.Message, - }; + return CreateGetVoucherFailureResponse(getVoucherResult.Message); } - TransactionProcessor.DataTransferObjects.GetVoucherResponse getVoucherResponse = getVoucherResult.Data; - response = new GetVoucherResponse - { - ResponseCode = "0000", // Success - ContractId = contractId, - EstateId = estateId, - ExpiryDate = getVoucherResponse.ExpiryDate, - Value = getVoucherResponse.Value, - VoucherCode = getVoucherResponse.VoucherCode, - VoucherId = getVoucherResponse.VoucherId, - Balance = getVoucherResponse.Balance - }; + + return CreateGetVoucherSuccessResponse(estateId, contractId, getVoucherResult.Data); } catch (Exception ex) { - // This means there is an error in the request - response = new GetVoucherResponse - { - ResponseCode = "0001", // Request Message error - ResponseMessage = "Get Voucher Failed", - ErrorMessages = ex.GetExceptionMessages() - }; + return CreateGetVoucherErrorResponse(ex); } - - return response; } public async Task RedeemVoucher(Guid estateId, @@ -511,6 +485,51 @@ private static ProcessReconciliationResponse CreateProcessReconciliationResponse }; } + private static GetVoucherResponse CreateGetVoucherSuccessResponse(Guid estateId, + Guid contractId, + TransactionProcessor.DataTransferObjects.GetVoucherResponse getVoucherResponse) + { + return new GetVoucherResponse + { + ResponseCode = "0000", // Success + ContractId = contractId, + EstateId = estateId, + ExpiryDate = getVoucherResponse.ExpiryDate, + Value = getVoucherResponse.Value, + VoucherCode = getVoucherResponse.VoucherCode, + VoucherId = getVoucherResponse.VoucherId, + Balance = getVoucherResponse.Balance + }; + } + + private static GetVoucherResponse CreateGetVoucherFailureResponse(String responseMessage) + { + return new GetVoucherResponse + { + ResponseCode = "0005", // Voucher not found + ResponseMessage = responseMessage + }; + } + + private static GetVoucherResponse CreateGetVoucherTokenErrorResponse() + { + return new GetVoucherResponse + { + ResponseCode = "0004", // Token error + ResponseMessage = "Token Error", + }; + } + + private static GetVoucherResponse CreateGetVoucherErrorResponse(Exception ex) + { + return new GetVoucherResponse + { + ResponseCode = "0001", // Request Message error + ResponseMessage = "Get Voucher Failed", + ErrorMessages = ex.GetExceptionMessages() + }; + } + private static ProcessReconciliationResponse CreateReconciliationErrorResponse(Guid estateId, Guid merchantId, Exception ex) diff --git a/TransactionProcessorACL.Tests/General/ModelFactoryTests.cs b/TransactionProcessorACL.Tests/General/ModelFactoryTests.cs index 5e643fd..b36718f 100644 --- a/TransactionProcessorACL.Tests/General/ModelFactoryTests.cs +++ b/TransactionProcessorACL.Tests/General/ModelFactoryTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text; From 54f71289c8e2fdabb155dbf7ff5d78094009af41 Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Wed, 18 Mar 2026 20:58:42 +0000 Subject: [PATCH 5/5] fix --- .../RedeemVoucher/RedeemVoucher.feature.cs | 159 +++++++++--------- 1 file changed, 81 insertions(+), 78 deletions(-) diff --git a/TransactionProcessorACL.IntegrationTests/RedeemVoucher/RedeemVoucher.feature.cs b/TransactionProcessorACL.IntegrationTests/RedeemVoucher/RedeemVoucher.feature.cs index 8b059ca..3424b81 100644 --- a/TransactionProcessorACL.IntegrationTests/RedeemVoucher/RedeemVoucher.feature.cs +++ b/TransactionProcessorACL.IntegrationTests/RedeemVoucher/RedeemVoucher.feature.cs @@ -111,130 +111,130 @@ public void ScenarioInitialize(global::Reqnroll.ScenarioInfo scenarioInfo, globa { #line 4 #line hidden - global::Reqnroll.Table table54 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table1 = new global::Reqnroll.Table(new string[] { "Role Name"}); - table54.AddRow(new string[] { + table1.AddRow(new string[] { "Merchant"}); - table54.AddRow(new string[] { + table1.AddRow(new string[] { "VoucherRedemption"}); #line 6 - await testRunner.GivenAsync("the following security roles exist", ((string)(null)), table54, "Given "); + await testRunner.GivenAsync("the following security roles exist", ((string)(null)), table1, "Given "); #line hidden - global::Reqnroll.Table table55 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table2 = new global::Reqnroll.Table(new string[] { "Name", "DisplayName", "Description"}); - table55.AddRow(new string[] { + table2.AddRow(new string[] { "estateManagement", "Estate Managememt REST Scope", "A scope for Estate Managememt REST"}); - table55.AddRow(new string[] { + table2.AddRow(new string[] { "transactionProcessor", "Transaction Processor REST Scope", "A scope for Transaction Processor REST"}); - table55.AddRow(new string[] { + table2.AddRow(new string[] { "transactionProcessorACL", "Transaction Processor ACL REST Scope", "A scope for Transaction Processor ACL REST"}); - table55.AddRow(new string[] { + table2.AddRow(new string[] { "voucherManagement", "Voucher Management REST Scope", "A scope for Voucher Management REST"}); #line 11 - await testRunner.GivenAsync("I create the following api scopes", ((string)(null)), table55, "Given "); + await testRunner.GivenAsync("I create the following api scopes", ((string)(null)), table2, "Given "); #line hidden - global::Reqnroll.Table table56 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table3 = new global::Reqnroll.Table(new string[] { "Name", "DisplayName", "Secret", "Scopes", "UserClaims"}); - table56.AddRow(new string[] { + table3.AddRow(new string[] { "estateManagement", "Estate Managememt REST", "Secret1", "estateManagement", "merchantId, estateId, role"}); - table56.AddRow(new string[] { + table3.AddRow(new string[] { "transactionProcessor", "Transaction Processor REST", "Secret1", "transactionProcessor", ""}); - table56.AddRow(new string[] { + table3.AddRow(new string[] { "transactionProcessorACL", "Transaction Processor ACL REST", "Secret1", "transactionProcessorACL", "merchantId, estateId, role, contractId"}); - table56.AddRow(new string[] { + table3.AddRow(new string[] { "voucherManagement", "Voucher Management REST", "Secret1", "voucherManagement", ""}); #line 18 - await testRunner.GivenAsync("the following api resources exist", ((string)(null)), table56, "Given "); + await testRunner.GivenAsync("the following api resources exist", ((string)(null)), table3, "Given "); #line hidden - global::Reqnroll.Table table57 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table4 = new global::Reqnroll.Table(new string[] { "ClientId", "ClientName", "Secret", "Scopes", "GrantTypes"}); - table57.AddRow(new string[] { + table4.AddRow(new string[] { "serviceClient", "Service Client", "Secret1", "estateManagement,transactionProcessor,transactionProcessorACL,voucherManagement", "client_credentials"}); - table57.AddRow(new string[] { + table4.AddRow(new string[] { "merchantClient", "Merchant Client", "Secret1", "transactionProcessorACL", "password"}); - table57.AddRow(new string[] { + table4.AddRow(new string[] { "redemptionClient", "Redemption Client", "Secret1", "transactionProcessorACL", "password"}); #line 25 - await testRunner.GivenAsync("the following clients exist", ((string)(null)), table57, "Given "); + await testRunner.GivenAsync("the following clients exist", ((string)(null)), table4, "Given "); #line hidden - global::Reqnroll.Table table58 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table5 = new global::Reqnroll.Table(new string[] { "ClientId"}); - table58.AddRow(new string[] { + table5.AddRow(new string[] { "serviceClient"}); #line 31 await testRunner.GivenAsync("I have a token to access the estate management and transaction processor acl reso" + - "urces", ((string)(null)), table58, "Given "); + "urces", ((string)(null)), table5, "Given "); #line hidden - global::Reqnroll.Table table59 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table6 = new global::Reqnroll.Table(new string[] { "EstateName"}); - table59.AddRow(new string[] { + table6.AddRow(new string[] { "Test Estate 1"}); - table59.AddRow(new string[] { + table6.AddRow(new string[] { "Test Estate 2"}); #line 35 - await testRunner.GivenAsync("I have created the following estates", ((string)(null)), table59, "Given "); + await testRunner.GivenAsync("I have created the following estates", ((string)(null)), table6, "Given "); #line hidden - global::Reqnroll.Table table60 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table7 = new global::Reqnroll.Table(new string[] { "Email Address", "Password", "Given Name", "Family Name", "EstateName", "Roles"}); - table60.AddRow(new string[] { + table7.AddRow(new string[] { "redemptionuser@testredemption1.co.uk", "123456", "TestRedemption", "User1", "Test Estate 1", "VoucherRedemption"}); - table60.AddRow(new string[] { + table7.AddRow(new string[] { "redemptionuser@testredemption2.co.uk", "123456", "TestRedemption", @@ -242,54 +242,54 @@ await testRunner.GivenAsync("I have a token to access the estate management and "Test Estate 2", "VoucherRedemption"}); #line 40 - await testRunner.GivenAsync("I have created the following security users for voucher redemption", ((string)(null)), table60, "Given "); + await testRunner.GivenAsync("I have created the following security users for voucher redemption", ((string)(null)), table7, "Given "); #line hidden - global::Reqnroll.Table table61 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table8 = new global::Reqnroll.Table(new string[] { "EstateName", "OperatorName", "RequireCustomMerchantNumber", "RequireCustomTerminalNumber"}); - table61.AddRow(new string[] { + table8.AddRow(new string[] { "Test Estate 1", "Voucher", "True", "True"}); - table61.AddRow(new string[] { + table8.AddRow(new string[] { "Test Estate 2", "Voucher", "True", "True"}); #line 45 - await testRunner.GivenAsync("I have created the following operators", ((string)(null)), table61, "Given "); + await testRunner.GivenAsync("I have created the following operators", ((string)(null)), table8, "Given "); #line hidden - global::Reqnroll.Table table62 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table9 = new global::Reqnroll.Table(new string[] { "EstateName", "OperatorName"}); - table62.AddRow(new string[] { + table9.AddRow(new string[] { "Test Estate 1", "Voucher"}); - table62.AddRow(new string[] { + table9.AddRow(new string[] { "Test Estate 2", "Voucher"}); #line 50 - await testRunner.AndAsync("I have assigned the following operators to the estates", ((string)(null)), table62, "And "); + await testRunner.AndAsync("I have assigned the following operators to the estates", ((string)(null)), table9, "And "); #line hidden - global::Reqnroll.Table table63 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table10 = new global::Reqnroll.Table(new string[] { "EstateName", "OperatorName", "ContractDescription"}); - table63.AddRow(new string[] { + table10.AddRow(new string[] { "Test Estate 1", "Voucher", "Hospital 1 Contract"}); - table63.AddRow(new string[] { + table10.AddRow(new string[] { "Test Estate 2", "Voucher", "Hospital 2 Contract"}); #line 55 - await testRunner.GivenAsync("I create a contract with the following values", ((string)(null)), table63, "Given "); + await testRunner.GivenAsync("I create a contract with the following values", ((string)(null)), table10, "Given "); #line hidden - global::Reqnroll.Table table64 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table11 = new global::Reqnroll.Table(new string[] { "EstateName", "OperatorName", "ContractDescription", @@ -297,7 +297,7 @@ await testRunner.GivenAsync("I have a token to access the estate management and "DisplayText", "Value", "ProductType"}); - table64.AddRow(new string[] { + table11.AddRow(new string[] { "Test Estate 1", "Voucher", "Hospital 1 Contract", @@ -305,7 +305,7 @@ await testRunner.GivenAsync("I have a token to access the estate management and "10 KES", "", "Voucher"}); - table64.AddRow(new string[] { + table11.AddRow(new string[] { "Test Estate 2", "Voucher", "Hospital 2 Contract", @@ -314,125 +314,128 @@ await testRunner.GivenAsync("I have a token to access the estate management and "", "Voucher"}); #line 60 - await testRunner.WhenAsync("I create the following Products", ((string)(null)), table64, "When "); + await testRunner.WhenAsync("I create the following Products", ((string)(null)), table11, "When "); #line hidden - global::Reqnroll.Table table65 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table12 = new global::Reqnroll.Table(new string[] { "MerchantName", "AddressLine1", "Town", "Region", + "PostalCode", "Country", "ContactName", "EmailAddress", "EstateName"}); - table65.AddRow(new string[] { + table12.AddRow(new string[] { "Test Merchant 1", "Address Line 1", "TestTown", "Test Region", + "TE57 1NG", "United Kingdom", "Test Contact 1", "testcontact1@merchant1.co.uk", "Test Estate 1"}); - table65.AddRow(new string[] { + table12.AddRow(new string[] { "Test Merchant 2", "Address Line 1", "TestTown", "Test Region", + "TE57 2NG", "United Kingdom", "Test Contact 1", "testcontact1@merchant1.co.uk", "Test Estate 2"}); #line 65 - await testRunner.GivenAsync("I create the following merchants", ((string)(null)), table65, "Given "); + await testRunner.GivenAsync("I create the following merchants", ((string)(null)), table12, "Given "); #line hidden - global::Reqnroll.Table table66 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table13 = new global::Reqnroll.Table(new string[] { "OperatorName", "MerchantName", "MerchantNumber", "TerminalNumber", "EstateName"}); - table66.AddRow(new string[] { + table13.AddRow(new string[] { "Voucher", "Test Merchant 1", "00000001", "10000001", "Test Estate 1"}); - table66.AddRow(new string[] { + table13.AddRow(new string[] { "Voucher", "Test Merchant 2", "00000002", "10000002", "Test Estate 2"}); #line 70 - await testRunner.GivenAsync("I have assigned the following operator to the merchants", ((string)(null)), table66, "Given "); + await testRunner.GivenAsync("I have assigned the following operator to the merchants", ((string)(null)), table13, "Given "); #line hidden - global::Reqnroll.Table table67 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table14 = new global::Reqnroll.Table(new string[] { "DeviceIdentifier", "MerchantName", "EstateName"}); - table67.AddRow(new string[] { + table14.AddRow(new string[] { "123456780", "Test Merchant 1", "Test Estate 1"}); - table67.AddRow(new string[] { + table14.AddRow(new string[] { "123456781", "Test Merchant 2", "Test Estate 2"}); #line 75 - await testRunner.GivenAsync("I have assigned the following devices to the merchants", ((string)(null)), table67, "Given "); + await testRunner.GivenAsync("I have assigned the following devices to the merchants", ((string)(null)), table14, "Given "); #line hidden - global::Reqnroll.Table table68 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table15 = new global::Reqnroll.Table(new string[] { "EstateName", "MerchantName", "ContractDescription"}); - table68.AddRow(new string[] { + table15.AddRow(new string[] { "Test Estate 1", "Test Merchant 1", "Hospital 1 Contract"}); - table68.AddRow(new string[] { + table15.AddRow(new string[] { "Test Estate 2", "Test Merchant 2", "Hospital 2 Contract"}); #line 80 -await testRunner.WhenAsync("I add the following contracts to the following merchants", ((string)(null)), table68, "When "); +await testRunner.WhenAsync("I add the following contracts to the following merchants", ((string)(null)), table15, "When "); #line hidden - global::Reqnroll.Table table69 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table16 = new global::Reqnroll.Table(new string[] { "Reference", "Amount", "DateTime", "MerchantName", "EstateName"}); - table69.AddRow(new string[] { + table16.AddRow(new string[] { "Deposit1", "20.00", "Today", "Test Merchant 1", "Test Estate 1"}); - table69.AddRow(new string[] { + table16.AddRow(new string[] { "Deposit1", "20.00", "Today", "Test Merchant 2", "Test Estate 2"}); #line 85 - await testRunner.GivenAsync("I make the following manual merchant deposits", ((string)(null)), table69, "Given "); + await testRunner.GivenAsync("I make the following manual merchant deposits", ((string)(null)), table16, "Given "); #line hidden - global::Reqnroll.Table table70 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table17 = new global::Reqnroll.Table(new string[] { "EmailAddress", "Password", "GivenName", "FamilyName", "EstateName", "MerchantName"}); - table70.AddRow(new string[] { + table17.AddRow(new string[] { "merchantuser@testmerchant1.co.uk", "123456", "TestMerchant", "User1", "Test Estate 1", "Test Merchant 1"}); - table70.AddRow(new string[] { + table17.AddRow(new string[] { "merchantuser@testmerchant2.co.uk", "123456", "TestMerchant", @@ -440,14 +443,14 @@ await testRunner.GivenAsync("I have a token to access the estate management and "Test Estate 2", "Test Merchant 2"}); #line 90 - await testRunner.GivenAsync("I have created the following security users", ((string)(null)), table70, "Given "); + await testRunner.GivenAsync("I have created the following security users", ((string)(null)), table17, "Given "); #line hidden #line 95 await testRunner.GivenAsync("I am logged in as \"merchantuser@testmerchant1.co.uk\" with password \"123456\" for M" + "erchant \"Test Merchant 1\" for Estate \"Test Estate 1\" with client \"merchantClient" + "\"", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); #line hidden - global::Reqnroll.Table table71 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table18 = new global::Reqnroll.Table(new string[] { "DateTime", "TransactionNumber", "TransactionType", @@ -466,7 +469,7 @@ await testRunner.GivenAsync("I have a token to access the estate management and "MessageType", "AccountNumber", "CustomerName"}); - table71.AddRow(new string[] { + table18.AddRow(new string[] { "Today", "1", "Sale", @@ -486,14 +489,14 @@ await testRunner.GivenAsync("I have a token to access the estate management and "", ""}); #line 97 - await testRunner.WhenAsync("I perform the following transactions", ((string)(null)), table71, "When "); + await testRunner.WhenAsync("I perform the following transactions", ((string)(null)), table18, "When "); #line hidden #line 101 await testRunner.GivenAsync("I am logged in as \"merchantuser@testmerchant2.co.uk\" with password \"123456\" for M" + "erchant \"Test Merchant 2\" for Estate \"Test Estate 2\" with client \"merchantClient" + "\"", ((string)(null)), ((global::Reqnroll.Table)(null)), "Given "); #line hidden - global::Reqnroll.Table table72 = new global::Reqnroll.Table(new string[] { + global::Reqnroll.Table table19 = new global::Reqnroll.Table(new string[] { "DateTime", "TransactionNumber", "TransactionType", @@ -512,7 +515,7 @@ await testRunner.GivenAsync("I have a token to access the estate management and "MessageType", "AccountNumber", "CustomerName"}); - table72.AddRow(new string[] { + table19.AddRow(new string[] { "Today", "2", "Sale", @@ -532,7 +535,7 @@ await testRunner.GivenAsync("I have a token to access the estate management and "", ""}); #line 103 - await testRunner.WhenAsync("I perform the following transactions", ((string)(null)), table72, "When "); + await testRunner.WhenAsync("I perform the following transactions", ((string)(null)), table19, "When "); #line hidden }