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>
140 lines
3.9 KiB
C#
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; } = "";
|
|
}
|
|
}
|
|
}
|