Skip to content

Commit 1f802bc

Browse files
Add reporting endpoint
1 parent 746eeb3 commit 1f802bc

19 files changed

Lines changed: 356 additions & 4 deletions

File tree

TransactionProcessorACL.BusinessLogic.Tests/MediatorTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace TransactionProcessorACL.BusinessLogic.Tests
1818
{
1919
using System.Threading;
2020
using Microsoft.Extensions.DependencyInjection;
21+
using TransactionProcessorACL.DataTransferObjects.Requests;
2122
using Models;
2223
using Services;
2324

@@ -160,5 +161,12 @@ public async Task<Result<MerchantScheduleResponse>> GetMerchantSchedule(Guid est
160161
CancellationToken cancellationToken) {
161162
return Result.Success(new MerchantScheduleResponse());
162163
}
164+
165+
public async Task<Result<MerchantDailyPerformanceSummaryResponse>> GetMerchantDailyPerformanceSummary(Guid estateId,
166+
MerchantDailyPerformanceSummaryRequest request,
167+
CancellationToken cancellationToken)
168+
{
169+
return Result.Success(new MerchantDailyPerformanceSummaryResponse());
170+
}
163171
}
164172
}

TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace TransactionProcessorACL.BusinesssLogic.Tests
66
using System.Threading;
77
using System.Threading.Tasks;
88
using BusinessLogic.Services;
9+
using TransactionProcessorACL.BusinessLogic.BackendAPI;
910
using Microsoft.Extensions.Configuration;
1011
using Models;
1112
using Moq;
@@ -14,6 +15,7 @@ namespace TransactionProcessorACL.BusinesssLogic.Tests
1415
using Shared.Logger;
1516
using Shouldly;
1617
using Testing;
18+
using TransactionProcessorACL.DataTransferObjects.Requests;
1719
using TransactionProcessor.Client;
1820
using TransactionProcessor.DataTransferObjects;
1921
using Xunit;
@@ -30,8 +32,9 @@ public TransactionProcessorACLApplicationServiceTests()
3032

3133
transactionProcessorClient = new Mock<ITransactionProcessorClient>();
3234
securityServiceClient = new Mock<ISecurityServiceClient>();
35+
estateReportingApiClient = new Mock<IEstateReportingApiClient>();
3336
applicationService =
34-
new TransactionProcessorACLApplicationService(transactionProcessorClient.Object, securityServiceClient.Object);
37+
new TransactionProcessorACLApplicationService(transactionProcessorClient.Object, securityServiceClient.Object, estateReportingApiClient.Object);
3538
}
3639

3740
private void SetupMemoryConfiguration()
@@ -47,6 +50,8 @@ private void SetupMemoryConfiguration()
4750

4851
private Mock<ISecurityServiceClient> securityServiceClient;
4952

