diff --git a/TransactionProcessor.BusinessLogic.Tests/Services/TransactionDomainServiceTests.cs b/TransactionProcessor.BusinessLogic.Tests/Services/TransactionDomainServiceTests.cs index 88401cfa..4136b689 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Services/TransactionDomainServiceTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Services/TransactionDomainServiceTests.cs @@ -1027,4 +1027,4 @@ public async Task TransactionDomainService_ResendCustomerEmailReceipt_GetTokenFa #endregion } -} \ No newline at end of file +} diff --git a/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs b/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs index e2e00078..36a97da4 100644 --- a/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/TransactionDomainService.cs @@ -252,42 +252,9 @@ public async Task CalculateFeesForTransaction(TransactionCommands.Calcul return ResultHelpers.CreateFailure(feesForCalculationResult); List resultFees = this.FeeCalculationManager.CalculateFees(feesForCalculationResult.Data, transactionAggregate.TransactionAmount.Value, command.CompletedDateTime); - - IEnumerable nonMerchantFees = resultFees.Where(f => f.FeeType == TransactionProcessor.Models.Contract.FeeType.ServiceProvider); - foreach (CalculatedFee calculatedFee in nonMerchantFees) { - // Add Fee to the Transaction - transactionAggregate.AddFee(calculatedFee); - } - - // Now deal with merchant fees - List merchantFees = resultFees.Where(f => f.FeeType == TransactionProcessor.Models.Contract.FeeType.Merchant).ToList(); - - if (merchantFees.Any()) { - Result merchantResult = await this.GetMerchant(command.MerchantId, cancellationToken); - if (merchantResult.IsFailed) - return ResultHelpers.CreateFailure(merchantResult); - if (merchantResult.Data.SettlementSchedule == Models.Merchant.SettlementSchedule.NotSet) { - return Result.Failure($"Merchant {merchantResult.Data.MerchantId} does not have a settlement schedule configured"); - } - - foreach (CalculatedFee calculatedFee in merchantFees) { - // Determine when the fee should be applied - DateTime settlementDate = TransactionHelpers.CalculateSettlementDate(merchantResult.Data.SettlementSchedule, command.CompletedDateTime); - - 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 - stateResult =transactionAggregate.AddSettledFee(calculatedFee, settlementDate, settlementId); - if (stateResult.IsFailed) - return ResultHelpers.CreateFailure(stateResult); - } - } - } + Result applyFeesResult = await this.ApplyCalculatedFees(transactionAggregate, resultFees, command, cancellationToken); + if (applyFeesResult.IsFailed) + return applyFeesResult; Result saveResult = await this.AggregateService.Save(transactionAggregate, cancellationToken); if (saveResult.IsFailed) @@ -386,7 +353,7 @@ public async Task ResendCustomerEmailReceipt(TransactionCommands.ResendC } private async Task>> GetTransactionFeesForCalculation(TransactionAggregate transactionAggregate, - CancellationToken cancellationToken) { + CancellationToken cancellationToken) { // Get the fees to be calculated Result> feesForProduct = await this.GetTransactionFeesForProduct(transactionAggregate.ContractId, transactionAggregate.ProductId, cancellationToken); @@ -408,9 +375,71 @@ private async Task>> GetTransactionFeesFo return Result.Success(feesForCalculation); } + private async Task ApplyCalculatedFees(TransactionAggregate transactionAggregate, + List calculatedFees, + TransactionCommands.CalculateFeesForTransactionCommand command, + CancellationToken cancellationToken) { + this.ApplyNonMerchantFees(transactionAggregate, calculatedFees.Where(f => f.FeeType == TransactionProcessor.Models.Contract.FeeType.ServiceProvider)); + + List merchantFees = calculatedFees.Where(f => f.FeeType == TransactionProcessor.Models.Contract.FeeType.Merchant).ToList(); + if (merchantFees.Any() == false) + return Result.Success(); + + Result merchantResult = await this.GetMerchant(command.MerchantId, cancellationToken); + if (merchantResult.IsFailed) + return ResultHelpers.CreateFailure(merchantResult); + + if (merchantResult.Data.SettlementSchedule == Models.Merchant.SettlementSchedule.NotSet) + return Result.Failure($"Merchant {merchantResult.Data.MerchantId} does not have a settlement schedule configured"); + + return this.ApplyMerchantFees(transactionAggregate, merchantResult.Data, merchantFees, command.CompletedDateTime, command.MerchantId, command.EstateId); + } + + private void ApplyNonMerchantFees(TransactionAggregate transactionAggregate, + IEnumerable calculatedFees) { + foreach (CalculatedFee calculatedFee in calculatedFees) { + transactionAggregate.AddFee(calculatedFee); + } + } + + private Result ApplyMerchantFees(TransactionAggregate transactionAggregate, + Merchant merchant, + IEnumerable calculatedFees, + DateTime completedDateTime, + Guid merchantId, + Guid estateId) { + foreach (CalculatedFee calculatedFee in calculatedFees) { + Result applyMerchantFeeResult = this.ApplyMerchantFee(transactionAggregate, merchant, calculatedFee, completedDateTime, merchantId, estateId); + if (applyMerchantFeeResult.IsFailed) + return ResultHelpers.CreateFailure(applyMerchantFeeResult); + } + + return Result.Success(); + } + + private Result ApplyMerchantFee(TransactionAggregate transactionAggregate, + Merchant merchant, + CalculatedFee calculatedFee, + DateTime completedDateTime, + Guid merchantId, + Guid estateId) { + DateTime settlementDate = TransactionHelpers.CalculateSettlementDate(merchant.SettlementSchedule, completedDateTime); + + Result stateResult = transactionAggregate.AddFeePendingSettlement(calculatedFee, settlementDate); + if (stateResult.IsFailed) + return stateResult; + + if (merchant.SettlementSchedule != Models.Merchant.SettlementSchedule.Immediate) + return Result.Success(); + + Guid settlementId = Helpers.CalculateSettlementAggregateId(settlementDate, merchantId, estateId); + + return transactionAggregate.AddSettledFee(calculatedFee, settlementDate, settlementId); + } + private async Task AddDeviceToMerchant(Guid merchantId, - String deviceIdentifier, - CancellationToken cancellationToken) { + String deviceIdentifier, + CancellationToken cancellationToken) { // Add the device to the merchant Result merchantAggregate = await this.AggregateService.GetLatest(merchantId, cancellationToken); if (merchantAggregate.IsFailed) @@ -688,4 +717,4 @@ private Result StartTransaction(TransactionAggregate transactionAggregate, return (start, end); } } -} \ No newline at end of file +}