diff --git a/EstateManagementUI.BlazorServer.Tests/Pages/HomePageTests.cs b/EstateManagementUI.BlazorServer.Tests/Pages/HomePageTests.cs index c7fa1120..2fa9e0b8 100644 --- a/EstateManagementUI.BlazorServer.Tests/Pages/HomePageTests.cs +++ b/EstateManagementUI.BlazorServer.Tests/Pages/HomePageTests.cs @@ -60,7 +60,7 @@ public void Home_RendersCorrectly() this._mockMediator.Setup(m => m.Send(It.IsAny())).ReturnsAsync(Result.Success(StubTestData.GetMockMerchantKpi())); this._mockMediator.Setup(m => m.Send(It.IsAny())).ReturnsAsync(Result.Success(StubTestData.GetMockTodaysSales())); this._mockMediator.Setup(m => m.Send(It.IsAny())).ReturnsAsync(Result.Success(StubTestData.GetMockTodaysSales())); - this._mockMediator.Setup(m => m.Send(It.IsAny())).ReturnsAsync(Result.Success(StubTestData.GetMockMerchants())); + this._mockMediator.Setup(m => m.Send(It.IsAny())).ReturnsAsync(Result.Success(StubTestData.GetMockRecentMerchants())); // Act var cut = RenderComponent(); @@ -87,7 +87,7 @@ public void Home_HasCorrectPageTitle() this._mockMediator.Setup(m => m.Send(It.IsAny())).ReturnsAsync(Result.Success(StubTestData.GetMockMerchantKpi())); this._mockMediator.Setup(m => m.Send(It.IsAny())).ReturnsAsync(Result.Success(StubTestData.GetMockTodaysSales())); this._mockMediator.Setup(m => m.Send(It.IsAny())).ReturnsAsync(Result.Success(StubTestData.GetMockTodaysSales())); - this._mockMediator.Setup(m => m.Send(It.IsAny())).ReturnsAsync(Result.Success(StubTestData.GetMockMerchants())); + this._mockMediator.Setup(m => m.Send(It.IsAny())).ReturnsAsync(Result.Success(StubTestData.GetMockRecentMerchants())); // Act diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Home.razor b/EstateManagementUI.BlazorServer/Components/Pages/Home.razor index f6ef9dce..c8ea7fb7 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Home.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Home.razor @@ -178,7 +178,7 @@
- @foreach (var merchant in recentMerchants.Take(5)) + @foreach (var merchant in recentMerchants) {
@@ -188,8 +188,9 @@
-

@merchant.MerchantName

-

@merchant.MerchantReference

+

@merchant.Name (@merchant.Reference)

+ @*

@merchant.Reference

*@ +

@merchant.CreatedDateTime.ToString("dd/MM/yyyy HH:mm")

View diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Home.razor.cs b/EstateManagementUI.BlazorServer/Components/Pages/Home.razor.cs index 35d7f444..2cd9a6e1 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Home.razor.cs +++ b/EstateManagementUI.BlazorServer/Components/Pages/Home.razor.cs @@ -26,7 +26,7 @@ public partial class Home private TodaysSalesModel? todaysSales; private TodaysSalesModel? todaysFailedSales; private List? comparisonDates; - private List? recentMerchants; + private List? recentMerchants; private string _selectedComparisonDate = DateTime.Now.AddDays(-7).ToString("yyyy-MM-dd"); private int changeEventCounter = 0; @@ -115,7 +115,7 @@ private async Task LoadDashboardData(CorrelationId correlationId, Guid e var kpiTask = Mediator.Send(new Queries.GetMerchantKpiQuery(correlationId, estateId)); var salesTask = Mediator.Send(new Queries.GetTodaysSalesQuery(correlationId, estateId, comparisonDateResult.Data)); var failedSalesTask = Mediator.Send(new Queries.GetTodaysFailedSalesQuery(correlationId, estateId, LOW_CREDIT_RESPONSE_CODE, comparisonDateResult.Data)); - var merchantsTask = Mediator.Send(new Queries.GetMerchantsQuery(correlationId, estateId)); + var merchantsTask = Mediator.Send(new Queries.GetRecentMerchantsQuery(correlationId, estateId)); await Task.WhenAll(kpiTask, salesTask, failedSalesTask, merchantsTask); diff --git a/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs b/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs index bde515fd..64c14a74 100644 --- a/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs +++ b/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs @@ -296,5 +296,29 @@ public static List ConvertFrom(List result.Add(ConvertFrom(m))); return result; } + + public static List? ConvertFrom(List models) { + List result = new List(); + models.ForEach(m => result.Add(ConvertFrom(m))); + return result; + } + + private static RecentMerchantsModel ConvertFrom(BusinessLogic.Models.RecentMerchantsModel model) { + RecentMerchantsModel result = new RecentMerchantsModel() { + CreatedDateTime = model.CreatedDateTime, + EstateReportingId = model.EstateReportingId, + LastSale = model.LastSale, + LastSaleDateTime = model.LastSaleDateTime, + LastStatement = model.LastStatement, + MerchantId = model.MerchantId, + MerchantReportingId = model.MerchantReportingId, + Name = model.Name, + PostCode = model.PostCode, + Reference = model.Reference, + Region = model.Region, + Town = model.Town + }; + return result; + } } } \ No newline at end of file diff --git a/EstateManagementUI.BlazorServer/Models/Models.cs b/EstateManagementUI.BlazorServer/Models/Models.cs index f9817828..1ae19fe1 100644 --- a/EstateManagementUI.BlazorServer/Models/Models.cs +++ b/EstateManagementUI.BlazorServer/Models/Models.cs @@ -230,3 +230,19 @@ public class TransactionDetailModel public decimal NetAmount { get; set; } public string? SettlementReference { get; set; } } + +public class RecentMerchantsModel +{ + public DateTime CreatedDateTime { get; set; } + public Int32 EstateReportingId { get; set; } + public DateTime LastSale { get; set; } + public DateTime LastSaleDateTime { get; set; } + public DateTime LastStatement { get; set; } + public Guid MerchantId { get; set; } + public Int32 MerchantReportingId { get; set; } + public String Name { get; set; } + public String PostCode { get; set; } + public String Reference { get; set; } + public String Region { get; set; } + public String Town { get; set; } +} \ No newline at end of file diff --git a/EstateManagmentUI.BusinessLogic/BackendAPI/DataTransferObjects/DataTransferObjects.cs b/EstateManagmentUI.BusinessLogic/BackendAPI/DataTransferObjects/DataTransferObjects.cs index 21932a9a..1162ca7e 100644 --- a/EstateManagmentUI.BusinessLogic/BackendAPI/DataTransferObjects/DataTransferObjects.cs +++ b/EstateManagmentUI.BusinessLogic/BackendAPI/DataTransferObjects/DataTransferObjects.cs @@ -37,4 +37,36 @@ public class TodaysSales [JsonProperty("comparison_average_sales_value")] public Decimal ComparisonAverageSalesValue { get; set; } } + + public class Merchant + { + #region Properties + + [JsonProperty("created_date_time")] + public DateTime CreatedDateTime { get; set; } + [JsonProperty("estate_reporting_id")] + public Int32 EstateReportingId { get; set; } + [JsonProperty("last_sale")] + public DateTime LastSale { get; set; } + [JsonProperty("last_sale_date_time")] + public DateTime LastSaleDateTime { get; set; } + [JsonProperty("last_statement")] + public DateTime LastStatement { get; set; } + [JsonProperty("merchant_id")] + public Guid MerchantId { get; set; } + [JsonProperty("merchant_reporting_id")] + public Int32 MerchantReportingId { get; set; } + [JsonProperty("name")] + public String Name { get; set; } + [JsonProperty("post_code")] + public String PostCode { get; set; } + [JsonProperty("reference")] + public String Reference { get; set; } + [JsonProperty("region")] + public String Region { get; set; } + [JsonProperty("town")] + public String Town { get; set; } + + #endregion + } } diff --git a/EstateManagmentUI.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs b/EstateManagmentUI.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs index 3dec7d75..261afe6a 100644 --- a/EstateManagmentUI.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs +++ b/EstateManagmentUI.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs @@ -12,6 +12,9 @@ public interface IEstateReportingApiClient Task>> GetComparisonDates(String accessToken, Guid estateId, CancellationToken cancellationToken); Task> GetMerchantKpi(String accessToken, Guid estateId, CancellationToken cancellationToken); + Task>> GetRecentMerchants(String accessToken, + Guid estateId, + CancellationToken cancellationToken); Task> GetTodaysSales(String accessToken, Guid estateId, Int32 merchantReportingId, @@ -83,6 +86,31 @@ public async Task> GetMerchantKpi(String accessToken, Guid e } } + public async Task>> GetRecentMerchants(String accessToken, Guid estateId, CancellationToken cancellationToken) + { + String requestUri = this.BuildRequestUrl("/api/merchants/recent"); + + try + { + List<(String headerName, String headerValue)> additionalHeaders = [ + (EstateIdHeaderName, estateId.ToString()) + ]; + Result> result = await this.SendHttpGetRequest>(requestUri, accessToken, additionalHeaders, cancellationToken); + + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); + + return result; + } + catch (Exception ex) + { + // An exception has occurred, add some additional information to the message + Exception exception = new Exception($"Error getting recent merchants for estate {estateId}.", ex); + + return Result.Failure(exception.Message); + } + } + public async Task> GetTodaysSales(String accessToken, Guid estateId, Int32 merchantReportingId, Int32 operatorReportingId, DateTime comparisonDate, CancellationToken cancellationToken) { QueryStringBuilder builder = new QueryStringBuilder(); diff --git a/EstateManagmentUI.BusinessLogic/Client/APIModelFactory.cs b/EstateManagmentUI.BusinessLogic/Client/APIModelFactory.cs index 7d8316dd..83df32fc 100644 --- a/EstateManagmentUI.BusinessLogic/Client/APIModelFactory.cs +++ b/EstateManagmentUI.BusinessLogic/Client/APIModelFactory.cs @@ -42,4 +42,28 @@ public static TodaysSalesModel ConvertFrom(TodaysSales apiResultData) { }; return model; } + + public static List ConvertFrom(List apiResultData) { + List merchants = new(); + + foreach (Merchant merchant in apiResultData) { + merchants.Add(new RecentMerchantsModel + { + CreatedDateTime = merchant.CreatedDateTime, + EstateReportingId = merchant.EstateReportingId, + LastSale = merchant.LastSale, + LastSaleDateTime = merchant.LastSaleDateTime, + LastStatement = merchant.LastStatement, + MerchantId = merchant.MerchantId, + MerchantReportingId = merchant.MerchantReportingId, + Name = merchant.Name, + PostCode = merchant.PostCode, + Reference = merchant.Reference, + Region = merchant.Region, + Town = merchant.Town + }); + } + + return merchants; + } } \ No newline at end of file diff --git a/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs b/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs index 10b40658..d611e14d 100644 --- a/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs +++ b/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs @@ -1,4 +1,5 @@ -using EstateManagementUI.BusinessLogic.Models; +using EstateManagementUI.BusinessLogic.BackendAPI.DataTransferObjects; +using EstateManagementUI.BusinessLogic.Models; using EstateManagementUI.BusinessLogic.Requests; using SecurityService.DataTransferObjects.Responses; using Shared.Results; @@ -9,6 +10,7 @@ namespace EstateManagementUI.BusinessLogic.Client public partial interface IApiClient { Task> GetMerchantKpi(Queries.GetMerchantKpiQuery request, CancellationToken cancellationToken); + Task>> GetRecentMerchants(Queries.GetRecentMerchantsQuery request, CancellationToken cancellationToken); } public partial class ApiClient : IApiClient { @@ -29,5 +31,21 @@ public async Task> GetMerchantKpi(Queries.GetMerchantKp return Result.Success(merchantKpiModel); } + + public async Task>> GetRecentMerchants(Queries.GetRecentMerchantsQuery request, + CancellationToken cancellationToken) { + Result token = await this.GetToken(cancellationToken); + if (token.IsFailed) + return ResultHelpers.CreateFailure(token); + + Result> apiResult = await this.EstateReportingApiClient.GetRecentMerchants(token.Data, request.EstateId, cancellationToken); + + if (apiResult.IsFailed) + return ResultHelpers.CreateFailure(apiResult); + + List recentMerchantsModels = APIModelFactory.ConvertFrom(apiResult.Data); + + return Result.Success(recentMerchantsModels); + } } } diff --git a/EstateManagmentUI.BusinessLogic/Client/StubTestData.cs b/EstateManagmentUI.BusinessLogic/Client/StubTestData.cs index d9854283..b5c8c883 100644 --- a/EstateManagmentUI.BusinessLogic/Client/StubTestData.cs +++ b/EstateManagmentUI.BusinessLogic/Client/StubTestData.cs @@ -43,6 +43,31 @@ public static class StubTestData { } }; + public static List GetMockRecentMerchants() => new() + { + new RecentMerchantsModel + { + MerchantId = Guid.Parse("22222222-2222-2222-2222-222222222222"), + Name = "Test Merchant 1", + Reference = "MERCH001", + CreatedDateTime = DateTime.Now + }, + new RecentMerchantsModel + { + MerchantId = Guid.Parse("22222222-2222-2222-2222-222222222223"), + Name = "Test Merchant 2", + Reference = "MERCH002", + CreatedDateTime = DateTime.Now.AddDays(-1) + }, + new RecentMerchantsModel + { + MerchantId = Guid.Parse("22222222-2222-2222-2222-222222222224"), + Name = "Test Merchant 3", + Reference = "MERCH003", + CreatedDateTime = DateTime.Now.AddDays(-5) + } + }; + public static MerchantModel GetMockMerchant() => new() { MerchantId = Guid.Parse("22222222-2222-2222-2222-222222222222"), diff --git a/EstateManagmentUI.BusinessLogic/Models/Models.cs b/EstateManagmentUI.BusinessLogic/Models/Models.cs index 1060dba4..0a9d5e3f 100644 --- a/EstateManagmentUI.BusinessLogic/Models/Models.cs +++ b/EstateManagmentUI.BusinessLogic/Models/Models.cs @@ -35,6 +35,7 @@ public class MerchantModel public string? ContactName { get; set; } public string? ContactEmailAddress { get; set; } public string? ContactPhoneNumber { get; set; } + public DateTime CreatedDateTime { get; set; } } // Operator Models @@ -253,3 +254,19 @@ public class TransactionDetailModel public decimal NetAmount { get; set; } public string? SettlementReference { get; set; } } + +public class RecentMerchantsModel +{ + public DateTime CreatedDateTime { get; set; } + public Int32 EstateReportingId { get; set; } + public DateTime LastSale { get; set; } + public DateTime LastSaleDateTime { get; set; } + public DateTime LastStatement { get; set; } + public Guid MerchantId { get; set; } + public Int32 MerchantReportingId { get; set; } + public String Name { get; set; } + public String PostCode { get; set; } + public String Reference { get; set; } + public String Region { get; set; } + public String Town { get; set; } +} diff --git a/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs b/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs index 112d6c22..783de7ed 100644 --- a/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs +++ b/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs @@ -58,7 +58,8 @@ public class MerchantRequestHandler : IRequestHandler, IRequestHandler, IRequestHandler, - IRequestHandler + IRequestHandler, + IRequestHandler>> { private readonly IApiClient ApiClient; @@ -136,6 +137,11 @@ public async Task Handle(Commands.AssignContractToMerchantCommand reques CancellationToken cancellationToken) { return Result.Success(); } + + public async Task>> Handle(Queries.GetRecentMerchantsQuery request, + CancellationToken cancellationToken) { + return await this.ApiClient.GetRecentMerchants(request, cancellationToken); + } } public class ContractRequestHandler : IRequestHandler>>, diff --git a/EstateManagmentUI.BusinessLogic/Requests/Requests.cs b/EstateManagmentUI.BusinessLogic/Requests/Requests.cs index c81d0b47..bf931650 100644 --- a/EstateManagmentUI.BusinessLogic/Requests/Requests.cs +++ b/EstateManagmentUI.BusinessLogic/Requests/Requests.cs @@ -15,6 +15,7 @@ public static class Queries { public record GetEstateQuery(CorrelationId CorrelationId, string AccessToken, Guid EstateId) : IRequest>; public record GetMerchantsQuery(CorrelationId CorrelationId, Guid EstateId) : IRequest>>; + public record GetRecentMerchantsQuery(CorrelationId CorrelationId, Guid EstateId) : IRequest>>; public record GetOperatorsQuery(CorrelationId CorrelationId, string AccessToken, Guid EstateId) : IRequest>>; public record GetContractsQuery(CorrelationId CorrelationId, string AccessToken, Guid EstateId) : IRequest>>; public record GetOperatorQuery(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid OperatorId) : IRequest>; diff --git a/EstateManagmentUI.BusinessLogic/Services/ITestDataStore.cs b/EstateManagmentUI.BusinessLogic/Services/ITestDataStore.cs index 78f80b9e..b7e35f81 100644 --- a/EstateManagmentUI.BusinessLogic/Services/ITestDataStore.cs +++ b/EstateManagmentUI.BusinessLogic/Services/ITestDataStore.cs @@ -14,6 +14,7 @@ public interface ITestDataStore // Merchant Management List GetMerchants(Guid estateId); + List GetRecentMerchants(Guid estateId); MerchantModel? GetMerchant(Guid estateId, Guid merchantId); void AddMerchant(Guid estateId, MerchantModel merchant); void UpdateMerchant(Guid estateId, MerchantModel merchant); diff --git a/EstateManagmentUI.BusinessLogic/Services/TestDataStore.cs b/EstateManagmentUI.BusinessLogic/Services/TestDataStore.cs index 2d0e1608..0ddc1463 100644 --- a/EstateManagmentUI.BusinessLogic/Services/TestDataStore.cs +++ b/EstateManagmentUI.BusinessLogic/Services/TestDataStore.cs @@ -66,6 +66,20 @@ public List GetMerchants(Guid estateId) return new List(); } + public List GetRecentMerchants(Guid estateId) + { + if (this._merchants.TryGetValue(estateId, out var merchantDict)) + { + return merchantDict.Values.Select(m => new RecentMerchantsModel { + CreatedDateTime = m.CreatedDateTime, + Reference = m.MerchantReference, + Name = m.MerchantName, + MerchantId = m.MerchantId + }).ToList(); + } + return new List(); + } + public MerchantModel? GetMerchant(Guid estateId, Guid merchantId) { if (this._merchants.TryGetValue(estateId, out var merchantDict)) @@ -213,7 +227,8 @@ private void InitializeDefaultData() Country = "Test Country", ContactName = "John Smith", ContactEmailAddress = "john@testmerchant.com", - ContactPhoneNumber = "555-1234" + ContactPhoneNumber = "555-1234", + CreatedDateTime = DateTime.Now }); this.AddMerchant(estateId, new MerchantModel @@ -223,7 +238,8 @@ private void InitializeDefaultData() MerchantReference = "MERCH002", Balance = 5000.00m, AvailableBalance = 4200.00m, - SettlementSchedule = "Weekly" + SettlementSchedule = "Weekly", + CreatedDateTime = DateTime.Now.AddDays(-1) }); this.AddMerchant(estateId, new MerchantModel @@ -233,7 +249,8 @@ private void InitializeDefaultData() MerchantReference = "MERCH003", Balance = 15000.00m, AvailableBalance = 12000.00m, - SettlementSchedule = "Monthly" + SettlementSchedule = "Monthly", + CreatedDateTime = DateTime.Now.AddDays(-5) }); // Default test operators diff --git a/EstateManagmentUI.BusinessLogic/Services/TestMediatorService.cs b/EstateManagmentUI.BusinessLogic/Services/TestMediatorService.cs index e3b518fc..192ed797 100644 --- a/EstateManagmentUI.BusinessLogic/Services/TestMediatorService.cs +++ b/EstateManagmentUI.BusinessLogic/Services/TestMediatorService.cs @@ -28,7 +28,8 @@ public Task Send(IRequest request, Cancellation // Merchant Queries Queries.GetMerchantsQuery query => Task.FromResult((TResponse)(object)Result.Success(this._testDataStore.GetMerchants(query.EstateId))), Queries.GetMerchantQuery query => Task.FromResult((TResponse)(object)this.GetMerchantResult(query.EstateId, query.MerchantId)), - + Queries.GetRecentMerchantsQuery query => Task.FromResult((TResponse)(object)Result.Success(this._testDataStore.GetRecentMerchants(query.EstateId))), + // Operator Queries Queries.GetOperatorsQuery query => Task.FromResult((TResponse)(object)Result.Success(this._testDataStore.GetOperators(query.EstateId))), Queries.GetOperatorQuery query => Task.FromResult((TResponse)(object)this.GetOperatorResult(query.EstateId, query.OperatorId)),