53+
private Mock<IEstateReportingApiClient> estateReportingApiClient;
54+
5055
private ITransactionProcessorACLApplicationService applicationService;
5156
[Fact]
5257
public async Task TransactionProcessorACLApplicationService_ProcessLogonTransaction_TransactionIsSuccessful()
@@ -587,5 +592,62 @@ public async Task TransactionProcessorACLApplicationService_GetMerchantSchedule_
587592
var merchantScheduleResponse = await applicationService.GetMerchantSchedule(TestData.EstateId, TestData.MerchantId, TestData.ScheduleYear, CancellationToken.None);
588593
merchantScheduleResponse.IsFailed.ShouldBeTrue();
589594
}
595+
596+
[Fact]
597+
public async Task TransactionProcessorACLApplicationService_GetMerchantDailyPerformanceSummary_ReturnedFromEstateReportingClient()
598+
{
599+
MerchantDailyPerformanceSummaryRequest capturedRequest = null;
600+
estateReportingApiClient
601+
.Setup(v => v.GetMerchantDailyPerformanceSummary(It.IsAny<String>(), It.IsAny<Guid>(), It.IsAny<MerchantDailyPerformanceSummaryRequest>(), It.IsAny<CancellationToken>()))
602+
.Callback<String, Guid, MerchantDailyPerformanceSummaryRequest, CancellationToken>((_, _, request, _) => capturedRequest = request)
603+
.ReturnsAsync(Result.Success(new MerchantDailyPerformanceSummaryResponse
604+
{
605+
Metrics =
606+
[
607+
new MetricItem
608+
{
609+
Title = "Total Sales Count",
610+
Value = 6,
611+
Description = "All sales transactions in the range",
612+
Category = 0
613+
}
614+
]
615+
}));
616+
securityServiceClient.Setup(s => s.GetToken(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<CancellationToken>())).ReturnsAsync(Result.Success(TestData.TokenResponse));
617+
618+
Result<MerchantDailyPerformanceSummaryResponse> result = await applicationService.GetMerchantDailyPerformanceSummary(
619+
TestData.EstateId,
620+
new MerchantDailyPerformanceSummaryRequest
621+
{
622+
MerchantReportingId = 12345,
623+
StartDate = new DateTime(2026, 7, 1),
624+
EndDate = new DateTime(2026, 7, 1)
625+
},
626+
CancellationToken.None);
627+
628+
result.IsSuccess.ShouldBeTrue();
629+
result.Data.ShouldNotBeNull();
630+
result.Data.Metrics.Count.ShouldBe(1);
631+
capturedRequest.ShouldNotBeNull();
632+
capturedRequest.MerchantReportingId.ShouldBe(12345);
633+
}
634+
635+
[Fact]
636+
public async Task TransactionProcessorACLApplicationService_GetMerchantDailyPerformanceSummary_GetTokenFailed_ResultIsFailed()
637+
{
638+
securityServiceClient.Setup(s => s.GetToken(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<CancellationToken>())).ReturnsAsync(Result.Failure());
639+
640+
Result<MerchantDailyPerformanceSummaryResponse> result = await applicationService.GetMerchantDailyPerformanceSummary(
641+
TestData.EstateId,
642+
new MerchantDailyPerformanceSummaryRequest
643+
{
644+
MerchantReportingId = 12345,
645+
StartDate = new DateTime(2026, 7, 1),
646+
EndDate = new DateTime(2026, 7, 1)
647+
},
648+
CancellationToken.None);
649+
650+
result.IsFailed.ShouldBeTrue();
651+
}
590652
}
591653
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Net.Http;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using ClientProxyBase;
7+
using Shared.General;
8+
using Shared.Results;
9+
using SimpleResults;
10+
using TransactionProcessorACL.DataTransferObjects.Requests;
11+
using TransactionProcessorACL.Models;
12+
13+
namespace TransactionProcessorACL.BusinessLogic.BackendAPI;
14+
15+
public class EstateReportingApiClient : ClientProxyBase.ClientProxyBase, IEstateReportingApiClient
16+
{
17+
private readonly Func<string, string> BaseAddressResolver;
18+
private const string EstateIdHeaderName = "EstateId";
19+
20+
public EstateReportingApiClient(Func<string, string> baseAddressResolver,
21+
HttpClient httpClient,
22+
Func<object, string> serialise,
23+
Func<string, Type, object> deserialise) : base(httpClient, serialise, deserialise)
24+
{
25+
this.BaseAddressResolver = baseAddressResolver;
26+
}
27+
28+
public async Task<Result<MerchantDailyPerformanceSummaryResponse>> GetMerchantDailyPerformanceSummary(String accessToken,
29+
Guid estateId,
30+
MerchantDailyPerformanceSummaryRequest request,
31+
CancellationToken cancellationToken)
32+
{
33+
string requestUri = this.BuildRequestUrl("/api/transactions/merchantdailyperformancesummary");
34+
35+
try
36+
{
37+
List<(string headerName, string headerValue)> additionalHeaders =
38+
[
39+
(EstateIdHeaderName, estateId.ToString())
40+
];
41+
42+
Result<MerchantDailyPerformanceSummaryResponse> result =
43+
await this.Post<MerchantDailyPerformanceSummaryRequest, MerchantDailyPerformanceSummaryResponse>(requestUri, request, accessToken, additionalHeaders, cancellationToken);
44+
45+
if (result.IsFailed)
46+
return ResultHelpers.CreateFailure(result);
47+
48+
return result;
49+
}
50+
catch (Exception ex)
51+
{
52+
Exception exception = new($"Error getting merchant daily performance summary for estate {estateId}.", ex);
53+
return Result.Failure(exception.Message);
54+
}
55+
}
56+
57+
private string BuildRequestUrl(string relativePath)
58+
{
59+
string baseAddress = this.BaseAddressResolver("EstateReportingApi");
60+
return $"{baseAddress.TrimEnd('/')}{relativePath}";
61+
}
62+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
using SimpleResults;
5+
using TransactionProcessorACL.DataTransferObjects.Requests;
6+
using TransactionProcessorACL.Models;
7+
8+
namespace TransactionProcessorACL.BusinessLogic.BackendAPI;
9+
10+
public interface IEstateReportingApiClient
11+
{
12+
Task<Result<MerchantDailyPerformanceSummaryResponse>> GetMerchantDailyPerformanceSummary(String accessToken,
13+
Guid estateId,
14+
MerchantDailyPerformanceSummaryRequest request,
15+
CancellationToken cancellationToken);
16+
}

TransactionProcessorACL.BusinessLogic/Services/ITransactionProcessorACLApplicationService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace TransactionProcessorACL.BusinessLogic.Services
88
using System.Threading;
99
using System.Threading.Tasks;
1010
using Shared.General;
11+
using TransactionProcessorACL.DataTransferObjects.Requests;
1112
using TransactionProcessor.DataTransferObjects;
1213
using TransactionProcessorACL.Models;
1314
using GetVoucherResponse = Models.GetVoucherResponse;
@@ -60,5 +61,9 @@ Task<Result<MerchantScheduleResponse>> GetMerchantSchedule(Guid estateId,
6061
Guid merchantId,
6162
Int32 year,
6263
CancellationToken cancellationToken);
64+
65+
Task<Result<MerchantDailyPerformanceSummaryResponse>> GetMerchantDailyPerformanceSummary(Guid estateId,
66+
MerchantDailyPerformanceSummaryRequest request,
67+
CancellationToken cancellationToken);
6368
}
6469
}

TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ namespace TransactionProcessorACL.BusinessLogic.Services
1111
using System.Net.Http;
1212
using System.Threading;
1313
using System.Threading.Tasks;
14+
using TransactionProcessorACL.BusinessLogic.BackendAPI;
15+
using TransactionProcessorACL.DataTransferObjects.Requests;
1416
using Models;
1517
using SecurityService.Client;
1618
using Shared.General;
@@ -38,6 +40,11 @@ public class TransactionProcessorACLApplicationService : ITransactionProcessorAC
3840
/// </summary>
3941
private readonly ITransactionProcessorClient TransactionProcessorClient;
4042

43+
/// <summary>
44+
/// The estate reporting client
45+
/// </summary>
46+
private readonly IEstateReportingApiClient? EstateReportingApiClient;
47+
4148
#endregion
4249

4350
#region Constructors
@@ -48,10 +55,12 @@ public class TransactionProcessorACLApplicationService : ITransactionProcessorAC
4855
/// <param name="transactionProcessorClient">The transaction processor client.</param>
4956
/// <param name="securityServiceClient">The security service client.</param>
5057
public TransactionProcessorACLApplicationService(ITransactionProcessorClient transactionProcessorClient,
51-
ISecurityServiceClient securityServiceClient)
58+
ISecurityServiceClient securityServiceClient,
59+
IEstateReportingApiClient? estateReportingApiClient = null)
5260
{
5361
this.TransactionProcessorClient = transactionProcessorClient;
5462
this.SecurityServiceClient = securityServiceClient;
63+
this.EstateReportingApiClient = estateReportingApiClient;
5564
}
5665

5766
#endregion
@@ -416,6 +425,24 @@ public async Task<Result<MerchantScheduleResponse>> GetMerchantSchedule(Guid est
416425
return Result.Success(merchantScheduleResponse);
417426
}
418427

