diff --git a/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs b/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs index 4f85a7f..6879c52 100644 --- a/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs +++ b/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs @@ -598,15 +598,15 @@ public async Task TransactionProcessorACLApplicationService_GetMerchantSchedule_ [Fact] public async Task TransactionProcessorACLApplicationService_GetMerchantDailyPerformanceSummary_ReturnedFromEstateReportingClient() { - MerchantDailyPerformanceSummaryRequest capturedRequest = null; + TransactionProcessorACL.BusinessLogic.BackendAPI.DataTransferObjects.MerchantDailyPerformanceSummaryRequest capturedRequest = null; estateReportingApiClient - .Setup(v => v.GetMerchantDailyPerformanceSummary(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Callback((_, _, request, _) => capturedRequest = request) - .ReturnsAsync(Result.Success(new MerchantDailyPerformanceSummaryResponse + .Setup(v => v.GetMerchantDailyPerformanceSummary(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Callback((_, _, request, _) => capturedRequest = request) + .ReturnsAsync(Result.Success(new TransactionProcessorACL.BusinessLogic.BackendAPI.DataTransferObjects.MerchantDailyPerformanceSummaryResponse { Metrics = [ - new MetricItem + new TransactionProcessorACL.BusinessLogic.BackendAPI.DataTransferObjects.MetricItem { Title = "Total Sales Count", Value = 6, @@ -655,24 +655,24 @@ public async Task TransactionProcessorACLApplicationService_GetMerchantDailyPerf [Fact] public async Task TransactionProcessorACLApplicationService_GetMerchantTransactionMixSummary_ReturnedFromEstateReportingClient() { - MerchantTransactionMixSummaryRequest capturedRequest = null; + TransactionProcessorACL.BusinessLogic.BackendAPI.DataTransferObjects.TransactionMixSummaryRequest capturedRequest = null; estateReportingApiClient - .Setup(v => v.GetMerchantTransactionMixSummary(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Callback((_, _, request, _) => capturedRequest = request) - .ReturnsAsync(Result.Success(new MerchantTransactionMixSummaryResponse + .Setup(v => v.GetMerchantTransactionMixSummary(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Callback((_, _, request, _) => capturedRequest = request) + .ReturnsAsync(Result.Success(new TransactionProcessorACL.BusinessLogic.BackendAPI.DataTransferObjects.TransactionMixSummaryResponse { FromDate = new DateTime(2026, 7, 1), ToDate = new DateTime(2026, 7, 3), - Breakdown = TransactionProcessorACL.Models.TransactionMixBreakdown.Product, - Measure = TransactionProcessorACL.Models.TransactionMixMeasure.Count, - Items = + Breakdown = TransactionProcessorACL.BusinessLogic.BackendAPI.DataTransferObjects.TransactionMixBreakdown.Product, + Measure = TransactionProcessorACL.BusinessLogic.BackendAPI.DataTransferObjects.TransactionMixMeasure.Count, + Groups = [ - new TransactionMixSummaryItem + new TransactionProcessorACL.BusinessLogic.BackendAPI.DataTransferObjects.TransactionMixSummaryGroup() { - Key = "product-1", - Label = "Product 1", - Count = 6, - Value = 42.75M + GroupKey = "product-1", + GroupName = "Product 1", + TransactionCount = 6, + TransactionValue = 42.75M } ] })); @@ -696,7 +696,7 @@ public async Task TransactionProcessorACLApplicationService_GetMerchantTransacti result.Data.Items.Count.ShouldBe(1); capturedRequest.ShouldNotBeNull(); capturedRequest.MerchantReportingId.ShouldBe(12345); - capturedRequest.Breakdown.ShouldBe(RequestTransactionMixBreakdown.Product); + //capturedRequest.Breakdown.ShouldBe(RequestTransactionMixBreakdown.Product); } } } diff --git a/TransactionProcessorACL.BusinessLogic/BackendAPI/DataTransferObjects/Class1.cs b/TransactionProcessorACL.BusinessLogic/BackendAPI/DataTransferObjects/Class1.cs new file mode 100644 index 0000000..f49f6a0 --- /dev/null +++ b/TransactionProcessorACL.BusinessLogic/BackendAPI/DataTransferObjects/Class1.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; + +namespace TransactionProcessorACL.BusinessLogic.BackendAPI.DataTransferObjects +{ + public class TransactionMixSummaryResponse + { + public DateTime FromDate { get; set; } + public DateTime ToDate { get; set; } + public TransactionMixBreakdown Breakdown { get; set; } + public TransactionMixMeasure Measure { get; set; } + public int TotalCount { get; set; } + public decimal TotalValue { get; set; } + public List Groups { get; set; } = []; + public List Transactions { get; set; } = []; + } + + public class TransactionMixSummaryGroup + { + public string? GroupKey { get; set; } + public string? GroupName { get; set; } + public int TransactionCount { get; set; } + public decimal TransactionValue { get; set; } + } + + public class TransactionMixSummaryTransaction + { + public Guid Id { get; set; } + public DateTime DateTime { get; set; } + public string? Merchant { get; set; } + public Guid MerchantId { get; set; } + public int MerchantReportingId { get; set; } + public string? Operator { get; set; } + public Guid OperatorId { get; set; } + public int OperatorReportingId { get; set; } + public string? Product { get; set; } + public Guid ProductId { get; set; } + public int ProductReportingId { get; set; } + public string? Type { get; set; } + public string? Status { get; set; } + public decimal Value { get; set; } + public decimal TotalFees { get; set; } + public string? SettlementReference { get; set; } + public int TransactionNumber { get; set; } + } + + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum TransactionMixBreakdown + { + Product, + TransactionType, + Operator, + Status + } + + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum TransactionMixMeasure + { + Count, + Value + } + + public class TransactionMixSummaryRequest + { + public int? MerchantReportingId { get; set; } + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + public TransactionMixBreakdown Breakdown { get; set; } + public TransactionMixMeasure Measure { get; set; } + public int TopN { get; set; } = 5; + } + + public class MerchantDailyPerformanceSummaryRequest + { + public Int32 MerchantReportingId { get; set; } + public DateTime StartDate { get; set; } + public DateTime EndDate { get; set; } + } + + public sealed class MerchantDailyPerformanceSummaryResponse + { + public List Metrics { get; set; } = []; + + public List DrillDownTransactions { get; set; } = []; + } + + public sealed class MetricItem + { + public string Title { get; set; } + + public Decimal Value { get; set; } + + public string Description { get; set; } + + public int Category { get; set; } + } + + public sealed class DrillDownTransaction + { + public string Reference { get; set; } + + public string Product { get; set; } + + public string Status { get; set; } + + public Decimal Amount { get; set; } + + public DateTime TransactionDateTime { get; set; } + } +} diff --git a/TransactionProcessorACL.BusinessLogic/BackendAPI/EstateReportingApiClient.cs b/TransactionProcessorACL.BusinessLogic/BackendAPI/EstateReportingApiClient.cs index 5c96e19..9d0b286 100644 --- a/TransactionProcessorACL.BusinessLogic/BackendAPI/EstateReportingApiClient.cs +++ b/TransactionProcessorACL.BusinessLogic/BackendAPI/EstateReportingApiClient.cs @@ -3,12 +3,9 @@ using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using ClientProxyBase; -using Shared.General; using Shared.Results; using SimpleResults; -using TransactionProcessorACL.DataTransferObjects.Requests; -using TransactionProcessorACL.Models; +using TransactionProcessorACL.BusinessLogic.BackendAPI.DataTransferObjects; namespace TransactionProcessorACL.BusinessLogic.BackendAPI; @@ -54,10 +51,10 @@ public async Task> GetMerchantDa } } - public async Task> GetMerchantTransactionMixSummary(String accessToken, - Guid estateId, - MerchantTransactionMixSummaryRequest request, - CancellationToken cancellationToken) + public async Task> GetMerchantTransactionMixSummary(String accessToken, + Guid estateId, + TransactionMixSummaryRequest request, + CancellationToken cancellationToken) { string requestUri = this.BuildRequestUrl("/api/transactions/transactionmixsummary"); @@ -68,8 +65,8 @@ public async Task> GetMerchantTran (EstateIdHeaderName, estateId.ToString()) ]; - Result result = - await this.Post(requestUri, request, accessToken, additionalHeaders, cancellationToken); + Result result = + await this.Post(requestUri, request, accessToken, additionalHeaders, cancellationToken); if (result.IsFailed) return ResultHelpers.CreateFailure(result); diff --git a/TransactionProcessorACL.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs b/TransactionProcessorACL.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs index 9b1bc59..8cdca7f 100644 --- a/TransactionProcessorACL.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs +++ b/TransactionProcessorACL.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs @@ -2,8 +2,8 @@ using System.Threading; using System.Threading.Tasks; using SimpleResults; -using TransactionProcessorACL.DataTransferObjects.Requests; -using TransactionProcessorACL.Models; +using TransactionProcessorACL.BusinessLogic.BackendAPI.DataTransferObjects; + namespace TransactionProcessorACL.BusinessLogic.BackendAPI; @@ -14,8 +14,8 @@ Task> GetMerchantDailyPerformanc MerchantDailyPerformanceSummaryRequest request, CancellationToken cancellationToken); - Task> GetMerchantTransactionMixSummary(String accessToken, - Guid estateId, - MerchantTransactionMixSummaryRequest request, - CancellationToken cancellationToken); + Task> GetMerchantTransactionMixSummary(String accessToken, + Guid estateId, + TransactionMixSummaryRequest request, + CancellationToken cancellationToken); } diff --git a/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs b/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs index a301ad9..2274bd0 100644 --- a/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs +++ b/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs @@ -1,7 +1,9 @@ -using SecurityService.DataTransferObjects; +using System.Linq; +using SecurityService.DataTransferObjects; using Shared.Exceptions; using Shared.Results; using SimpleResults; +using TransactionProcessor.DataTransferObjects.Requests.Merchant; using TransactionProcessor.DataTransferObjects.Responses.Contract; namespace TransactionProcessorACL.BusinessLogic.Services @@ -375,8 +377,26 @@ public async Task> GetMerchantDa return ResultHelpers.CreateFailure(accessTokenResult); } + BackendAPI.DataTransferObjects.MerchantDailyPerformanceSummaryRequest apiRequest = new BackendAPI.DataTransferObjects.MerchantDailyPerformanceSummaryRequest { StartDate = request.StartDate, EndDate = request.EndDate, MerchantReportingId = request.MerchantReportingId }; + TokenResponse accessToken = accessTokenResult.Data; - return await this.EstateReportingApiClient.GetMerchantDailyPerformanceSummary(accessToken.AccessToken, estateId, request, cancellationToken); + Result apiResponse = await this.EstateReportingApiClient.GetMerchantDailyPerformanceSummary(accessToken.AccessToken, estateId, apiRequest, cancellationToken); + + if (apiResponse.IsFailed) + return ResultHelpers.CreateFailure(apiResponse); + + MerchantDailyPerformanceSummaryResponse response = new MerchantDailyPerformanceSummaryResponse { + Metrics = apiResponse.Data.Metrics.Select(m => new MetricItem { Category = m.Category, Description = m.Description, Title = m.Title, Value = m.Value }).ToList(), + DrillDownTransactions = apiResponse.Data.DrillDownTransactions.Select(d => new DrillDownTransaction { + Amount = d.Amount, + Product = d.Product, + Reference = d.Reference, + Status = d.Status, + TransactionDateTime = d.TransactionDateTime + }).ToList() + }; + + return response; } public async Task> GetMerchantTransactionMixSummary(Guid estateId, @@ -388,8 +408,42 @@ public async Task> GetMerchantTran return ResultHelpers.CreateFailure(accessTokenResult); } + var apiRequest = new BackendAPI.DataTransferObjects.TransactionMixSummaryRequest { + StartDate = request.StartDate, + EndDate = request.EndDate, + Breakdown = Enum.Parse(request.Breakdown.ToString()), + Measure = Enum.Parse(request.Measure.ToString()), + MerchantReportingId = request.MerchantReportingId, + TopN = request.TopN + }; + TokenResponse accessToken = accessTokenResult.Data; - return await this.EstateReportingApiClient.GetMerchantTransactionMixSummary(accessToken.AccessToken, estateId, request, cancellationToken); + var apiResponse = await this.EstateReportingApiClient.GetMerchantTransactionMixSummary(accessToken.AccessToken, estateId, apiRequest, cancellationToken); + + if (apiResponse.IsFailed) + return ResultHelpers.CreateFailure(apiResponse); + + MerchantTransactionMixSummaryResponse response = new MerchantTransactionMixSummaryResponse() { + Breakdown = Enum.Parse(apiResponse.Data.Breakdown.ToString()), + Measure = Enum.Parse(apiResponse.Data.Measure.ToString()), + FromDate = apiResponse.Data.FromDate, + ToDate = apiResponse.Data.ToDate, + TotalCount = apiResponse.Data.TotalCount, + TotalValue = apiResponse.Data.TotalValue, + Items = apiResponse.Data.Groups.Select(g => new TransactionMixSummaryItem { Value = g.TransactionValue, Count = g.TransactionCount, Key = g.GroupKey, Label = g.GroupName }).ToList(), + DrillDownTransactions = apiResponse.Data.Transactions.Select(t => new TransactionMixDrillDownTransaction { + Amount = t.Value, + Operator = t.Operator, + Product = t.Product, + Reference = t.SettlementReference, + Status = t.Status, + TransactionDateTime = t.DateTime, + TransactionType = t.Type + }).ToList() + + }; + + return response; } private static ProcessReconciliationResponse CreateProcessReconciliationResponse(ReconciliationResponse reconciliationResponse) diff --git a/TransactionProcessorACL.DataTransferObjects/Requests/MerchantDailyPerformanceSummaryRequest.cs b/TransactionProcessorACL.DataTransferObjects/Requests/MerchantDailyPerformanceSummaryRequest.cs index 9f3cbbf..95df5a0 100644 --- a/TransactionProcessorACL.DataTransferObjects/Requests/MerchantDailyPerformanceSummaryRequest.cs +++ b/TransactionProcessorACL.DataTransferObjects/Requests/MerchantDailyPerformanceSummaryRequest.cs @@ -11,4 +11,5 @@ public class MerchantDailyPerformanceSummaryRequest public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } + public String ApplicationVersion { get; set; } } diff --git a/TransactionProcessorACL.DataTransferObjects/Requests/MerchantTransactionMixSummaryRequest.cs b/TransactionProcessorACL.DataTransferObjects/Requests/MerchantTransactionMixSummaryRequest.cs index c94ca56..467a2e0 100644 --- a/TransactionProcessorACL.DataTransferObjects/Requests/MerchantTransactionMixSummaryRequest.cs +++ b/TransactionProcessorACL.DataTransferObjects/Requests/MerchantTransactionMixSummaryRequest.cs @@ -15,6 +15,7 @@ public class MerchantTransactionMixSummaryRequest public TransactionMixBreakdown Breakdown { get; set; } public TransactionMixMeasure Measure { get; set; } + public String ApplicationVersion { get; set; } public int TopN { get; set; } = 5; } diff --git a/TransactionProcessorACL.IntegrationTests/Common/GenericSteps.cs b/TransactionProcessorACL.IntegrationTests/Common/GenericSteps.cs index 729a3d5..3a264b1 100644 --- a/TransactionProcessorACL.IntegrationTests/Common/GenericSteps.cs +++ b/TransactionProcessorACL.IntegrationTests/Common/GenericSteps.cs @@ -59,6 +59,8 @@ public async Task StartSystem() this.TestingContext.DockerHelper.SqlServerContainerName = "sharedsqlserver"; this.TestingContext.DockerHelper.SetImageDetails(ContainerType.TransactionProcessorAcl, ("transactionprocessoracl", false)); + this.TestingContext.DockerHelper.SetImageDetails(ContainerType.EstateReporting + , ("stuartferguson/estatereportingapi:master", true)); this.TestingContext.Logger = logger; this.TestingContext.Logger.LogInformation("About to Start Containers for Scenario Run"); diff --git a/TransactionProcessorACL.IntegrationTests/Reporting/Reporting.feature b/TransactionProcessorACL.IntegrationTests/Reporting/Reporting.feature index 2c6c852..edf8c64 100644 --- a/TransactionProcessorACL.IntegrationTests/Reporting/Reporting.feature +++ b/TransactionProcessorACL.IntegrationTests/Reporting/Reporting.feature @@ -119,7 +119,6 @@ Scenario: Merchant daily performance summary Then the merchant daily performance summary response should contain at least one metric and the sale amount 50.00 @PRTest -@ignore Scenario: Merchant transaction mix summary Given I am logged in as "merchantuser@testmerchant1.co.uk" with password "123456" for Merchant "Test Merchant 1" for Estate "Test Estate 1" with client "merchantClient" When I perform the following transactions diff --git a/TransactionProcessorACL.IntegrationTests/Shared/ACLSteps.cs b/TransactionProcessorACL.IntegrationTests/Shared/ACLSteps.cs index 84e4524..5a72b25 100644 --- a/TransactionProcessorACL.IntegrationTests/Shared/ACLSteps.cs +++ b/TransactionProcessorACL.IntegrationTests/Shared/ACLSteps.cs @@ -1,6 +1,7 @@ using Shared.Serialisation; using SimpleResults; using TransactionProcessor.IntegrationTesting.Helpers; +using TransactionProcessorACL.DataTransferObjects.Requests; namespace TransactionProcessorACL.IntegrationTests.Shared; @@ -247,12 +248,12 @@ public async Task WhenIGetTheMerchantDailyPerformanceSummaryForMerchantForEstate this.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", userAccessToken); - Object request = new + MerchantDailyPerformanceSummaryRequest request = new() { - application_version = "1.0.5", - merchant_reporting_id = merchantReportingId, - start_date = DateTime.Today, - end_date = DateTime.Today, + EndDate = DateTime.Today, + StartDate = DateTime.Today, + ApplicationVersion = "1.0.5", + MerchantReportingId = merchantReportingId }; @@ -303,15 +304,15 @@ public async Task WhenIGetTheMerchantTransactionMixSummaryForMerchantForEstate(S this.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", userAccessToken); - Object request = new + MerchantTransactionMixSummaryRequest request= new() { - application_version = "1.0.5", - merchant_reporting_id = merchantReportingId, - start_date = DateTime.Today, - end_date = DateTime.Today, - breakdown = 2, - measure = 1, - top_n = 5, + ApplicationVersion = "1.0.5", + MerchantReportingId = merchantReportingId, + StartDate = DateTime.Today, + EndDate = DateTime.Today, + Breakdown = TransactionMixBreakdown.Product, + Measure = TransactionMixMeasure.Count, + TopN = 5, }; StringContent content = new StringContent(StringSerialiser.Serialise(request), Encoding.UTF8, "application/json");