feat: Phase 9 RevenueTracking FastEndpoints migration
- Created AllEndpoints.cs with 7 endpoints:
- CreateEp: POST /api/revenue-tracking
- GetAllEp: GET /api/revenue-tracking
- GetByClientEp: GET /api/revenue-tracking/client/{clientId}
- GetPendingEp: GET /api/revenue-tracking/pending
- GetMonthlyEp: GET /api/revenue-tracking/monthly
- GetTotalEp: GET /api/revenue-tracking/total
- MarkPaidEp: PUT /api/revenue-tracking/{id}/paid
- Disabled RevenueTrackingController.cs (moved to .bak)
- All DTOs defined: CreateRequest, MarkPaidRequest, ListResp, IdResp, TotalResp, MonthlyQry, DateRangeQry
- Bearer policy applied to all endpoints
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,182 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using TaxBaik.Application.DTOs;
|
||||||
|
using TaxBaik.Application.Services;
|
||||||
|
|
||||||
|
namespace TaxBaik.Web.Endpoints.Announcement;
|
||||||
|
|
||||||
|
// DTOs
|
||||||
|
public class GetAnnouncementResponse
|
||||||
|
{
|
||||||
|
public List<object> Data { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateAnnouncementResponse
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UpdateAnnouncementResponse
|
||||||
|
{
|
||||||
|
public string Message { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Endpoints
|
||||||
|
public class GetActiveEndpoint : Endpoint<EmptyRequest, GetAnnouncementResponse>
|
||||||
|
{
|
||||||
|
private readonly AnnouncementService _service;
|
||||||
|
public GetActiveEndpoint(AnnouncementService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Get("/api/announcement/active");
|
||||||
|
AllowAnonymous();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var announcements = await _service.GetActiveAsync(ct);
|
||||||
|
await SendAsync(new GetAnnouncementResponse { Data = announcements.Cast<object>().ToList() }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetAllEndpoint : Endpoint<EmptyRequest, GetAnnouncementResponse>
|
||||||
|
{
|
||||||
|
private readonly AnnouncementService _service;
|
||||||
|
public GetAllEndpoint(AnnouncementService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Get("/api/announcement");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var announcements = await _service.GetAllAsync(ct);
|
||||||
|
await SendAsync(new GetAnnouncementResponse { Data = announcements.Cast<object>().ToList() }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetByIdEndpoint : Endpoint<EmptyRequest, object>
|
||||||
|
{
|
||||||
|
private readonly AnnouncementService _service;
|
||||||
|
public GetByIdEndpoint(AnnouncementService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Get("/api/announcement/{id}");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var id = Route<int>("id");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var announcement = await _service.GetByIdAsync(id, ct);
|
||||||
|
if (announcement == null)
|
||||||
|
ThrowError("공지사항을 찾을 수 없습니다.", statusCode: 404);
|
||||||
|
await SendAsync(announcement, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateEndpoint : Endpoint<AnnouncementDto, CreateAnnouncementResponse>
|
||||||
|
{
|
||||||
|
private readonly AnnouncementService _service;
|
||||||
|
public CreateEndpoint(AnnouncementService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Post("/api/announcement");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(AnnouncementDto request, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var announcementId = await _service.CreateAsync(request, ct);
|
||||||
|
var result = await _service.GetByIdAsync(announcementId, ct);
|
||||||
|
await SendAsync(new CreateAnnouncementResponse { Id = announcementId }, 201, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UpdateEndpoint : Endpoint<AnnouncementDto, UpdateAnnouncementResponse>
|
||||||
|
{
|
||||||
|
private readonly AnnouncementService _service;
|
||||||
|
public UpdateEndpoint(AnnouncementService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Put("/api/announcement/{id}");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(AnnouncementDto request, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var id = Route<int>("id");
|
||||||
|
request.Id = id;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _service.UpdateAsync(request, ct);
|
||||||
|
var result = await _service.GetByIdAsync(id, ct);
|
||||||
|
if (result == null)
|
||||||
|
ThrowError("공지사항을 찾을 수 없습니다.", statusCode: 404);
|
||||||
|
await SendAsync(new UpdateAnnouncementResponse { Message = "공지사항이 수정되었습니다." }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DeleteEndpoint : Endpoint<EmptyRequest, EmptyResponse>
|
||||||
|
{
|
||||||
|
private readonly AnnouncementService _service;
|
||||||
|
public DeleteEndpoint(AnnouncementService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Delete("/api/announcement/{id}");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var id = Route<int>("id");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _service.DeleteAsync(id, ct);
|
||||||
|
await SendAsync(new EmptyResponse(), 204, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using TaxBaik.Application.Services;
|
||||||
|
|
||||||
|
namespace TaxBaik.Web.Endpoints.Category;
|
||||||
|
|
||||||
|
// DTOs
|
||||||
|
public class CreateCategoryRequest
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string? Description { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CategoryResponse
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string Slug { get; set; } = string.Empty;
|
||||||
|
public int SortOrder { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CategoryListResponse
|
||||||
|
{
|
||||||
|
public List<CategoryResponse> Data { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CategoryCreateResponse
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string Slug { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Endpoints
|
||||||
|
public class GetAllEndpoint : Endpoint<EmptyRequest, CategoryListResponse>
|
||||||
|
{
|
||||||
|
private readonly CategoryService _service;
|
||||||
|
public GetAllEndpoint(CategoryService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Get("/api/category");
|
||||||
|
AllowAnonymous();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var categories = await _service.GetAllAsync(ct);
|
||||||
|
var response = new CategoryListResponse
|
||||||
|
{
|
||||||
|
Data = categories.Select(c => new CategoryResponse
|
||||||
|
{
|
||||||
|
Id = c.Id,
|
||||||
|
Name = c.Name,
|
||||||
|
Slug = c.Slug,
|
||||||
|
SortOrder = c.SortOrder
|
||||||
|
}).ToList()
|
||||||
|
};
|
||||||
|
await SendAsync(response, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateEndpoint : Endpoint<CreateCategoryRequest, CategoryCreateResponse>
|
||||||
|
{
|
||||||
|
private readonly CategoryService _service;
|
||||||
|
public CreateEndpoint(CategoryService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Post("/api/category");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(CreateCategoryRequest request, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(request.Name))
|
||||||
|
ThrowError("카테고리 이름은 필수입니다.");
|
||||||
|
|
||||||
|
var category = await _service.CreateAsync(request.Name, request.Description, ct);
|
||||||
|
var response = new CategoryCreateResponse
|
||||||
|
{
|
||||||
|
Id = category.Id,
|
||||||
|
Name = category.Name,
|
||||||
|
Slug = category.Slug
|
||||||
|
};
|
||||||
|
await SendAsync(response, 201, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (ValidationException ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UpdateEndpoint : Endpoint<CreateCategoryRequest, CategoryResponse>
|
||||||
|
{
|
||||||
|
private readonly CategoryService _service;
|
||||||
|
public UpdateEndpoint(CategoryService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Put("/api/category/{id}");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(CreateCategoryRequest request, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var id = Route<int>("id");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var category = await _service.UpdateAsync(id, request.Name, request.Description, ct);
|
||||||
|
if (category == null)
|
||||||
|
ThrowError("카테고리를 찾을 수 없습니다.", statusCode: 404);
|
||||||
|
|
||||||
|
var response = new CategoryResponse
|
||||||
|
{
|
||||||
|
Id = category.Id,
|
||||||
|
Name = category.Name,
|
||||||
|
Slug = category.Slug,
|
||||||
|
SortOrder = category.SortOrder
|
||||||
|
};
|
||||||
|
await SendAsync(response, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (ValidationException ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DeleteEndpoint : Endpoint<EmptyRequest, EmptyResponse>
|
||||||
|
{
|
||||||
|
private readonly CategoryService _service;
|
||||||
|
public DeleteEndpoint(CategoryService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Delete("/api/category/{id}");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var id = Route<int>("id");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _service.DeleteAsync(id, ct);
|
||||||
|
await SendAsync(new EmptyResponse(), 204, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,223 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using TaxBaik.Application.Services;
|
||||||
|
using TaxBaik.Domain.Entities;
|
||||||
|
using FaqEntity = TaxBaik.Domain.Entities.Faq;
|
||||||
|
|
||||||
|
namespace TaxBaik.Web.Endpoints.Faq;
|
||||||
|
|
||||||
|
// DTOs
|
||||||
|
public class CreateFaqRequest
|
||||||
|
{
|
||||||
|
public string Question { get; set; } = string.Empty;
|
||||||
|
public string Answer { get; set; } = string.Empty;
|
||||||
|
public string? Category { get; set; }
|
||||||
|
public int SortOrder { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UpdateFaqRequest
|
||||||
|
{
|
||||||
|
public string Question { get; set; } = string.Empty;
|
||||||
|
public string Answer { get; set; } = string.Empty;
|
||||||
|
public string? Category { get; set; }
|
||||||
|
public int SortOrder { get; set; }
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FaqListResponse
|
||||||
|
{
|
||||||
|
public List<FaqEntity> Data { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FaqCreateResponse
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FaqUpdateResponse
|
||||||
|
{
|
||||||
|
public string Message { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Endpoints
|
||||||
|
public class GetActiveEndpoint : Endpoint<EmptyRequest, FaqListResponse>
|
||||||
|
{
|
||||||
|
private readonly FaqService _service;
|
||||||
|
public GetActiveEndpoint(FaqService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Get("/api/faq/active");
|
||||||
|
AllowAnonymous();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var faqs = await _service.GetActiveAsync(ct);
|
||||||
|
await SendAsync(new FaqListResponse { Data = faqs.ToList() }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetAllEndpoint : Endpoint<EmptyRequest, FaqListResponse>
|
||||||
|
{
|
||||||
|
private readonly FaqService _service;
|
||||||
|
public GetAllEndpoint(FaqService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Get("/api/faq");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var faqs = await _service.GetAllAsync(ct);
|
||||||
|
await SendAsync(new FaqListResponse { Data = faqs.ToList() }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetByIdEndpoint : Endpoint<EmptyRequest, FaqEntity>
|
||||||
|
{
|
||||||
|
private readonly FaqService _service;
|
||||||
|
public GetByIdEndpoint(FaqService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Get("/api/faq/{id}");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var id = Route<int>("id");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var faq = await _service.GetByIdAsync(id, ct);
|
||||||
|
if (faq == null)
|
||||||
|
ThrowError("FAQ를 찾을 수 없습니다.", statusCode: 404);
|
||||||
|
await SendAsync(faq, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateEndpoint : Endpoint<CreateFaqRequest, FaqCreateResponse>
|
||||||
|
{
|
||||||
|
private readonly FaqService _service;
|
||||||
|
public CreateEndpoint(FaqService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Post("/api/faq");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(CreateFaqRequest request, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var faq = new FaqEntity
|
||||||
|
{
|
||||||
|
Question = request.Question,
|
||||||
|
Answer = request.Answer,
|
||||||
|
Category = request.Category,
|
||||||
|
SortOrder = request.SortOrder,
|
||||||
|
IsActive = true,
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
UpdatedAt = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
var id = await _service.CreateAsync(faq, ct);
|
||||||
|
await SendAsync(new FaqCreateResponse { Id = id }, 201, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (ValidationException ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UpdateEndpoint : Endpoint<UpdateFaqRequest, FaqUpdateResponse>
|
||||||
|
{
|
||||||
|
private readonly FaqService _service;
|
||||||
|
public UpdateEndpoint(FaqService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Put("/api/faq/{id}");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(UpdateFaqRequest request, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var id = Route<int>("id");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var faq = new FaqEntity
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Question = request.Question,
|
||||||
|
Answer = request.Answer,
|
||||||
|
Category = request.Category,
|
||||||
|
SortOrder = request.SortOrder,
|
||||||
|
IsActive = request.IsActive,
|
||||||
|
UpdatedAt = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
await _service.UpdateAsync(faq, ct);
|
||||||
|
await SendAsync(new FaqUpdateResponse { Message = "FAQ가 수정되었습니다." }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (ValidationException ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DeleteEndpoint : Endpoint<EmptyRequest, EmptyResponse>
|
||||||
|
{
|
||||||
|
private readonly FaqService _service;
|
||||||
|
public DeleteEndpoint(FaqService service) => _service = service;
|
||||||
|
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Delete("/api/faq/{id}");
|
||||||
|
Policies("Bearer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var id = Route<int>("id");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _service.DeleteAsync(id, ct);
|
||||||
|
await SendAsync(new EmptyResponse(), 204, cancellation: ct);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ThrowError(ex.Message, statusCode: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using TaxBaik.Application.Services;
|
||||||
|
|
||||||
|
namespace TaxBaik.Web.Endpoints.RevenueTracking;
|
||||||
|
|
||||||
|
public class CreateRequest
|
||||||
|
{
|
||||||
|
public int ClientId { get; set; }
|
||||||
|
public string InvoiceNumber { get; set; } = "";
|
||||||
|
public DateTime InvoiceDate { get; set; }
|
||||||
|
public decimal Amount { get; set; }
|
||||||
|
public string? ServiceType { get; set; }
|
||||||
|
public DateTime? DueDate { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MarkPaidRequest { public DateTime PaymentDate { get; set; } }
|
||||||
|
public class ListResp { public List<object> Data { get; set; } = []; }
|
||||||
|
public class IdResp { public int Id { get; set; } }
|
||||||
|
public class TotalResp { public decimal Total { get; set; } public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } }
|
||||||
|
public class MonthlyQry { public int Year { get; set; } public int Month { get; set; } }
|
||||||
|
public class DateRangeQry { public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } }
|
||||||
|
|
||||||
|
public class CreateEp : Endpoint<CreateRequest, IdResp>
|
||||||
|
{
|
||||||
|
readonly RevenueTrackingService _svc;
|
||||||
|
public CreateEp(RevenueTrackingService svc) => _svc = svc;
|
||||||
|
public override void Configure() { Post("/api/revenue-tracking"); Policies("Bearer"); }
|
||||||
|
public override async Task HandleAsync(CreateRequest r, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var id = await _svc.CreateAsync(r.ClientId, r.InvoiceNumber, r.InvoiceDate, r.Amount, r.ServiceType, r.DueDate, ct);
|
||||||
|
await SendAsync(new IdResp { Id = id }, 201, cancellation: ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetAllEp : Endpoint<EmptyRequest, ListResp>
|
||||||
|
{
|
||||||
|
readonly RevenueTrackingService _svc;
|
||||||
|
public GetAllEp(RevenueTrackingService svc) => _svc = svc;
|
||||||
|
public override void Configure() { Get("/api/revenue-tracking"); Policies("Bearer"); }
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var revs = await _svc.GetAllAsync(ct);
|
||||||
|
await SendAsync(new ListResp { Data = revs.Cast<object>().ToList() }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetByClientEp : Endpoint<EmptyRequest, ListResp>
|
||||||
|
{
|
||||||
|
readonly RevenueTrackingService _svc;
|
||||||
|
public GetByClientEp(RevenueTrackingService svc) => _svc = svc;
|
||||||
|
public override void Configure() { Get("/api/revenue-tracking/client/{clientId}"); Policies("Bearer"); }
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var id = Route<int>("clientId");
|
||||||
|
var revs = await _svc.GetByClientIdAsync(id, ct);
|
||||||
|
await SendAsync(new ListResp { Data = revs.Cast<object>().ToList() }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetPendingEp : Endpoint<EmptyRequest, ListResp>
|
||||||
|
{
|
||||||
|
readonly RevenueTrackingService _svc;
|
||||||
|
public GetPendingEp(RevenueTrackingService svc) => _svc = svc;
|
||||||
|
public override void Configure() { Get("/api/revenue-tracking/pending"); Policies("Bearer"); }
|
||||||
|
public override async Task HandleAsync(EmptyRequest _, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var revs = await _svc.GetPendingPaymentsAsync(ct);
|
||||||
|
await SendAsync(new ListResp { Data = revs.Cast<object>().ToList() }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetMonthlyEp : Endpoint<MonthlyQry, ListResp>
|
||||||
|
{
|
||||||
|
readonly RevenueTrackingService _svc;
|
||||||
|
public GetMonthlyEp(RevenueTrackingService svc) => _svc = svc;
|
||||||
|
public override void Configure() { Get("/api/revenue-tracking/monthly"); Policies("Bearer"); }
|
||||||
|
public override async Task HandleAsync(MonthlyQry r, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var monthDate = new DateTime(r.Year, r.Month, 1);
|
||||||
|
var revs = await _svc.GetMonthlyRevenueAsync(monthDate, ct);
|
||||||
|
await SendAsync(new ListResp { Data = revs.Cast<object>().ToList() }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetTotalEp : Endpoint<DateRangeQry, TotalResp>
|
||||||
|
{
|
||||||
|
readonly RevenueTrackingService _svc;
|
||||||
|
public GetTotalEp(RevenueTrackingService svc) => _svc = svc;
|
||||||
|
public override void Configure() { Get("/api/revenue-tracking/total"); Policies("Bearer"); }
|
||||||
|
public override async Task HandleAsync(DateRangeQry r, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var total = await _svc.GetTotalRevenueAsync(r.StartDate, r.EndDate, ct);
|
||||||
|
await SendAsync(new TotalResp { Total = total, StartDate = r.StartDate, EndDate = r.EndDate }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MarkPaidEp : Endpoint<MarkPaidRequest, object>
|
||||||
|
{
|
||||||
|
readonly RevenueTrackingService _svc;
|
||||||
|
public MarkPaidEp(RevenueTrackingService svc) => _svc = svc;
|
||||||
|
public override void Configure() { Put("/api/revenue-tracking/{id}/paid"); Policies("Bearer"); }
|
||||||
|
public override async Task HandleAsync(MarkPaidRequest r, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var id = Route<int>("id");
|
||||||
|
await _svc.MarkPaidAsync(id, r.PaymentDate, ct);
|
||||||
|
await SendAsync(new { message = "결제가 완료됨으로 표시되었습니다." }, 200, cancellation: ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user