428+
public async Task<Result<MerchantDailyPerformanceSummaryResponse>> GetMerchantDailyPerformanceSummary(Guid estateId,
429+
MerchantDailyPerformanceSummaryRequest request,
430+
CancellationToken cancellationToken)
431+
{
432+
if (this.EstateReportingApiClient == null)
433+
{
434+
return Result.Failure("Estate reporting client is not configured");
435+
}
436+
437+
Result<TokenResponse> accessTokenResult = await this.GetAccessToken(cancellationToken);
438+
if (accessTokenResult.IsFailed) {
439+
return ResultHelpers.CreateFailure(accessTokenResult);
440+
}
441+
442+
TokenResponse accessToken = accessTokenResult.Data;
443+
return await this.EstateReportingApiClient.GetMerchantDailyPerformanceSummary(accessToken.AccessToken, estateId, request, cancellationToken);
444+
}
445+
419446
private static ProcessReconciliationResponse CreateProcessReconciliationResponse(ReconciliationResponse reconciliationResponse)
420447
{
421448
return new ProcessReconciliationResponse

TransactionProcessorACL.BusinessLogic/TransactionProcessorACL.BusinessLogic.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
<ItemGroup>
2121
<ProjectReference Include="..\TransactionProcessorACL.Models\TransactionProcessorACL.Models.csproj" />
22+
<ProjectReference Include="..\TransactionProcessorACL.DataTransferObjects\TransactionProcessorACL.DataTransferObjects.csproj" />
2223
</ItemGroup>
2324

2425
<ItemGroup>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
using System.Diagnostics.CodeAnalysis;
3+
4+
namespace TransactionProcessorACL.DataTransferObjects.Requests;
5+
6+
[ExcludeFromCodeCoverage]
7+
public class MerchantDailyPerformanceSummaryRequest
8+
{
9+
public int MerchantReportingId { get; set; }
10+
11+
public DateTime StartDate { get; set; }
12+
13+
public DateTime EndDate { get; set; }
14+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace TransactionProcessorACL.Models;
5+
6+
public class MerchantDailyPerformanceSummaryResponse
7+
{
8+
public List<MetricItem> Metrics { get; set; } = [];
9+
10+
public List<DrillDownTransaction> DrillDownTransactions { get; set; } = [];
11+
}
12+
13+
public class MetricItem
14+
{
15+
public string Title { get; set; }
16+
17+
public decimal Value { get; set; }
18+
19+
public string Description { get; set; }
20+
21+
public int Category { get; set; }
22+
}
23+
24+
public class DrillDownTransaction
25+
{
26+
public string Reference { get; set; }
27+
28+
public string Product { get; set; }
29+
30+
public string Status { get; set; }
31+
32+
public decimal Amount { get; set; }
33+
34+
public DateTime TransactionDateTime { get; set; }
35+
}

TransactionProcessorACL.Testing/TestData.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ public class TestData
189189
["AppSettings:MinimumSupportedApplicationVersion"] = "1.0.5",
190190
["AppSettings:SecurityService"] = "http://192.168.1.133:5001",
191191
["AppSettings:TransactionProcessorApi"] = "http://192.168.1.133:5002",
192+
["AppSettings:EstateReportingApi"] = "http://192.168.1.133:5011",
192193
["AppSettings:ClientId"] = "ClientId",
193194
["AppSettings:ClientSecret"] = "secret",
194195
["SecurityConfiguration:Authority"] = "https://127.0.0.1",
@@ -202,6 +203,7 @@ public class TestData
202203
["AppSettings:MinimumSupportedApplicationVersion"] = "1.0.5",
203204
["AppSettings:SecurityService"] = "http://192.168.1.133:5001",
204205
["AppSettings:TransactionProcessorApi"] = "http://192.168.1.133:5002",
206+
["AppSettings:EstateReportingApi"] = "http://192.168.1.133:5011",
205207
["AppSettings:ClientId"] = "ClientId",
206208
["AppSettings:ClientSecret"] = "secret",
207209
["SecurityConfiguration:Authority"] = "https://127.0.0.1",

0 commit comments

Comments
 (0)