From dc6e4610370021d25da3d33969dc4cefa3c085ac Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Sat, 31 Jan 2026 20:57:58 +0000 Subject: [PATCH] Allow re-adding previously removed operators to merchants Updated operator assignment logic to only prevent adding operators that are not marked as deleted, enabling reactivation of removed operators. Modified event handling to undelete existing operators instead of creating duplicates. Added a unit test to verify correct behavior when removing and re-adding an operator. --- .../MerchantAggregateTests.cs | 28 +++++++++++++++++++ .../MerchantAggregate.cs | 16 +++++++---- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/TransactionProcessor.Aggregates.Tests/MerchantAggregateTests.cs b/TransactionProcessor.Aggregates.Tests/MerchantAggregateTests.cs index cfb62416..f203951b 100644 --- a/TransactionProcessor.Aggregates.Tests/MerchantAggregateTests.cs +++ b/TransactionProcessor.Aggregates.Tests/MerchantAggregateTests.cs @@ -790,5 +790,33 @@ public void MerchantAggregate_RemoveContract_MerchantDoesNotHaveContract_ErrorTh result.IsFailed.ShouldBeTrue(); result.Status.ShouldBe(ResultStatus.Invalid); } + + [Fact] + public void MerchantAggregate_RemoveOperator_And_ReAdd_OperatorIsReAdded() + { + MerchantAggregate aggregate = MerchantAggregate.Create(TestData.MerchantId); + aggregate.Create(TestData.EstateId, TestData.MerchantName, TestData.DateMerchantCreated, TestData.AddressModel, TestData.ContactModel, + TestData.SettlementScheduleModel); + aggregate.AssignOperator(TestData.OperatorId, TestData.OperatorName, TestData.OperatorMerchantNumber, TestData.OperatorTerminalNumber); + + Result result = aggregate.RemoveOperator(TestData.OperatorId); + result.IsSuccess.ShouldBeTrue(); + + Merchant merchantModel = aggregate.GetMerchant(); + merchantModel.Operators.ShouldHaveSingleItem(); + Operator operatorModel = merchantModel.Operators.Single(); + operatorModel.OperatorId.ShouldBe(TestData.OperatorId); + operatorModel.Name.ShouldBe(TestData.OperatorName); + operatorModel.MerchantNumber.ShouldBe(TestData.OperatorMerchantNumber); + operatorModel.TerminalNumber.ShouldBe(TestData.OperatorTerminalNumber); + operatorModel.IsDeleted.ShouldBeTrue(); + + result = aggregate.AssignOperator(TestData.OperatorId, TestData.OperatorName, TestData.OperatorMerchantNumber, TestData.OperatorTerminalNumber); + result.IsSuccess.ShouldBeTrue(); + merchantModel = aggregate.GetMerchant(); + merchantModel.Operators.ShouldHaveSingleItem(); + operatorModel = merchantModel.Operators.Single(); + operatorModel.IsDeleted.ShouldBeFalse(); + } } } diff --git a/TransactionProcessor.Aggregates/MerchantAggregate.cs b/TransactionProcessor.Aggregates/MerchantAggregate.cs index 0764cdd0..a4c0b48b 100644 --- a/TransactionProcessor.Aggregates/MerchantAggregate.cs +++ b/TransactionProcessor.Aggregates/MerchantAggregate.cs @@ -603,7 +603,7 @@ private static Result EnsureMerchantHasSpaceForDevice(this MerchantAggregate agg private static Result EnsureOperatorHasNotAlreadyBeenAssigned(this MerchantAggregate aggregate, Guid operatorId) { - if (aggregate.Operators.Any(o => o.Key == operatorId)) { + if (aggregate.Operators.Any(o => o.Key == operatorId && o.Value.IsDeleted == false)) { return Result.Invalid($"Operator {operatorId} has already been assigned to merchant"); } @@ -785,13 +785,19 @@ public static void PlayEvent(this MerchantAggregate aggregate, MerchantDomainEve aggregate.Contacts.Add(contactAddedEvent.ContactId, contact); } - public static void PlayEvent(this MerchantAggregate aggregate, MerchantDomainEvents.OperatorAssignedToMerchantEvent operatorAssignedToMerchantEvent) - { - Operator @operator = new Operator(operatorAssignedToMerchantEvent.OperatorId, operatorAssignedToMerchantEvent.Name, + public static void PlayEvent(this MerchantAggregate aggregate, MerchantDomainEvents.OperatorAssignedToMerchantEvent operatorAssignedToMerchantEvent) { + var @operator = aggregate.Operators.SingleOrDefault(o => o.Key == operatorAssignedToMerchantEvent.OperatorId); + + if (@operator.Value != null) { + aggregate.Operators[operatorAssignedToMerchantEvent.OperatorId] = @operator.Value with { IsDeleted = false }; + return; + } + + Operator newOperator = new Operator(operatorAssignedToMerchantEvent.OperatorId, operatorAssignedToMerchantEvent.Name, operatorAssignedToMerchantEvent.MerchantNumber, operatorAssignedToMerchantEvent.TerminalNumber); - aggregate.Operators.Add(operatorAssignedToMerchantEvent.OperatorId, @operator); + aggregate.Operators.Add(operatorAssignedToMerchantEvent.OperatorId, newOperator); } public static void PlayEvent(this MerchantAggregate aggregate, MerchantDomainEvents.OperatorRemovedFromMerchantEvent operatorRemovedFromMerchantEvent){