From c5343b9adbfb9bea5b1f5b2aa0d52e456cd9bd55 Mon Sep 17 00:00:00 2001 From: StuartFerguson Date: Tue, 20 Jan 2026 11:48:05 +0000 Subject: [PATCH] Enhance Estate Index with estate-level summary data Refactor Estate Index to display total merchants, contracts, operators, and users by extending EstateModel and related models. Add new DTOs and API client methods to fetch estate details and recent contracts. Update UI, model factories, test data, and tests to support new structure. Set TestMode to "Disabled" in development settings. --- .../Pages/Estate/EstateIndexPageTests.cs | 37 ++++---- .../Components/Pages/Estate/Index.razor | 14 +-- .../Components/Pages/Estate/Index.razor.cs | 72 ++++++++------- .../Components/Pages/Home.razor | 1 - .../Factories/ModelFactory.cs | 41 ++++++++- .../Models/Models.cs | 34 +++++++ .../appsettings.Development.json | 2 +- .../DataTransferObjects.cs | 88 +++++++++++++++++++ .../BackendAPI/IEstateReportingApiClient.cs | 58 ++++++++++++ .../Client/APIModelFactory.cs | 64 ++++++++++++-- .../Client/EstateMethods.cs | 3 +- .../Client/MerchantMethods.cs | 17 ++++ .../Models/Models.cs | 34 +++++++ .../RequestHandlers/DateRequestHandler.cs | 8 +- .../Requests/Requests.cs | 1 + .../Services/TestDataStore.cs | 27 +++++- 16 files changed, 418 insertions(+), 83 deletions(-) diff --git a/EstateManagementUI.BlazorServer.Tests/Pages/Estate/EstateIndexPageTests.cs b/EstateManagementUI.BlazorServer.Tests/Pages/Estate/EstateIndexPageTests.cs index 9e6b095b..5c152d5e 100644 --- a/EstateManagementUI.BlazorServer.Tests/Pages/Estate/EstateIndexPageTests.cs +++ b/EstateManagementUI.BlazorServer.Tests/Pages/Estate/EstateIndexPageTests.cs @@ -29,12 +29,10 @@ public void EstateIndex_RendersCorrectly() _mockMediator.Setup(x => x.Send(It.IsAny(), default)) .ReturnsAsync(Result.Success(estate)); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); + _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + .ReturnsAsync(Result.Success(new List())); + _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + .ReturnsAsync(Result.Success(new List())); // Act var cut = RenderComponent(); @@ -57,18 +55,15 @@ public void EstateIndex_DisplaysEstateDetails() _mockMediator.Setup(x => x.Send(It.IsAny(), default)) .ReturnsAsync(Result.Success(estate)); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); + _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + .ReturnsAsync(Result.Success(new List())); + _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + .ReturnsAsync(Result.Success(new List())); + // Act var cut = RenderComponent(); - //cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); - + // Assert - //cut.Markup.ShouldContain("Test Estate"); cut.WaitForAssertion(() => cut.Markup.ShouldContain("Test Estate"), timeout: TimeSpan.FromSeconds(5)); } @@ -78,13 +73,11 @@ public void EstateIndex_HasCorrectPageTitle() // Arrange _mockMediator.Setup(x => x.Send(It.IsAny(), default)) .ReturnsAsync(Result.Success(new EstateModel { EstateId = Guid.NewGuid() })); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); - + _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + .ReturnsAsync(Result.Success(new List())); + _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + .ReturnsAsync(Result.Success(new List())); + // Act var cut = RenderComponent(); diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor b/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor index a8249de9..c306d73e 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor @@ -62,7 +62,7 @@

Total Merchants

-

@(merchants?.Count ?? 0)

+

@(estate.Merchants?.Count ?? 0)

@@ -74,7 +74,7 @@

Total Operators

-

@(assignedOperators?.Count ?? 0)

+

@(estate.Operators?.Count ?? 0)

@@ -86,7 +86,7 @@

Total Contracts

-

@(contracts?.Count ?? 0)

+

@(estate.Operators?.Count ?? 0)

@@ -98,7 +98,7 @@

Total Users

-

5

+

