From 65f2f914e7c347cd19f2b6a683c7c240d8bdfaaf Mon Sep 17 00:00:00 2001 From: SEAN Date: Tue, 10 Feb 2026 11:18:07 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20API=20=EA=B5=AC=ED=98=84=20(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DeleteServiceRequestDto 생성 (service_code 필수) - IServiceManagementService에 DeleteAsync 메서드 추가 - ServiceManagementService에 Soft Delete 로직 구현 (IsDeleted=true, DeletedAt=UtcNow, Status=Suspended) - ServiceController에 POST /v1/in/service/delete 엔드포인트 추가 Closes #68 --- SPMS.API/Controllers/ServiceController.cs | 15 ++++++++++ .../DTOs/Service/DeleteServiceRequestDto.cs | 11 ++++++++ .../Interfaces/IServiceManagementService.cs | 1 + .../Services/ServiceManagementService.cs | 28 +++++++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 SPMS.Application/DTOs/Service/DeleteServiceRequestDto.cs diff --git a/SPMS.API/Controllers/ServiceController.cs b/SPMS.API/Controllers/ServiceController.cs index 7c94cb4..8af1835 100644 --- a/SPMS.API/Controllers/ServiceController.cs +++ b/SPMS.API/Controllers/ServiceController.cs @@ -57,6 +57,21 @@ public class ServiceController : ControllerBase return Ok(ApiResponse.Success(result)); } + [HttpPost("delete")] + [SwaggerOperation( + Summary = "서비스 삭제", + Description = "서비스를 Soft Delete 처리합니다. IsDeleted=true, 상태를 Suspended로 변경합니다.")] + [SwaggerResponse(200, "삭제 성공", typeof(ApiResponse))] + [SwaggerResponse(401, "인증되지 않은 요청")] + [SwaggerResponse(403, "권한 없음")] + [SwaggerResponse(404, "서비스를 찾을 수 없음")] + [SwaggerResponse(409, "이미 삭제된 서비스")] + public async Task DeleteAsync([FromBody] DeleteServiceRequestDto request) + { + await _serviceManagementService.DeleteAsync(request); + return Ok(ApiResponse.Success()); + } + [HttpPost("list")] [SwaggerOperation( Summary = "서비스 목록 조회", diff --git a/SPMS.Application/DTOs/Service/DeleteServiceRequestDto.cs b/SPMS.Application/DTOs/Service/DeleteServiceRequestDto.cs new file mode 100644 index 0000000..9a77845 --- /dev/null +++ b/SPMS.Application/DTOs/Service/DeleteServiceRequestDto.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace SPMS.Application.DTOs.Service; + +public class DeleteServiceRequestDto +{ + [Required(ErrorMessage = "서비스 코드는 필수입니다.")] + [JsonPropertyName("service_code")] + public string ServiceCode { get; set; } = string.Empty; +} diff --git a/SPMS.Application/Interfaces/IServiceManagementService.cs b/SPMS.Application/Interfaces/IServiceManagementService.cs index 5d01a8c..19afd94 100644 --- a/SPMS.Application/Interfaces/IServiceManagementService.cs +++ b/SPMS.Application/Interfaces/IServiceManagementService.cs @@ -8,6 +8,7 @@ public interface IServiceManagementService Task UpdateAsync(UpdateServiceRequestDto request); Task GetListAsync(ServiceListRequestDto request); Task GetByServiceCodeAsync(string serviceCode); + Task DeleteAsync(DeleteServiceRequestDto request); Task ChangeStatusAsync(string serviceCode, ChangeServiceStatusRequestDto request); Task RefreshApiKeyAsync(string serviceCode); Task RegisterApnsCredentialsAsync(string serviceCode, ApnsCredentialsRequestDto request); diff --git a/SPMS.Application/Services/ServiceManagementService.cs b/SPMS.Application/Services/ServiceManagementService.cs index d382fdd..b70989b 100644 --- a/SPMS.Application/Services/ServiceManagementService.cs +++ b/SPMS.Application/Services/ServiceManagementService.cs @@ -233,6 +233,34 @@ public class ServiceManagementService : IServiceManagementService return MapToDto(serviceWithIps ?? service); } + public async Task DeleteAsync(DeleteServiceRequestDto request) + { + var service = await _serviceRepository.GetByServiceCodeAsync(request.ServiceCode); + if (service is null) + { + throw new SpmsException( + ErrorCodes.NotFound, + "서비스를 찾을 수 없습니다.", + 404); + } + + if (service.IsDeleted) + { + throw new SpmsException( + ErrorCodes.Conflict, + "이미 삭제된 서비스입니다.", + 409); + } + + service.IsDeleted = true; + service.DeletedAt = DateTime.UtcNow; + service.Status = ServiceStatus.Suspended; + service.UpdatedAt = DateTime.UtcNow; + + _serviceRepository.Update(service); + await _unitOfWork.SaveChangesAsync(); + } + public async Task ChangeStatusAsync(string serviceCode, ChangeServiceStatusRequestDto request) { var service = await _serviceRepository.GetByServiceCodeAsync(serviceCode); -- 2.45.1