diff --git a/TransactionProcessor.Client/ITransactionProcessorClient.cs b/TransactionProcessor.Client/ITransactionProcessorClient.cs index a8311d27..31660d13 100644 --- a/TransactionProcessor.Client/ITransactionProcessorClient.cs +++ b/TransactionProcessor.Client/ITransactionProcessorClient.cs @@ -34,7 +34,8 @@ Task ResendEmailReceipt(String accessToken, Task GetMerchantBalance(String accessToken, Guid estateId, Guid merchantId, - CancellationToken cancellationToken); + CancellationToken cancellationToken, + Boolean liveBalance = true); Task> GetMerchantBalanceHistory(String accessToken, Guid estateId, diff --git a/TransactionProcessor.Client/TransactionProcessorClient.cs b/TransactionProcessor.Client/TransactionProcessorClient.cs index 67e20ad8..d13f4cd1 100644 --- a/TransactionProcessor.Client/TransactionProcessorClient.cs +++ b/TransactionProcessor.Client/TransactionProcessorClient.cs @@ -189,8 +189,16 @@ public async Task ResendEmailReceipt(String accessToken, public async Task GetMerchantBalance(String accessToken, Guid estateId, Guid merchantId, - CancellationToken cancellationToken) { + CancellationToken cancellationToken, + Boolean liveBalance = true){ + + String requestUri = $"{this.BaseAddress}/api/estates/{estateId}/merchants/{merchantId}/balance"; + + if (liveBalance){ + requestUri = $"{this.BaseAddress}/api/estates/{estateId}/merchants/{merchantId}/livebalance"; + } + MerchantBalanceResponse response = null; try { diff --git a/TransactionProcessor/Controllers/MerchantController.cs b/TransactionProcessor/Controllers/MerchantController.cs index f1491e4e..2f6c4e25 100644 --- a/TransactionProcessor/Controllers/MerchantController.cs +++ b/TransactionProcessor/Controllers/MerchantController.cs @@ -10,9 +10,11 @@ using DataTransferObjects; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; using ProjectionEngine.Models; using ProjectionEngine.Repository; using ProjectionEngine.State; +using Shared.EventStore.EventStore; using Shared.Exceptions; using Shared.General; using Swashbuckle.AspNetCore.Annotations; @@ -25,12 +27,16 @@ public class MerchantController : ControllerBase { private readonly IProjectionStateRepository MerchantBalanceStateRepository; + private readonly IEventStoreContext EventStoreContext; + private readonly ITransactionProcessorReadRepository TransactionProcessorReadRepository; public MerchantController(IProjectionStateRepository merchantBalanceStateRepository, - ITransactionProcessorReadRepository transactionProcessorReadRepository) { + ITransactionProcessorReadRepository transactionProcessorReadRepository, + IEventStoreContext eventStoreContext) { this.MerchantBalanceStateRepository = merchantBalanceStateRepository; this.TransactionProcessorReadRepository = transactionProcessorReadRepository; + this.EventStoreContext = eventStoreContext; } #region Others @@ -110,12 +116,74 @@ public async Task GetMerchantBalance([FromRoute] Guid estateId, throw new NotFoundException($"Merchant Balance details not found with estate Id {estateId} and merchant Id {merchantId}"); } - MerchantBalanceResponse response= new MerchantBalanceResponse { - Balance = merchantBalance.Balance, - MerchantId = merchantId, - AvailableBalance = merchantBalance.AvailableBalance, - EstateId = estateId - }; + MerchantBalanceResponse response = new MerchantBalanceResponse + { + Balance = merchantBalance.Balance, + MerchantId = merchantId, + AvailableBalance = merchantBalance.AvailableBalance, + EstateId = estateId + }; + + return this.Ok(response); + } + + [HttpGet] + [Route("{merchantId}/livebalance")] + [SwaggerResponse(200, "OK", typeof(MerchantBalanceResponse))] + public async Task GetMerchantBalanceLive([FromRoute] Guid estateId, + [FromRoute] Guid merchantId, + CancellationToken cancellationToken) + { + String estateRoleName = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("EstateRoleName")) + ? "Estate" + : Environment.GetEnvironmentVariable("EstateRoleName"); + String merchantRoleName = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MerchantRoleName")) + ? "Merchant" + : Environment.GetEnvironmentVariable("MerchantRoleName"); + + if (ClaimsHelper.IsUserRolesValid(this.User, new[] { estateRoleName, merchantRoleName }) == false) + { + return this.Forbid(); + } + + Claim estateIdClaim = null; + Claim merchantIdClaim = null; + + // Determine the users role + if (this.User.IsInRole(estateRoleName)) + { + // Estate user + // Get the Estate Id claim from the user + estateIdClaim = ClaimsHelper.GetUserClaim(this.User, "EstateId"); + } + + if (this.User.IsInRole(merchantRoleName)) + { + // Get the merchant Id claim from the user + estateIdClaim = ClaimsHelper.GetUserClaim(this.User, "EstateId"); + merchantIdClaim = ClaimsHelper.GetUserClaim(this.User, "MerchantId"); + } + + if (ClaimsHelper.ValidateRouteParameter(estateId, estateIdClaim) == false) + { + return this.Forbid(); + } + + if (ClaimsHelper.ValidateRouteParameter(merchantId, merchantIdClaim) == false) + { + return this.Forbid(); + } + + String state = await this.EventStoreContext.GetPartitionStateFromProjection("MerchantBalanceProjection", $"MerchantBalance-{merchantId:N}", cancellationToken); + MerchantBalanceProjectionState1 projectionState = JsonConvert.DeserializeObject(state); + + MerchantBalanceResponse response = new MerchantBalanceResponse + { + Balance = projectionState.merchant.balance, + MerchantId = merchantId, + AvailableBalance = projectionState.merchant.balance, + EstateId = estateId + }; return this.Ok(response); }