@(estate.Users?.Count ?? 0)

@@ -118,12 +118,12 @@ @if (merchants != null && merchants.Any()) {
- @foreach (var merchant in merchants.Take(5)) + @foreach (var merchant in merchants) {
-

@merchant.MerchantName

-

@merchant.MerchantReference

+

@merchant.Name (@merchant.Reference)

+

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

diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor.cs b/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor.cs index f6933b89..2cb040dc 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor.cs +++ b/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor.cs @@ -4,6 +4,7 @@ using EstateManagementUI.BlazorServer.Permissions; using EstateManagementUI.BusinessLogic.Requests; using Microsoft.AspNetCore.Components.Authorization; +using Shared.Results; using SimpleResults; namespace EstateManagementUI.BlazorServer.Components.Pages.Estate @@ -12,10 +13,10 @@ public partial class Index { private bool isLoading = true; private EstateModel? estate; - private List? merchants; + private List merchants; private List? availableOperators; private List assignedOperators = new(); - private List? contracts; + private List contracts; private string activeTab = "overview"; private bool showAddOperator = false; private string? selectedOperatorId; @@ -35,41 +36,9 @@ protected override async Task OnAfterRenderAsync(bool firstRender) await RequirePermission(PermissionSection.Estate, PermissionFunction.View); CorrelationId correlationId = new(Guid.NewGuid()); Guid estateId = await this.GetEstateId(); - - Result estateResult = await Mediator.Send(new Queries.GetEstateQuery(correlationId, estateId)); - if (estateResult.IsSuccess) - { - estate = ModelFactory.ConvertFrom(estateResult.Data); - // Load assigned operators from estate model - if (estate.Operators != null) - { - assignedOperators = estate.Operators.Select(o => new OperatorModel - { - OperatorId = o.OperatorId, - Name = o.Name, - RequireCustomMerchantNumber = o.RequireCustomMerchantNumber, - RequireCustomTerminalNumber = o.RequireCustomTerminalNumber - }).ToList(); - } - } - - // TODO: Make these calls concurrent... - var merchantsResult = await Mediator.Send(new Queries.GetMerchantsQuery(correlationId, estateId)); - if (merchantsResult.IsSuccess) - { - merchants = ModelFactory.ConvertFrom(merchantsResult.Data); - } - - var operatorsResult = await Mediator.Send(new Queries.GetOperatorsQuery(correlationId, String.Empty, estateId)); - if (operatorsResult.IsSuccess) - { - availableOperators = ModelFactory.ConvertFrom(operatorsResult.Data); - } - - var contractsResult = await Mediator.Send(new Queries.GetContractsQuery(correlationId, String.Empty, estateId)); - if (contractsResult.IsSuccess) - { - contracts = ModelFactory.ConvertFrom(contractsResult.Data); + var result = await this.LoadEstateData(correlationId, estateId); + if (result.IsFailed) { + this.NavigationManager.NavigateToErrorPage(); } } finally @@ -79,6 +48,35 @@ protected override async Task OnAfterRenderAsync(bool firstRender) } } + private async Task LoadEstateData(CorrelationId correlationId, Guid estateId) + { + Result estateResult = await Mediator.Send(new Queries.GetEstateQuery(correlationId, estateId)); + if (estateResult.IsFailed) + return ResultHelpers.CreateFailure(estateResult); + estate = ModelFactory.ConvertFrom(estateResult.Data); + + Result> merchantResult = await Mediator.Send(new Queries.GetRecentMerchantsQuery(correlationId, estateId)); + + if (merchantResult.IsFailed) + return ResultHelpers.CreateFailure(merchantResult); + + // Note: API returns merchants in creation order (newest first) + // If ordering is incorrect, would need CreatedDate field in the model + this.merchants = ModelFactory.ConvertFrom(merchantResult.Data); + + Result> contractResult = await Mediator.Send(new Queries.GetRecentContractsQuery(correlationId, estateId)); + + if (contractResult.IsFailed) + return ResultHelpers.CreateFailure(contractResult); + + // Note: API returns merchants in creation order (newest first) + // If ordering is incorrect, would need CreatedDate field in the model + this.contracts = ModelFactory.ConvertFrom(contractResult.Data); + + return Result.Success(); + } + + private void SetActiveTab(string tab) { activeTab = tab; diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Home.razor b/EstateManagementUI.BlazorServer/Components/Pages/Home.razor index 00a4f067..e1a5b8f8 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Home.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Home.razor @@ -190,7 +190,6 @@

@merchant.Name (@merchant.Reference)

- @*

@merchant.Reference

*@

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

diff --git a/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs b/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs index e7867fad..1b594588 100644 --- a/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs +++ b/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs @@ -3,14 +3,41 @@ namespace EstateManagementUI.BlazorServer.Factories { public static class ModelFactory { public static EstateModel ConvertFrom(BusinessLogic.Models.EstateModel model) { - EstateModel result = new EstateModel { EstateId = model.EstateId, EstateName = model.EstateName, Operators = new List(), Reference = model.Reference }; + EstateModel result = new EstateModel { EstateId = model.EstateId, EstateName = model.EstateName, + Operators = new List(), + Contracts = new(), + Merchants = new(), + Users = new(), + Reference = model.Reference }; if (model.Operators != null && model.Operators.Any()) { model.Operators.ForEach((o) => result.Operators.Add(ConvertFrom(o))); } + if (model.Merchants != null && model.Merchants.Any()) { + model.Merchants.ForEach((m) => result.Merchants.Add(ConvertFrom(m))); + } + if (model.Contracts != null && model.Contracts.Any()) { + model.Contracts.ForEach((m) => result.Contracts.Add(ConvertFrom(m))); + } + if (model.Users != null && model.Users.Any()) + { + model.Users.ForEach((m) => result.Users.Add(ConvertFrom(m))); + } return result; } + private static EstateUserModel ConvertFrom(BusinessLogic.Models.EstateUserModel model) { + return new EstateUserModel() { CreatedDateTime = model.CreatedDateTime, EmailAddress = model.EmailAddress, UserId = model.UserId }; + } + + private static EstateContractModel ConvertFrom(BusinessLogic.Models.EstateContractModel model) { + return new EstateContractModel() { ContractId = model.ContractId, Name = model.Name, OperatorId = model.OperatorId, OperatorName = model.OperatorName }; + } + + private static EstateMerchantModel ConvertFrom(BusinessLogic.Models.EstateMerchantModel model) { + return new EstateMerchantModel() { Reference = model.Reference, Name = model.Name, MerchantId = model.MerchantId }; + } + public static EstateOperatorModel ConvertFrom(BusinessLogic.Models.EstateOperatorModel model) { return new EstateOperatorModel() { Name = model.Name, OperatorId = model.OperatorId, RequireCustomMerchantNumber = model.RequireCustomMerchantNumber, RequireCustomTerminalNumber = model.RequireCustomTerminalNumber }; } @@ -299,7 +326,7 @@ public static List ConvertFrom(List? ConvertFrom(List models) { + public static List ConvertFrom(List models) { List result = new List(); models.ForEach(m => result.Add(ConvertFrom(m))); return result; @@ -322,5 +349,15 @@ private static RecentMerchantsModel ConvertFrom(BusinessLogic.Models.RecentMerch }; return result; } + + public static List ConvertFrom(List models) { + List result = new List(); + models.ForEach(m => result.Add(ConvertFrom(m))); + return result; + } + + private static RecentContractModel ConvertFrom(BusinessLogic.Models.RecentContractModel model) { + return new RecentContractModel { OperatorName = model.OperatorName, Description = model.Description, ContractId = model.ContractId }; + } } } \ No newline at end of file diff --git a/EstateManagementUI.BlazorServer/Models/Models.cs b/EstateManagementUI.BlazorServer/Models/Models.cs index cfaa6524..12fb4e78 100644 --- a/EstateManagementUI.BlazorServer/Models/Models.cs +++ b/EstateManagementUI.BlazorServer/Models/Models.cs @@ -7,6 +7,16 @@ public class EstateModel public string? EstateName { get; set; } public string? Reference { get; set; } public List? Operators { get; set; } + public List? Merchants { get; set; } + public List? Contracts { get; set; } + public List? Users { get; set; } +} + +public class EstateUserModel +{ + public Guid UserId { get; set; } + public string? EmailAddress { get; set; } + public DateTime CreatedDateTime { get; set; } } public class EstateOperatorModel @@ -15,6 +25,23 @@ public class EstateOperatorModel public string? Name { get; set; } public bool RequireCustomMerchantNumber { get; set; } public bool RequireCustomTerminalNumber { get; set; } + public DateTime CreatedDateTime { get; set; } +} + +public class EstateContractModel +{ + public Guid OperatorId { get; set; } + public Guid ContractId { get; set; } + public string? Name { get; set; } + public string? OperatorName { get; set; } +} + + +public class EstateMerchantModel +{ + public Guid MerchantId { get; set; } + public string? Name { get; set; } + public string? Reference { get; set; } } // Merchant Models @@ -247,4 +274,11 @@ public class RecentMerchantsModel public String Reference { get; set; } public String Region { get; set; } public String Town { get; set; } +} + +public class RecentContractModel +{ + public Guid ContractId { get; set; } + public string? Description { get; set; } + public string? OperatorName { get; set; } } \ No newline at end of file diff --git a/EstateManagementUI.BlazorServer/appsettings.Development.json b/EstateManagementUI.BlazorServer/appsettings.Development.json index 801f143b..41aa7485 100644 --- a/EstateManagementUI.BlazorServer/appsettings.Development.json +++ b/EstateManagementUI.BlazorServer/appsettings.Development.json @@ -6,6 +6,6 @@ } }, "AppSettings": { - "TestMode": "Full" + "TestMode": "Disabled" } } diff --git a/EstateManagmentUI.BusinessLogic/BackendAPI/DataTransferObjects/DataTransferObjects.cs b/EstateManagmentUI.BusinessLogic/BackendAPI/DataTransferObjects/DataTransferObjects.cs index 1162ca7e..22c77f68 100644 --- a/EstateManagmentUI.BusinessLogic/BackendAPI/DataTransferObjects/DataTransferObjects.cs +++ b/EstateManagmentUI.BusinessLogic/BackendAPI/DataTransferObjects/DataTransferObjects.cs @@ -69,4 +69,92 @@ public class Merchant #endregion } + + public class Contract + { + #region Properties + [JsonProperty("estate_id")] + public Guid EstateId { get; set; } + [JsonProperty("estate_reporting_id")] + public Int32 EstateReportingId { get; set; } + [JsonProperty("contract_id")] + public Guid ContractId { get; set; } + [JsonProperty("contract_reporting_id")] + public Int32 ContractReportingId { get; set; } + [JsonProperty("description")] + public String Description { get; set; } + [JsonProperty("operator_name")] + public String OperatorName { get; set; } + [JsonProperty("operator_id")] + public Guid OperatorId { get; set; } + [JsonProperty("operator_reporting_id")] + public Int32 OperatorReportingId { get; set; } + + #endregion + } + + public class Estate + { + [JsonProperty("estate_id")] + public Guid EstateId { get; set; } + [JsonProperty("estate_name")] + public string? EstateName { get; set; } + [JsonProperty("reference")] + public string? Reference { get; set; } + [JsonProperty("operators")] + public List? Operators { get; set; } + [JsonProperty("merchants")] + public List? Merchants { get; set; } + [JsonProperty("contracts")] + public List? Contracts { get; set; } + [JsonProperty("users")] + public List? Users { get; set; } + } + + public class EstateUser + { + [JsonProperty("user_id")] + public Guid UserId { get; set; } + [JsonProperty("email_address")] + public string? EmailAddress { get; set; } + [JsonProperty("created_date_time")] + public DateTime CreatedDateTime { get; set; } + } + + public class EstateOperator + { + [JsonProperty("operator_id")] + public Guid OperatorId { get; set; } + [JsonProperty("name")] + public string? Name { get; set; } + [JsonProperty("require_custom_merchant_number")] + public bool RequireCustomMerchantNumber { get; set; } + [JsonProperty("require_custom_terminal_number")] + public bool RequireCustomTerminalNumber { get; set; } + [JsonProperty("created_date_time")] + public DateTime CreatedDateTime { get; set; } + } + + public class EstateContract + { + [JsonProperty("operator_id")] + public Guid OperatorId { get; set; } + [JsonProperty("contract_id")] + public Guid ContractId { get; set; } + [JsonProperty("name")] + public string? Name { get; set; } + [JsonProperty("operator_name")] + public string? OperatorName { get; set; } + } + + + public class EstateMerchant + { + [JsonProperty("merchant_id")] + public Guid MerchantId { get; set; } + [JsonProperty("name")] + public string? Name { get; set; } + [JsonProperty("reference")] + public string? Reference { get; set; } + } } diff --git a/EstateManagmentUI.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs b/EstateManagmentUI.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs index 261afe6a..ab8e117b 100644 --- a/EstateManagmentUI.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs +++ b/EstateManagmentUI.BusinessLogic/BackendAPI/IEstateReportingApiClient.cs @@ -9,12 +9,17 @@ namespace EstateManagementUI.BusinessLogic.BackendAPI { public interface IEstateReportingApiClient { + Task> GetEstate(String accessToken, Guid estateId, CancellationToken cancellationToken); + 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>> GetRecentContracts(String accessToken, + Guid estateId, CancellationToken cancellationToken); Task> GetTodaysSales(String accessToken, Guid estateId, Int32 merchantReportingId, @@ -34,6 +39,33 @@ public EstateReportingApiClient(Func baseAddressResolver, this.BaseAddressResolver = baseAddressResolver; } + public async Task> GetEstate(String accessToken, + Guid estateId, + CancellationToken cancellationToken) { + String requestUri = this.BuildRequestUrl("/api/estates"); + + 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 estate {estateId}.", ex); + + return Result.Failure(exception.Message); + } + } + public async Task>> GetComparisonDates(String accessToken, Guid estateId, CancellationToken cancellationToken) { @@ -111,6 +143,32 @@ public async Task>> GetRecentMerchants(String accessToken, } } + public async Task>> GetRecentContracts(String accessToken, + Guid estateId, + CancellationToken cancellationToken) { + String requestUri = this.BuildRequestUrl("/api/contracts/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 6f84cc3c..f4c185ec 100644 --- a/EstateManagmentUI.BusinessLogic/Client/APIModelFactory.cs +++ b/EstateManagmentUI.BusinessLogic/Client/APIModelFactory.cs @@ -68,23 +68,69 @@ public static List ConvertFrom(List apiResultDat return merchants; } - public static EstateModel ConvertFrom(EstateResponse apiResultData) { - EstateModel model = new EstateModel { - Reference = apiResultData.EstateReference, + public static EstateModel ConvertFrom(Estate apiResultData) { + EstateModel model = new() { + Reference = apiResultData.Reference, EstateId = apiResultData.EstateId, EstateName = apiResultData.EstateName, - Operators = new List() + Operators = new(), + Users = new(), + Contracts = new(), + Merchants = new () }; - foreach (EstateOperatorResponse estateOperatorResponse in apiResultData.Operators) { + foreach (var estateOperator in apiResultData.Operators) { model.Operators.Add(new EstateOperatorModel { - Name = estateOperatorResponse.Name, - OperatorId = estateOperatorResponse.OperatorId, - RequireCustomMerchantNumber = estateOperatorResponse.RequireCustomMerchantNumber, - RequireCustomTerminalNumber = estateOperatorResponse.RequireCustomTerminalNumber, + Name = estateOperator.Name, + OperatorId = estateOperator.OperatorId, + RequireCustomMerchantNumber = estateOperator.RequireCustomMerchantNumber, + RequireCustomTerminalNumber = estateOperator.RequireCustomTerminalNumber, }); } + foreach (var estateMerchant in apiResultData.Merchants) + { + model.Merchants.Add(new EstateMerchantModel() + { + Name = estateMerchant.Name, + Reference = estateMerchant.Reference, + MerchantId = estateMerchant.MerchantId + }); + } + foreach (var estateContract in apiResultData.Contracts) + { + model.Contracts.Add(new EstateContractModel() + { + Name = estateContract.Name, + OperatorId = estateContract.OperatorId, + ContractId = estateContract.ContractId, + OperatorName = estateContract.OperatorName + }); + } + foreach (var estateUser in apiResultData.Users) + { + model.Users.Add(new EstateUserModel() + { + CreatedDateTime = estateUser.CreatedDateTime, + EmailAddress = estateUser.EmailAddress, + UserId = estateUser.UserId + }); + } + return model; } + + public static List ConvertFrom(List apiResultData) { + List contracts = new(); + + foreach (Contract contract in apiResultData) { + contracts.Add(new RecentContractModel { + ContractId = contract.ContractId, + Description = contract.Description, + OperatorName = contract.OperatorName + }); + } + + return contracts; + } } \ No newline at end of file diff --git a/EstateManagmentUI.BusinessLogic/Client/EstateMethods.cs b/EstateManagmentUI.BusinessLogic/Client/EstateMethods.cs index 03cb85cc..8c59f228 100644 --- a/EstateManagmentUI.BusinessLogic/Client/EstateMethods.cs +++ b/EstateManagmentUI.BusinessLogic/Client/EstateMethods.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics.Tracing; using System.Text; +using EstateManagementUI.BusinessLogic.BackendAPI.DataTransferObjects; using Shared.Results; using TransactionProcessor.DataTransferObjects.Responses.Estate; @@ -23,7 +24,7 @@ public async Task> GetEstate(Queries.GetEstateQuery request, if (token.IsFailed) return ResultHelpers.CreateFailure(token); - Result? apiResult = await this.TransactionProcessorClient.GetEstate(token.Data, request.EstateId, cancellationToken); + Result? apiResult = await this.EstateReportingApiClient.GetEstate(token.Data, request.EstateId, cancellationToken); if (apiResult.IsFailed) return ResultHelpers.CreateFailure(apiResult); diff --git a/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs b/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs index d611e14d..6a286f9c 100644 --- a/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs +++ b/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs @@ -11,6 +11,7 @@ public partial interface IApiClient { Task> GetMerchantKpi(Queries.GetMerchantKpiQuery request, CancellationToken cancellationToken); Task>> GetRecentMerchants(Queries.GetRecentMerchantsQuery request, CancellationToken cancellationToken); + Task>> GetRecentContracts(Queries.GetRecentContractsQuery request, CancellationToken cancellationToken); } public partial class ApiClient : IApiClient { @@ -47,5 +48,21 @@ public async Task>> GetRecentMerchants(Queries return Result.Success(recentMerchantsModels); } + + public async Task>> GetRecentContracts(Queries.GetRecentContractsQuery request, + CancellationToken cancellationToken) { + Result token = await this.GetToken(cancellationToken); + if (token.IsFailed) + return ResultHelpers.CreateFailure(token); + + Result> apiResult = await this.EstateReportingApiClient.GetRecentContracts(token.Data, request.EstateId, cancellationToken); + + if (apiResult.IsFailed) + return ResultHelpers.CreateFailure(apiResult); + + List recentContractModels = APIModelFactory.ConvertFrom(apiResult.Data); + + return Result.Success(recentContractModels); + } } } diff --git a/EstateManagmentUI.BusinessLogic/Models/Models.cs b/EstateManagmentUI.BusinessLogic/Models/Models.cs index cd189cd0..7e26641f 100644 --- a/EstateManagmentUI.BusinessLogic/Models/Models.cs +++ b/EstateManagmentUI.BusinessLogic/Models/Models.cs @@ -7,6 +7,15 @@ public class EstateModel public string? EstateName { get; set; } public string? Reference { get; set; } public List? Operators { get; set; } + public List? Merchants { get; set; } + public List? Contracts { get; set; } + public List? Users { get; set; } +} + +public class EstateUserModel { + public Guid UserId { get; set; } + public string? EmailAddress { get; set; } + public DateTime CreatedDateTime { get; set; } } public class EstateOperatorModel @@ -15,8 +24,25 @@ public class EstateOperatorModel public string? Name { get; set; } public bool RequireCustomMerchantNumber { get; set; } public bool RequireCustomTerminalNumber { get; set; } + public DateTime CreatedDateTime { get; set; } +} + +public class EstateContractModel +{ + public Guid OperatorId { get; set; } + public Guid ContractId { get; set; } + public string? Name { get; set; } + public string? OperatorName { get; set; } +} + + +public class EstateMerchantModel { + public Guid MerchantId { get; set; } + public string? Name { get; set; } + public string? Reference { get; set; } } + // Merchant Models public class MerchantModel { @@ -272,3 +298,11 @@ public class RecentMerchantsModel public String Region { get; set; } public String Town { get; set; } } + +public class RecentContractModel +{ + public Guid ContractId { get; set; } + public string? Description { get; set; } + public string? OperatorName { get; set; } +} + diff --git a/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs b/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs index bb400575..94a3abe4 100644 --- a/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs +++ b/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs @@ -148,7 +148,8 @@ public class ContractRequestHandler : IRequestHandler>, IRequestHandler, IRequestHandler, - IRequestHandler { + IRequestHandler, + IRequestHandler>> { private readonly IApiClient ApiClient; @@ -181,6 +182,11 @@ public async Task Handle(Commands.AddTransactionFeeForProductToContractC CancellationToken cancellationToken) { return Result.Success(); } + + public async Task>> Handle(Queries.GetRecentContractsQuery request, + CancellationToken cancellationToken) { + return await this.ApiClient.GetRecentContracts(request, cancellationToken); + } } public class OperatorRequestHandler : IRequestHandler>>, diff --git a/EstateManagmentUI.BusinessLogic/Requests/Requests.cs b/EstateManagmentUI.BusinessLogic/Requests/Requests.cs index 341891a5..f492da67 100644 --- a/EstateManagmentUI.BusinessLogic/Requests/Requests.cs +++ b/EstateManagmentUI.BusinessLogic/Requests/Requests.cs @@ -16,6 +16,7 @@ public static class Queries public record GetEstateQuery(CorrelationId CorrelationId, Guid EstateId) : IRequest>; public record GetMerchantsQuery(CorrelationId CorrelationId, Guid EstateId) : IRequest>>; public record GetRecentMerchantsQuery(CorrelationId CorrelationId, Guid EstateId) : IRequest>>; + public record GetRecentContractsQuery(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/TestDataStore.cs b/EstateManagmentUI.BusinessLogic/Services/TestDataStore.cs index 0ddc1463..34a8f5c3 100644 --- a/EstateManagmentUI.BusinessLogic/Services/TestDataStore.cs +++ b/EstateManagmentUI.BusinessLogic/Services/TestDataStore.cs @@ -1,5 +1,6 @@ -using System.Collections.Concurrent; +using EstateManagementUI.BusinessLogic.BackendAPI.DataTransferObjects; using EstateManagementUI.BusinessLogic.Models; +using System.Collections.Concurrent; namespace EstateManagementUI.BusinessLogic.Services; @@ -35,6 +36,28 @@ public EstateModel GetEstate(Guid estateId) RequireCustomTerminalNumber = o.RequireCustomTerminalNumber }).ToList(); } + if (this._contracts.TryGetValue(estateId, out var contractDict)) + { + estate.Contracts = contractDict.Values.Select(o => new EstateContractModel() + { + OperatorId = o.OperatorId, + Name = o.Description, + OperatorName = o.OperatorName, + ContractId = o.ContractId + }).ToList(); + } + if (this._merchants.TryGetValue(estateId, out var merchantDict)) + { + estate.Merchants = merchantDict.Values.Select(o => new EstateMerchantModel() + { + Name = o.MerchantName, + Reference = o.MerchantReference, + MerchantId = o.MerchantId + }).ToList(); + } + + estate.Users = [new EstateUserModel { CreatedDateTime = DateTime.Now, EmailAddress = "estatedevuser1@estate.co.uk", UserId = Guid.Parse("61BFC7DC-FDB4-408A-9CAA-B9F0CF690130") }]; + return estate; } @@ -207,7 +230,7 @@ private void InitializeDefaultData() { EstateId = estateId, EstateName = "Test Estate", - Reference = "Test Estate" + Reference = "Test Estate", }; this.SetEstate(estate);