forked from kimhyungsik/ax_hub_mcp_tool
Merge remote-tracking branch 'origin/main'
# Conflicts: # dat-was-lib/src/main/java/io/shinhanlife/dat/lib/util/ToolScaffolder.java # dat-was-pro/src/main/java/io/shinhanlife/dat/mcc/biz/pro/converter/RecruitmentFeeDisclosureDataConverter.java # dat-was-pro/src/main/java/io/shinhanlife/dat/mcc/biz/pro/dto/RecruitmentFeeDisclosureDataRequest.java # dat-was-sal/Dockerfile # dat-was-sal/build.gradle # dat-was-sal/src/main/java/io/shinhanlife/dat/mcc/sal/DatWasSalApplication.java # dat-was-sal/src/main/resources/application-dev.yml # dat-was-sal/src/main/resources/application-local.yml # dat-was-sal/src/main/resources/application-prod.yml # dat-was-sal/src/main/resources/application-test.yml # dat-was-sal/src/main/resources/application.yml # dat-was-sal/src/main/resources/logback-spring.xml # dat-was-sal/src/main/resources/tool-service-manifest.yml
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package io.shinhanlife.dat.lib.paging;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @package io.shinhanlife.dat.lib.paging
|
||||
* @className MciPagingUtils
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author 0986406
|
||||
* @create 2026.09.01
|
||||
* <pre>
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2026.09.01 0986406 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
public final class MciPagingUtils {
|
||||
|
||||
private MciPagingUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 페이징 응답 데이터(List 필드)를 대상(target) 객체에 순차적으로 병합(append)합니다.
|
||||
* 클래스 상속 계층 구조를 탐색하여 모든 List 타입 필드를 병합합니다.
|
||||
*
|
||||
* @param target 누적할 최종 응답 DTO
|
||||
* @param src 각 페이지별 응답 DTO
|
||||
*/
|
||||
public static void mergeResponseData(Object target, Object src) {
|
||||
if (target == null || src == null) {
|
||||
return;
|
||||
}
|
||||
Class<?> current = target.getClass();
|
||||
while (current != null && current != Object.class) {
|
||||
for (Field field : current.getDeclaredFields()) {
|
||||
if (List.class.isAssignableFrom(field.getType())) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
List<?> srcList = (List<?>) field.get(src);
|
||||
if (srcList != null && !srcList.isEmpty()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> targetList = (List<Object>) field.get(target);
|
||||
if (targetList == null) {
|
||||
targetList = new ArrayList<>(srcList);
|
||||
field.set(target, targetList);
|
||||
} else {
|
||||
if (!(targetList instanceof ArrayList)) {
|
||||
targetList = new ArrayList<>(targetList);
|
||||
field.set(target, targetList);
|
||||
}
|
||||
targetList.addAll(srcList);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("[MCI Tool] 리스트 병합 중 예외 발생 (field: {}): {}", field.getName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
current = current.getSuperclass();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package io.shinhanlife.dat.lib.util;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @package io.shinhanlife.dat.lib.util
|
||||
* @className CommonCodeResolver
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author 0986406
|
||||
* @create 2026.09.01
|
||||
* <pre>
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2026.09.01 0986406 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class CommonCodeResolver {
|
||||
|
||||
private static final String DEFAULT_RESOURCE_PATH = "codes.csv";
|
||||
|
||||
// Group -> (Code -> Name)
|
||||
private static final Map<String, Map<String, String>> CODE_TO_NAME_MAP = new ConcurrentHashMap<>();
|
||||
// Group -> (Normalized Name or Code -> Code)
|
||||
private static final Map<String, Map<String, String>> NAME_TO_CODE_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
static {
|
||||
loadCodes(DEFAULT_RESOURCE_PATH);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
loadCodes(DEFAULT_RESOURCE_PATH);
|
||||
}
|
||||
|
||||
public static synchronized void reload() {
|
||||
loadCodes(DEFAULT_RESOURCE_PATH);
|
||||
}
|
||||
|
||||
public static synchronized void loadCodes(String resourcePath) {
|
||||
ClassLoader classLoader = CommonCodeResolver.class.getClassLoader();
|
||||
try (InputStream is = classLoader.getResourceAsStream(resourcePath)) {
|
||||
if (is == null) {
|
||||
log.warn("[CommonCodeResolver] 리소스 파일을 찾을 수 없습니다: {}", resourcePath);
|
||||
return;
|
||||
}
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
||||
CODE_TO_NAME_MAP.clear();
|
||||
NAME_TO_CODE_MAP.clear();
|
||||
|
||||
String line;
|
||||
boolean firstLine = true;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (firstLine) {
|
||||
firstLine = false;
|
||||
if (line.startsWith("\uFEFF")) {
|
||||
line = line.substring(1);
|
||||
}
|
||||
if (line.contains("그룹") || line.contains("group")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
line = line.trim();
|
||||
if (line.isEmpty() || line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
String[] parts = line.split(",", -1);
|
||||
if (parts.length < 3) {
|
||||
continue;
|
||||
}
|
||||
String group = parts[0].trim().toUpperCase(Locale.ROOT);
|
||||
String code = parts[1].trim();
|
||||
String name = parts[2].trim();
|
||||
|
||||
if (group.isEmpty() || code.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, String> codeToName = CODE_TO_NAME_MAP.computeIfAbsent(group, k -> new ConcurrentHashMap<>());
|
||||
Map<String, String> nameToCode = NAME_TO_CODE_MAP.computeIfAbsent(group, k -> new ConcurrentHashMap<>());
|
||||
|
||||
codeToName.put(code, name);
|
||||
nameToCode.put(code, code);
|
||||
nameToCode.put(name, code);
|
||||
nameToCode.put(name.toLowerCase(Locale.ROOT), code);
|
||||
nameToCode.put(name.replace(" ", ""), code);
|
||||
}
|
||||
log.info("[CommonCodeResolver] 공통코드 로드 완료: {}개 그룹", CODE_TO_NAME_MAP.size());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[CommonCodeResolver] 공통코드 로드 중 오류 발생: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 입력값(명칭 또는 코드)을 처리계 표준 코드값으로 변환합니다.
|
||||
*
|
||||
* @param group 코드 그룹명 (예: COMPANY, STATUS)
|
||||
* @param input 사용자가 입력한 명칭("삼성전자") 또는 코드("005930")
|
||||
* @return 매핑된 코드값(예: "005930"). 매핑되지 않으면 원본 입력값 반환.
|
||||
*/
|
||||
public static String resolve(String group, String input) {
|
||||
return resolve(group, input, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* 입력값(명칭 또는 코드)을 처리계 표준 코드값으로 변환합니다.
|
||||
*
|
||||
* @param group 코드 그룹명
|
||||
* @param input 입력값
|
||||
* @param defaultValue 매핑 실패 시 반환할 기본값
|
||||
* @return 매핑된 코드값 또는 defaultValue
|
||||
*/
|
||||
public static String resolve(String group, String input, String defaultValue) {
|
||||
if (input == null || input.isBlank()) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (group == null) {
|
||||
return input.trim();
|
||||
}
|
||||
String normalizedGroup = group.trim().toUpperCase(Locale.ROOT);
|
||||
Map<String, String> nameToCode = NAME_TO_CODE_MAP.get(normalizedGroup);
|
||||
if (nameToCode == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
String trimmed = input.trim();
|
||||
String matched = nameToCode.get(trimmed);
|
||||
if (matched != null) {
|
||||
return matched;
|
||||
}
|
||||
matched = nameToCode.get(trimmed.toLowerCase(Locale.ROOT));
|
||||
if (matched != null) {
|
||||
return matched;
|
||||
}
|
||||
matched = nameToCode.get(trimmed.replace(" ", ""));
|
||||
if (matched != null) {
|
||||
return matched;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 코드값에 해당하는 표준 명칭을 반환합니다. (응답 변환 시 사용)
|
||||
*/
|
||||
public static String getName(String group, String code) {
|
||||
if (group == null || code == null) {
|
||||
return code;
|
||||
}
|
||||
String normalizedGroup = group.trim().toUpperCase(Locale.ROOT);
|
||||
Map<String, String> codeToName = CODE_TO_NAME_MAP.get(normalizedGroup);
|
||||
if (codeToName != null) {
|
||||
return codeToName.getOrDefault(code.trim(), code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 그룹의 전체 코드-명칭 맵을 반환합니다.
|
||||
*/
|
||||
public static Map<String, String> getCodeMap(String group) {
|
||||
if (group == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, String> map = CODE_TO_NAME_MAP.get(group.trim().toUpperCase(Locale.ROOT));
|
||||
return map != null ? Collections.unmodifiableMap(map) : Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
17
dat-was-lib/src/main/resources/codes.csv
Normal file
17
dat-was-lib/src/main/resources/codes.csv
Normal file
@@ -0,0 +1,17 @@
|
||||
그룹,코드,명칭
|
||||
COMPANY,005930,삼성전자
|
||||
COMPANY,035420,NAVER
|
||||
COMPANY,035720,카카오
|
||||
COMPANY,000660,SK하이닉스
|
||||
COMPANY,055550,신한지주
|
||||
COMPANY,086790,하나금융지주
|
||||
COMPANY,105560,KB금융
|
||||
COMPANY,316140,우리금융지주
|
||||
COMPANY,000810,삼성화재
|
||||
COMPANY,088350,한화생명
|
||||
COMPANY,005830,DB손해보험
|
||||
COMPANY,000030,우리은행
|
||||
STATUS,01,정상
|
||||
STATUS,02,비정상
|
||||
STATUS,03,해지
|
||||
STATUS,04,실효
|
||||
|
@@ -0,0 +1,62 @@
|
||||
package io.shinhanlife.dat.lib.util;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @package io.shinhanlife.dat.lib.util
|
||||
* @className CommonCodeResolverTest
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author 0986406
|
||||
* @create 2026.09.01
|
||||
* <pre>
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2026.09.01 0986406 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
class CommonCodeResolverTest {
|
||||
|
||||
@Test
|
||||
void resolvesCompanyCodeFromExactName() {
|
||||
assertEquals("005930", CommonCodeResolver.resolve("COMPANY", "삼성전자"));
|
||||
assertEquals("035420", CommonCodeResolver.resolve("COMPANY", "NAVER"));
|
||||
assertEquals("035720", CommonCodeResolver.resolve("COMPANY", "카카오"));
|
||||
assertEquals("055550", CommonCodeResolver.resolve("COMPANY", "신한지주"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvesCompanyCodeWhenAlreadyCode() {
|
||||
assertEquals("005930", CommonCodeResolver.resolve("COMPANY", "005930"));
|
||||
assertEquals("035420", CommonCodeResolver.resolve("COMPANY", "035420"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvesCaseInsensitiveAndSpaceIgnored() {
|
||||
assertEquals("035420", CommonCodeResolver.resolve("COMPANY", "naver"));
|
||||
assertEquals("005930", CommonCodeResolver.resolve("COMPANY", "삼성 전자"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolvesStatusGroupCode() {
|
||||
assertEquals("01", CommonCodeResolver.resolve("STATUS", "정상"));
|
||||
assertEquals("02", CommonCodeResolver.resolve("STATUS", "비정상"));
|
||||
assertEquals("03", CommonCodeResolver.resolve("STATUS", "해지"));
|
||||
assertEquals("01", CommonCodeResolver.resolve("STATUS", "01"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getsNameFromCode() {
|
||||
assertEquals("삼성전자", CommonCodeResolver.getName("COMPANY", "005930"));
|
||||
assertEquals("정상", CommonCodeResolver.getName("STATUS", "01"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnsOriginalWhenNotFound() {
|
||||
assertEquals("알수없는회사", CommonCodeResolver.resolve("COMPANY", "알수없는회사"));
|
||||
assertEquals("99", CommonCodeResolver.resolve("STATUS", "99"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package io.shinhanlife.dat.mcc.biz.pro.converter;
|
||||
|
||||
import io.shinhanlife.dat.lib.util.CommonCodeResolver;
|
||||
import io.shinhanlife.dat.mcc.biz.pro.dto.RecruitmentFeeDisclosureDataRequest;
|
||||
import io.shinhanlife.dat.mcc.biz.pro.dto.RecruitmentFeeDisclosureDataResponse;
|
||||
import io.shinhanlife.dat.mcc.infra.itrf.mci.nbt.i.io.ONBTI2370_I;
|
||||
import io.shinhanlife.dat.mcc.infra.itrf.mci.nbt.i.io.ONBTI2370_O;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
/**
|
||||
* @package io.shinhanlife.dat.mcc.biz.pro.converter
|
||||
* @className RecruitmentFeeDisclosureDataConverter
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author 0986406
|
||||
* @create 2026.09.01
|
||||
* <pre>
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2026.09.01 0986406 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface RecruitmentFeeDisclosureDataConverter {
|
||||
|
||||
@Mapping(target = "companyCode", expression = "java(toCompanyCode(request.getCompanyCode()))")
|
||||
ONBTI2370_I toLegacyRequest(RecruitmentFeeDisclosureDataRequest request);
|
||||
|
||||
default String toCompanyCode(String company) {
|
||||
return CommonCodeResolver.resolve("COMPANY", company);
|
||||
}
|
||||
|
||||
RecruitmentFeeDisclosureDataRequest toRequest(ONBTI2370_I mciRequest);
|
||||
RecruitmentFeeDisclosureDataResponse toResponse(ONBTI2370_O mciRes);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package io.shinhanlife.dat.mcc.biz.pro.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
|
||||
|
||||
/**
|
||||
* @package io.shinhanlife.dat.mcc.biz.pro.dto
|
||||
* @className RecruitmentFeeDisclosureDataRequest
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author 0986406
|
||||
* @create 2026.09.01
|
||||
* <pre>
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2026.09.01 0986406 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class RecruitmentFeeDisclosureDataRequest {
|
||||
@Schema(description = "조회할 회사 코드 또는 회사명 (예시: 005930, 삼성전자, NAVER, 카카오)", example = "삼성전자", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String companyCode;
|
||||
|
||||
@Schema(description = "조회할 연도 (형식: ^[0-9]{4}$) (예시: 2023, 2024)", example = "2023", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Pattern(regexp = "^[0-9]{4}$")
|
||||
private String year;
|
||||
|
||||
@Schema(description = "조회할 분기 (1-4) (형식: ^[1-4]$) (예시: 1, 2, 3, 4)", example = "1")
|
||||
@Pattern(regexp = "^[1-4]$")
|
||||
private String quarter;
|
||||
|
||||
@Schema(description = "조회 시작일 (YYYY-MM-DD) (형식: ^[0-9]{4}-[0-9]{2}-[0-9]{2}$) (예시: 2024-01-01, 2024-04-01)", example = "2024-01-01")
|
||||
@Pattern(regexp = "^[0-9]{4}-[0-9]{2}-[0-9]{2}$")
|
||||
private String startDate;
|
||||
|
||||
@Schema(description = "조회 종료일 (YYYY-MM-DD) (형식: ^[0-9]{4}-[0-9]{2}-[0-9]{2}$) (예시: 2024-03-31, 2024-06-30)", example = "2024-03-31")
|
||||
@Pattern(regexp = "^[0-9]{4}-[0-9]{2}-[0-9]{2}$")
|
||||
private String endDate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package io.shinhanlife.dat.mcc.biz.pro.converter;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import io.shinhanlife.dat.mcc.biz.pro.dto.RecruitmentFeeDisclosureDataRequest;
|
||||
import io.shinhanlife.dat.mcc.infra.itrf.mci.nbt.i.io.ONBTI2370_I;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
* @package io.shinhanlife.dat.mcc.biz.pro.converter
|
||||
* @className RecruitmentFeeDisclosureDataConverterTest
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author 0986406
|
||||
* @create 2026.09.01
|
||||
* <pre>
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2026.09.01 0986406 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
class RecruitmentFeeDisclosureDataConverterTest {
|
||||
|
||||
private final RecruitmentFeeDisclosureDataConverter converter =
|
||||
Mappers.getMapper(RecruitmentFeeDisclosureDataConverter.class);
|
||||
|
||||
@Test
|
||||
void mapsCompanyNameToLegacyCompanyCode() {
|
||||
RecruitmentFeeDisclosureDataRequest request = new RecruitmentFeeDisclosureDataRequest();
|
||||
request.setCompanyCode("삼성전자");
|
||||
request.setYear("2024");
|
||||
request.setQuarter("1");
|
||||
|
||||
ONBTI2370_I legacyReq = converter.toLegacyRequest(request);
|
||||
|
||||
assertNotNull(legacyReq);
|
||||
assertEquals("005930", legacyReq.getCompanyCode());
|
||||
assertEquals("2024", legacyReq.getYear());
|
||||
assertEquals("1", legacyReq.getQuarter());
|
||||
}
|
||||
|
||||
@Test
|
||||
void preservesCompanyCodeWhenAlreadyNumericCode() {
|
||||
RecruitmentFeeDisclosureDataRequest request = new RecruitmentFeeDisclosureDataRequest();
|
||||
request.setCompanyCode("035420");
|
||||
request.setYear("2024");
|
||||
|
||||
ONBTI2370_I legacyReq = converter.toLegacyRequest(request);
|
||||
|
||||
assertNotNull(legacyReq);
|
||||
assertEquals("035420", legacyReq.getCompanyCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void mapsNaverAndKakao() {
|
||||
RecruitmentFeeDisclosureDataRequest requestNaver = new RecruitmentFeeDisclosureDataRequest();
|
||||
requestNaver.setCompanyCode("NAVER");
|
||||
assertEquals("035420", converter.toLegacyRequest(requestNaver).getCompanyCode());
|
||||
|
||||
RecruitmentFeeDisclosureDataRequest requestKakao = new RecruitmentFeeDisclosureDataRequest();
|
||||
requestKakao.setCompanyCode("카카오");
|
||||
assertEquals("035720", converter.toLegacyRequest(requestKakao).getCompanyCode());
|
||||
}
|
||||
}
|
||||
7
dat-was-sal/Dockerfile
Normal file
7
dat-was-sal/Dockerfile
Normal file
@@ -0,0 +1,7 @@
|
||||
FROM eclipse-temurin:21-jre-alpine
|
||||
WORKDIR /app
|
||||
RUN apk add --no-cache tzdata
|
||||
ENV TZ=Asia/Seoul
|
||||
COPY dat-was-sal/build/libs/*-SNAPSHOT.jar app.jar
|
||||
EXPOSE 8083
|
||||
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||
9
dat-was-sal/build.gradle
Normal file
9
dat-was-sal/build.gradle
Normal file
@@ -0,0 +1,9 @@
|
||||
plugins {
|
||||
// Spring Boot 3.5.11 version is managed by the root build.gradle.
|
||||
id 'org.springframework.boot'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Shared MCP, Glow integration, validation, logging, Lombok and MapStruct configuration.
|
||||
implementation project(':dat-was-lib')
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.shinhanlife.dat.mcc.sal;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
|
||||
/**
|
||||
* @package io.shinhanlife.dat.mcc.sal
|
||||
* @className DatWasSalApplication
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author jade
|
||||
* @create 2026.09.08
|
||||
* <pre>
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2026.09.08 jade 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@SpringBootApplication(scanBasePackages = {"io.shinhanlife.dat.mcc", "io.shinhanlife.dat.lib"})
|
||||
@ConfigurationPropertiesScan(basePackages = {"io.shinhanlife.dat.mcc", "io.shinhanlife.dat.lib"})
|
||||
@EnableCaching
|
||||
public class DatWasSalApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DatWasSalApplication.class, args);
|
||||
}
|
||||
}
|
||||
11
dat-was-sal/src/main/resources/application-dev.yml
Normal file
11
dat-was-sal/src/main/resources/application-dev.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
server:
|
||||
port: ${PORT:8083}
|
||||
|
||||
spring:
|
||||
config:
|
||||
activate:
|
||||
on-profile: dev
|
||||
import:
|
||||
- classpath:application-core-dev.yml
|
||||
- classpath:glow/application-glow.yml
|
||||
- classpath:glow/application-glow-dev.yml
|
||||
7
dat-was-sal/src/main/resources/application-local.yml
Normal file
7
dat-was-sal/src/main/resources/application-local.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
spring:
|
||||
config:
|
||||
activate:
|
||||
on-profile: local
|
||||
import:
|
||||
- classpath:glow/application-glow.yml
|
||||
- classpath:glow/application-glow-local.yml
|
||||
11
dat-was-sal/src/main/resources/application-prod.yml
Normal file
11
dat-was-sal/src/main/resources/application-prod.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
server:
|
||||
port: ${PORT:8083}
|
||||
|
||||
spring:
|
||||
config:
|
||||
activate:
|
||||
on-profile: prod
|
||||
import:
|
||||
- classpath:application-core-prod.yml
|
||||
- classpath:glow/application-glow.yml
|
||||
- classpath:glow/application-glow-prod.yml
|
||||
11
dat-was-sal/src/main/resources/application-test.yml
Normal file
11
dat-was-sal/src/main/resources/application-test.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
server:
|
||||
port: ${PORT:8083}
|
||||
|
||||
spring:
|
||||
config:
|
||||
activate:
|
||||
on-profile: test
|
||||
import:
|
||||
- classpath:application-core-test.yml
|
||||
- classpath:glow/application-glow.yml
|
||||
- classpath:glow/application-glow-test.yml
|
||||
21
dat-was-sal/src/main/resources/application.yml
Normal file
21
dat-was-sal/src/main/resources/application.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
server:
|
||||
port: 8083
|
||||
spring:
|
||||
application:
|
||||
name: dat-was-sal
|
||||
config:
|
||||
import: optional:classpath:tool-service-manifest.yml
|
||||
profiles:
|
||||
active: local
|
||||
logging:
|
||||
level:
|
||||
org.apache.kafka: ERROR
|
||||
mcp:
|
||||
namespace: ""
|
||||
manifest:
|
||||
bundle-id: dat-was-sal
|
||||
name-prefix: ""
|
||||
security:
|
||||
api-key: ${TOOL_SERVER_API_KEY:tool-server-key}
|
||||
tenant-domains:
|
||||
TESTER-DEV: ALL
|
||||
24
dat-was-sal/src/main/resources/logback-spring.xml
Normal file
24
dat-was-sal/src/main/resources/logback-spring.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n" />
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${LOG_PATTERN}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>logs/dat-was-sal.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<fileNamePattern>logs/dat-was-sal-%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<maxHistory>30</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${LOG_PATTERN}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
<logger name="io.shinhanlife" level="DEBUG" />
|
||||
</configuration>
|
||||
22
dat-was-sal/src/main/resources/tool-service-manifest.yml
Normal file
22
dat-was-sal/src/main/resources/tool-service-manifest.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
mcp:
|
||||
manifest:
|
||||
routing-functions:
|
||||
- name: "route_to_dat-was-sal"
|
||||
server-id: "dat-was-sal"
|
||||
category-key: "sal"
|
||||
product-boundary: "영업 업무 서버를 위한 제품 범위 정의입니다."
|
||||
business-domain: "영업 조직 및 설계사 관리 도메인입니다."
|
||||
business-outcome: "영업 요청의 효율적인 처리와 설계사 업무 지원을 보장합니다."
|
||||
primary-entities: "영업 조직, 설계사, 고객"
|
||||
capabilities: "요청 라우팅, 업무 할당, 상태 조회"
|
||||
select-if: "요청의 주요 엔티티가 영업 조직 또는 설계사일 경우 선택합니다."
|
||||
reject-if: "요청이 다른 도메인에 속하거나 유효하지 않은 엔티티를 포함할 경우 거부합니다."
|
||||
confusable-servers:
|
||||
- "dat-was-cus"
|
||||
- "dat-was-ehr"
|
||||
- "dat-was-pro"
|
||||
- "dat-was-sys"
|
||||
decision-policy: "가장 가까운 영업 서버를 선택하고, 부하를 고려하여 결정합니다."
|
||||
description_serialization: "이 도구는 영업 요청을 처리하며, 영업 조직과 설계사 업무를 효율적으로 라우팅하고, 부\
|
||||
하를 고려한 결정 정책을 적용하여 적절한 서버로 분배합니다."
|
||||
Reference in New Issue
Block a user