From 73efe146001f1d38758e4bdf081e8765a07b98b7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 13:00:24 +0000 Subject: [PATCH 1/3] Initial plan From 50d42993eaf4dcb8e0172316d799ea7e27523879 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 13:05:22 +0000 Subject: [PATCH 2/3] refactor: reduce assign operator complexity Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com> --- .../Services/MerchantDomainService.cs | 70 ++++++++++++------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs b/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs index c1af5881..3c555e2e 100644 --- a/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs @@ -124,34 +124,12 @@ public async Task AssignOperatorToMerchant(MerchantCommands.AssignOperat if (result.IsFailed) return ResultHelpers.CreateFailure(result); - // Is the operator valid for this estate - Estate estate = estateAggregate.GetEstate(); - Models.Estate.Operator @operator = estate.Operators?.SingleOrDefault(o => o.OperatorId == command.RequestDto.OperatorId); - if (@operator == null) { - return Result.Invalid($"Operator Id {command.RequestDto.OperatorId} is not supported on Estate [{estate.Name}]"); - } - - Result operatorResult = await DomainServiceHelper.GetAggregateOrFailure(ct => this.AggregateService.GetLatest(command.RequestDto.OperatorId, ct), command.RequestDto.OperatorId, cancellationToken); - if (operatorResult.IsFailed) - return ResultHelpers.CreateFailure(operatorResult); - OperatorAggregate @operatorAggregate = operatorResult.Data; - // Operator has been validated, now check the rules of the operator against the passed in data - if (@operatorAggregate.RequireCustomMerchantNumber) { - // requested addition must have a merchant number supplied - if (String.IsNullOrEmpty(command.RequestDto.MerchantNumber)) { - return Result.Invalid($"Operator Id {command.RequestDto.OperatorId} requires that a merchant number is provided"); - } - } - - if (@operatorAggregate.RequireCustomTerminalNumber) { - // requested addition must have a terminal number supplied - if (String.IsNullOrEmpty(command.RequestDto.TerminalNumber)) { - return Result.Invalid($"Operator Id {command.RequestDto.OperatorId} requires that a terminal number is provided"); - } - } + (Result operatorValidationResult, String operatorName) = await this.GetOperatorAssignmentDetails(command, estateAggregate, cancellationToken); + if (operatorValidationResult.IsFailed) + return operatorValidationResult; // Assign the operator - Result stateResult = merchantAggregate.AssignOperator(command.RequestDto.OperatorId, @operator.Name, command.RequestDto.MerchantNumber, command.RequestDto.TerminalNumber); + Result stateResult = merchantAggregate.AssignOperator(command.RequestDto.OperatorId, operatorName, command.RequestDto.MerchantNumber, command.RequestDto.TerminalNumber); if (stateResult.IsFailed) return stateResult; @@ -166,6 +144,46 @@ public async Task AssignOperatorToMerchant(MerchantCommands.AssignOperat } } + private async Task<(Result Result, String OperatorName)> GetOperatorAssignmentDetails(MerchantCommands.AssignOperatorToMerchantCommand command, + EstateAggregate estateAggregate, + CancellationToken cancellationToken) + { + Estate estate = estateAggregate.GetEstate(); + Models.Estate.Operator @operator = estate.Operators?.SingleOrDefault(o => o.OperatorId == command.RequestDto.OperatorId); + if (@operator == null) { + return (Result.Invalid($"Operator Id {command.RequestDto.OperatorId} is not supported on Estate [{estate.Name}]"), null); + } + + Result operatorResult = await DomainServiceHelper.GetAggregateOrFailure(ct => this.AggregateService.GetLatest(command.RequestDto.OperatorId, ct), command.RequestDto.OperatorId, cancellationToken); + if (operatorResult.IsFailed) + return (ResultHelpers.CreateFailure(operatorResult), null); + + Result validationResult = this.ValidateOperatorAssignment(command.RequestDto.OperatorId, + command.RequestDto.MerchantNumber, + command.RequestDto.TerminalNumber, + operatorResult.Data); + + return validationResult.IsFailed + ? (validationResult, null) + : (Result.Success(), @operator.Name); + } + + private Result ValidateOperatorAssignment(Guid operatorId, + String merchantNumber, + String terminalNumber, + OperatorAggregate operatorAggregate) + { + if (operatorAggregate.RequireCustomMerchantNumber && String.IsNullOrEmpty(merchantNumber)) { + return Result.Invalid($"Operator Id {operatorId} requires that a merchant number is provided"); + } + + if (operatorAggregate.RequireCustomTerminalNumber && String.IsNullOrEmpty(terminalNumber)) { + return Result.Invalid($"Operator Id {operatorId} requires that a terminal number is provided"); + } + + return Result.Success(); + } + private SettlementSchedule ConvertSettlementSchedule(DataTransferObjects.Responses.Merchant.SettlementSchedule settlementSchedule) => settlementSchedule switch { From 2d7a9a89fa18be85cd6b606217ce2decf77a8d2e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Mar 2026 13:09:36 +0000 Subject: [PATCH 3/3] chore: address review feedback on helper contract Co-authored-by: StuartFerguson <16325469+StuartFerguson@users.noreply.github.com> --- .../Services/MerchantDomainService.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs b/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs index 3c555e2e..dc1e63e5 100644 --- a/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs @@ -124,9 +124,9 @@ public async Task AssignOperatorToMerchant(MerchantCommands.AssignOperat if (result.IsFailed) return ResultHelpers.CreateFailure(result); - (Result operatorValidationResult, String operatorName) = await this.GetOperatorAssignmentDetails(command, estateAggregate, cancellationToken); - if (operatorValidationResult.IsFailed) - return operatorValidationResult; + (Result validationResult, String operatorName) = await this.GetOperatorAssignmentDetails(command, estateAggregate, cancellationToken); + if (validationResult.IsFailed) + return validationResult; // Assign the operator Result stateResult = merchantAggregate.AssignOperator(command.RequestDto.OperatorId, operatorName, command.RequestDto.MerchantNumber, command.RequestDto.TerminalNumber); @@ -144,19 +144,19 @@ public async Task AssignOperatorToMerchant(MerchantCommands.AssignOperat } } - private async Task<(Result Result, String OperatorName)> GetOperatorAssignmentDetails(MerchantCommands.AssignOperatorToMerchantCommand command, - EstateAggregate estateAggregate, - CancellationToken cancellationToken) + private async Task<(Result ValidationResult, String OperatorName)> GetOperatorAssignmentDetails(MerchantCommands.AssignOperatorToMerchantCommand command, + EstateAggregate estateAggregate, + CancellationToken cancellationToken) { Estate estate = estateAggregate.GetEstate(); Models.Estate.Operator @operator = estate.Operators?.SingleOrDefault(o => o.OperatorId == command.RequestDto.OperatorId); if (@operator == null) { - return (Result.Invalid($"Operator Id {command.RequestDto.OperatorId} is not supported on Estate [{estate.Name}]"), null); + return (Result.Invalid($"Operator Id {command.RequestDto.OperatorId} is not supported on Estate [{estate.Name}]"), String.Empty); } Result operatorResult = await DomainServiceHelper.GetAggregateOrFailure(ct => this.AggregateService.GetLatest(command.RequestDto.OperatorId, ct), command.RequestDto.OperatorId, cancellationToken); if (operatorResult.IsFailed) - return (ResultHelpers.CreateFailure(operatorResult), null); + return (ResultHelpers.CreateFailure(operatorResult), String.Empty); Result validationResult = this.ValidateOperatorAssignment(command.RequestDto.OperatorId, command.RequestDto.MerchantNumber, @@ -164,7 +164,7 @@ public async Task AssignOperatorToMerchant(MerchantCommands.AssignOperat operatorResult.Data); return validationResult.IsFailed - ? (validationResult, null) + ? (validationResult, String.Empty) : (Result.Success(), @operator.Name); }