snp-global/src/main/java/com/snp/batch/service/BypassConfigService.java
HYOJIN fab03a31bb feat(swagger): Swagger 응답 스키마 자동 생성 및 API 문서 개선 (#14)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:40:49 +09:00

193 lines
7.1 KiB
Java

package com.snp.batch.service;
import com.snp.batch.global.dto.BypassConfigRequest;
import com.snp.batch.global.dto.BypassConfigResponse;
import com.snp.batch.global.dto.BypassParamDto;
import com.snp.batch.global.model.BypassApiConfig;
import com.snp.batch.global.model.BypassApiParam;
import com.snp.batch.global.repository.BypassApiConfigRepository;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
/**
* BYPASS API 설정 CRUD 비즈니스 로직
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class BypassConfigService {
private final BypassApiConfigRepository configRepository;
private final EntityManager entityManager;
/**
* 설정 목록 조회
*/
public List<BypassConfigResponse> getConfigs() {
return configRepository.findAll().stream()
.map(this::toResponse)
.toList();
}
/**
* 설정 상세 조회
*/
public BypassConfigResponse getConfig(Long id) {
BypassApiConfig config = configRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("설정을 찾을 수 없습니다: " + id));
return toResponse(config);
}
/**
* 설정 등록
*/
@Transactional
public BypassConfigResponse createConfig(BypassConfigRequest request) {
String endpointName = extractEndpointName(request.getExternalPath());
if (configRepository.existsByDomainNameAndEndpointName(request.getDomainName(), endpointName)) {
throw new IllegalArgumentException(
"이미 존재하는 도메인+엔드포인트 조합입니다: " + request.getDomainName() + "/" + endpointName);
}
BypassApiConfig config = toEntity(request);
if (request.getParams() != null) {
request.getParams().forEach(p -> {
BypassApiParam param = toParamEntity(p);
param.setConfig(config);
config.getParams().add(param);
});
}
return toResponse(configRepository.save(config));
}
/**
* 설정 수정
*/
@Transactional
public BypassConfigResponse updateConfig(Long id, BypassConfigRequest request) {
BypassApiConfig config = configRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("설정을 찾을 수 없습니다: " + id));
config.setDomainName(request.getDomainName());
config.setDisplayName(request.getDisplayName());
config.setWebclientBean(request.getWebclientBean());
config.setExternalPath(request.getExternalPath());
config.setHttpMethod(request.getHttpMethod());
config.setDescription(request.getDescription());
config.setResponseSchemaClass(request.getResponseSchemaClass());
// params 교체: clear → flush(DELETE 실행) → 새로 추가
config.getParams().clear();
entityManager.flush();
if (request.getParams() != null) {
request.getParams().forEach(p -> {
BypassApiParam param = toParamEntity(p);
param.setConfig(config);
config.getParams().add(param);
});
}
return toResponse(configRepository.save(config));
}
/**
* 설정 삭제
*/
@Transactional
public void deleteConfig(Long id) {
if (!configRepository.existsById(id)) {
throw new IllegalArgumentException("설정을 찾을 수 없습니다: " + id);
}
configRepository.deleteById(id);
}
/**
* 코드 생성 완료 마킹
*/
@Transactional
public void markAsGenerated(Long id) {
BypassApiConfig config = configRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("설정을 찾을 수 없습니다: " + id));
config.setGenerated(true);
config.setGeneratedAt(LocalDateTime.now());
configRepository.save(config);
}
// ---- private 헬퍼 메서드 ----
private BypassConfigResponse toResponse(BypassApiConfig config) {
return BypassConfigResponse.builder()
.id(config.getId())
.domainName(config.getDomainName())
.endpointName(config.getEndpointName())
.displayName(config.getDisplayName())
.webclientBean(config.getWebclientBean())
.externalPath(config.getExternalPath())
.httpMethod(config.getHttpMethod())
.description(config.getDescription())
.responseSchemaClass(config.getResponseSchemaClass())
.generated(config.getGenerated())
.generatedAt(config.getGeneratedAt())
.createdAt(config.getCreatedAt())
.updatedAt(config.getUpdatedAt())
.params(config.getParams().stream().map(this::toParamDto).toList())
.build();
}
private BypassApiConfig toEntity(BypassConfigRequest request) {
return BypassApiConfig.builder()
.domainName(request.getDomainName())
.endpointName(extractEndpointName(request.getExternalPath()))
.displayName(request.getDisplayName())
.webclientBean(request.getWebclientBean())
.externalPath(request.getExternalPath())
.httpMethod(request.getHttpMethod() != null ? request.getHttpMethod() : "GET")
.description(request.getDescription())
.responseSchemaClass(request.getResponseSchemaClass())
.build();
}
/**
* externalPath의 마지막 세그먼트를 endpointName으로 추출
*/
private String extractEndpointName(String externalPath) {
if (externalPath == null || externalPath.isEmpty()) {
return "";
}
String[] segments = externalPath.split("/");
return segments[segments.length - 1];
}
private BypassApiParam toParamEntity(BypassParamDto dto) {
return BypassApiParam.builder()
.paramName(dto.getParamName())
.paramType(dto.getParamType() != null ? dto.getParamType() : "STRING")
.paramIn(dto.getParamIn() != null ? dto.getParamIn() : "QUERY")
.required(dto.getRequired() != null ? dto.getRequired() : true)
.description(dto.getDescription())
.sortOrder(dto.getSortOrder() != null ? dto.getSortOrder() : 0)
.example(dto.getExample())
.build();
}
private BypassParamDto toParamDto(BypassApiParam param) {
return BypassParamDto.builder()
.id(param.getId())
.paramName(param.getParamName())
.paramType(param.getParamType())
.paramIn(param.getParamIn())
.required(param.getRequired())
.description(param.getDescription())
.sortOrder(param.getSortOrder())
.example(param.getExample())
.build();
}
}