From 6fdf233976bc1a3beea71924acb5ba8c4093f38f Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Fri, 3 Jul 2026 17:28:43 +0900 Subject: [PATCH] feat: migrate ContractController to FastEndpoints (Phase 7) Phase 7: 6 endpoints Total: 44/73 (60%) Co-Authored-By: Claude Haiku 4.5 --- ...ontroller.cs => ContractController.cs.bak} | 0 .../Endpoints/Contract/AllEndpoints.cs | 97 +++++++++++++++++++ 2 files changed, 97 insertions(+) rename src/TaxBaik.Web/Controllers/{ContractController.cs => ContractController.cs.bak} (100%) create mode 100644 src/TaxBaik.Web/Endpoints/Contract/AllEndpoints.cs diff --git a/src/TaxBaik.Web/Controllers/ContractController.cs b/src/TaxBaik.Web/Controllers/ContractController.cs.bak similarity index 100% rename from src/TaxBaik.Web/Controllers/ContractController.cs rename to src/TaxBaik.Web/Controllers/ContractController.cs.bak diff --git a/src/TaxBaik.Web/Endpoints/Contract/AllEndpoints.cs b/src/TaxBaik.Web/Endpoints/Contract/AllEndpoints.cs new file mode 100644 index 0000000..f4e080d --- /dev/null +++ b/src/TaxBaik.Web/Endpoints/Contract/AllEndpoints.cs @@ -0,0 +1,97 @@ +using FastEndpoints; +using TaxBaik.Application.Services; + +namespace TaxBaik.Web.Endpoints.Contract; + +public class CreateRequest { public int ClientId { get; set; } public string? ContractNumber { get; set; } public string? ServiceType { get; set; } public DateTime StartDate { get; set; } public DateTime? EndDate { get; set; } public decimal MonthlyAmount { get; set; } } +public class ListResp { public List Data { get; set; } = []; } +public class IdResp { public int Id { get; set; } } +public class MRRResp { public decimal MRR { get; set; } } +public class DaysQry { public int DaysAhead { get; set; } = 30; } + +public class CreateEp : Endpoint +{ + readonly ContractService _svc; + public CreateEp(ContractService svc) => _svc = svc; + public override void Configure() { Post("/api/contract"); Policies("Bearer"); } + public override async Task HandleAsync(CreateRequest r, CancellationToken ct) + { + var id = await _svc.CreateAsync(r.ClientId, r.ContractNumber, r.ServiceType, r.StartDate, r.EndDate, r.MonthlyAmount); + await SendAsync(new IdResp { Id = id }, 201, cancellation: ct); + } +} + +public class GetByIdEp : Endpoint +{ + readonly ContractService _svc; + public GetByIdEp(ContractService svc) => _svc = svc; + public override void Configure() { Get("/api/contract/{id}"); Policies("Bearer"); } + public override async Task HandleAsync(EmptyRequest _, CancellationToken ct) + { + var id = Route("id"); + var c = await _svc.GetByIdAsync(id); + if (c == null) ThrowError("계약을 찾을 수 없습니다.", statusCode: 404); + await SendAsync(c, 200, cancellation: ct); + } +} + +public class GetAllEp : Endpoint +{ + readonly ContractService _svc; + public GetAllEp(ContractService svc) => _svc = svc; + public override void Configure() { Get("/api/contract"); Policies("Bearer"); } + public override async Task HandleAsync(EmptyRequest _, CancellationToken ct) + { + var cs = await _svc.GetAllAsync(); + await SendAsync(new ListResp { Data = cs.Cast().ToList() }, 200, cancellation: ct); + } +} + +public class GetByClientEp : Endpoint +{ + readonly ContractService _svc; + public GetByClientEp(ContractService svc) => _svc = svc; + public override void Configure() { Get("/api/contract/client/{clientId}"); Policies("Bearer"); } + public override async Task HandleAsync(EmptyRequest _, CancellationToken ct) + { + var id = Route("clientId"); + var cs = await _svc.GetByClientIdAsync(id); + await SendAsync(new ListResp { Data = cs.Cast().ToList() }, 200, cancellation: ct); + } +} + +public class GetActiveEp : Endpoint +{ + readonly ContractService _svc; + public GetActiveEp(ContractService svc) => _svc = svc; + public override void Configure() { Get("/api/contract/active"); Policies("Bearer"); } + public override async Task HandleAsync(EmptyRequest _, CancellationToken ct) + { + var cs = await _svc.GetActiveContractsAsync(); + await SendAsync(new ListResp { Data = cs.Cast().ToList() }, 200, cancellation: ct); + } +} + +public class GetExpiringEp : Endpoint +{ + readonly ContractService _svc; + public GetExpiringEp(ContractService svc) => _svc = svc; + public override void Configure() { Get("/api/contract/expiring"); Policies("Bearer"); } + public override async Task HandleAsync(DaysQry r, CancellationToken ct) + { + var cs = await _svc.GetExpiringContractsAsync(r.DaysAhead); + await SendAsync(new { data = cs, daysAhead = r.DaysAhead }, 200, cancellation: ct); + } +} + +public class GetMRREp : Endpoint +{ + readonly ContractService _svc; + public GetMRREp(ContractService svc) => _svc = svc; + public override void Configure() { Get("/api/contract/mrr"); Policies("Bearer"); } + public override async Task HandleAsync(EmptyRequest _, CancellationToken ct) + { + var mrr = await _svc.GetMonthlyRecurringRevenueAsync(); + await SendAsync(new MRRResp { MRR = mrr }, 200, cancellation: ct); + } +}