diff --git a/TransactionProcessor.Aggregates.Tests/MerchantStatementForDateAggregateTests.cs b/TransactionProcessor.Aggregates.Tests/MerchantStatementForDateAggregateTests.cs index 30a8ca7..2bb2b27 100644 --- a/TransactionProcessor.Aggregates.Tests/MerchantStatementForDateAggregateTests.cs +++ b/TransactionProcessor.Aggregates.Tests/MerchantStatementForDateAggregateTests.cs @@ -1,6 +1,9 @@ using Shouldly; +using SimpleResults; +using TransactionProcessor.DataTransferObjects.Requests.Merchant; using TransactionProcessor.Models.Merchant; using TransactionProcessor.Testing; +using MerchantDepositSource = TransactionProcessor.Models.Merchant.MerchantDepositSource; namespace TransactionProcessor.Aggregates.Tests; @@ -19,11 +22,12 @@ public void MerchantStatementForDateAggregate_CanBeCreated_IsCreated() public void MerchantStatementForDateAggregate_AddTransactionToStatement_TransactionAddedToStatement() { MerchantStatementForDateAggregate merchantStatementForDateAggregate = MerchantStatementForDateAggregate.Create(TestData.MerchantStatementForDateId1); - merchantStatementForDateAggregate.AddTransactionToStatement(TestData.MerchantStatementId, + Result result = merchantStatementForDateAggregate.AddTransactionToStatement(TestData.MerchantStatementId, TestData.StatementDate, TestData.EventId1, TestData.EstateId, TestData.MerchantId, TestData.Transaction1); + result.IsSuccess.ShouldBeTrue(); MerchantStatementForDate merchantStatementForDate = merchantStatementForDateAggregate.GetStatement(true); List? statementLines = merchantStatementForDate.GetStatementLines(); @@ -42,11 +46,12 @@ public void MerchantStatementForDateAggregate_AddTransactionToStatement_Duplicat TestData.EstateId, TestData.MerchantId, TestData.Transaction1); - merchantStatementForDateAggregate.AddTransactionToStatement(TestData.MerchantStatementId, + Result result = merchantStatementForDateAggregate.AddTransactionToStatement(TestData.MerchantStatementId, TestData.StatementDate, TestData.EventId1, TestData.EstateId, TestData.MerchantId, TestData.Transaction1); + result.IsSuccess.ShouldBeTrue(); MerchantStatementForDate merchantStatementForDate = merchantStatementForDateAggregate.GetStatement(true); List? statementLines = merchantStatementForDate.GetStatementLines(); @@ -55,11 +60,40 @@ public void MerchantStatementForDateAggregate_AddTransactionToStatement_Duplicat statementLines.Count.ShouldBe(1); } + [Theory] + [InlineData("", null, null)] + [InlineData(null, "", null)] + [InlineData(null, null, "")] + public void MerchantStatementForDateAggregate_AddTransactionToStatement_InvalidData_TransactionAddedToStatement(String statementId, String estateId, String merchantId) { + Guid statementIdGuid = TestData.MerchantStatementId; + Guid estateIdGuid = TestData.EstateId; + Guid merchantIdGuid = TestData.MerchantId; + + if (statementId == String.Empty) { + statementIdGuid = Guid.Empty; + } + if (estateId == String.Empty) { + estateIdGuid = Guid.Empty; + } + if (merchantId == String.Empty) { + merchantIdGuid = Guid.Empty; + } + MerchantStatementForDateAggregate merchantStatementForDateAggregate = MerchantStatementForDateAggregate.Create(TestData.MerchantStatementForDateId1); + Result result = merchantStatementForDateAggregate.AddTransactionToStatement(statementIdGuid, + TestData.StatementDate, + TestData.EventId1, + estateIdGuid, + merchantIdGuid, TestData.Transaction1); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); + } + [Fact] public void MerchantStatementForDateAggregate_AddSettledFeeToStatement_FeeAddedToStatement() { MerchantStatementForDateAggregate merchantStatementForDateAggregate = MerchantStatementForDateAggregate.Create(TestData.MerchantStatementForDateId1); - merchantStatementForDateAggregate.AddSettledFeeToStatement(TestData.MerchantStatementId, TestData.StatementDate, TestData.EventId1, TestData.EstateId, TestData.MerchantId, TestData.SettledFee1); + Result result = merchantStatementForDateAggregate.AddSettledFeeToStatement(TestData.MerchantStatementId, TestData.StatementDate, TestData.EventId1, TestData.EstateId, TestData.MerchantId, TestData.SettledFee1); + result.IsSuccess.ShouldBeTrue(); MerchantStatementForDate merchantStatementForDate = merchantStatementForDateAggregate.GetStatement(true); List? statementLines = merchantStatementForDate.GetStatementLines(); @@ -73,7 +107,8 @@ public void MerchantStatementForDateAggregate_AddSettledFeeToStatement_Duplicate { MerchantStatementForDateAggregate merchantStatementForDateAggregate = MerchantStatementForDateAggregate.Create(TestData.MerchantStatementForDateId1); merchantStatementForDateAggregate.AddSettledFeeToStatement(TestData.MerchantStatementId, TestData.StatementDate, TestData.EventId1, TestData.EstateId, TestData.MerchantId, TestData.SettledFee1); - merchantStatementForDateAggregate.AddSettledFeeToStatement(TestData.MerchantStatementId, TestData.StatementDate, TestData.EventId1, TestData.EstateId, TestData.MerchantId, TestData.SettledFee1); + Result result = merchantStatementForDateAggregate.AddSettledFeeToStatement(TestData.MerchantStatementId, TestData.StatementDate, TestData.EventId1, TestData.EstateId, TestData.MerchantId, TestData.SettledFee1); + result.IsSuccess.ShouldBeTrue(); MerchantStatementForDate merchantStatementForDate = merchantStatementForDateAggregate.GetStatement(true); List? statementLines = merchantStatementForDate.GetStatementLines(); @@ -82,13 +117,43 @@ public void MerchantStatementForDateAggregate_AddSettledFeeToStatement_Duplicate statementLines.Count.ShouldBe(1); } + [Theory] + [InlineData("", null, null)] + [InlineData(null, "", null)] + [InlineData(null, null, "")] + public void MerchantStatementForDateAggregate_AddSettledFeeToStatement_InvalidData_TransactionAddedToStatement(String statementId, String estateId, String merchantId) + { + Guid statementIdGuid = TestData.MerchantStatementId; + Guid estateIdGuid = TestData.EstateId; + Guid merchantIdGuid = TestData.MerchantId; + + if (statementId == String.Empty) + { + statementIdGuid = Guid.Empty; + } + if (estateId == String.Empty) + { + estateIdGuid = Guid.Empty; + } + if (merchantId == String.Empty) + { + merchantIdGuid = Guid.Empty; + } + + MerchantStatementForDateAggregate merchantStatementForDateAggregate = MerchantStatementForDateAggregate.Create(TestData.MerchantStatementForDateId1); + Result result = merchantStatementForDateAggregate.AddSettledFeeToStatement(statementIdGuid, TestData.StatementDate, TestData.EventId1, estateIdGuid, merchantIdGuid, TestData.SettledFee1); + + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); + } + [Theory] [InlineData(MerchantDepositSource.Manual)] [InlineData(MerchantDepositSource.Automatic)] public void MerchantStatementForDateAggregate_AddDepositToStatement_DepositAddedToStatement(MerchantDepositSource source) { MerchantStatementForDateAggregate merchantStatementForDateAggregate = MerchantStatementForDateAggregate.Create(TestData.MerchantStatementForDateId1); - merchantStatementForDateAggregate.AddDepositToStatement(TestData.MerchantStatementId, + Result result = merchantStatementForDateAggregate.AddDepositToStatement(TestData.MerchantStatementId, TestData.StatementDate, TestData.EventId1, TestData.EstateId, @@ -99,6 +164,7 @@ public void MerchantStatementForDateAggregate_AddDepositToStatement_DepositAdded Reference = TestData.DepositReference, Source = source }); + result.IsSuccess.ShouldBeTrue(); MerchantStatementForDate merchantStatementForDate = merchantStatementForDateAggregate.GetStatement(true); List? statementLines = merchantStatementForDate.GetStatementLines(); @@ -107,11 +173,52 @@ public void MerchantStatementForDateAggregate_AddDepositToStatement_DepositAdded statementLines.Count.ShouldBe(1); } + [Theory] + [InlineData(null, "", null)] + [InlineData(null, null, "")] + [InlineData("", null, null)] + public void MerchantStatementForDateAggregate_AddDepositToStatement_InvalidData_TransactionAddedToStatement(String statementId, String estateId, String merchantId) + { + Guid statementIdGuid = TestData.MerchantStatementId; + Guid estateIdGuid = TestData.EstateId; + Guid merchantIdGuid = TestData.MerchantId; + + if (statementId == String.Empty) + { + statementIdGuid = Guid.Empty; + } + if (estateId == String.Empty) + { + estateIdGuid = Guid.Empty; + } + if (merchantId == String.Empty) + { + merchantIdGuid = Guid.Empty; + } + + MerchantStatementForDateAggregate merchantStatementForDateAggregate = MerchantStatementForDateAggregate.Create(TestData.MerchantStatementForDateId1); + Result result = merchantStatementForDateAggregate.AddDepositToStatement(statementIdGuid, + TestData.StatementDate, + TestData.EventId1, + estateIdGuid, + merchantIdGuid, new Deposit + { + DepositDateTime = TestData.DepositDateTime, + Amount = TestData.DepositAmount.Value, + DepositId = TestData.DepositId, + Reference = TestData.DepositReference, + Source = MerchantDepositSource.Manual + }); + + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); + } + [Fact] public void MerchantStatementForDateAggregate_AddWithdrawalToStatement_WithdrawalAddedToStatement() { MerchantStatementForDateAggregate merchantStatementForDateAggregate = MerchantStatementForDateAggregate.Create(TestData.MerchantStatementForDateId1); - merchantStatementForDateAggregate.AddWithdrawalToStatement(TestData.MerchantStatementId, + Result result = merchantStatementForDateAggregate.AddWithdrawalToStatement(TestData.MerchantStatementId, TestData.StatementDate, TestData.EventId1, TestData.EstateId, @@ -121,11 +228,51 @@ public void MerchantStatementForDateAggregate_AddWithdrawalToStatement_Withdrawa Amount = TestData.WithdrawalAmount.Value, WithdrawalId = TestData.WithdrawalId }); + result.IsSuccess.ShouldBeTrue(); MerchantStatementForDate merchantStatementForDate = merchantStatementForDateAggregate.GetStatement(true); List? statementLines = merchantStatementForDate.GetStatementLines(); statementLines.ShouldNotBeNull(); statementLines.ShouldNotBeEmpty(); statementLines.Count.ShouldBe(1); - } + } + + [Theory] + [InlineData("", null, null)] + [InlineData(null, "", null)] + [InlineData( null, null, "")] + public void MerchantStatementForDateAggregate_AddWithdrawalToStatement_InvalidData_TransactionAddedToStatement(String statementId, String estateId, String merchantId) + { + Guid statementIdGuid = TestData.MerchantStatementId; + Guid estateIdGuid = TestData.EstateId; + Guid merchantIdGuid = TestData.MerchantId; + + if (statementId == String.Empty) + { + statementIdGuid = Guid.Empty; + } + if (estateId == String.Empty) + { + estateIdGuid = Guid.Empty; + } + if (merchantId == String.Empty) + { + merchantIdGuid = Guid.Empty; + } + + MerchantStatementForDateAggregate merchantStatementForDateAggregate = MerchantStatementForDateAggregate.Create(TestData.MerchantStatementForDateId1); + Result result = merchantStatementForDateAggregate.AddWithdrawalToStatement(statementIdGuid, + TestData.StatementDate, + TestData.EventId1, + estateIdGuid, + merchantIdGuid, new Withdrawal + { + WithdrawalDateTime = TestData.WithdrawalDateTime, + Amount = TestData.WithdrawalAmount.Value, + WithdrawalId = TestData.WithdrawalId + }); + + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); + } } \ No newline at end of file diff --git a/TransactionProcessor.Aggregates/MerchantStatementForDateAggregate.cs b/TransactionProcessor.Aggregates/MerchantStatementForDateAggregate.cs index 1595d36..f451a57 100644 --- a/TransactionProcessor.Aggregates/MerchantStatementForDateAggregate.cs +++ b/TransactionProcessor.Aggregates/MerchantStatementForDateAggregate.cs @@ -2,6 +2,7 @@ using Shared.EventStore.Aggregate; using Shared.General; using System.Diagnostics.CodeAnalysis; +using SimpleResults; using TransactionProcessor.Aggregates.Models; using TransactionProcessor.DomainEvents; using TransactionProcessor.Models.Merchant; @@ -12,7 +13,7 @@ namespace TransactionProcessor.Aggregates; public static class MerchantStatementForDateAggregateExtensions { - public static void AddSettledFeeToStatement(this MerchantStatementForDateAggregate aggregate, + public static Result AddSettledFeeToStatement(this MerchantStatementForDateAggregate aggregate, Guid merchantStatementId, DateTime statementDate, Guid eventId, @@ -20,55 +21,69 @@ public static void AddSettledFeeToStatement(this MerchantStatementForDateAggrega Guid merchantId, SettledFee settledFee) { // Create statement id required - aggregate.CreateStatementForDate(merchantStatementId, settledFee.DateTime.Date, statementDate, estateId, merchantId); + Result result = aggregate.CreateStatementForDate(merchantStatementId, settledFee.DateTime.Date, statementDate, estateId, merchantId); + if (result.IsFailed) + return result; MerchantStatementForDateDomainEvents.SettledFeeAddedToStatementForDateEvent settledFeeAddedToStatementEvent = new(aggregate.AggregateId, eventId, aggregate.EstateId, aggregate.MerchantId, settledFee.SettledFeeId, settledFee.TransactionId, settledFee.DateTime, settledFee.Amount); aggregate.ApplyAndAppend(settledFeeAddedToStatementEvent); + + return Result.Success(); } - public static void AddDepositToStatement(this MerchantStatementForDateAggregate aggregate, - Guid merchantStatementId, - DateTime statementDate, - Guid eventId, - Guid estateId, - Guid merchantId, - Deposit deposit) + public static Result AddDepositToStatement(this MerchantStatementForDateAggregate aggregate, + Guid merchantStatementId, + DateTime statementDate, + Guid eventId, + Guid estateId, + Guid merchantId, + Deposit deposit) { // Create statement id required - aggregate.CreateStatementForDate(merchantStatementId, deposit.DepositDateTime.Date, statementDate, estateId, merchantId); + Result result = aggregate.CreateStatementForDate(merchantStatementId, deposit.DepositDateTime.Date, statementDate, estateId, merchantId); + if (result.IsFailed) + return result; MerchantStatementForDateDomainEvents.DepositAddedToStatementForDateEvent depositAddedToStatementEvent = new(aggregate.AggregateId, eventId, aggregate.EstateId, aggregate.MerchantId, deposit.DepositId, deposit.DepositDateTime, deposit.Amount); aggregate.ApplyAndAppend(depositAddedToStatementEvent); + + return Result.Success(); } - public static void AddWithdrawalToStatement(this MerchantStatementForDateAggregate aggregate, - Guid merchantStatementId, - DateTime statementDate, - Guid eventId, - Guid estateId, - Guid merchantId, - Withdrawal withdrawal) + public static Result AddWithdrawalToStatement(this MerchantStatementForDateAggregate aggregate, + Guid merchantStatementId, + DateTime statementDate, + Guid eventId, + Guid estateId, + Guid merchantId, + Withdrawal withdrawal) { // Create statement id required - aggregate.CreateStatementForDate(merchantStatementId, withdrawal.WithdrawalDateTime.Date, statementDate, estateId, merchantId); + Result result = aggregate.CreateStatementForDate(merchantStatementId, withdrawal.WithdrawalDateTime.Date, statementDate, estateId, merchantId); + if (result.IsFailed) + return result; MerchantStatementForDateDomainEvents.WithdrawalAddedToStatementForDateEvent withdrawalAddedToStatementEvent = new(aggregate.AggregateId, eventId, aggregate.EstateId, aggregate.MerchantId, withdrawal.WithdrawalId, withdrawal.WithdrawalDateTime, withdrawal.Amount); aggregate.ApplyAndAppend(withdrawalAddedToStatementEvent); + + return Result.Success(); } - public static void AddTransactionToStatement(this MerchantStatementForDateAggregate aggregate, - Guid merchantStatementId, - DateTime statementDate, - Guid eventId, - Guid estateId, - Guid merchantId, - Transaction transaction) + public static Result AddTransactionToStatement(this MerchantStatementForDateAggregate aggregate, + Guid merchantStatementId, + DateTime statementDate, + Guid eventId, + Guid estateId, + Guid merchantId, + Transaction transaction) { // Create statement if required - aggregate.CreateStatementForDate(merchantStatementId, transaction.DateTime.Date, statementDate, estateId, merchantId); + Result result = aggregate.CreateStatementForDate(merchantStatementId, transaction.DateTime.Date, statementDate, estateId, merchantId); + if (result.IsFailed) + return result; MerchantStatementForDateDomainEvents.TransactionAddedToStatementForDateEvent transactionAddedToStatementEvent = new(aggregate.AggregateId, eventId, @@ -79,26 +94,32 @@ public static void AddTransactionToStatement(this MerchantStatementForDateAggreg transaction.Amount); aggregate.ApplyAndAppend(transactionAddedToStatementEvent); + + return Result.Success(); } - private static void CreateStatementForDate(this MerchantStatementForDateAggregate aggregate, + private static Result CreateStatementForDate(this MerchantStatementForDateAggregate aggregate, Guid merchantStatementId, DateTime activityDate, DateTime statementDate, Guid estateId, Guid merchantId) { - if (aggregate.IsCreated == false) - { - Guard.ThrowIfInvalidGuid(merchantStatementId, nameof(merchantStatementId)); - Guard.ThrowIfInvalidGuid(estateId, nameof(estateId)); - Guard.ThrowIfInvalidGuid(merchantId, nameof(merchantId)); - - MerchantStatementForDateDomainEvents.StatementCreatedForDateEvent statementCreatedForDateEvent = new(aggregate.AggregateId, - activityDate, statementDate, merchantStatementId, estateId, merchantId); - - aggregate.ApplyAndAppend(statementCreatedForDateEvent); - } + if (aggregate.IsCreated) + return Result.Success(); + + if (merchantStatementId == Guid.Empty) + return Result.Invalid("Merchant Statement Id cannot be an empty Guid"); + if (estateId == Guid.Empty) + return Result.Invalid("Estate Id cannot be an empty Guid"); + if (merchantId == Guid.Empty) + return Result.Invalid("Merchant Id cannot be an empty Guid"); + + MerchantStatementForDateDomainEvents.StatementCreatedForDateEvent statementCreatedForDateEvent = new(aggregate.AggregateId, + activityDate, statementDate, merchantStatementId, estateId, merchantId); + + aggregate.ApplyAndAppend(statementCreatedForDateEvent); + return Result.Success(); } public static void PlayEvent(this MerchantStatementForDateAggregate aggregate, MerchantStatementForDateDomainEvents.StatementCreatedForDateEvent domainEvent) diff --git a/TransactionProcessor.BusinessLogic/Services/MerchantStatementDomainService.cs b/TransactionProcessor.BusinessLogic/Services/MerchantStatementDomainService.cs index e75dd0d..704565e 100644 --- a/TransactionProcessor.BusinessLogic/Services/MerchantStatementDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/MerchantStatementDomainService.cs @@ -93,7 +93,9 @@ public async Task AddSettledFeeToStatement(MerchantStatementCommands.Add command.TransactionId, settlementFeeId, settledFee, command.SettledDateTime, }); - merchantStatementForDateAggregate.AddSettledFeeToStatement(merchantStatementId, nextStatementDate, eventId, command.EstateId, command.MerchantId, settledFee); + Result stateResult = merchantStatementForDateAggregate.AddSettledFeeToStatement(merchantStatementId, nextStatementDate, eventId, command.EstateId, command.MerchantId, settledFee); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); Result saveResult = await this.AggregateService.Save(merchantStatementForDateAggregate, cancellationToken); if (saveResult.IsFailed) @@ -339,8 +341,10 @@ public async Task AddDepositToStatement(MerchantStatementCommands.AddDep command.DepositDateTime, }); - merchantStatementForDateAggregate.AddDepositToStatement(merchantStatementId, nextStatementDate, eventId, command.EstateId, command.MerchantId, deposit); - + Result stateResult = merchantStatementForDateAggregate.AddDepositToStatement(merchantStatementId, nextStatementDate, eventId, command.EstateId, command.MerchantId, deposit); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); + Result saveResult = await this.AggregateService.Save(merchantStatementForDateAggregate, cancellationToken); if (saveResult.IsFailed) return ResultHelpers.CreateFailure(saveResult); @@ -378,7 +382,9 @@ public async Task AddWithdrawalToStatement(MerchantStatementCommands.Add command.WithdrawalDateTime, }); - merchantStatementForDateAggregate.AddWithdrawalToStatement(merchantStatementId, nextStatementDate, eventId, command.EstateId, command.MerchantId, withdrawal); + Result stateResult = merchantStatementForDateAggregate.AddWithdrawalToStatement(merchantStatementId, nextStatementDate, eventId, command.EstateId, command.MerchantId, withdrawal); + if(stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); Result saveResult = await this.AggregateService.Save(merchantStatementForDateAggregate, cancellationToken); if (saveResult.IsFailed) @@ -425,7 +431,9 @@ public async Task AddTransactionToStatement(MerchantStatementCommands.Ad command.TransactionDateTime, }); - merchantStatementForDateAggregate.AddTransactionToStatement(merchantStatementId, nextStatementDate, eventId, command.EstateId, command.MerchantId, transaction); + Result stateResult = merchantStatementForDateAggregate.AddTransactionToStatement(merchantStatementId, nextStatementDate, eventId, command.EstateId, command.MerchantId, transaction); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); Result saveResult = await this.AggregateService.Save(merchantStatementForDateAggregate, cancellationToken); if (saveResult.IsFailed)