diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Merchants/View.razor b/EstateManagementUI.BlazorServer/Components/Pages/Merchants/View.razor index 0100bae7..3452b14d 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Merchants/View.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Merchants/View.razor @@ -2,6 +2,8 @@ @rendermode InteractiveServer @inject IMediator Mediator @inject NavigationManager NavigationManager +@using EstateManagementUI.BlazorServer.Models +@using EstateManagementUI.BlazorServer.Requests View Merchant @@ -52,6 +54,9 @@ + @@ -226,6 +231,73 @@

Transaction history will be displayed here

} + else if (activeTab == "settlements") + { +
+

Settlement History

+ + @if (loadingSettlements) + { +
+
+
+ } + else if (settlements != null && settlements.Any()) + { +
+
+

Total Settlements

+

@settlements.Count

+
+
+

Total Transactions

+

@settlements.Sum(s => s.TransactionCount).ToString("N0")

+
+
+

Total Paid

+

@settlements.Sum(s => s.NetAmountPaid).ToString("C")

+
+
+ +
+ + + + + + + + + + + @foreach (var settlement in settlements.Take(10)) + { + + + + + + + } + +
DateReferenceTransactionsAmount
@settlement.SettlementDate.ToString("MMM dd, yyyy")@settlement.SettlementReference@settlement.TransactionCount.ToString("N0")@settlement.NetAmountPaid.ToString("C")
+
+ + @if (settlements.Count > 10) + { +
+ + View all @settlements.Count settlements → + +
+ } + } + else + { +

No settlement history available

+ } +
+ } } @@ -250,11 +322,24 @@ private List assignedOperators = new(); private List assignedContracts = new(); private List assignedDevices = new(); + + // Settlement history data + private List? settlements; + private bool loadingSettlements = false; protected override async Task OnInitializedAsync() { await LoadMerchant(); } + + protected override async Task OnParametersSetAsync() + { + // Load settlements when the settlements tab is active + if (activeTab == "settlements" && settlements == null) + { + await LoadSettlements(); + } + } private async Task LoadMerchant() { @@ -299,6 +384,38 @@ isLoading = false; } } + + private async Task LoadSettlements() + { + loadingSettlements = true; + try + { + var estateId = Guid.Parse("11111111-1111-1111-1111-111111111111"); // Test estate ID + var query = new Queries.GetMerchantSettlementHistoryQuery( + CorrelationIdHelper.New(), + "test-token", + estateId, + MerchantId, + DateTime.Today.AddMonths(-6), + DateTime.Today + ); + + var result = await Mediator.Send(query); + if (result.IsSuccess) + { + settlements = result.Data; + } + } + catch (Exception) + { + // Handle error silently for now + settlements = new List(); + } + finally + { + loadingSettlements = false; + } + } private string GetTabClass(string tab) { diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Reporting/Index.razor b/EstateManagementUI.BlazorServer/Components/Pages/Reporting/Index.razor index 40bb4505..68afbd96 100644 --- a/EstateManagementUI.BlazorServer/Components/Pages/Reporting/Index.razor +++ b/EstateManagementUI.BlazorServer/Components/Pages/Reporting/Index.razor @@ -82,6 +82,14 @@ + +
+ Merchant Settlement History + + + +
+
diff --git a/EstateManagementUI.BlazorServer/Components/Pages/Reporting/MerchantSettlementHistory.razor b/EstateManagementUI.BlazorServer/Components/Pages/Reporting/MerchantSettlementHistory.razor new file mode 100644 index 00000000..9fafb709 --- /dev/null +++ b/EstateManagementUI.BlazorServer/Components/Pages/Reporting/MerchantSettlementHistory.razor @@ -0,0 +1,276 @@ +@page "/reporting/merchant-settlement-history" +@rendermode InteractiveServer +@inject IMediator Mediator +@inject NavigationManager NavigationManager +@using EstateManagementUI.BlazorServer.Models +@using EstateManagementUI.BlazorServer.Requests + +Merchant Settlement History + +
+ +
+
+

Merchant Settlement History

+

Historical settlement visibility per merchant

