diff --git a/EstateManagementUI.BlazorServer.Tests/Pages/BaseTest.cs b/EstateManagementUI.BlazorServer.Tests/Pages/BaseTest.cs index 1ec82ac5..7fb9d9c6 100644 --- a/EstateManagementUI.BlazorServer.Tests/Pages/BaseTest.cs +++ b/EstateManagementUI.BlazorServer.Tests/Pages/BaseTest.cs @@ -21,8 +21,7 @@ protected BaseTest() { this._mockPermissionService = new Mock(); this._mockPermissionStore = new Mock(); this._fakeNavigationManager = new FakeNavigationManager(); - this.EstateUIService = new Mock(); - + this._mockPermissionKeyProvider.Setup(x => x.GetKey()).Returns("test-key"); this._mockPermissionService.Setup(x => x.HasPermissionAsync(It.IsAny(), It.IsAny())).ReturnsAsync(true); @@ -34,6 +33,7 @@ protected BaseTest() { this.Services.AddSingleton(this._mockAuthStateProvider.Object); this.Services.AddSingleton(this._mockPermissionStore.Object); this.Services.AddSingleton(this.EstateUIService.Object); + this.Services.AddSingleton(this.OperatorUIService.Object); // Add required permission components that render their children @@ -53,8 +53,8 @@ protected BaseTest() { protected readonly Mock _mockAuthStateProvider; protected readonly Mock _mockPermissionStore; protected readonly FakeNavigationManager _fakeNavigationManager; - protected readonly Mock EstateUIService; - + protected readonly Mock EstateUIService = new Mock(); + protected readonly Mock OperatorUIService = new Mock(); /// /// Minimal test double for NavigationManager. /// Register in DI as NavigationManager so components receive it in tests. diff --git a/EstateManagementUI.BlazorServer.Tests/Pages/Estate/EstateIndexPageTests.cs b/EstateManagementUI.BlazorServer.Tests/Pages/Estate/EstateIndexPageTests.cs index b1cb3081..5c3ebb39 100644 --- a/EstateManagementUI.BlazorServer.Tests/Pages/Estate/EstateIndexPageTests.cs +++ b/EstateManagementUI.BlazorServer.Tests/Pages/Estate/EstateIndexPageTests.cs @@ -25,8 +25,8 @@ public void EstateIndex_RendersCorrectly() ContractCount = 0, RecentContracts = new List(), OperatorCount = 0, - AllOperators = new List(), - AssignedOperators = new List(), + AllOperators = new List(), + AssignedOperators = new List(), MerchantCount = 0, RecentMerchants = new List(), UserCount = 0 @@ -51,8 +51,8 @@ public void EstateIndex_DisplaysEstateDetails() ContractCount = 0, RecentContracts = new List(), OperatorCount = 0, - AllOperators = new List(), - AssignedOperators = new List(), + AllOperators = new List(), + AssignedOperators = new List(), MerchantCount = 0, RecentMerchants = new List(), UserCount = 0 @@ -76,8 +76,8 @@ public void EstateIndex_HasCorrectPageTitle() ContractCount = 0, RecentContracts = new List(), OperatorCount = 0, - AllOperators = new List(), - AssignedOperators = new List(), + AllOperators = new List(), + AssignedOperators = new List(), MerchantCount = 0, RecentMerchants = new List(), UserCount = 0 @@ -135,14 +135,14 @@ public void EstateIndex_AddOperator_Success_UpdatesAssignedOperators() { // Arrange Guid operatorId = Guid.NewGuid(); - OperatorDropDownModel operatorToAdd = new() { + OperatorModels.OperatorDropDownModel operatorToAdd = new() { OperatorId = operatorId, OperatorName = "Test Operator" }; - SetupSuccessfulDataLoadWithOperators(new List { operatorToAdd }); + SetupSuccessfulDataLoadWithOperators(new List { operatorToAdd }); - OperatorModel operatorDetails = new() { + OperatorModels.OperatorModel operatorDetails = new() { OperatorId = operatorId, Name = "Test Operator", RequireCustomMerchantNumber = true, @@ -183,12 +183,12 @@ public void EstateIndex_AddOperator_Failure_ShowsErrorMessage() { // Arrange Guid operatorId = Guid.NewGuid(); - OperatorDropDownModel operatorToAdd = new() { + OperatorModels.OperatorDropDownModel operatorToAdd = new() { OperatorId = operatorId, OperatorName = "Test Operator" }; - SetupSuccessfulDataLoadWithOperators(new List { operatorToAdd }); + SetupSuccessfulDataLoadWithOperators(new List { operatorToAdd }); this.EstateUIService.Setup(e => e.AddOperatorToEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure); @@ -220,14 +220,14 @@ public void EstateIndex_RemoveOperator_Success_RemovesFromList() { // Arrange Guid operatorId = Guid.NewGuid(); - OperatorModel assignedOperator = new() { + OperatorModels.OperatorModel assignedOperator = new() { OperatorId = operatorId, Name = "Test Operator", RequireCustomMerchantNumber = true, RequireCustomTerminalNumber = false }; - SetupSuccessfulDataLoadWithAssignedOperators(new List { assignedOperator }); + SetupSuccessfulDataLoadWithAssignedOperators(new List { assignedOperator }); this.EstateUIService.Setup(e => e.RemoveOperatorFromEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success); @@ -255,14 +255,14 @@ public void EstateIndex_RemoveOperator_Failure_ShowsErrorMessage() { // Arrange Guid operatorId = Guid.NewGuid(); - OperatorModel assignedOperator = new() { + OperatorModels.OperatorModel assignedOperator = new() { OperatorId = operatorId, Name = "Test Operator", RequireCustomMerchantNumber = true, RequireCustomTerminalNumber = false }; - SetupSuccessfulDataLoadWithAssignedOperators(new List { assignedOperator }); + SetupSuccessfulDataLoadWithAssignedOperators(new List { assignedOperator }); this.EstateUIService.Setup(e => e.RemoveOperatorFromEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure(String.Empty)); @@ -377,14 +377,14 @@ public void EstateIndex_DisplaysOperatorRequirements_WhenPresent() { // Arrange Guid operatorId = Guid.NewGuid(); - OperatorModel assignedOperator = new() { + OperatorModels.OperatorModel assignedOperator = new() { OperatorId = operatorId, Name = "Test Operator", RequireCustomMerchantNumber = true, RequireCustomTerminalNumber = true }; - SetupSuccessfulDataLoadWithAssignedOperators(new List { assignedOperator }); + SetupSuccessfulDataLoadWithAssignedOperators(new List { assignedOperator }); IRenderedComponent cut = RenderComponent(); cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); @@ -424,14 +424,14 @@ public void EstateIndex_SuccessMessage_ClearsWhenSwitchingTabs() { // Arrange Guid operatorId = Guid.NewGuid(); - OperatorModel assignedOperator = new() { + OperatorModels.OperatorModel assignedOperator = new() { OperatorId = operatorId, Name = "Test Operator", RequireCustomMerchantNumber = true, RequireCustomTerminalNumber = false }; - SetupSuccessfulDataLoadWithAssignedOperators(new List { assignedOperator }); + SetupSuccessfulDataLoadWithAssignedOperators(new List { assignedOperator }); this.EstateUIService.Setup(e => e.RemoveOperatorFromEstate(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success); @@ -462,8 +462,8 @@ public void EstateIndex_SuccessMessage_ClearsWhenSwitchingTabs() // Helper methods private void SetupSuccessfulDataLoad(List? merchants = null, List? contracts = null, - List? assignedOperators = null, - List? operators = null) + List? assignedOperators = null, + List? operators = null) { BlazorServer.Models.EstateModel estate = new(Guid.NewGuid(), "Test Estate", "EST001"); estate = estate with @@ -471,8 +471,8 @@ private void SetupSuccessfulDataLoad(List? merchants = nul ContractCount = 5, RecentContracts = contracts ?? new List(), OperatorCount = 3, - AllOperators = operators ?? new List(), - AssignedOperators = assignedOperators ?? new List(), + AllOperators = operators ?? new List(), + AssignedOperators = assignedOperators ?? new List(), MerchantCount = 10, RecentMerchants = merchants ?? new List(), UserCount = 2 @@ -480,10 +480,10 @@ private void SetupSuccessfulDataLoad(List? merchants = nul this.EstateUIService.Setup(e => e.LoadEstate(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(estate)); } - private void SetupSuccessfulDataLoadWithOperators(List operators) + private void SetupSuccessfulDataLoadWithOperators(List operators) => SetupSuccessfulDataLoad(operators: operators); - private void SetupSuccessfulDataLoadWithAssignedOperators(List assignedOperators) + private void SetupSuccessfulDataLoadWithAssignedOperators(List assignedOperators) => SetupSuccessfulDataLoad(assignedOperators: assignedOperators); private void SetupSuccessfulDataLoadWithMerchants(List merchants) diff --git a/EstateManagementUI.BlazorServer.Tests/Pages/Operators/OperatorsIndexPageTests.cs b/EstateManagementUI.BlazorServer.Tests/Pages/Operators/OperatorsIndexPageTests.cs index 47ed591a..21a5ca91 100644 --- a/EstateManagementUI.BlazorServer.Tests/Pages/Operators/OperatorsIndexPageTests.cs +++ b/EstateManagementUI.BlazorServer.Tests/Pages/Operators/OperatorsIndexPageTests.cs @@ -1,8 +1,9 @@ using Bunit; using EstateManagementUI.BlazorServer.Components.Permissions; +using EstateManagementUI.BlazorServer.Models; using EstateManagementUI.BlazorServer.Permissions; using EstateManagementUI.BlazorServer.Tests.Pages.FileProcessing; -using EstateManagementUI.BusinessLogic.Models; +using EstateManagementUI.BusinessLogic.BackendAPI.DataTransferObjects; using EstateManagementUI.BusinessLogic.Requests; using MediatR; using Microsoft.AspNetCore.Components; @@ -20,9 +21,9 @@ public class OperatorsIndexPageTests : BaseTest public void OperatorsIndex_RendersCorrectly() { // Arrange - var operators = new List + var operators = new List { - new OperatorModel + new OperatorModels.OperatorModel { OperatorId = Guid.NewGuid(), Name = "Test Operator", @@ -31,7 +32,7 @@ public void OperatorsIndex_RendersCorrectly() } }; - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + this.OperatorUIService.Setup(o => o.GetOperators(It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(operators)); // Act @@ -45,10 +46,10 @@ public void OperatorsIndex_RendersCorrectly() public void OperatorsIndex_WithNoOperators_ShowsEmptyState() { // Arrange - var emptyList = new List(); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + var emptyList = new List(); + this.OperatorUIService.Setup(o => o.GetOperators(It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(emptyList)); - + // Act var cut = RenderComponent(); cut.WaitForState(() => !cut.Markup.Contains("animate-spin")); @@ -61,16 +62,16 @@ public void OperatorsIndex_WithNoOperators_ShowsEmptyState() public void OperatorsIndex_WithOperators_DisplaysOperatorList() { // Arrange - var operators = new List + var operators = new List { - new OperatorModel + new OperatorModels.OperatorModel { OperatorId = Guid.NewGuid(), Name = "Operator 1", RequireCustomMerchantNumber = true, RequireCustomTerminalNumber = false }, - new OperatorModel + new OperatorModels.OperatorModel { OperatorId = Guid.NewGuid(), Name = "Operator 2", @@ -78,10 +79,10 @@ public void OperatorsIndex_WithOperators_DisplaysOperatorList() RequireCustomTerminalNumber = true } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.OperatorUIService.Setup(o => o.GetOperators(It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(operators)); - + // Act var cut = RenderComponent(); cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); @@ -95,9 +96,9 @@ public void OperatorsIndex_WithOperators_DisplaysOperatorList() public void OperatorsIndex_DisplaysCustomNumberRequirements() { // Arrange - var operators = new List + var operators = new List { - new OperatorModel + new OperatorModels.OperatorModel { OperatorId = Guid.NewGuid(), Name = "Test Operator", @@ -105,10 +106,10 @@ public void OperatorsIndex_DisplaysCustomNumberRequirements() RequireCustomTerminalNumber = false } }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.OperatorUIService.Setup(o => o.GetOperators(It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(operators)); - + // Act var cut = RenderComponent(); cut.WaitForState(() => !cut.Markup.Contains("animate-spin"), TimeSpan.FromSeconds(5)); @@ -122,9 +123,9 @@ public void OperatorsIndex_DisplaysCustomNumberRequirements() public void OperatorsIndex_HasCorrectPageTitle() { // Arrange - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new List())); - + this.OperatorUIService.Setup(o => o.GetOperators(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(new List())); + // Act var cut = RenderComponent(); diff --git a/EstateManagementUI.BlazorServer.Tests/Pages/Operators/OperatorsViewPageTests.cs b/EstateManagementUI.BlazorServer.Tests/Pages/Operators/OperatorsViewPageTests.cs index 7a65d7b0..0f5ce3a2 100644 --- a/EstateManagementUI.BlazorServer.Tests/Pages/Operators/OperatorsViewPageTests.cs +++ b/EstateManagementUI.BlazorServer.Tests/Pages/Operators/OperatorsViewPageTests.cs @@ -9,7 +9,6 @@ using Moq; using Shouldly; using SimpleResults; -using OperatorModel = EstateManagementUI.BusinessLogic.Models.OperatorModel; namespace EstateManagementUI.BlazorServer.Tests.Pages.Operators; @@ -20,15 +19,15 @@ public void OperatorsView_RendersCorrectly() { // Arrange var operatorId = Guid.NewGuid(); - var operatorModel = new OperatorModel + var operatorModel = new OperatorModels.OperatorModel { OperatorId = operatorId, Name = "Test Operator" }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.OperatorUIService.Setup(o => o.GetOperator(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(operatorModel)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.OperatorId, operatorId)); @@ -42,15 +41,15 @@ public void OperatorsView_DisplaysOperatorName() { // Arrange var operatorId = Guid.NewGuid(); - var operatorModel = new OperatorModel + var operatorModel = new OperatorModels.OperatorModel { OperatorId = operatorId, Name = "Test Operator" }; - - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) + + this.OperatorUIService.Setup(o => o.GetOperator(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(Result.Success(operatorModel)); - + // Act var cut = RenderComponent(parameters => parameters .Add(p => p.OperatorId, operatorId)); @@ -65,8 +64,8 @@ public void OperatorsView_HasCorrectPageTitle() { // Arrange var operatorId = Guid.NewGuid(); - _mockMediator.Setup(x => x.Send(It.IsAny(), default)) - .ReturnsAsync(Result.Success(new OperatorModel { OperatorId = operatorId })); + this.OperatorUIService.Setup(o => o.GetOperator(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(new OperatorModels.OperatorModel { OperatorId = operatorId })); // Act var cut = RenderComponent(parameters => parameters diff --git a/EstateManagementUI.BlazorServer.Tests/UIServices/OperatorUIServiceTests.cs b/EstateManagementUI.BlazorServer.Tests/UIServices/OperatorUIServiceTests.cs new file mode 100644 index 00000000..7061b8a7 --- /dev/null +++ b/EstateManagementUI.BlazorServer.Tests/UIServices/OperatorUIServiceTests.cs @@ -0,0 +1,191 @@ + using EstateManagementUI.BlazorServer.UIServices; + using EstateManagementUI.BusinessLogic.Requests; + using MediatR; + using Moq; + using Shouldly; + using SimpleResults; + + namespace EstateManagementUI.BlazorServer.Tests.UIServices; + + public class OperatorUIServiceTests + { + private readonly Mock _mockMediator; + private readonly OperatorUIService _service; + + public OperatorUIServiceTests() + { + _mockMediator = new Mock(); + _service = new OperatorUIService(_mockMediator.Object); + } + + [Fact] + public async Task GetOperators_ReturnsMappedList_WhenMediatorSucceeds() + { + // Arrange + var estateId = Guid.NewGuid(); + var correlationId = CorrelationIdHelper.New(); + + var bizOperators = new List + { + new() { OperatorId = Guid.NewGuid(), Name = "OpA", RequireCustomMerchantNumber = true, RequireCustomTerminalNumber = false } + }; + + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(bizOperators)); + + // Act + var result = await _service.GetOperators(correlationId, estateId); + + // Assert + result.IsSuccess.ShouldBeTrue(); + result.Data.ShouldNotBeNull(); + result.Data!.Count.ShouldBe(1); + var mapped = result.Data.First(); + mapped.OperatorId.ShouldBe(bizOperators[0].OperatorId); + mapped.Name.ShouldBe("OpA"); + mapped.RequireCustomMerchantNumber.ShouldBeTrue(); + mapped.RequireCustomTerminalNumber.ShouldBeFalse(); + } + + [Fact] + public async Task GetOperators_ReturnsFailure_WhenMediatorFails() + { + // Arrange + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure("failure")); + + // Act + var result = await _service.GetOperators(CorrelationIdHelper.New(), Guid.NewGuid()); + + // Assert + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task GetOperator_ReturnsMappedModel_WhenMediatorSucceeds() + { + // Arrange + var estateId = Guid.NewGuid(); + var correlationId = CorrelationIdHelper.New(); + var operatorId = Guid.NewGuid(); + + var bizOperator = new EstateManagementUI.BusinessLogic.Models.OperatorModel + { + OperatorId = operatorId, + Name = "OpDetail", + RequireCustomMerchantNumber = false, + RequireCustomTerminalNumber = true + }; + + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(bizOperator)); + + // Act + var result = await _service.GetOperator(correlationId, estateId, operatorId); + + // Assert + result.IsSuccess.ShouldBeTrue(); + var model = result.Data!; + model.OperatorId.ShouldBe(operatorId); + model.Name.ShouldBe("OpDetail"); + model.RequireCustomMerchantNumber.ShouldBeFalse(); + model.RequireCustomTerminalNumber.ShouldBeTrue(); + } + + [Fact] + public async Task GetOperator_ReturnsFailure_WhenMediatorFails() + { + // Arrange + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure("not found")); + + // Act + var result = await _service.GetOperator(CorrelationIdHelper.New(), Guid.NewGuid(), Guid.NewGuid()); + + // Assert + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task UpdateOperator_CallsMediatorWithCorrectCommand_AndReturnsResult() + { + // Arrange + var estateId = Guid.NewGuid(); + var correlationId = CorrelationIdHelper.New(); + var operatorId = Guid.NewGuid(); + + var editModel = new EstateManagementUI.BlazorServer.Models.OperatorModels.EditOperatorModel + { + OperatorName = "UpdatedName", + RequireCustomMerchantNumber = true, + RequireCustomTerminalNumber = false + }; + + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + // Act + var result = await _service.UpdateOperator(correlationId, estateId, operatorId, editModel); + + // Assert + result.IsSuccess.ShouldBeTrue(); + _mockMediator.Verify(m => m.Send(It.Is(c => + c.EstateId == estateId && + c.OperatorId == operatorId && + c.Name == editModel.OperatorName && + c.RequireCustomMerchantNumber == editModel.RequireCustomMerchantNumber && + c.RequireCustomTerminalNumber == editModel.RequireCustomTerminalNumber + ), It.IsAny()), Times.Once); + } + + [Fact] + public async Task CreateOperator_CallsMediatorWithCorrectCommand_AndReturnsResult() + { + // Arrange + var estateId = Guid.NewGuid(); + var correlationId = CorrelationIdHelper.New(); + + var createModel = new EstateManagementUI.BlazorServer.Models.OperatorModels.CreateOperatorModel + { + OperatorName = "NewOperator", + RequireCustomMerchantNumber = false, + RequireCustomTerminalNumber = true + }; + + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + + // Act + var result = await _service.CreateOperator(correlationId, estateId, createModel); + + // Assert + result.IsSuccess.ShouldBeTrue(); + _mockMediator.Verify(m => m.Send(It.Is(c => + c.EstateId == estateId && + c.Name == createModel.OperatorName && + c.RequireCustomMerchantNumber == createModel.RequireCustomMerchantNumber && + c.RequireCustomTerminalNumber == createModel.RequireCustomTerminalNumber + ), It.IsAny()), Times.Once); + } + + [Fact] + public async Task CreateOperator_ReturnsFailure_WhenMediatorFails() + { + // Arrange + _mockMediator + .Setup(m => m.Send(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure); + + // Act + var result = await _service.CreateOperator(CorrelationIdHelper.New(), Guid.NewGuid(), new EstateManagementUI.BlazorServer.Models.OperatorModels.CreateOperatorModel { OperatorName = "x" }); + + // Assert + result.IsFailed.ShouldBeTrue(); + } + } \ No newline at end of file diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Contracts/New.razor.cs b/EstateManagementUI.BlazorServer/Components/Pages/Contracts/New.razor.cs index 6657c060..bc3c1e73 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Contracts/New.razor.cs +++ b/EstateManagementUI.BlazorServer/Components/Pages/Contracts/New.razor.cs @@ -13,7 +13,7 @@ public partial class New private bool isLoadingOperators = true; private bool hasPermission = false; private string? errorMessage; - private List? operators; + private List? operators; protected override async Task OnAfterRenderAsync(bool firstRender) { diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor b/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor index 61ea565d..e9726988 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor @@ -4,7 +4,7 @@ @inherits AuthorizedComponentBase @rendermode InteractiveServer @inject NavigationManager NavigationManager -@inject IEstateUIService EstateUIService +@inject IEstateUIService EstateUiService Estate Management diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor.cs b/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor.cs index 26b2a586..38dcb775 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor.cs +++ b/EstateManagementUI.BlazorServer/Components/Pages/Estate/Index.razor.cs @@ -23,17 +23,13 @@ public Index() { } protected override async Task OnAfterRenderAsync(bool firstRender) { - if (!firstRender) { + if (!firstRender) + { return; } - - Result authResult = await RequirePermission(PermissionSection.Estate, PermissionFunction.View); - if (authResult.IsFailed) - return; - - Result result = await this.LoadEstateData(); - if (result.IsFailed) { - this.NavigationManager.NavigateToErrorPage(); + Result result = await OnAfterRender(PermissionSection.Operator, PermissionFunction.Edit, this.LoadEstateData); + if (result.IsFailed) + { return; } @@ -44,7 +40,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { private async Task LoadEstateData() { CorrelationId correlationId = new(Guid.NewGuid()); Guid estateId = await this.GetEstateId(); - Result result = await this.EstateUIService.LoadEstate(correlationId, estateId); + Result result = await this.EstateUiService.LoadEstate(correlationId, estateId); if (result.IsFailed) { return ResultHelpers.CreateFailure(result); } @@ -62,7 +58,7 @@ private async Task AddOperatorToEstate() { CorrelationId correlationId = new CorrelationId(Guid.NewGuid()); Guid estateId = await this.GetEstateId(); - var result = await this.EstateUIService.AddOperatorToEstate(correlationId, estateId, this.selectedOperatorId); + var result = await this.EstateUiService.AddOperatorToEstate(correlationId, estateId, this.selectedOperatorId); if (result.IsSuccess) { successMessage = "Operator added successfully"; @@ -88,7 +84,7 @@ private async Task RemoveOperatorFromEstate(Guid operatorId) { try { CorrelationId correlationId = new CorrelationId(Guid.NewGuid()); Guid estateId = await this.GetEstateId(); - var result = await this.EstateUIService.RemoveOperatorFromEstate(correlationId, estateId, operatorId); + var result = await this.EstateUiService.RemoveOperatorFromEstate(correlationId, estateId, operatorId); if (result.IsSuccess) { successMessage = "Operator removed successfully"; diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor.cs b/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor.cs index 61034e37..ded6216f 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor.cs +++ b/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor.cs @@ -29,11 +29,11 @@ public partial class Edit private MerchantEditModel merchantEditModel = new(); // Operators - private List? availableOperators; + private List? availableOperators; private List assignedOperators = new(); private bool showAddOperator = false; private string? selectedOperatorId; - private OperatorModel? selectedOperator; + private OperatorModels.OperatorModel? selectedOperator; private string? merchantNumber; private string? terminalNumber; private string? merchantNumberError; diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Operators/Edit.razor b/EstateManagementUI.BlazorServer/Components/Pages/Operators/Edit.razor index be8bf2dc..fb26ccab 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Operators/Edit.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Operators/Edit.razor @@ -3,8 +3,9 @@ @using System.ComponentModel.DataAnnotations @using EstateManagementUI.BlazorServer.Factories @using EstateManagementUI.BlazorServer.Permissions +@using EstateManagementUI.BlazorServer.UIServices @using EstateManagementUI.BusinessLogic.Requests -@inject IMediator Mediator +@inject IOperatorUIService OperatorUiService @inherits AuthorizedComponentBase @inject NavigationManager NavigationManager @inject IPermissionService PermissionService diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Operators/Edit.razor.cs b/EstateManagementUI.BlazorServer/Components/Pages/Operators/Edit.razor.cs index 7532e308..4dff6aa6 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Operators/Edit.razor.cs +++ b/EstateManagementUI.BlazorServer/Components/Pages/Operators/Edit.razor.cs @@ -1,10 +1,12 @@ using EstateManagementUI.BlazorServer.Factories; +using EstateManagementUI.BlazorServer.Models; using EstateManagementUI.BlazorServer.Permissions; using EstateManagementUI.BusinessLogic.Requests; using MediatR; using Microsoft.AspNetCore.Components; +using Shared.Results; +using SimpleResults; using System.ComponentModel.DataAnnotations; -using EstateManagementUI.BlazorServer.Models; namespace EstateManagementUI.BlazorServer.Components.Pages.Operators { @@ -13,121 +15,83 @@ public partial class Edit [Parameter] public Guid OperatorId { get; set; } - private OperatorModel? operatorModel; - private EditOperatorModel model = new(); + private OperatorModels.OperatorModel? operatorModel; + private OperatorModels.EditOperatorModel model = new(); private bool isLoading = true; private bool isSaving = false; - private bool hasPermission = false; - private string? errorMessage; - private string? successMessage; - + protected override async Task OnAfterRenderAsync(bool firstRender) { if (!firstRender) { - await base.OnAfterRenderAsync(firstRender); + return; + } + Result result = await OnAfterRender(PermissionSection.Operator, PermissionFunction.Edit, this.LoadOperator); + if (result.IsFailed) + { return; } - await RequirePermission(PermissionSection.Operator, PermissionFunction.Edit); - await LoadOperator(); + isLoading = false; + this.StateHasChanged(); } - private async Task LoadOperator() + private async Task LoadOperator() { - try - { - isLoading = true; - var correlationId = new CorrelationId(Guid.NewGuid()); - var estateId = await GetEstateId(); - - var result = await Mediator.Send(new OperatorQueries.GetOperatorQuery(correlationId, estateId, OperatorId)); + var correlationId = new CorrelationId(Guid.NewGuid()); + var estateId = await this.GetEstateId(); - if (result.IsSuccess && result.Data != null) - { - operatorModel = ModelFactory.ConvertFrom(result.Data); + var result = await this.OperatorUiService.GetOperator(correlationId, estateId, this.OperatorId); - // Initialize model with current values - model = new EditOperatorModel - { - OperatorName = operatorModel.Name, - RequireCustomMerchantNumber = operatorModel.RequireCustomMerchantNumber, - RequireCustomTerminalNumber = operatorModel.RequireCustomTerminalNumber - }; - } - } - finally + if (result.IsFailed) { - isLoading = false; - this.StateHasChanged(); + return ResultHelpers.CreateFailure(result); } + + operatorModel = result.Data; + + // Initialize model with current values + model = new OperatorModels.EditOperatorModel + { + OperatorName = operatorModel.Name, + RequireCustomMerchantNumber = operatorModel.RequireCustomMerchantNumber, + RequireCustomTerminalNumber = operatorModel.RequireCustomTerminalNumber + }; + + return Result.Success(); } + private async Task HandleSubmit() { isSaving = true; ClearMessages(); - try - { - var correlationId = new CorrelationId(Guid.NewGuid()); - var estateId = await this.GetEstateId(); + var correlationId = new CorrelationId(Guid.NewGuid()); + var estateId = await this.GetEstateId(); - var command = new OperatorCommands.UpdateOperatorCommand( - correlationId, - estateId, - OperatorId, - model.OperatorName!, - model.RequireCustomMerchantNumber, - model.RequireCustomTerminalNumber - ); - - var result = await Mediator.Send(command); - - if (result.IsSuccess) - { - successMessage = "Operator updated successfully"; - StateHasChanged(); + var result = await this.OperatorUiService.UpdateOperator(correlationId, estateId, this.OperatorId, this.model); + if (result.IsSuccess) + { + successMessage = "Operator updated successfully"; + StateHasChanged(); - // Small delay so user sees confirmation (adjust duration as needed) - await this.WaitOnUIRefresh(); + // Small delay so user sees confirmation (adjust duration as needed) + await this.WaitOnUIRefresh(); - NavigationManager.NavigateTo("/operators"); - } - else - { - errorMessage = result.Message ?? "Failed to update operator"; - } + NavigationManager.NavigateTo("/operators"); } - catch (Exception ex) + else { - errorMessage = $"An error occurred: {ex.Message}"; + errorMessage = "Failed to update operator"; } - finally - { - isSaving = false; - } - } - - private void ClearMessages() - { - errorMessage = null; - successMessage = null; + + isSaving = false; } - + private void BackToList() { NavigationManager.NavigateTo("/operators"); } - - public class EditOperatorModel - { - [Required(ErrorMessage = "Operator name is required")] - public string? OperatorName { get; set; } - - public bool RequireCustomMerchantNumber { get; set; } - - public bool RequireCustomTerminalNumber { get; set; } - } } } diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Operators/Index.razor b/EstateManagementUI.BlazorServer/Components/Pages/Operators/Index.razor index acef46bc..71b51c7a 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Operators/Index.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Operators/Index.razor @@ -2,8 +2,9 @@ @using EstateManagementUI.BlazorServer.Factories @rendermode InteractiveServer @using EstateManagementUI.BlazorServer.Permissions +@using EstateManagementUI.BlazorServer.UIServices @using EstateManagementUI.BusinessLogic.Requests -@inject IMediator Mediator +@inject IOperatorUIService OperatorUiService @inherits AuthorizedComponentBase @inject NavigationManager NavigationManager @inject IPermissionKeyProvider PermissionKeyProvider diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Operators/Index.razor.cs b/EstateManagementUI.BlazorServer/Components/Pages/Operators/Index.razor.cs index 62ab5a7f..8b44376a 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Operators/Index.razor.cs +++ b/EstateManagementUI.BlazorServer/Components/Pages/Operators/Index.razor.cs @@ -1,40 +1,47 @@ -using EstateManagementUI.BlazorServer.Factories; +using EstateManagementUI.BlazorServer.Common; using EstateManagementUI.BlazorServer.Models; using EstateManagementUI.BlazorServer.Permissions; +using EstateManagementUI.BusinessLogic.Models; using EstateManagementUI.BusinessLogic.Requests; +using Shared.Results; +using SimpleResults; namespace EstateManagementUI.BlazorServer.Components.Pages.Operators { public partial class Index { private bool isLoading = true; - private List operators; + private List operators; protected override async Task OnAfterRenderAsync(bool firstRender) { if (!firstRender) { - await base.OnAfterRenderAsync(firstRender); return; } + Result result = await OnAfterRender(PermissionSection.Operator, PermissionFunction.List, this.LoadOperators); + if (result.IsFailed) { + return; + } + + isLoading = false; + this.StateHasChanged(); + } - try { - await RequirePermission(PermissionSection.Operator, PermissionFunction.List); + private async Task LoadOperators() + { + var correlationId = new CorrelationId(Guid.NewGuid()); + var estateId = await this.GetEstateId(); - var correlationId = new CorrelationId(Guid.NewGuid()); - var estateId = await this.GetEstateId(); + Result> result = await this.OperatorUiService.GetOperators(correlationId, estateId); - var result = await Mediator.Send(new OperatorQueries.GetOperatorsQuery(correlationId, estateId)); - if (result.IsSuccess) - { - operators = ModelFactory.ConvertFrom(result.Data); - } - } - finally - { - isLoading = false; - this.StateHasChanged(); + if (result.IsFailed) { + return ResultHelpers.CreateFailure(result); } + + operators = result.Data; + + return Result.Success(); } } } diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Operators/New.razor b/EstateManagementUI.BlazorServer/Components/Pages/Operators/New.razor index b71350bc..b60c6d6f 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Operators/New.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Operators/New.razor @@ -2,8 +2,9 @@ @rendermode InteractiveServer @using System.ComponentModel.DataAnnotations @using EstateManagementUI.BlazorServer.Permissions +@using EstateManagementUI.BlazorServer.UIServices @using EstateManagementUI.BusinessLogic.Requests -@inject IMediator Mediator +@inject IOperatorUIService OperatorUiService @inherits AuthorizedComponentBase @inject NavigationManager NavigationManager @inject IPermissionService PermissionService diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Operators/New.razor.cs b/EstateManagementUI.BlazorServer/Components/Pages/Operators/New.razor.cs index 5b7974ee..0d5fc301 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Operators/New.razor.cs +++ b/EstateManagementUI.BlazorServer/Components/Pages/Operators/New.razor.cs @@ -1,73 +1,56 @@ using EstateManagementUI.BlazorServer.Permissions; using EstateManagementUI.BusinessLogic.Requests; using System.ComponentModel.DataAnnotations; +using EstateManagementUI.BlazorServer.Models; +using SimpleResults; namespace EstateManagementUI.BlazorServer.Components.Pages.Operators { public partial class New { - private CreateOperatorModel model = new(); + private OperatorModels.CreateOperatorModel model = new(); private bool isSaving = false; - private string? errorMessage; - private string? successMessage; protected override async Task OnAfterRenderAsync(bool firstRender) { if (!firstRender) { - await base.OnAfterRenderAsync(firstRender); + return; + } + Result result = await OnAfterRender(PermissionSection.Operator, PermissionFunction.Create); + if (result.IsFailed) + { return; } - await RequirePermission(PermissionSection.Operator, PermissionFunction.Create); + this.StateHasChanged(); } private async Task HandleSubmit() { isSaving = true; - errorMessage = null; - - try - { - var correlationId = new CorrelationId(Guid.NewGuid()); - var estateId = await this.GetEstateId(); - - // Create operator - var createCommand = new OperatorCommands.CreateOperatorCommand( - correlationId, - estateId, - model.OperatorName!, - model.RequireCustomMerchantNumber, - model.RequireCustomTerminalNumber - ); + ClearMessages(); - var createResult = await Mediator.Send(createCommand); + var correlationId = new CorrelationId(Guid.NewGuid()); + var estateId = await this.GetEstateId(); - if (!createResult.IsSuccess) - { - errorMessage = createResult.Message ?? "Failed to create operator"; - return; - } - - // Show success message briefly before navigating away - successMessage = "Operator created successfully."; + var result = await this.OperatorUiService.CreateOperator(correlationId, estateId, this.model); + if (result.IsSuccess) + { + successMessage = "Operator created successfully"; StateHasChanged(); // Small delay so user sees confirmation (adjust duration as needed) await this.WaitOnUIRefresh(); - - // Navigate to operators list with success NavigationManager.NavigateTo("/operators"); } - catch (Exception ex) - { - errorMessage = $"An error occurred: {ex.Message}"; - } - finally + else { - isSaving = false; + errorMessage = "Failed to create operator"; } + + isSaving = false; } private void Cancel() @@ -75,14 +58,6 @@ private void Cancel() NavigationManager.NavigateTo("/operators"); } - public class CreateOperatorModel - { - [Required(ErrorMessage = "Operator name is required")] - public string? OperatorName { get; set; } - - public bool RequireCustomMerchantNumber { get; set; } - - public bool RequireCustomTerminalNumber { get; set; } - } + } } diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Operators/View.razor b/EstateManagementUI.BlazorServer/Components/Pages/Operators/View.razor index 9a09fdfe..f077fcc2 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Operators/View.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Operators/View.razor @@ -1,8 +1,9 @@ @page "/operators/{OperatorId:guid}" @using EstateManagementUI.BlazorServer.Factories +@using EstateManagementUI.BlazorServer.UIServices @using EstateManagementUI.BusinessLogic.Requests @rendermode InteractiveServer -@inject IMediator Mediator +@inject IOperatorUIService OperatorUiService @inherits AuthorizedComponentBase @inject NavigationManager NavigationManager diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Operators/View.razor.cs b/EstateManagementUI.BlazorServer/Components/Pages/Operators/View.razor.cs index 230bf6d2..963ff381 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Operators/View.razor.cs +++ b/EstateManagementUI.BlazorServer/Components/Pages/Operators/View.razor.cs @@ -1,8 +1,11 @@ -using EstateManagementUI.BlazorServer.Factories; +using EstateManagementUI.BlazorServer.Common; +using EstateManagementUI.BlazorServer.Factories; using EstateManagementUI.BlazorServer.Models; using EstateManagementUI.BlazorServer.Permissions; using EstateManagementUI.BusinessLogic.Requests; using Microsoft.AspNetCore.Components; +using Shared.Results; +using SimpleResults; namespace EstateManagementUI.BlazorServer.Components.Pages.Operators { @@ -11,42 +14,35 @@ public partial class View [Parameter] public Guid OperatorId { get; set; } - private OperatorModel? operatorModel; + private OperatorModels.OperatorModel? operatorModel; private bool isLoading = true; protected override async Task OnAfterRenderAsync(bool firstRender) { - if (!firstRender) - { - await base.OnAfterRenderAsync(firstRender); + if (!firstRender) { return; } - - await RequirePermission(PermissionSection.Operator, PermissionFunction.View); - - await LoadOperator(); + Result result = await OnAfterRender(PermissionSection.Operator, PermissionFunction.View, this.LoadOperator); + if (result.IsFailed) { + return; + } + isLoading = false; + this.StateHasChanged(); } + + private async Task LoadOperator() { + var correlationId = new CorrelationId(Guid.NewGuid()); + var estateId = await this.GetEstateId(); - private async Task LoadOperator() - { - try - { - isLoading = true; - var correlationId = new CorrelationId(Guid.NewGuid()); - var estateId = await this.GetEstateId(); - - var result = await Mediator.Send(new OperatorQueries.GetOperatorQuery(correlationId, estateId, OperatorId)); - - if (result.IsSuccess && result.Data != null) - { - operatorModel = ModelFactory.ConvertFrom(result.Data); - } - } - finally - { - isLoading = false; - this.StateHasChanged(); + var result = await this.OperatorUiService.GetOperator(correlationId, estateId, this.OperatorId); + + if (result.IsFailed) { + return ResultHelpers.CreateFailure(result); } + + operatorModel = result.Data; + + return Result.Success(); } private void BackToList() diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionDetail.razor b/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionDetail.razor index c385b937..5df2f506 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionDetail.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionDetail.razor @@ -8,8 +8,8 @@ @using ContractProductModel = EstateManagementUI.BlazorServer.Models.ContractProductModel @using MerchantDropDownModel = EstateManagementUI.BlazorServer.Models.MerchantDropDownModel @using MerchantModel = EstateManagementUI.BlazorServer.Models.MerchantModel -@using OperatorDropDownModel = EstateManagementUI.BlazorServer.Models.OperatorDropDownModel -@using OperatorModel = EstateManagementUI.BlazorServer.Models.OperatorModel +@using OperatorDropDownModel = EstateManagementUI.BlazorServer.Models.OperatorModels.OperatorDropDownModel +@using OperatorModel = EstateManagementUI.BlazorServer.Models.OperatorModels.OperatorModel @using TransactionDetailModel = EstateManagementUI.BlazorServer.Models.TransactionDetailModel @inject IMediator Mediator @inject NavigationManager Navigation diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionSummaryMerchant.razor b/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionSummaryMerchant.razor index cbc7ae0f..464d877c 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionSummaryMerchant.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionSummaryMerchant.razor @@ -4,8 +4,8 @@ @using EstateManagementUI.BusinessLogic.Requests @using MerchantDropDownModel = EstateManagementUI.BlazorServer.Models.MerchantDropDownModel @using MerchantTransactionSummaryModel = EstateManagementUI.BlazorServer.Models.MerchantTransactionSummaryModel -@using OperatorDropDownModel = EstateManagementUI.BlazorServer.Models.OperatorDropDownModel -@using OperatorModel = EstateManagementUI.BlazorServer.Models.OperatorModel +@using OperatorDropDownModel = EstateManagementUI.BlazorServer.Models.OperatorModels.OperatorDropDownModel +@using OperatorModel = EstateManagementUI.BlazorServer.Models.OperatorModels.OperatorModel @rendermode InteractiveServer @inject IMediator Mediator @inject NavigationManager Navigation diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionSummaryOperator.razor b/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionSummaryOperator.razor index 2ff725de..1d0aab0e 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionSummaryOperator.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Reporting/TransactionSummaryOperator.razor @@ -3,8 +3,8 @@ @using EstateManagementUI.BusinessLogic.Models @using EstateManagementUI.BusinessLogic.Requests @using MerchantDropDownModel = EstateManagementUI.BlazorServer.Models.MerchantDropDownModel -@using OperatorDropDownModel = EstateManagementUI.BlazorServer.Models.OperatorDropDownModel -@using OperatorModel = EstateManagementUI.BlazorServer.Models.OperatorModel +@using OperatorDropDownModel = EstateManagementUI.BlazorServer.Models.OperatorModels.OperatorDropDownModel +@using OperatorModel = EstateManagementUI.BlazorServer.Models.OperatorModels.OperatorModel @using OperatorTransactionSummaryModel = EstateManagementUI.BlazorServer.Models.OperatorTransactionSummaryModel @rendermode InteractiveServer @inject IMediator Mediator diff --git a/EstateManagementUI.BlazorServer/Components/Permissions/AuthorizedComponentBase.cs b/EstateManagementUI.BlazorServer/Components/Permissions/AuthorizedComponentBase.cs index 0f4c45b5..8f7ded6d 100644 --- a/EstateManagementUI.BlazorServer/Components/Permissions/AuthorizedComponentBase.cs +++ b/EstateManagementUI.BlazorServer/Components/Permissions/AuthorizedComponentBase.cs @@ -72,4 +72,28 @@ protected async Task GetEstateId() { } return estateIdResult.Data; } + + protected async Task OnAfterRender(PermissionSection section, + PermissionFunction function) => + await OnAfterRender(section, function, null); + + protected async Task OnAfterRender(PermissionSection section, + PermissionFunction function, + Func>? loadFunc) + { + Result authResult = await RequirePermission(section, function); + if (authResult.IsFailed) + return Result.Failure(); + + if (loadFunc == null) + return Result.Success(); + + Result result = await loadFunc(); + if (result.IsFailed) + { + this.NavigationManager.NavigateToErrorPage(); + return Result.Failure(); + } + return Result.Success(); + } } \ No newline at end of file diff --git a/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs b/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs index 36aa666e..0dde29f4 100644 --- a/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs +++ b/EstateManagementUI.BlazorServer/Factories/ModelFactory.cs @@ -2,7 +2,7 @@ using TransactionProcessor.DataTransferObjects.Responses.Contract; using ComparisonDateModel = EstateManagementUI.BlazorServer.Models.ComparisonDateModel; using ContractDropDownModel = EstateManagementUI.BlazorServer.Models.ContractDropDownModel; -using OperatorDropDownModel = EstateManagementUI.BlazorServer.Models.OperatorDropDownModel; +using OperatorDropDownModel = EstateManagementUI.BlazorServer.Models.OperatorModels.OperatorDropDownModel; using ContractModel = EstateManagementUI.BlazorServer.Models.ContractModel; using ContractProductModel = EstateManagementUI.BlazorServer.Models.ContractProductModel; using ContractProductTransactionFeeModel = EstateManagementUI.BlazorServer.Models.ContractProductTransactionFeeModel; @@ -18,7 +18,7 @@ using MerchantOperatorModel = EstateManagementUI.BlazorServer.Models.MerchantOperatorModel; using MerchantSettlementHistoryModel = EstateManagementUI.BlazorServer.Models.MerchantSettlementHistoryModel; using MerchantTransactionSummaryModel = EstateManagementUI.BlazorServer.Models.MerchantTransactionSummaryModel; -using OperatorModel = EstateManagementUI.BlazorServer.Models.OperatorModel; +using OperatorModel = EstateManagementUI.BlazorServer.Models.OperatorModels.OperatorModel; using OperatorTransactionSummaryModel = EstateManagementUI.BlazorServer.Models.OperatorTransactionSummaryModel; using ProductPerformanceModel = EstateManagementUI.BlazorServer.Models.ProductPerformanceModel; using RecentContractModel = EstateManagementUI.BlazorServer.Models.RecentContractModel; diff --git a/EstateManagementUI.BlazorServer/Models/Models.cs b/EstateManagementUI.BlazorServer/Models/Models.cs index 282e18e7..a37952ae 100644 --- a/EstateManagementUI.BlazorServer/Models/Models.cs +++ b/EstateManagementUI.BlazorServer/Models/Models.cs @@ -9,8 +9,8 @@ public record EstateModel(Guid EstateId, string? EstateName, string? Reference) public Int32 UserCount { get; init; } public List RecentMerchants { get; init; } public List RecentContracts { get; init; } - public List AssignedOperators { get; init; } - public List AllOperators { get; init; } + public List AssignedOperators { get; init; } + public List AllOperators { get; init; } } @@ -36,13 +36,6 @@ public class MerchantModel } // Operator Models -public class OperatorModel -{ - public Guid OperatorId { get; set; } - public string? Name { get; set; } - public bool RequireCustomMerchantNumber { get; set; } - public bool RequireCustomTerminalNumber { get; set; } -} public class ContractDropDownModel { @@ -51,12 +44,6 @@ public class ContractDropDownModel public string? OperatorName { get; set; } } -public class OperatorDropDownModel -{ - public Guid OperatorId { get; set; } - public string? OperatorName { get; set; } -} - // Contract Models public class ContractModel { diff --git a/EstateManagementUI.BlazorServer/Models/OperatorModels.cs b/EstateManagementUI.BlazorServer/Models/OperatorModels.cs new file mode 100644 index 00000000..5a1a6933 --- /dev/null +++ b/EstateManagementUI.BlazorServer/Models/OperatorModels.cs @@ -0,0 +1,38 @@ +using System.ComponentModel.DataAnnotations; + +namespace EstateManagementUI.BlazorServer.Models; + +public record OperatorModels { + public record EditOperatorModel { + [Required(ErrorMessage = "Operator name is required")] + public string? OperatorName { get; set; } + + public bool RequireCustomMerchantNumber { get; set; } + + public bool RequireCustomTerminalNumber { get; set; } + } + + public record OperatorModel + { + public Guid OperatorId { get; set; } + public string? Name { get; set; } + public bool RequireCustomMerchantNumber { get; set; } + public bool RequireCustomTerminalNumber { get; set; } + } + + public class OperatorDropDownModel + { + public Guid OperatorId { get; set; } + public string? OperatorName { get; set; } + } + + public class CreateOperatorModel + { + [Required(ErrorMessage = "Operator name is required")] + public string? OperatorName { get; set; } + + public bool RequireCustomMerchantNumber { get; set; } + + public bool RequireCustomTerminalNumber { get; set; } + } +} \ No newline at end of file diff --git a/EstateManagementUI.BlazorServer/Program.cs b/EstateManagementUI.BlazorServer/Program.cs index e12b192e..737d7a5d 100644 --- a/EstateManagementUI.BlazorServer/Program.cs +++ b/EstateManagementUI.BlazorServer/Program.cs @@ -242,6 +242,7 @@ builder.Services.RegisterHttpClient(); builder.Services.AddSingleton(); + builder.Services.AddSingleton(); } builder.Host.UseWindowsService(); diff --git a/EstateManagementUI.BlazorServer/UIServices/EstateUIService.cs b/EstateManagementUI.BlazorServer/UIServices/EstateUIService.cs index 396de2da..4dff5ce1 100644 --- a/EstateManagementUI.BlazorServer/UIServices/EstateUIService.cs +++ b/EstateManagementUI.BlazorServer/UIServices/EstateUIService.cs @@ -5,97 +5,96 @@ using Shared.Results; using SimpleResults; -namespace EstateManagementUI.BlazorServer.UIServices +namespace EstateManagementUI.BlazorServer.UIServices; + +public interface IEstateUIService { - public interface IEstateUIService - { - Task> LoadEstate(CorrelationId correlationId, Guid estateId); + Task> LoadEstate(CorrelationId correlationId, Guid estateId); + + Task AddOperatorToEstate(CorrelationId correlationId, Guid estateId, String selectedOperatorId); + Task RemoveOperatorFromEstate(CorrelationId correlationId, Guid estateId, Guid selectedOperatorId); +} + +public class EstateUIService : IEstateUIService +{ + private readonly IMediator Mediator; - Task AddOperatorToEstate(CorrelationId correlationId, Guid estateId, String selectedOperatorId); - Task RemoveOperatorFromEstate(CorrelationId correlationId, Guid estateId, Guid selectedOperatorId); + public EstateUIService(IMediator mediator) + { + this.Mediator = mediator; } - public class EstateUIService : IEstateUIService + public async Task> LoadEstate(CorrelationId correlationId, + Guid estateId) { - private readonly IMediator Mediator; + Task> estateTask = Mediator.Send(new EstateQueries.GetEstateQuery(correlationId, estateId)); + Task>> merchantTask = Mediator.Send(new MerchantQueries.GetRecentMerchantsQuery(correlationId, estateId)); + Task>> contractsTask = Mediator.Send(new ContractQueries.GetRecentContractsQuery(correlationId, estateId)); + Task>> assignedOperatorsTask = Mediator.Send(new EstateQueries.GetAssignedOperatorsQuery(correlationId, estateId)); + Task>> allOperatorsTask = Mediator.Send(new OperatorQueries.GetOperatorsForDropDownQuery(correlationId, estateId)); - public EstateUIService(IMediator mediator) - { - this.Mediator = mediator; - } + await Task.WhenAll(estateTask, merchantTask, contractsTask, assignedOperatorsTask, allOperatorsTask); - public async Task> LoadEstate(CorrelationId correlationId, - Guid estateId) - { - Task> estateTask = Mediator.Send(new EstateQueries.GetEstateQuery(correlationId, estateId)); - Task>> merchantTask = Mediator.Send(new MerchantQueries.GetRecentMerchantsQuery(correlationId, estateId)); - Task>> contractsTask = Mediator.Send(new ContractQueries.GetRecentContractsQuery(correlationId, estateId)); - Task>> assignedOperatorsTask = Mediator.Send(new EstateQueries.GetAssignedOperatorsQuery(correlationId, estateId)); - Task>> allOperatorsTask = Mediator.Send(new OperatorQueries.GetOperatorsForDropDownQuery(correlationId, estateId)); - - await Task.WhenAll(estateTask, merchantTask, contractsTask, assignedOperatorsTask, allOperatorsTask); - - if (estateTask.Result.IsFailed) - return ResultHelpers.CreateFailure(estateTask.Result); - - if (merchantTask.Result.IsFailed) - return ResultHelpers.CreateFailure(merchantTask.Result); - var merchants = ModelFactory.ConvertFrom(merchantTask.Result.Data); - - if (contractsTask.Result.IsFailed) - return ResultHelpers.CreateFailure(contractsTask.Result); - var contracts = ModelFactory.ConvertFrom(contractsTask.Result.Data); - - if (assignedOperatorsTask.Result.IsFailed) - return ResultHelpers.CreateFailure(assignedOperatorsTask.Result); - var assignedOperators = ModelFactory.ConvertFrom(assignedOperatorsTask.Result.Data); - - if (allOperatorsTask.Result.IsFailed) - return ResultHelpers.CreateFailure(allOperatorsTask.Result); - - List unfiltered = ModelFactory.ConvertFrom(allOperatorsTask.Result.Data); - var availableOperators = unfiltered.Where(u => !assignedOperators.Any(a => a.OperatorId == u.OperatorId)).Select(u => new OperatorDropDownModel { OperatorId = u.OperatorId, OperatorName = u.OperatorName }).ToList(); - var estateModel = estateTask.Result.Data; - var resultModel = new EstateModel(estateModel.EstateId, estateModel.EstateName, estateModel.Reference); - resultModel = resultModel with - { - MerchantCount = estateModel.Merchants.Count, - AllOperators = availableOperators, - AssignedOperators = assignedOperators, - ContractCount = estateModel.Contracts.Count, - RecentContracts = contracts, - RecentMerchants = merchants, - UserCount = estateModel.Users.Count, - }; - - return Result.Success(resultModel); - } - - public async Task AddOperatorToEstate(CorrelationId correlationId, - Guid estateId, String selectedOperatorId) - { - var operatorId = Guid.Parse(selectedOperatorId); + if (estateTask.Result.IsFailed) + return ResultHelpers.CreateFailure(estateTask.Result); + + if (merchantTask.Result.IsFailed) + return ResultHelpers.CreateFailure(merchantTask.Result); + var merchants = ModelFactory.ConvertFrom(merchantTask.Result.Data); - var command = new EstateCommands.AddOperatorToEstateCommand(correlationId, estateId, operatorId); + if (contractsTask.Result.IsFailed) + return ResultHelpers.CreateFailure(contractsTask.Result); + var contracts = ModelFactory.ConvertFrom(contractsTask.Result.Data); - var result = await Mediator.Send(command); - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); + if (assignedOperatorsTask.Result.IsFailed) + return ResultHelpers.CreateFailure(assignedOperatorsTask.Result); + var assignedOperators = ModelFactory.ConvertFrom(assignedOperatorsTask.Result.Data); - return Result.Success(); - } + if (allOperatorsTask.Result.IsFailed) + return ResultHelpers.CreateFailure(allOperatorsTask.Result); - public async Task RemoveOperatorFromEstate(CorrelationId correlationId, - Guid estateId, - Guid operatorId) + List unfiltered = ModelFactory.ConvertFrom(allOperatorsTask.Result.Data); + var availableOperators = unfiltered.Where(u => !assignedOperators.Any(a => a.OperatorId == u.OperatorId)).Select(u => new OperatorModels.OperatorDropDownModel { OperatorId = u.OperatorId, OperatorName = u.OperatorName }).ToList(); + var estateModel = estateTask.Result.Data; + var resultModel = new EstateModel(estateModel.EstateId, estateModel.EstateName, estateModel.Reference); + resultModel = resultModel with { - var command = new EstateCommands.RemoveOperatorFromEstateCommand(correlationId, estateId, operatorId); + MerchantCount = estateModel.Merchants.Count, + AllOperators = availableOperators, + AssignedOperators = assignedOperators, + ContractCount = estateModel.Contracts.Count, + RecentContracts = contracts, + RecentMerchants = merchants, + UserCount = estateModel.Users.Count, + }; + + return Result.Success(resultModel); + } + + public async Task AddOperatorToEstate(CorrelationId correlationId, + Guid estateId, String selectedOperatorId) + { + var operatorId = Guid.Parse(selectedOperatorId); + + var command = new EstateCommands.AddOperatorToEstateCommand(correlationId, estateId, operatorId); + + var result = await Mediator.Send(command); + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); + + return Result.Success(); + } + + public async Task RemoveOperatorFromEstate(CorrelationId correlationId, + Guid estateId, + Guid operatorId) + { + var command = new EstateCommands.RemoveOperatorFromEstateCommand(correlationId, estateId, operatorId); - var result = await Mediator.Send(command); - if (result.IsFailed) - return ResultHelpers.CreateFailure(result); + var result = await Mediator.Send(command); + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); - return Result.Success(); - } + return Result.Success(); } } \ No newline at end of file diff --git a/EstateManagementUI.BlazorServer/UIServices/OperatorUIService.cs b/EstateManagementUI.BlazorServer/UIServices/OperatorUIService.cs new file mode 100644 index 00000000..359fb63d --- /dev/null +++ b/EstateManagementUI.BlazorServer/UIServices/OperatorUIService.cs @@ -0,0 +1,69 @@ +using EstateManagementUI.BlazorServer.Factories; +using EstateManagementUI.BlazorServer.Models; +using EstateManagementUI.BusinessLogic.Requests; +using MediatR; +using Shared.Results; +using SimpleResults; +using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; + +namespace EstateManagementUI.BlazorServer.UIServices; + +public interface IOperatorUIService +{ + Task>> GetOperators(CorrelationId correlationId, Guid estateId); + Task> GetOperator(CorrelationId correlationId, Guid estateId, Guid operatorId); + + Task UpdateOperator(CorrelationId correlationId, Guid estateId, Guid operatorId, OperatorModels.EditOperatorModel editOperatorModel); + Task CreateOperator(CorrelationId correlationId, Guid estateId, OperatorModels.CreateOperatorModel createOperatorModel); +} +public class OperatorUIService : IOperatorUIService +{ + private readonly IMediator Mediator; + public OperatorUIService(IMediator mediator) + { + this.Mediator = mediator; + } + public async Task>> GetOperators(CorrelationId correlationId, Guid estateId) + { + var result = await this.Mediator.Send(new OperatorQueries.GetOperatorsQuery(correlationId, estateId)); + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); + var operators = ModelFactory.ConvertFrom(result.Data); + return Result.Success(operators); + } + + public async Task> GetOperator(CorrelationId correlationId, + Guid estateId, + Guid operatorId) { + var result = await this.Mediator.Send(new OperatorQueries.GetOperatorQuery(correlationId, estateId, operatorId)); + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); + var @operator = ModelFactory.ConvertFrom(result.Data); + return Result.Success(@operator); + } + + public async Task UpdateOperator(CorrelationId correlationId, + Guid estateId, + Guid operatorId, + OperatorModels.EditOperatorModel editOperatorModel) { + var command = new OperatorCommands.UpdateOperatorCommand(correlationId, estateId, operatorId, editOperatorModel.OperatorName, editOperatorModel.RequireCustomMerchantNumber, editOperatorModel.RequireCustomTerminalNumber); + + var result = await Mediator.Send(command); + return result; + } + + public async Task CreateOperator(CorrelationId correlationId, + Guid estateId, + OperatorModels.CreateOperatorModel createOperatorModel) { + // Create operator + var command = new OperatorCommands.CreateOperatorCommand(correlationId, + estateId, + createOperatorModel.OperatorName!, + createOperatorModel.RequireCustomMerchantNumber, + createOperatorModel.RequireCustomTerminalNumber + ); + + var result = await Mediator.Send(command); + return result; + } +} \ No newline at end of file