diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor b/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor
index 87e1f347..b853143c 100644
--- a/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor
+++ b/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor
@@ -323,7 +323,7 @@
@if (assignedDevices == null || !assignedDevices.Any()) {
No devices assigned
}
- else {
+ @* else {
@foreach (var device in assignedDevices) {
@@ -334,7 +334,42 @@
}
- }
+ } *@
+ else {
+
+ @foreach (var device in assignedDevices) {
+
+
+ @device.DeviceIdentifier
+
+
+ @if (selectedDeviceToSwap == device.DeviceIdentifier) {
+
+
+
+
+
+ }
+ else {
+
+
+
+ }
+
+
+ @if (selectedDeviceToSwap == device.DeviceIdentifier && !string.IsNullOrEmpty(swapDeviceError))
+ {
+
@swapDeviceError
+ }
+ }
+
+ }
}
diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor.cs b/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor.cs
index fd8ebc24..5dbd7ed6 100644
--- a/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor.cs
+++ b/EstateManagementUI.BlazorServer/Components/Pages/Merchants/Edit.razor.cs
@@ -2,7 +2,9 @@
using EstateManagementUI.BlazorServer.Factories;
using EstateManagementUI.BlazorServer.Models;
using EstateManagementUI.BlazorServer.Permissions;
+using EstateManagementUI.BusinessLogic.BackendAPI.DataTransferObjects;
using EstateManagementUI.BusinessLogic.Requests;
+using MediatR;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Shared.Results;
@@ -490,21 +492,12 @@ private async Task AddDeviceToMerchant()
try
{
var correlationId = new CorrelationId(Guid.NewGuid());
- var estateId = Guid.Parse("11111111-1111-1111-1111-111111111111");
- var accessToken = "stubbed-token";
-
- var command = new Commands.AddMerchantDeviceCommand(
- correlationId,
- accessToken,
- estateId,
- MerchantId,
- deviceIdentifier
- );
+ var estateId = await this.GetEstateId();
+ IRequest command = new MerchantCommands.AddMerchantDeviceCommand(correlationId, estateId, MerchantId, deviceIdentifier);
var result = await Mediator.Send(command);
- if (result.IsSuccess)
- {
+ if (result.IsSuccess) {
successMessage = "Device added successfully";
assignedDevices.Add(new MerchantDeviceModel() {
DeviceIdentifier = this.deviceIdentifier
@@ -523,15 +516,71 @@ private async Task AddDeviceToMerchant()
}
}
- private void RemoveDevice(string device)
- {
- ClearMessages();
- var d = this.assignedDevices.Single(d => d.DeviceIdentifier == device);
- assignedDevices.Remove(d);
- successMessage = "Device removed successfully";
+ // inside partial class Edit (add the following fields and methods)
+
+ // Swap device UI state
+ private string? selectedDeviceToSwap;
+ private string? swapDeviceIdentifier;
+ private string? swapDeviceError;
+
+ private void StartSwapDevice(string device)
+ {
+ ClearMessages();
+ selectedDeviceToSwap = device;
+ swapDeviceIdentifier = string.Empty;
+ swapDeviceError = null;
+ }
+
+ private void CancelSwapDevice()
+ {
+ swapDeviceIdentifier = null;
+ swapDeviceError = null;
+ selectedDeviceToSwap = null;
+ }
+
+ private async Task SwapDeviceConfirm(string originalDevice)
+ {
+ ClearMessages();
+
+ var newId = swapDeviceIdentifier?.Trim();
+
+ // Validation
+ if (string.IsNullOrWhiteSpace(newId)) {
+ swapDeviceError = "New device identifier is required.";
+ return;
}
- private void ClearMessages()
+ // Case-insensitive comparison for equality/duplicates
+ if (string.Equals(originalDevice?.Trim(), newId, StringComparison.OrdinalIgnoreCase)) {
+ swapDeviceError = "New device identifier cannot be the same as the current device.";
+ return;
+ }
+
+ if (assignedDevices.Any(d => string.Equals(d.DeviceIdentifier.Trim(), newId, StringComparison.OrdinalIgnoreCase))) {
+ swapDeviceError = "The specified device identifier is already assigned.";
+ return;
+ }
+
+ var correlationId = new CorrelationId(Guid.NewGuid());
+ var estateId = await this.GetEstateId();
+ var command = new MerchantCommands.SwapMerchantDeviceCommand(correlationId, estateId, this.MerchantId, this.assignedDevices.Single().DeviceIdentifier, newId);
+
+ var result = await Mediator.Send(command);
+
+ if (result.IsSuccess) {
+ successMessage = $"Device {originalDevice} swapped for {newId}.";
+ }
+ else {
+ swapDeviceError = "Original device not found.";
+ }
+
+ // Reset swap UI
+ CancelSwapDevice();
+ StateHasChanged();
+ }
+
+
+ private void ClearMessages()
{
errorMessage = null;
successMessage = null;
diff --git a/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs b/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs
index 7d1ba585..5d3965e4 100644
--- a/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs
+++ b/EstateManagmentUI.BusinessLogic/Client/MerchantMethods.cs
@@ -26,6 +26,8 @@ public partial interface IApiClient
Task AddOperatorToMerchant(MerchantCommands.AddOperatorToMerchantCommand request, CancellationToken cancellationToken);
Task RemoveContractFromMerchant(MerchantCommands.RemoveContractFromMerchantCommand request, CancellationToken cancellationToken);
Task AddContractToMerchant(MerchantCommands.AssignContractToMerchantCommand request, CancellationToken cancellationToken);
+ Task AddDeviceToMerchant(MerchantCommands.AddMerchantDeviceCommand request, CancellationToken cancellationToken);
+ Task SwapMerchantDevice(MerchantCommands.SwapMerchantDeviceCommand request, CancellationToken cancellationToken);
}
public partial class ApiClient : IApiClient {
@@ -74,6 +76,36 @@ public async Task AddContractToMerchant(MerchantCommands.AssignContractT
return Result.Success();
}
+ public async Task AddDeviceToMerchant(MerchantCommands.AddMerchantDeviceCommand request,
+ CancellationToken cancellationToken) {
+ var token = await this.GetToken(cancellationToken);
+ if (token.IsFailed)
+ return ResultHelpers.CreateFailure(token);
+
+ AddMerchantDeviceRequest apiRequest = new() { DeviceIdentifier = request.DeviceIdentifier};
+
+ var apiResult = await this.TransactionProcessorClient.AddDeviceToMerchant(token.Data, request.EstateId, request.MerchantId, apiRequest, cancellationToken);
+ if (apiResult.IsFailed)
+ return ResultHelpers.CreateFailure(apiResult);
+
+ return Result.Success();
+ }
+
+ public async Task SwapMerchantDevice(MerchantCommands.SwapMerchantDeviceCommand request,
+ CancellationToken cancellationToken) {
+ var token = await this.GetToken(cancellationToken);
+ if (token.IsFailed)
+ return ResultHelpers.CreateFailure(token);
+
+ SwapMerchantDeviceRequest apiRequest = new() { NewDeviceIdentifier = request.NewDevice};
+
+ var apiResult = await this.TransactionProcessorClient.SwapDeviceForMerchant(token.Data, request.EstateId, request.MerchantId, request.OldDevice,apiRequest, cancellationToken);
+ if (apiResult.IsFailed)
+ return ResultHelpers.CreateFailure(apiResult);
+
+ return Result.Success();
+ }
+
public async Task RemoveOperatorFromMerchant(MerchantCommands.RemoveOperatorFromMerchantCommand request,
CancellationToken cancellationToken) {
var token = await this.GetToken(cancellationToken);
diff --git a/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs b/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs
index 33a19ba7..2c806642 100644
--- a/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs
+++ b/EstateManagmentUI.BusinessLogic/RequestHandlers/DateRequestHandler.cs
@@ -54,13 +54,13 @@ public async Task>> Handle(EstateQueries.GetAssignedO
public class MerchantRequestHandler : IRequestHandler>>,
IRequestHandler>,
- IRequestHandler,
+ IRequestHandler,
IRequestHandler,
IRequestHandler,
IRequestHandler,
IRequestHandler,
IRequestHandler,
- IRequestHandler,
+ IRequestHandler,
IRequestHandler,
IRequestHandler,
IRequestHandler>>,
@@ -82,9 +82,9 @@ public async Task>> Handle(MerchantQueries.GetMer
return await this.ApiClient.GetMerchants(request, cancellationToken);
}
- public async Task Handle(Commands.AddMerchantDeviceCommand request,
+ public async Task Handle(MerchantCommands.AddMerchantDeviceCommand request,
CancellationToken cancellationToken) {
- return Result.Success();
+ return await this.ApiClient.AddDeviceToMerchant(request, cancellationToken);
}
public async Task Handle(MerchantCommands.AddOperatorToMerchantCommand request,
@@ -112,9 +112,9 @@ public async Task Handle(MerchantCommands.RemoveOperatorFromMerchantComm
return await this.ApiClient.RemoveOperatorFromMerchant(request, cancellationToken);
}
- public async Task Handle(Commands.SwapMerchantDeviceCommand request,
+ public async Task Handle(MerchantCommands.SwapMerchantDeviceCommand request,
CancellationToken cancellationToken) {
- return Result.Success();
+ return await this.ApiClient.SwapMerchantDevice(request, cancellationToken);
}
diff --git a/EstateManagmentUI.BusinessLogic/Requests/Requests.cs b/EstateManagmentUI.BusinessLogic/Requests/Requests.cs
index 5d397a67..d0862972 100644
--- a/EstateManagmentUI.BusinessLogic/Requests/Requests.cs
+++ b/EstateManagmentUI.BusinessLogic/Requests/Requests.cs
@@ -82,18 +82,20 @@ public record RemoveOperatorFromMerchantCommand(CorrelationId CorrelationId, Gui
public record AddOperatorToMerchantCommand(CorrelationId CorrelationId, Guid EstateId, Guid MerchantId, Guid OperatorId, string? MerchantNumber, string? TerminalNumber) : IRequest;
public record RemoveContractFromMerchantCommand(CorrelationId CorrelationId, Guid EstateId, Guid MerchantId, Guid ContractId) : IRequest;
public record AssignContractToMerchantCommand(CorrelationId CorrelationId, Guid EstateId, Guid MerchantId, Guid ContractId) : IRequest;
+ public record AddMerchantDeviceCommand(CorrelationId CorrelationId, Guid EstateId, Guid MerchantId, string DeviceIdentifier) : IRequest;
+ public record SwapMerchantDeviceCommand(CorrelationId CorrelationId, Guid EstateId, Guid MerchantId, string OldDevice, string NewDevice) : IRequest;
}
public static class Commands
{
- public record AddMerchantDeviceCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid MerchantId, string DeviceIdentifier) : IRequest;
+
public record CreateContractCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, string Description, Guid OperatorId) : IRequest;
public record CreateMerchantCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, string Name, string ContactName, string ContactEmail) : IRequest;
public record CreateMerchantUserCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid MerchantId, string EmailAddress, string Password) : IRequest;
public record CreateOperatorCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, string Name, bool RequireCustomMerchantNumber, bool RequireCustomTerminalNumber) : IRequest;
public record MakeMerchantDepositCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid MerchantId, decimal Amount, DateTime Date, string Reference) : IRequest;
- public record SwapMerchantDeviceCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid MerchantId, string OldDevice, string NewDevice) : IRequest;
+
public record UpdateOperatorCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid OperatorId, string Name, bool RequireCustomMerchantNumber, bool RequireCustomTerminalNumber) : IRequest;
public record AddProductToContractCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid ContractId, string ProductName, string DisplayText, decimal? Value) : IRequest;
public record AddTransactionFeeForProductToContractCommand(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid ContractId, Guid ProductId, string Description, decimal Value) : IRequest;
diff --git a/EstateManagmentUI.BusinessLogic/Services/TestMediatorService.cs b/EstateManagmentUI.BusinessLogic/Services/TestMediatorService.cs
index 744d2be5..33217582 100644
--- a/EstateManagmentUI.BusinessLogic/Services/TestMediatorService.cs
+++ b/EstateManagmentUI.BusinessLogic/Services/TestMediatorService.cs
@@ -80,8 +80,8 @@ public Task Send(IRequest request, Cancellation
MerchantCommands.RemoveOperatorFromMerchantCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteRemoveOperatorFromMerchant(cmd)),
EstateCommands.AddOperatorToEstateCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteAddOperatorToEstate(cmd)),
EstateCommands.RemoveOperatorFromEstateCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteRemoveOperatorFromEstate(cmd)),
- Commands.AddMerchantDeviceCommand => Task.FromResult((TResponse)(object)Result.Success()),
- Commands.SwapMerchantDeviceCommand => Task.FromResult((TResponse)(object)Result.Success()),
+ MerchantCommands.AddMerchantDeviceCommand => Task.FromResult((TResponse)(object)Result.Success()),
+ MerchantCommands.SwapMerchantDeviceCommand => Task.FromResult((TResponse)(object)Result.Success()),
Commands.CreateMerchantUserCommand => Task.FromResult((TResponse)(object)Result.Success()),
Commands.MakeMerchantDepositCommand cmd => Task.FromResult((TResponse)(object)this.ExecuteMakeMerchantDeposit(cmd)),