From ed32c21998a5c1aee80831f1636bebf1312964cc Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Fri, 8 Aug 2025 12:00:33 +0100 Subject: [PATCH 1/5] Updated GET methods to read the balance aggregate --- .../TransactionProcessorManagerTests.cs | 18 ++++++++++++++++++ .../Mediator/DummyEstateManagementManager.cs | 6 ++++++ .../Manager/ITransactionProcessorManager.cs | 4 ++++ .../Manager/TransactionProcessorManager.cs | 15 +++++++++++++-- .../RequestHandlers/MerchantRequestHandler.cs | 18 +++++++++--------- .../Requests/MerchantQueries.cs | 2 +- TransactionProcessor.Testing/TestData.cs | 2 +- .../Bootstrapper/MediatorRegistry.cs | 2 +- .../Controllers/MerchantController.cs | 15 ++++----------- 9 files changed, 57 insertions(+), 25 deletions(-) diff --git a/TransactionProcessor.BusinessLogic.Tests/Manager/TransactionProcessorManagerTests.cs b/TransactionProcessor.BusinessLogic.Tests/Manager/TransactionProcessorManagerTests.cs index 04a896fa..215b361e 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Manager/TransactionProcessorManagerTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Manager/TransactionProcessorManagerTests.cs @@ -479,5 +479,23 @@ public async Task TransactionProcessorManager_GetMerchants_RepoCallFails_Excepti Result> getMerchantsResult = await this.TransactionProcessorManager.GetMerchants(TestData.EstateId, CancellationToken.None); getMerchantsResult.IsFailed.ShouldBeTrue(); } + + [Fact] + public async Task TransactionProcessorManager_GetMerchantLiveBalance_ResultSuccess() + { + this.AggregateService.Setup(a => a.GetLatest(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.Aggregates.MerchantBalanceAggregateWithCredit())); + + Result getLiveMerchantBalanceResult = await this.TransactionProcessorManager.GetMerchantLiveBalance(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + getLiveMerchantBalanceResult.IsSuccess.ShouldBeTrue(); + } + + [Fact] + public async Task TransactionProcessorManager_GetMerchantLiveBalance_GetFailed_ResultFailed() + { + this.AggregateService.Setup(a => a.GetLatest(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); + + Result getLiveMerchantBalanceResult = await this.TransactionProcessorManager.GetMerchantLiveBalance(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + getLiveMerchantBalanceResult.IsFailed.ShouldBeTrue(); + } } } diff --git a/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyEstateManagementManager.cs b/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyEstateManagementManager.cs index 1a8eb60f..8168c2dd 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyEstateManagementManager.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Mediator/DummyEstateManagementManager.cs @@ -12,6 +12,12 @@ namespace TransactionProcessor.BusinessLogic.Tests.Mediator; public class DummyTransactionProcessorManager : ITransactionProcessorManager { + public async Task> GetMerchantLiveBalance(Guid estateId, + Guid merchantId, + CancellationToken cancellationToken) { + return Result.Success(1000.00m); // Dummy balance + } + public async Task>> GetMerchantContracts(Guid estateId, Guid merchantId, CancellationToken cancellationToken) { diff --git a/TransactionProcessor.BusinessLogic/Manager/ITransactionProcessorManager.cs b/TransactionProcessor.BusinessLogic/Manager/ITransactionProcessorManager.cs index f3557d44..dee5e211 100644 --- a/TransactionProcessor.BusinessLogic/Manager/ITransactionProcessorManager.cs +++ b/TransactionProcessor.BusinessLogic/Manager/ITransactionProcessorManager.cs @@ -14,6 +14,10 @@ public interface ITransactionProcessorManager { #region Methods + Task> GetMerchantLiveBalance(Guid estateId, + Guid merchantId, + CancellationToken cancellationToken); + Task>> GetMerchantContracts(Guid estateId, Guid merchantId, CancellationToken cancellationToken); diff --git a/TransactionProcessor.BusinessLogic/Manager/TransactionProcessorManager.cs b/TransactionProcessor.BusinessLogic/Manager/TransactionProcessorManager.cs index 3a9b97ae..1c8c7b5c 100644 --- a/TransactionProcessor.BusinessLogic/Manager/TransactionProcessorManager.cs +++ b/TransactionProcessor.BusinessLogic/Manager/TransactionProcessorManager.cs @@ -147,9 +147,20 @@ public async Task> GetMerchant(Guid estateId, return Result.Success(merchantModel); } + public async Task> GetMerchantLiveBalance(Guid estateId, + Guid merchantId, + CancellationToken cancellationToken) { + Result getMerchantBalanceResult = await this.AggregateService.GetLatest(merchantId, cancellationToken); + if (getMerchantBalanceResult.IsFailed) + return ResultHelpers.CreateFailure(getMerchantBalanceResult); + + MerchantBalanceAggregate aggregate = getMerchantBalanceResult.Data; + return aggregate.Balance; + } + public async Task>> GetMerchantContracts(Guid estateId, - Guid merchantId, - CancellationToken cancellationToken) + Guid merchantId, + CancellationToken cancellationToken) { Result> getMerchantContractsResult = await this.TransactionProcessorReadModelRepository.GetMerchantContracts(estateId, merchantId, cancellationToken); if (getMerchantContractsResult.IsFailed) diff --git a/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs b/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs index 7ad79f5c..ea66b41c 100644 --- a/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs +++ b/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs @@ -19,7 +19,7 @@ namespace TransactionProcessor.BusinessLogic.RequestHandlers; public class MerchantRequestHandler : IRequestHandler>, - IRequestHandler>, + IRequestHandler>, IRequestHandler>>, IRequestHandler, IRequestHandler, @@ -64,17 +64,17 @@ public async Task> Handle(MerchantQueries.GetMercha return await this.MerchantBalanceStateRepository.Load(query.EstateId, query.MerchantId, cancellationToken); } - public async Task> Handle(MerchantQueries.GetMerchantLiveBalanceQuery query, + public async Task> Handle(MerchantQueries.GetMerchantLiveBalanceQuery query, CancellationToken cancellationToken) { + return await this.TransactionProcessorManager.GetMerchantLiveBalance(query.EstateId, query.MerchantId, cancellationToken); + //Result result = await this.EventStoreContext.GetPartitionStateFromProjection("MerchantBalanceProjection", $"MerchantBalance-{query.MerchantId:N}", cancellationToken); + //if (result.IsFailed) + // return Result.NotFound( + // $"Merchant Balance not found for Merchant {query.MerchantId} on MerchantBalanceProjection"); - Result result = await this.EventStoreContext.GetPartitionStateFromProjection("MerchantBalanceProjection", $"MerchantBalance-{query.MerchantId:N}", cancellationToken); - if (result.IsFailed) - return Result.NotFound( - $"Merchant Balance not found for Merchant {query.MerchantId} on MerchantBalanceProjection"); - - MerchantBalanceProjectionState1 projectionState = JsonConvert.DeserializeObject(result.Data); + //MerchantBalanceProjectionState1 projectionState = JsonConvert.DeserializeObject(result.Data); - return Result.Success(projectionState); + //return Result.Success(projectionState); } public async Task>> Handle(MerchantQueries.GetMerchantBalanceHistoryQuery query, diff --git a/TransactionProcessor.BusinessLogic/Requests/MerchantQueries.cs b/TransactionProcessor.BusinessLogic/Requests/MerchantQueries.cs index cca79389..96f19eff 100644 --- a/TransactionProcessor.BusinessLogic/Requests/MerchantQueries.cs +++ b/TransactionProcessor.BusinessLogic/Requests/MerchantQueries.cs @@ -12,7 +12,7 @@ namespace TransactionProcessor.BusinessLogic.Requests; public record MerchantQueries { public record GetMerchantBalanceQuery(Guid EstateId, Guid MerchantId) : IRequest>; - public record GetMerchantLiveBalanceQuery(Guid MerchantId) : IRequest>; + public record GetMerchantLiveBalanceQuery(Guid EstateId, Guid MerchantId) : IRequest>; public record GetMerchantBalanceHistoryQuery(Guid EstateId, Guid MerchantId, DateTime StartDate, DateTime EndDate) : IRequest>>; diff --git a/TransactionProcessor.Testing/TestData.cs b/TransactionProcessor.Testing/TestData.cs index 88b0f42f..97b7cd4e 100644 --- a/TransactionProcessor.Testing/TestData.cs +++ b/TransactionProcessor.Testing/TestData.cs @@ -2264,7 +2264,7 @@ public static class Queries { public static MerchantQueries.GetMerchantBalanceQuery GetMerchantBalanceQuery => new(EstateId, MerchantId); - public static MerchantQueries.GetMerchantLiveBalanceQuery GetMerchantLiveBalanceQuery => new(MerchantId); + public static MerchantQueries.GetMerchantLiveBalanceQuery GetMerchantLiveBalanceQuery => new(EstateId, MerchantId); public static MerchantQueries.GetMerchantBalanceHistoryQuery GetMerchantBalanceHistoryQuery => new MerchantQueries.GetMerchantBalanceHistoryQuery(EstateId, MerchantId, DateTime.MinValue, DateTime.MaxValue); diff --git a/TransactionProcessor/Bootstrapper/MediatorRegistry.cs b/TransactionProcessor/Bootstrapper/MediatorRegistry.cs index e42cf2f3..2ccfc55d 100644 --- a/TransactionProcessor/Bootstrapper/MediatorRegistry.cs +++ b/TransactionProcessor/Bootstrapper/MediatorRegistry.cs @@ -81,7 +81,7 @@ private void RegisterMerchantRequestHandler() { this.AddSingleton>>, MerchantRequestHandler>(); this.AddSingleton>>, MerchantRequestHandler>(); this.AddSingleton>>, MerchantRequestHandler>(); - this.AddSingleton>, MerchantRequestHandler>(); + this.AddSingleton>, MerchantRequestHandler>(); this.AddSingleton>, MerchantRequestHandler>(); this.AddSingleton>>, MerchantRequestHandler>(); } diff --git a/TransactionProcessor/Controllers/MerchantController.cs b/TransactionProcessor/Controllers/MerchantController.cs index a8f30396..3cc13e5f 100644 --- a/TransactionProcessor/Controllers/MerchantController.cs +++ b/TransactionProcessor/Controllers/MerchantController.cs @@ -161,22 +161,15 @@ public async Task GetMerchantBalanceLive([FromRoute] Guid estateI return this.Forbid(); } - MerchantQueries.GetMerchantLiveBalanceQuery query = new MerchantQueries.GetMerchantLiveBalanceQuery(merchantId); + MerchantQueries.GetMerchantLiveBalanceQuery query = new MerchantQueries.GetMerchantLiveBalanceQuery(estateId, merchantId); - Result getLiveMerchantBalanceResult = await this.Mediator.Send(query, cancellationToken); + Result getLiveMerchantBalanceResult = await this.Mediator.Send(query, cancellationToken); - if (getLiveMerchantBalanceResult.IsFailed) - { + if (getLiveMerchantBalanceResult.IsFailed) { return getLiveMerchantBalanceResult.ToActionResultX(); } - Result result = Result.Success(new MerchantBalanceResponse - { - Balance = getLiveMerchantBalanceResult.Data.merchant.balance, - MerchantId = merchantId, - AvailableBalance = getLiveMerchantBalanceResult.Data.merchant.balance, - EstateId = estateId - }); + Result result = Result.Success(new MerchantBalanceResponse { Balance = getLiveMerchantBalanceResult.Data, MerchantId = merchantId, AvailableBalance = getLiveMerchantBalanceResult.Data, EstateId = estateId }); return result.ToActionResultX(); } From 3e7d19a5c34c1560eb10554915436008a6700d96 Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Fri, 8 Aug 2025 12:45:45 +0100 Subject: [PATCH 2/5] :| --- .../RequestHandlers/MerchantRequestHandler.cs | 8 ------- .../TransactionProcessorSteps.cs | 24 +++++++++---------- .../Common/DockerHelper.cs | 9 ++++--- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs b/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs index ea66b41c..f8c28a39 100644 --- a/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs +++ b/TransactionProcessor.BusinessLogic/RequestHandlers/MerchantRequestHandler.cs @@ -67,14 +67,6 @@ public async Task> Handle(MerchantQueries.GetMercha public async Task> Handle(MerchantQueries.GetMerchantLiveBalanceQuery query, CancellationToken cancellationToken) { return await this.TransactionProcessorManager.GetMerchantLiveBalance(query.EstateId, query.MerchantId, cancellationToken); - //Result result = await this.EventStoreContext.GetPartitionStateFromProjection("MerchantBalanceProjection", $"MerchantBalance-{query.MerchantId:N}", cancellationToken); - //if (result.IsFailed) - // return Result.NotFound( - // $"Merchant Balance not found for Merchant {query.MerchantId} on MerchantBalanceProjection"); - - //MerchantBalanceProjectionState1 projectionState = JsonConvert.DeserializeObject(result.Data); - - //return Result.Success(projectionState); } public async Task>> Handle(MerchantQueries.GetMerchantBalanceHistoryQuery query, diff --git a/TransactionProcessor.IntegrationTesting.Helpers/TransactionProcessorSteps.cs b/TransactionProcessor.IntegrationTesting.Helpers/TransactionProcessorSteps.cs index a0bd6e3e..f3af4fbb 100644 --- a/TransactionProcessor.IntegrationTesting.Helpers/TransactionProcessorSteps.cs +++ b/TransactionProcessor.IntegrationTesting.Helpers/TransactionProcessorSteps.cs @@ -279,21 +279,21 @@ await Retry.For(async () => { MerchantResponse merchant = getMerchantResult.Data; responses.Add(merchant); - string projectionName = "MerchantBalanceProjection"; - String partitionId = $"MerchantBalance-{m.Item2:N}"; + //string projectionName = "MerchantBalanceProjection"; + //String partitionId = $"MerchantBalance-{m.Item2:N}"; - dynamic gg = await this.ProjectionManagementClient.GetStateAsync( - projectionName, partitionId); - JsonElement x = (JsonElement)gg; + //dynamic gg = await this.ProjectionManagementClient.GetStateAsync( + // projectionName, partitionId); + //JsonElement x = (JsonElement)gg; - Result? getMerchantBalanceResult = await this.TransactionProcessorClient.GetMerchantBalance(accessToken, m.Item1, m.Item2, CancellationToken.None); - getMerchantBalanceResult.IsSuccess.ShouldBeTrue(); - getMerchantBalanceResult.Data.ShouldNotBeNull(); + //Result? getMerchantBalanceResult = await this.TransactionProcessorClient.GetMerchantBalance(accessToken, m.Item1, m.Item2, CancellationToken.None); + //getMerchantBalanceResult.IsSuccess.ShouldBeTrue(); + //getMerchantBalanceResult.Data.ShouldNotBeNull(); - // Force a read model database hit - Result? getMerchantBalanceResult2 = await this.TransactionProcessorClient.GetMerchantBalance(accessToken, m.Item1, m.Item2, CancellationToken.None, liveBalance: false); - getMerchantBalanceResult2.IsSuccess.ShouldBeTrue(); - getMerchantBalanceResult2.Data.ShouldNotBeNull(); + //// Force a read model database hit + //Result? getMerchantBalanceResult2 = await this.TransactionProcessorClient.GetMerchantBalance(accessToken, m.Item1, m.Item2, CancellationToken.None, liveBalance: false); + //getMerchantBalanceResult2.IsSuccess.ShouldBeTrue(); + //getMerchantBalanceResult2.Data.ShouldNotBeNull(); }); } diff --git a/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs b/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs index 06b4f15c..40e236a7 100644 --- a/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs +++ b/TransactionProcessor.IntegrationTests/Common/DockerHelper.cs @@ -224,11 +224,10 @@ protected override List GetRequiredProjections() { List requiredProjections = new List(); - requiredProjections.Add("CallbackHandlerEnricher.js"); - requiredProjections.Add("EstateAggregator.js"); - requiredProjections.Add("MerchantAggregator.js"); - requiredProjections.Add("MerchantBalanceCalculator.js"); - requiredProjections.Add("MerchantBalanceProjection.js"); + //requiredProjections.Add("EstateAggregator.js"); + //requiredProjections.Add("MerchantAggregator.js"); + //requiredProjections.Add("MerchantBalanceCalculator.js"); + //requiredProjections.Add("MerchantBalanceProjection.js"); return requiredProjections; } From 99df2330890a706b12b57dc1a623965e11ca65c4 Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Fri, 8 Aug 2025 13:52:50 +0100 Subject: [PATCH 3/5] change to balance checking --- .../Services/MerchantDomainService.cs | 25 ++++++++++--------- .../Shared/SharedSteps.cs | 14 +++++------ 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs b/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs index ffee1934..a20d3f43 100644 --- a/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs @@ -398,20 +398,21 @@ public async Task MakeMerchantWithdrawal(MerchantCommands.MakeMerchantWi { return Result.Invalid($"Merchant [{command.MerchantId}] has not made any deposits yet"); } + + // TODO:Convert to use the new MerchantBalanceAggregate + //// Now we need to check the merchants balance to ensure they have funds to withdraw + //Result getBalanceResult = await this.EventStoreContext.GetPartitionStateFromProjection("MerchantBalanceProjection", $"MerchantBalance-{command.MerchantId:N}", cancellationToken); + //if (getBalanceResult.IsFailed) + //{ + // Result.Invalid($"Failed to get Merchant Balance."); + //} - // Now we need to check the merchants balance to ensure they have funds to withdraw - Result getBalanceResult = await this.EventStoreContext.GetPartitionStateFromProjection("MerchantBalanceProjection", $"MerchantBalance-{command.MerchantId:N}", cancellationToken); - if (getBalanceResult.IsFailed) - { - Result.Invalid($"Failed to get Merchant Balance."); - } - - MerchantBalanceProjectionState1 projectionState = JsonConvert.DeserializeObject(getBalanceResult.Data); + //MerchantBalanceProjectionState1 projectionState = JsonConvert.DeserializeObject(getBalanceResult.Data); - if (command.RequestDto.Amount > projectionState.merchant.balance) - { - return Result.Invalid($"Not enough credit available for withdrawal of [{command.RequestDto.Amount}]. Balance is {projectionState.merchant.balance}"); - } + //if (command.RequestDto.Amount > projectionState.merchant.balance) + //{ + // return Result.Invalid($"Not enough credit available for withdrawal of [{command.RequestDto.Amount}]. Balance is {projectionState.merchant.balance}"); + //} // If we are here we have enough credit to withdraw PositiveMoney amount = PositiveMoney.Create(Money.Create(command.RequestDto.Amount)); diff --git a/TransactionProcessor.IntegrationTests/Shared/SharedSteps.cs b/TransactionProcessor.IntegrationTests/Shared/SharedSteps.cs index 527d66b7..a5f115dd 100644 --- a/TransactionProcessor.IntegrationTests/Shared/SharedSteps.cs +++ b/TransactionProcessor.IntegrationTests/Shared/SharedSteps.cs @@ -251,12 +251,12 @@ public async Task WhenIMakeTheFollowingManualMerchantDeposits(DataTable table) foreach ((EstateDetails, Guid, MakeMerchantDepositRequest) request in requests) { - Decimal previousMerchantBalance = await this.GetMerchantBalance(request.Item2); + Decimal previousMerchantBalance = await this.GetMerchantBalance(request.Item1.EstateId, request.Item2); await this.TransactionProcessorSteps.GivenIMakeTheFollowingManualMerchantDeposits(this.TestingContext.AccessToken, request); await Retry.For(async () => { - Decimal currentMerchantBalance = await this.GetMerchantBalance(request.Item2); + Decimal currentMerchantBalance = await this.GetMerchantBalance(request.Item1.EstateId, request.Item2); currentMerchantBalance.ShouldBe(previousMerchantBalance + request.Item3.Amount); @@ -374,12 +374,12 @@ public async Task WhenIAddTheFollowingContractsToTheFollowingMerchants(DataTable await this.TransactionProcessorSteps.WhenIAddTheFollowingContractsToTheFollowingMerchants(this.TestingContext.AccessToken, requests); } - private async Task GetMerchantBalance(Guid merchantId) + private async Task GetMerchantBalance(Guid estateId, Guid merchantId) { - JsonElement jsonElement = (JsonElement)await this.TestingContext.DockerHelper.ProjectionManagementClient.GetStateAsync("MerchantBalanceProjection", $"MerchantBalance-{merchantId:N}"); - JObject jsonObject = JObject.Parse(jsonElement.GetRawText()); - decimal balanceValue = jsonObject.SelectToken("merchant.balance").Value(); - return balanceValue; + Result result = await this.TestingContext.DockerHelper.TransactionProcessorClient.GetMerchantBalance(this.TestingContext.AccessToken, estateId, merchantId, CancellationToken.None, liveBalance: true); + if (result.IsFailed) + throw new Exception($"Error gettin merchant balance for merchant id {merchantId}"); + return result.Data.Balance; } From 5927a6d6c194761b34bb879f83e7f4307681623d Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Fri, 8 Aug 2025 14:05:22 +0100 Subject: [PATCH 4/5] unit test fixes --- .../Services/MerchantDomainServiceTests.cs | 4 +++- .../Services/MerchantDomainService.cs | 22 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/TransactionProcessor.BusinessLogic.Tests/Services/MerchantDomainServiceTests.cs b/TransactionProcessor.BusinessLogic.Tests/Services/MerchantDomainServiceTests.cs index 238324e3..bbc1152d 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Services/MerchantDomainServiceTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Services/MerchantDomainServiceTests.cs @@ -607,7 +607,9 @@ public async Task MerchantDomainService_MakeMerchantWithdrawal_WithdrawalIsMade( .Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(TestData.TokenResponse())); - this.EventStoreContext.Setup(e => e.GetPartitionStateFromProjection(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(JsonConvert.SerializeObject(TestData.MerchantBalanceProjectionState))); + this.AggregateService + .Setup(m => m.GetLatest(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.Aggregates.MerchantBalanceAggregateWithCredit())); var result = await this.DomainService.MakeMerchantWithdrawal(TestData.Commands.MakeMerchantWithdrawalCommand, CancellationToken.None); result.IsSuccess.ShouldBeTrue(); diff --git a/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs b/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs index a20d3f43..9fdf1fe1 100644 --- a/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/MerchantDomainService.cs @@ -399,20 +399,18 @@ public async Task MakeMerchantWithdrawal(MerchantCommands.MakeMerchantWi return Result.Invalid($"Merchant [{command.MerchantId}] has not made any deposits yet"); } - // TODO:Convert to use the new MerchantBalanceAggregate - //// Now we need to check the merchants balance to ensure they have funds to withdraw - //Result getBalanceResult = await this.EventStoreContext.GetPartitionStateFromProjection("MerchantBalanceProjection", $"MerchantBalance-{command.MerchantId:N}", cancellationToken); - //if (getBalanceResult.IsFailed) - //{ - // Result.Invalid($"Failed to get Merchant Balance."); - //} + Result getMerchantBalanceResult = await this.AggregateService.GetLatest(command.MerchantId, cancellationToken); + Result merchantBalanceAggregateResult = + DomainServiceHelper.HandleGetAggregateResult(getMerchantBalanceResult, command.MerchantId, false); + if (merchantBalanceAggregateResult.IsFailed) + return ResultHelpers.CreateFailure(merchantBalanceAggregateResult); - //MerchantBalanceProjectionState1 projectionState = JsonConvert.DeserializeObject(getBalanceResult.Data); + MerchantBalanceAggregate merchantBalanceAggregate = merchantBalanceAggregateResult.Data; - //if (command.RequestDto.Amount > projectionState.merchant.balance) - //{ - // return Result.Invalid($"Not enough credit available for withdrawal of [{command.RequestDto.Amount}]. Balance is {projectionState.merchant.balance}"); - //} + if (command.RequestDto.Amount > merchantBalanceAggregate.Balance) + { + return Result.Invalid($"Not enough credit available for withdrawal of [{command.RequestDto.Amount}]. Balance is {merchantBalanceAggregate.Balance}"); + } // If we are here we have enough credit to withdraw PositiveMoney amount = PositiveMoney.Create(Money.Create(command.RequestDto.Amount)); From fafe035531735a8e04277fda25c3c655694a22fa Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Fri, 8 Aug 2025 17:57:06 +0100 Subject: [PATCH 5/5] fix integration tests --- .../Manager/TransactionProcessorManager.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TransactionProcessor.BusinessLogic/Manager/TransactionProcessorManager.cs b/TransactionProcessor.BusinessLogic/Manager/TransactionProcessorManager.cs index 1c8c7b5c..3a87b343 100644 --- a/TransactionProcessor.BusinessLogic/Manager/TransactionProcessorManager.cs +++ b/TransactionProcessor.BusinessLogic/Manager/TransactionProcessorManager.cs @@ -151,11 +151,15 @@ public async Task> GetMerchantLiveBalance(Guid estateId, Guid merchantId, CancellationToken cancellationToken) { Result getMerchantBalanceResult = await this.AggregateService.GetLatest(merchantId, cancellationToken); + + if (getMerchantBalanceResult.Status == ResultStatus.NotFound) + return Result.Success(0.0m); + if (getMerchantBalanceResult.IsFailed) return ResultHelpers.CreateFailure(getMerchantBalanceResult); MerchantBalanceAggregate aggregate = getMerchantBalanceResult.Data; - return aggregate.Balance; + return Result.Success(aggregate.Balance); } public async Task>> GetMerchantContracts(Guid estateId,