Files
MoneyMap/MoneyMap/Pages/Merchants.cshtml.cs
AJ 04a7e92bc9 Refactor: migrate PageModels to use new service layer
Refactor 7 PageModels to delegate business logic to services:

- AccountDetails: Use AccountService for account details retrieval
- Accounts: Use AccountService for listing and deletion
- Cards: Use CardService for listing and deletion
- EditTransaction: Use ReferenceDataService for dropdowns
- Merchants: Use MerchantService for CRUD operations
- Recategorize: Use ReferenceDataService and TransactionStatisticsService
- Transactions: Use ReferenceDataService and TransactionStatisticsService

Significantly simplifies PageModels (229 lines removed, 97 added) by extracting data access and business logic into testable services. Pages now focus solely on HTTP request/response handling.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 23:08:28 -04:00

140 lines
3.9 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using MoneyMap.Data;
using MoneyMap.Models;
using MoneyMap.Services;
using System.ComponentModel.DataAnnotations;
namespace MoneyMap.Pages
{
public class MerchantsModel : PageModel
{
private readonly IMerchantService _merchantService;
public MerchantsModel(IMerchantService merchantService)
{
_merchantService = merchantService;
}
public List<MerchantRow> Merchants { get; set; } = new();
public int TotalMerchants { get; set; }
[TempData]
public string? SuccessMessage { get; set; }
[TempData]
public string? ErrorMessage { get; set; }
public async Task OnGetAsync()
{
await LoadDataAsync();
}
public async Task<IActionResult> OnPostAddMerchantAsync(AddMerchantModel model)
{
if (!ModelState.IsValid)
{
ErrorMessage = "Please fill in all required fields.";
await LoadDataAsync();
return Page();
}
// Check if merchant already exists
var existing = await _merchantService.FindByNameAsync(model.Name);
if (existing != null)
{
ErrorMessage = $"Merchant '{model.Name}' already exists.";
await LoadDataAsync();
return Page();
}
var merchant = await _merchantService.GetOrCreateAsync(model.Name);
SuccessMessage = $"Added merchant '{merchant.Name}'.";
return RedirectToPage();
}
public async Task<IActionResult> OnPostUpdateMerchantAsync(UpdateMerchantModel model)
{
if (!ModelState.IsValid)
{
ErrorMessage = "Please fill in all required fields.";
await LoadDataAsync();
return Page();
}
var result = await _merchantService.UpdateMerchantAsync(model.Id, model.Name);
if (result.Success)
{
SuccessMessage = result.Message;
}
else
{
ErrorMessage = result.Message;
await LoadDataAsync();
return Page();
}
return RedirectToPage();
}
public async Task<IActionResult> OnPostDeleteMerchantAsync(int id)
{
var result = await _merchantService.DeleteMerchantAsync(id);
if (result.Success)
{
SuccessMessage = result.Message;
}
else
{
ErrorMessage = result.Message;
}
return RedirectToPage();
}
private async Task LoadDataAsync()
{
var merchantsWithStats = await _merchantService.GetAllMerchantsWithStatsAsync();
Merchants = merchantsWithStats.Select(m => new MerchantRow
{
Id = m.Id,
Name = m.Name,
TransactionCount = m.TransactionCount,
MappingCount = m.MappingCount
}).ToList();
TotalMerchants = Merchants.Count;
}
public class MerchantRow
{
public int Id { get; set; }
public string Name { get; set; } = "";
public int TransactionCount { get; set; }
public int MappingCount { get; set; }
}
public class AddMerchantModel
{
[Required(ErrorMessage = "Merchant name is required")]
[StringLength(100)]
public string Name { get; set; } = "";
}
public class UpdateMerchantModel
{
[Required]
public int Id { get; set; }
[Required(ErrorMessage = "Merchant name is required")]
[StringLength(100)]
public string Name { get; set; } = "";
}
}
}