+
+ + + + + Back to Reporting + +
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+ + @if (isLoading) + { +
+
+
+ } + else if (errorMessage != null) + { +
+
+ + + + @errorMessage +
+
+ } + else if (settlements != null && settlements.Any()) + { + +
+
+
+
+
+

Total Settlements

+

@settlements.Count

+
+
+ + + +
+
+
+
+
+
+
+
+

Total Transactions

+

@settlements.Sum(s => s.TransactionCount).ToString("N0")

+
+
+ + + +
+
+
+
+
+
+
+
+

Total Amount Paid

+

@settlements.Sum(s => s.NetAmountPaid).ToString("C")

+
+
+ + + +
+
+
+
+
+
+
+
+

Average Settlement

+

@((settlements.Sum(s => s.NetAmountPaid) / settlements.Count).ToString("C"))

+
+
+ + + +
+
+
+
+
+ + +
+
+

Settlement History

+
+
+
+ + + + + + + + + + + @foreach (var settlement in settlements) + { + + + + + + + } + +
Settlement DateSettlement ReferenceTransaction CountNet Amount Paid
+ @settlement.SettlementDate.ToString("MMM dd, yyyy") + + @settlement.SettlementReference + + @settlement.TransactionCount.ToString("N0") + + @settlement.NetAmountPaid.ToString("C") +
+
+
+
+ } + else if (!isLoading) + { +
+
+ + + +

No settlement history found for the selected criteria

+

Try adjusting your date range or merchant selection

+
+
+ } +
+ +@code { + private List? merchants; + private List? settlements; + private bool isLoading = false; + private string? errorMessage; + + private string selectedMerchantId = ""; + private DateTime startDate = DateTime.Today.AddMonths(-3); + private DateTime endDate = DateTime.Today; + + protected override async Task OnInitializedAsync() + { + await LoadMerchants(); + await LoadSettlementHistory(); + } + + private async Task LoadMerchants() + { + try + { + var estateId = Guid.Parse("11111111-1111-1111-1111-111111111111"); // Test estate ID + var query = new Queries.GetMerchantsQuery( + CorrelationIdHelper.New(), + "test-token", + estateId + ); + + var result = await Mediator.Send(query); + if (result.IsSuccess) + { + merchants = result.Data; + } + } + catch (Exception ex) + { + errorMessage = $"Failed to load merchants: {ex.Message}"; + } + } + + private async Task LoadSettlementHistory() + { + isLoading = true; + errorMessage = null; + + try + { + var estateId = Guid.Parse("11111111-1111-1111-1111-111111111111"); // Test estate ID + Guid? merchantId = string.IsNullOrEmpty(selectedMerchantId) ? null : Guid.Parse(selectedMerchantId); + + var query = new Queries.GetMerchantSettlementHistoryQuery( + CorrelationIdHelper.New(), + "test-token", + estateId, + merchantId, + startDate, + endDate + ); + + var result = await Mediator.Send(query); + if (result.IsSuccess) + { + settlements = result.Data; + } + else + { + errorMessage = result.Message ?? "Failed to load settlement history"; + } + } + catch (Exception ex) + { + errorMessage = $"Error loading settlement history: {ex.Message}"; + } + finally + { + isLoading = false; + } + } +} diff --git a/EstateManagementUI.BlazorServer/Models/Models.cs b/EstateManagementUI.BlazorServer/Models/Models.cs index d2cf1af2..714d4d9f 100644 --- a/EstateManagementUI.BlazorServer/Models/Models.cs +++ b/EstateManagementUI.BlazorServer/Models/Models.cs @@ -231,3 +231,12 @@ public class ProductPerformanceModel public decimal TransactionValue { get; set; } public decimal PercentageContribution { get; set; } } + +// Settlement History Models +public class MerchantSettlementHistoryModel +{ + public DateTime SettlementDate { get; set; } + public string? SettlementReference { get; set; } + public int TransactionCount { get; set; } + public decimal NetAmountPaid { get; set; } +} diff --git a/EstateManagementUI.BlazorServer/Requests/Requests.cs b/EstateManagementUI.BlazorServer/Requests/Requests.cs index 2f734d3c..f9e5406c 100644 --- a/EstateManagementUI.BlazorServer/Requests/Requests.cs +++ b/EstateManagementUI.BlazorServer/Requests/Requests.cs @@ -40,6 +40,7 @@ public record GetLastSettlementQuery(CorrelationId CorrelationId, string AccessT public record GetMerchantQuery(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid MerchantId) : IRequest>; public record GetMerchantTransactionSummaryQuery(CorrelationId CorrelationId, string AccessToken, Guid EstateId, DateTime StartDate, DateTime EndDate, Guid? MerchantId = null, Guid? OperatorId = null, Guid? ProductId = null) : IRequest>>; public record GetProductPerformanceQuery(CorrelationId CorrelationId, string AccessToken, Guid EstateId, DateTime StartDate, DateTime EndDate) : IRequest>>; + public record GetMerchantSettlementHistoryQuery(CorrelationId CorrelationId, string AccessToken, Guid EstateId, Guid? MerchantId, DateTime StartDate, DateTime EndDate) : IRequest>>; } public static class Commands diff --git a/EstateManagementUI.BlazorServer/Services/TestMediatorService.cs b/EstateManagementUI.BlazorServer/Services/TestMediatorService.cs index 2bb982bc..7e3aca66 100644 --- a/EstateManagementUI.BlazorServer/Services/TestMediatorService.cs +++ b/EstateManagementUI.BlazorServer/Services/TestMediatorService.cs @@ -58,6 +58,7 @@ public Task Send(IRequest request, Cancellation Queries.GetLastSettlementQuery => Task.FromResult((TResponse)(object)Result.Success(GetMockLastSettlement())), Queries.GetMerchantTransactionSummaryQuery query => Task.FromResult((TResponse)(object)Result>.Success(GetMockMerchantTransactionSummary(query))), Queries.GetProductPerformanceQuery query => Task.FromResult((TResponse)(object)Result>.Success(GetMockProductPerformance(query))), + Queries.GetMerchantSettlementHistoryQuery query => Task.FromResult((TResponse)(object)Result>.Success(GetMockMerchantSettlementHistory(query))), // Commands - execute against test data store Commands.CreateMerchantCommand cmd => Task.FromResult((TResponse)(object)ExecuteCreateMerchant(cmd)), @@ -577,6 +578,71 @@ private List GetMockMerchantTransactionSummary( return summary; } + private List GetMockMerchantSettlementHistory(Queries.GetMerchantSettlementHistoryQuery query) + { + var merchants = _testDataStore.GetMerchants(query.EstateId); + + // Filter by merchant if specified + if (query.MerchantId.HasValue) + { + merchants = merchants.Where(m => m.MerchantId == query.MerchantId.Value).ToList(); + } + + // Generate settlement history data + var settlements = new List(); + var random = new Random(42); // Use seed for consistent data + + // Calculate the number of weeks in the date range + var startDate = query.StartDate.Date; + var endDate = query.EndDate.Date; + var currentDate = startDate; + + // Generate weekly settlements (every Monday) + int settlementCounter = 1; + while (currentDate <= endDate) + { + // Find the next Monday or use current date if it's already Monday + var daysUntilMonday = ((int)DayOfWeek.Monday - (int)currentDate.DayOfWeek + 7) % 7; + if (daysUntilMonday > 0) + { + currentDate = currentDate.AddDays(daysUntilMonday); + } + + if (currentDate > endDate) + break; + + foreach (var merchant in merchants) + { + // Generate unique settlement reference + var settlementRef = $"STL-{currentDate:yyyyMMdd}-{merchant.MerchantReference ?? merchant.MerchantId.ToString().Substring(0, 8)}-{settlementCounter:D4}"; + + // Generate realistic transaction counts and amounts + var transactionCount = random.Next(50, 500); + var averageTransactionValue = (decimal)(random.NextDouble() * 50 + 10); // $10-$60 average + var grossAmount = transactionCount * averageTransactionValue; + var feePercentage = 0.015m + (decimal)(random.NextDouble() * 0.01); // 1.5%-2.5% fee + var fees = grossAmount * feePercentage; + var netAmount = grossAmount - fees; + + settlements.Add(new MerchantSettlementHistoryModel + { + SettlementDate = currentDate, + SettlementReference = settlementRef, + TransactionCount = transactionCount, + NetAmountPaid = Math.Round(netAmount, 2) + }); + + settlementCounter++; + } + + // Move to next week + currentDate = currentDate.AddDays(7); + } + + // Sort by date descending (most recent first) + return settlements.OrderByDescending(s => s.SettlementDate).ToList(); + } + private List GetMockProductPerformance(Queries.GetProductPerformanceQuery query) { var contracts = _testDataStore.GetContracts(query.EstateId);