refactor: Phase 7-3 - Clients + TaxFilings API-First (WIP)
TaxBaik CI/CD / build-and-deploy (push) Successful in 54s

**Clients Migration Complete:**
- ClientController: GET /api/client (paged), POST/PUT/DELETE
- ClientBrowserClient: IClientBrowserClient interface + implementation
- ClientList.razor: Service → API client
- ClientEdit.razor: Service → API client (Create/Update)

**TaxFilings API Framework Ready:**
- TaxFilingController: GET upcoming, GET by client, POST/PUT/DELETE
- TaxFilingBrowserClient: ITaxFilingBrowserClient interface + impl
- Registered in Program.cs with TokenRefreshHandler

**SOLID Applied:**
✓ Separation of concerns (Controller → Service → Repository)
✓ Dependency inversion (Blazor → Browser clients, not services)
✓ Interface segregation (Specialized clients per domain)

**Status:**
- Clients Blazor:  ClientList + ClientEdit refactored
- TaxFilings Blazor:  Pending refactor (pages exist)
- Faqs:  API + Blazor pending
- Announcements:  API + Blazor pending
- Phase 6 SignalR:  Deferred

Next: Refactor TaxFilings Blazor pages, then Faqs & Announcements
Build:  Success (0 errors, 2 warnings in Dashboard)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-28 11:08:43 +09:00
parent 160afb7c7e
commit fbdbbc7a1f
7 changed files with 503 additions and 32 deletions
@@ -0,0 +1,80 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using TaxBaik.Application.DTOs;
using TaxBaik.Application.Services;
namespace TaxBaik.Web.Controllers;
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class ClientController : ControllerBase
{
private readonly ClientService _clientService;
public ClientController(ClientService clientService)
{
_clientService = clientService;
}
[HttpGet]
public async Task<IActionResult> GetPaged(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 20,
[FromQuery] string? status = null,
[FromQuery] string? search = null)
{
var (clients, total) = await _clientService.GetPagedAsync(page, pageSize, status, search);
return Ok(new { data = clients, total, page, pageSize });
}
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var client = await _clientService.GetByIdAsync(id);
if (client == null)
return NotFound(new ProblemDetails { Title = "고객을 찾을 수 없습니다.", Status = StatusCodes.Status404NotFound });
return Ok(client);
}
[HttpPost]
public async Task<IActionResult> Create([FromBody] CreateClientDto dto)
{
try
{
var clientId = await _clientService.CreateAsync(dto);
var client = await _clientService.GetByIdAsync(clientId);
return CreatedAtAction(nameof(GetById), new { id = clientId }, client);
}
catch (ValidationException ex)
{
return BadRequest(new ProblemDetails { Title = ex.Message, Status = StatusCodes.Status400BadRequest });
}
}
[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, [FromBody] CreateClientDto dto)
{
try
{
await _clientService.UpdateAsync(id, dto);
var client = await _clientService.GetByIdAsync(id);
if (client == null)
return NotFound(new ProblemDetails { Title = "고객을 찾을 수 없습니다.", Status = StatusCodes.Status404NotFound });
return Ok(client);
}
catch (ValidationException ex)
{
return BadRequest(new ProblemDetails { Title = ex.Message, Status = StatusCodes.Status400BadRequest });
}
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
await _clientService.DeleteAsync(id);
return NoContent();
}
}