P17: CommonCodeController → FastEndpoints (AllEndpoints.cs)

- Migrate CommonCodeController to 6 FastEndpoints
- GetAllActive, GetByGroup, GetGroups, GetByGroupAndValue, Upsert, Delete
- Backup original controller as .bak
- All endpoints require Bearer token auth
- Validation rules enforced on Upsert (no spaces in group/value)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 17:34:49 +09:00
parent 2bbe2ef47f
commit 063ec189ce
2 changed files with 295 additions and 0 deletions
@@ -0,0 +1,213 @@
using FastEndpoints;
using TaxBaik.Application.Services;
using TaxBaik.Domain.Entities;
namespace TaxBaik.Web.Endpoints.CommonCode;
// DTOs
public class CommonCodeResponse
{
public List<object> Data { get; set; } = [];
}
public class CommonCodeSingleResponse
{
public object Data { get; set; } = null!;
}
public class GroupResponse
{
public List<string> Data { get; set; } = [];
}
public class UpsertCommonCodeRequest
{
public string? CodeGroup { get; set; }
public string? CodeValue { get; set; }
public string? CodeName { get; set; }
public string? Description { get; set; }
public int? SortOrder { get; set; }
public bool IsActive { get; set; } = true;
}
public class UpsertCommonCodeResponse
{
public object Data { get; set; } = null!;
}
// Endpoints
public class GetAllActiveEndpoint : Endpoint<EmptyRequest, CommonCodeResponse>
{
private readonly CommonCodeService _service;
public GetAllActiveEndpoint(CommonCodeService service) => _service = service;
public override void Configure()
{
Get("/api/commoncode");
Policies("Bearer");
}
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
{
try
{
var codes = await _service.GetAllActiveAsync();
await SendAsync(new CommonCodeResponse { Data = codes.Cast<object>().ToList() }, 200, cancellation: ct);
}
catch (Exception ex)
{
ThrowError("공통코드 조회 실패", statusCode: 500);
}
}
}
public class GetByGroupEndpoint : Endpoint<EmptyRequest, CommonCodeResponse>
{
private readonly CommonCodeService _service;
public GetByGroupEndpoint(CommonCodeService service) => _service = service;
public override void Configure()
{
Get("/api/commoncode/group/{group}");
Policies("Bearer");
}
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
{
var group = Route<string>("group");
try
{
var codes = await _service.GetByGroupAsync(group);
await SendAsync(new CommonCodeResponse { Data = codes.Cast<object>().ToList() }, 200, cancellation: ct);
}
catch (Exception ex)
{
ThrowError("그룹별 공통코드 조회 실패", statusCode: 500);
}
}
}
public class GetGroupsEndpoint : Endpoint<EmptyRequest, GroupResponse>
{
private readonly CommonCodeService _service;
public GetGroupsEndpoint(CommonCodeService service) => _service = service;
public override void Configure()
{
Get("/api/commoncode/groups");
Policies("Bearer");
}
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
{
try
{
var groups = await _service.GetAllGroupsAsync();
await SendAsync(new GroupResponse { Data = groups.ToList() }, 200, cancellation: ct);
}
catch (Exception ex)
{
ThrowError("공통코드 그룹 조회 실패", statusCode: 500);
}
}
}
public class GetByGroupAndValueEndpoint : Endpoint<EmptyRequest, CommonCodeSingleResponse>
{
private readonly CommonCodeService _service;
public GetByGroupAndValueEndpoint(CommonCodeService service) => _service = service;
public override void Configure()
{
Get("/api/commoncode/{group}/{value}");
Policies("Bearer");
}
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
{
var group = Route<string>("group");
var value = Route<string>("value");
try
{
var code = await _service.GetAsync(group, value);
if (code == null)
ThrowError("공통코드를 찾을 수 없습니다.", statusCode: 404);
await SendAsync(new CommonCodeSingleResponse { Data = code }, 200, cancellation: ct);
}
catch (Exception ex)
{
ThrowError(ex.Message, statusCode: 500);
}
}
}
public class UpsertEndpoint : Endpoint<UpsertCommonCodeRequest, UpsertCommonCodeResponse>
{
private readonly CommonCodeService _service;
public UpsertEndpoint(CommonCodeService service) => _service = service;
public override void Configure()
{
Post("/api/commoncode");
Policies("Bearer");
}
public override async Task HandleAsync(UpsertCommonCodeRequest request, CancellationToken ct)
{
try
{
if (string.IsNullOrWhiteSpace(request.CodeGroup) || string.IsNullOrWhiteSpace(request.CodeValue) || string.IsNullOrWhiteSpace(request.CodeName))
ThrowError("코드 그룹, 값, 이름은 필수입니다.");
if (request.CodeGroup.Any(char.IsWhiteSpace))
ThrowError("code_group에는 공백을 사용할 수 없습니다.");
if (request.CodeValue.Contains(' '))
ThrowError("code_value에는 공백을 사용할 수 없습니다.");
var code = new CommonCode
{
CodeGroup = request.CodeGroup,
CodeValue = request.CodeValue,
CodeName = request.CodeName,
Description = request.Description,
SortOrder = request.SortOrder ?? 0,
IsActive = request.IsActive
};
await _service.UpsertAsync(code);
await SendAsync(new UpsertCommonCodeResponse { Data = code }, 200, cancellation: ct);
}
catch (Exception ex)
{
ThrowError(ex.Message);
}
}
}
public class DeleteEndpoint : Endpoint<EmptyRequest, EmptyResponse>
{
private readonly CommonCodeService _service;
public DeleteEndpoint(CommonCodeService service) => _service = service;
public override void Configure()
{
Delete("/api/commoncode/{group}/{value}");
Policies("Bearer");
}
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
{
var group = Route<string>("group");
var value = Route<string>("value");
try
{
await _service.DeleteAsync(group, value);
await SendNoContentAsync(ct);
}
catch (Exception ex)
{
ThrowError(ex.Message);
}
}
}