diff --git a/TransactionProcessor.Aggregates.Tests/TransactionAggregateTests.cs b/TransactionProcessor.Aggregates.Tests/TransactionAggregateTests.cs index ba3435d..197b9f1 100644 --- a/TransactionProcessor.Aggregates.Tests/TransactionAggregateTests.cs +++ b/TransactionProcessor.Aggregates.Tests/TransactionAggregateTests.cs @@ -1,4 +1,5 @@ using Shouldly; +using SimpleResults; using TransactionProcessor.Models; using TransactionProcessor.Models.Contract; using TransactionProcessor.Testing; @@ -17,7 +18,7 @@ public void TransactionAggregate_CanBeCreated_IsCreated(){ [InlineData(TransactionType.Sale)] public void TransactionAggregate_StartTransaction_TransactionIsStarted(TransactionType transactionType){ Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - transactionAggregate.StartTransaction(TestData.TransactionDateTime, + Result result = transactionAggregate.StartTransaction(TestData.TransactionDateTime, TestData.TransactionNumber, transactionType, TestData.TransactionReference, @@ -25,6 +26,7 @@ public void TransactionAggregate_StartTransaction_TransactionIsStarted(Transacti TestData.MerchantId, TestData.DeviceIdentifier, TestData.TransactionAmount); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.IsStarted.ShouldBeTrue(); transactionAggregate.TransactionDateTime.ShouldBe(TestData.TransactionDateTime); @@ -44,7 +46,7 @@ public void TransactionAggregate_StartTransaction_TransactionIsStarted(Transacti [InlineData(TransactionType.Logon)] public void TransactionAggregate_StartTransaction_NullAmount_TransactionIsStarted(TransactionType transactionType){ Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - transactionAggregate.StartTransaction(TestData.TransactionDateTime, + Result result = transactionAggregate.StartTransaction(TestData.TransactionDateTime, TestData.TransactionNumber, transactionType, TestData.TransactionReference, @@ -52,6 +54,7 @@ public void TransactionAggregate_StartTransaction_NullAmount_TransactionIsStarte TestData.MerchantId, TestData.DeviceIdentifier, null); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.IsStarted.ShouldBeTrue(); transactionAggregate.TransactionDateTime.ShouldBe(TestData.TransactionDateTime); @@ -81,8 +84,7 @@ public void TransactionAggregate_StartTransaction_TransactionAlreadyStarted_Erro TestData.DeviceIdentifier, TestData.TransactionAmount); - Should.Throw(() => { - transactionAggregate.StartTransaction(TestData.TransactionDateTime, + Result result = transactionAggregate.StartTransaction(TestData.TransactionDateTime, TestData.TransactionNumber, transactionType, TestData.TransactionReference, @@ -90,7 +92,8 @@ public void TransactionAggregate_StartTransaction_TransactionAlreadyStarted_Erro TestData.MerchantId, TestData.DeviceIdentifier, TestData.TransactionAmount); - }); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -122,8 +125,7 @@ public void TransactionAggregate_StartTransaction_TransactionAlreadyCompleted_Er transactionAggregate.CompleteTransaction(); - Should.Throw(() => { - transactionAggregate.StartTransaction(TestData.TransactionDateTime, + Result result = transactionAggregate.StartTransaction(TestData.TransactionDateTime, TestData.TransactionNumber, transactionType, TestData.TransactionReference, @@ -131,7 +133,8 @@ public void TransactionAggregate_StartTransaction_TransactionAlreadyCompleted_Er TestData.MerchantId, TestData.DeviceIdentifier, TestData.TransactionAmount); - }); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -156,23 +159,22 @@ public void TransactionAggregate_StartTransaction_TransactionAlreadyCompleted_Er [InlineData(true, "0001", TransactionType.Sale, "ABCDEFG", true, true, null)] [InlineData(true, "0001", TransactionType.Sale, "", true, true, "A1234567890")] [InlineData(true, "0001", TransactionType.Sale, null, true, true, "A1234567890")] - public void TransactionAggregate_StartTransaction_InvalidData_ErrorThrown(Boolean validTransactionDateTime, String transactionNumber, TransactionType transactionType, String transactionReference, Boolean validEstateId, Boolean validMerchantId, String deviceIdentifier){ + public void TransactionAggregate_StartTransaction_InvalidData_ErrorThrown(Boolean validTransactionDateTime, + String transactionNumber, + TransactionType transactionType, + String transactionReference, + Boolean validEstateId, + Boolean validMerchantId, + String deviceIdentifier) { DateTime transactionDateTime = validTransactionDateTime ? TestData.TransactionDateTime : DateTime.MinValue; Guid estateId = validEstateId ? TestData.EstateId : Guid.Empty; Guid merchantId = validMerchantId ? TestData.MerchantId : Guid.Empty; Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - Should.Throw(() => { - transactionAggregate.StartTransaction(transactionDateTime, - transactionNumber, - transactionType, - transactionReference, - estateId, - merchantId, - deviceIdentifier, - TestData.TransactionAmount); - }); + Result result = transactionAggregate.StartTransaction(transactionDateTime, transactionNumber, transactionType, transactionReference, estateId, merchantId, deviceIdentifier, TestData.TransactionAmount); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -188,7 +190,8 @@ public void TransactionAggregate_AddProductDetails_ProductDetailsAdded(Transacti TestData.DeviceIdentifier, TestData.TransactionAmount); - transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); + Result result = transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.IsProductDetailsAdded.ShouldBeTrue(); transactionAggregate.ContractId.ShouldBe(TestData.ContractId); @@ -210,7 +213,8 @@ public void TransactionAggregate_AddTransactionSource_TransactionSourceAdded(Tra TestData.TransactionAmount); transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); - transactionAggregate.AddTransactionSource(transactionSource); + Result result = transactionAggregate.AddTransactionSource(transactionSource); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.TransactionSource.ShouldBe(transactionSource); } @@ -228,7 +232,9 @@ public void TransactionAggregate_AddTransactionSource_InvalidSource_ErrorThrown( TestData.TransactionAmount); transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); - Should.Throw(() => { transactionAggregate.AddTransactionSource((TransactionSource)99); }); + Result result = transactionAggregate.AddTransactionSource((TransactionSource)99); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -247,7 +253,8 @@ public void TransactionAggregate_AddTransactionSource_SourceAlreadySet_NoErrorTh transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); transactionAggregate.AddTransactionSource(transactionSource); - Should.NotThrow(() => { transactionAggregate.AddTransactionSource(transactionSource); }); + Result result = transactionAggregate.AddTransactionSource(transactionSource); + result.IsSuccess.ShouldBeTrue(); } [Theory] @@ -263,7 +270,9 @@ public void TransactionAggregate_AddProductDetails_InvalidContractId_ErrorThrown TestData.DeviceIdentifier, TestData.TransactionAmount); - Should.Throw(() => { transactionAggregate.AddProductDetails(Guid.Empty, TestData.ProductId); }); + Result result = transactionAggregate.AddProductDetails(Guid.Empty, TestData.ProductId); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -279,7 +288,9 @@ public void TransactionAggregate_AddProductDetails_InvalidProductId_ErrorThrown( TestData.DeviceIdentifier, TestData.TransactionAmount); - Should.Throw(() => { transactionAggregate.AddProductDetails(TestData.ContractId, Guid.Empty); }); + Result result = transactionAggregate.AddProductDetails(TestData.ContractId, Guid.Empty); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -297,7 +308,9 @@ public void TransactionAggregate_AddProductDetails_ProductDetailsAlreadyAdded_Er transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); - Should.Throw(() => { transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); }); + Result result = transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid);result.IsFailed.ShouldBeTrue(); } [Theory] @@ -305,7 +318,9 @@ public void TransactionAggregate_AddProductDetails_ProductDetailsAlreadyAdded_Er public void TransactionAggregate_AddProductDetails_TransactionNotStarted_ErrorThrown(TransactionType transactionType){ Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - Should.Throw(() => { transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); }); + Result result = transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -339,7 +354,9 @@ public void TransactionAggregate_AddProductDetails_TransactionAlreadyCompleted_E transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); }); + Result result = transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -355,7 +372,8 @@ public void TransactionAggregate_AuthoriseTransactionLocally_TransactionIsAuthor TestData.DeviceIdentifier, TestData.TransactionAmount); - transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, TestData.ResponseCode, TestData.ResponseMessage); + Result result = transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, TestData.ResponseCode, TestData.ResponseMessage); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.IsLocallyAuthorised.ShouldBeTrue(); transactionAggregate.IsAuthorised.ShouldBeFalse(); @@ -368,11 +386,11 @@ public void TransactionAggregate_AuthoriseTransactionLocally_TransactionIsAuthor public void TransactionAggregate_AuthoriseTransactionLocally_TransactionNotStarted_ErrorThrown(){ Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - Should.Throw(() => { - transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, + Result result = transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, TestData.ResponseCode, TestData.ResponseMessage); - }); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -389,11 +407,11 @@ public void TransactionAggregate_AuthoriseTransactionLocally_TransactionAlreadyA TestData.TransactionAmount); transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, TestData.ResponseCode, TestData.ResponseMessage); - Should.Throw(() => { - transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, + Result result = transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, TestData.ResponseCode, TestData.ResponseMessage); - }); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -410,11 +428,11 @@ public void TransactionAggregate_AuthoriseTransactionLocally_TransactionAlreadyA TestData.TransactionAmount); transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); - Should.Throw(() => { - transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, + Result result = transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, TestData.ResponseCode, TestData.ResponseMessage); - }); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -431,11 +449,11 @@ public void TransactionAggregate_AuthoriseTransactionLocally_TransactionCannotBe TestData.TransactionAmount); transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); - Should.Throw(() => { - transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, + Result result = transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, TestData.ResponseCode, TestData.ResponseMessage); - }); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } @@ -456,7 +474,8 @@ public void TransactionAggregate_AuthoriseTransaction_TransactionIsAuthorised(Tr transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); } - transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); + Result result = transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.IsLocallyAuthorised.ShouldBeFalse(); transactionAggregate.IsAuthorised.ShouldBeTrue(); @@ -470,7 +489,9 @@ public void TransactionAggregate_AuthoriseTransaction_TransactionIsAuthorised(Tr public void TransactionAggregate_AuthoriseTransaction_TransactionNotStarted_ErrorThrown(){ Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - Should.Throw(() => { transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); }); + Result result = transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -492,7 +513,9 @@ public void TransactionAggregate_AuthoriseTransaction_TransactionAlreadyAuthoris transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); - Should.Throw(() => { transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); }); + Result result = transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -512,7 +535,8 @@ public void TransactionAggregate_DeclineTransactionLocally_TransactionIsDeclined transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); } - transactionAggregate.DeclineTransactionLocally(TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); + Result result = transactionAggregate.DeclineTransactionLocally(TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.IsAuthorised.ShouldBeFalse(); transactionAggregate.IsLocallyAuthorised.ShouldBeFalse(); @@ -527,7 +551,9 @@ public void TransactionAggregate_DeclineTransactionLocally_TransactionIsDeclined public void TransactionAggregate_DeclineTransactionLocally_TransactionNotStarted_ErrorThrown(){ Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - Should.Throw(() => { transactionAggregate.DeclineTransactionLocally(TestData.ResponseCode, TestData.ResponseMessage); }); + Result result = transactionAggregate.DeclineTransactionLocally(TestData.ResponseCode, TestData.ResponseMessage); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -544,7 +570,9 @@ public void TransactionAggregate_DeclineTransactionLocally_TransactionAlreadyAut TestData.TransactionAmount); transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, TestData.ResponseCode, TestData.ResponseMessage); - Should.Throw(() => { transactionAggregate.DeclineTransactionLocally(TestData.ResponseCode, TestData.ResponseMessage); }); + Result result = transactionAggregate.DeclineTransactionLocally(TestData.ResponseCode, TestData.ResponseMessage); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -566,7 +594,9 @@ public void TransactionAggregate_DeclineTransactionLocally_TransactionAlreadyAut transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); - Should.Throw(() => { transactionAggregate.DeclineTransactionLocally(TestData.ResponseCode, TestData.ResponseMessage); }); + Result result = transactionAggregate.DeclineTransactionLocally(TestData.ResponseCode, TestData.ResponseMessage); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -588,7 +618,9 @@ public void TransactionAggregate_DeclineTransactionLocally_TransactionAlreadyDec transactionAggregate.DeclineTransactionLocally(TestData.ResponseCode, TestData.ResponseMessage); - Should.Throw(() => { transactionAggregate.DeclineTransactionLocally(TestData.ResponseCode, TestData.ResponseMessage); }); + Result result = transactionAggregate.DeclineTransactionLocally(TestData.ResponseCode, TestData.ResponseMessage); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -610,7 +642,9 @@ public void TransactionAggregate_DeclineTransactionLocally_TransactionAlreadyDec transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); - Should.Throw(() => { transactionAggregate.DeclineTransactionLocally(TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); }); + Result result = transactionAggregate.DeclineTransactionLocally(TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -630,7 +664,8 @@ public void TransactionAggregate_DeclineTransaction_TransactionIsDeclined(Transa transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); } - transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.DeclinedOperatorResponseCode, TestData.DeclinedOperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); + Result result = transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.DeclinedOperatorResponseCode, TestData.DeclinedOperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.IsAuthorised.ShouldBeFalse(); transactionAggregate.IsLocallyAuthorised.ShouldBeFalse(); @@ -645,7 +680,9 @@ public void TransactionAggregate_DeclineTransaction_TransactionIsDeclined(Transa public void TransactionAggregate_DeclineTransaction_TransactionNotStarted_ErrorThrown(){ Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - Should.Throw(() => { transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.DeclinedOperatorResponseCode, TestData.DeclinedOperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); }); + Result result = transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.DeclinedOperatorResponseCode, TestData.DeclinedOperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } //[Theory] @@ -682,7 +719,9 @@ public void TransactionAggregate_DeclineTransaction_TransactionAlreadyAuthorised transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); - Should.Throw(() => { transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.DeclinedOperatorResponseCode, TestData.DeclinedOperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); }); + Result result = transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.DeclinedOperatorResponseCode, TestData.DeclinedOperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -704,7 +743,9 @@ public void TransactionAggregate_DeclineTransaction_TransactionAlreadyDeclinedLo transactionAggregate.DeclineTransactionLocally(TestData.ResponseCode, TestData.ResponseMessage); - Should.Throw(() => { transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.DeclinedOperatorResponseCode, TestData.DeclinedOperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); }); + Result result = transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.DeclinedOperatorResponseCode, TestData.DeclinedOperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -726,7 +767,9 @@ public void TransactionAggregate_DeclineTransaction_TransactionAlreadyDeclined_E transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.DeclinedOperatorResponseCode, TestData.DeclinedOperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); - Should.Throw(() => { transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.DeclinedOperatorResponseCode, TestData.DeclinedOperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); }); + Result result = transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.DeclinedOperatorResponseCode, TestData.DeclinedOperatorResponseMessage, TestData.DeclinedResponseCode, TestData.DeclinedResponseMessage); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -759,7 +802,9 @@ public void TransactionAggregate_CompleteTransaction_TransactionIsCompleted(Tran public void TransactionAggregate_CompleteTransaction_TransactionNotStarted_ErrorThrown(){ Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - Should.Throw(() => { transactionAggregate.CompleteTransaction(); }); + Result result = transactionAggregate.CompleteTransaction(); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -779,7 +824,9 @@ public void TransactionAggregate_CompleteTransaction_TransactionNotAuthorised_Er transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); } - Should.Throw(() => { transactionAggregate.CompleteTransaction(); }); + Result result = transactionAggregate.CompleteTransaction(); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -806,7 +853,9 @@ public void TransactionAggregate_CompleteTransaction_TransactionAlreadyCompleted transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.CompleteTransaction(); }); + Result result = transactionAggregate.CompleteTransaction(); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -826,8 +875,8 @@ public void TransactionAggregate_RecordAdditionalRequestData_RequestDataRecorded transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); } - Should.NotThrow(() => { transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); }); - + Result result = transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); + result.IsSuccess.ShouldBeTrue(); } [Theory] @@ -836,7 +885,9 @@ public void TransactionAggregate_RecordAdditionalRequestData_RequestDataRecorded public void TransactionAggregate_RecordAdditionalRequestData_TransactionNotStarted_ErrorThrown(TransactionType transactionType){ Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - Should.Throw(() => { transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); }); + Result result = transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -858,7 +909,9 @@ public void TransactionAggregate_RecordAdditionalRequestData_AdditionalRequestDa transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); - Should.Throw(() => { transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); }); + Result result = transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -887,7 +940,9 @@ public void TransactionAggregate_RecordAdditionalRequestData_AlreadyAuthorised_E transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); } - Should.Throw(() => { transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); }); + Result result = transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -916,7 +971,9 @@ public void TransactionAggregate_RecordAdditionalRequestData_AlreadyDeclined_Err transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.ResponseCode, TestData.ResponseMessage); } - Should.Throw(() => { transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); }); + Result result = transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -946,7 +1003,9 @@ public void TransactionAggregate_RecordAdditionalRequestData_AlreadyCompleted_Er transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); }); + Result result = transactionAggregate.RecordAdditionalRequestData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } //####### @@ -976,7 +1035,8 @@ public void TransactionAggregate_RecordAdditionalResponseData_ResponseDataRecord transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); } - Should.NotThrow(() => { transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); }); + Result result = transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); + result.IsSuccess.ShouldBeTrue(); } @@ -986,7 +1046,9 @@ public void TransactionAggregate_RecordAdditionalResponseData_ResponseDataRecord public void TransactionAggregate_RecordAdditionalResponseData_TransactionNotStarted_ErrorThrown(TransactionType transactionType){ Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - Should.Throw(() => { transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); }); + Result result = transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1016,7 +1078,9 @@ public void TransactionAggregate_RecordAdditionalResponseData_AdditionalResponse transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); - Should.Throw(() => { transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); }); + Result result = transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1047,7 +1111,9 @@ public void TransactionAggregate_RecordAdditionalResponseData_AlreadyCompleted_E transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); }); + Result result = transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -1067,7 +1133,8 @@ public void TransactionAggregate_RequestEmailReceipt_CustomerEmailReceiptHasBeen transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); transactionAggregate.CompleteTransaction(); - transactionAggregate.RequestEmailReceipt(TestData.CustomerEmailAddress); + Result result = transactionAggregate.RequestEmailReceipt(TestData.CustomerEmailAddress); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.CustomerEmailReceiptHasBeenRequested.ShouldBeTrue(); transactionAggregate.CustomerEmailAddress.ShouldBe(TestData.CustomerEmailAddress); @@ -1089,7 +1156,9 @@ public void TransactionAggregate_RequestEmailReceipt_TransactionNotCompleted_Err transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); - Should.Throw(() => { transactionAggregate.RequestEmailReceipt(TestData.CustomerEmailAddress); }); + Result result = transactionAggregate.RequestEmailReceipt(TestData.CustomerEmailAddress); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -1111,7 +1180,9 @@ public void TransactionAggregate_RequestEmailReceipt_EmailReceiptAlreadyRequeste transactionAggregate.RequestEmailReceipt(TestData.CustomerEmailAddress); - Should.Throw(() => { transactionAggregate.RequestEmailReceipt(TestData.CustomerEmailAddress); }); + Result result = transactionAggregate.RequestEmailReceipt(TestData.CustomerEmailAddress); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -1132,7 +1203,8 @@ public void TransactionAggregate_RequestEmailReceiptResend_CustomerEmailReceiptH transactionAggregate.CompleteTransaction(); transactionAggregate.RequestEmailReceipt(TestData.CustomerEmailAddress); - transactionAggregate.RequestEmailReceiptResend(); + Result result = transactionAggregate.RequestEmailReceiptResend(); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.ReceiptResendCount.ShouldBe(1); } @@ -1153,7 +1225,9 @@ public void TransactionAggregate_RequestEmailReceiptResend_ReceiptNotSent_ErrorT transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.RecordAdditionalResponseData(TestData.OperatorId, TestData.AdditionalTransactionMetaDataForMobileTopup()); - Should.Throw(() => { transactionAggregate.RequestEmailReceiptResend(); }); + var result = transactionAggregate.RequestEmailReceiptResend(); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1175,7 +1249,8 @@ public void TransactionAggregate_AddFee_FeeDetailsAdded(TransactionType transact CalculatedFee calculatedFee = this.GetCalculatedFeeToAdd(feeType); - transactionAggregate.AddFee(calculatedFee); + Result result = transactionAggregate.AddFee(calculatedFee); + result.IsSuccess.ShouldBeTrue(); List fees = transactionAggregate.GetFees(); @@ -1206,7 +1281,9 @@ public void TransactionAggregate_AddFee_NullFee_ErrorThrown(TransactionType tran transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddFee(null); }); + Result result = transactionAggregate.AddFee(null); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1227,7 +1304,9 @@ public void TransactionAggregate_AddFee_TransactionNotAuthorised_ErrorThrown(Tra transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddFee(this.GetCalculatedFeeToAdd(feeType)); }); + Result result = transactionAggregate.AddFee(this.GetCalculatedFeeToAdd(feeType)); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } private CalculatedFee GetCalculatedFeeToAdd(FeeType feeType){ @@ -1258,7 +1337,9 @@ public void TransactionAggregate_AddFee_TransactionNotCompleted_ErrorThrown(Tran transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); - Should.Throw(() => { transactionAggregate.AddFee(this.GetCalculatedFeeToAdd(feeType)); }); + Result result = transactionAggregate.AddFee(this.GetCalculatedFeeToAdd(feeType)); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1279,7 +1360,9 @@ public void TransactionAggregate_AddFee_FeeAlreadyAdded_NoErrorThrown(Transactio transactionAggregate.CompleteTransaction(); transactionAggregate.AddFee(this.GetCalculatedFeeToAdd(feeType)); - Should.NotThrow(() => { transactionAggregate.AddFee(this.GetCalculatedFeeToAdd(feeType)); }); + Result result = transactionAggregate.AddFee(this.GetCalculatedFeeToAdd(feeType)); + result.IsSuccess.ShouldBeTrue(); + transactionAggregate.GetFees().Count.ShouldBe(1); } @@ -1300,7 +1383,9 @@ public void TransactionAggregate_AddFee_UnsupportedFeeType_ErrorThrown(Transacti transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddFee(TestData.CalculatedFeeUnsupportedFee); }); + Result result = transactionAggregate.AddFee(TestData.CalculatedFeeUnsupportedFee); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1320,7 +1405,9 @@ public void TransactionAggregate_AddFee_LogonTransaction_ErrorThrown(FeeType fee transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddFee(this.GetCalculatedFeeToAdd(feeType)); }); + Result result = transactionAggregate.AddFee(this.GetCalculatedFeeToAdd(feeType)); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1342,7 +1429,8 @@ public void TransactionAggregate_AddSettledFee_FeeDetailsAdded(TransactionType t CalculatedFee calculatedFee = this.GetCalculatedFeeToAdd(feeType); transactionAggregate.AddFeePendingSettlement(calculatedFee, TestData.TransactionFeeSettlementDueDate); - transactionAggregate.AddSettledFee(calculatedFee, TestData.SettlementDate,TestData.SettlementAggregateId); + Result result = transactionAggregate.AddSettledFee(calculatedFee, TestData.SettlementDate,TestData.SettlementAggregateId); + result.IsSuccess.ShouldBeTrue(); List fees = transactionAggregate.GetFees(); @@ -1373,7 +1461,9 @@ public void TransactionAggregate_AddSettledFee_NullFee_ErrorThrown(TransactionTy transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddSettledFee(null, TestData.SettlementDate, TestData.SettlementAggregateId); }); + Result result = transactionAggregate.AddSettledFee(null, TestData.SettlementDate, TestData.SettlementAggregateId); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1393,7 +1483,9 @@ public void TransactionAggregate_AddSettledFee_TransactionNotAuthorised_ErrorThr transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddSettledFee(this.GetCalculatedFeeToAdd(feeType), TestData.SettlementDate, TestData.SettlementAggregateId); }); + Result result = transactionAggregate.AddSettledFee(this.GetCalculatedFeeToAdd(feeType), TestData.SettlementDate, TestData.SettlementAggregateId); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1412,7 +1504,9 @@ public void TransactionAggregate_AddSettledFee_TransactionNotCompleted_ErrorThro transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); - Should.Throw(() => { transactionAggregate.AddSettledFee(this.GetCalculatedFeeToAdd(feeType), TestData.SettlementDate, TestData.SettlementAggregateId); }); + Result result = transactionAggregate.AddSettledFee(this.GetCalculatedFeeToAdd(feeType), TestData.SettlementDate, TestData.SettlementAggregateId); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1435,7 +1529,8 @@ public void TransactionAggregate_AddSettledFee_FeeNotAlreadyAdded_NoErrorThrown( transactionAggregate.AddFeePendingSettlement(feeDetails, TestData.TransactionFeeSettlementDueDate); transactionAggregate.AddSettledFee(feeDetails, TestData.SettlementDate, TestData.SettlementAggregateId); - Should.NotThrow(() => { transactionAggregate.AddSettledFee(feeDetails, TestData.SettlementDate, TestData.SettlementAggregateId); }); + Result result = transactionAggregate.AddSettledFee(feeDetails, TestData.SettlementDate, TestData.SettlementAggregateId); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.GetFees().Count.ShouldBe(1); } @@ -1459,9 +1554,9 @@ public void TransactionAggregate_AddSettledFee_UnsupportedFeeType_ErrorThrown(Tr CalculatedFee feeDetails = this.GetCalculatedFeeToAdd(FeeType.Merchant); transactionAggregate.AddFeePendingSettlement(feeDetails, TestData.TransactionFeeSettlementDueDate); - Should.Throw(() => { - transactionAggregate.AddSettledFee(TestData.CalculatedFeeUnsupportedFee, TestData.SettlementDate, TestData.SettlementAggregateId); - }); + Result result = transactionAggregate.AddSettledFee(TestData.CalculatedFeeUnsupportedFee, TestData.SettlementDate, TestData.SettlementAggregateId); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1480,7 +1575,9 @@ public void TransactionAggregate_AddSettledFee_LogonTransaction_ErrorThrown(FeeT transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddSettledFee(this.GetCalculatedFeeToAdd(feeType), TestData.SettlementDate, TestData.SettlementAggregateId); }); + Result result = transactionAggregate.AddSettledFee(this.GetCalculatedFeeToAdd(feeType), TestData.SettlementDate, TestData.SettlementAggregateId); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1502,7 +1599,8 @@ public void TransactionAggregate_AddFeePendingSettlement_FeeDetailsAdded(Transac CalculatedFee calculatedFee = this.GetCalculatedFeeToAdd(feeType); - transactionAggregate.AddFeePendingSettlement(calculatedFee, DateTime.Now); + Result result = transactionAggregate.AddFeePendingSettlement(calculatedFee, DateTime.Now); + result.IsSuccess.ShouldBeTrue(); List fees = transactionAggregate.GetFees(); @@ -1533,7 +1631,9 @@ public void TransactionAggregate_AddFeePendingSettlement_NullFee_ErrorThrown(Tra transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddFeePendingSettlement(null, DateTime.Now); }); + Result result = transactionAggregate.AddFeePendingSettlement(null, DateTime.Now); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1554,7 +1654,9 @@ public void TransactionAggregate_AddFeePendingSettlement_TransactionNotAuthorise transactionAggregate.DeclineTransaction(TestData.OperatorId, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddFeePendingSettlement(this.GetCalculatedFeeToAdd(feeType), DateTime.Now); }); + Result result = transactionAggregate.AddFeePendingSettlement(this.GetCalculatedFeeToAdd(feeType), DateTime.Now); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } @@ -1574,7 +1676,9 @@ public void TransactionAggregate_AddFeePendingSettlement_TransactionNotCompleted transactionAggregate.AddProductDetails(TestData.ContractId, TestData.ProductId); transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); - Should.Throw(() => { transactionAggregate.AddFeePendingSettlement(this.GetCalculatedFeeToAdd(feeType), DateTime.Now); }); + Result result = transactionAggregate.AddFeePendingSettlement(this.GetCalculatedFeeToAdd(feeType), DateTime.Now); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1595,7 +1699,8 @@ public void TransactionAggregate_AddFeePendingSettlement_FeeAlreadyAdded_NoError transactionAggregate.CompleteTransaction(); transactionAggregate.AddFeePendingSettlement(this.GetCalculatedFeeToAdd(feeType), DateTime.Now); - Should.NotThrow(() => { transactionAggregate.AddFeePendingSettlement(this.GetCalculatedFeeToAdd(feeType), DateTime.Now); }); + var result = transactionAggregate.AddFeePendingSettlement(this.GetCalculatedFeeToAdd(feeType), DateTime.Now); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.GetFees().Count.ShouldBe(1); } @@ -1616,7 +1721,9 @@ public void TransactionAggregate_AddFeePendingSettlement_UnsupportedFeeType_Erro transactionAggregate.AuthoriseTransaction(TestData.OperatorId, TestData.OperatorAuthorisationCode, TestData.OperatorResponseCode, TestData.OperatorResponseMessage, TestData.OperatorTransactionId, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddFeePendingSettlement(TestData.CalculatedFeeUnsupportedFee, DateTime.Now); }); + Result result = transactionAggregate.AddFeePendingSettlement(TestData.CalculatedFeeUnsupportedFee, DateTime.Now); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Theory] @@ -1636,7 +1743,9 @@ public void TransactionAggregate_AddFeePendingSettlement_LogonTransaction_ErrorT transactionAggregate.AuthoriseTransactionLocally(TestData.AuthorisationCode, TestData.ResponseCode, TestData.ResponseMessage); transactionAggregate.CompleteTransaction(); - Should.Throw(() => { transactionAggregate.AddFeePendingSettlement(this.GetCalculatedFeeToAdd(feeType), DateTime.Now); }); + Result result = transactionAggregate.AddFeePendingSettlement(this.GetCalculatedFeeToAdd(feeType), DateTime.Now); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } public static TheoryData TransactionAggregate_RecordCostPrice_SaleTransaction_CostPriceRecorded_Data => @@ -1662,7 +1771,8 @@ public void TransactionAggregate_RecordCostPrice_SaleTransaction_CostPriceRecord TestData.DeviceIdentifier, TestData.TransactionAmount); - transactionAggregate.RecordCostPrice(unitCost, totalCost); + Result result = transactionAggregate.RecordCostPrice(unitCost, totalCost); + result.IsSuccess.ShouldBeTrue(); transactionAggregate.UnitCost.ShouldBe(expectedUnitCost); transactionAggregate.TotalCost.ShouldBe(expectedTotalCost); @@ -1683,14 +1793,17 @@ public void TransactionAggregate_RecordCostPrice_SaleTransaction_CostAlreadyReco transactionAggregate.RecordCostPrice(TestData.UnitCostPrice, TestData.TotalCostPrice); - Should.Throw(() => { transactionAggregate.RecordCostPrice(TestData.UnitCostPrice, TestData.TotalCostPrice); }); + Result result = transactionAggregate.RecordCostPrice(TestData.UnitCostPrice, TestData.TotalCostPrice); + result.IsSuccess.ShouldBeTrue(); } [Fact] public void TransactionAggregate_RecordCostPrice_SaleTransaction_NotStarted_ErrorThrown(){ Aggregates.TransactionAggregate transactionAggregate = Aggregates.TransactionAggregate.Create(TestData.TransactionId); - Should.Throw(() => { transactionAggregate.RecordCostPrice(TestData.UnitCostPrice, TestData.TotalCostPrice); }); + Result result = transactionAggregate.RecordCostPrice(TestData.UnitCostPrice, TestData.TotalCostPrice); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } } } diff --git a/TransactionProcessor.Aggregates/TransactionAggregate.cs b/TransactionProcessor.Aggregates/TransactionAggregate.cs index 8daa408..f211edd 100644 --- a/TransactionProcessor.Aggregates/TransactionAggregate.cs +++ b/TransactionProcessor.Aggregates/TransactionAggregate.cs @@ -1,4 +1,5 @@ -using TransactionProcessor.DomainEvents; +using SimpleResults; +using TransactionProcessor.DomainEvents; using TransactionProcessor.Models; using TransactionProcessor.Models.Contract; @@ -14,19 +15,25 @@ namespace TransactionProcessor.Aggregates public static class TransactionAggregateExtensions{ - public static void DeclineTransaction(this TransactionAggregate aggregate, + public static Result DeclineTransaction(this TransactionAggregate aggregate, Guid operatorId, String operatorResponseCode, String operatorResponseMessage, String responseCode, String responseMessage) { - aggregate.CheckTransactionHasBeenStarted(); - aggregate.CheckTransactionNotAlreadyAuthorised(); - aggregate.CheckTransactionNotAlreadyDeclined(); + Result result = aggregate.CheckTransactionHasBeenStarted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionNotAlreadyAuthorised(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionNotAlreadyDeclined(); + if (result.IsFailed) + return result; TransactionDomainEvents.TransactionDeclinedByOperatorEvent transactionDeclinedByOperatorEvent = - new TransactionDomainEvents.TransactionDeclinedByOperatorEvent(aggregate.AggregateId, + new(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, operatorId, @@ -36,20 +43,30 @@ public static void DeclineTransaction(this TransactionAggregate aggregate, responseMessage, aggregate.TransactionDateTime); aggregate.ApplyAndAppend(transactionDeclinedByOperatorEvent); + + return Result.Success(); } - public static void DeclineTransactionLocally(this TransactionAggregate aggregate, + public static Result DeclineTransactionLocally(this TransactionAggregate aggregate, String responseCode, String responseMessage) { - aggregate.CheckTransactionHasBeenStarted(); - aggregate.CheckTransactionNotAlreadyAuthorised(); - aggregate.CheckTransactionNotAlreadyDeclined(); + Result result = aggregate.CheckTransactionHasBeenStarted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionNotAlreadyAuthorised(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionNotAlreadyDeclined(); + if (result.IsFailed) + return result; TransactionDomainEvents.TransactionHasBeenLocallyDeclinedEvent transactionHasBeenLocallyDeclinedEvent = - new TransactionDomainEvents.TransactionHasBeenLocallyDeclinedEvent(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, responseCode, responseMessage, + new(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, responseCode, responseMessage, aggregate.TransactionDateTime); aggregate.ApplyAndAppend(transactionHasBeenLocallyDeclinedEvent); + + return Result.Success(); } public static List GetFees(this TransactionAggregate aggregate) @@ -77,16 +94,23 @@ public static TransactionProcessor.Models.Transaction GetTransaction(this Transa }; } - public static void AddFee(this TransactionAggregate aggregate, CalculatedFee calculatedFee) + public static Result AddFee(this TransactionAggregate aggregate, CalculatedFee calculatedFee) { - Guard.ThrowIfNull(calculatedFee, nameof(calculatedFee)); - if (aggregate.HasFeeAlreadyBeenAdded(calculatedFee)) - return; + return Result.Success(); - aggregate.CheckTransactionHasBeenAuthorised(); - aggregate.CheckTransactionHasBeenCompleted(); - aggregate.CheckTransactionCanAttractFees(); + if (calculatedFee == null) + return Result.Invalid("Calculated Fee must not be null"); + + Result result = aggregate.CheckTransactionHasBeenAuthorised(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionHasBeenCompleted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionCanAttractFees(); + if (result.IsFailed) + return result; DomainEvent @event = null; if (calculatedFee.FeeType == FeeType.ServiceProvider) @@ -104,43 +128,61 @@ public static void AddFee(this TransactionAggregate aggregate, CalculatedFee cal } else { - throw new InvalidOperationException("Unsupported Fee Type"); + return Result.Invalid("Unsupported Fee Type"); } aggregate.ApplyAndAppend(@event); + + return Result.Success(); } - public static void AddProductDetails(this TransactionAggregate aggregate, Guid contractId, + public static Result AddProductDetails(this TransactionAggregate aggregate, Guid contractId, Guid productId) { - Guard.ThrowIfInvalidGuid(contractId, typeof(ArgumentException), $"Contract Id must not be [{Guid.Empty}]"); - Guard.ThrowIfInvalidGuid(productId, typeof(ArgumentException), $"Product Id must not be [{Guid.Empty}]"); - - aggregate.CheckTransactionHasBeenStarted(); - aggregate.CheckTransactionNotAlreadyCompleted(); - aggregate.CheckProductDetailsNotAlreadyAdded(); + if (contractId == Guid.Empty) + return Result.Invalid($"Contract Id must not be [{Guid.Empty}]"); + if (productId == Guid.Empty) + return Result.Invalid($"Product Id must not be [{Guid.Empty}]"); + + Result result = aggregate.CheckTransactionHasBeenStarted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionNotAlreadyCompleted(); + if (result.IsFailed) + return result; + result = aggregate.CheckProductDetailsNotAlreadyAdded(); + if (result.IsFailed) + return result; TransactionDomainEvents.ProductDetailsAddedToTransactionEvent productDetailsAddedToTransactionEvent = - new TransactionDomainEvents.ProductDetailsAddedToTransactionEvent(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, contractId, productId, + new(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, contractId, productId, aggregate.TransactionDateTime); aggregate.ApplyAndAppend(productDetailsAddedToTransactionEvent); + + return Result.Success(); } - public static void AddFeePendingSettlement(this TransactionAggregate aggregate, CalculatedFee calculatedFee, + public static Result AddFeePendingSettlement(this TransactionAggregate aggregate, CalculatedFee calculatedFee, DateTime settlementDueDate) { if (calculatedFee == null) { - throw new ArgumentNullException(nameof(calculatedFee)); + return Result.Invalid("Calculated fee cannot be null"); } if (aggregate.HasFeeAlreadyBeenAdded(calculatedFee)) - return; - - aggregate.CheckTransactionHasBeenAuthorised(); - aggregate.CheckTransactionHasBeenCompleted(); - aggregate.CheckTransactionCanAttractFees(); + return Result.Success(); + + Result result = aggregate.CheckTransactionHasBeenAuthorised(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionHasBeenCompleted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionCanAttractFees(); + if (result.IsFailed) + return result; DomainEvent @event = null; if (calculatedFee.FeeType == FeeType.Merchant){ @@ -157,26 +199,34 @@ public static void AddFeePendingSettlement(this TransactionAggregate aggregate, } else { - throw new InvalidOperationException("Unsupported Fee Type"); + return Result.Invalid("Unsupported Fee Type"); } aggregate.ApplyAndAppend(@event); + + return Result.Success(); } - public static void AddSettledFee(this TransactionAggregate aggregate, CalculatedFee calculatedFee, + public static Result AddSettledFee(this TransactionAggregate aggregate, CalculatedFee calculatedFee, DateTime settledDateTime, Guid settlementId) { - if (calculatedFee == null) - { - throw new ArgumentNullException(nameof(calculatedFee)); + if (calculatedFee == null) { + return Result.Invalid("Calculated fee cannot be null"); } - aggregate.CheckTransactionHasBeenAuthorised(); - aggregate.CheckTransactionHasBeenCompleted(); - aggregate.CheckTransactionCanAttractFees(); + if (aggregate.HasFeeAlreadyBeenSettled(calculatedFee)) + return Result.Success(); + + Result result = aggregate.CheckTransactionHasBeenAuthorised(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionHasBeenCompleted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionCanAttractFees(); + if (result.IsFailed) + return result; - if (aggregate.HasFeeAlreadyBeenSettled(calculatedFee) == true) - return; DomainEvent @event = null; if (calculatedFee.FeeType == FeeType.Merchant) @@ -196,27 +246,31 @@ public static void AddSettledFee(this TransactionAggregate aggregate, Calculated } else { - throw new InvalidOperationException("Unsupported Fee Type"); + return Result.Invalid("Unsupported Fee Type"); } aggregate.ApplyAndAppend(@event); + return Result.Success(); } - public static void AddTransactionSource(this TransactionAggregate aggregate, TransactionSource transactionSource) + public static Result AddTransactionSource(this TransactionAggregate aggregate, TransactionSource transactionSource) { - Guard.ThrowIfInvalidEnum(typeof(TransactionSource), transactionSource, typeof(ArgumentException), "Transaction Source must be a valid source"); - if (aggregate.TransactionSource != TransactionSource.NotSet) - return; + return Result.Success(); + + if (Enum.IsDefined(typeof(TransactionSource), transactionSource) == false) + return Result.Invalid("Transaction Source must be a valid source"); TransactionDomainEvents.TransactionSourceAddedToTransactionEvent transactionSourceAddedToTransactionEvent = - new TransactionDomainEvents.TransactionSourceAddedToTransactionEvent(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, (Int32)transactionSource, + new(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, (Int32)transactionSource, aggregate.TransactionDateTime); aggregate.ApplyAndAppend(transactionSourceAddedToTransactionEvent); + + return Result.Success(); } - public static void AuthoriseTransaction(this TransactionAggregate aggregate, + public static Result AuthoriseTransaction(this TransactionAggregate aggregate, Guid operatorId, String authorisationCode, String operatorResponseCode, @@ -225,10 +279,14 @@ public static void AuthoriseTransaction(this TransactionAggregate aggregate, String responseCode, String responseMessage) { - aggregate.CheckTransactionHasBeenStarted(); - aggregate.CheckTransactionNotAlreadyAuthorised(); + Result result = aggregate.CheckTransactionHasBeenStarted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionNotAlreadyAuthorised(); + if (result.IsFailed) + return result; - TransactionDomainEvents.TransactionAuthorisedByOperatorEvent transactionAuthorisedByOperatorEvent = new TransactionDomainEvents.TransactionAuthorisedByOperatorEvent(aggregate.AggregateId, + TransactionDomainEvents.TransactionAuthorisedByOperatorEvent transactionAuthorisedByOperatorEvent = new(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, operatorId, @@ -240,31 +298,47 @@ public static void AuthoriseTransaction(this TransactionAggregate aggregate, responseMessage, aggregate.TransactionDateTime); aggregate.ApplyAndAppend(transactionAuthorisedByOperatorEvent); + + return Result.Success(); } - public static void AuthoriseTransactionLocally(this TransactionAggregate aggregate, + public static Result AuthoriseTransactionLocally(this TransactionAggregate aggregate, String authorisationCode, String responseCode, String responseMessage) { - aggregate.CheckTransactionHasBeenStarted(); - aggregate.CheckTransactionNotAlreadyAuthorised(); - aggregate.CheckTransactionCanBeLocallyAuthorised(); + var result = aggregate.CheckTransactionHasBeenStarted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionNotAlreadyAuthorised(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionCanBeLocallyAuthorised(); + if (result.IsFailed) + return result; TransactionDomainEvents.TransactionHasBeenLocallyAuthorisedEvent transactionHasBeenLocallyAuthorisedEvent = - new TransactionDomainEvents.TransactionHasBeenLocallyAuthorisedEvent(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, authorisationCode, responseCode, responseMessage, + new(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, authorisationCode, responseCode, responseMessage, aggregate.TransactionDateTime); aggregate.ApplyAndAppend(transactionHasBeenLocallyAuthorisedEvent); + + return Result.Success(); } - public static void CompleteTransaction(this TransactionAggregate aggregate) + public static Result CompleteTransaction(this TransactionAggregate aggregate) { - aggregate.CheckTransactionHasBeenStarted(); - aggregate.CheckTransactionHasBeenAuthorisedOrDeclined(); - aggregate.CheckTransactionNotAlreadyCompleted(); + Result result = aggregate.CheckTransactionHasBeenStarted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionHasBeenAuthorisedOrDeclined(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionNotAlreadyCompleted(); + if (result.IsFailed) + return result; TransactionDomainEvents.TransactionHasBeenCompletedEvent transactionHasBeenCompletedEvent = - new TransactionDomainEvents.TransactionHasBeenCompletedEvent(aggregate.AggregateId, + new(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, aggregate.ResponseCode, @@ -275,9 +349,11 @@ public static void CompleteTransaction(this TransactionAggregate aggregate) aggregate.TransactionDateTime); aggregate.ApplyAndAppend(transactionHasBeenCompletedEvent); + + return Result.Success(); } - public static void RecordTransactionTimings(this TransactionAggregate aggregate, + public static Result RecordTransactionTimings(this TransactionAggregate aggregate, DateTime TransactionStartedDateTime, DateTime? OperatorCommunicationsStartedEvent, DateTime? OperatorCommunicationsCompletedEvent, @@ -292,63 +368,92 @@ public static void RecordTransactionTimings(this TransactionAggregate aggregate, TransactionCompletedDateTime); aggregate.ApplyAndAppend(transactionTimingsAddedToTransactionEvent); + + return Result.Success(); } - public static void RecordAdditionalRequestData(this TransactionAggregate aggregate, + public static Result RecordAdditionalRequestData(this TransactionAggregate aggregate, Guid operatorId, Dictionary additionalTransactionRequestMetadata) { - aggregate.CheckTransactionNotAlreadyCompleted(); - aggregate.CheckTransactionHasBeenStarted(); - aggregate.CheckTransactionNotAlreadyAuthorised(); - aggregate.CheckTransactionNotAlreadyDeclined(); - aggregate.CheckAdditionalRequestDataNotAlreadyRecorded(); + var result = aggregate.CheckTransactionNotAlreadyCompleted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionHasBeenStarted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionNotAlreadyAuthorised(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionNotAlreadyDeclined(); + if (result.IsFailed) + return result; + result= aggregate.CheckAdditionalRequestDataNotAlreadyRecorded(); + if (result.IsFailed) + return result; TransactionDomainEvents.AdditionalRequestDataRecordedEvent additionalRequestDataRecordedEvent = - new TransactionDomainEvents.AdditionalRequestDataRecordedEvent(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, operatorId, additionalTransactionRequestMetadata, + new(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, operatorId, additionalTransactionRequestMetadata, aggregate.TransactionDateTime); aggregate.ApplyAndAppend(additionalRequestDataRecordedEvent); + + return Result.Success(); } - public static void RecordAdditionalResponseData(this TransactionAggregate aggregate, + public static Result RecordAdditionalResponseData(this TransactionAggregate aggregate, Guid operatorId, Dictionary additionalTransactionResponseMetadata) { - aggregate.CheckTransactionHasBeenStarted(); - aggregate.CheckAdditionalResponseDataNotAlreadyRecorded(); + Result result = aggregate.CheckTransactionHasBeenStarted(); + if (result.IsFailed) + return result; + result = aggregate.CheckAdditionalResponseDataNotAlreadyRecorded(); + if (result.IsFailed) + return result; TransactionDomainEvents.AdditionalResponseDataRecordedEvent additionalResponseDataRecordedEvent = - new TransactionDomainEvents.AdditionalResponseDataRecordedEvent(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, operatorId, additionalTransactionResponseMetadata, + new(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, operatorId, additionalTransactionResponseMetadata, aggregate.TransactionDateTime); aggregate.ApplyAndAppend(additionalResponseDataRecordedEvent); + return Result.Success(); } - public static void RequestEmailReceipt(this TransactionAggregate aggregate, String customerEmailAddress) + public static Result RequestEmailReceipt(this TransactionAggregate aggregate, String customerEmailAddress) { - aggregate.CheckTransactionHasBeenCompleted(); - aggregate.CheckCustomerHasNotAlreadyRequestedEmailReceipt(); + Result result = aggregate.CheckTransactionHasBeenCompleted(); + if (result.IsFailed) + return result; + result = aggregate.CheckCustomerHasNotAlreadyRequestedEmailReceipt(); + if (result.IsFailed) + return result; TransactionDomainEvents.CustomerEmailReceiptRequestedEvent customerEmailReceiptRequestedEvent = - new TransactionDomainEvents.CustomerEmailReceiptRequestedEvent(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, customerEmailAddress, + new(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, customerEmailAddress, aggregate.TransactionDateTime); aggregate.ApplyAndAppend(customerEmailReceiptRequestedEvent); + + return Result.Success(); } - public static void RequestEmailReceiptResend(this TransactionAggregate aggregate) + public static Result RequestEmailReceiptResend(this TransactionAggregate aggregate) { - aggregate.CheckCustomerHasAlreadyRequestedEmailReceipt(); + var result = aggregate.CheckCustomerHasAlreadyRequestedEmailReceipt(); + if (result.IsFailed) + return result; TransactionDomainEvents.CustomerEmailReceiptResendRequestedEvent customerEmailReceiptResendRequestedEvent = - new TransactionDomainEvents.CustomerEmailReceiptResendRequestedEvent(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, + new(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, aggregate.TransactionDateTime); aggregate.ApplyAndAppend(customerEmailReceiptResendRequestedEvent); + + return Result.Success(); } - public static void StartTransaction(this TransactionAggregate aggregate, + public static Result StartTransaction(this TransactionAggregate aggregate, DateTime transactionDateTime, String transactionNumber, TransactionType transactionType, @@ -358,24 +463,35 @@ public static void StartTransaction(this TransactionAggregate aggregate, String deviceIdentifier, Decimal? transactionAmount) { - Guard.ThrowIfInvalidDate(transactionDateTime, typeof(ArgumentException), $"Transaction Date Time must not be [{DateTime.MinValue}]"); - Guard.ThrowIfNullOrEmpty(transactionNumber, typeof(ArgumentException), "Transaction Number must not be null or empty"); - Guard.ThrowIfNullOrEmpty(transactionReference, typeof(ArgumentException), "Transaction Reference must not be null or empty"); - if (Int32.TryParse(transactionNumber, out Int32 txnnumber) == false) - { - throw new ArgumentException("Transaction Number must be numeric"); + if (transactionDateTime == DateTime.MinValue) + return Result.Invalid($"Transaction Date Time must not be [{DateTime.MinValue}]"); + if (String.IsNullOrEmpty(transactionNumber)) + return Result.Invalid("Transaction Number must not be null or empty"); + if (String.IsNullOrEmpty(transactionReference)) + return Result.Invalid("Transaction Reference must not be null or empty"); + + if (Int32.TryParse(transactionNumber, out Int32 _) == false) { + return Result.Invalid("Transaction Number must be numeric"); } - // Validate the transaction Type - Guard.ThrowIfInvalidEnum(typeof(TransactionType), transactionType, typeof(ArgumentOutOfRangeException), $"Invalid Transaction Type [{transactionType}]"); + if (Enum.IsDefined(typeof(TransactionType), transactionType) == false) + return Result.Invalid("Transaction Type not valid"); - Guard.ThrowIfInvalidGuid(estateId, typeof(ArgumentException), $"Estate Id must not be [{Guid.Empty}]"); - Guard.ThrowIfInvalidGuid(merchantId, typeof(ArgumentException), $"Merchant Id must not be [{Guid.Empty}]"); - Guard.ThrowIfNullOrEmpty(deviceIdentifier, typeof(ArgumentException), "Device Identifier must not be null or empty"); + if (estateId == Guid.Empty) + return Result.Invalid($"Estate Id must not be [{Guid.Empty}]"); + if (merchantId == Guid.Empty) + return Result.Invalid($"Merchant Id must not be [{Guid.Empty}]"); + if (String.IsNullOrEmpty(deviceIdentifier)) + return Result.Invalid("Device Identifier must not be null or empty"); - aggregate.CheckTransactionNotAlreadyStarted(); - aggregate.CheckTransactionNotAlreadyCompleted(); - TransactionDomainEvents.TransactionHasStartedEvent transactionHasStartedEvent = new TransactionDomainEvents.TransactionHasStartedEvent(aggregate.AggregateId, + Result result = aggregate.CheckTransactionNotAlreadyStarted(); + if (result.IsFailed) + return result; + result = aggregate.CheckTransactionNotAlreadyCompleted(); + if (result.IsFailed) + return result; + + TransactionDomainEvents.TransactionHasStartedEvent transactionHasStartedEvent = new(aggregate.AggregateId, estateId, merchantId, transactionDateTime, @@ -386,16 +502,23 @@ public static void StartTransaction(this TransactionAggregate aggregate, transactionAmount); aggregate.ApplyAndAppend(transactionHasStartedEvent); - } - public static void RecordCostPrice(this TransactionAggregate aggregate, Decimal unitCost, Decimal totalCost){ - aggregate.CheckTransactionHasBeenStarted(); - aggregate.CheckCostValuesNotAlreadyRecorded(); + return Result.Success(); + } - // Dont emit an event when no cost + public static Result RecordCostPrice(this TransactionAggregate aggregate, Decimal unitCost, Decimal totalCost){ + // Don't emit an event when no cost if (unitCost == 0 || totalCost == 0) - return; + return Result.Success(); + Result result = aggregate.CheckTransactionHasBeenStarted(); + if (result.IsFailed) + return result; + + if (aggregate.UnitCost != null && aggregate.TotalCost != null) { + return Result.Success(); + } + TransactionDomainEvents.TransactionCostInformationRecordedEvent transactionCostInformationRecordedEvent = new TransactionDomainEvents.TransactionCostInformationRecordedEvent(aggregate.AggregateId, aggregate.EstateId, aggregate.MerchantId, @@ -404,136 +527,143 @@ public static void RecordCostPrice(this TransactionAggregate aggregate, Decimal aggregate.TransactionDateTime); aggregate.ApplyAndAppend(transactionCostInformationRecordedEvent); + + return Result.Success(); } - private static void CheckAdditionalRequestDataNotAlreadyRecorded(this TransactionAggregate aggregate) + private static Result CheckAdditionalRequestDataNotAlreadyRecorded(this TransactionAggregate aggregate) { if (aggregate.AdditionalTransactionRequestMetadata != null) { - throw new InvalidOperationException("Additional Request Data already recorded"); + return Result.Invalid("Additional Request Data already recorded"); } + return Result.Success(); } - private static void CheckAdditionalResponseDataNotAlreadyRecorded(this TransactionAggregate aggregate) + private static Result CheckAdditionalResponseDataNotAlreadyRecorded(this TransactionAggregate aggregate) { if (aggregate.AdditionalTransactionResponseMetadata != null) { - throw new InvalidOperationException("Additional Response Data already recorded"); + return Result.Invalid("Additional Response Data already recorded"); } + return Result.Success(); } - private static void CheckCostValuesNotAlreadyRecorded(this TransactionAggregate aggregate) - { - if (aggregate.UnitCost != null && aggregate.TotalCost != null) - { - throw new InvalidOperationException("Cost information already recorded"); - } - } - - private static void CheckCustomerHasNotAlreadyRequestedEmailReceipt(this TransactionAggregate aggregate) + private static Result CheckCustomerHasNotAlreadyRequestedEmailReceipt(this TransactionAggregate aggregate) { if (aggregate.CustomerEmailReceiptHasBeenRequested) { - throw new InvalidOperationException($"Customer Email Receipt already requested for Transaction [{aggregate.AggregateId}]"); + return Result.Invalid($"Customer Email Receipt already requested for Transaction [{aggregate.AggregateId}]"); } + return Result.Success(); } - private static void CheckCustomerHasAlreadyRequestedEmailReceipt(this TransactionAggregate aggregate) + private static Result CheckCustomerHasAlreadyRequestedEmailReceipt(this TransactionAggregate aggregate) { if (aggregate.CustomerEmailReceiptHasBeenRequested == false) { - throw new InvalidOperationException($"Customer Email Receipt not already requested for Transaction [{aggregate.AggregateId}]"); + return Result.Invalid($"Customer Email Receipt not already requested for Transaction [{aggregate.AggregateId}]"); } + return Result.Success(); } - private static void CheckProductDetailsNotAlreadyAdded(this TransactionAggregate aggregate) + private static Result CheckProductDetailsNotAlreadyAdded(this TransactionAggregate aggregate) { if (aggregate.IsProductDetailsAdded) { - throw new InvalidOperationException("Product details already added"); + return Result.Invalid("Product details already added"); } + return Result.Success(); } - private static void CheckTransactionCanAttractFees(this TransactionAggregate aggregate) + private static Result CheckTransactionCanAttractFees(this TransactionAggregate aggregate) { if (aggregate.TransactionType != TransactionType.Sale) { - throw new NotSupportedException($"Transactions of type {aggregate.TransactionType} cannot attract fees"); + return Result.Invalid($"Transactions of type {aggregate.TransactionType} cannot attract fees"); } + return Result.Success(); } - private static void CheckTransactionCanBeLocallyAuthorised(this TransactionAggregate aggregate) + private static Result CheckTransactionCanBeLocallyAuthorised(this TransactionAggregate aggregate) { if (aggregate.TransactionType == TransactionType.Sale) { - throw new InvalidOperationException("Sales cannot be locally authorised"); + return Result.Invalid("Sales cannot be locally authorised"); } + return Result.Success(); } - private static void CheckTransactionHasBeenAuthorised(this TransactionAggregate aggregate) + private static Result CheckTransactionHasBeenAuthorised(this TransactionAggregate aggregate) { if (aggregate.IsLocallyAuthorised == false && aggregate.IsAuthorised == false) { - throw new InvalidOperationException($"Transaction [{aggregate.AggregateId}] has not been authorised"); + return Result.Invalid($"Transaction [{aggregate.AggregateId}] has not been authorised"); } + return Result.Success(); } - private static void CheckTransactionHasBeenAuthorisedOrDeclined(this TransactionAggregate aggregate) + private static Result CheckTransactionHasBeenAuthorisedOrDeclined(this TransactionAggregate aggregate) { if (aggregate.IsAuthorised == false && aggregate.IsLocallyAuthorised == false && aggregate.IsDeclined == false && aggregate.IsLocallyDeclined == false) { - throw new InvalidOperationException($"Transaction [{aggregate.AggregateId}] has not been authorised or declined"); + return Result.Invalid($"Transaction [{aggregate.AggregateId}] has not been authorised or declined"); } + return Result.Success(); } - private static void CheckTransactionHasBeenCompleted(this TransactionAggregate aggregate) + private static Result CheckTransactionHasBeenCompleted(this TransactionAggregate aggregate) { if (aggregate.IsCompleted == false) { - throw new InvalidOperationException($"Transaction [{aggregate.AggregateId}] has not been completed"); + return Result.Invalid($"Transaction [{aggregate.AggregateId}] has not been completed"); } + return Result.Success(); } - private static void CheckTransactionHasBeenStarted(this TransactionAggregate aggregate) - { - if (aggregate.IsStarted == false) - { - throw new InvalidOperationException($"Transaction [{aggregate.AggregateId}] has not been started"); + private static Result CheckTransactionHasBeenStarted(this TransactionAggregate aggregate) { + if (aggregate.IsStarted == false) { + return Result.Invalid($"Transaction [{aggregate.AggregateId}] has not been started"); } + return Result.Success(); } - private static void CheckTransactionNotAlreadyAuthorised(this TransactionAggregate aggregate) + private static Result CheckTransactionNotAlreadyAuthorised(this TransactionAggregate aggregate) { if (aggregate.IsLocallyAuthorised || aggregate.IsAuthorised) { String authtype = aggregate.IsLocallyAuthorised ? " locally " : " "; - throw new InvalidOperationException($"Transaction [{aggregate.AggregateId}] has already been{authtype}authorised"); + return Result.Invalid($"Transaction [{aggregate.AggregateId}] has already been{authtype}authorised"); } + return Result.Success(); } - private static void CheckTransactionNotAlreadyCompleted(this TransactionAggregate aggregate) + private static Result CheckTransactionNotAlreadyCompleted(this TransactionAggregate aggregate) { if (aggregate.IsCompleted) { - throw new InvalidOperationException($"Transaction Id [{aggregate.AggregateId}] has already been completed"); + return Result.Invalid($"Transaction Id [{aggregate.AggregateId}] has already been completed"); } + return Result.Success(); } - private static void CheckTransactionNotAlreadyDeclined(this TransactionAggregate aggregate) + private static Result CheckTransactionNotAlreadyDeclined(this TransactionAggregate aggregate) { if (aggregate.IsLocallyDeclined || aggregate.IsDeclined) { String authtype = aggregate.IsLocallyDeclined ? " locally " : " "; - throw new InvalidOperationException($"Transaction [{aggregate.AggregateId}] has already been{authtype}declined"); + return Result.Invalid($"Transaction [{aggregate.AggregateId}] has already been{authtype}declined"); } + return Result.Success(); } - private static void CheckTransactionNotAlreadyStarted(this TransactionAggregate aggregate) + private static Result CheckTransactionNotAlreadyStarted(this TransactionAggregate aggregate) { if (aggregate.IsStarted) { - throw new InvalidOperationException($"Transaction Id [{aggregate.AggregateId}] has already been started"); + return Result.Invalid($"Transaction Id [{aggregate.AggregateId}] has already been started"); } + return Result.Success(); } private static Boolean HasFeeAlreadyBeenSettled(this TransactionAggregate aggregate, CalculatedFee calculatedFee) diff --git a/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs b/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs index d32f037..486258e 100644 --- a/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs @@ -102,7 +102,9 @@ public async Task> ProcessLogonTransacti // Generate a transaction reference String transactionReference = this.GenerateTransactionReference(); - transactionAggregate.StartTransaction(command.TransactionDateTime, command.TransactionNumber, transactionType, transactionReference, command.EstateId, command.MerchantId, command.DeviceIdentifier, null); // Logon transaction has no amount + Result stateResult = transactionAggregate.StartTransaction(command.TransactionDateTime, command.TransactionNumber, transactionType, transactionReference, command.EstateId, command.MerchantId, command.DeviceIdentifier, null); // Logon transaction has no amount + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); Result validationResult = await this.TransactionValidationService.ValidateLogonTransaction(command.EstateId, command.MerchantId, command.DeviceIdentifier, cancellationToken); @@ -113,17 +115,24 @@ public async Task> ProcessLogonTransacti // Record the successful validation // TODO: Generate local authcode - transactionAggregate.AuthoriseTransactionLocally("ABCD1234", ((Int32)validationResult.Data.ResponseCode).ToString().PadLeft(4, '0'), validationResult.Data.ResponseMessage); + stateResult = transactionAggregate.AuthoriseTransactionLocally("ABCD1234", ((Int32)validationResult.Data.ResponseCode).ToString().PadLeft(4, '0'), validationResult.Data.ResponseMessage); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); } else { // Record the failure - transactionAggregate.DeclineTransactionLocally(((Int32)validationResult.Data.ResponseCode).ToString().PadLeft(4, '0'), validationResult.Data.ResponseMessage); + stateResult = transactionAggregate.DeclineTransactionLocally(((Int32)validationResult.Data.ResponseCode).ToString().PadLeft(4, '0'), validationResult.Data.ResponseMessage); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); } - transactionAggregate.CompleteTransaction(); - - transactionAggregate.RecordTransactionTimings(command.TransactionReceivedDateTime, null, null, DateTime.Now); + stateResult = transactionAggregate.CompleteTransaction(); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); + stateResult = transactionAggregate.RecordTransactionTimings(command.TransactionReceivedDateTime, null, null, DateTime.Now); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); Result saveResult = await this.AggregateService.Save(transactionAggregate, cancellationToken); if (saveResult.IsFailed) @@ -231,22 +240,32 @@ public async Task> ProcessSaleTransaction totalCost = transactionAmount.GetValueOrDefault() * unitCost; } - transactionAggregate.StartTransaction(command.TransactionDateTime, command.TransactionNumber, transactionType, transactionReference, command.EstateId, command.MerchantId, command.DeviceIdentifier, transactionAmount); + Result stateResult = transactionAggregate.StartTransaction(command.TransactionDateTime, command.TransactionNumber, transactionType, transactionReference, command.EstateId, command.MerchantId, command.DeviceIdentifier, transactionAmount); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); // Add the product details (unless invalid estate) if (validationResult.Data.ResponseCode != TransactionResponseCode.InvalidEstateId && validationResult.Data.ResponseCode != TransactionResponseCode.InvalidContractIdValue && validationResult.Data.ResponseCode != TransactionResponseCode.InvalidProductIdValue && validationResult.Data.ResponseCode != TransactionResponseCode.ContractNotValidForMerchant && validationResult.Data.ResponseCode != TransactionResponseCode.ProductNotValidForMerchant) { - transactionAggregate.AddProductDetails(command.ContractId, command.ProductId); + stateResult = transactionAggregate.AddProductDetails(command.ContractId, command.ProductId); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); } - transactionAggregate.RecordCostPrice(unitCost, totalCost); + stateResult = transactionAggregate.RecordCostPrice(unitCost, totalCost); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); // Add the transaction source - transactionAggregate.AddTransactionSource(transactionSourceValue); + stateResult = transactionAggregate.AddTransactionSource(transactionSourceValue); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); DateTime? operatorStartDateTime = null; DateTime? operatorEndDateTime = null; if (validationResult.Data.ResponseCode == TransactionResponseCode.Success) { // Record any additional request metadata - transactionAggregate.RecordAdditionalRequestData(command.OperatorId, command.AdditionalTransactionMetadata); + stateResult = transactionAggregate.RecordAdditionalRequestData(command.OperatorId, command.AdditionalTransactionMetadata); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); // Do the online processing with the operator here Result merchantResult = await this.GetMerchant(command.MerchantId, cancellationToken); @@ -272,30 +291,44 @@ public async Task> ProcessSaleTransaction TransactionResponseCode transactionResponseCode = TransactionResponseCode.Success; String responseMessage = "SUCCESS"; - transactionAggregate.AuthoriseTransaction(command.OperatorId, operatorResult.Data.AuthorisationCode, operatorResult.Data.ResponseCode, operatorResult.Data.ResponseMessage, operatorResult.Data.TransactionId, ((Int32)transactionResponseCode).ToString().PadLeft(4, '0'), responseMessage); + stateResult= transactionAggregate.AuthoriseTransaction(command.OperatorId, operatorResult.Data.AuthorisationCode, operatorResult.Data.ResponseCode, operatorResult.Data.ResponseMessage, operatorResult.Data.TransactionId, ((Int32)transactionResponseCode).ToString().PadLeft(4, '0'), responseMessage); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); } else { TransactionResponseCode transactionResponseCode = TransactionResponseCode.TransactionDeclinedByOperator; String responseMessage = "DECLINED BY OPERATOR"; - transactionAggregate.DeclineTransaction(command.OperatorId, operatorResult.Data.ResponseCode, operatorResult.Data.ResponseMessage, ((Int32)transactionResponseCode).ToString().PadLeft(4, '0'), responseMessage); + stateResult = transactionAggregate.DeclineTransaction(command.OperatorId, operatorResult.Data.ResponseCode, operatorResult.Data.ResponseMessage, ((Int32)transactionResponseCode).ToString().PadLeft(4, '0'), responseMessage); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); } // Record any additional operator response metadata - transactionAggregate.RecordAdditionalResponseData(command.OperatorId, operatorResult.Data.AdditionalTransactionResponseMetadata); + stateResult = transactionAggregate.RecordAdditionalResponseData(command.OperatorId, operatorResult.Data.AdditionalTransactionResponseMetadata); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); } else { // Record the failure - transactionAggregate.DeclineTransactionLocally(((Int32)validationResult.Data.ResponseCode).ToString().PadLeft(4, '0'), validationResult.Data.ResponseMessage); + stateResult = transactionAggregate.DeclineTransactionLocally(((Int32)validationResult.Data.ResponseCode).ToString().PadLeft(4, '0'), validationResult.Data.ResponseMessage); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); } - transactionAggregate.RecordTransactionTimings(command.TransactionReceivedDateTime, operatorStartDateTime, operatorEndDateTime, DateTime.Now);; + stateResult = transactionAggregate.RecordTransactionTimings(command.TransactionReceivedDateTime, operatorStartDateTime, operatorEndDateTime, DateTime.Now);; + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); - transactionAggregate.CompleteTransaction(); + stateResult= transactionAggregate.CompleteTransaction(); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); // Determine if the email receipt is required if (String.IsNullOrEmpty(command.CustomerEmailAddress) == false) { - transactionAggregate.RequestEmailReceipt(command.CustomerEmailAddress); + stateResult = transactionAggregate.RequestEmailReceipt(command.CustomerEmailAddress); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); } // Get the model from the aggregate @@ -332,7 +365,9 @@ public async Task ResendTransactionReceipt(TransactionCommands.ResendTra TransactionAggregate transactionAggregate = transactionResult.Data; - transactionAggregate.RequestEmailReceiptResend(); + Result stateResult = transactionAggregate.RequestEmailReceiptResend(); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); Result saveResult = await this.AggregateService.Save(transactionAggregate, cancellationToken); if (saveResult.IsFailed) @@ -399,14 +434,17 @@ public async Task CalculateFeesForTransaction(TransactionCommands.Calcul // Determine when the fee should be applied DateTime settlementDate = CalculateSettlementDate(merchantResult.Data.SettlementSchedule, command.CompletedDateTime); - transactionAggregate.AddFeePendingSettlement(calculatedFee, settlementDate); - - + Result stateResult = transactionAggregate.AddFeePendingSettlement(calculatedFee, settlementDate); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); + if (merchantResult.Data.SettlementSchedule == Models.Merchant.SettlementSchedule.Immediate) { Guid settlementId = Helpers.CalculateSettlementAggregateId(settlementDate, command.MerchantId, command.EstateId); // Add fees to transaction now if settlement is immediate - transactionAggregate.AddSettledFee(calculatedFee, settlementDate, settlementId); + stateResult =transactionAggregate.AddSettledFee(calculatedFee, settlementDate, settlementId); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); } } } @@ -442,7 +480,9 @@ public async Task AddSettledMerchantFee(TransactionCommands.AddSettledMe IsSettled = true }; - transactionAggregate.AddSettledFee(calculatedFee, command.SettledDateTime, command.SettlementId); + Result stateResult = transactionAggregate.AddSettledFee(calculatedFee, command.SettledDateTime, command.SettlementId); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); Result saveResult = await this.AggregateService.Save(transactionAggregate, cancellationToken); if (saveResult.IsFailed) @@ -542,14 +582,18 @@ private async Task> GetTransactionFeesForCalcula return feesForCalculation; } - private async Task AddDeviceToMerchant(Guid merchantId, + private async Task AddDeviceToMerchant(Guid merchantId, String deviceIdentifier, CancellationToken cancellationToken) { // TODO: Should this be firing a command to add the device?? // Add the device to the merchant Result merchantAggregate = await this.AggregateService.GetLatest(merchantId, cancellationToken); - merchantAggregate.Data.AddDevice(Guid.NewGuid(), deviceIdentifier); - await this.AggregateService.Save(merchantAggregate.Data, cancellationToken); + if (merchantAggregate.IsFailed) + return ResultHelpers.CreateFailure(merchantAggregate); + Result stateResult = merchantAggregate.Data.AddDevice(Guid.NewGuid(), deviceIdentifier); + if (stateResult.IsFailed) + return ResultHelpers.CreateFailure(stateResult); + return await this.AggregateService.Save(merchantAggregate.Data, cancellationToken); } [ExcludeFromCodeCoverage]