feat: 서비스 수정 API 구현 (#54)
All checks were successful
SPMS_API/pipeline/head This commit looks good

Reviewed-on: https://git.ipstein.myds.me/SPMS/SPMS_API/pulls/55
This commit is contained in:
김선규 2026-02-10 00:57:44 +00:00
commit b5b015255e
4 changed files with 103 additions and 0 deletions

View File

@ -41,6 +41,22 @@ public class ServiceController : ControllerBase
return Ok(ApiResponse<CreateServiceResponseDto>.Success(result));
}
[HttpPost("update")]
[SwaggerOperation(
Summary = "서비스 수정",
Description = "기존 서비스의 정보를 수정합니다. 서비스명, 설명, 웹훅 URL, 태그를 변경할 수 있습니다.")]
[SwaggerResponse(200, "수정 성공", typeof(ApiResponse<ServiceResponseDto>))]
[SwaggerResponse(400, "변경된 내용 없음")]
[SwaggerResponse(401, "인증되지 않은 요청")]
[SwaggerResponse(403, "권한 없음")]
[SwaggerResponse(404, "서비스를 찾을 수 없음")]
[SwaggerResponse(409, "이미 존재하는 서비스명")]
public async Task<IActionResult> UpdateAsync([FromBody] UpdateServiceRequestDto request)
{
var result = await _serviceManagementService.UpdateAsync(request);
return Ok(ApiResponse<ServiceResponseDto>.Success(result));
}
[HttpPost("list")]
[SwaggerOperation(
Summary = "서비스 목록 조회",

View File

@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
namespace SPMS.Application.DTOs.Service;
public class UpdateServiceRequestDto
{
[Required(ErrorMessage = "서비스 코드는 필수입니다.")]
public string ServiceCode { get; set; } = string.Empty;
[StringLength(100, ErrorMessage = "서비스명은 100자 이내여야 합니다.")]
public string? ServiceName { get; set; }
[StringLength(500, ErrorMessage = "설명은 500자 이내여야 합니다.")]
public string? Description { get; set; }
[StringLength(500, ErrorMessage = "웹훅 URL은 500자 이내여야 합니다.")]
public string? WebhookUrl { get; set; }
public string? Tags { get; set; }
}

View File

@ -5,6 +5,7 @@ namespace SPMS.Application.Interfaces;
public interface IServiceManagementService
{
Task<CreateServiceResponseDto> CreateAsync(CreateServiceRequestDto request, long adminId);
Task<ServiceResponseDto> UpdateAsync(UpdateServiceRequestDto request);
Task<ServiceListResponseDto> GetListAsync(ServiceListRequestDto request);
Task<ServiceResponseDto> GetByServiceCodeAsync(string serviceCode);
Task<ServiceResponseDto> ChangeStatusAsync(string serviceCode, ChangeServiceStatusRequestDto request);

View File

@ -77,6 +77,72 @@ public class ServiceManagementService : IServiceManagementService
};
}
public async Task<ServiceResponseDto> UpdateAsync(UpdateServiceRequestDto request)
{
var service = await _serviceRepository.GetByServiceCodeAsync(request.ServiceCode);
if (service is null)
{
throw new SpmsException(
ErrorCodes.NotFound,
"서비스를 찾을 수 없습니다.",
404);
}
var hasChanges = false;
// ServiceName 변경
if (request.ServiceName != null && request.ServiceName != service.ServiceName)
{
var nameExists = await _serviceRepository.ServiceNameExistsAsync(request.ServiceName);
if (nameExists)
{
throw new SpmsException(
ErrorCodes.Conflict,
"이미 존재하는 서비스명입니다.",
409);
}
service.ServiceName = request.ServiceName;
hasChanges = true;
}
// Description 변경
if (request.Description != null && request.Description != service.Description)
{
service.Description = request.Description;
hasChanges = true;
}
// WebhookUrl 변경
if (request.WebhookUrl != null && request.WebhookUrl != service.WebhookUrl)
{
service.WebhookUrl = request.WebhookUrl;
hasChanges = true;
}
// Tags 변경
if (request.Tags != null && request.Tags != service.Tags)
{
service.Tags = request.Tags;
hasChanges = true;
}
if (!hasChanges)
{
throw new SpmsException(
ErrorCodes.NoChange,
"변경된 내용이 없습니다.",
400);
}
service.UpdatedAt = DateTime.UtcNow;
_serviceRepository.Update(service);
await _unitOfWork.SaveChangesAsync();
var serviceWithIps = await _serviceRepository.GetByIdWithIpsAsync(service.Id);
return MapToDto(serviceWithIps ?? service);
}
private async Task<string> GenerateUniqueServiceCodeAsync()
{
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";