diff --git a/TransactionProcessor.BusinessLogic.Tests/DomainEventHandlers/TransactionDomainEventHandlerTests.cs b/TransactionProcessor.BusinessLogic.Tests/DomainEventHandlers/TransactionDomainEventHandlerTests.cs index 5e731c1d..0434be48 100644 --- a/TransactionProcessor.BusinessLogic.Tests/DomainEventHandlers/TransactionDomainEventHandlerTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/DomainEventHandlers/TransactionDomainEventHandlerTests.cs @@ -31,9 +31,8 @@ public class TransactionDomainEventHandlerTests { - private Mock TransactionAggregateManager; - private Mock> SettlementAggregateRepository; + private Mock> TransactionAggregateRepository; private Mock FeeCalculationManager; @@ -44,10 +43,13 @@ public class TransactionDomainEventHandlerTests private Mock TransactionReceiptBuilder; private Mock MessagingServiceClient; + + private TransactionDomainEventHandler TransactionDomainEventHandler; + public TransactionDomainEventHandlerTests() { - this.TransactionAggregateManager = new Mock(); this.SettlementAggregateRepository = new Mock>(); + this.TransactionAggregateRepository = new Mock>(); this.FeeCalculationManager = new Mock(); this.EstateClient = new Mock(); this.SecurityServiceClient = new Mock(); @@ -57,12 +59,20 @@ public TransactionDomainEventHandlerTests() IConfigurationRoot configurationRoot = new ConfigurationBuilder().AddInMemoryCollection(TestData.DefaultAppSettings).Build(); ConfigurationReader.Initialise(configurationRoot); Logger.Initialise(NullLogger.Instance); + + this.TransactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateRepository.Object, + this.FeeCalculationManager.Object, + this.EstateClient.Object, + this.SecurityServiceClient.Object, + this.TransactionReceiptBuilder.Object, + this.MessagingServiceClient.Object, + this.SettlementAggregateRepository.Object); } [Fact] public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_SuccessfulSale_MerchantWithImmediateSettlement_EventIsHandled() { - this.TransactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) + this.TransactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); this.SettlementAggregateRepository.Setup(s => s.GetLatestVersion(It.IsAny(), It.IsAny())) @@ -87,28 +97,14 @@ public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenComplet It.IsAny())).ReturnsAsync(TestData.ContractProductTransactionFees); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); - await transactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); - - this.TransactionAggregateManager.Verify(t => t.AddFee(It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny()),Times.Once); + await this.TransactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); } [Fact] public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_SuccessfulSale_MerchantWithWeeklySettlement_EventIsHandled() { - this.TransactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) + this.TransactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); SettlementAggregate pendingSettlementAggregate = new SettlementAggregate(); this.SettlementAggregateRepository.Setup(p => p.GetLatestVersion(It.IsAny(), It.IsAny())) @@ -135,20 +131,13 @@ public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenComplet this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); - - await transactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); + await this.TransactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); - this.TransactionAggregateManager.Verify(t => t.AddFee(It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); + // TODO: way of verifying needed + //this.TransactionAggregateManager.Verify(t => t.AddFee(It.IsAny(), + // It.IsAny(), + // It.IsAny(), + // It.IsAny()), Times.Once); this.SettlementAggregateRepository.Verify(p => p.GetLatestVersion(It.IsAny(), It.IsAny()),Times.Once); this.SettlementAggregateRepository.Verify(p => p.SaveChanges(It.IsAny(), It.IsAny()), Times.Once); pendingSettlementAggregate.GetNumberOfFeesPendingSettlement().ShouldBe(1); @@ -158,7 +147,7 @@ public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenComplet [Fact] public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_SuccessfulSale_MerchantWithMonthlySettlement_EventIsHandled() { - this.TransactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) + this.TransactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); SettlementAggregate pendingSettlementAggregate = new SettlementAggregate(); this.SettlementAggregateRepository.Setup(p => p.GetLatestVersion(It.IsAny(), It.IsAny())) @@ -185,20 +174,8 @@ public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenComplet this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); + await this.TransactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); - await transactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); - - this.TransactionAggregateManager.Verify(t => t.AddFee(It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny()), Times.Once); this.SettlementAggregateRepository.Verify(p => p.GetLatestVersion(It.IsAny(), It.IsAny()), Times.Once); this.SettlementAggregateRepository.Verify(p => p.SaveChanges(It.IsAny(), It.IsAny()), Times.Once); pendingSettlementAggregate.GetNumberOfFeesPendingSettlement().ShouldBe(1); @@ -208,7 +185,7 @@ public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenComplet [Fact] public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_SuccessfulSale_MerchantWithNotSetSettlementSchedule_ErrorThrown() { - this.TransactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) + this.TransactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); this.FeeCalculationManager.Setup(f => f.CalculateFees(It.IsAny>(), It.IsAny(), It.IsAny())).Returns(new List @@ -230,106 +207,57 @@ public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenComplet It.IsAny())).ReturnsAsync(TestData.ContractProductTransactionFees); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); + Should.Throw(async () => { - await transactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); + await this.TransactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); }); } [Fact] public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_UnsuccessfulSale_EventIsHandled() { - this.TransactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) + this.TransactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetCompletedDeclinedSaleTransactionAggregate); - - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); - await transactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); + await this.TransactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); } [Fact] public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_IncompleteSale_EventIsHandled() { - this.TransactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) + this.TransactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetIncompleteAuthorisedSaleTransactionAggregate); - - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); - - await transactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); + await this.TransactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); } [Fact] public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_SaleWithNoProductDetails_EventIsHandled() { - this.TransactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) + this.TransactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetCompletedAuthorisedSaleWithNoProductDetailsTransactionAggregate); - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); - - await transactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); + await this.TransactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); } [Fact] public async Task TransactionDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_AuthorisedLogon_EventIsHandled() { - this.TransactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) + this.TransactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetCompletedAuthorisedLogonTransactionAggregate); - - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); - await transactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); + await this.TransactionDomainEventHandler.Handle(TestData.TransactionHasBeenCompletedEvent, CancellationToken.None); } [Fact] public async Task TransactionDomainEventHandler_Handle_CustomerEmailReceiptRequestedEvent_EventIsHandled() { - this.TransactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) + this.TransactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); - await transactionDomainEventHandler.Handle(TestData.CustomerEmailReceiptRequestedEvent, CancellationToken.None); + await this.TransactionDomainEventHandler.Handle(TestData.CustomerEmailReceiptRequestedEvent, CancellationToken.None); } [Fact] @@ -337,15 +265,7 @@ public async Task TransactionDomainEventHandler_Handle_CustomerEmailReceiptResen { this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); - - await transactionDomainEventHandler.Handle(TestData.CustomerEmailReceiptResendRequestedEvent, CancellationToken.None); + await this.TransactionDomainEventHandler.Handle(TestData.CustomerEmailReceiptResendRequestedEvent, CancellationToken.None); this.MessagingServiceClient.Verify(v => v.ResendEmail(It.IsAny(), It.IsAny(), @@ -359,29 +279,13 @@ public async Task TransactionDomainEventHandler_Handle_MerchantFeeAddedToTransac this.SettlementAggregateRepository.Setup(s => s.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetSettlementAggregateWithPendingMerchantFees(1)); - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); - - await transactionDomainEventHandler.Handle(TestData.MerchantFeeAddedToTransactionEvent(TestData.TransactionFeeSettlementDueDate), CancellationToken.None); + await this.TransactionDomainEventHandler.Handle(TestData.MerchantFeeAddedToTransactionEvent(TestData.TransactionFeeSettlementDueDate), CancellationToken.None); } [Fact] public async Task TransactionDomainEventHandler_Handle_MerchantFeeAddedToTransactionEvent_EventHasNoSettlementDueDate_EventIsHandled() { - TransactionDomainEventHandler transactionDomainEventHandler = new TransactionDomainEventHandler(this.TransactionAggregateManager.Object, - this.FeeCalculationManager.Object, - this.EstateClient.Object, - this.SecurityServiceClient.Object, - this.TransactionReceiptBuilder.Object, - this.MessagingServiceClient.Object, - this.SettlementAggregateRepository.Object); - - await transactionDomainEventHandler.Handle(TestData.MerchantFeeAddedToTransactionEvent(DateTime.MinValue), CancellationToken.None); + await this.TransactionDomainEventHandler.Handle(TestData.MerchantFeeAddedToTransactionEvent(DateTime.MinValue), CancellationToken.None); } } } diff --git a/TransactionProcessor.BusinessLogic.Tests/Services/SettlementDomainServiceTests.cs b/TransactionProcessor.BusinessLogic.Tests/Services/SettlementDomainServiceTests.cs index 4a534569..e0e54481 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Services/SettlementDomainServiceTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Services/SettlementDomainServiceTests.cs @@ -14,26 +14,39 @@ using Shared.Logger; using Shouldly; using Testing; + using TransactionAggregate; using Xunit; public class SettlementDomainServiceTests { - [Fact] - public async Task TransactionDomainService_ProcessSettlement_SettlementIsProcessed() - { + private Mock> transactionAggregateRepository; + + private Mock> settlementAggregateRepository; + + private SettlementDomainService settlementDomainService; + + public SettlementDomainServiceTests() { + this.transactionAggregateRepository = + new Mock>(); + this.settlementAggregateRepository = + new Mock>(); + + this.settlementDomainService = + new SettlementDomainService(this.transactionAggregateRepository.Object, settlementAggregateRepository.Object); + IConfigurationRoot configurationRoot = new ConfigurationBuilder().AddInMemoryCollection(TestData.DefaultAppSettings).Build(); ConfigurationReader.Initialise(configurationRoot); Logger.Initialise(NullLogger.Instance); + } - Mock transactionAggregateManager = new Mock(); - Mock> settlementAggregateRepository = - new Mock>(); + [Fact] + public async Task TransactionDomainService_ProcessSettlement_SettlementIsProcessed() + { settlementAggregateRepository.Setup(s => s.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetSettlementAggregateWithPendingMerchantFees(10)); - - SettlementDomainService settlementDomainService= - new SettlementDomainService(transactionAggregateManager.Object, settlementAggregateRepository.Object); + this.transactionAggregateRepository.Setup(s => s.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); ProcessSettlementResponse response = await settlementDomainService.ProcessSettlement(TestData.SettlementDate, TestData.EstateId, @@ -48,21 +61,9 @@ public async Task TransactionDomainService_ProcessSettlement_SettlementIsProcess [Fact] public async Task TransactionDomainService_ProcessSettlement_SettlementAggregateNotCreated_NothingProcessed() { - IConfigurationRoot configurationRoot = new ConfigurationBuilder().AddInMemoryCollection(TestData.DefaultAppSettings).Build(); - ConfigurationReader.Initialise(configurationRoot); - - Logger.Initialise(NullLogger.Instance); - - Mock transactionAggregateManager = new Mock(); - Mock> settlementAggregateRepository = - new Mock>(); settlementAggregateRepository.Setup(s => s.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetEmptySettlementAggregate); - - SettlementDomainService settlementDomainService = - new SettlementDomainService(transactionAggregateManager.Object, - settlementAggregateRepository.Object); - + ProcessSettlementResponse response = await settlementDomainService.ProcessSettlement(TestData.SettlementDate, TestData.EstateId, CancellationToken.None); @@ -76,21 +77,9 @@ public async Task TransactionDomainService_ProcessSettlement_SettlementAggregate [Fact] public async Task TransactionDomainService_ProcessSettlement_SettlementAggregateNoFeesToSettles_NothingProcessed() { - IConfigurationRoot configurationRoot = new ConfigurationBuilder().AddInMemoryCollection(TestData.DefaultAppSettings).Build(); - ConfigurationReader.Initialise(configurationRoot); - - Logger.Initialise(NullLogger.Instance); - - Mock transactionAggregateManager = new Mock(); - Mock> settlementAggregateRepository = - new Mock>(); settlementAggregateRepository.Setup(s => s.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetCreatedSettlementAggregate); - SettlementDomainService settlementDomainService = - new SettlementDomainService(transactionAggregateManager.Object, - settlementAggregateRepository.Object); - ProcessSettlementResponse response = await settlementDomainService.ProcessSettlement(TestData.SettlementDate, TestData.EstateId, CancellationToken.None); @@ -104,28 +93,9 @@ public async Task TransactionDomainService_ProcessSettlement_SettlementAggregate [Fact] public async Task TransactionDomainService_ProcessSettlement_AddSettledFeeThrownException_SettlementProcessed() { - IConfigurationRoot configurationRoot = new ConfigurationBuilder().AddInMemoryCollection(TestData.DefaultAppSettings).Build(); - ConfigurationReader.Initialise(configurationRoot); - - Logger.Initialise(NullLogger.Instance); - - Mock transactionAggregateManager = new Mock(); - transactionAggregateManager.Setup(t => t.AddSettledFee(It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny())).ThrowsAsync(new Exception()); - - Mock> settlementAggregateRepository = - new Mock>(); settlementAggregateRepository.Setup(s => s.GetLatestVersion(It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.GetSettlementAggregateWithPendingMerchantFees(10)); - SettlementDomainService settlementDomainService = - new SettlementDomainService(transactionAggregateManager.Object, - settlementAggregateRepository.Object); - ProcessSettlementResponse response = await settlementDomainService.ProcessSettlement(TestData.SettlementDate, TestData.EstateId, CancellationToken.None); diff --git a/TransactionProcessor.BusinessLogic.Tests/Services/TransactionAggregateManagerTests.cs b/TransactionProcessor.BusinessLogic.Tests/Services/TransactionAggregateManagerTests.cs deleted file mode 100644 index c07c2ee4..00000000 --- a/TransactionProcessor.BusinessLogic.Tests/Services/TransactionAggregateManagerTests.cs +++ /dev/null @@ -1,300 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace TransactionProcessor.BusinessLogic.Tests.Services -{ - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using BusinessLogic.Services; - using Microsoft.Extensions.Logging.Abstractions; - using Models; - using Moq; - using Shared.DomainDrivenDesign.EventSourcing; - using Shared.EventStore.Aggregate; - using Shared.EventStore.EventStore; - using Shared.Logger; - using Shouldly; - using Testing; - using TransactionAggregate; - using Xunit; - using NullLogger = Shared.Logger.NullLogger; - - public class TransactionAggregateManagerTests - { - public TransactionAggregateManagerTests() { - Logger.Initialise(new NullLogger()); - } - - [Fact] - public async Task TransactionAggregateManager_AuthoriseTransaction_TransactionAuthorised() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetStartedTransactionAggregate()); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.AuthoriseTransaction(TestData.EstateId, - TestData.TransactionId, - TestData.OperatorIdentifier1, - TestData.OperatorResponse, - TestData.TransactionResponseCodeSuccess, - TestData.ResponseMessage, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_AuthoriseTransactionLocally_TransactionLocallyAuthorised() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetStartedTransactionAggregate()); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.AuthoriseTransactionLocally(TestData.EstateId, - TestData.TransactionId, - TestData.AuthorisationCode, - (TestData.ResponseMessage, TestData.TransactionResponseCodeSuccess), - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_DeclineTransaction_TransactionDeclined() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetStartedTransactionAggregate()); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.DeclineTransaction(TestData.EstateId, - TestData.TransactionId, - TestData.OperatorIdentifier1, - TestData.OperatorResponse, - TestData.TransactionResponseCodeDeclinedByOperator, - TestData.ResponseMessage, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_DeclineTransactionLocally_TransactionLocallyDeclined() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetStartedTransactionAggregate()); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.DeclineTransactionLocally(TestData.EstateId, - TestData.TransactionId, - (TestData.ResponseMessage, TestData.TransactionResponseCodeSuccess), - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_GetAggregate_AggregateReturned() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCompletedLogonTransactionAggregate); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - TransactionAggregate result = await transactionAggregateManager.GetAggregate(TestData.EstateId, - TestData.TransactionId, - CancellationToken.None); - - result.ShouldNotBeNull(); - } - - [Fact] - public async Task TransactionAggregateManager_RecordAdditionalRequestData_AdditionalRequestDataRecorded() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetStartedTransactionAggregate()); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.RecordAdditionalRequestData(TestData.EstateId, - TestData.TransactionId, - TestData.OperatorIdentifier1, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_RecordAdditionalRequestData_NullAdditionalRequestData_NoActionPerformed() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetStartedTransactionAggregate()); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.RecordAdditionalRequestData(TestData.EstateId, - TestData.TransactionId, - TestData.OperatorIdentifier1, - TestData.NullAdditionalTransactionMetaData, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_RecordAdditionalRequestData_EmptyAdditionalRequestData_NoActionPerformed() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetStartedTransactionAggregate()); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.RecordAdditionalRequestData(TestData.EstateId, - TestData.TransactionId, - TestData.OperatorIdentifier1, - TestData.EmptyAdditionalTransactionMetaData, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_RecordAdditionalResponseData_AdditionalResponseDataRecorded() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetStartedTransactionAggregate()); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.RecordAdditionalResponseData(TestData.EstateId, - TestData.TransactionId, - TestData.OperatorIdentifier1, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_RecordAdditionalResponseData_NullAdditionalResponseData_NoActionPerformed() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetStartedTransactionAggregate()); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.RecordAdditionalResponseData(TestData.EstateId, - TestData.TransactionId, - TestData.OperatorIdentifier1, - TestData.NullAdditionalTransactionMetaData, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_RecordAdditionalResponseData_EmptyAdditionalResponseData_NoActionPerformed() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetStartedTransactionAggregate()); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.RecordAdditionalResponseData(TestData.EstateId, - TestData.TransactionId, - TestData.OperatorIdentifier1, - TestData.EmptyAdditionalTransactionMetaData, - CancellationToken.None); - } - - [Theory] - [InlineData(TransactionType.Logon)] - [InlineData(TransactionType.Sale)] - public async Task TransactionAggregateManager_StartTransaction_TransactionStarted(TransactionType transactionType) - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEmptyTransactionAggregate); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.StartTransaction(TestData.TransactionId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - transactionType, - TestData.TransactionReference, - TestData.EstateId, - TestData.MerchantId, - TestData.DeviceIdentifier, - TestData.TransactionAmount, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_CompleteTransaction_TransactionCompleted() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetLocallyAuthorisedTransactionAggregate); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.CompleteTransaction(TestData.EstateId, - TestData.TransactionId, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_RequestEmailReceipt_EmailRecieptRequested() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCompletedLogonTransactionAggregate); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.RequestEmailReceipt(TestData.EstateId, - TestData.TransactionId, - TestData.CustomerEmailAddress, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_ResendReceipt_EmailRecieptResendRequested() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionWithReceiptRequestedAggregate); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.ResendReceipt(TestData.EstateId, - TestData.TransactionId, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_AddProductDetails_ProductDetailsAddedToTransaction() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetStartedTransactionAggregate()); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.AddProductDetails(TestData.EstateId, - TestData.TransactionId, - TestData.ContractId, - TestData.ProductId, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_AddTransactionSource_TransactionSourceAddedToTransaction() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.AddTransactionSource(TestData.EstateId, - TestData.TransactionId, - (TransactionSource)TestData.TransactionSource, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_AddFee_FeeAddedToTransaction() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.AddFee(TestData.EstateId, - TestData.TransactionId, - TestData.CalculatedFeeServiceProviderFee, - CancellationToken.None); - } - - [Fact] - public async Task TransactionAggregateManager_AddSettledFee_FeeAddedToTransaction() - { - Mock> aggregateRepository = new Mock>(); - aggregateRepository.Setup(a => a.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); - TransactionAggregateManager transactionAggregateManager = new TransactionAggregateManager(aggregateRepository.Object); - - await transactionAggregateManager.AddSettledFee(TestData.EstateId, - TestData.TransactionId, - TestData.CalculatedFeeMerchantFee2, - TestData.TransactionFeeSettlementDueDate, - TestData.TransactionFeeSettledDateTime, - CancellationToken.None); - } - } -} diff --git a/TransactionProcessor.BusinessLogic.Tests/Services/TransactionDomainServiceTests.cs b/TransactionProcessor.BusinessLogic.Tests/Services/TransactionDomainServiceTests.cs index ef3066b5..10e7ddc6 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Services/TransactionDomainServiceTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Services/TransactionDomainServiceTests.cs @@ -1,27 +1,23 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace TransactionProcessor.BusinessLogic.Tests.Services +namespace TransactionProcessor.BusinessLogic.Tests.Services { + using System; + using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using BusinessLogic.OperatorInterfaces; using BusinessLogic.Services; using EstateManagement.Client; + using EstateManagement.DataTransferObjects.Requests; using EstateManagement.DataTransferObjects.Responses; using Microsoft.Extensions.Configuration; using Models; using Moq; - using OperatorInterfaces; using ProjectionEngine.Repository; using ProjectionEngine.State; using ReconciliationAggregate; using SecurityService.Client; - using SecurityService.DataTransferObjects.Responses; using Shared.DomainDrivenDesign.EventSourcing; using Shared.EventStore.Aggregate; - using Shared.EventStore.EventStore; using Shared.General; using Shared.Logger; using Shouldly; @@ -31,19 +27,25 @@ namespace TransactionProcessor.BusinessLogic.Tests.Services public class TransactionDomainServiceTests { - private Mock transactionAggregateManager = null; + #region Fields + + private readonly Mock estateClient; + + private readonly Mock operatorProxy; - private Mock estateClient = null; + private readonly Mock> reconciliationAggregateRepository; - private Mock securityServiceClient = null; + private readonly Mock securityServiceClient; - private Mock operatorProxy = null; + private readonly Mock> stateRepository; - private TransactionDomainService transactionDomainService = null; + private readonly Mock> transactionAggregateRepository; - private Mock> stateRepository; + private readonly TransactionDomainService transactionDomainService; - private Mock> reconciliationAggregateRepository = null; + #endregion + + #region Constructors public TransactionDomainServiceTests() { IConfigurationRoot configurationRoot = new ConfigurationBuilder().AddInMemoryCollection(TestData.DefaultAppSettings).Build(); @@ -51,109 +53,96 @@ public TransactionDomainServiceTests() { Logger.Initialise(NullLogger.Instance); - transactionAggregateManager = new Mock(); - estateClient = new Mock(); - securityServiceClient = new Mock(); - operatorProxy = new Mock(); - reconciliationAggregateRepository = new Mock>(); - Func operatorProxyResolver = (operatorName) => { return operatorProxy.Object; }; - stateRepository = new Mock>(); - transactionDomainService = new TransactionDomainService(transactionAggregateManager.Object, - estateClient.Object, - securityServiceClient.Object, - operatorProxyResolver, - reconciliationAggregateRepository.Object, - stateRepository.Object); + this.transactionAggregateRepository = new Mock>(); + this.estateClient = new Mock(); + this.securityServiceClient = new Mock(); + this.operatorProxy = new Mock(); + this.reconciliationAggregateRepository = new Mock>(); + Func operatorProxyResolver = operatorName => { return this.operatorProxy.Object; }; + this.stateRepository = new Mock>(); + this.transactionDomainService = new TransactionDomainService(this.transactionAggregateRepository.Object, + this.estateClient.Object, + this.securityServiceClient.Object, + operatorProxyResolver, + this.reconciliationAggregateRepository.Object, + this.stateRepository.Object); } - [Fact] - public async Task TransactionDomainService_ProcessReconciliationTransaction_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - - reconciliationAggregateRepository.Setup(r => r.GetLatestVersion(It.IsAny(), It.IsAny())) - .ReturnsAsync(new ReconciliationAggregate()); - - ProcessReconciliationTransactionResponse response = await transactionDomainService.ProcessReconciliationTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.DeviceIdentifier, - TestData.TransactionDateTime, - TestData.ReconciliationTransactionCount, - TestData.ReconciliationTransactionValue, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.Success); - } + #endregion + + #region Methods [Fact] - public async Task TransactionDomainService_ProcessReconciliationTransaction_IncorrectDevice_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - - reconciliationAggregateRepository.Setup(r => r.GetLatestVersion(It.IsAny(), It.IsAny())) - .ReturnsAsync(new ReconciliationAggregate()); - - ProcessReconciliationTransactionResponse response = await transactionDomainService.ProcessReconciliationTransaction(TestData.TransactionId, + public async Task TransactionDomainService_ProcessLogonTransaction_LogonFailed_TransactionIsProcessed() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Estate Not Found"))); + + this.transactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEmptyTransactionAggregate); + + this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionState); + + ProcessLogonTransactionResponse response = await this.transactionDomainService.ProcessLogonTransaction(TestData.TransactionId, TestData.EstateId, TestData.MerchantId, - TestData.DeviceIdentifier1, TestData.TransactionDateTime, - TestData.ReconciliationTransactionCount, - TestData.ReconciliationTransactionValue, + TestData.TransactionNumber, + TestData.DeviceIdentifier, CancellationToken.None); - this.ValidateResponse(response, TransactionResponseCode.InvalidDeviceIdentifier); + response.EstateId.ShouldBe(TestData.EstateId); + response.MerchantId.ShouldBe(TestData.MerchantId); + response.ResponseCode.ShouldNotBe("0000"); + response.ResponseMessage.ShouldNotBe("SUCCESS"); + response.TransactionId.ShouldBe(TestData.TransactionId); } - [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task TransactionDomainService_ProcessReconciliationTransaction_MerchantHasNoDevices_TransactionIsProcessed(Boolean deviceListIsNull) - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); + [Fact] + public async Task TransactionDomainService_ProcessLogonTransaction_TransactionIsProcessed() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - MerchantResponse merchantResponse = deviceListIsNull ? TestData.GetMerchantResponseWithNullDevices : TestData.GetMerchantResponseWithNoDevices; - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(merchantResponse); + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - reconciliationAggregateRepository.Setup(r => r.GetLatestVersion(It.IsAny(), It.IsAny())) - .ReturnsAsync(new ReconciliationAggregate()); + this.transactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEmptyTransactionAggregate); + + this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionState); - ProcessReconciliationTransactionResponse response = await transactionDomainService.ProcessReconciliationTransaction(TestData.TransactionId, + ProcessLogonTransactionResponse response = await this.transactionDomainService.ProcessLogonTransaction(TestData.TransactionId, TestData.EstateId, TestData.MerchantId, - TestData.DeviceIdentifier1, TestData.TransactionDateTime, - TestData.ReconciliationTransactionCount, - TestData.ReconciliationTransactionValue, + TestData.TransactionNumber, + TestData.DeviceIdentifier, CancellationToken.None); - this.ValidateResponse(response, TransactionResponseCode.NoValidDevices); + response.EstateId.ShouldBe(TestData.EstateId); + response.MerchantId.ShouldBe(TestData.MerchantId); + response.ResponseCode.ShouldBe("0000"); + response.ResponseMessage.ShouldBe("SUCCESS"); + response.TransactionId.ShouldBe(TestData.TransactionId); } [Fact] - public async Task TransactionDomainService_ProcessReconciliationTransaction_InvalidEstate_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Estate"))); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + public async Task TransactionDomainService_ProcessReconciliationTransaction_TransactionIsProcessed() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - reconciliationAggregateRepository.Setup(r => r.GetLatestVersion(It.IsAny(), It.IsAny())) - .ReturnsAsync(new ReconciliationAggregate()); + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - ProcessReconciliationTransactionResponse response = await transactionDomainService.ProcessReconciliationTransaction(TestData.TransactionId, + this.reconciliationAggregateRepository.Setup(r => r.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(new ReconciliationAggregate()); + + ProcessReconciliationTransactionResponse response = await this.transactionDomainService.ProcessReconciliationTransaction(TestData.TransactionId, TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier, @@ -162,22 +151,24 @@ public async Task TransactionDomainService_ProcessReconciliationTransaction_Inva TestData.ReconciliationTransactionValue, CancellationToken.None); - this.ValidateResponse(response, TransactionResponseCode.InvalidEstateId); + response.EstateId.ShouldBe(TestData.EstateId); + response.MerchantId.ShouldBe(TestData.MerchantId); + response.ResponseCode.ShouldBe("0000"); + response.ResponseMessage.ShouldBe("SUCCESS"); + response.TransactionId.ShouldBe(TestData.TransactionId); } [Fact] - public async Task TransactionDomainService_ProcessReconciliationTransaction_InvalidMerchant_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Merchant"))); - - reconciliationAggregateRepository.Setup(r => r.GetLatestVersion(It.IsAny(), It.IsAny())) - .ReturnsAsync(new ReconciliationAggregate()); + public async Task TransactionDomainService_ProcessReconciliationTransaction_ValidationFailed_TransactionIsProcessed() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - ProcessReconciliationTransactionResponse response = await transactionDomainService.ProcessReconciliationTransaction(TestData.TransactionId, + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Merchant"))); + + this.reconciliationAggregateRepository.Setup(r => r.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(new ReconciliationAggregate()); + + ProcessReconciliationTransactionResponse response = await this.transactionDomainService.ProcessReconciliationTransaction(TestData.TransactionId, TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier, @@ -186,893 +177,1045 @@ public async Task TransactionDomainService_ProcessReconciliationTransaction_Inva TestData.ReconciliationTransactionValue, CancellationToken.None); - this.ValidateResponse(response, TransactionResponseCode.InvalidMerchantId); + response.EstateId.ShouldBe(TestData.EstateId); + response.MerchantId.ShouldBe(TestData.MerchantId); + response.ResponseCode.ShouldNotBe("0000"); + response.ResponseMessage.ShouldNotBe("SUCCESS"); + response.TransactionId.ShouldBe(TestData.TransactionId); } [Fact] - public async Task TransactionDomainService_ProcessLogonTransaction_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetCompletedLogonTransactionAggregate); + public async Task TransactionDomainService_ProcessSaleTransaction_DeclinedByOperator_TransactionIsProcessed() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantContractResponses); + + this.transactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEmptyTransactionAggregate); + + this.operatorProxy.Setup(o => o.ProcessSaleMessage(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())).ReturnsAsync(new OperatorResponse { + ResponseMessage = TestData.OperatorResponseMessage, + IsSuccessful = false, + AuthorisationCode = + TestData.OperatorAuthorisationCode, + TransactionId = TestData.OperatorTransactionId, + ResponseCode = TestData.ResponseCode + }); + + this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionState); + + ProcessSaleTransactionResponse response = await this.transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, + TestData.EstateId, + TestData.MerchantId, + TestData.TransactionDateTime, + TestData.TransactionNumber, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.CustomerEmailAddress, + TestData + .AdditionalTransactionMetaDataForMobileTopup(), + TestData.ContractId, + TestData.ProductId, + TestData.TransactionSource, + CancellationToken.None); - ProcessLogonTransactionResponse response = await transactionDomainService.ProcessLogonTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.Success); + response.EstateId.ShouldBe(TestData.EstateId); + response.MerchantId.ShouldBe(TestData.MerchantId); + response.ResponseCode.ShouldNotBe("0000"); + response.ResponseMessage.ShouldNotBe("SUCCESS"); + response.TransactionId.ShouldBe(TestData.TransactionId); } [Fact] - public async Task TransactionDomainService_ProcessLogonTransaction_MerchantWithNullDevices_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithNullDevices); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetCompletedLogonTransactionAggregate); + public async Task TransactionDomainService_ProcessSaleTransaction_EstateValidationFailed_TransactionIsProcessed() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("", new KeyNotFoundException())); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantContractResponses); + + this.transactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEmptyTransactionAggregate); + + this.operatorProxy.Setup(o => o.ProcessSaleMessage(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())).ReturnsAsync(new OperatorResponse { + ResponseMessage = TestData.OperatorResponseMessage, + IsSuccessful = true, + AuthorisationCode = + TestData.OperatorAuthorisationCode, + TransactionId = TestData.OperatorTransactionId, + ResponseCode = TestData.ResponseCode + }); + + this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionState); + + ProcessSaleTransactionResponse response = await this.transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, + TestData.EstateId, + TestData.MerchantId, + TestData.TransactionDateTime, + TestData.TransactionNumber, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.CustomerEmailAddress, + TestData + .AdditionalTransactionMetaDataForMobileTopup(), + TestData.ContractId, + TestData.ProductId, + TestData.TransactionSource, + CancellationToken.None); - ProcessLogonTransactionResponse response = await transactionDomainService.ProcessLogonTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.Success); + response.EstateId.ShouldBe(TestData.EstateId); + response.MerchantId.ShouldBe(TestData.MerchantId); + response.ResponseCode.ShouldNotBe("0000"); + response.ResponseMessage.ShouldNotBe("SUCCESS"); + response.TransactionId.ShouldBe(TestData.TransactionId); } [Fact] - public async Task TransactionDomainService_ProcessLogonTransaction_MerchantWithNoDevices_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithNoDevices); + public async Task TransactionDomainService_ProcessSaleTransaction_OperatorProxyThrowsException_TransactionIsProcessed() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantContractResponses); + + this.transactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEmptyTransactionAggregate); + + this.operatorProxy.Setup(o => o.ProcessSaleMessage(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())).ThrowsAsync(new Exception("Operator Error")); + + this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionState); + + ProcessSaleTransactionResponse response = await this.transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, + TestData.EstateId, + TestData.MerchantId, + TestData.TransactionDateTime, + TestData.TransactionNumber, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.CustomerEmailAddress, + TestData + .AdditionalTransactionMetaDataForMobileTopup(), + TestData.ContractId, + TestData.ProductId, + TestData.TransactionSource, + CancellationToken.None); - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetCompletedLogonTransactionAggregate); - - ProcessLogonTransactionResponse response = await transactionDomainService.ProcessLogonTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.Success); + response.EstateId.ShouldBe(TestData.EstateId); + response.MerchantId.ShouldBe(TestData.MerchantId); + response.ResponseCode.ShouldBe("0000"); + response.ResponseMessage.ShouldBe("SUCCESS"); + response.TransactionId.ShouldBe(TestData.TransactionId); } [Fact] - public async Task TransactionDomainService_ProcessLogonTransaction_IncorrectDevice_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + public async Task TransactionDomainService_ProcessSaleTransaction_TransactionIsProcessed() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantContractResponses); + + this.transactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEmptyTransactionAggregate); + + this.operatorProxy.Setup(o => o.ProcessSaleMessage(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny())).ReturnsAsync(new OperatorResponse { + ResponseMessage = TestData.OperatorResponseMessage, + IsSuccessful = true, + AuthorisationCode = + TestData.OperatorAuthorisationCode, + TransactionId = TestData.OperatorTransactionId, + ResponseCode = TestData.ResponseCode + }); + + this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionState); + + ProcessSaleTransactionResponse response = await this.transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, + TestData.EstateId, + TestData.MerchantId, + TestData.TransactionDateTime, + TestData.TransactionNumber, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.CustomerEmailAddress, + TestData + .AdditionalTransactionMetaDataForMobileTopup(), + TestData.ContractId, + TestData.ProductId, + TestData.TransactionSource, + CancellationToken.None); - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(TransactionResponseCode.InvalidDeviceIdentifier)); - - ProcessLogonTransactionResponse response = await transactionDomainService.ProcessLogonTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier1, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.InvalidDeviceIdentifier); + response.EstateId.ShouldBe(TestData.EstateId); + response.MerchantId.ShouldBe(TestData.MerchantId); + response.ResponseCode.ShouldBe("0000"); + response.ResponseMessage.ShouldBe("SUCCESS"); + response.TransactionId.ShouldBe(TestData.TransactionId); + } + + [Fact] + public async Task TransactionDomainService_ResendTransactionReceipt_TransactionReceiptResendIsRequested() { + this.transactionAggregateRepository.Setup(t => t.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionWithReceiptRequestedAggregate); + + Should.NotThrow(async () => { + await this.transactionDomainService.ResendTransactionReceipt(TestData.TransactionId, TestData.EstateId, CancellationToken.None); + }); } [Fact] - public async Task TransactionDomainService_ProcessLogonTransaction_InvalidEstate_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Estate"))); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(TransactionResponseCode.InvalidEstateId)); - - ProcessLogonTransactionResponse response = await transactionDomainService.ProcessLogonTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier1, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.InvalidEstateId); + public async Task TransactionDomainService_ValidateLogonTransaction_DeviceNotRegisteredToMerchant_ResponseIsInvalidDeviceIdentifier() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateLogonTransaction(TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier1, CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidDeviceIdentifier); } [Fact] - public async Task TransactionDomainService_ProcessLogonTransaction_InvalidMerchant_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetEmptyMerchantResponse); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(TransactionResponseCode.InvalidMerchantId)); - - ProcessLogonTransactionResponse response = await transactionDomainService.ProcessLogonTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier1, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.InvalidMerchantId); + public async Task TransactionDomainService_ValidateLogonTransaction_EstateClientGetEstateThrewOtherException_ResponseIsUnknownFailure() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Exception")); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateLogonTransaction(TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier, CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.UnknownFailure); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_SuccessfulOperatorResponse_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantContractResponses); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); - - operatorProxy.Setup(o => o.ProcessSaleMessage(It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())).ReturnsAsync(new OperatorResponse - { - ResponseMessage = TestData.OperatorResponseMessage, - IsSuccessful = true, - AuthorisationCode = TestData.OperatorAuthorisationCode, - TransactionId = TestData.OperatorTransactionId, - ResponseCode = TestData.ResponseCode - }); + public async Task TransactionDomainService_ValidateLogonTransaction_EstateClientGetMerchantThrewOtherException_ResponseIsUnknownFailure() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantBalanceProjectionState); + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception")); - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.Success); + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateLogonTransaction(TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier, CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.UnknownFailure); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_InvalidTransactionAmountResponse_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(TransactionResponseCode.InvalidSaleTransactionAmount)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(amount:"0.00"), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.InvalidSaleTransactionAmount); + public async Task TransactionDomainService_ValidateLogonTransaction_EstateNotFound_ResponseIsInvalidEstateId() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Estate"))); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateLogonTransaction(TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier, CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidEstateId); } - [Theory] - [InlineData("amount")] - [InlineData("Amount")] - [InlineData("AMOUNT")] - public async Task TransactionDomainService_ProcessSaleTransaction_MetaDataCaseTests_Amount_TransactionIsProcessed(String amountFieldName) - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantContractResponses); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); - - operatorProxy.Setup(o => o.ProcessSaleMessage(It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())).ReturnsAsync(new OperatorResponse - { - ResponseMessage = TestData.OperatorResponseMessage, - IsSuccessful = true, - AuthorisationCode = TestData.OperatorAuthorisationCode, - TransactionId = TestData.OperatorTransactionId, - ResponseCode = TestData.ResponseCode - }); + [Fact] + public async Task TransactionDomainService_ValidateLogonTransaction_MerchantDeviceListEmpty_SuccessfulLogon() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithNoDevices); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateLogonTransaction(TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier, CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.Success); + this.estateClient.Verify(vf => vf.AddDeviceToMerchant(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), + Times.Once); + } - this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantBalanceProjectionState); + [Fact] + public async Task TransactionDomainService_ValidateLogonTransaction_MerchantDeviceListNull_SuccessfulLogon() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithNullDevices); + // TODO: Verify device was added... + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateLogonTransaction(TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier, CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.Success); + this.estateClient.Verify(vf => vf.AddDeviceToMerchant(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), + Times.Once); + } - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(amountName:amountFieldName), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.Success); + [Fact] + public async Task TransactionDomainService_ValidateLogonTransaction_MerchantNotFound_ResponseIsInvalidMerchantId() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Merchant"))); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateLogonTransaction(TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier, CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidMerchantId); } - [Theory] - [InlineData("customerAccountNumber")] - [InlineData("CustomerAccountNumber")] - [InlineData("CUSTOMERACCOUNTNUMBER")] - public async Task TransactionDomainService_ProcessSaleTransaction_MetaDataCaseTests_CustomerAccountNumber_TransactionIsProcessed(String customerAccountNumberFieldName) - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantContractResponses); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); - - operatorProxy.Setup(o => o.ProcessSaleMessage(It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())).ReturnsAsync(new OperatorResponse - { - ResponseMessage = TestData.OperatorResponseMessage, - IsSuccessful = true, - AuthorisationCode = TestData.OperatorAuthorisationCode, - TransactionId = TestData.OperatorTransactionId, - ResponseCode = TestData.ResponseCode - }); + [Fact] + public async Task TransactionDomainService_ValidateLogonTransaction_SuccessfulLogon() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantBalanceProjectionState); + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateLogonTransaction(TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier, CancellationToken.None); - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(customerAccountNumberName: customerAccountNumberFieldName), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.Success); + response.responseCode.ShouldBe(TransactionResponseCode.Success); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_FailedOperatorResponse_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantContractResponses); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetDeclinedTransactionAggregate(TransactionResponseCode.TransactionDeclinedByOperator)); - - operatorProxy.Setup(o => o.ProcessSaleMessage(It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())).ReturnsAsync(new OperatorResponse - { - ResponseMessage = TestData.DeclinedOperatorResponseMessage, - IsSuccessful = false, - ResponseCode = TestData.DeclinedOperatorResponseCode - }); + public async Task TransactionDomainService_ValidateReconciliationTransaction_DeviceNotRegisteredToMerchant_ResponseIsInvalidDeviceIdentifier() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantBalanceProjectionState); + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.TransactionDeclinedByOperator); + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateReconciliationTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.DeviceIdentifier1, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidDeviceIdentifier); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_MerchantWithNullDevices_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithNullDevices); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(TransactionResponseCode.NoValidDevices)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.NoValidDevices); + public async Task TransactionDomainService_ValidateReconciliationTransaction_EstateClientGetEstateThrewOtherException_ResponseIsUnknownFailure() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Exception")); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateReconciliationTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.DeviceIdentifier, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.UnknownFailure); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_MerchantWithNoDevices_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithNoDevices); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetDeclinedTransactionAggregate(TransactionResponseCode.NoValidDevices)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.NoValidDevices); + public async Task TransactionDomainService_ValidateReconciliationTransaction_EstateClientGetMerchantThrewOtherException_ResponseIsUnknownFailure() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception")); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateReconciliationTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.DeviceIdentifier, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.UnknownFailure); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_IncorrectDevice_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(TransactionResponseCode.InvalidDeviceIdentifier)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier1, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.InvalidDeviceIdentifier); + public async Task TransactionDomainService_ValidateReconciliationTransaction_EstateNotFound_ResponseIsInvalidEstateId() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Estate"))); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateReconciliationTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.DeviceIdentifier, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidEstateId); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_InvalidEstate_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Estate"))); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(TransactionResponseCode.InvalidEstateId)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier1, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.InvalidEstateId); + public async Task TransactionDomainService_ValidateReconciliationTransaction_MerchantDeviceListEmpty_ResponseIsResponseIsNoValidDevices() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithNoDevices); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateReconciliationTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.DeviceIdentifier, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.NoValidDevices); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_NotEnoughCredit_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantContractResponses); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetDeclinedTransactionAggregate(TransactionResponseCode.MerchantDoesNotHaveEnoughCredit)); + public async Task TransactionDomainService_ValidateReconciliationTransaction_MerchantDeviceListNull_ResponseIsResponseIsNoValidDevices() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithNullDevices); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateReconciliationTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.DeviceIdentifier, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.NoValidDevices); + } + + [Fact] + public async Task TransactionDomainService_ValidateReconciliationTransaction_MerchantNotFound_ResponseIsInvalidMerchantId() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Merchant"))); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateReconciliationTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.DeviceIdentifier, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidMerchantId); + } + + [Fact] + public async Task TransactionDomainService_ValidateReconciliationTransaction_SuccessfulReconciliation() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + + (String responseMessage, TransactionResponseCode responseCode) response = + await this.transactionDomainService.ValidateReconciliationTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.DeviceIdentifier, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.Success); + } + + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_DeviceNotRegisteredToMerchant_ResponseIsInvalidDeviceIdentifier() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier1, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidDeviceIdentifier); + } + + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_EstateClientGetEstateThrewOtherException_ResponseIsUnknownFailure() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Exception")); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.UnknownFailure); + } + + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_EstateClientGetMerchantThrewOtherException_ResponseIsUnknownFailure() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception")); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.UnknownFailure); + } + + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_EstateClientThrownOtherExceptionFoundOnGetContract_ResponseIsUnknownFailure() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception")); this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.MerchantBalanceProjectionState); - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.MerchantDoesNotHaveEnoughCredit); + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.UnknownFailure); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_InvalidMerchant_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Merchant"))); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(TransactionResponseCode.InvalidMerchantId)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier1, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.InvalidMerchantId); + public async Task TransactionDomainService_ValidateSaleTransaction_EstateFoundButHasNoOperators_ResponseIsInvalidEstateId() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithEmptyOperators); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.NoEstateOperators); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_EstateWithEmptyOperators_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithEmptyOperators); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(TransactionResponseCode.NoEstateOperators)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.NoEstateOperators); + public async Task TransactionDomainService_ValidateSaleTransaction_EstateFoundButHasNullOperators_ResponseIsInvalidEstateId() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithNullOperators); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.NoEstateOperators); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_EstateWithNullOperators_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithNullOperators); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(TransactionResponseCode.NoEstateOperators)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.NoEstateOperators); + public async Task TransactionDomainService_ValidateSaleTransaction_EstateFoundOperatorsNotConfiguredForEstate_ResponseIsOperatorNotValidForEstate() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier2, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.OperatorNotValidForEstate); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_OperatorNotSupportedByEstate_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetDeclinedTransactionAggregate(TransactionResponseCode.OperatorNotValidForEstate)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier2, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.OperatorNotValidForEstate); + public async Task TransactionDomainService_ValidateSaleTransaction_EstateNotFound_ResponseIsInvalidEstateId() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Estate"))); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidEstateId); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_MerchantWithEmptyOperators_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithEmptyOperators); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetDeclinedTransactionAggregate(TransactionResponseCode.NoMerchantOperators)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.NoMerchantOperators); + public async Task TransactionDomainService_ValidateSaleTransaction_InvalidContractId_ResponseIsInvalidContractIdValue() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + + this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionState); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + Guid.Empty, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidContractIdValue); } - [Theory] - [InlineData("00000000-0000-0000-0000-000000000000", TransactionResponseCode.InvalidContractIdValue)] - [InlineData("DB641DAF-B0C2-4CA5-B141-13882F3ACEFA", TransactionResponseCode.ContractNotValidForMerchant)] - public async Task TransactionDomainService_ProcessSaleTransaction_ContractId_TransactionIsProcessed(String contractId, TransactionResponseCode expectedResponseCode) - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantContractResponses); - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(expectedResponseCode)); + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_InvalidProductId_ResponseIsInvalidProductIdValue() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantContractResponses); this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.MerchantBalanceProjectionState); - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - Guid.Parse(contractId), - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, expectedResponseCode); + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + Guid.Empty, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidProductIdValue); } [Theory] - [InlineData("00000000-0000-0000-0000-000000000000", TransactionResponseCode.InvalidProductIdValue)] - [InlineData("DB641DAF-B0C2-4CA5-B141-13882F3ACEFA", TransactionResponseCode.ProductNotValidForMerchant)] - public async Task TransactionDomainService_ProcessSaleTransaction_ProductId_TransactionIsProcessed(String productId, - TransactionResponseCode expectedResponseCode) { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantContractResponses); - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(expectedResponseCode)); + [InlineData(0)] + [InlineData(-1)] + public async Task TransactionDomainService_ValidateSaleTransaction_InvalidTransactionAmount_ResponseIsInvalidSaleTransactionAmount(Decimal transactionAmount) { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + transactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidSaleTransactionAmount); + } + + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_MerchantDeviceListEmpty_ResponseIsNoValidDevices() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithNoDevices); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier1, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.NoValidDevices); + } + + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_MerchantDeviceListNull_ResponseIsNoValidDevices() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithNullDevices); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier1, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.NoValidDevices); + } + + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_MerchantDoesNotHaveSuppliedContract_ResponseIsContractNotValidForMerchant() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantContractResponses); this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.MerchantBalanceProjectionState); - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - Guid.Parse(productId), - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, expectedResponseCode); + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId1, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.ContractNotValidForMerchant); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_MerchantWithNullOperators_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithNullOperators); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetDeclinedTransactionAggregate(TransactionResponseCode.NoMerchantOperators)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.NoMerchantOperators); + public async Task TransactionDomainService_ValidateSaleTransaction_MerchantHasNoContracts_ResponseIsMerchantDoesNotHaveEnoughCredit() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(new List()); + + this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionState); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.MerchantHasNoContractsConfigured); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_OperatorNotSupportedByMerchant_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator2); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetDeclinedTransactionAggregate(TransactionResponseCode.OperatorNotValidForMerchant)); - - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.OperatorNotValidForMerchant); + public async Task TransactionDomainService_ValidateSaleTransaction_MerchantHasNullContracts_ResponseIsMerchantDoesNotHaveEnoughCredit() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + List contracts = null; + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(contracts); + + this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionState); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.MerchantHasNoContractsConfigured); } [Fact] - public async Task TransactionDomainService_ProcessSaleTransaction_ErrorInOperatorComms_TransactionIsProcessed() - { - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - - estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEstateResponseWithOperator1); - estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); - estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.MerchantContractResponses); - - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetLocallyDeclinedTransactionAggregate(TransactionResponseCode.OperatorCommsError)); - - operatorProxy.Setup(o => o.ProcessSaleMessage(It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny>(), - It.IsAny())).ThrowsAsync(new Exception("Comms Error")); + public async Task TransactionDomainService_ValidateSaleTransaction_MerchantNotEnoughCredit_ResponseIsMerchantDoesNotHaveEnoughCredit() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + + this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionStateNoCredit); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.MerchantDoesNotHaveEnoughCredit); + } + + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_MerchantNotFound_ResponseIsInvalidMerchantId() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Merchant"))); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidMerchantId); + } + + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_MerchantNotFoundOnGetContract_ResponseIsInvalidMerchantId() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Exception", new KeyNotFoundException("Invalid Merchant"))); this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.MerchantBalanceProjectionState); - ProcessSaleTransactionResponse response = await transactionDomainService.ProcessSaleTransaction(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorIdentifier1, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource, - CancellationToken.None); - - this.ValidateResponse(response, TransactionResponseCode.OperatorCommsError); + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.InvalidMerchantId); } [Fact] - public async Task TransactionDomainService_ResendTransactionReceipt_TransactionReceiptResendIsRequested() - { - transactionAggregateManager.Setup(t => t.GetAggregate(It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetCompletedAuthorisedSaleTransactionAggregate); - - Should.NotThrow(async () => { - await transactionDomainService.ResendTransactionReceipt(TestData.TransactionId, TestData.EstateId, CancellationToken.None); - }); + public async Task TransactionDomainService_ValidateSaleTransaction_MerchantOperatorListEmpty_ResponseIsNoMerchantOperators() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithEmptyOperators); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.NoMerchantOperators); + } + + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_MerchantOperatorListNull_ResponseIsNoMerchantOperators() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithNullOperators); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.NoMerchantOperators); } - private void ValidateResponse(ProcessLogonTransactionResponse response, - TransactionResponseCode transactionResponseCode) - { - response.ShouldNotBeNull(); - response.ResponseCode.ShouldBe(TestData.GetResponseCodeAsString(transactionResponseCode)); + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_OperatorNotConfiguredFroMerchant_ResponseIsOperatorNotValidForMerchant() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator2); - String messageToValidate = TestData.GetResponseCodeMessage(transactionResponseCode); - if (transactionResponseCode == TransactionResponseCode.Success) - { - messageToValidate = messageToValidate.ToUpper(); - } + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); - response.ResponseMessage.ShouldBe(messageToValidate); + response.responseCode.ShouldBe(TransactionResponseCode.OperatorNotValidForMerchant); } - private void ValidateResponse(ProcessSaleTransactionResponse response, - TransactionResponseCode transactionResponseCode) - { - response.ShouldNotBeNull(); - response.ResponseCode.ShouldBe(TestData.GetResponseCodeAsString(transactionResponseCode)); + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_ProductIdNotConfigured_ResponseIsProductNotValidForMerchant() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - String messageToValidate = TestData.GetResponseCodeMessage(transactionResponseCode); - if (transactionResponseCode == TransactionResponseCode.Success) - { - messageToValidate = messageToValidate.ToUpper(); - } + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantContractResponses); + + this.stateRepository.Setup(p => p.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionState); + + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId1, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); - response.ResponseMessage.ShouldBe(messageToValidate); + response.responseCode.ShouldBe(TransactionResponseCode.ProductNotValidForMerchant); } - private void ValidateResponse(ProcessReconciliationTransactionResponse response, - TransactionResponseCode transactionResponseCode) - { - response.ShouldNotBeNull(); - response.ResponseCode.ShouldBe(TestData.GetResponseCodeAsString(transactionResponseCode)); + [Fact] + public async Task TransactionDomainService_ValidateSaleTransaction_SuccessfulSale() { + this.securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); + + this.estateClient.Setup(e => e.GetEstate(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetEstateResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.GetMerchantResponseWithOperator1); + this.estateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantContractResponses); + + this.stateRepository.Setup(s => s.Load(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.MerchantBalanceProjectionState); + (String responseMessage, TransactionResponseCode responseCode) response = await this.transactionDomainService.ValidateSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ProductId, + TestData.DeviceIdentifier, + TestData.OperatorIdentifier1, + TestData.TransactionAmount, + CancellationToken.None); + + response.responseCode.ShouldBe(TransactionResponseCode.Success); } + + #endregion } -} +} \ No newline at end of file diff --git a/TransactionProcessor.BusinessLogic/AssemblyInfo.cs b/TransactionProcessor.BusinessLogic/AssemblyInfo.cs new file mode 100644 index 00000000..972bc71b --- /dev/null +++ b/TransactionProcessor.BusinessLogic/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("TransactionProcessor.BusinessLogic.Tests")] \ No newline at end of file diff --git a/TransactionProcessor.BusinessLogic/EventHandling/TransactionDomainEventHandler.cs b/TransactionProcessor.BusinessLogic/EventHandling/TransactionDomainEventHandler.cs index c296dcc4..d7b8945c 100644 --- a/TransactionProcessor.BusinessLogic/EventHandling/TransactionDomainEventHandler.cs +++ b/TransactionProcessor.BusinessLogic/EventHandling/TransactionDomainEventHandler.cs @@ -59,16 +59,13 @@ public class TransactionDomainEventHandler : IDomainEventHandler private readonly IAggregateRepository SettlementAggregateRepository; + private readonly IAggregateRepository TransactionAggregateRepository; + /// /// The token response /// private TokenResponse TokenResponse; - /// - /// The transaction aggregate manager - /// - private readonly ITransactionAggregateManager TransactionAggregateManager; - /// /// The transaction receipt builder /// @@ -78,14 +75,14 @@ public class TransactionDomainEventHandler : IDomainEventHandler #region Constructors - public TransactionDomainEventHandler(ITransactionAggregateManager transactionAggregateManager, + public TransactionDomainEventHandler(IAggregateRepository transactionAggregateRepository, IFeeCalculationManager feeCalculationManager, IEstateClient estateClient, ISecurityServiceClient securityServiceClient, ITransactionReceiptBuilder transactionReceiptBuilder, IMessagingServiceClient messagingServiceClient, IAggregateRepository settlementAggregateRepository) { - this.TransactionAggregateManager = transactionAggregateManager; + this.TransactionAggregateRepository = transactionAggregateRepository; this.FeeCalculationManager = feeCalculationManager; this.EstateClient = estateClient; this.SecurityServiceClient = securityServiceClient; @@ -148,7 +145,7 @@ private async Task GetToken(CancellationToken cancellationToken) private async Task HandleSpecificDomainEvent(TransactionHasBeenCompletedEvent domainEvent, CancellationToken cancellationToken) { TransactionAggregate transactionAggregate = - await this.TransactionAggregateManager.GetAggregate(domainEvent.EstateId, domainEvent.TransactionId, cancellationToken); + await this.TransactionAggregateRepository.GetLatestVersion(domainEvent.TransactionId, cancellationToken); if (transactionAggregate.IsAuthorised == false) { // Ignore not successful transactions @@ -194,7 +191,7 @@ private async Task HandleSpecificDomainEvent(TransactionHasBeenCompletedEvent do foreach (CalculatedFee calculatedFee in nonMerchantFees) { // Add Fee to the Transaction - await this.TransactionAggregateManager.AddFee(transactionAggregate.EstateId, transactionAggregate.AggregateId, calculatedFee, cancellationToken); + transactionAggregate.AddFee(calculatedFee); } // Now deal with merchant fees @@ -232,15 +229,13 @@ private async Task HandleSpecificDomainEvent(TransactionHasBeenCompletedEvent do if (merchant.SettlementSchedule == SettlementSchedule.Immediate) { // Add fees to transaction now if settlement is immediate - await this.TransactionAggregateManager.AddSettledFee(transactionAggregate.EstateId, - transactionAggregate.AggregateId, - calculatedFee, - DateTime.Now.Date, - DateTime.Now, - cancellationToken); + transactionAggregate.AddSettledFee(calculatedFee, + DateTime.Now.Date, + DateTime.Now); aggregate.ImmediatelyMarkFeeAsSettled(transactionAggregate.MerchantId, transactionAggregate.AggregateId, calculatedFee.FeeId); } + await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); await this.SettlementAggregateRepository.SaveChanges(aggregate, cancellationToken); } } @@ -250,7 +245,7 @@ private async Task HandleSpecificDomainEvent(CustomerEmailReceiptRequestedEvent this.TokenResponse = await this.GetToken(cancellationToken); TransactionAggregate transactionAggregate = - await this.TransactionAggregateManager.GetAggregate(domainEvent.EstateId, domainEvent.TransactionId, cancellationToken); + await this.TransactionAggregateRepository.GetLatestVersion(domainEvent.TransactionId, cancellationToken); MerchantResponse merchant = await this.EstateClient.GetMerchant(this.TokenResponse.AccessToken, domainEvent.EstateId, domainEvent.MerchantId, cancellationToken); diff --git a/TransactionProcessor.BusinessLogic/Services/ITransactionAggregateManager.cs b/TransactionProcessor.BusinessLogic/Services/ITransactionAggregateManager.cs deleted file mode 100644 index e572355a..00000000 --- a/TransactionProcessor.BusinessLogic/Services/ITransactionAggregateManager.cs +++ /dev/null @@ -1,110 +0,0 @@ -namespace TransactionProcessor.BusinessLogic.Services -{ - using System; - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using Models; - using OperatorInterfaces; - using TransactionAggregate; - - /// - /// - /// - public interface ITransactionAggregateManager - { - #region Methods - - Task AddFee(Guid estateId, - Guid transactionId, - CalculatedFee calculatedFee, - CancellationToken cancellationToken); - - Task AddProductDetails(Guid estateId, - Guid transactionId, - Guid contractId, - Guid productId, - CancellationToken cancellationToken); - - Task AddSettledFee(Guid estateId, - Guid transactionId, - CalculatedFee calculatedFee, - DateTime settlementDueDate, - DateTime settledDateTime, - CancellationToken cancellationToken); - - Task AddTransactionSource(Guid estateId, - Guid transactionId, - TransactionSource transactionSource, - CancellationToken cancellationToken); - - Task AuthoriseTransaction(Guid estateId, - Guid transactionId, - String operatorIdentifier, - OperatorResponse operatorResponse, - TransactionResponseCode transactionResponseCode, - String responseMessage, - CancellationToken cancellationToken); - - Task AuthoriseTransactionLocally(Guid estateId, - Guid transactionId, - String authorisationCode, - (String responseMessage, TransactionResponseCode responseCode) validationResult, - CancellationToken cancellationToken); - - Task CompleteTransaction(Guid estateId, - Guid transactionId, - CancellationToken cancellationToken); - - Task DeclineTransaction(Guid estateId, - Guid transactionId, - String operatorIdentifier, - OperatorResponse operatorResponse, - TransactionResponseCode transactionResponseCode, - String responseMessage, - CancellationToken cancellationToken); - - Task DeclineTransactionLocally(Guid estateId, - Guid transactionId, - (String responseMessage, TransactionResponseCode responseCode) validationResult, - CancellationToken cancellationToken); - - Task GetAggregate(Guid estateId, - Guid transactionId, - CancellationToken cancellationToken); - - Task RecordAdditionalRequestData(Guid estateId, - Guid transactionId, - String operatorIdentifier, - Dictionary additionalTransactionRequestMetadata, - CancellationToken cancellationToken); - - Task RecordAdditionalResponseData(Guid estateId, - Guid transactionId, - String operatorIdentifier, - Dictionary additionalTransactionResponseMetadata, - CancellationToken cancellationToken); - - Task RequestEmailReceipt(Guid estateId, - Guid transactionId, - String customerEmailAddress, - CancellationToken cancellationToken); - - Task ResendReceipt(Guid estateId, - Guid transactionId, - CancellationToken cancellationToken); - - Task StartTransaction(Guid transactionId, - DateTime transactionDateTime, - String transactionNumber, - TransactionType transactionType, - String transactionReference, - Guid estateId, - Guid merchantId, - String deviceIdentifier, - Decimal? transactionAmount, - CancellationToken cancellationToken); - - #endregion - } -} \ No newline at end of file diff --git a/TransactionProcessor.BusinessLogic/Services/SettlementDomainService.cs b/TransactionProcessor.BusinessLogic/Services/SettlementDomainService.cs index 049b7f95..925a480c 100644 --- a/TransactionProcessor.BusinessLogic/Services/SettlementDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/SettlementDomainService.cs @@ -1,6 +1,7 @@ namespace TransactionProcessor.BusinessLogic.Services { using System; + using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Common; @@ -9,11 +10,11 @@ using Shared.DomainDrivenDesign.EventSourcing; using Shared.EventStore.Aggregate; using Shared.Logger; + using TransactionAggregate; public class SettlementDomainService : ISettlementDomainService { - private readonly ITransactionAggregateManager TransactionAggregateManager; - + private readonly IAggregateRepository TransactionAggregateRepository; private readonly IAggregateRepository SettlementAggregateRepository; public async Task ProcessSettlement(DateTime settlementDate, @@ -33,19 +34,20 @@ public async Task ProcessSettlement(DateTime settleme return response; } - var feesToBeSettled = settlementAggregate.GetFeesToBeSettled(); + List<(Guid transactionId, Guid merchantId, CalculatedFee calculatedFee)> feesToBeSettled = settlementAggregate.GetFeesToBeSettled(); response.NumberOfFeesPendingSettlement = feesToBeSettled.Count; + + foreach ((Guid transactionId, Guid merchantId, CalculatedFee calculatedFee) feeToSettle in feesToBeSettled) { try { - await this.TransactionAggregateManager.AddSettledFee(estateId, - feeToSettle.transactionId, - feeToSettle.calculatedFee, - settlementDate, - DateTime.Now, - cancellationToken); + TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(feeToSettle.transactionId, cancellationToken); + transactionAggregate.AddSettledFee(feeToSettle.calculatedFee, + settlementDate, + DateTime.Now); + await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); response.NumberOfFeesSuccessfullySettled++; response.NumberOfFeesPendingSettlement--; } @@ -61,10 +63,10 @@ await this.TransactionAggregateManager.AddSettledFee(estateId, return response; } - public SettlementDomainService(ITransactionAggregateManager transactionAggregateManager, + public SettlementDomainService(IAggregateRepository transactionAggregateRepository, IAggregateRepository settlementAggregateRepository) { - this.TransactionAggregateManager = transactionAggregateManager; + this.TransactionAggregateRepository = transactionAggregateRepository; this.SettlementAggregateRepository = settlementAggregateRepository; } } diff --git a/TransactionProcessor.BusinessLogic/Services/TransactionAggregateManager.cs b/TransactionProcessor.BusinessLogic/Services/TransactionAggregateManager.cs deleted file mode 100644 index 900278bd..00000000 --- a/TransactionProcessor.BusinessLogic/Services/TransactionAggregateManager.cs +++ /dev/null @@ -1,245 +0,0 @@ -namespace TransactionProcessor.BusinessLogic.Services -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using Models; - using Newtonsoft.Json; - using OperatorInterfaces; - using Shared.DomainDrivenDesign.EventSourcing; - using Shared.EventStore.Aggregate; - using Shared.Logger; - using TransactionAggregate; - - /// - /// - /// - /// - public class TransactionAggregateManager : ITransactionAggregateManager - { - #region Fields - - private readonly IAggregateRepository TransactionAggregateRepository; - - #endregion - - #region Constructors - - public TransactionAggregateManager(IAggregateRepository transactionAggregateRepository) { - this.TransactionAggregateRepository = transactionAggregateRepository; - } - - #endregion - - #region Methods - - public async Task AddFee(Guid estateId, - Guid transactionId, - CalculatedFee calculatedFee, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.AddFee(calculatedFee); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - - public async Task AddProductDetails(Guid estateId, - Guid transactionId, - Guid contractId, - Guid productId, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.AddProductDetails(contractId, productId); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - - public async Task AddSettledFee(Guid estateId, - Guid transactionId, - CalculatedFee calculatedFee, - DateTime settlementDueDate, - DateTime settledDateTime, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.AddSettledFee(calculatedFee, settlementDueDate, settledDateTime); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - - public async Task AddTransactionSource(Guid estateId, - Guid transactionId, - TransactionSource transactionSource, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.AddTransactionSource(transactionSource); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - - } - - public async Task AuthoriseTransaction(Guid estateId, - Guid transactionId, - String operatorIdentifier, - OperatorResponse operatorResponse, - TransactionResponseCode transactionResponseCode, - String responseMessage, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.AuthoriseTransaction(operatorIdentifier, - operatorResponse.AuthorisationCode, - operatorResponse.ResponseCode, - operatorResponse.ResponseMessage, - operatorResponse.TransactionId, - ((Int32)transactionResponseCode).ToString().PadLeft(4, '0'), - responseMessage); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - - public async Task AuthoriseTransactionLocally(Guid estateId, - Guid transactionId, - String authorisationCode, - (String responseMessage, TransactionResponseCode responseCode) validationResult, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.AuthoriseTransactionLocally(authorisationCode, - ((Int32)validationResult.responseCode).ToString().PadLeft(4, '0'), - validationResult.responseMessage); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - - public async Task CompleteTransaction(Guid estateId, - Guid transactionId, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.CompleteTransaction(); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - - public async Task DeclineTransaction(Guid estateId, - Guid transactionId, - String operatorIdentifier, - OperatorResponse operatorResponse, - TransactionResponseCode transactionResponseCode, - String responseMessage, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.DeclineTransaction(operatorIdentifier, - operatorResponse.ResponseCode, - operatorResponse.ResponseMessage, - ((Int32)transactionResponseCode).ToString().PadLeft(4, '0'), - responseMessage); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - - public async Task DeclineTransactionLocally(Guid estateId, - Guid transactionId, - (String responseMessage, TransactionResponseCode responseCode) validationResult, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.DeclineTransactionLocally(((Int32)validationResult.responseCode).ToString().PadLeft(4, '0'), validationResult.responseMessage); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - - public async Task GetAggregate(Guid estateId, - Guid transactionId, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - return transactionAggregate; - } - - public async Task RecordAdditionalRequestData(Guid estateId, - Guid transactionId, - String operatorIdentifier, - Dictionary additionalTransactionRequestMetadata, - CancellationToken cancellationToken) { - if (additionalTransactionRequestMetadata != null && additionalTransactionRequestMetadata.Any()) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.RecordAdditionalRequestData(operatorIdentifier, additionalTransactionRequestMetadata); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - } - - public async Task RecordAdditionalResponseData(Guid estateId, - Guid transactionId, - String operatorIdentifier, - Dictionary additionalTransactionResponseMetadata, - CancellationToken cancellationToken) { - if (additionalTransactionResponseMetadata != null && additionalTransactionResponseMetadata.Any()) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.RecordAdditionalResponseData(operatorIdentifier, additionalTransactionResponseMetadata); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - } - - public async Task RequestEmailReceipt(Guid estateId, - Guid transactionId, - String customerEmailAddress, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.RequestEmailReceipt(customerEmailAddress); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - - public async Task ResendReceipt(Guid estateId, - Guid transactionId, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - var aggregateJson = JsonConvert.SerializeObject(transactionAggregate, Formatting.Indented); - Logger.LogInformation($"Transaction Id is [{transactionId}]"); - Logger.LogInformation(aggregateJson); - - transactionAggregate.RequestEmailReceiptResend(); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - - public async Task StartTransaction(Guid transactionId, - DateTime transactionDateTime, - String transactionNumber, - TransactionType transactionType, - String transactionReference, - Guid estateId, - Guid merchantId, - String deviceIdentifier, - Decimal? transactionAmount, - CancellationToken cancellationToken) { - TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); - - transactionAggregate.StartTransaction(transactionDateTime, - transactionNumber, - transactionType, - transactionReference, - estateId, - merchantId, - deviceIdentifier, - transactionAmount); - - await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); - } - - #endregion - } -} \ No newline at end of file diff --git a/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs b/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs index a1be5bf7..b8ae1a61 100644 --- a/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs @@ -31,6 +31,8 @@ public class TransactionDomainService : ITransactionDomainService { #region Fields + private readonly IAggregateRepository TransactionAggregateRepository; + /// /// The estate client /// @@ -61,7 +63,7 @@ public class TransactionDomainService : ITransactionDomainService /// /// The transaction aggregate manager /// - private readonly ITransactionAggregateManager TransactionAggregateManager; + //private readonly ITransactionAggregateManager TransactionAggregateManager; #endregion @@ -75,13 +77,13 @@ public class TransactionDomainService : ITransactionDomainService /// The security service client. /// The operator proxy resolver. /// The reconciliation aggregate repository. - public TransactionDomainService(ITransactionAggregateManager transactionAggregateManager, + public TransactionDomainService(IAggregateRepository transactionAggregateRepository, IEstateClient estateClient, ISecurityServiceClient securityServiceClient, Func operatorProxyResolver, IAggregateRepository reconciliationAggregateRepository, IProjectionStateRepository merchantBalanceStateRepository) { - this.TransactionAggregateManager = transactionAggregateManager; + this.TransactionAggregateRepository = transactionAggregateRepository; this.EstateClient = estateClient; this.SecurityServiceClient = securityServiceClient; this.OperatorProxyResolver = operatorProxyResolver; @@ -116,16 +118,16 @@ public async Task ProcessLogonTransaction(Guid // Generate a transaction reference String transactionReference = this.GenerateTransactionReference(); - await this.TransactionAggregateManager.StartTransaction(transactionId, - transactionDateTime, - transactionNumber, - transactionType, - transactionReference, - estateId, - merchantId, - deviceIdentifier, - null, // Logon transaction has no amount - cancellationToken); + TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); + + transactionAggregate.StartTransaction(transactionDateTime, + transactionNumber, + transactionType, + transactionReference, + estateId, + merchantId, + deviceIdentifier, + null); // Logon transaction has no amount (String responseMessage, TransactionResponseCode responseCode) validationResult = await this.ValidateLogonTransaction(estateId, merchantId, deviceIdentifier, cancellationToken); @@ -133,16 +135,19 @@ await this.TransactionAggregateManager.StartTransaction(transactionId, if (validationResult.responseCode == TransactionResponseCode.Success) { // Record the successful validation // TODO: Generate local authcode - await this.TransactionAggregateManager.AuthoriseTransactionLocally(estateId, transactionId, "ABCD1234", validationResult, cancellationToken); + transactionAggregate.AuthoriseTransactionLocally("ABCD1234", + ((Int32)validationResult.responseCode).ToString().PadLeft(4, '0'), + validationResult.responseMessage); } else { // Record the failure - await this.TransactionAggregateManager.DeclineTransactionLocally(estateId, transactionId, validationResult, cancellationToken); + transactionAggregate.DeclineTransactionLocally(((Int32)validationResult.responseCode).ToString().PadLeft(4, '0'), + validationResult.responseMessage); } - await this.TransactionAggregateManager.CompleteTransaction(estateId, transactionId, cancellationToken); + transactionAggregate.CompleteTransaction(); - TransactionAggregate transactionAggregate = await this.TransactionAggregateManager.GetAggregate(estateId, transactionId, cancellationToken); + await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); return new ProcessLogonTransactionResponse { ResponseMessage = transactionAggregate.ResponseMessage, @@ -243,117 +248,103 @@ public async Task ProcessSaleTransaction(Guid tr Decimal? transactionAmount = additionalTransactionMetadata.ExtractFieldFromMetadata("Amount"); (String responseMessage, TransactionResponseCode responseCode) validationResult = - await this.ValidateSaleTransaction(estateId, merchantId,contractId, productId, deviceIdentifier, operatorIdentifier, transactionAmount, cancellationToken); + await this.ValidateSaleTransaction(estateId, + merchantId, + contractId, + productId, + deviceIdentifier, + operatorIdentifier, + transactionAmount, + cancellationToken); Logger.LogInformation($"Validation response is [{validationResult.responseCode}]"); - await this.TransactionAggregateManager.StartTransaction(transactionId, - transactionDateTime, - transactionNumber, - transactionType, - transactionReference, - estateId, - merchantId, - deviceIdentifier, - transactionAmount, - cancellationToken); - - // Add the product details (unless invalid estate) - if (validationResult.responseCode != TransactionResponseCode.InvalidEstateId && - validationResult.responseCode != TransactionResponseCode.InvalidContractIdValue && - validationResult.responseCode != TransactionResponseCode.InvalidProductIdValue && - validationResult.responseCode != TransactionResponseCode.ContractNotValidForMerchant && - validationResult.responseCode != TransactionResponseCode.ProductNotValidForMerchant) - { - await this.TransactionAggregateManager.AddProductDetails(estateId, transactionId, contractId, productId, cancellationToken); - } + TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); + + transactionAggregate.StartTransaction(transactionDateTime, + transactionNumber, + transactionType, + transactionReference, + estateId, + merchantId, + deviceIdentifier, + transactionAmount); + + // Add the product details (unless invalid estate) + if (validationResult.responseCode != TransactionResponseCode.InvalidEstateId && + validationResult.responseCode != TransactionResponseCode.InvalidContractIdValue && + validationResult.responseCode != TransactionResponseCode.InvalidProductIdValue && + validationResult.responseCode != TransactionResponseCode.ContractNotValidForMerchant && + validationResult.responseCode != TransactionResponseCode.ProductNotValidForMerchant) { + transactionAggregate.AddProductDetails(contractId, productId); + } - // Add the transaction source - await this.TransactionAggregateManager.AddTransactionSource(estateId, transactionId, transactionSourceValue, cancellationToken); + // Add the transaction source + transactionAggregate.AddTransactionSource(transactionSourceValue); - if (validationResult.responseCode == TransactionResponseCode.Success) - { - // Record any additional request metadata - await this.TransactionAggregateManager.RecordAdditionalRequestData(estateId, - transactionId, - operatorIdentifier, - additionalTransactionMetadata, - cancellationToken); - - // Do the online processing with the operator here - MerchantResponse merchant = await this.GetMerchant(estateId, merchantId, cancellationToken); - OperatorResponse operatorResponse = await this.ProcessMessageWithOperator(merchant, - transactionId, - transactionDateTime, - operatorIdentifier, - additionalTransactionMetadata, - transactionReference, - cancellationToken); - - // Act on the operator response - if (operatorResponse == null) - { - // Failed to perform sed/receive with the operator - TransactionResponseCode transactionResponseCode = TransactionResponseCode.OperatorCommsError; - String responseMessage = "OPERATOR COMMS ERROR"; - - await this.TransactionAggregateManager.DeclineTransactionLocally(estateId, - transactionId, - (responseMessage, transactionResponseCode), - cancellationToken); + if (validationResult.responseCode == TransactionResponseCode.Success) { + // Record any additional request metadata + transactionAggregate.RecordAdditionalRequestData(operatorIdentifier, additionalTransactionMetadata); + + // Do the online processing with the operator here + MerchantResponse merchant = await this.GetMerchant(estateId, merchantId, cancellationToken); + OperatorResponse operatorResponse = await this.ProcessMessageWithOperator(merchant, + transactionId, + transactionDateTime, + operatorIdentifier, + additionalTransactionMetadata, + transactionReference, + cancellationToken); + + // Act on the operator response + if (operatorResponse == null) { + // Failed to perform sed/receive with the operator + TransactionResponseCode transactionResponseCode = TransactionResponseCode.OperatorCommsError; + String responseMessage = "OPERATOR COMMS ERROR"; + + transactionAggregate.DeclineTransactionLocally(((Int32)validationResult.responseCode).ToString().PadLeft(4, '0'), validationResult.responseMessage); + } + else { + if (operatorResponse.IsSuccessful) { + TransactionResponseCode transactionResponseCode = TransactionResponseCode.Success; + String responseMessage = "SUCCESS"; + + transactionAggregate.AuthoriseTransaction(operatorIdentifier, + operatorResponse.AuthorisationCode, + operatorResponse.ResponseCode, + operatorResponse.ResponseMessage, + operatorResponse.TransactionId, + ((Int32)transactionResponseCode).ToString().PadLeft(4, '0'), + responseMessage); } - else - { - if (operatorResponse.IsSuccessful) - { - TransactionResponseCode transactionResponseCode = TransactionResponseCode.Success; - String responseMessage = "SUCCESS"; - - await this.TransactionAggregateManager.AuthoriseTransaction(estateId, - transactionId, - operatorIdentifier, - operatorResponse, - transactionResponseCode, - responseMessage, - cancellationToken); - } - else - { - TransactionResponseCode transactionResponseCode = TransactionResponseCode.TransactionDeclinedByOperator; - String responseMessage = "DECLINED BY OPERATOR"; - - await this.TransactionAggregateManager.DeclineTransaction(estateId, - transactionId, - operatorIdentifier, - operatorResponse, - transactionResponseCode, - responseMessage, - cancellationToken); - } - - // Record any additional operator response metadata - await this.TransactionAggregateManager.RecordAdditionalResponseData(estateId, - transactionId, - operatorIdentifier, - operatorResponse.AdditionalTransactionResponseMetadata, - cancellationToken); + else { + TransactionResponseCode transactionResponseCode = TransactionResponseCode.TransactionDeclinedByOperator; + String responseMessage = "DECLINED BY OPERATOR"; + + transactionAggregate.DeclineTransaction(operatorIdentifier, + operatorResponse.ResponseCode, + operatorResponse.ResponseMessage, + ((Int32)transactionResponseCode).ToString().PadLeft(4, '0'), + responseMessage); } + + // Record any additional operator response metadata + transactionAggregate.RecordAdditionalResponseData(operatorIdentifier, operatorResponse.AdditionalTransactionResponseMetadata); } - else - { - // Record the failure - await this.TransactionAggregateManager.DeclineTransactionLocally(estateId, transactionId, validationResult, cancellationToken); - } + } + else { + // Record the failure + transactionAggregate.DeclineTransactionLocally(((Int32)validationResult.responseCode).ToString().PadLeft(4, '0'), validationResult.responseMessage); + } - await this.TransactionAggregateManager.CompleteTransaction(estateId, transactionId, cancellationToken); + transactionAggregate.CompleteTransaction(); - // Determine if the email receipt is required - if (String.IsNullOrEmpty(customerEmailAddress) == false) - { - await this.TransactionAggregateManager.RequestEmailReceipt(estateId, transactionId, customerEmailAddress, cancellationToken); - } + // Determine if the email receipt is required + if (String.IsNullOrEmpty(customerEmailAddress) == false) { + transactionAggregate.RequestEmailReceipt(customerEmailAddress); + } - TransactionAggregate transactionAggregate = await this.TransactionAggregateManager.GetAggregate(estateId, transactionId, cancellationToken); + await this.TransactionAggregateRepository.SaveChanges(transactionAggregate, cancellationToken); // Get the model from the aggregate Transaction transaction = transactionAggregate.GetTransaction(); @@ -371,7 +362,11 @@ await this.TransactionAggregateManager.RecordAdditionalResponseData(estateId, public async Task ResendTransactionReceipt(Guid transactionId, Guid estateId, CancellationToken cancellationToken) { - await this.TransactionAggregateManager.ResendReceipt(estateId, transactionId, cancellationToken); + TransactionAggregate transactionAggregate = await this.TransactionAggregateRepository.GetLatestVersion(transactionId, cancellationToken); + + transactionAggregate.RequestEmailReceiptResend(); + + await this.TransactionAggregateRepository.SaveChanges(transactionAggregate,cancellationToken); } /// @@ -454,11 +449,7 @@ private async Task> GetMerchantContracts(Guid estateId, return merchantContracts; } - /// - /// Gets the token. - /// - /// The cancellation token. - /// + [ExcludeFromCodeCoverage] private async Task GetToken(CancellationToken cancellationToken) { // Get a token to talk to the estate service String clientId = ConfigurationReader.GetValue("AppSettings", "ClientId"); @@ -508,23 +499,13 @@ private async Task ProcessMessageWithOperator(MerchantResponse return operatorResponse; } - - /// - /// Validates the transaction. - /// - /// The estate identifier. - /// The merchant identifier. - /// The device identifier. - /// The cancellation token. - /// - /// Device Identifier {deviceIdentifier} not valid for Merchant {merchant.MerchantName} - /// Device Identifier {deviceIdentifier} not valid for Merchant {merchant.MerchantName} - private async Task<(String responseMessage, TransactionResponseCode responseCode)> ValidateLogonTransaction(Guid estateId, + + internal async Task<(String responseMessage, TransactionResponseCode responseCode)> ValidateLogonTransaction(Guid estateId, Guid merchantId, String deviceIdentifier, CancellationToken cancellationToken) { try { - (EstateResponse estate, MerchantResponse merchant, List merchantContracts) validateTransactionResponse = await this.ValidateTransaction(estateId, merchantId, cancellationToken); + (EstateResponse estate, MerchantResponse merchant) validateTransactionResponse = await this.ValidateMerchant(estateId, merchantId, cancellationToken); MerchantResponse merchant = validateTransactionResponse.merchant; // Device Validation @@ -549,24 +530,13 @@ private async Task ProcessMessageWithOperator(MerchantResponse return (tvex.Message, tvex.ResponseCode); } } - - /// - /// Validates the reconciliation transaction. - /// - /// The estate identifier. - /// The merchant identifier. - /// The device identifier. - /// The cancellation token. - /// - /// Merchant {merchant.MerchantName} has no valid Devices for this transaction. - /// or - /// Device Identifier {deviceIdentifier} not valid for Merchant {merchant.MerchantName} - private async Task<(String responseMessage, TransactionResponseCode responseCode)> ValidateReconciliationTransaction(Guid estateId, + + internal async Task<(String responseMessage, TransactionResponseCode responseCode)> ValidateReconciliationTransaction(Guid estateId, Guid merchantId, String deviceIdentifier, CancellationToken cancellationToken) { try { - (EstateResponse estate, MerchantResponse merchant, List merchantContracts) validateTransactionResponse = await this.ValidateTransaction(estateId, merchantId, cancellationToken); + (EstateResponse estate, MerchantResponse merchant) validateTransactionResponse = await this.ValidateMerchant(estateId, merchantId, cancellationToken); MerchantResponse merchant = validateTransactionResponse.merchant; // Device Validation @@ -592,28 +562,7 @@ private async Task ProcessMessageWithOperator(MerchantResponse } } - /// - /// Validates the sale transaction. - /// - /// The estate identifier. - /// The merchant identifier. - /// The device identifier. - /// The operator identifier. - /// The transaction amount. - /// The cancellation token. - /// - /// Merchant {merchant.MerchantName} has no valid Devices for this transaction. - /// or - /// Device Identifier {deviceIdentifier} not valid for Merchant {merchant.MerchantName} - /// or - /// Estate {estate.EstateName} has no operators defined - /// or - /// Operator {operatorIdentifier} not configured for Estate [{estate.EstateName}] - /// or - /// Merchant {merchant.MerchantName} has no operators defined - /// or - /// Operator {operatorIdentifier} not configured for Merchant [{merchant.MerchantName}] - private async Task<(String responseMessage, TransactionResponseCode responseCode)> ValidateSaleTransaction(Guid estateId, + internal async Task<(String responseMessage, TransactionResponseCode responseCode)> ValidateSaleTransaction(Guid estateId, Guid merchantId, Guid contractId, Guid productId, @@ -622,10 +571,23 @@ private async Task ProcessMessageWithOperator(MerchantResponse Decimal? transactionAmount, CancellationToken cancellationToken) { try { - (EstateResponse estate, MerchantResponse merchant, List merchantContracts) validateTransactionResponse = await this.ValidateTransaction(estateId, merchantId, cancellationToken); + (EstateResponse estate, MerchantResponse merchant) validateTransactionResponse = await this.ValidateMerchant(estateId, merchantId, cancellationToken); EstateResponse estate = validateTransactionResponse.estate; MerchantResponse merchant = validateTransactionResponse.merchant; - List contracts = validateTransactionResponse.merchantContracts; + + // Operator Validation (Estate) + if (estate.Operators == null || estate.Operators.Any() == false) + { + throw new TransactionValidationException($"Estate {estate.EstateName} has no operators defined", TransactionResponseCode.NoEstateOperators); + } + + // Operators have been configured for the estate + EstateOperatorResponse estateOperatorRecord = estate.Operators.SingleOrDefault(o => o.Name == operatorIdentifier); + if (estateOperatorRecord == null) + { + throw new TransactionValidationException($"Operator {operatorIdentifier} not configured for Estate [{estate.EstateName}]", + TransactionResponseCode.OperatorNotValidForEstate); + } // Device Validation if (merchant.Devices == null || merchant.Devices.Any() == false) { @@ -641,30 +603,16 @@ private async Task ProcessMessageWithOperator(MerchantResponse throw new TransactionValidationException($"Device Identifier {deviceIdentifier} not valid for Merchant {merchant.MerchantName}", TransactionResponseCode.InvalidDeviceIdentifier); } - - // Operator Validation (Estate) - if (estate.Operators == null || estate.Operators.Any() == false) { - throw new TransactionValidationException($"Estate {estate.EstateName} has no operators defined", TransactionResponseCode.NoEstateOperators); - } - - { - // Operators have been configured for the estate - EstateOperatorResponse operatorRecord = estate.Operators.SingleOrDefault(o => o.Name == operatorIdentifier); - if (operatorRecord == null) { - throw new TransactionValidationException($"Operator {operatorIdentifier} not configured for Estate [{estate.EstateName}]", - TransactionResponseCode.OperatorNotValidForEstate); - } - } - + // Operator Validation (Merchant) if (merchant.Operators == null || merchant.Operators.Any() == false) { - throw new TransactionValidationException($"Merchant {merchant.MerchantName} has no operators defined", TransactionResponseCode.NoEstateOperators); + throw new TransactionValidationException($"Merchant {merchant.MerchantName} has no operators defined", TransactionResponseCode.NoMerchantOperators); } { // Operators have been configured for the estate - MerchantOperatorResponse operatorRecord = merchant.Operators.SingleOrDefault(o => o.Name == operatorIdentifier); - if (operatorRecord == null) { + MerchantOperatorResponse merchantOperatorRecord = merchant.Operators.SingleOrDefault(o => o.Name == operatorIdentifier); + if (merchantOperatorRecord == null) { throw new TransactionValidationException($"Operator {operatorIdentifier} not configured for Merchant [{merchant.MerchantName}]", TransactionResponseCode.OperatorNotValidForMerchant); } @@ -693,8 +641,28 @@ private async Task ProcessMessageWithOperator(MerchantResponse TransactionResponseCode.InvalidContractIdValue); } + List merchantContracts = null; + try + { + merchantContracts = await this.GetMerchantContracts(estateId, merchantId, cancellationToken); + } + catch (Exception ex) when (ex.InnerException != null && ex.InnerException.GetType() == typeof(KeyNotFoundException)) + { + throw new TransactionValidationException($"Merchant Id [{merchantId}] is not a valid merchant for estate [{estate.EstateName}]", + TransactionResponseCode.InvalidMerchantId); + } + catch (Exception e) + { + throw new TransactionValidationException($"Exception occurred while getting Merchant Id [{merchantId}] Contracts Exception [{e.Message}]", TransactionResponseCode.UnknownFailure); + } + + if (merchantContracts == null || merchantContracts.Any() == false) + { + throw new TransactionValidationException($"Merchant {merchant.MerchantName} has no contracts configured", TransactionResponseCode.MerchantHasNoContractsConfigured); + } + // Check the contract and product id against the merchant - ContractResponse contract = contracts.SingleOrDefault(c => c.ContractId == contractId); + ContractResponse contract = merchantContracts.SingleOrDefault(c => c.ContractId == contractId); if (contract == null) { @@ -707,7 +675,7 @@ private async Task ProcessMessageWithOperator(MerchantResponse throw new TransactionValidationException($"Product Id [{productId}] must be set for a sale transaction", TransactionResponseCode.InvalidProductIdValue); } - + ContractProduct contractProduct = contract.Products.SingleOrDefault(p => p.ProductId == productId); if (contractProduct == null) @@ -723,23 +691,12 @@ private async Task ProcessMessageWithOperator(MerchantResponse return (tvex.Message, tvex.ResponseCode); } } - - /// - /// Validates the transaction. - /// - /// The estate identifier. - /// The merchant identifier. - /// The cancellation token. - /// - /// Estate Id [{estateId}] is not a valid estate - /// or - /// Merchant Id [{merchantId}] is not a valid merchant for estate [{estate.EstateName}] - private async Task<(EstateResponse estate, MerchantResponse merchant, List merchantContracts)> ValidateTransaction(Guid estateId, + + private async Task<(EstateResponse estate, MerchantResponse merchant)> ValidateMerchant(Guid estateId, Guid merchantId, CancellationToken cancellationToken) { EstateResponse estate = null; MerchantResponse merchant = null; - List merchantContracts = null; // Validate the Estate Record is a valid estate try { @@ -748,6 +705,10 @@ private async Task ProcessMessageWithOperator(MerchantResponse catch(Exception ex) when(ex.InnerException != null && ex.InnerException.GetType() == typeof(KeyNotFoundException)) { throw new TransactionValidationException($"Estate Id [{estateId}] is not a valid estate", TransactionResponseCode.InvalidEstateId); } + catch(Exception e) + { + throw new TransactionValidationException($"Exception occurred while getting Estate Id [{estateId}] Exception [{e.Message}]", TransactionResponseCode.UnknownFailure); + } // get the merchant record and validate the device try { @@ -757,18 +718,12 @@ private async Task ProcessMessageWithOperator(MerchantResponse throw new TransactionValidationException($"Merchant Id [{merchantId}] is not a valid merchant for estate [{estate.EstateName}]", TransactionResponseCode.InvalidMerchantId); } - - try + catch (Exception e) { - merchantContracts = await this.GetMerchantContracts(estateId, merchantId, cancellationToken); + throw new TransactionValidationException($"Exception occurred while getting Merchant Id [{merchantId}] Exception [{e.Message}]", TransactionResponseCode.UnknownFailure); } - catch (Exception ex) when (ex.InnerException != null && ex.InnerException.GetType() == typeof(KeyNotFoundException)) - { - //throw new TransactionValidationException($"Merchant Id [{merchantId}] is not a valid merchant for estate [{estate.EstateName}]", - // TransactionResponseCode.InvalidMerchantId); - } - - return (estate, merchant, merchantContracts); + + return (estate, merchant); } #endregion diff --git a/TransactionProcessor.BusinessLogic/Services/TransactionResponseCode.cs b/TransactionProcessor.BusinessLogic/Services/TransactionResponseCode.cs index 7be501ee..f7ccea24 100644 --- a/TransactionProcessor.BusinessLogic/Services/TransactionResponseCode.cs +++ b/TransactionProcessor.BusinessLogic/Services/TransactionResponseCode.cs @@ -18,8 +18,9 @@ public enum TransactionResponseCode InvalidSaleTransactionAmount = 1011, InvalidContractIdValue = 1012, InvalidProductIdValue = 1013, - ContractNotValidForMerchant = 1014, - ProductNotValidForMerchant = 1015, + MerchantHasNoContractsConfigured = 1014, + ContractNotValidForMerchant = 1015, + ProductNotValidForMerchant = 1016, // A Catch All generic Error where reason has not been identified UnknownFailure = 9999 diff --git a/TransactionProcessor.Testing/TestData.cs b/TransactionProcessor.Testing/TestData.cs index 4ec597a7..e2637676 100644 --- a/TransactionProcessor.Testing/TestData.cs +++ b/TransactionProcessor.Testing/TestData.cs @@ -42,8 +42,10 @@ public class TestData public static Guid EstateId = Guid.Parse("A522FA27-F9D0-470A-A88D-325DED3B62EE"); public static Guid ContractId = Guid.Parse("97A9ED00-E522-428C-B3C3-5931092DBDCE"); + public static Guid ContractId1 = Guid.Parse("9314DD8B-42A6-4C24-87FE-53CDC70BA48F"); public static Guid ProductId = Guid.Parse("ABA0E536-4E43-4E26-8362-7FB549DDA534"); + public static Guid ProductId1 = Guid.Parse("C758C21E-6BB2-4709-9F1D-5DA789FB6182"); public static String EstateName = "Test Estate 1"; @@ -984,6 +986,11 @@ public static TokenResponse TokenResponse() new MerchantBalanceState { AvailableBalance = TestData.AvailableBalance, }; + public static MerchantBalanceState MerchantBalanceProjectionStateNoCredit => + new MerchantBalanceState + { + AvailableBalance = 0, + }; public static ResendTransactionReceiptRequest ResendTransactionReceiptRequest => ResendTransactionReceiptRequest.Create(TestData.TransactionId, TestData.EstateId); diff --git a/TransactionProcessor/Bootstrapper/RepositoryRegistry.cs b/TransactionProcessor/Bootstrapper/RepositoryRegistry.cs index 71149366..dc83d486 100644 --- a/TransactionProcessor/Bootstrapper/RepositoryRegistry.cs +++ b/TransactionProcessor/Bootstrapper/RepositoryRegistry.cs @@ -91,8 +91,7 @@ public RepositoryRegistry() } this.AddTransient(); - - this.AddSingleton(); + this.AddSingleton, AggregateRepository>(); this.AddSingleton, diff --git a/TransactionProcessor/Common/Examples/GetVoucherResponseExample.cs b/TransactionProcessor/Common/Examples/GetVoucherResponseExample.cs index 5010e7dd..adc1e16a 100644 --- a/TransactionProcessor/Common/Examples/GetVoucherResponseExample.cs +++ b/TransactionProcessor/Common/Examples/GetVoucherResponseExample.cs @@ -2,7 +2,9 @@ using DataTransferObjects; using Swashbuckle.AspNetCore.Filters; +using System.Diagnostics.CodeAnalysis; +[ExcludeFromCodeCoverage] public class GetVoucherResponseExample : IExamplesProvider { /// diff --git a/TransactionProcessor/Common/Examples/RedeemVoucherRequestExample.cs b/TransactionProcessor/Common/Examples/RedeemVoucherRequestExample.cs index b6d656fb..94952410 100644 --- a/TransactionProcessor/Common/Examples/RedeemVoucherRequestExample.cs +++ b/TransactionProcessor/Common/Examples/RedeemVoucherRequestExample.cs @@ -2,7 +2,9 @@ using DataTransferObjects; using Swashbuckle.AspNetCore.Filters; +using System.Diagnostics.CodeAnalysis; +[ExcludeFromCodeCoverage] public class RedeemVoucherRequestExample : IExamplesProvider { /// diff --git a/TransactionProcessor/Common/Examples/RedeemVoucherResponseExample.cs b/TransactionProcessor/Common/Examples/RedeemVoucherResponseExample.cs index 3dcd7c91..7a504295 100644 --- a/TransactionProcessor/Common/Examples/RedeemVoucherResponseExample.cs +++ b/TransactionProcessor/Common/Examples/RedeemVoucherResponseExample.cs @@ -2,7 +2,9 @@ using DataTransferObjects; using Swashbuckle.AspNetCore.Filters; +using System.Diagnostics.CodeAnalysis; +[ExcludeFromCodeCoverage] public class RedeemVoucherResponseExample : IExamplesProvider { /// diff --git a/TransactionProcessor/Extensions.cs b/TransactionProcessor/Extensions.cs index f870d897..4f6241f0 100644 --- a/TransactionProcessor/Extensions.cs +++ b/TransactionProcessor/Extensions.cs @@ -161,7 +161,8 @@ private static void OperatorLogon(String operatorId) } } } - + + [ExcludeFromCodeCoverage] public class SubscriptionWorkersRoot { public Boolean InternalSubscriptionService { get; set; } @@ -170,6 +171,7 @@ public class SubscriptionWorkersRoot public List SubscriptionWorkers { get; set; } } + [ExcludeFromCodeCoverage] public class SubscriptionWorkerConfig { public String WorkerName { get; set; }