diff --git a/TransactionProcessor.Aggregates.Tests/MerchantDepositListAggregateTests.cs b/TransactionProcessor.Aggregates.Tests/MerchantDepositListAggregateTests.cs new file mode 100644 index 00000000..c4f9a051 --- /dev/null +++ b/TransactionProcessor.Aggregates.Tests/MerchantDepositListAggregateTests.cs @@ -0,0 +1,283 @@ +using Shared.ValueObjects; +using Shouldly; +using TransactionProcessor.Models.Merchant; +using TransactionProcessor.Testing; + +namespace TransactionProcessor.Aggregates.Tests +{ + public class MerchantDepositListAggregateTests + { + #region Methods + + [Fact] + public void MerchantDepositListAggregate_Create_IsCreated() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.AggregateId.ShouldBe(TestData.MerchantId); + merchantDepositListAggregate.EstateId.ShouldBe(TestData.EstateId); + merchantDepositListAggregate.DateCreated.ShouldBe(TestData.DateMerchantCreated); + } + + [Fact] + public void MerchantDepositListAggregate_Create_AlreadyCreated_IsCreated() + { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.AggregateId.ShouldBe(TestData.MerchantId); + merchantDepositListAggregate.EstateId.ShouldBe(TestData.EstateId); + merchantDepositListAggregate.DateCreated.ShouldBe(TestData.DateMerchantCreated); + } + + [Fact] + public void MerchantDepositListAggregate_Create_MerchantNotCreated_ErrorThrown() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + Should.Throw(() => { merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); }); + } + + [Fact] + public void MerchantDepositListAggregate_MakeDeposit_AutomaticDepositSource_DepositMade() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.MakeDeposit(TestData.MerchantDepositSourceAutomatic, + TestData.DepositReference, + TestData.DepositDateTime, + TestData.DepositAmount); + + List depositListModel = merchantDepositListAggregate.GetDeposits(); + depositListModel.ShouldHaveSingleItem(); + depositListModel.Single().Source.ShouldBe(TestData.MerchantDepositSourceAutomatic); + depositListModel.Single().DepositDateTime.ShouldBe(TestData.DepositDateTime); + depositListModel.Single().Reference.ShouldBe(TestData.DepositReference); + depositListModel.Single().Amount.ShouldBe(TestData.DepositAmount.Value); + } + + [Fact] + public void MerchantDepositListAggregate_MakeDeposit_DepositMade() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.MakeDeposit(TestData.MerchantDepositSourceManual, TestData.DepositReference, TestData.DepositDateTime, TestData.DepositAmount); + + List depositListModel = merchantDepositListAggregate.GetDeposits(); + depositListModel.ShouldHaveSingleItem(); + depositListModel.Single().Source.ShouldBe(TestData.MerchantDepositSourceManual); + + depositListModel.Single().DepositDateTime.ShouldBe(TestData.DepositDateTime); + depositListModel.Single().Reference.ShouldBe(TestData.DepositReference); + depositListModel.Single().Amount.ShouldBe(TestData.DepositAmount.Value); + } + + [Fact] + public void MerchantDepositListAggregate_MakeDeposit_DepositSourceNotSet_ErrorThrown() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + Should.Throw(() => { + merchantDepositListAggregate.MakeDeposit(MerchantDepositSource.NotSet, + TestData.DepositReference, + TestData.DepositDateTime, + TestData.DepositAmount); + }); + } + + [Fact] + public void MerchantDepositListAggregate_MakeDeposit_DuplicateDeposit_ErrorThrown() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.MakeDeposit(TestData.MerchantDepositSourceManual, TestData.DepositReference, TestData.DepositDateTime, TestData.DepositAmount); + List depositListModel = merchantDepositListAggregate.GetDeposits(); + depositListModel.ShouldHaveSingleItem(); + + Should.Throw(() => { + merchantDepositListAggregate.MakeDeposit(TestData.MerchantDepositSourceManual, + TestData.DepositReference, + TestData.DepositDateTime, + TestData.DepositAmount); + }); + } + + [Fact] + public void MerchantDepositListAggregate_MakeDeposit_MerchantDepositListNotCreated_ErrorThrown() { + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + + Should.Throw(() => { + merchantDepositListAggregate.MakeDeposit(TestData.MerchantDepositSourceManual, + TestData.DepositReference, + TestData.DepositDateTime, + TestData.DepositAmount); + }); + } + + [Fact] + public void MerchantDepositListAggregate_MakeDeposit_TwoDeposits_BothDepositsMade() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.MakeDeposit(TestData.MerchantDepositSourceManual, TestData.DepositReference, TestData.DepositDateTime, TestData.DepositAmount); + merchantDepositListAggregate.MakeDeposit(TestData.MerchantDepositSourceManual, + TestData.DepositReference2, + TestData.DepositDateTime2, + TestData.DepositAmount2); + + List depositListModel = merchantDepositListAggregate.GetDeposits(); + depositListModel.Count.ShouldBe(2); + } + + [Fact] + public void MerchantDepositListAggregate_MakeDeposit_TwoDepositsOneMonthApartSameDetails_BothDepositsMade() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.MakeDeposit(TestData.MerchantDepositSourceManual, + "Test Data Gen Deposit", + new DateTime(2021, 1, 1, 0, 0, 0), + PositiveMoney.Create(Money.Create(650.00m))); + merchantDepositListAggregate.MakeDeposit(TestData.MerchantDepositSourceManual, + "Test Data Gen Deposit", + new DateTime(2021, 2, 1, 0, 0, 0), + PositiveMoney.Create(Money.Create(650.00m))); + + List depositListModel = merchantDepositListAggregate.GetDeposits(); + depositListModel.Count.ShouldBe(2); + } + + [Fact] + public void MerchantDepositListAggregate_MakeDeposit_TwoDepositsSameDetailsApartFromAmounts_BothDepositsMade() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.MakeDeposit(TestData.MerchantDepositSourceManual, + "Test Data Gen Deposit", + new DateTime(2021, 1, 1, 0, 0, 0), + PositiveMoney.Create(Money.Create(650.00m))); + merchantDepositListAggregate.MakeDeposit(TestData.MerchantDepositSourceManual, + "Test Data Gen Deposit", + new DateTime(2021, 1, 1, 0, 0, 0), + PositiveMoney.Create(Money.Create(934.00m))); + + List depositListModel = merchantDepositListAggregate.GetDeposits(); + depositListModel.Count.ShouldBe(2); + } + + [Fact] + public void MerchantDepositListAggregate_MakeWithdrawal_DuplicateWithdrawal_ErrorThrown() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.MakeWithdrawal(TestData.WithdrawalDateTime, TestData.WithdrawalAmount); + List withdrawalListModel = merchantDepositListAggregate.GetWithdrawals(); + withdrawalListModel.ShouldHaveSingleItem(); + + Should.Throw(() => { merchantDepositListAggregate.MakeWithdrawal(TestData.WithdrawalDateTime, TestData.WithdrawalAmount); }); + } + + [Fact] + public void MerchantDepositListAggregate_MakeWithdrawal_MerchantDepositListNotCreated_ErrorThrown() { + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + + Should.Throw(() => { merchantDepositListAggregate.MakeWithdrawal(TestData.WithdrawalDateTime, TestData.WithdrawalAmount); }); + } + + [Fact] + public void MerchantDepositListAggregate_MakeWithdrawal_TwoWithdrawals_BothWithdrawalsMade() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.MakeWithdrawal(TestData.WithdrawalDateTime, TestData.WithdrawalAmount); + merchantDepositListAggregate.MakeWithdrawal(TestData.WithdrawalDateTime2, TestData.WithdrawalAmount2); + + List withdrawalListModel = merchantDepositListAggregate.GetWithdrawals(); + withdrawalListModel.Count.ShouldBe(2); + } + + [Fact] + public void MerchantDepositListAggregate_MakeWithdrawal_TwoWithdrawalsOneMonthApartSameDetails_BothWithdrawalsMade() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.MakeWithdrawal(new DateTime(2021, 1, 1, 0, 0, 0), PositiveMoney.Create(Money.Create(650.00m))); + merchantDepositListAggregate.MakeWithdrawal(new DateTime(2021, 2, 1, 0, 0, 0), PositiveMoney.Create(Money.Create(650.00m))); + + List withdrawalListModel = merchantDepositListAggregate.GetWithdrawals(); + withdrawalListModel.Count.ShouldBe(2); + } + + [Fact] + public void MerchantDepositListAggregate_MakeWithdrawal_TwoWithdrawalsSameDetailsApartFromAmounts_BothWithdrawalsMade() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.MakeWithdrawal(new DateTime(2021, 1, 1, 0, 0, 0), PositiveMoney.Create(Money.Create(650.00m))); + merchantDepositListAggregate.MakeWithdrawal(new DateTime(2021, 1, 1, 0, 0, 0), PositiveMoney.Create(Money.Create(934.00m))); + + List withdrawalListModel = merchantDepositListAggregate.GetWithdrawals(); + withdrawalListModel.Count.ShouldBe(2); + } + + [Fact] + public void MerchantDepositListAggregate_MakeWithdrawal_WithdrawalMade() { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + merchantDepositListAggregate.MakeWithdrawal(TestData.WithdrawalDateTime, TestData.WithdrawalAmount); + + var withdrawalListModel = merchantDepositListAggregate.GetWithdrawals(); + withdrawalListModel.ShouldHaveSingleItem(); + + withdrawalListModel.Single().WithdrawalDateTime.ShouldBe(TestData.WithdrawalDateTime); + withdrawalListModel.Single().Amount.ShouldBe(TestData.WithdrawalAmount.Value); + } + + #endregion + } +} \ No newline at end of file diff --git a/TransactionProcessor.Aggregates.Tests/TransactionProcessor.Aggregates.Tests.csproj b/TransactionProcessor.Aggregates.Tests/TransactionProcessor.Aggregates.Tests.csproj index 72b3c082..9ddfb280 100644 --- a/TransactionProcessor.Aggregates.Tests/TransactionProcessor.Aggregates.Tests.csproj +++ b/TransactionProcessor.Aggregates.Tests/TransactionProcessor.Aggregates.Tests.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - Full + None false true diff --git a/TransactionProcessor.Aggregates/MerchantDepositListAggregate.cs b/TransactionProcessor.Aggregates/MerchantDepositListAggregate.cs new file mode 100644 index 00000000..19b6b763 --- /dev/null +++ b/TransactionProcessor.Aggregates/MerchantDepositListAggregate.cs @@ -0,0 +1,226 @@ +using System.Diagnostics.CodeAnalysis; +using System.Security.Cryptography; +using System.Text; +using Shared.DomainDrivenDesign.EventSourcing; +using Shared.EventStore.Aggregate; +using Shared.General; +using Shared.ValueObjects; +using TransactionProcessor.DomainEvents; +using TransactionProcessor.Models.Merchant; + +namespace TransactionProcessor.Aggregates{ + public static class MerchantDepositListAggregateExtensions{ + #region Methods + + public static void Create(this MerchantDepositListAggregate aggregate, + MerchantAggregate merchantAggregate, + DateTime dateCreated){ + aggregate.EnsureMerchantHasBeenCreated(merchantAggregate); + // Ensure this aggregate has not already been created + if (aggregate.IsCreated) + return; + + MerchantDomainEvents.MerchantDepositListCreatedEvent merchantDepositListCreatedEvent = + new MerchantDomainEvents.MerchantDepositListCreatedEvent(aggregate.AggregateId, merchantAggregate.EstateId, dateCreated); + + aggregate.ApplyAndAppend(merchantDepositListCreatedEvent); + } + + public static List GetDeposits(this MerchantDepositListAggregate aggregate){ + List deposits = new (); + if (aggregate.Deposits.Any()){ + aggregate.Deposits.ForEach(d => deposits.Add(new TransactionProcessor.Models.Merchant.Deposit { + Amount = d.Amount, + DepositDateTime = d.DepositDateTime, + DepositId = d.DepositId, + Reference = d.Reference, + Source = d.Source + })); + } + + return deposits; + } + + public static List GetWithdrawals(this MerchantDepositListAggregate aggregate){ + List withdrawals = new List(); + if (aggregate.Withdrawals.Any()){ + aggregate.Withdrawals.ForEach(d => withdrawals.Add(new Withdrawal{ + WithdrawalDateTime = d.WithdrawalDateTime, + WithdrawalId = d.WithdrawalId, + Amount = d.Amount + })); + } + + return withdrawals; + } + + public static void MakeDeposit(this MerchantDepositListAggregate aggregate, + MerchantDepositSource source, + String reference, + DateTime depositDateTime, + PositiveMoney amount){ + String depositData = $"{depositDateTime.ToString("yyyyMMdd hh:mm:ss.fff")}-{reference}-{amount:N2}-{source}"; + Guid depositId = aggregate.GenerateGuidFromString(depositData); + + aggregate.EnsureMerchantDepositListHasBeenCreated(); + aggregate.EnsureNotDuplicateDeposit(depositId); + // TODO: Change amount to a value object (PositiveAmount VO) + aggregate.EnsureDepositSourceHasBeenSet(source); + + if (source == MerchantDepositSource.Manual){ + MerchantDomainEvents.ManualDepositMadeEvent manualDepositMadeEvent = + new MerchantDomainEvents.ManualDepositMadeEvent(aggregate.AggregateId, aggregate.EstateId, depositId, reference, depositDateTime, amount.Value); + aggregate.ApplyAndAppend(manualDepositMadeEvent); + } + else if (source == MerchantDepositSource.Automatic){ + MerchantDomainEvents.AutomaticDepositMadeEvent automaticDepositMadeEvent = + new MerchantDomainEvents.AutomaticDepositMadeEvent(aggregate.AggregateId, aggregate.EstateId, depositId, reference, depositDateTime, amount.Value); + aggregate.ApplyAndAppend(automaticDepositMadeEvent); + } + } + + public static void MakeWithdrawal(this MerchantDepositListAggregate aggregate, + DateTime withdrawalDateTime, + PositiveMoney amount){ + String depositData = $"{withdrawalDateTime.ToString("yyyyMMdd hh:mm:ss.fff")}-{amount:N2}"; + Guid withdrawalId = aggregate.GenerateGuidFromString(depositData); + + aggregate.EnsureMerchantDepositListHasBeenCreated(); + aggregate.EnsureNotDuplicateWithdrawal(withdrawalId); + + MerchantDomainEvents.WithdrawalMadeEvent withdrawalMadeEvent = new(aggregate.AggregateId, aggregate.EstateId, withdrawalId, withdrawalDateTime, amount.Value); + aggregate.ApplyAndAppend(withdrawalMadeEvent); + } + + public static void PlayEvent(this MerchantDepositListAggregate aggregate, MerchantDomainEvents.MerchantDepositListCreatedEvent merchantDepositListCreatedEvent){ + aggregate.IsCreated = true; + aggregate.EstateId = merchantDepositListCreatedEvent.EstateId; + aggregate.DateCreated = merchantDepositListCreatedEvent.DateCreated; + aggregate.AggregateId = merchantDepositListCreatedEvent.AggregateId; + } + + public static void PlayEvent(this MerchantDepositListAggregate aggregate, MerchantDomainEvents.ManualDepositMadeEvent manualDepositMadeEvent){ + Models.Deposit deposit = new(manualDepositMadeEvent.DepositId, + MerchantDepositSource.Manual, + manualDepositMadeEvent.Reference, + manualDepositMadeEvent.DepositDateTime, + manualDepositMadeEvent.Amount); + aggregate.Deposits.Add(deposit); + } + + public static void PlayEvent(this MerchantDepositListAggregate aggregate, MerchantDomainEvents.AutomaticDepositMadeEvent automaticDepositMadeEvent){ + Models.Deposit deposit = new(automaticDepositMadeEvent.DepositId, + MerchantDepositSource.Automatic, + automaticDepositMadeEvent.Reference, + automaticDepositMadeEvent.DepositDateTime, + automaticDepositMadeEvent.Amount); + aggregate.Deposits.Add(deposit); + } + + public static void PlayEvent(this MerchantDepositListAggregate aggregate, MerchantDomainEvents.WithdrawalMadeEvent withdrawalMadeEvent){ + Models.Withdrawal withdrawal = new(withdrawalMadeEvent.WithdrawalId, withdrawalMadeEvent.WithdrawalDateTime, withdrawalMadeEvent.Amount); + aggregate.Withdrawals.Add(withdrawal); + } + + private static void EnsureDepositSourceHasBeenSet(this MerchantDepositListAggregate aggregate, MerchantDepositSource merchantDepositSource){ + if (merchantDepositSource == MerchantDepositSource.NotSet){ + throw new InvalidOperationException("Merchant deposit source must be set"); + } + } + + private static void EnsureMerchantDepositListHasBeenCreated(this MerchantDepositListAggregate aggregate){ + if (aggregate.IsCreated == false){ + throw new InvalidOperationException("Merchant Deposit List has not been created"); + } + } + + private static void EnsureMerchantHasBeenCreated(this MerchantDepositListAggregate aggregate, MerchantAggregate merchantAggregate){ + if (merchantAggregate.IsCreated == false){ + throw new InvalidOperationException("Merchant has not been created"); + } + } + + private static void EnsureNotDuplicateDeposit(this MerchantDepositListAggregate aggregate, Guid depositId){ + if (aggregate.Deposits.Any(d => d.DepositId == depositId)){ + throw new InvalidOperationException($"Deposit Id [{depositId}] already made for merchant [{aggregate.AggregateId}]"); + } + } + + private static void EnsureNotDuplicateWithdrawal(this MerchantDepositListAggregate aggregate, Guid withdrawalId){ + if (aggregate.Withdrawals.Any(d => d.WithdrawalId == withdrawalId)){ + throw new InvalidOperationException($"Withdrawal Id [{withdrawalId}] already made for merchant [{aggregate.AggregateId}]"); + } + } + + private static Guid GenerateGuidFromString(this MerchantDepositListAggregate aggregate, String input){ + using(SHA256 sha256Hash = SHA256.Create()){ + //Generate hash from the key + Byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(input)); + + Byte[] j = bytes.Skip(Math.Max(0, bytes.Count() - 16)).ToArray(); //Take last 16 + + //Create our Guid. + return new Guid(j); + } + } + + #endregion + } + + public record MerchantDepositListAggregate : Aggregate{ + #region Fields + + internal readonly List Deposits; + + internal readonly List Withdrawals; + + #endregion + + #region Constructors + + [ExcludeFromCodeCoverage] + public MerchantDepositListAggregate(){ + // Nothing here + this.Deposits = new List(); + this.Withdrawals = new List(); + } + + private MerchantDepositListAggregate(Guid aggregateId){ + Guard.ThrowIfInvalidGuid(aggregateId, "Aggregate Id cannot be an Empty Guid"); + + this.AggregateId = aggregateId; + this.Deposits = new List(); + this.Withdrawals = new List(); + } + + #endregion + + #region Properties + + public DateTime DateCreated{ get; internal set; } + + public Guid EstateId{ get; internal set; } + + public Boolean IsCreated{ get; internal set; } + + #endregion + + #region Methods + + public static MerchantDepositListAggregate Create(Guid aggregateId){ + return new MerchantDepositListAggregate(aggregateId); + } + + public override void PlayEvent(IDomainEvent domainEvent) => MerchantDepositListAggregateExtensions.PlayEvent(this, (dynamic)domainEvent); + + [ExcludeFromCodeCoverage] + protected override Object GetMetadata(){ + return new{ + this.EstateId, + MerchantId = this.AggregateId + }; + } + + #endregion + } +} \ No newline at end of file diff --git a/TransactionProcessor.Aggregates/Models/Contract.cs b/TransactionProcessor.Aggregates/Models/Contract.cs index 1dfc4910..1d78fbef 100644 --- a/TransactionProcessor.Aggregates/Models/Contract.cs +++ b/TransactionProcessor.Aggregates/Models/Contract.cs @@ -1,5 +1,8 @@ -namespace TransactionProcessor.Aggregates.Models; +using System.Diagnostics.CodeAnalysis; +namespace TransactionProcessor.Aggregates.Models; + +[ExcludeFromCodeCoverage] internal record Contract { public Contract(Guid ContractId, Boolean IsDeleted = false) diff --git a/TransactionProcessor.Aggregates/Models/Deposit.cs b/TransactionProcessor.Aggregates/Models/Deposit.cs new file mode 100644 index 00000000..5ab1c999 --- /dev/null +++ b/TransactionProcessor.Aggregates/Models/Deposit.cs @@ -0,0 +1,12 @@ +using System.Diagnostics.CodeAnalysis; +using TransactionProcessor.Models.Merchant; + +namespace TransactionProcessor.Aggregates.Models +{ + [ExcludeFromCodeCoverage] + internal record Deposit(Guid DepositId, + MerchantDepositSource Source, + String Reference, + DateTime DepositDateTime, + Decimal Amount); +} \ No newline at end of file diff --git a/TransactionProcessor.Aggregates/Models/Device.cs b/TransactionProcessor.Aggregates/Models/Device.cs index 78e5a9bc..04d35151 100644 --- a/TransactionProcessor.Aggregates/Models/Device.cs +++ b/TransactionProcessor.Aggregates/Models/Device.cs @@ -1,3 +1,6 @@ -namespace TransactionProcessor.Aggregates.Models; +using System.Diagnostics.CodeAnalysis; +namespace TransactionProcessor.Aggregates.Models; + +[ExcludeFromCodeCoverage] internal record Device(Guid DeviceId, String DeviceIdentifier, Boolean IsEnabled = true); \ No newline at end of file diff --git a/TransactionProcessor.Aggregates/Models/Operator.cs b/TransactionProcessor.Aggregates/Models/Operator.cs index e0c3b3ae..dc4dd08d 100644 --- a/TransactionProcessor.Aggregates/Models/Operator.cs +++ b/TransactionProcessor.Aggregates/Models/Operator.cs @@ -1,4 +1,7 @@ -namespace TransactionProcessor.Aggregates.Models +using System.Diagnostics.CodeAnalysis; + +namespace TransactionProcessor.Aggregates.Models { + [ExcludeFromCodeCoverage] internal record Operator(Guid OperatorId, String Name, String MerchantNumber, String TerminalNumber, Boolean IsDeleted = false); } \ No newline at end of file diff --git a/TransactionProcessor.Aggregates/Models/SecurityUser.cs b/TransactionProcessor.Aggregates/Models/SecurityUser.cs index 9c8c0a94..9255d074 100644 --- a/TransactionProcessor.Aggregates/Models/SecurityUser.cs +++ b/TransactionProcessor.Aggregates/Models/SecurityUser.cs @@ -1,4 +1,7 @@ -namespace TransactionProcessor.Aggregates.Models +using System.Diagnostics.CodeAnalysis; + +namespace TransactionProcessor.Aggregates.Models { + [ExcludeFromCodeCoverage] internal record SecurityUser(Guid SecurityUserId, String EmailAddress); } diff --git a/TransactionProcessor.Aggregates/Models/Withdrawal.cs b/TransactionProcessor.Aggregates/Models/Withdrawal.cs new file mode 100644 index 00000000..aaf90490 --- /dev/null +++ b/TransactionProcessor.Aggregates/Models/Withdrawal.cs @@ -0,0 +1,9 @@ +using System.Diagnostics.CodeAnalysis; + +namespace TransactionProcessor.Aggregates.Models +{ + [ExcludeFromCodeCoverage] + internal record Withdrawal(Guid WithdrawalId, + DateTime WithdrawalDateTime, + Decimal Amount); +} \ No newline at end of file diff --git a/TransactionProcessor.BusinessLogic.Tests/DomainEventHandlers/MerchantDomainEventHandlerTests.cs b/TransactionProcessor.BusinessLogic.Tests/DomainEventHandlers/MerchantDomainEventHandlerTests.cs index 9a97a84d..e00f0c8c 100644 --- a/TransactionProcessor.BusinessLogic.Tests/DomainEventHandlers/MerchantDomainEventHandlerTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/DomainEventHandlers/MerchantDomainEventHandlerTests.cs @@ -10,6 +10,7 @@ using SimpleResults; using TransactionProcessor.Aggregates; using TransactionProcessor.BusinessLogic.EventHandling; +using TransactionProcessor.BusinessLogic.Events; using TransactionProcessor.BusinessLogic.Requests; using TransactionProcessor.DomainEvents; using TransactionProcessor.Repository; @@ -38,43 +39,43 @@ public MerchantDomainEventHandlerTests() { this.Mediator.Object); } - //[Fact] - //public async Task MerchantDomainEventHandler_Handle_CallbackReceivedEnrichedEvent_Deposit_EventIsHandled() - //{ - // this.EstateManagementRepository.Setup(e => e.GetMerchantFromReference(It.IsAny(), It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.MerchantModelWithAddressesContactsDevicesAndOperatorsAndContracts())); - // this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success); - // CallbackReceivedEnrichedEvent domainEvent = TestData.CallbackReceivedEnrichedEventDeposit; + [Fact] + public async Task MerchantDomainEventHandler_Handle_CallbackReceivedEnrichedEvent_Deposit_EventIsHandled() + { + this.EstateManagementRepository.Setup(e => e.GetMerchantFromReference(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.MerchantModelWithAddressesContactsDevicesAndOperatorsAndContracts())); + this.Mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success); + CallbackReceivedEnrichedEvent domainEvent = TestData.DomainEvents.CallbackReceivedEnrichedEventDeposit; - // var result = await this.DomainEventHandler.Handle(domainEvent, CancellationToken.None); - // result.IsSuccess.ShouldBeTrue(); + var result = await this.DomainEventHandler.Handle(domainEvent, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); - //} + } - //[Fact] - //public async Task MerchantDomainEventHandler_Handle_CallbackReceivedEnrichedEvent_OtherType_EventIsHandled() - //{ - // this.EstateManagementRepository.Setup(e => e.GetMerchantFromReference(It.IsAny(), It.IsAny(), It.IsAny())) - // .ReturnsAsync(TestData.MerchantModelWithAddressesContactsDevicesAndOperatorsAndContracts()); + [Fact] + public async Task MerchantDomainEventHandler_Handle_CallbackReceivedEnrichedEvent_OtherType_EventIsHandled() + { + //this.EstateManagementRepository.Setup(e => e.GetMerchantFromReference(It.IsAny(), It.IsAny(), It.IsAny())) + // .ReturnsAsync(TestData.MerchantModelWithAddressesContactsDevicesAndOperatorsAndContracts()); - // CallbackReceivedEnrichedEvent domainEvent = TestData.CallbackReceivedEnrichedEventOtherType; + CallbackReceivedEnrichedEvent domainEvent = TestData.DomainEvents.CallbackReceivedEnrichedEventOtherType; - // var result = await this.DomainEventHandler.Handle(domainEvent, CancellationToken.None); - // result.IsSuccess.ShouldBeTrue(); - //} + var result = await this.DomainEventHandler.Handle(domainEvent, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); + } - //[Fact] - //public async Task MerchantDomainEventHandler_Handle_CallbackReceivedEnrichedEvent_Deposit_GetMerchantFailed_ResultIsFailure() - //{ - // this.EstateManagementRepository.Setup(e => e.GetMerchantFromReference(It.IsAny(), It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Failure()); + [Fact] + public async Task MerchantDomainEventHandler_Handle_CallbackReceivedEnrichedEvent_Deposit_GetMerchantFailed_ResultIsFailure() + { + this.EstateManagementRepository.Setup(e => e.GetMerchantFromReference(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); - // CallbackReceivedEnrichedEvent domainEvent = TestData.CallbackReceivedEnrichedEventDeposit; + CallbackReceivedEnrichedEvent domainEvent = TestData.DomainEvents.CallbackReceivedEnrichedEventDeposit; - // var result = await this.DomainEventHandler.Handle(domainEvent, CancellationToken.None); - // result.IsFailed.ShouldBeTrue(); + var result = await this.DomainEventHandler.Handle(domainEvent, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); - //} + } #region Methods diff --git a/TransactionProcessor.BusinessLogic.Tests/Manager/EstateManagementManagerTests.cs b/TransactionProcessor.BusinessLogic.Tests/Manager/EstateManagementManagerTests.cs index 011aaf7d..e89f643e 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Manager/EstateManagementManagerTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Manager/EstateManagementManagerTests.cs @@ -1,5 +1,4 @@ -using EstateManagement.DataTransferObjects.Responses.Merchant; -using Moq; +using Moq; using Shared.DomainDrivenDesign.EventSourcing; using Shared.EventStore.Aggregate; using SimpleResults; @@ -17,7 +16,9 @@ using TransactionProcessor.Testing; using Xunit; using TransactionProcessor.Models.Contract; -using TransactionProcessor.Models.Operator; +using TransactionProcessor.Models.Merchant; +using Contract = TransactionProcessor.Models.Contract.Contract; +using Operator = TransactionProcessor.Models.Operator.Operator; namespace TransactionProcessor.BusinessLogic.Tests.Manager { @@ -487,6 +488,201 @@ public async Task EstateManagementManager_GetOperators_RepoCallFails_ExceptionTh var getOperatorsResult = await this.EstateManagementManager.GetOperators(TestData.EstateId, CancellationToken.None); getOperatorsResult.IsFailed.ShouldBeTrue(); } - + + [Fact] + public async Task EstateManagementManager_GetMerchant_MerchantIsReturned() + { + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.Aggregates.MerchantAggregateWithEverything(SettlementSchedule.Immediate))); + this.OperatorAggregateRepository.Setup(o => o.GetLatestVersion(It.IsAny(), CancellationToken.None)).ReturnsAsync(Result.Success(TestData.Aggregates.CreatedOperatorAggregate())); + + Merchant expectedModel = TestData.MerchantModelWithAddressesContactsDevicesAndOperatorsAndContracts(); + + var getMerchantResult = await this.EstateManagementManager.GetMerchant(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + getMerchantResult.IsSuccess.ShouldBeTrue(); + var merchantModel = getMerchantResult.Data; + + merchantModel.ShouldNotBeNull(); + merchantModel.MerchantReportingId.ShouldBe(expectedModel.MerchantReportingId); + merchantModel.EstateId.ShouldBe(expectedModel.EstateId); + merchantModel.EstateReportingId.ShouldBe(expectedModel.EstateReportingId); + merchantModel.NextStatementDate.ShouldBe(expectedModel.NextStatementDate); + merchantModel.MerchantId.ShouldBe(expectedModel.MerchantId); + merchantModel.MerchantName.ShouldBe(expectedModel.MerchantName); + merchantModel.SettlementSchedule.ShouldBe(expectedModel.SettlementSchedule); + + merchantModel.Addresses.ShouldHaveSingleItem(); + merchantModel.Addresses.Single().AddressId.ShouldNotBe(Guid.Empty); + merchantModel.Addresses.Single().AddressLine1.ShouldBe(expectedModel.Addresses.Single().AddressLine1); + merchantModel.Addresses.Single().AddressLine2.ShouldBe(expectedModel.Addresses.Single().AddressLine2); + merchantModel.Addresses.Single().AddressLine3.ShouldBe(expectedModel.Addresses.Single().AddressLine3); + merchantModel.Addresses.Single().AddressLine4.ShouldBe(expectedModel.Addresses.Single().AddressLine4); + merchantModel.Addresses.Single().Country.ShouldBe(expectedModel.Addresses.Single().Country); + merchantModel.Addresses.Single().PostalCode.ShouldBe(expectedModel.Addresses.Single().PostalCode); + merchantModel.Addresses.Single().Region.ShouldBe(expectedModel.Addresses.Single().Region); + merchantModel.Addresses.Single().Town.ShouldBe(expectedModel.Addresses.Single().Town); + + merchantModel.Contacts.ShouldHaveSingleItem(); + merchantModel.Contacts.Single().ContactEmailAddress.ShouldBe(expectedModel.Contacts.Single().ContactEmailAddress); + merchantModel.Contacts.Single().ContactId.ShouldNotBe(Guid.Empty); + merchantModel.Contacts.Single().ContactName.ShouldBe(expectedModel.Contacts.Single().ContactName); + merchantModel.Contacts.Single().ContactPhoneNumber.ShouldBe(expectedModel.Contacts.Single().ContactPhoneNumber); + + merchantModel.Devices.ShouldHaveSingleItem(); + merchantModel.Devices.Single().DeviceId.ShouldBe(expectedModel.Devices.Single().DeviceId); + merchantModel.Devices.Single().DeviceIdentifier.ShouldBe(expectedModel.Devices.Single().DeviceIdentifier); + + merchantModel.Operators.ShouldHaveSingleItem(); + merchantModel.Operators.Single().MerchantNumber.ShouldBe(expectedModel.Operators.Single().MerchantNumber); + merchantModel.Operators.Single().Name.ShouldBe(expectedModel.Operators.Single().Name); + merchantModel.Operators.Single().OperatorId.ShouldBe(expectedModel.Operators.Single().OperatorId); + merchantModel.Operators.Single().TerminalNumber.ShouldBe(expectedModel.Operators.Single().TerminalNumber); + + } + + [Fact] + public async Task EstateManagementManager_GetMerchant_MerchantIsReturnedWithNullAddressesAndContacts() + { + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.Aggregates.MerchantAggregateWithOperator())); + this.OperatorAggregateRepository.Setup(o => o.GetLatestVersion(It.IsAny(), CancellationToken.None)).ReturnsAsync(Result.Success(TestData.Aggregates.EmptyOperatorAggregate())); + + var getMerchantResult = await this.EstateManagementManager.GetMerchant(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + getMerchantResult.IsSuccess.ShouldBeTrue(); + var merchantModel = getMerchantResult.Data; + + merchantModel.ShouldNotBeNull(); + merchantModel.MerchantId.ShouldBe(TestData.MerchantId); + merchantModel.MerchantName.ShouldBe(TestData.MerchantName); + merchantModel.Addresses.ShouldBeNull(); + merchantModel.Contacts.ShouldBeNull(); + } + + [Fact] + public async Task EstateManagementManager_GetMerchant_WithAddress_MerchantIsReturnedWithNullContacts() + { + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.Aggregates.MerchantAggregateWithAddress())); + + var getMerchantResult = await this.EstateManagementManager.GetMerchant(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + getMerchantResult.IsSuccess.ShouldBeTrue(); + var merchantModel = getMerchantResult.Data; + + merchantModel.ShouldNotBeNull(); + merchantModel.MerchantId.ShouldBe(TestData.MerchantId); + merchantModel.MerchantName.ShouldBe(TestData.MerchantName); + merchantModel.Addresses.ShouldHaveSingleItem(); + merchantModel.Contacts.ShouldBeNull(); + } + + [Fact] + public async Task EstateManagementManager_GetMerchant_WithContact_MerchantIsReturnedWithNullAddresses() + { + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.Aggregates.MerchantAggregateWithContact())); + + var getMerchantResult = await this.EstateManagementManager.GetMerchant(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + getMerchantResult.IsSuccess.ShouldBeTrue(); + var merchantModel = getMerchantResult.Data; + + merchantModel.ShouldNotBeNull(); + merchantModel.MerchantId.ShouldBe(TestData.MerchantId); + merchantModel.MerchantName.ShouldBe(TestData.MerchantName); + merchantModel.Addresses.ShouldBeNull(); + merchantModel.Contacts.ShouldHaveSingleItem(); + } + + [Fact] + public async Task EstateManagementManager_GetMerchant_MerchantNotCreated_ErrorThrown() + { + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.Aggregates.EmptyMerchantAggregate())); + + var result = await this.EstateManagementManager.GetMerchant(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task EstateManagementManager_GetMerchant_GetLatestFails_ErrorThrown() + { + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); + + var result = await this.EstateManagementManager.GetMerchant(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task EstateManagementManager_GetMerchantContracts_MerchantContractsReturned() + { + this.EstateManagementRepository.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.MerchantContracts)); + + var getMerchantContractsResult = await this.EstateManagementManager.GetMerchantContracts(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + getMerchantContractsResult.IsSuccess.ShouldBeTrue(); + var merchantContracts = getMerchantContractsResult.Data; + merchantContracts.ShouldNotBeNull(); + merchantContracts.ShouldHaveSingleItem(); + merchantContracts.Single().ContractId.ShouldBe(TestData.ContractId); + } + + [Fact] + public async Task EstateManagementManager_GetMerchantContracts_EmptyListReturned_ResultFailed() + { + this.EstateManagementRepository.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.MerchantContractsEmptyList)); + + var getMerchantContractsResult = await this.EstateManagementManager.GetMerchantContracts(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + getMerchantContractsResult.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task EstateManagementManager_GetMerchantContracts_RepoCallFailed_ResultFailed() + { + this.EstateManagementRepository.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); + + var getMerchantContractsResult = await this.EstateManagementManager.GetMerchantContracts(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + getMerchantContractsResult.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task EstateManagementManager_GetMerchants_MerchantListIsReturned() + { + this.EstateManagementRepository.Setup(e => e.GetMerchants(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(new List + { + TestData + .MerchantModelWithAddressesContactsDevicesAndOperatorsAndContracts() + })); + + Result> getMerchantsResult = await this.EstateManagementManager.GetMerchants(TestData.EstateId, CancellationToken.None); + getMerchantsResult.IsSuccess.ShouldBeTrue(); + var merchantList = getMerchantsResult.Data; + + merchantList.ShouldNotBeNull(); + merchantList.ShouldNotBeEmpty(); + merchantList.ShouldHaveSingleItem(); + } + + [Fact] + public async Task EstateManagementManager_GetMerchants_NullMerchants_ExceptionThrown() + { + List merchants = null; + this.EstateManagementRepository.Setup(e => e.GetMerchants(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(merchants)); + + Result> getMerchantsResult = await this.EstateManagementManager.GetMerchants(TestData.EstateId, CancellationToken.None); + getMerchantsResult.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task EstateManagementManager_GetMerchants_EmptyMerchants_ExceptionThrown() + { + List merchants = new List(); + this.EstateManagementRepository.Setup(e => e.GetMerchants(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(merchants)); + + Result> getMerchantsResult = await this.EstateManagementManager.GetMerchants(TestData.EstateId, CancellationToken.None); + getMerchantsResult.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task EstateManagementManager_GetMerchants_RepoCallFails_ExceptionThrown() + { + List merchants = new List(); + this.EstateManagementRepository.Setup(e => e.GetMerchants(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); + + Result> getMerchantsResult = await this.EstateManagementManager.GetMerchants(TestData.EstateId, CancellationToken.None); + getMerchantsResult.IsFailed.ShouldBeTrue(); + } } } diff --git a/TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs b/TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs index 2a454a48..21da3fc4 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Mediator/MediatorTests.cs @@ -29,20 +29,22 @@ public class MediatorTests public MediatorTests() { - this.Requests.Add(TestData.ProcessLogonTransactionCommand); - this.Requests.Add(TestData.ProcessReconciliationCommand); - this.Requests.Add(TestData.ProcessSaleTransactionCommand); - this.Requests.Add(TestData.ProcessSettlementCommand); - this.Requests.Add(TestData.GetMerchantBalanceQuery); - this.Requests.Add(TestData.GetMerchantLiveBalanceQuery); - this.Requests.Add(TestData.GetMerchantBalanceHistoryQuery); - this.Requests.Add(TestData.AddMerchantFeePendingSettlementCommand); - this.Requests.Add(TestData.AddSettledFeeToSettlementCommand); - this.Requests.Add(TestData.GetPendingSettlementQuery); - this.Requests.Add(TestData.RecordCreditPurchaseCommand); - this.Requests.Add(TestData.CalculateFeesForTransactionCommand); - this.Requests.Add(TestData.AddSettledMerchantFeeCommand); - this.Requests.Add(TestData.RecordTransactionCommand); + this.Requests.Add(TestData.Commands.ProcessLogonTransactionCommand); + this.Requests.Add(TestData.Commands.ProcessReconciliationCommand); + this.Requests.Add(TestData.Commands.ProcessSaleTransactionCommand); + this.Requests.Add(TestData.Commands.ProcessSettlementCommand); + this.Requests.Add(TestData.Queries.GetMerchantBalanceQuery); + this.Requests.Add(TestData.Queries.GetMerchantLiveBalanceQuery); + this.Requests.Add(TestData.Queries.GetMerchantBalanceHistoryQuery); + this.Requests.Add(TestData.Commands.AddMerchantFeePendingSettlementCommand); + this.Requests.Add(TestData.Commands.AddSettledFeeToSettlementCommand); + this.Requests.Add(TestData.Queries.GetPendingSettlementQuery); + this.Requests.Add(TestData.Commands.RecordCreditPurchaseCommand); + this.Requests.Add(TestData.Commands.CalculateFeesForTransactionCommand); + this.Requests.Add(TestData.Commands.AddSettledMerchantFeeCommand); + this.Requests.Add(TestData.Commands.RecordTransactionCommand); + this.Requests.Add(TestData.Commands.SendCustomerEmailReceiptCommand); + this.Requests.Add(TestData.Commands.ResendTransactionReceiptCommand); // TODO: this needs the query handling function refactoring to use a repository not the context direct //this.Requests.Add(TestData.GetVoucherByVoucherCodeQuery); //this.Requests.Add(TestData.GetVoucherByTransactionIdQuery); @@ -69,6 +71,28 @@ public MediatorTests() this.Requests.Add(TestData.Commands.DisableTransactionFeeForProductCommand); this.Requests.Add(TestData.Queries.GetContractQuery); this.Requests.Add(TestData.Queries.GetContractsQuery); + + // Merchant Commands and Queries + this.Requests.Add(TestData.Commands.AddMerchantDeviceCommand); + this.Requests.Add(TestData.Commands.CreateMerchantCommand); + this.Requests.Add(TestData.Commands.AssignOperatorToMerchantCommand); + this.Requests.Add(TestData.Commands.AddMerchantContractCommand); + this.Requests.Add(TestData.Commands.CreateMerchantUserCommand); + this.Requests.Add(TestData.Commands.MakeMerchantDepositCommand); + this.Requests.Add(TestData.Commands.MakeMerchantWithdrawalCommand); + this.Requests.Add(TestData.Commands.SwapMerchantDeviceCommand); + this.Requests.Add(TestData.Commands.UpdateMerchantCommand); + this.Requests.Add(TestData.Commands.AddMerchantAddressCommand); + this.Requests.Add(TestData.Commands.UpdateMerchantAddressCommand); + this.Requests.Add(TestData.Commands.AddMerchantContactCommand); + this.Requests.Add(TestData.Commands.UpdateMerchantContactCommand); + this.Requests.Add(TestData.Commands.RemoveOperatorFromMerchantCommand); + this.Requests.Add(TestData.Commands.RemoveMerchantContractCommand); + this.Requests.Add(TestData.Queries.GetMerchantsQuery); + this.Requests.Add(TestData.Queries.GetMerchantQuery); + this.Requests.Add(TestData.Queries.GetMerchantContractsQuery); + this.Requests.Add(TestData.Queries.GetTransactionFeesForProductQuery); + } [Fact] diff --git a/TransactionProcessor.BusinessLogic.Tests/RequestHandler/SettlementRequestHandlerTests.cs b/TransactionProcessor.BusinessLogic.Tests/RequestHandler/SettlementRequestHandlerTests.cs index 7038a453..fab59a35 100644 --- a/TransactionProcessor.BusinessLogic.Tests/RequestHandler/SettlementRequestHandlerTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/RequestHandler/SettlementRequestHandlerTests.cs @@ -24,7 +24,7 @@ public async Task SettlementRequestHandler_ProcessSettlementRequest_IsHandled() SettlementRequestHandler handler = new SettlementRequestHandler(settlementDomainService.Object, settlementAggregateRepository.Object); settlementDomainService .Setup(s => s.ProcessSettlement(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success()); - var command = TestData.ProcessSettlementCommand; + var command = TestData.Commands.ProcessSettlementCommand; var result = await handler.Handle(command, CancellationToken.None); result.IsSuccess.ShouldBeTrue(); diff --git a/TransactionProcessor.BusinessLogic.Tests/RequestHandler/TransactionRequestHandlerTests.cs b/TransactionProcessor.BusinessLogic.Tests/RequestHandler/TransactionRequestHandlerTests.cs index 3f3f0260..1ac0ebec 100644 --- a/TransactionProcessor.BusinessLogic.Tests/RequestHandler/TransactionRequestHandlerTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/RequestHandler/TransactionRequestHandlerTests.cs @@ -22,7 +22,7 @@ public async Task TransactionRequestHandler_ProcessLogonTransactionRequest_IsHan TransactionRequestHandler handler = new TransactionRequestHandler(transactionDomainService.Object); transactionDomainService.Setup(t => t.ProcessLogonTransaction(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success()); - TransactionCommands.ProcessLogonTransactionCommand command = TestData.ProcessLogonTransactionCommand; + TransactionCommands.ProcessLogonTransactionCommand command = TestData.Commands.ProcessLogonTransactionCommand; var result = await handler.Handle(command, CancellationToken.None); result.IsSuccess.ShouldBeTrue(); @@ -36,7 +36,7 @@ public async Task TransactionRequestHandler_ProcessSaleTransactionRequest_IsHand TransactionRequestHandler handler = new TransactionRequestHandler(transactionDomainService.Object); transactionDomainService.Setup(t => t.ProcessSaleTransaction(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success()); - TransactionCommands.ProcessSaleTransactionCommand command = TestData.ProcessSaleTransactionCommand; + TransactionCommands.ProcessSaleTransactionCommand command = TestData.Commands.ProcessSaleTransactionCommand; var result = await handler.Handle(command, CancellationToken.None); result.IsSuccess.ShouldBeTrue(); @@ -50,7 +50,7 @@ public async Task TransactionRequestHandler_ProcessReconciliationRequest_IsHandl TransactionRequestHandler handler = new TransactionRequestHandler(transactionDomainService.Object); transactionDomainService.Setup(t => t.ProcessReconciliationTransaction(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success()); - TransactionCommands.ProcessReconciliationCommand command = TestData.ProcessReconciliationCommand; + TransactionCommands.ProcessReconciliationCommand command = TestData.Commands.ProcessReconciliationCommand; var result = await handler.Handle(command, CancellationToken.None); result.IsSuccess.ShouldBeTrue(); @@ -65,7 +65,7 @@ public async Task TransactionRequestHandler_ResendTransactionReceiptRequest_IsHa transactionDomainService .Setup(t => t.ResendTransactionReceipt(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success()); - TransactionCommands.ResendTransactionReceiptCommand command = TestData.ResendTransactionReceiptCommand; + TransactionCommands.ResendTransactionReceiptCommand command = TestData.Commands.ResendTransactionReceiptCommand; var result = await handler.Handle(command, CancellationToken.None); result.IsSuccess.ShouldBeTrue(); diff --git a/TransactionProcessor.BusinessLogic.Tests/Services/MerchantDomainServiceTests.cs b/TransactionProcessor.BusinessLogic.Tests/Services/MerchantDomainServiceTests.cs index e1a6c718..7c859517 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Services/MerchantDomainServiceTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Services/MerchantDomainServiceTests.cs @@ -4,11 +4,13 @@ using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Moq; +using Newtonsoft.Json; using SecurityService.Client; using SecurityService.DataTransferObjects; using SecurityService.DataTransferObjects.Responses; using Shared.DomainDrivenDesign.EventSourcing; using Shared.EventStore.Aggregate; +using Shared.EventStore.EventStore; using Shared.General; using Shared.Logger; using Shouldly; @@ -27,18 +29,17 @@ namespace TransactionProcessor.BusinessLogic.Tests.Services; public class MerchantDomainServiceTests { private readonly Mock> MerchantAggregateRepository; - //private readonly Mock> - // MerchantDepositListAggregateRepository; + private readonly Mock> + MerchantDepositListAggregateRepository; private readonly Mock> EstateAggregateRepository; private readonly Mock SecurityServiceClient; - //private readonly Mock TransactionProcessorClient; - private readonly Mock> ContractAggregateRepository; private readonly MerchantDomainService DomainService; + private readonly Mock EventStoreContext; public MerchantDomainServiceTests() { IConfigurationRoot configurationRoot = @@ -48,15 +49,16 @@ public MerchantDomainServiceTests() { Logger.Initialise(new NullLogger()); this.MerchantAggregateRepository = new Mock>(); - //this.MerchantDepositListAggregateRepository = - // new Mock>(); + this.MerchantDepositListAggregateRepository = + new Mock>(); this.EstateAggregateRepository = new Mock>(); this.SecurityServiceClient = new Mock(); - //this.TransactionProcessorClient = new Mock(); this.ContractAggregateRepository = new Mock>(); + this.EventStoreContext = new Mock(); this.DomainService = new MerchantDomainService(this.EstateAggregateRepository.Object, - this.MerchantAggregateRepository.Object, //this.MerchantDepositListAggregateRepository.Object, - this.ContractAggregateRepository.Object, this.SecurityServiceClient.Object); + this.MerchantAggregateRepository.Object, this.MerchantDepositListAggregateRepository.Object, + this.ContractAggregateRepository.Object, this.SecurityServiceClient.Object, + this.EventStoreContext.Object); } [Theory] @@ -429,125 +431,125 @@ public async Task MerchantDomainService_AddDeviceToMerchant_MerchantNotCreated_E result.IsFailed.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantDeposit_DepositIsMade() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); - - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); - - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success()); - - //var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); - //result.IsSuccess.ShouldBeTrue(); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); + + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + this.MerchantDepositListAggregateRepository + .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); + this.MerchantDepositListAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success()); + + var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantDeposit_GetDepositListFailed_ResultIsFailed() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); - - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); - - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Failure()); - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success()); - - //var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); - //result.IsFailed.ShouldBeTrue(); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); + + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + this.MerchantDepositListAggregateRepository + .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); + this.MerchantDepositListAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success()); + + var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantDeposit_DepositListSaveFailed_ResultIsFailed() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); - - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); - - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Failure); - - //var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); - //result.IsFailed.ShouldBeTrue(); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); + + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + this.MerchantDepositListAggregateRepository + .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); + this.MerchantDepositListAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure); + + var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantDeposit_EstateNotCreated_ErrorThrown() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyEstateAggregate)); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyEstateAggregate)); - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); - //var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); - //result.IsFailed.ShouldBeTrue(); + var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantDeposit_MerchantNotCreated_ErrorThrown() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); - //var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); - //result.IsFailed.ShouldBeTrue(); + var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantDeposit_NoDepositsYet_DepositIsMade() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); - - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); - - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyMerchantDepositListAggregate)); - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success()); - - //var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); - //result.IsSuccess.ShouldBeTrue(); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); + + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + this.MerchantDepositListAggregateRepository + .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyMerchantDepositListAggregate)); + this.MerchantDepositListAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success()); + + var result = await this.DomainService.MakeMerchantDeposit(TestData.Commands.MakeMerchantDepositCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); } [Fact] @@ -595,182 +597,160 @@ public async Task MerchantDomainService_SwapMerchantDevice_EstateNotCreated_Erro result.IsFailed.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantWithdrawal_WithdrawalIsMade() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); - - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); - - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success()); - - //this.SecurityServiceClient - // .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.TokenResponse())); - - //this.TransactionProcessorClient - // .Setup(t => t.GetMerchantBalance(It.IsAny(), It.IsAny(), It.IsAny(), - // It.IsAny(), true)).ReturnsAsync(TestData.MerchantBalance); - - //var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); - //result.IsSuccess.ShouldBeTrue(); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); + + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + this.MerchantDepositListAggregateRepository + .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); + this.MerchantDepositListAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success()); + + this.SecurityServiceClient + .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.TokenResponse())); + + this.EventStoreContext.Setup(e => e.GetPartitionStateFromProjection(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(JsonConvert.SerializeObject(TestData.MerchantBalanceProjectionState))); + + var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantWithdrawal_GetDepositListFailed_ResultIsFailed() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); - - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); - - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Failure()); - - //this.SecurityServiceClient - // .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.TokenResponse())); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); - //this.TransactionProcessorClient - // .Setup(t => t.GetMerchantBalance(It.IsAny(), It.IsAny(), It.IsAny(), - // It.IsAny(), true)).ReturnsAsync(TestData.MerchantBalance); + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); - //var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); - //result.IsFailed.ShouldBeTrue(); + this.MerchantDepositListAggregateRepository + .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); + + this.SecurityServiceClient + .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.TokenResponse())); + + var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantWithdrawal_EstateNotCreated_ErrorThrown() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyEstateAggregate)); - - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); - - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success()); - - //this.SecurityServiceClient - // .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.TokenResponse())); - - //this.TransactionProcessorClient - // .Setup(t => t.GetMerchantBalance(It.IsAny(), It.IsAny(), It.IsAny(), - // It.IsAny(), true)).ReturnsAsync(TestData.MerchantBalance); - - //var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); - //result.IsFailed.ShouldBeTrue(); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyEstateAggregate)); + + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + this.MerchantDepositListAggregateRepository + .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); + this.MerchantDepositListAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success()); + + this.SecurityServiceClient + .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.TokenResponse())); + + var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantWithdrawal_MerchantNotCreated_ErrorThrown() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); - - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); - - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success()); - - //this.SecurityServiceClient - // .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.TokenResponse())); - - //this.TransactionProcessorClient - // .Setup(t => t.GetMerchantBalance(It.IsAny(), It.IsAny(), It.IsAny(), - // It.IsAny(), true)).ReturnsAsync(TestData.MerchantBalance); - - //var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); - //result.IsFailed.ShouldBeTrue(); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); + + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + this.MerchantDepositListAggregateRepository + .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); + this.MerchantDepositListAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success()); + + this.SecurityServiceClient + .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.TokenResponse())); + + var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantWithdrawal_MerchantDepositListNotCreated_ErrorThrown() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); - - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); - - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyMerchantDepositListAggregate)); - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success()); - - //this.SecurityServiceClient - // .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.TokenResponse())); - - //this.TransactionProcessorClient - // .Setup(t => t.GetMerchantBalance(It.IsAny(), It.IsAny(), It.IsAny(), - // It.IsAny(), true)).ReturnsAsync(TestData.MerchantBalance); - - //var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); - //result.IsFailed.ShouldBeTrue(); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); + + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + this.MerchantDepositListAggregateRepository + .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.EmptyMerchantDepositListAggregate)); + this.MerchantDepositListAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success()); + + this.SecurityServiceClient + .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.TokenResponse())); + + var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); } - [Fact(Skip = "Needs MerchantDepositListAggregateRepository")] + [Fact] public async Task MerchantDomainService_MakeMerchantWithdrawal_NotEnoughFundsToWithdraw_ErrorThrown() { - //this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); - - //this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); - //this.MerchantAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success); - - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); - //this.MerchantDepositListAggregateRepository - // .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success()); - - //this.SecurityServiceClient - // .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) - // .ReturnsAsync(Result.Success(TestData.TokenResponse())); - - //this.TransactionProcessorClient - // .Setup(t => t.GetMerchantBalance(It.IsAny(), It.IsAny(), It.IsAny(), - // It.IsAny(), true)).ReturnsAsync(TestData.MerchantBalanceNoAvailableBalance); - - //var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); - //result.IsFailed.ShouldBeTrue(); + this.EstateAggregateRepository.Setup(e => e.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedEstateAggregate())); + + this.MerchantAggregateRepository.Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantAggregate())); + this.MerchantAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + this.MerchantDepositListAggregateRepository + .Setup(m => m.GetLatestVersion(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.CreatedMerchantDepositListAggregate())); + this.MerchantDepositListAggregateRepository + .Setup(m => m.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success()); + + this.SecurityServiceClient + .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.TokenResponse())); + + var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); } [Fact] diff --git a/TransactionProcessor.BusinessLogic.Tests/TransactionProcessor.BusinessLogic.Tests.csproj b/TransactionProcessor.BusinessLogic.Tests/TransactionProcessor.BusinessLogic.Tests.csproj index e20033ab..1b357293 100644 --- a/TransactionProcessor.BusinessLogic.Tests/TransactionProcessor.BusinessLogic.Tests.csproj +++ b/TransactionProcessor.BusinessLogic.Tests/TransactionProcessor.BusinessLogic.Tests.csproj @@ -2,7 +2,7 @@ net8.0 - Full + None false diff --git a/TransactionProcessor.BusinessLogic/Common/Extensions.cs b/TransactionProcessor.BusinessLogic/Common/Extensions.cs index 192e27af..76fbc938 100644 --- a/TransactionProcessor.BusinessLogic/Common/Extensions.cs +++ b/TransactionProcessor.BusinessLogic/Common/Extensions.cs @@ -15,6 +15,7 @@ namespace TransactionProcessor.BusinessLogic.Common using SecurityService.DataTransferObjects.Responses; using Shared.Logger; + [ExcludeFromCodeCoverage] public static class Helpers { public static Guid CalculateSettlementAggregateId(DateTime settlementDate, diff --git a/TransactionProcessor.BusinessLogic/EventHandling/MerchantDomainEventHandler.cs b/TransactionProcessor.BusinessLogic/EventHandling/MerchantDomainEventHandler.cs index c502baba..b2db9134 100644 --- a/TransactionProcessor.BusinessLogic/EventHandling/MerchantDomainEventHandler.cs +++ b/TransactionProcessor.BusinessLogic/EventHandling/MerchantDomainEventHandler.cs @@ -10,23 +10,21 @@ using Shared.Results; using SimpleResults; using TransactionProcessor.Aggregates; +using TransactionProcessor.BusinessLogic.Events; using TransactionProcessor.BusinessLogic.Requests; using TransactionProcessor.DomainEvents; using TransactionProcessor.Models.Merchant; using TransactionProcessor.Repository; using TransactionProcessor.DomainEvents; +using MakeMerchantDepositRequest = TransactionProcessor.DataTransferObjects.Requests.Merchant.MakeMerchantDepositRequest; using MerchantDepositSource = EstateManagement.DataTransferObjects.Requests.Merchant.MerchantDepositSource; namespace TransactionProcessor.BusinessLogic.EventHandling { - //using Deposit = CallbackHandler.DataTransferObjects.Deposit; - public class MerchantDomainEventHandler : IDomainEventHandler { #region Fields - //private readonly IEstateManagementRepository EstateManagementRepository; - private readonly IMediator Mediator; private readonly IAggregateRepository MerchantAggregateRepository; @@ -37,12 +35,10 @@ public class MerchantDomainEventHandler : IDomainEventHandler #region Constructors public MerchantDomainEventHandler(IAggregateRepository merchantAggregateRepository, - //IEstateManagementRepository estateManagementRepository, ITransactionProcessorReadModelRepository estateReportingRepository, IMediator mediator) { this.MerchantAggregateRepository = merchantAggregateRepository; - //this.EstateManagementRepository = estateManagementRepository; this.EstateReportingRepository = estateReportingRepository; this.Mediator = mediator; } @@ -67,7 +63,7 @@ public async Task Handle(IDomainEvent domainEvent, //StatementGeneratedEvent de => this.EstateReportingRepository.UpdateMerchant(de, cancellationToken), TransactionDomainEvents.TransactionHasBeenCompletedEvent de => this.EstateReportingRepository.UpdateMerchant(de, cancellationToken), MerchantDomainEvents.ContractAddedToMerchantEvent de => this.EstateReportingRepository.AddContractToMerchant(de, cancellationToken), - //CallbackReceivedEnrichedEvent de => this.HandleSpecificDomainEvent(de, cancellationToken), + CallbackReceivedEnrichedEvent de => this.HandleSpecificDomainEvent(de, cancellationToken), MerchantDomainEvents.DeviceSwappedForMerchantEvent de => this.EstateReportingRepository.SwapMerchantDevice(de, cancellationToken), MerchantDomainEvents.OperatorRemovedFromMerchantEvent de => this.EstateReportingRepository.RemoveOperatorFromMerchant(de, cancellationToken), MerchantDomainEvents.MerchantAddressLine1UpdatedEvent de => this.EstateReportingRepository.UpdateMerchantAddress(de,cancellationToken), @@ -89,36 +85,37 @@ public async Task Handle(IDomainEvent domainEvent, return Result.Success(); } - //private async Task HandleSpecificDomainEvent(CallbackReceivedEnrichedEvent domainEvent, - // CancellationToken cancellationToken) - //{ - // if (domainEvent.TypeString == typeof(Deposit).ToString()) - // { - // // Work out the merchant id from the reference field (second part, split on hyphen) - // String merchantReference = domainEvent.Reference.Split("-")[1]; - - // Result result = await this.EstateManagementRepository.GetMerchantFromReference(domainEvent.EstateId, merchantReference, cancellationToken); - // if (result.IsFailed) - // return ResultHelpers.CreateFailure(result); - - // // We now need to deserialise the message from the callback - // Deposit callbackMessage = JsonConvert.DeserializeObject(domainEvent.CallbackMessage); - - // MerchantCommands.MakeMerchantDepositCommand command = new(domainEvent.EstateId, - // result.Data.MerchantId, - // MerchantDepositSource.Automatic, - // new MakeMerchantDepositRequest{ - // DepositDateTime = callbackMessage.DateTime, - // Reference = callbackMessage.Reference, - // Amount = callbackMessage.Amount, - // }); - // return await this.Mediator.Send(command, cancellationToken); - // } - // return Result.Success(); - //} - - - + private async Task HandleSpecificDomainEvent(CallbackReceivedEnrichedEvent domainEvent, + CancellationToken cancellationToken) + { + if (domainEvent.TypeString == typeof(CallbackHandler.DataTransferObjects.Deposit).ToString()) + { + // Work out the merchant id from the reference field (second part, split on hyphen) + String merchantReference = domainEvent.Reference.Split("-")[1]; + + Result result = await this.EstateReportingRepository.GetMerchantFromReference(domainEvent.EstateId, merchantReference, cancellationToken); + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); + + // We now need to deserialise the message from the callback + CallbackHandler.DataTransferObjects.Deposit callbackMessage = JsonConvert.DeserializeObject(domainEvent.CallbackMessage); + + MerchantCommands.MakeMerchantDepositCommand command = new(domainEvent.EstateId, + result.Data.MerchantId, + DataTransferObjects.Requests.Merchant.MerchantDepositSource.Automatic, + new MakeMerchantDepositRequest + { + DepositDateTime = callbackMessage.DateTime, + Reference = callbackMessage.Reference, + Amount = callbackMessage.Amount, + }); + return await this.Mediator.Send(command, cancellationToken); + } + return Result.Success(); + } + + + #endregion } diff --git a/TransactionProcessor.BusinessLogic/Events/CallbackReceivedEnrichedEvent.cs b/TransactionProcessor.BusinessLogic/Events/CallbackReceivedEnrichedEvent.cs new file mode 100644 index 00000000..421950aa --- /dev/null +++ b/TransactionProcessor.BusinessLogic/Events/CallbackReceivedEnrichedEvent.cs @@ -0,0 +1,82 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using Newtonsoft.Json; +using Shared.DomainDrivenDesign.EventSourcing; + +namespace TransactionProcessor.BusinessLogic.Events +{ + [ExcludeFromCodeCoverage] + public record CallbackReceivedEnrichedEvent : DomainEvent + { + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The aggregate identifier. + public CallbackReceivedEnrichedEvent(Guid aggregateId) : base(aggregateId, Guid.NewGuid()) + { + } + + public CallbackReceivedEnrichedEvent(Guid aggregateId, Guid estateId, Int32 messageFormat, + String reference, String typeString, + String callbackMessage) : base(aggregateId, Guid.NewGuid()){ + this.EstateId = estateId; + this.MessageFormat = messageFormat; + this.Reference = reference; + this.TypeString = typeString; + this.CallbackMessage = callbackMessage; + } + + #endregion + + #region Properties + + /// + /// Gets or sets the callback message. + /// + /// + /// The callback message. + /// + [JsonProperty("callbackMessage")] + public String CallbackMessage { get; set; } + + /// + /// Gets or sets the estate identifier. + /// + /// + /// The estate identifier. + /// + [JsonProperty("estateid")] + public Guid EstateId { get; set; } + + /// + /// Gets or sets the message format. + /// + /// + /// The message format. + /// + [JsonProperty("messageFormat")] + public Int32 MessageFormat { get; set; } + + /// + /// Gets or sets the reference. + /// + /// + /// The reference. + /// + [JsonProperty("reference")] + public String Reference { get; set; } + + /// + /// Gets or sets the type string. + /// + /// + /// The type string. + /// + [JsonProperty("typeString")] + public String TypeString { get; set; } + + #endregion + } +} \ No newline at end of file diff --git a/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs b/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs index 3be2796d..f573dbdb 100644 --- a/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs +++ b/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs @@ -103,8 +103,7 @@ public async Task Handle(MerchantCommands.AddMerchantDeviceCommand comma public async Task Handle(MerchantCommands.MakeMerchantDepositCommand command, CancellationToken cancellationToken) { - return Result.Success(); - //return await this.MerchantDomainService.MakeMerchantDeposit(command, cancellationToken); + return await this.MerchantDomainService.MakeMerchantDeposit(command, cancellationToken); } public async Task Handle(MerchantCommands.SwapMerchantDeviceCommand command, @@ -116,8 +115,7 @@ public async Task Handle(MerchantCommands.SwapMerchantDeviceCommand comm public async Task Handle(MerchantCommands.MakeMerchantWithdrawalCommand command, CancellationToken cancellationToken) { - return Result.Success(); - //return await this.MerchantDomainService.MakeMerchantWithdrawal(command, cancellationToken); + return await this.MerchantDomainService.MakeMerchantWithdrawal(command, cancellationToken); } public async Task Handle(MerchantCommands.AddMerchantContractCommand command, CancellationToken cancellationToken) diff --git a/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs b/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs index 22644d83..3af5d68f 100644 --- a/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs @@ -1,7 +1,9 @@ -using SecurityService.Client; +using Newtonsoft.Json; +using SecurityService.Client; using SecurityService.DataTransferObjects; using Shared.DomainDrivenDesign.EventSourcing; using Shared.EventStore.Aggregate; +using Shared.EventStore.EventStore; using Shared.Exceptions; using Shared.Results; using Shared.ValueObjects; @@ -16,6 +18,7 @@ using TransactionProcessor.BusinessLogic.Requests; using TransactionProcessor.Models.Estate; using TransactionProcessor.Models.Merchant; +using TransactionProcessor.ProjectionEngine.State; using Operator = TransactionProcessor.Models.Operator.Operator; namespace TransactionProcessor.BusinessLogic.Services @@ -28,8 +31,8 @@ public interface IMerchantDomainService Task CreateMerchantUser(MerchantCommands.CreateMerchantUserCommand command, CancellationToken cancellationToken); Task AddDeviceToMerchant(MerchantCommands.AddMerchantDeviceCommand command, CancellationToken cancellationToken); Task SwapMerchantDevice(MerchantCommands.SwapMerchantDeviceCommand command, CancellationToken cancellationToken); - //Task MakeMerchantDeposit(MerchantCommands.MakeMerchantDepositCommand command, CancellationToken cancellationToken); - //Task MakeMerchantWithdrawal(MerchantCommands.MakeMerchantWithdrawalCommand command, CancellationToken cancellationToken); + Task MakeMerchantDeposit(MerchantCommands.MakeMerchantDepositCommand command, CancellationToken cancellationToken); + Task MakeMerchantWithdrawal(MerchantCommands.MakeMerchantWithdrawalCommand command, CancellationToken cancellationToken); Task AddContractToMerchant(MerchantCommands.AddMerchantContractCommand command, CancellationToken cancellationToken); Task UpdateMerchant(MerchantCommands.UpdateMerchantCommand command, CancellationToken cancellationToken); Task AddMerchantAddress(MerchantCommands.AddMerchantAddressCommand command, CancellationToken cancellationToken); @@ -50,11 +53,12 @@ public class MerchantDomainService : IMerchantDomainService private readonly IAggregateRepository MerchantAggregateRepository; - //private readonly IAggregateRepository MerchantDepositListAggregateRepository; + private readonly IAggregateRepository MerchantDepositListAggregateRepository; private readonly IAggregateRepository ContractAggregateRepository; private readonly ISecurityServiceClient SecurityServiceClient; + private readonly IEventStoreContext EventStoreContext; #endregion @@ -62,15 +66,17 @@ public class MerchantDomainService : IMerchantDomainService public MerchantDomainService(IAggregateRepository estateAggregateRepository, IAggregateRepository merchantAggregateRepository, - //IAggregateRepository merchantDepositListAggregateRepository, + IAggregateRepository merchantDepositListAggregateRepository, IAggregateRepository contractAggregateRepository, - ISecurityServiceClient securityServiceClient) + ISecurityServiceClient securityServiceClient, + IEventStoreContext eventStoreContext) { this.EstateAggregateRepository = estateAggregateRepository; this.MerchantAggregateRepository = merchantAggregateRepository; - //this.MerchantDepositListAggregateRepository = merchantDepositListAggregateRepository; + this.MerchantDepositListAggregateRepository = merchantDepositListAggregateRepository; this.ContractAggregateRepository = contractAggregateRepository; this.SecurityServiceClient = securityServiceClient; + this.EventStoreContext = eventStoreContext; } #endregion @@ -291,91 +297,101 @@ public async Task CreateMerchantUser(MerchantCommands.CreateMerchantUser return Result.Success(); } - //public async Task MakeMerchantDeposit(MerchantCommands.MakeMerchantDepositCommand command, CancellationToken cancellationToken) - //{ - // Result result = await ApplyUpdates( - // async ((EstateAggregate estateAggregate, MerchantAggregate merchantAggregate) aggregates) => { + public async Task MakeMerchantDeposit(MerchantCommands.MakeMerchantDepositCommand command, CancellationToken cancellationToken) + { + Result result = await ApplyUpdates( + async ((EstateAggregate estateAggregate, MerchantAggregate merchantAggregate) aggregates) => { - // Result result = - // this.ValidateEstateAndMerchant(aggregates.estateAggregate, aggregates.merchantAggregate); - // if (result.IsFailed) - // return ResultHelpers.CreateFailure(result); + Result result = + this.ValidateEstateAndMerchant(aggregates.estateAggregate, aggregates.merchantAggregate); + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); - // Result getDepositListResult = await this.MerchantDepositListAggregateRepository.GetLatestVersion(command.MerchantId, cancellationToken); - // Result merchantDepositListAggregateResult = - // DomainServiceHelper.HandleGetAggregateResult(getDepositListResult, command.MerchantId, false); - // if (merchantDepositListAggregateResult.IsFailed) - // return ResultHelpers.CreateFailure(merchantDepositListAggregateResult); + Result getDepositListResult = await this.MerchantDepositListAggregateRepository.GetLatestVersion(command.MerchantId, cancellationToken); + Result merchantDepositListAggregateResult = + DomainServiceHelper.HandleGetAggregateResult(getDepositListResult, command.MerchantId, false); + if (merchantDepositListAggregateResult.IsFailed) + return ResultHelpers.CreateFailure(merchantDepositListAggregateResult); - // MerchantDepositListAggregate merchantDepositListAggregate = merchantDepositListAggregateResult.Data; - // if (merchantDepositListAggregate.IsCreated == false) - // { - // merchantDepositListAggregate.Create(aggregates.merchantAggregate, command.RequestDto.DepositDateTime); - // } + MerchantDepositListAggregate merchantDepositListAggregate = merchantDepositListAggregateResult.Data; + if (merchantDepositListAggregate.IsCreated == false) + { + merchantDepositListAggregate.Create(aggregates.merchantAggregate, command.RequestDto.DepositDateTime); + } - // PositiveMoney amount = PositiveMoney.Create(Money.Create(command.RequestDto.Amount)); + PositiveMoney amount = PositiveMoney.Create(Money.Create(command.RequestDto.Amount)); + MerchantDepositSource depositSource = command.DepositSource switch + { + DataTransferObjects.Requests.Merchant.MerchantDepositSource.Manual => Models.Merchant.MerchantDepositSource.Manual, + _ => Models.Merchant.MerchantDepositSource.Automatic, + }; + merchantDepositListAggregate.MakeDeposit(depositSource, command.RequestDto.Reference, command.RequestDto.DepositDateTime, amount); - // merchantDepositListAggregate.MakeDeposit(command.DepositSource, command.RequestDto.Reference, command.RequestDto.DepositDateTime, amount); + Result saveResult = await this.MerchantDepositListAggregateRepository.SaveChanges(merchantDepositListAggregate, cancellationToken); + if (saveResult.IsFailed) + return ResultHelpers.CreateFailure(saveResult); - // Result saveResult = await this.MerchantDepositListAggregateRepository.SaveChanges(merchantDepositListAggregate, cancellationToken); - // if (saveResult.IsFailed) - // return ResultHelpers.CreateFailure(saveResult); + return Result.Success(); + }, command.EstateId, command.MerchantId, cancellationToken); - // return Result.Success(); - // }, command.EstateId, command.MerchantId, cancellationToken); + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); - // if (result.IsFailed) - // return ResultHelpers.CreateFailure(result); + return Result.Success(); + } - // return Result.Success(); - //} + public async Task MakeMerchantWithdrawal(MerchantCommands.MakeMerchantWithdrawalCommand command, + CancellationToken cancellationToken) + { - //public async Task MakeMerchantWithdrawal(MerchantCommands.MakeMerchantWithdrawalCommand command, - // CancellationToken cancellationToken) - //{ + Result result = await ApplyUpdates( + async ((EstateAggregate estateAggregate, MerchantAggregate merchantAggregate) aggregates) => + { - // Result result = await ApplyUpdates( - // async ((EstateAggregate estateAggregate, MerchantAggregate merchantAggregate) aggregates) => { + Result result = + this.ValidateEstateAndMerchant(aggregates.estateAggregate, aggregates.merchantAggregate); + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); - // Result result = - // this.ValidateEstateAndMerchant(aggregates.estateAggregate, aggregates.merchantAggregate); - // if (result.IsFailed) - // return ResultHelpers.CreateFailure(result); + Result getDepositListResult = await this.MerchantDepositListAggregateRepository.GetLatestVersion(command.MerchantId, cancellationToken); + Result merchantDepositListAggregateResult = + DomainServiceHelper.HandleGetAggregateResult(getDepositListResult, command.MerchantId, false); + if (merchantDepositListAggregateResult.IsFailed) + return ResultHelpers.CreateFailure(merchantDepositListAggregateResult); - // Result getDepositListResult = await this.MerchantDepositListAggregateRepository.GetLatestVersion(command.MerchantId, cancellationToken); - // Result merchantDepositListAggregateResult = - // DomainServiceHelper.HandleGetAggregateResult(getDepositListResult, command.MerchantId, false); - // if (merchantDepositListAggregateResult.IsFailed) - // return ResultHelpers.CreateFailure(merchantDepositListAggregateResult); + MerchantDepositListAggregate merchantDepositListAggregate = merchantDepositListAggregateResult.Data; + if (merchantDepositListAggregate.IsCreated == false) + { + return Result.Invalid($"Merchant [{command.MerchantId}] has not made any deposits yet"); + } - // MerchantDepositListAggregate merchantDepositListAggregate = merchantDepositListAggregateResult.Data; - // if (merchantDepositListAggregate.IsCreated == false) - // { - // return Result.Invalid($"Merchant [{command.MerchantId}] has not made any deposits yet"); - // } + // Now we need to check the merchants balance to ensure they have funds to withdraw + Result getBalanceResult = await this.EventStoreContext.GetPartitionStateFromProjection("MerchantBalanceProjection", $"MerchantBalance-{command.MerchantId:N}", cancellationToken); + if (getBalanceResult.IsFailed) + { + Result.Invalid($"Failed to get Merchant Balance."); + } - // // Now we need to check the merchants balance to ensure they have funds to withdraw - // this.TokenResponse = await Helpers.GetToken(this.TokenResponse, this.SecurityServiceClient, cancellationToken); - // MerchantBalanceResponse merchantBalance = await this.TransactionProcessorClient.GetMerchantBalance(this.TokenResponse.AccessToken, command.EstateId, command.MerchantId, cancellationToken); + MerchantBalanceProjectionState1 projectionState = JsonConvert.DeserializeObject(getBalanceResult.Data); - // if (command.RequestDto.Amount > merchantBalance.Balance) - // { - // return Result.Invalid($"Not enough credit available for withdrawal of [{command.RequestDto.Amount}]. Balance is {merchantBalance}"); - // } + if (command.RequestDto.Amount > projectionState.merchant.balance) + { + return Result.Invalid($"Not enough credit available for withdrawal of [{command.RequestDto.Amount}]. Balance is {projectionState.merchant.balance}"); + } - // // If we are here we have enough credit to withdraw - // PositiveMoney amount = PositiveMoney.Create(Money.Create(command.RequestDto.Amount)); + // If we are here we have enough credit to withdraw + PositiveMoney amount = PositiveMoney.Create(Money.Create(command.RequestDto.Amount)); - // merchantDepositListAggregate.MakeWithdrawal(command.RequestDto.WithdrawalDateTime, amount); + merchantDepositListAggregate.MakeWithdrawal(command.RequestDto.WithdrawalDateTime, amount); - // return Result.Success(); - // }, command.EstateId, command.MerchantId, cancellationToken); + return Result.Success(); + }, command.EstateId, command.MerchantId, cancellationToken); - // if (result.IsFailed) - // return ResultHelpers.CreateFailure(result); + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); - // return Result.Success(); - //} + return Result.Success(); + } /// /// The token response diff --git a/TransactionProcessor.BusinessLogic/TransactionProcessor.BusinessLogic.csproj b/TransactionProcessor.BusinessLogic/TransactionProcessor.BusinessLogic.csproj index 6eb524e4..e4205e68 100644 --- a/TransactionProcessor.BusinessLogic/TransactionProcessor.BusinessLogic.csproj +++ b/TransactionProcessor.BusinessLogic/TransactionProcessor.BusinessLogic.csproj @@ -5,6 +5,7 @@ + diff --git a/TransactionProcessor.Repository/ITransactionProcessorReadModelRepository.cs b/TransactionProcessor.Repository/ITransactionProcessorReadModelRepository.cs index 7cbc7686..74584a2a 100644 --- a/TransactionProcessor.Repository/ITransactionProcessorReadModelRepository.cs +++ b/TransactionProcessor.Repository/ITransactionProcessorReadModelRepository.cs @@ -23,7 +23,9 @@ namespace TransactionProcessor.Repository { public interface ITransactionProcessorReadModelRepository { - + Task> GetMerchantFromReference(Guid estateId, + String reference, + CancellationToken cancellationToken); Task UpdateOperator(OperatorDomainEvents.OperatorNameUpdatedEvent domainEvent, CancellationToken cancellationToken); @@ -289,6 +291,20 @@ public TransactionProcessorReadModelRepository(Shared.EntityFramework.IDbContext } + public async Task> GetMerchantFromReference(Guid estateId, + String reference, + CancellationToken cancellationToken) + { + EstateManagementGenericContext context = await this.DbContextFactory.GetContext(estateId, ConnectionStringIdentifier, cancellationToken); + + Merchant merchant = await (from m in context.Merchants where m.Reference == reference select m).SingleOrDefaultAsync(cancellationToken); + + if (merchant == null) + return Result.NotFound($"No merchant found with reference {reference}"); + + return Result.Success(ModelFactory.ConvertFrom(estateId, merchant, null, null, null, null, null)); + } + public async Task AddMerchant(MerchantDomainEvents.MerchantCreatedEvent domainEvent, CancellationToken cancellationToken) { diff --git a/TransactionProcessor.Repository/ModelFactory.cs b/TransactionProcessor.Repository/ModelFactory.cs index 537cce7a..713419ba 100644 --- a/TransactionProcessor.Repository/ModelFactory.cs +++ b/TransactionProcessor.Repository/ModelFactory.cs @@ -23,6 +23,93 @@ namespace TransactionProcessor.Repository public static class ModelFactory { + //public static MerchantModel ConvertFrom(Guid estateId, MerchantEntity merchant) + //{ + // MerchantModel merchantModel = new MerchantModel(); + // merchantModel.EstateId = estateId; + // merchantModel.MerchantReportingId = merchant.MerchantReportingId; + // merchantModel.MerchantId = merchant.MerchantId; + // merchantModel.MerchantName = merchant.Name; + // merchantModel.Reference = merchant.Reference; + // merchantModel.SettlementSchedule = (SettlementSchedule)merchant.SettlementSchedule; + + // return merchantModel; + //} + + //public static MerchantModel ConvertFrom(Guid estateId, + // MerchantEntity merchant, + // List merchantAddresses, + // List merchantContacts, + // List merchantOperators, + // List merchantDevices, + // List merchantSecurityUsers) + //{ + // MerchantModel merchantModel = this.ConvertFrom(estateId, merchant); + + // if (merchantAddresses != null && merchantAddresses.Any()) + // { + // merchantModel.Addresses = new List(); + // merchantAddresses.ForEach(ma => merchantModel.Addresses.Add(new MerchantAddressModel + // { + // AddressId = ma.AddressId, + // AddressLine1 = ma.AddressLine1, + // AddressLine2 = ma.AddressLine2, + // AddressLine3 = ma.AddressLine3, + // AddressLine4 = ma.AddressLine4, + // Country = ma.Country, + // PostalCode = ma.PostalCode, + // Region = ma.Region, + // Town = ma.Town + // })); + // } + + // if (merchantContacts != null && merchantContacts.Any()) + // { + // merchantModel.Contacts = new List(); + // merchantContacts.ForEach(mc => merchantModel.Contacts.Add(new MerchantContactModel + // { + // ContactEmailAddress = mc.EmailAddress, + // ContactId = mc.ContactId, + // ContactName = mc.Name, + // ContactPhoneNumber = mc.PhoneNumber + // })); + // } + + // if (merchantOperators != null && merchantOperators.Any()) + // { + // merchantModel.Operators = new List(); + // merchantOperators.ForEach(mo => merchantModel.Operators.Add(new MerchantOperatorModel + // { + // Name = mo.Name, + // MerchantNumber = mo.MerchantNumber, + // OperatorId = mo.OperatorId, + // TerminalNumber = mo.TerminalNumber + // })); + // } + + // if (merchantDevices != null && merchantDevices.Any()) + // { + // merchantModel.Devices = new List(); + // merchantDevices.ForEach(md => merchantModel.Devices.Add(new Device + // { + // DeviceIdentifier = md.DeviceIdentifier, + // DeviceId = md.DeviceId, + // })); + // } + + // if (merchantSecurityUsers != null && merchantSecurityUsers.Any()) + // { + // merchantModel.SecurityUsers = new List(); + // merchantSecurityUsers.ForEach(msu => merchantModel.SecurityUsers.Add(new SecurityUserModel + // { + // EmailAddress = msu.EmailAddress, + // SecurityUserId = msu.SecurityUserId + // })); + // } + + // return merchantModel; + //} + public static EstateModel ConvertFrom(EstateEntity estate, List estateSecurityUsers, List operators) diff --git a/TransactionProcessor.Repository/TransactionProcessor.Repository.csproj b/TransactionProcessor.Repository/TransactionProcessor.Repository.csproj index c91ccd93..eda23eee 100644 --- a/TransactionProcessor.Repository/TransactionProcessor.Repository.csproj +++ b/TransactionProcessor.Repository/TransactionProcessor.Repository.csproj @@ -4,6 +4,7 @@ net8.0 enable enable + None diff --git a/TransactionProcessor.Testing/TestData.cs b/TransactionProcessor.Testing/TestData.cs index 0a27665a..b4e4c3ca 100644 --- a/TransactionProcessor.Testing/TestData.cs +++ b/TransactionProcessor.Testing/TestData.cs @@ -1,4 +1,7 @@ -using TransactionProcessor.Aggregates; +using CallbackHandler.DataTransferObjects; +using Newtonsoft.Json; +using TransactionProcessor.Aggregates; +using TransactionProcessor.BusinessLogic.Events; using TransactionProcessor.DataTransferObjects.Requests.Contract; using TransactionProcessor.DataTransferObjects.Requests.Estate; using TransactionProcessor.DataTransferObjects.Requests.Merchant; @@ -7,9 +10,14 @@ using TransactionProcessor.DataTransferObjects.Responses.Merchant; using TransactionProcessor.DomainEvents; using TransactionProcessor.Models.Contract; +using TransactionProcessor.Models.Merchant; using Address = TransactionProcessor.DataTransferObjects.Requests.Merchant.Address; using AssignOperatorRequest = TransactionProcessor.DataTransferObjects.Requests.Estate.AssignOperatorRequest; using Contact = TransactionProcessor.DataTransferObjects.Requests.Merchant.Contact; +using Contract = TransactionProcessor.Models.Merchant.Contract; +using Deposit = CallbackHandler.DataTransferObjects.Deposit; +using MerchantDepositSource = TransactionProcessor.DataTransferObjects.Requests.Merchant.MerchantDepositSource; +using SettlementSchedule = TransactionProcessor.DataTransferObjects.Responses.Merchant.SettlementSchedule; using SettlementScheduleModel = TransactionProcessor.Models.Merchant.SettlementSchedule; namespace TransactionProcessor.Testing @@ -30,16 +38,174 @@ namespace TransactionProcessor.Testing using TransactionProcessor.Models.Estate; using System.Linq; using ContractProductTransactionFeeModel = Models.Contract.ContractProductTransactionFee; - using static TransactionProcessor.DomainEvents.ContractDomainEvents; - + using Shared.ValueObjects; + public class TestData { #region Fields + public static List MerchantContractsEmptyList => new List(); + + public static List MerchantContracts => + new List{ + new Models.Contract.Contract{ + ContractId = TestData.ContractId, + Description = TestData.ContractDescription, + OperatorId = TestData.OperatorId, + OperatorName = TestData.OperatorName, + Products = new List{ + new Product{ + ContractProductId = TestData.ContractProductId, + Value = TestData.ProductFixedValue, + DisplayText = TestData.ProductDisplayText, + Name = TestData.ProductName + } + } + } + }; + + public static List ProductTransactionFees => + new List{ + new ContractProductTransactionFeeModel{ + TransactionFeeId = TestData.TransactionFeeId, + Description = TestData.TransactionFeeDescription, + Value = TestData.TransactionFeeValue, + CalculationType = CalculationType.Fixed + } + }; + + public static Models.Merchant.Merchant MerchantModelWithNullAddresses => + new Models.Merchant.Merchant + { + MerchantId = TestData.MerchantId, + MerchantName = TestData.MerchantName, + SettlementSchedule = Models.Merchant.SettlementSchedule.Immediate, + Addresses = null, + Contacts = new List{ + new Models.Merchant.Contact(Guid.NewGuid(), MerchantContactEmailAddress, MerchantContactName, MerchantContactPhoneNumber) + }, + Devices = new List{ + new Device(DeviceId, DeviceIdentifier, true) + }, + Operators = new List{ + new Models.Merchant.Operator(TestData.OperatorId,TestData.OperatorName,TestData.OperatorMerchantNumber,TestData.OperatorTerminalNumber) + } + }; + + public static Models.Merchant.Merchant MerchantModelWithNullContacts=> + new Models.Merchant.Merchant + { + MerchantId = TestData.MerchantId, + MerchantName = TestData.MerchantName, + SettlementSchedule = Models.Merchant.SettlementSchedule.Immediate, + Addresses = new List{ + new Models.Merchant.Address(Guid.NewGuid(), MerchantAddressLine1,MerchantAddressLine2, + MerchantAddressLine3,MerchantAddressLine4, MerchantTown,MerchantRegion, + MerchantPostalCode, MerchantCountry) + }, + Contacts = null, + Devices = new List{ + new Device(DeviceId, DeviceIdentifier, true) + }, + Operators = new List{ + new Models.Merchant.Operator(TestData.OperatorId,TestData.OperatorName,TestData.OperatorMerchantNumber,TestData.OperatorTerminalNumber) + } + }; + + public static Models.Merchant.Merchant MerchantModelWithNullDevices => + new Models.Merchant.Merchant + { + MerchantId = TestData.MerchantId, + MerchantName = TestData.MerchantName, + SettlementSchedule = Models.Merchant.SettlementSchedule.Immediate, + Addresses = new List{ + new Models.Merchant.Address(Guid.NewGuid(), MerchantAddressLine1,MerchantAddressLine2, + MerchantAddressLine3,MerchantAddressLine4, MerchantTown,MerchantRegion, + MerchantPostalCode, MerchantCountry) + }, + Contacts = new List{ + new Models.Merchant.Contact(Guid.NewGuid(), MerchantContactEmailAddress, MerchantContactName, MerchantContactPhoneNumber) + }, + Devices = null, + Operators = new List{ + new Models.Merchant.Operator(TestData.OperatorId,TestData.OperatorName,TestData.OperatorMerchantNumber,TestData.OperatorTerminalNumber) + } + }; + + public static Models.Merchant.Merchant MerchantModelWithNullOperators => + new Models.Merchant.Merchant{ + MerchantId = TestData.MerchantId, + MerchantName = TestData.MerchantName, + SettlementSchedule = Models.Merchant.SettlementSchedule.Immediate, + Addresses = new List{ + new Models.Merchant.Address(Guid.NewGuid(), MerchantAddressLine1,MerchantAddressLine2, + MerchantAddressLine3,MerchantAddressLine4, MerchantTown,MerchantRegion, + MerchantPostalCode, MerchantCountry) + }, + Contacts = new List{ + new Models.Merchant.Contact(Guid.NewGuid(), MerchantContactEmailAddress, MerchantContactName, MerchantContactPhoneNumber) + }, + Devices = new List{ + new Device(DeviceId, DeviceIdentifier, true) + }, + Operators = null + }; + + public static Models.Contract.Contract ContractModelWithProducts => + new Models.Contract.Contract + { + OperatorId = TestData.OperatorId, + ContractId = TestData.ContractId, + Description = TestData.ContractDescription, + IsCreated = true, + Products = new List{ + new Product{ + Value = TestData.ProductFixedValue, + ContractProductId = TestData.ContractProductId, + DisplayText = TestData.ProductDisplayText, + Name = TestData.ProductName, + TransactionFees = null + } + } + }; + + public static Models.Contract.Contract ContractModel => + new Models.Contract.Contract + { + OperatorId = TestData.OperatorId, + ContractId = TestData.ContractId, + Description = TestData.ContractDescription, + IsCreated = true, + Products = null + }; + + + public static PositiveMoney WithdrawalAmount = PositiveMoney.Create(Money.Create(1000.00m)); + + public static PositiveMoney WithdrawalAmount2 = PositiveMoney.Create(Money.Create(1200.00m)); + + public static DateTime WithdrawalDateTime = new DateTime(2019, 11, 16); + + public static DateTime WithdrawalDateTime2 = new DateTime(2019, 11, 16); + + public static PositiveMoney DepositAmount = PositiveMoney.Create(Money.Create(1000.00m)); + + public static PositiveMoney DepositAmount2 = PositiveMoney.Create(Money.Create(1200.00m)); + + public static DateTime DepositDateTime = new DateTime(2019, 11, 16); + + public static DateTime DepositDateTime2 = new DateTime(2019, 11, 16); + public static String DepositReference = "Test Deposit 1"; + + public static String DepositReference2 = "Test Deposit 2"; + public static MerchantDepositSource MerchantDepositSourceManualDTO = MerchantDepositSource.Manual; + public static MerchantDepositSource MerchantDepositSourceAutomaticDTO = MerchantDepositSource.Automatic; + public static Models.Merchant.MerchantDepositSource MerchantDepositSourceManual = Models.Merchant.MerchantDepositSource.Manual; + public static Models.Merchant.MerchantDepositSource MerchantDepositSourceAutomatic = Models.Merchant.MerchantDepositSource.Automatic; public static DataTransferObjects.Responses.Merchant.SettlementSchedule SettlementScheduleDTO = DataTransferObjects.Responses.Merchant.SettlementSchedule.Monthly; public static CreateMerchantRequest CreateMerchantRequest => new CreateMerchantRequest { - Address = new Address + Address = new TransactionProcessor.DataTransferObjects.Requests.Merchant.Address { AddressLine1 = TestData.MerchantAddressLine1, AddressLine2 = TestData.MerchantAddressLine2, @@ -50,7 +216,7 @@ public class TestData Region = TestData.MerchantRegion, Town = TestData.MerchantTown }, - Contact = new Contact + Contact = new TransactionProcessor.DataTransferObjects.Requests.Merchant.Contact { ContactName = TestData.MerchantContactName, EmailAddress = TestData.MerchantContactEmailAddress, @@ -591,7 +757,7 @@ public static Dictionary AdditionalTransactionMetaDataForPataPaw } } }, - SettlementSchedule = SettlementSchedule.Monthly + SettlementSchedule = TransactionProcessor.DataTransferObjects.Responses.Merchant.SettlementSchedule.Monthly }; public static DataTransferObjects.Responses.Merchant.MerchantResponse GetMerchantResponseWithOperator1ImmediateSettlement => @@ -621,7 +787,7 @@ public static Dictionary AdditionalTransactionMetaDataForPataPaw } } }, - SettlementSchedule = SettlementSchedule.Immediate + SettlementSchedule = TransactionProcessor.DataTransferObjects.Responses.Merchant.SettlementSchedule.Immediate }; public static DataTransferObjects.Responses.Merchant.MerchantResponse GetMerchantResponseWithOperator1AndNullContracts => @@ -807,23 +973,10 @@ public static Dictionary AdditionalTransactionMetaDataForPataPaw EstateId = TestData.EstateId, MerchantId = TestData.MerchantId, MerchantName = TestData.MerchantName, - SettlementSchedule = SettlementSchedule.Immediate + SettlementSchedule = TransactionProcessor.DataTransferObjects.Responses.Merchant.SettlementSchedule.Immediate }; - public static TransactionCommands.ProcessLogonTransactionCommand ProcessLogonTransactionCommand => - new(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.DeviceIdentifier, - TestData.TransactionTypeLogon.ToString(), - TestData.TransactionDateTime, - TestData.TransactionNumber); - - public static SettlementCommands.ProcessSettlementCommand ProcessSettlementCommand => - new(TestData.SettlementDate, - TestData.MerchantId, - TestData.EstateId); - + public static ProcessLogonTransactionResponse ProcessLogonTransactionResponseModel => new ProcessLogonTransactionResponse { @@ -831,40 +984,6 @@ public static Dictionary AdditionalTransactionMetaDataForPataPaw ResponseCode = TestData.ResponseCode }; - public static MerchantQueries.GetMerchantBalanceQuery GetMerchantBalanceQuery => new(EstateId, MerchantId); - - public static MerchantQueries.GetMerchantLiveBalanceQuery GetMerchantLiveBalanceQuery => new(MerchantId); - - public static MerchantQueries.GetMerchantBalanceHistoryQuery GetMerchantBalanceHistoryQuery => new MerchantQueries.GetMerchantBalanceHistoryQuery(EstateId, MerchantId, DateTime.MinValue, DateTime.MaxValue); - - public static SettlementCommands.AddMerchantFeePendingSettlementCommand AddMerchantFeePendingSettlementCommand => new(TransactionId, CalculatedFeeValue, TransactionFeeCalculateDateTime, CalculationType.Fixed, TransactionFeeId, CalculatedFeeValue, TransactionFeeSettlementDueDate, MerchantId, EstateId); - public static SettlementCommands.AddSettledFeeToSettlementCommand AddSettledFeeToSettlementCommand => new(SettlementDate,MerchantId,EstateId,TransactionFeeId, TransactionId); - - public static FloatActivityCommands.RecordCreditPurchaseCommand RecordCreditPurchaseCommand => new(EstateId, FloatAggregateId, CreditPurchasedDateTime, FloatCreditAmount, FloatCreditId); - public static FloatActivityCommands.RecordTransactionCommand RecordTransactionCommand => new(EstateId, TransactionId); - public static TransactionCommands.CalculateFeesForTransactionCommand CalculateFeesForTransactionCommand => new(TransactionId, TransactionDateTime, EstateId, MerchantId); - - public static TransactionCommands.AddSettledMerchantFeeCommand AddSettledMerchantFeeCommand => new(TransactionId, CalculatedFeeValue, TransactionFeeCalculateDateTime, CalculationType.Percentage, TransactionFeeId, TransactionFeeValue, SettlementDate, SettlementAggregateId); - - public static VoucherQueries.GetVoucherByVoucherCodeQuery GetVoucherByVoucherCodeQuery => new(EstateId, VoucherCode); - public static VoucherQueries.GetVoucherByTransactionIdQuery GetVoucherByTransactionIdQuery => new(EstateId, TransactionId); - - public static SettlementQueries.GetPendingSettlementQuery GetPendingSettlementQuery => new(SettlementDate, MerchantId, EstateId); - public static TransactionCommands.ProcessSaleTransactionCommand ProcessSaleTransactionCommand => - new(TestData.TransactionId, - TestData.EstateId, - TestData.MerchantId, - TestData.DeviceIdentifier, - TestData.TransactionTypeLogon.ToString(), - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.OperatorId, - TestData.CustomerEmailAddress, - TestData.AdditionalTransactionMetaDataForMobileTopup(), - TestData.ContractId, - TestData.ProductId, - TestData.TransactionSource); - public static ProcessSaleTransactionResponse ProcessSaleTransactionResponseModel => new ProcessSaleTransactionResponse { @@ -887,8 +1006,7 @@ public static Dictionary AdditionalTransactionMetaDataForPataPaw Pin = "1234" }; - public static TransactionCommands.ProcessReconciliationCommand ProcessReconciliationCommand => - new(TestData.TransactionId, TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier, TestData.TransactionDateTime, TestData.ReconciliationTransactionCount, TestData.ReconciliationTransactionValue); + public static ProcessReconciliationTransactionResponse ProcessReconciliationTransactionResponseModel => new ProcessReconciliationTransactionResponse @@ -1395,9 +1513,6 @@ public static TokenResponse TokenResponse() public static MerchantBalanceProjectionState1 MerchantBalanceProjectionStateNoCredit => new MerchantBalanceProjectionState1(TestData.MerchantStateNoCredit); - public static TransactionCommands.ResendTransactionReceiptCommand ResendTransactionReceiptCommand => new(TestData.TransactionId, - TestData.EstateId); - public static List ContractProductTransactionFees => new List { @@ -1828,6 +1943,26 @@ public static DataTransferObjects.Requests.Contract.AddTransactionFeeForProductT Password = TestData.MerchantUserPassword }; + public static MakeMerchantDepositRequest MakeMerchantDepositRequest => + new MakeMerchantDepositRequest + { + DepositDateTime = TestData.DepositDateTime, + Amount = TestData.DepositAmount.Value, + Reference = TestData.DepositReference + }; + + + + public static MakeMerchantWithdrawalRequest MakeMerchantWithdrawalRequest => + new MakeMerchantWithdrawalRequest + { + WithdrawalDateTime = TestData.WithdrawalDateTime, + Amount = TestData.WithdrawalAmount.Value, + Reference = TestData.WithdrawalReference + }; + + public static String WithdrawalReference = "Withdraw1"; + public static String MerchantUserFamilyName = "Merchant"; public static String MerchantUserGivenName = "Test"; @@ -1881,8 +2016,8 @@ public static DataTransferObjects.Requests.Contract.AddTransactionFeeForProductT public static String PostCode = "PostCode"; public static String Region = "Region"; public static String Town = "Town"; - public static Address Address => - new Address + public static TransactionProcessor.DataTransferObjects.Requests.Merchant.Address Address => + new TransactionProcessor.DataTransferObjects.Requests.Merchant.Address { AddressLine1 = TestData.AddressLine1, AddressLine2 = TestData.AddressLine2, @@ -1894,16 +2029,63 @@ public static DataTransferObjects.Requests.Contract.AddTransactionFeeForProductT Town = TestData.Town }; - public static Contact Contact => - new Contact + public static TransactionProcessor.DataTransferObjects.Requests.Merchant.Contact Contact => + new TransactionProcessor.DataTransferObjects.Requests.Merchant.Contact { ContactName = TestData.ContactName, EmailAddress = TestData.ContactEmail, PhoneNumber = TestData.ContactPhone }; + + public static Guid EventId = Guid.Parse("0F537961-A19C-4A29-80DC-68889474142B"); #endregion public static class Commands { + public static TransactionCommands.ResendTransactionReceiptCommand ResendTransactionReceiptCommand => new(TestData.TransactionId, + TestData.EstateId); + + public static SettlementCommands.AddMerchantFeePendingSettlementCommand AddMerchantFeePendingSettlementCommand => new(TransactionId, CalculatedFeeValue, TransactionFeeCalculateDateTime, CalculationType.Fixed, TransactionFeeId, CalculatedFeeValue, TransactionFeeSettlementDueDate, MerchantId, EstateId); + public static SettlementCommands.AddSettledFeeToSettlementCommand AddSettledFeeToSettlementCommand => new(SettlementDate, MerchantId, EstateId, TransactionFeeId, TransactionId); + + public static FloatActivityCommands.RecordCreditPurchaseCommand RecordCreditPurchaseCommand => new(EstateId, FloatAggregateId, CreditPurchasedDateTime, FloatCreditAmount, FloatCreditId); + public static FloatActivityCommands.RecordTransactionCommand RecordTransactionCommand => new(EstateId, TransactionId); + public static TransactionCommands.CalculateFeesForTransactionCommand CalculateFeesForTransactionCommand => new(TransactionId, TransactionDateTime, EstateId, MerchantId); + + public static TransactionCommands.AddSettledMerchantFeeCommand AddSettledMerchantFeeCommand => new(TransactionId, CalculatedFeeValue, TransactionFeeCalculateDateTime, CalculationType.Percentage, TransactionFeeId, TransactionFeeValue, SettlementDate, SettlementAggregateId); + + public static TransactionCommands.ProcessSaleTransactionCommand ProcessSaleTransactionCommand => + new(TestData.TransactionId, + TestData.EstateId, + TestData.MerchantId, + TestData.DeviceIdentifier, + TestData.TransactionTypeLogon.ToString(), + TestData.TransactionDateTime, + TestData.TransactionNumber, + TestData.OperatorId, + TestData.CustomerEmailAddress, + TestData.AdditionalTransactionMetaDataForMobileTopup(), + TestData.ContractId, + TestData.ProductId, + TestData.TransactionSource); + public static TransactionCommands.ProcessReconciliationCommand ProcessReconciliationCommand => + new(TestData.TransactionId, TestData.EstateId, TestData.MerchantId, TestData.DeviceIdentifier, TestData.TransactionDateTime, TestData.ReconciliationTransactionCount, TestData.ReconciliationTransactionValue); + public static TransactionCommands.ProcessLogonTransactionCommand ProcessLogonTransactionCommand => + new(TestData.TransactionId, + TestData.EstateId, + TestData.MerchantId, + TestData.DeviceIdentifier, + TestData.TransactionTypeLogon.ToString(), + TestData.TransactionDateTime, + TestData.TransactionNumber); + + public static SettlementCommands.ProcessSettlementCommand ProcessSettlementCommand => + new(TestData.SettlementDate, + TestData.MerchantId, + TestData.EstateId); + + + public static TransactionCommands.SendCustomerEmailReceiptCommand SendCustomerEmailReceiptCommand => new TransactionCommands.SendCustomerEmailReceiptCommand(EstateId, TransactionId, EventId, CustomerEmailAddress); + public static MerchantCommands.RemoveMerchantContractCommand RemoveMerchantContractCommand => new MerchantCommands.RemoveMerchantContractCommand(TestData.EstateId, TestData.MerchantId, @@ -1983,10 +2165,39 @@ public static ContractCommands.AddTransactionFeeForProductToContractCommand public static OperatorCommands.CreateOperatorCommand CreateOperatorCommand => new(TestData.EstateId, TestData.CreateOperatorRequest); public static OperatorCommands.UpdateOperatorCommand UpdateOperatorCommand => new(TestData.EstateId, TestData.OperatorId, TestData.UpdateOperatorRequest); + public static MerchantCommands.MakeMerchantWithdrawalCommand MakeMerchantWithdrawalCommand => + new(TestData.EstateId, + TestData.MerchantId, + TestData.MakeMerchantWithdrawalRequest); + public static MerchantCommands.MakeMerchantDepositCommand MakeMerchantDepositCommand => + new(TestData.EstateId, + TestData.MerchantId, + MerchantDepositSourceManualDTO, + TestData.MakeMerchantDepositRequest); } public static class Queries { + public static VoucherQueries.GetVoucherByVoucherCodeQuery GetVoucherByVoucherCodeQuery => new(EstateId, VoucherCode); + public static VoucherQueries.GetVoucherByTransactionIdQuery GetVoucherByTransactionIdQuery => new(EstateId, TransactionId); + + public static SettlementQueries.GetPendingSettlementQuery GetPendingSettlementQuery => new(SettlementDate, MerchantId, EstateId); + + public static MerchantQueries.GetMerchantBalanceQuery GetMerchantBalanceQuery => new(EstateId, MerchantId); + + public static MerchantQueries.GetMerchantLiveBalanceQuery GetMerchantLiveBalanceQuery => new(MerchantId); + + public static MerchantQueries.GetMerchantBalanceHistoryQuery GetMerchantBalanceHistoryQuery => new MerchantQueries.GetMerchantBalanceHistoryQuery(EstateId, MerchantId, DateTime.MinValue, DateTime.MaxValue); + + public static MerchantQueries.GetTransactionFeesForProductQuery GetTransactionFeesForProductQuery => + new MerchantQueries.GetTransactionFeesForProductQuery(TestData.EstateId, + TestData.MerchantId, + TestData.ContractId, + TestData.ContractProductId); + public static MerchantQueries.GetMerchantContractsQuery GetMerchantContractsQuery => new MerchantQueries.GetMerchantContractsQuery(TestData.EstateId, TestData.MerchantId); + public static MerchantQueries.GetMerchantQuery GetMerchantQuery => new MerchantQueries.GetMerchantQuery(TestData.EstateId, TestData.MerchantId); + + public static MerchantQueries.GetMerchantsQuery GetMerchantsQuery => new MerchantQueries.GetMerchantsQuery(TestData.EstateId); public static EstateQueries.GetEstateQuery GetEstateQuery => new(TestData.EstateId); public static EstateQueries.GetEstatesQuery GetEstatesQuery => new(TestData.EstateId); @@ -1997,6 +2208,48 @@ public static class Queries { } public static class Aggregates { + public static MerchantAggregate MerchantAggregateWithAddress() + { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + merchantAggregate.AddAddress(TestData.MerchantAddressLine1, + TestData.MerchantAddressLine2, + TestData.MerchantAddressLine3, + TestData.MerchantAddressLine4, + TestData.MerchantTown, + TestData.MerchantRegion, + TestData.MerchantPostalCode, + TestData.MerchantCountry); + + return merchantAggregate; + } + + public static MerchantAggregate MerchantAggregateWithContact() + { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + merchantAggregate.AddContact(TestData.MerchantContactName, + TestData.MerchantContactPhoneNumber, + TestData.MerchantContactEmailAddress); + + return merchantAggregate; + } + + public static MerchantDepositListAggregate EmptyMerchantDepositListAggregate = new MerchantDepositListAggregate(); + + public static MerchantDepositListAggregate CreatedMerchantDepositListAggregate() + { + MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); + + merchantAggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated); + + MerchantDepositListAggregate merchantDepositListAggregate = MerchantDepositListAggregate.Create(TestData.MerchantId); + merchantDepositListAggregate.Create(merchantAggregate, TestData.DateMerchantCreated); + + return merchantDepositListAggregate; + } public static MerchantAggregate MerchantAggregateWithDevice() { MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); @@ -2017,7 +2270,7 @@ public static MerchantAggregate MerchantAggregateWithOperator() return merchantAggregate; } - public static MerchantAggregate MerchantAggregateWithEverything(SettlementScheduleModel settlementSchedule) + public static MerchantAggregate MerchantAggregateWithEverything(Models.Merchant.SettlementSchedule settlementSchedule) { MerchantAggregate merchantAggregate = MerchantAggregate.Create(TestData.MerchantId); @@ -2207,7 +2460,82 @@ public static EstateAggregate EstateAggregateWithOperatorDeleted() public static Guid AddressId = Guid.Parse("B1C68246-F867-43CC-ACA9-37D15D6437C6"); public static Guid ContactId = Guid.Parse("B1C68246-F867-43CC-ACA9-37D15D6437C6"); public static Guid MerchantSecurityUserId = Guid.Parse("DFCE7A95-CB6D-442A-928A-F1B41D2AA4A9"); + + public static Guid CallbackId = Guid.Parse("ABC603D3-360E-4F58-8BB9-827EE7A1CB03"); + + public static String CallbackMessage = "Message1"; + + public static Int32 CallbackMessageFormat = 1; + + public static String CallbackReference = "Estate1-Merchant1"; + + public static String CallbackTypeString = "CallbackHandler.DataTransferObjects.Deposit"; + public static Guid DepositId = Guid.Parse("A15460B1-9665-4C3E-861D-3B65D0EBEF19"); + public static String DepositAccountNumber = "12345678"; + public static Guid DepositHostIdentifier = Guid.Parse("1D1BD9F0-D953-4B2A-9969-98D3C0CDFA2A"); + public static String DepositSortCode = "112233"; + + public static Models.Merchant.Merchant MerchantModelWithAddressesContactsDevicesAndOperatorsAndContracts(Models.Merchant.SettlementSchedule settlementSchedule = Models.Merchant.SettlementSchedule.Immediate) => + new Models.Merchant.Merchant + { + EstateId = TestData.EstateId, + MerchantId = TestData.MerchantId, + MerchantName = TestData.MerchantName, + SettlementSchedule = settlementSchedule, + Addresses = new List{ + new Models.Merchant.Address(Guid.NewGuid(), MerchantAddressLine1,MerchantAddressLine2, + MerchantAddressLine3,MerchantAddressLine4, MerchantTown,MerchantRegion, + MerchantPostalCode, MerchantCountry) + }, + Contacts = new List{ + new Models.Merchant.Contact(Guid.NewGuid(), MerchantContactEmailAddress, MerchantContactName, MerchantContactPhoneNumber) + }, + Devices = new List{ new Device(DeviceId, DeviceIdentifier)}, + Operators= new List() { + new Models.Merchant.Operator(OperatorId, OperatorName, OperatorMerchantNumber, OperatorTerminalNumber) + }, + Contracts = new List() { + new Contract(ContractId) { + ContractProducts = new List { + Guid.Parse("8EF716B9-422D-4FC6-B5A7-22FC4BABDD97") + } + } + } + }; + + public static Deposit Deposit => + new Deposit + { + Reference = TestData.CallbackReference, + Amount = TestData.DepositAmount.Value, + DateTime = TestData.DepositDateTime, + DepositId = TestData.DepositId, + AccountNumber = TestData.DepositAccountNumber, + HostIdentifier = TestData.DepositHostIdentifier, + SortCode = TestData.DepositSortCode + }; + public static class DomainEvents { + public static CallbackReceivedEnrichedEvent CallbackReceivedEnrichedEventDeposit => + new CallbackReceivedEnrichedEvent(TestData.CallbackId) + { + Reference = TestData.CallbackReference, + CallbackMessage = JsonConvert.SerializeObject(TestData.Deposit), + EstateId = TestData.EstateId, + MessageFormat = TestData.CallbackMessageFormat, + TypeString = TestData.CallbackTypeString + }; + + public static CallbackReceivedEnrichedEvent CallbackReceivedEnrichedEventOtherType => + new CallbackReceivedEnrichedEvent(TestData.CallbackId) + { + Reference = TestData.CallbackReference, + CallbackMessage = JsonConvert.SerializeObject(TestData.Deposit), + EstateId = TestData.EstateId, + MessageFormat = TestData.CallbackMessageFormat, + TypeString = "OtherType" + }; + public static MerchantDomainEvents.ContractAddedToMerchantEvent ContractAddedToMerchantEvent => new MerchantDomainEvents.ContractAddedToMerchantEvent(TestData.MerchantId, TestData.EstateId, @@ -2272,8 +2600,8 @@ public static class DomainEvents { public static MerchantDomainEvents.MerchantRegionUpdatedEvent MerchantRegionUpdatedEvent => new MerchantDomainEvents.MerchantRegionUpdatedEvent(TestData.MerchantId, TestData.EstateId, TestData.AddressId, TestData.Region); public static MerchantDomainEvents.MerchantTownUpdatedEvent MerchantTownUpdatedEvent => new MerchantDomainEvents.MerchantTownUpdatedEvent(TestData.MerchantId, TestData.EstateId, TestData.AddressId, TestData.Town); - public static TransactionFeeForProductAddedToContractEvent TransactionFeeForProductAddedToContractEvent => - new TransactionFeeForProductAddedToContractEvent(TestData.ContractId, + public static ContractDomainEvents.TransactionFeeForProductAddedToContractEvent TransactionFeeForProductAddedToContractEvent => + new ContractDomainEvents.TransactionFeeForProductAddedToContractEvent(TestData.ContractId, TestData.EstateId, TestData.ContractProductId, TestData.TransactionFeeId, @@ -2282,8 +2610,8 @@ public static class DomainEvents { TestData.FeeType, TestData.FeeValue); - public static TransactionFeeForProductDisabledEvent TransactionFeeForProductDisabledEvent => new TransactionFeeForProductDisabledEvent(TestData.ContractId, TestData.EstateId, TestData.ContractProductId, TestData.TransactionFeeId); - public static VariableValueProductAddedToContractEvent VariableValueProductAddedToContractEvent => new VariableValueProductAddedToContractEvent(TestData.ContractId, TestData.EstateId, TestData.ContractProductId, TestData.ProductName, TestData.ProductDisplayText, (Int32)TestData.ProductTypeMobileTopup); + public static ContractDomainEvents.TransactionFeeForProductDisabledEvent TransactionFeeForProductDisabledEvent => new ContractDomainEvents.TransactionFeeForProductDisabledEvent(TestData.ContractId, TestData.EstateId, TestData.ContractProductId, TestData.TransactionFeeId); + public static ContractDomainEvents.VariableValueProductAddedToContractEvent VariableValueProductAddedToContractEvent => new ContractDomainEvents.VariableValueProductAddedToContractEvent(TestData.ContractId, TestData.EstateId, TestData.ContractProductId, TestData.ProductName, TestData.ProductDisplayText, (Int32)TestData.ProductTypeMobileTopup); public static ContractDomainEvents.FixedValueProductAddedToContractEvent FixedValueProductAddedToContractEvent => new ContractDomainEvents.FixedValueProductAddedToContractEvent(TestData.ContractId, TestData.EstateId, diff --git a/TransactionProcessor.Tests/Factories/ModelFactoryTests.cs b/TransactionProcessor.Tests/Factories/ModelFactoryTests.cs index a72c890f..9b7c2f0b 100644 --- a/TransactionProcessor.Tests/Factories/ModelFactoryTests.cs +++ b/TransactionProcessor.Tests/Factories/ModelFactoryTests.cs @@ -1,7 +1,18 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; +using SimpleResults; using TransactionProcessor.Aggregates; +using TransactionProcessor.DataTransferObjects.Responses.Contract; +using TransactionProcessor.DataTransferObjects.Responses.Estate; +using TransactionProcessor.DataTransferObjects.Responses.Merchant; +using TransactionProcessor.DataTransferObjects.Responses.Operator; +using TransactionProcessor.Models.Contract; +using TransactionProcessor.Models.Estate; +using TransactionProcessor.Models.Merchant; +using Contract = TransactionProcessor.Models.Contract.Contract; +using ProductType = TransactionProcessor.DataTransferObjects.Responses.Contract.ProductType; namespace TransactionProcessor.Tests.Factories { @@ -16,6 +27,164 @@ namespace TransactionProcessor.Tests.Factories public class ModelFactoryTests { + [Fact] + public void ModelFactory_Contract_ContractOnly_IsConverted() + { + Contract contractModel = TestData.ContractModel; + + ContractResponse contractResponse = ModelFactory.ConvertFrom(contractModel); + + contractResponse.ShouldNotBeNull(); + contractResponse.OperatorId.ShouldBe(contractModel.OperatorId); + contractResponse.OperatorName.ShouldBe(contractModel.OperatorName); + contractResponse.ContractId.ShouldBe(contractModel.ContractId); + contractResponse.Description.ShouldBe(contractModel.Description); + contractResponse.Products.ShouldBeNull(); + } + + [Fact] + public void ModelFactory_Contract_ContractWithProducts_IsConverted() + { + Contract contractModel = TestData.ContractModelWithProducts; + + ContractResponse contractResponse = ModelFactory.ConvertFrom(contractModel); + + contractResponse.ShouldNotBeNull(); + contractResponse.OperatorId.ShouldBe(contractModel.OperatorId); + contractResponse.ContractId.ShouldBe(contractModel.ContractId); + contractResponse.Description.ShouldBe(contractModel.Description); + contractResponse.Products.ShouldNotBeNull(); + contractResponse.Products.ShouldHaveSingleItem(); + + ContractProduct contractProduct = contractResponse.Products.Single(); + Product expectedContractProduct = contractModel.Products.Single(); + + contractProduct.ProductId.ShouldBe(expectedContractProduct.ContractProductId); + contractProduct.Value.ShouldBe(expectedContractProduct.Value); + contractProduct.DisplayText.ShouldBe(expectedContractProduct.DisplayText); + contractProduct.Name.ShouldBe(expectedContractProduct.Name); + contractProduct.ProductType.ShouldBe(Enum.Parse(expectedContractProduct.ProductType.ToString())); + contractProduct.TransactionFees.ShouldBeNull(); + } + + [Fact] + public void ModelFactory_EstateList_IsConverted() + { + List estateModel = [TestData.EstateModel]; + + Result> estateResponse = ModelFactory.ConvertFrom(estateModel); + estateResponse.IsSuccess.ShouldBeTrue(); + estateResponse.Data.Count.ShouldBe(1); + estateResponse.Data.Single().EstateId.ShouldBe(TestData.EstateModel.EstateId); + estateResponse.Data.Single().EstateName.ShouldBe(TestData.EstateModel.Name); + } + + [Fact] + public void ModelFactory_EstateList_NullModelInList_IsConverted() + { + List estateModel = [null]; + + Result> estateResponse = ModelFactory.ConvertFrom(estateModel); + estateResponse.IsFailed.ShouldBeTrue(); + } + + [Fact] + public void ModelFactory_MerchantList_IsConverted() + { + List merchantModelList = new List{ + TestData.MerchantModelWithAddressesContactsDevicesAndOperatorsAndContracts() + }; + + List merchantResponseList = ModelFactory.ConvertFrom(merchantModelList); + + merchantResponseList.ShouldNotBeNull(); + merchantResponseList.ShouldNotBeEmpty(); + merchantResponseList.Count.ShouldBe(merchantModelList.Count); + } + + [Fact] + public void ModelFactory_MerchantList_NullList_IsConverted() { + List merchantModelList = null; + + List merchantResponseList = ModelFactory.ConvertFrom(merchantModelList); + + merchantResponseList.ShouldNotBeNull(); + merchantResponseList.ShouldBeEmpty(); + } + + [Fact] + public void ModelFactory_MerchantList_NullModelInList_IsConverted() + { + List merchantModelList = new List{ + null + }; + + var result = ModelFactory.ConvertFrom(merchantModelList); + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public void ModelFactory_Contract_ContractWithProductsAndFees_IsConverted() + { + Contract contractModel = TestData.ContractModelWithProductsAndTransactionFees; + + ContractResponse contractResponse = ModelFactory.ConvertFrom(contractModel); + + contractResponse.ShouldNotBeNull(); + contractResponse.OperatorId.ShouldBe(contractModel.OperatorId); + contractResponse.ContractId.ShouldBe(contractModel.ContractId); + contractResponse.Description.ShouldBe(contractModel.Description); + contractResponse.Products.ShouldNotBeNull(); + contractResponse.Products.ShouldHaveSingleItem(); + + ContractProduct contractProduct = contractResponse.Products.Single(); + Product expectedContractProduct = contractModel.Products.Single(); + + contractProduct.ProductId.ShouldBe(expectedContractProduct.ContractProductId); + contractProduct.Value.ShouldBe(expectedContractProduct.Value); + contractProduct.DisplayText.ShouldBe(expectedContractProduct.DisplayText); + contractProduct.Name.ShouldBe(expectedContractProduct.Name); + contractProduct.ProductType.ShouldBe(Enum.Parse(expectedContractProduct.ProductType.ToString())); + contractProduct.TransactionFees.ShouldNotBeNull(); + contractProduct.TransactionFees.ShouldHaveSingleItem(); + + DataTransferObjects.Responses.Contract.ContractProductTransactionFee productTransactionFee = contractProduct.TransactionFees.Single(); + Models.Contract.ContractProductTransactionFee expectedProductTransactionFee = expectedContractProduct.TransactionFees.Single(); + + productTransactionFee.TransactionFeeId.ShouldBe(expectedProductTransactionFee.TransactionFeeId); + productTransactionFee.Value.ShouldBe(expectedProductTransactionFee.Value); + productTransactionFee.CalculationType.ShouldBe(Enum.Parse(expectedProductTransactionFee.CalculationType.ToString())); + productTransactionFee.Description.ShouldBe(expectedProductTransactionFee.Description); + } + + [Fact] + public void ModelFactory_ContractList_IsConverted() + { + List contractModel = new List{ + TestData.ContractModel + }; + + Result> contractResponses = ModelFactory.ConvertFrom(contractModel); + contractResponses.IsSuccess.ShouldBeTrue(); + contractResponses.Data.ShouldNotBeNull(); + contractResponses.Data.ShouldHaveSingleItem(); + contractResponses.Data.Single().OperatorId.ShouldBe(contractModel.Single().OperatorId); + contractResponses.Data.Single().ContractId.ShouldBe(contractModel.Single().ContractId); + contractResponses.Data.Single().Description.ShouldBe(contractModel.Single().Description); + contractResponses.Data.Single().Products.ShouldBeNull(); + } + + [Fact] + public void ModelFactory_ContractList_ModelInListIsNull_IsConverted() + { + List contractModel = new List{ + null + }; + + Result> contractResponses = ModelFactory.ConvertFrom(contractModel); + contractResponses.IsFailed.ShouldBeTrue(); + } + [Fact] public void ModelFactory_ProcessLogonTransactionResponseModel_IsConverted() { @@ -167,5 +336,355 @@ public void ModelFactory_ConvertFrom_RedeemVoucherResponse_NullInput_IsConverted dto.ShouldBeNull(); } + + [Fact] + public void ModelFactory_ConvertFrom_Operator_ModelConverted() + { + OperatorResponse operatorResponse = ModelFactory.ConvertFrom(TestData.OperatorModel); + + operatorResponse.ShouldNotBeNull(); + operatorResponse.OperatorId.ShouldBe(TestData.OperatorId); + operatorResponse.RequireCustomTerminalNumber.ShouldBe(TestData.RequireCustomTerminalNumber); + operatorResponse.RequireCustomMerchantNumber.ShouldBe(TestData.RequireCustomMerchantNumber); + operatorResponse.Name.ShouldBe(TestData.OperatorName); + } + + [Fact] + public void ModelFactory_ConvertFrom_OperatorModelIsNull_ModelConverted() + { + TransactionProcessor.Models.Operator.Operator operatorModel = null; + + OperatorResponse operatorResponse = ModelFactory.ConvertFrom(operatorModel); + + operatorResponse.ShouldBeNull(); + } + + [Fact] + public void ModelFactory_ConvertFrom_OperatorList_ModelConverted() + { + List operatorList = new List{ + TestData.OperatorModel + }; + + List operatorResponses = ModelFactory.ConvertFrom(operatorList); + operatorResponses.ShouldNotBeNull(); + operatorResponses.ShouldNotBeEmpty(); + operatorResponses.Count.ShouldBe(operatorList.Count); + foreach (OperatorResponse operatorResponse in operatorResponses) + { + TransactionProcessor.Models.Operator.Operator @operator = operatorList.SingleOrDefault(o => o.OperatorId == operatorResponse.OperatorId); + @operator.ShouldNotBeNull(); + @operator.OperatorId.ShouldBe(operatorResponse.OperatorId); + @operator.RequireCustomTerminalNumber.ShouldBe(operatorResponse.RequireCustomTerminalNumber); + @operator.RequireCustomMerchantNumber.ShouldBe(operatorResponse.RequireCustomMerchantNumber); + @operator.Name.ShouldBe(operatorResponse.Name); + } + } + + [Fact] + public void ModelFactory_ConvertFrom_NullOperatorList_ModelConverted() + { + List operatorList = null; + + List operatorResponses = ModelFactory.ConvertFrom(operatorList); + operatorResponses.ShouldBeEmpty(); + + } + + [Fact] + public void ModelFactory_ConvertFrom_EmptyOperatorList_ModelConverted() + { + List operatorList = new List(); + + List operatorResponses = ModelFactory.ConvertFrom(operatorList); + operatorResponses.ShouldBeEmpty(); + + } + + [Fact] + public void ModelFactory_ConvertFrom_NullModelInList_ModelConverted() + { + List operatorList = new List { + null + }; + + var result = ModelFactory.ConvertFrom(operatorList); + result.IsFailed.ShouldBeTrue(); + + } + + [Fact] + public void ModelFactory_Estate_NullInput_IsConverted() + { + Estate estateModel = null; + + EstateResponse estateResponse = ModelFactory.ConvertFrom(estateModel); + + estateResponse.ShouldBeNull(); + } + + [Fact] + public void ModelFactory_Estate_WithNoOperatorsOrSecurityUsers_IsConverted() + { + Estate estateModel = TestData.EstateModel; + + EstateResponse estateResponse = ModelFactory.ConvertFrom(estateModel); + + estateResponse.ShouldNotBeNull(); + estateResponse.EstateId.ShouldBe(estateModel.EstateId); + estateResponse.EstateName.ShouldBe(estateModel.Name); + } + + [Fact] + public void ModelFactory_Estate_WithOperators_IsConverted() + { + Estate estateModel = TestData.EstateModelWithOperators; + + EstateResponse estateResponse = ModelFactory.ConvertFrom(estateModel); + + estateResponse.ShouldNotBeNull(); + estateResponse.EstateId.ShouldBe(estateModel.EstateId); + estateResponse.EstateName.ShouldBe(estateModel.Name); + estateResponse.Operators.ShouldNotBeNull(); + estateResponse.Operators.Count.ShouldBe(estateModel.Operators.Count); + estateResponse.SecurityUsers.ShouldBeEmpty(); + } + + [Fact] + public void ModelFactory_Estate_WithSecurityUsers_IsConverted() + { + Estate estateModel = TestData.EstateModelWithSecurityUsers; + + EstateResponse estateResponse = ModelFactory.ConvertFrom(estateModel); + + estateResponse.ShouldNotBeNull(); + estateResponse.EstateId.ShouldBe(estateModel.EstateId); + estateResponse.EstateName.ShouldBe(estateModel.Name); + estateResponse.Operators.ShouldBeEmpty(); + estateResponse.SecurityUsers.ShouldNotBeNull(); + estateResponse.SecurityUsers.Count.ShouldBe(estateModel.SecurityUsers.Count); + } + + [Fact] + public void ModelFactory_Estate_WithOperatorsAndSecurityUsers_IsConverted() + { + Estate estateModel = TestData.EstateModelWithOperatorsAndSecurityUsers; + + EstateResponse estateResponse = ModelFactory.ConvertFrom(estateModel); + + estateResponse.ShouldNotBeNull(); + estateResponse.EstateId.ShouldBe(estateModel.EstateId); + estateResponse.EstateName.ShouldBe(estateModel.Name); + estateResponse.Operators.ShouldNotBeNull(); + estateResponse.Operators.Count.ShouldBe(estateModel.Operators.Count); + estateResponse.SecurityUsers.ShouldNotBeNull(); + estateResponse.SecurityUsers.Count.ShouldBe(estateModel.SecurityUsers.Count); + } + + [Theory] + [InlineData(Models.Merchant.SettlementSchedule.NotSet)] + [InlineData(Models.Merchant.SettlementSchedule.Immediate)] + [InlineData(Models.Merchant.SettlementSchedule.Weekly)] + [InlineData(Models.Merchant.SettlementSchedule.Monthly)] + public void ModelFactory_Merchant_IsConverted(Models.Merchant.SettlementSchedule settlementSchedule) + { + Merchant merchantModel = TestData.MerchantModelWithAddressesContactsDevicesAndOperatorsAndContracts(settlementSchedule); + + MerchantResponse merchantResponse = ModelFactory.ConvertFrom(merchantModel); + + merchantResponse.ShouldNotBeNull(); + merchantResponse.MerchantId.ShouldBe(merchantModel.MerchantId); + merchantResponse.MerchantName.ShouldBe(merchantModel.MerchantName); + merchantResponse.Addresses.ShouldHaveSingleItem(); + + AddressResponse addressResponse = merchantResponse.Addresses.Single(); + addressResponse.AddressId.ShouldBe(merchantModel.Addresses.Single().AddressId); + addressResponse.AddressLine1.ShouldBe(merchantModel.Addresses.Single().AddressLine1); + addressResponse.AddressLine2.ShouldBe(merchantModel.Addresses.Single().AddressLine2); + addressResponse.AddressLine3.ShouldBe(merchantModel.Addresses.Single().AddressLine3); + addressResponse.AddressLine4.ShouldBe(merchantModel.Addresses.Single().AddressLine4); + addressResponse.Town.ShouldBe(merchantModel.Addresses.Single().Town); + addressResponse.Region.ShouldBe(merchantModel.Addresses.Single().Region); + addressResponse.Country.ShouldBe(merchantModel.Addresses.Single().Country); + addressResponse.PostalCode.ShouldBe(merchantModel.Addresses.Single().PostalCode); + + merchantResponse.Contacts.ShouldHaveSingleItem(); + ContactResponse contactResponse = merchantResponse.Contacts.Single(); + contactResponse.ContactId.ShouldBe(merchantModel.Contacts.Single().ContactId); + contactResponse.ContactEmailAddress.ShouldBe(merchantModel.Contacts.Single().ContactEmailAddress); + contactResponse.ContactName.ShouldBe(merchantModel.Contacts.Single().ContactName); + contactResponse.ContactPhoneNumber.ShouldBe(merchantModel.Contacts.Single().ContactPhoneNumber); + } + + [Fact] + public void ModelFactory_Merchant_NullInput_IsConverted() + { + Merchant merchantModel = null; + + MerchantResponse merchantResponse = ModelFactory.ConvertFrom(merchantModel); + + merchantResponse.ShouldBeNull(); + } + + [Fact] + public void ModelFactory_Merchant_NullAddresses_IsConverted() + { + Merchant merchantModel = TestData.MerchantModelWithNullAddresses; + + MerchantResponse merchantResponse = ModelFactory.ConvertFrom(merchantModel); + + merchantResponse.ShouldNotBeNull(); + merchantResponse.MerchantId.ShouldBe(merchantModel.MerchantId); + merchantResponse.MerchantName.ShouldBe(merchantModel.MerchantName); + + merchantResponse.Addresses.ShouldBeNull(); + + merchantResponse.Contacts.ShouldHaveSingleItem(); + ContactResponse contactResponse = merchantResponse.Contacts.Single(); + contactResponse.ContactId.ShouldBe(merchantModel.Contacts.Single().ContactId); + contactResponse.ContactEmailAddress.ShouldBe(merchantModel.Contacts.Single().ContactEmailAddress); + contactResponse.ContactName.ShouldBe(merchantModel.Contacts.Single().ContactName); + contactResponse.ContactPhoneNumber.ShouldBe(merchantModel.Contacts.Single().ContactPhoneNumber); + + merchantResponse.Devices.ShouldHaveSingleItem(); + KeyValuePair device = merchantResponse.Devices.Single(); + device.Key.ShouldBe(merchantModel.Devices.Single().DeviceId); + device.Value.ShouldBe(merchantModel.Devices.Single().DeviceIdentifier); + + merchantResponse.Operators.ShouldHaveSingleItem(); + MerchantOperatorResponse operatorDetails = merchantResponse.Operators.Single(); + operatorDetails.Name.ShouldBe(merchantModel.Operators.Single().Name); + operatorDetails.OperatorId.ShouldBe(merchantModel.Operators.Single().OperatorId); + operatorDetails.MerchantNumber.ShouldBe(merchantModel.Operators.Single().MerchantNumber); + operatorDetails.TerminalNumber.ShouldBe(merchantModel.Operators.Single().TerminalNumber); + } + + [Fact] + public void ModelFactory_Merchant_NullContacts_IsConverted() + { + Merchant merchantModel = TestData.MerchantModelWithNullContacts; + + MerchantResponse merchantResponse = ModelFactory.ConvertFrom(merchantModel); + + merchantResponse.ShouldNotBeNull(); + merchantResponse.MerchantId.ShouldBe(merchantModel.MerchantId); + merchantResponse.MerchantName.ShouldBe(merchantModel.MerchantName); + merchantResponse.Addresses.ShouldHaveSingleItem(); + + AddressResponse addressResponse = merchantResponse.Addresses.Single(); + addressResponse.AddressId.ShouldBe(merchantModel.Addresses.Single().AddressId); + addressResponse.AddressLine1.ShouldBe(merchantModel.Addresses.Single().AddressLine1); + addressResponse.AddressLine2.ShouldBe(merchantModel.Addresses.Single().AddressLine2); + addressResponse.AddressLine3.ShouldBe(merchantModel.Addresses.Single().AddressLine3); + addressResponse.AddressLine4.ShouldBe(merchantModel.Addresses.Single().AddressLine4); + addressResponse.Town.ShouldBe(merchantModel.Addresses.Single().Town); + addressResponse.Region.ShouldBe(merchantModel.Addresses.Single().Region); + addressResponse.Country.ShouldBe(merchantModel.Addresses.Single().Country); + addressResponse.PostalCode.ShouldBe(merchantModel.Addresses.Single().PostalCode); + + merchantResponse.Contacts.ShouldBeNull(); + + merchantResponse.Devices.ShouldHaveSingleItem(); + KeyValuePair device = merchantResponse.Devices.Single(); + device.Key.ShouldBe(merchantModel.Devices.Single().DeviceId); + device.Value.ShouldBe(merchantModel.Devices.Single().DeviceIdentifier); + + merchantResponse.Operators.ShouldHaveSingleItem(); + MerchantOperatorResponse operatorDetails = merchantResponse.Operators.Single(); + operatorDetails.Name.ShouldBe(merchantModel.Operators.Single().Name); + operatorDetails.OperatorId.ShouldBe(merchantModel.Operators.Single().OperatorId); + operatorDetails.MerchantNumber.ShouldBe(merchantModel.Operators.Single().MerchantNumber); + operatorDetails.TerminalNumber.ShouldBe(merchantModel.Operators.Single().TerminalNumber); + } + + [Fact] + public void ModelFactory_Merchant_NullDevices_IsConverted() + { + Merchant merchantModel = TestData.MerchantModelWithNullDevices; + + MerchantResponse merchantResponse = ModelFactory.ConvertFrom(merchantModel); + + merchantResponse.ShouldNotBeNull(); + merchantResponse.MerchantId.ShouldBe(merchantModel.MerchantId); + merchantResponse.MerchantName.ShouldBe(merchantModel.MerchantName); + merchantResponse.Addresses.ShouldHaveSingleItem(); + + AddressResponse addressResponse = merchantResponse.Addresses.Single(); + addressResponse.AddressId.ShouldBe(merchantModel.Addresses.Single().AddressId); + addressResponse.AddressLine1.ShouldBe(merchantModel.Addresses.Single().AddressLine1); + addressResponse.AddressLine2.ShouldBe(merchantModel.Addresses.Single().AddressLine2); + addressResponse.AddressLine3.ShouldBe(merchantModel.Addresses.Single().AddressLine3); + addressResponse.AddressLine4.ShouldBe(merchantModel.Addresses.Single().AddressLine4); + addressResponse.Town.ShouldBe(merchantModel.Addresses.Single().Town); + addressResponse.Region.ShouldBe(merchantModel.Addresses.Single().Region); + addressResponse.Country.ShouldBe(merchantModel.Addresses.Single().Country); + addressResponse.PostalCode.ShouldBe(merchantModel.Addresses.Single().PostalCode); + + merchantResponse.Contacts.ShouldHaveSingleItem(); + ContactResponse contactResponse = merchantResponse.Contacts.Single(); + contactResponse.ContactId.ShouldBe(merchantModel.Contacts.Single().ContactId); + contactResponse.ContactEmailAddress.ShouldBe(merchantModel.Contacts.Single().ContactEmailAddress); + contactResponse.ContactName.ShouldBe(merchantModel.Contacts.Single().ContactName); + contactResponse.ContactPhoneNumber.ShouldBe(merchantModel.Contacts.Single().ContactPhoneNumber); + + merchantResponse.Devices.ShouldBeNull(); + + merchantResponse.Operators.ShouldHaveSingleItem(); + MerchantOperatorResponse operatorDetails = merchantResponse.Operators.Single(); + operatorDetails.Name.ShouldBe(merchantModel.Operators.Single().Name); + operatorDetails.OperatorId.ShouldBe(merchantModel.Operators.Single().OperatorId); + operatorDetails.MerchantNumber.ShouldBe(merchantModel.Operators.Single().MerchantNumber); + operatorDetails.TerminalNumber.ShouldBe(merchantModel.Operators.Single().TerminalNumber); + } + + [Fact] + public void ModelFactory_Merchant_NullOperators_IsConverted() + { + Merchant merchantModel = TestData.MerchantModelWithNullOperators; + + MerchantResponse merchantResponse = ModelFactory.ConvertFrom(merchantModel); + + merchantResponse.ShouldNotBeNull(); + merchantResponse.MerchantId.ShouldBe(merchantModel.MerchantId); + merchantResponse.MerchantName.ShouldBe(merchantModel.MerchantName); + merchantResponse.Addresses.ShouldHaveSingleItem(); + + AddressResponse addressResponse = merchantResponse.Addresses.Single(); + addressResponse.AddressId.ShouldBe(merchantModel.Addresses.Single().AddressId); + addressResponse.AddressLine1.ShouldBe(merchantModel.Addresses.Single().AddressLine1); + addressResponse.AddressLine2.ShouldBe(merchantModel.Addresses.Single().AddressLine2); + addressResponse.AddressLine3.ShouldBe(merchantModel.Addresses.Single().AddressLine3); + addressResponse.AddressLine4.ShouldBe(merchantModel.Addresses.Single().AddressLine4); + addressResponse.Town.ShouldBe(merchantModel.Addresses.Single().Town); + addressResponse.Region.ShouldBe(merchantModel.Addresses.Single().Region); + addressResponse.Country.ShouldBe(merchantModel.Addresses.Single().Country); + addressResponse.PostalCode.ShouldBe(merchantModel.Addresses.Single().PostalCode); + + merchantResponse.Contacts.ShouldHaveSingleItem(); + ContactResponse contactResponse = merchantResponse.Contacts.Single(); + contactResponse.ContactId.ShouldBe(merchantModel.Contacts.Single().ContactId); + contactResponse.ContactEmailAddress.ShouldBe(merchantModel.Contacts.Single().ContactEmailAddress); + contactResponse.ContactName.ShouldBe(merchantModel.Contacts.Single().ContactName); + contactResponse.ContactPhoneNumber.ShouldBe(merchantModel.Contacts.Single().ContactPhoneNumber); + + merchantResponse.Devices.ShouldHaveSingleItem(); + var device = merchantResponse.Devices.Single(); + device.Key.ShouldBe(merchantModel.Devices.Single().DeviceId); + device.Value.ShouldBe(merchantModel.Devices.Single().DeviceIdentifier); + + merchantResponse.Operators.ShouldBeNull(); + } + + [Fact] + public void ModelFactory_TransactionFeeList_IsConverted() + { + List transactionFeeModelList = TestData.ProductTransactionFees; + + List transactionFeeResponseList = ModelFactory.ConvertFrom(transactionFeeModelList); + + transactionFeeResponseList.ShouldNotBeNull(); + transactionFeeResponseList.ShouldNotBeEmpty(); + transactionFeeResponseList.Count.ShouldBe(transactionFeeModelList.Count); + } } } diff --git a/TransactionProcessor/Bootstrapper/MediatorRegistry.cs b/TransactionProcessor/Bootstrapper/MediatorRegistry.cs index 41c6516d..96939600 100644 --- a/TransactionProcessor/Bootstrapper/MediatorRegistry.cs +++ b/TransactionProcessor/Bootstrapper/MediatorRegistry.cs @@ -108,6 +108,7 @@ private void RegisterTransactionRequestHandler() { this.AddSingleton, TransactionRequestHandler>(); this.AddSingleton, TransactionRequestHandler>(); this.AddSingleton, TransactionRequestHandler>(); + this.AddSingleton, TransactionRequestHandler>(); } private void RegisterOperatorRequestHandler() diff --git a/TransactionProcessor/Bootstrapper/RepositoryRegistry.cs b/TransactionProcessor/Bootstrapper/RepositoryRegistry.cs index 3564c004..fffed42b 100644 --- a/TransactionProcessor/Bootstrapper/RepositoryRegistry.cs +++ b/TransactionProcessor/Bootstrapper/RepositoryRegistry.cs @@ -78,6 +78,7 @@ public RepositoryRegistry() this.AddSingleton, AggregateRepository>(); this.AddSingleton, AggregateRepository>(); this.AddSingleton, AggregateRepository>(); + this.AddSingleton, AggregateRepository>(); this.AddSingleton, MerchantBalanceStateRepository>(); this.AddSingleton, VoucherStateRepository>(); diff --git a/TransactionProcessor/Controllers/MerchantController.cs b/TransactionProcessor/Controllers/MerchantController.cs index e066dd53..76a59adc 100644 --- a/TransactionProcessor/Controllers/MerchantController.cs +++ b/TransactionProcessor/Controllers/MerchantController.cs @@ -47,14 +47,7 @@ namespace TransactionProcessor.Controllers; [Authorize] public class MerchantController : ControllerBase { - private readonly IProjectionStateRepository MerchantBalanceStateRepository; - - private readonly IEventStoreContext EventStoreContext; private readonly IMediator Mediator; - private readonly IEstateClient EstateClient; - private readonly ISecurityServiceClient SecurityServiceClient; - - private readonly ITransactionProcessorReadRepository TransactionProcessorReadRepository; public MerchantController(IProjectionStateRepository merchantBalanceStateRepository, ITransactionProcessorReadRepository transactionProcessorReadRepository, @@ -62,12 +55,7 @@ public MerchantController(IProjectionStateRepository merch IMediator mediator, IEstateClient estateClient, ISecurityServiceClient securityServiceClient) { - this.MerchantBalanceStateRepository = merchantBalanceStateRepository; - this.TransactionProcessorReadRepository = transactionProcessorReadRepository; - this.EventStoreContext = eventStoreContext; this.Mediator = mediator; - this.EstateClient = estateClient; - this.SecurityServiceClient = securityServiceClient; } #region Others @@ -269,7 +257,7 @@ private bool PerformStandardChecks(Guid estateId) return true; } - private TokenResponse TokenResponse; + //private TokenResponse TokenResponse; [HttpPost] [Route("")] public async Task CreateMerchant([FromRoute] Guid estateId, @@ -439,17 +427,11 @@ public async Task MakeDeposit([FromRoute] Guid estateId, return Forbid(); } - this.TokenResponse = await Helpers.GetToken(this.TokenResponse, this.SecurityServiceClient, cancellationToken); - - var estateClientRequest = new EstateManagement.DataTransferObjects.Requests.Merchant.MakeMerchantDepositRequest - { - Amount = makeMerchantDepositRequest.Amount, - DepositDateTime = makeMerchantDepositRequest.DepositDateTime, - Reference = makeMerchantDepositRequest.Reference - }; - - var result = await this.EstateClient.MakeMerchantDeposit(this.TokenResponse.AccessToken, estateId, merchantId, estateClientRequest, cancellationToken); + // This will always be a manual deposit as auto ones come in via another route + MerchantCommands.MakeMerchantDepositCommand command = new(estateId, merchantId, DataTransferObjects.Requests.Merchant.MerchantDepositSource.Manual, makeMerchantDepositRequest); + // Route the command + Result result = await Mediator.Send(command, cancellationToken); // return the result return result.ToActionResultX(); @@ -470,16 +452,10 @@ public async Task MakeWithdrawal([FromRoute] Guid estateId, return Forbid(); } - this.TokenResponse = await Helpers.GetToken(this.TokenResponse, this.SecurityServiceClient, cancellationToken); - - var estateClientRequest= new EstateManagement.DataTransferObjects.Requests.Merchant.MakeMerchantWithdrawalRequest - { - Amount = makeMerchantWithdrawalRequest.Amount, - Reference = makeMerchantWithdrawalRequest.Reference, - WithdrawalDateTime = makeMerchantWithdrawalRequest.WithdrawalDateTime - }; + MerchantCommands.MakeMerchantWithdrawalCommand command = new(estateId, merchantId, makeMerchantWithdrawalRequest); - var result = await this.EstateClient.MakeMerchantWithdrawal(this.TokenResponse.AccessToken, estateId, merchantId, estateClientRequest, cancellationToken); + // Route the command + Result result = await Mediator.Send(command, cancellationToken); // return the result return result.ToActionResultX();