From 232f646c2e76f9e1c801e5fd89e01732246613ed Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Tue, 7 Apr 2026 18:29:13 +0100 Subject: [PATCH] Refactor BuildStatement with improved validation and flow Refactored the BuildStatement method to enhance structure, readability, and error handling. Introduced helper methods GetStatementAggregate and GetValidMerchant to encapsulate aggregate retrieval and validation logic. The new implementation ensures merchants exist and have addresses before building statements, and uses early returns for failure cases. The previous implementation was commented out and replaced with this improved version. --- .../MerchantStatementDomainService.cs | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/TransactionProcessor.BusinessLogic/Services/MerchantStatementDomainService.cs b/TransactionProcessor.BusinessLogic/Services/MerchantStatementDomainService.cs index 62d81baf..1055cc6d 100644 --- a/TransactionProcessor.BusinessLogic/Services/MerchantStatementDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/MerchantStatementDomainService.cs @@ -258,7 +258,7 @@ static String EncodeTo64(String toEncode) return returnValue; } - public async Task BuildStatement(MerchantStatementCommands.BuildMerchantStatementCommand command, + /*public async Task BuildStatement(MerchantStatementCommands.BuildMerchantStatementCommand command, CancellationToken cancellationToken) { try { // Work out the next statement date @@ -300,6 +300,69 @@ public async Task BuildStatement(MerchantStatementCommands.BuildMerchant catch (Exception ex) { return Result.Failure(ex.GetExceptionMessages()); } + }*/ + + public async Task BuildStatement(MerchantStatementCommands.BuildMerchantStatementCommand command, + CancellationToken cancellationToken) + { + try + { + Result statementAggregate = await GetStatementAggregate(command, cancellationToken); + if (statementAggregate.IsFailed) return ResultHelpers.CreateFailure(statementAggregate); + + Result merchant = await GetValidMerchant(statementAggregate.Data, cancellationToken); + if (merchant.IsFailed) return ResultHelpers.CreateFailure(merchant); + + Result htmlResult = await this.StatementBuilder.GetStatementHtml(statementAggregate.Data, merchant.Data, cancellationToken); + if (htmlResult.IsFailed) return ResultHelpers.CreateFailure(htmlResult); + + String base64 = EncodeTo64(htmlResult.Data); + + Result buildResult = statementAggregate.Data.BuildStatement(DateTime.Now, base64); + if (buildResult.IsFailed) return buildResult; + + Result saveResult = await this.AggregateService.Save(statementAggregate.Data, cancellationToken); + if (saveResult.IsFailed) return saveResult; + + return Result.Success(); + } + catch (Exception ex) + { + return Result.Failure(ex.GetExceptionMessages()); + } + } + + private async Task> GetStatementAggregate(MerchantStatementCommands.BuildMerchantStatementCommand command, + CancellationToken ct) + { + return await DomainServiceHelper.GetAggregateOrFailure( + c => this.AggregateService.GetLatest(command.MerchantStatementId, c), + command.MerchantStatementId, + ct); + } + + private async Task> GetValidMerchant(MerchantStatementAggregate statementAggregate, + CancellationToken ct) + { + MerchantStatement statement = statementAggregate.GetStatement(); + + Result merchantResult = await DomainServiceHelper.GetAggregateOrFailure( + c => this.AggregateService.Get(statement.MerchantId, c), + statement.MerchantId, + ct); + + if (merchantResult.IsFailed) + return ResultHelpers.CreateFailure(merchantResult); + + if (!merchantResult.Data.IsCreated) + return Result.Invalid("Merchant must be created to build a statement"); + + Merchant merchant = merchantResult.Data.GetMerchant(); + + if (!merchant.Addresses.Any()) + return Result.Invalid("Merchant must have an address to build a statement"); + + return Result.Success(merchant); } public async Task RecordActivityDateOnMerchantStatement(MerchantStatementCommands.RecordActivityDateOnMerchantStatementCommand command,