- BypassApiConfig에 endpointName 필드 추가 (externalPath에서 자동 추출) - domainName unique 제약 → domainName + endpointName 복합 unique로 변경 - 코드 생성 시 같은 도메인의 모든 설정을 합쳐 Controller 1개 생성 - Service/DTO는 엔드포인트별로 별도 생성 - CodeGenerationResult에 servicePaths/dtoPaths 목록 반환 - 프론트엔드 타입/UI 업데이트 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
245 lines
9.0 KiB
Java
245 lines
9.0 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.BypassFieldDto;
|
|
import com.snp.batch.global.dto.BypassParamDto;
|
|
import com.snp.batch.global.model.BypassApiConfig;
|
|
import com.snp.batch.global.model.BypassApiField;
|
|
import com.snp.batch.global.model.BypassApiParam;
|
|
import com.snp.batch.global.repository.BypassApiConfigRepository;
|
|
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;
|
|
|
|
/**
|
|
* 설정 목록 조회
|
|
*
|
|
* @return 전체 BYPASS API 설정 목록
|
|
*/
|
|
public List<BypassConfigResponse> getConfigs() {
|
|
return configRepository.findAll().stream()
|
|
.map(this::toResponse)
|
|
.toList();
|
|
}
|
|
|
|
/**
|
|
* 설정 상세 조회
|
|
*
|
|
* @param id 설정 ID
|
|
* @return 설정 상세 정보
|
|
*/
|
|
public BypassConfigResponse getConfig(Long id) {
|
|
BypassApiConfig config = configRepository.findById(id)
|
|
.orElseThrow(() -> new IllegalArgumentException("설정을 찾을 수 없습니다: " + id));
|
|
return toResponse(config);
|
|
}
|
|
|
|
/**
|
|
* 설정 등록
|
|
*
|
|
* @param request 등록 요청 DTO
|
|
* @return 등록된 설정 정보
|
|
*/
|
|
@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);
|
|
});
|
|
}
|
|
if (request.getFields() != null) {
|
|
request.getFields().forEach(f -> {
|
|
BypassApiField field = toFieldEntity(f);
|
|
field.setConfig(config);
|
|
config.getFields().add(field);
|
|
});
|
|
}
|
|
return toResponse(configRepository.save(config));
|
|
}
|
|
|
|
/**
|
|
* 설정 수정
|
|
*
|
|
* @param id 설정 ID
|
|
* @param request 수정 요청 DTO
|
|
* @return 수정된 설정 정보
|
|
*/
|
|
@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.setResponseType(request.getResponseType());
|
|
config.setDescription(request.getDescription());
|
|
|
|
// params 교체 (orphanRemoval로 기존 자동 삭제)
|
|
config.getParams().clear();
|
|
if (request.getParams() != null) {
|
|
request.getParams().forEach(p -> {
|
|
BypassApiParam param = toParamEntity(p);
|
|
param.setConfig(config);
|
|
config.getParams().add(param);
|
|
});
|
|
}
|
|
|
|
// fields 교체
|
|
config.getFields().clear();
|
|
if (request.getFields() != null) {
|
|
request.getFields().forEach(f -> {
|
|
BypassApiField field = toFieldEntity(f);
|
|
field.setConfig(config);
|
|
config.getFields().add(field);
|
|
});
|
|
}
|
|
|
|
return toResponse(configRepository.save(config));
|
|
}
|
|
|
|
/**
|
|
* 설정 삭제
|
|
*
|
|
* @param id 설정 ID
|
|
*/
|
|
@Transactional
|
|
public void deleteConfig(Long id) {
|
|
if (!configRepository.existsById(id)) {
|
|
throw new IllegalArgumentException("설정을 찾을 수 없습니다: " + id);
|
|
}
|
|
configRepository.deleteById(id);
|
|
}
|
|
|
|
/**
|
|
* 코드 생성 완료 마킹
|
|
*
|
|
* @param id 설정 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())
|
|
.responseType(config.getResponseType())
|
|
.description(config.getDescription())
|
|
.generated(config.getGenerated())
|
|
.generatedAt(config.getGeneratedAt())
|
|
.createdAt(config.getCreatedAt())
|
|
.updatedAt(config.getUpdatedAt())
|
|
.params(config.getParams().stream().map(this::toParamDto).toList())
|
|
.fields(config.getFields().stream().map(this::toFieldDto).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")
|
|
.responseType(request.getResponseType() != null ? request.getResponseType() : "LIST")
|
|
.description(request.getDescription())
|
|
.build();
|
|
}
|
|
|
|
/**
|
|
* externalPath의 마지막 세그먼트를 endpointName으로 추출
|
|
* 예: "/RiskAndCompliance/CompliancesByImos" → "CompliancesByImos"
|
|
*/
|
|
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)
|
|
.build();
|
|
}
|
|
|
|
private BypassApiField toFieldEntity(BypassFieldDto dto) {
|
|
return BypassApiField.builder()
|
|
.fieldName(dto.getFieldName())
|
|
.jsonProperty(dto.getJsonProperty())
|
|
.fieldType(dto.getFieldType() != null ? dto.getFieldType() : "String")
|
|
.description(dto.getDescription())
|
|
.sortOrder(dto.getSortOrder() != null ? dto.getSortOrder() : 0)
|
|
.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())
|
|
.build();
|
|
}
|
|
|
|
private BypassFieldDto toFieldDto(BypassApiField field) {
|
|
return BypassFieldDto.builder()
|
|
.id(field.getId())
|
|
.fieldName(field.getFieldName())
|
|
.jsonProperty(field.getJsonProperty())
|
|
.fieldType(field.getFieldType())
|
|
.description(field.getDescription())
|
|
.sortOrder(field.getSortOrder())
|
|
.build();
|
|
}
|
|
}
|