refactor: rename dap-tool-other to dap-tool-oth
Some checks failed
Deploy to OCIWP / deploy (push) Has been cancelled

This commit is contained in:
jade
2026-07-25 01:36:12 +09:00
parent 7ba18f7809
commit 92fe2399be
67 changed files with 28 additions and 28 deletions

View File

@@ -0,0 +1,25 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className BalanceRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
import io.shinhanlife.dap.lib.annotation.McpParameter;
import lombok.Data;
@Data
public class BalanceRequest {
@McpParameter(description = "고객의 계좌번호 (- 제외)", required = true)
private String accountNumber;
}

View File

@@ -0,0 +1,26 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className BalanceResponse
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
import lombok.Data;
@Data
public class BalanceResponse {
private String status;
private String message;
private String accountNumber;
private long balance;
}

View File

@@ -0,0 +1,37 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import io.shinhanlife.dap.lib.annotation.McpParameter;
import lombok.Getter;
import lombok.Setter;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className BillingProcessRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BillingProcessRequest {
@McpParameter(description = "처리할 청구 접수 번호", required = true)
private String billingId;
@McpParameter(description = "심사 승인 여부 (예: APPROVE, REJECT)")
private String approvalStatus;
}

View File

@@ -0,0 +1,34 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import io.shinhanlife.dap.lib.annotation.McpParameter;
import lombok.Getter;
import lombok.Setter;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className BillingStatusRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BillingStatusRequest {
@McpParameter(description = "조회할 청구 접수 번호", required = true)
private String billingId;
}

View File

@@ -0,0 +1,34 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import io.shinhanlife.dap.lib.annotation.McpParameter;
import lombok.Getter;
import lombok.Setter;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className BondCheckRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BondCheckRequest {
@McpParameter(description = "확인하고자 하는 디지털 증권 발행 금액", required = true)
private Long amount;
}

View File

@@ -0,0 +1,37 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import io.shinhanlife.dap.lib.annotation.McpParameter;
import lombok.Getter;
import lombok.Setter;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className BondIssueRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BondIssueRequest {
@McpParameter(description = "발행할 디지털 증권 금액", required = true)
private Long amount;
@McpParameter(description = "발행 대상 계좌 번호", required = true)
private String targetAccount;
}

View File

@@ -0,0 +1,37 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import io.shinhanlife.dap.lib.annotation.McpParameter;
import lombok.Getter;
import lombok.Setter;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className ContractDetailRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ContractDetailRequest {
@McpParameter(description = "고객명", required = true)
private String customerName;
@McpParameter(description = "조회할 계약 번호", required = true)
private String contractId;
}

View File

@@ -0,0 +1,37 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import io.shinhanlife.dap.lib.annotation.McpParameter;
import lombok.Getter;
import lombok.Setter;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className ContractStatusRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ContractStatusRequest {
@McpParameter(description = "고객명", required = true)
private String customerName;
@McpParameter(description = "조회할 계약 번호")
private String contractId;
}

View File

@@ -0,0 +1,37 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import io.shinhanlife.dap.lib.annotation.McpParameter;
import lombok.Getter;
import lombok.Setter;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className CustomerDetailRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CustomerDetailRequest {
@McpParameter(description = "고객명", required = true)
private String customerName;
@McpParameter(description = "고객 식별 번호 (CID)")
private String customerId;
}

View File

@@ -0,0 +1,37 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import io.shinhanlife.dap.lib.annotation.McpParameter;
import lombok.Getter;
import lombok.Setter;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className CustomerGradeRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CustomerGradeRequest {
@McpParameter(description = "고객 이름 (예: 김신한)", required = true)
private String customerName;
@McpParameter(description = "고객 식별 번호 (CID)")
private String customerId;
}

View File

@@ -0,0 +1,34 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import io.shinhanlife.dap.lib.annotation.McpParameter;
import lombok.Getter;
import lombok.Setter;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className LeaveCountRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class LeaveCountRequest {
@McpParameter(description = "연차 내역을 조회할 사원 번호", required = true)
private String employeeId;
}

View File

@@ -0,0 +1,32 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.shinhanlife.glow.GlowMciFieldInfo;
import lombok.Data;
import java.util.List;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className MciSampleStringResponse
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MciSampleStringResponse {
@GlowMciFieldInfo(order = 1, length = 10, description = "이름")
private String name;
@GlowMciFieldInfo(order = 2, length = 3, description = "나이")
private int age;
@GlowMciFieldInfo(order = 3, length = 8, description = "가입일자(YYYYMMDD)")
private String joinDate;
@GlowMciFieldInfo(order = 4, length = 2, description = "상태코드")
private String statusCode;
@GlowMciFieldInfo(order = 5, length = 30, description = "타겟 리스트", target = MciSampleTargetDto.class)
private List<MciSampleTargetDto> targetList;
}

View File

@@ -0,0 +1,20 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import io.shinhanlife.glow.GlowMciFieldInfo;
import lombok.Data;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className MciSampleTargetDto
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
*/
@Data
public class MciSampleTargetDto {
@GlowMciFieldInfo(order = 1, length = 5, description = "항목 코드")
private String itemCode;
@GlowMciFieldInfo(order = 2, length = 5, description = "항목 값")
private String itemValue;
}

View File

@@ -0,0 +1,24 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className SampleStringRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SampleStringRequest {
private String query;
}

View File

@@ -0,0 +1,38 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.shinhanlife.glow.GlowTrgmField;
import lombok.Data;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className SampleStringResponse
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SampleStringResponse {
@GlowTrgmField(order = 1, length = 10, description = "이름")
private String name;
@GlowTrgmField(order = 2, length = 3, description = "나이")
private int age;
@GlowTrgmField(order = 3, length = 8, description = "가입일자(YYYYMMDD)")
private String joinDate;
@GlowTrgmField(order = 4, length = 2, description = "상태코드")
private String statusCode;
@GlowTrgmField(order = 5, length = 10, description = "타겟")
private String target;
}

View File

@@ -0,0 +1,35 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className TemplateDownloadRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Getter
@Builder
@ToString
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class TemplateDownloadRequest {
/**
* 다운로드할 템플릿의 종류 ID (예: CUSTOMER_EXCEL, PRODUCT_PDF 등)
*/
private String templateId;
}

View File

@@ -0,0 +1,37 @@
package io.shinhanlife.dap.mcc.biz.cmm.dto;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import io.shinhanlife.dap.lib.annotation.McpParameter;
import lombok.Getter;
import lombok.Setter;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className VacationRegisterRequest
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VacationRegisterRequest {
@McpParameter(description = "연차를 등록할 사원 번호", required = true)
private String employeeId;
@McpParameter(description = "휴가 일자 (YYYY-MM-DD 형식)", required = true)
private String date;
}

View File

@@ -0,0 +1,16 @@
package io.shinhanlife.dap.mcc.biz.cmm.io;
import lombok.Data;
/**
* @package io.shinhanlife.dap.mcc.infra.itrf.mci.sample.io
* @className CUST_INQ_001_I
* @description 고객 정보 조회 샘플 MCI 요청 전문
* @author 0986406
* @create 2026.09.01
*/
@Data
public class CUST_INQ_001_I {
private String customerId;
private String inquiryType;
}

View File

@@ -0,0 +1,15 @@
package io.shinhanlife.dap.mcc.biz.cmm.io;
import lombok.Data;
/**
* @package io.shinhanlife.dap.mcc.infra.itrf.mci.sample.io
* @className CUST_INQ_001_O
* @description 고객 정보 조회 샘플 MCI 응답 전문
* @author 0986406
* @create 2026.09.01
*/
@Data
public class CUST_INQ_001_O {
private Object resultData;
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase;
import io.shinhanlife.dap.mcc.biz.cmm.dto.*;
public interface BalanceUseCase {
Object execute(BalanceRequest req);
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase;
import io.shinhanlife.dap.mcc.biz.cmm.dto.*;
public interface BillingProcessUseCase {
Object getStatus(BillingStatusRequest req);
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase;
import io.shinhanlife.dap.mcc.biz.cmm.dto.*;
public interface BondIssueUseCase {
Object check(BondCheckRequest req);
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase;
import io.shinhanlife.dap.mcc.biz.cmm.dto.*;
public interface CommonUtilityUseCase {
Object registerVacation(VacationRegisterRequest req);
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase;
import io.shinhanlife.dap.mcc.biz.cmm.dto.*;
public interface ContractInquiryUseCase {
Object getStatus(ContractStatusRequest req);
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase;
import io.shinhanlife.dap.mcc.biz.cmm.dto.*;
public interface CustomerInfoUseCase {
Object getGrade(CustomerGradeRequest req);
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase;
import io.shinhanlife.dap.mcc.biz.cmm.dto.*;
public interface SampleMciToolUseCase {
Object inquiryCustomerInfo(io.shinhanlife.dap.mcc.biz.cmm.usecase.impl.SampleMciToolUseCaseImpl.SampleMciRequest req);
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase;
import io.shinhanlife.dap.mcc.biz.cmm.dto.*;
public interface SampleStringToolUseCase {
Object execute(SampleStringRequest req);
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase;
import io.shinhanlife.dap.mcc.biz.cmm.dto.*;
public interface TemplateUtilityUseCase {
java.util.Map<String, Object> getTemplateFileUrl(TemplateDownloadRequest req);
}

View File

@@ -0,0 +1,55 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase.impl;
/**
* @package io.shinhanlife.dap.mcc.service
* @className BalanceService
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.cmm.usecase.BalanceUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import io.shinhanlife.dap.mcc.biz.cmm.dto.BalanceRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Map;
@Slf4j
@Service
@McpTool(routingType = "MCI", categoryKey = "cmm")
public class BalanceUseCaseImpl extends AbstractMcpToolService implements BalanceUseCase {
@McpFunction(register = false, displayName = "balance 툴", name = "balance",
description = "고객의 계좌 잔액을 조회합니다.",
prompt = "고객 계좌 잔액을 조회해줘.",
mappingId = "ACC_001"
)
@Override
public Object execute(BalanceRequest req) {
log.info("[Balance] 계좌 잔액 조회 요청 수신. 계좌번호: {}", req.getAccountNumber());
// 레거시 연동
Map<String, Object> result = executeLegacy("MCI", "ACC_001", req);
// 가짜 데이터 응답 매핑 (AI 에이전트가 그럴듯하게 보여주기 위함)
if ("SUCCESS".equals(result.get("status"))) {
result.put("accountNumber", req.getAccountNumber());
result.put("balance", 1520300); // 1,520,300원 (가상의 잔액)
result.put("currency", "KRW");
result.put("message", "잔액 조회가 완료되었습니다.");
}
return result;
}
}

View File

@@ -0,0 +1,71 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase.impl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.cmm.usecase.BillingProcessUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import io.shinhanlife.dap.mcc.biz.cmm.dto.BillingProcessRequest;
import io.shinhanlife.dap.mcc.biz.cmm.dto.BillingStatusRequest;
import java.util.HashMap;
import java.util.Map;
@McpTool(
routingType = "MCI",
categoryKey = "claim"
)
/**
* @package io.shinhanlife.dap.mcc.service
* @className BillingProcessService
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@lombok.extern.slf4j.Slf4j
public class BillingProcessUseCaseImpl extends AbstractMcpToolService implements BillingProcessUseCase {
@McpFunction(register = false, displayName = "status 툴", name = "status", description = "청구심사 상태 조회", prompt = "현재 접수된 청구건 상태를 알려줘.", mappingId = "BILL_001")
@Override
public Object getStatus(BillingStatusRequest data) {
return executeBillingLogic("BILL_001", data);
}
@McpFunction(register = false, displayName = "process 툴", name = "process", description = "청구 처리", prompt = "현재 접수된 청구건에 대한 심사 처리를 진행해.", mappingId = "BILL_002")
public Object processBilling(BillingProcessRequest data) {
return executeBillingLogic("BILL_002", data);
}
private Object executeBillingLogic(String mappingId, Object data) {
log.info(" [Billing] 청구 처리 전용 커스텀 전/후처리 로직 수행 시작");
Map<String, Object> payload;
if (data == null) {
payload = new HashMap<>();
} else {
ObjectMapper mapper = new ObjectMapper();
payload = mapper.convertValue(data, new TypeReference<Map<String, Object>>() {});
}
// 커스텀 전처리
payload.put("custom_injected_data", "Billing System Check OK");
log.info(" [Billing] 커스텀 파라미터 주입 완료");
// 부모 클래스의 레거시 공통 연동 메서드 호출 (PII 마스킹 포함)
Map<String, Object> result = executeLegacy("MCI", mappingId, payload);
// 커스텀 후처리
if ("SUCCESS".equals(result.get("status"))) {
result.put("billing_custom_insight", "청구 특화 후처리 로직이 적용되었습니다.");
}
return result;
}
}

View File

@@ -0,0 +1,40 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase.impl;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.cmm.usecase.BondIssueUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import io.shinhanlife.dap.mcc.biz.cmm.dto.BondCheckRequest;
import io.shinhanlife.dap.mcc.biz.cmm.dto.BondIssueRequest;
@McpTool(
routingType = "EAI",
categoryKey = "policy"
)
/**
* @package io.shinhanlife.dap.mcc.service
* @className BondIssueService
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
public class BondIssueUseCaseImpl extends AbstractMcpToolService implements BondIssueUseCase {
@McpFunction(displayName = "check 툴", name = "check", register = false, description = "발행 가능 여부 조회 테스트", prompt = "디지털 증권 발행 한도가 충분한지 확인해줘.", mappingId = "BOND_001")
@Override
public Object check(BondCheckRequest data) {
return executeLegacy("EAI", "BOND_001", data);
}
@McpFunction(displayName = "issue 툴", name = "issue", register = false, description = "증권 발행 테스트1", prompt = "디지털 증권 발행 프로세스를 실행해.", mappingId = "BOND_002")
public Object issue(BondIssueRequest data) {
return executeLegacy("EAI", "BOND_002", data);
}
}

View File

@@ -0,0 +1,46 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase.impl;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.cmm.usecase.CommonUtilityUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import io.shinhanlife.dap.mcc.biz.cmm.dto.LeaveCountRequest;
import io.shinhanlife.dap.mcc.biz.cmm.dto.VacationRegisterRequest;
@McpTool(
routingType = "HTTP",
categoryKey = "hr"
)
/**
* @package io.shinhanlife.dap.mcc.service
* @className CommonUtilityService
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
public class CommonUtilityUseCaseImpl extends AbstractMcpToolService implements CommonUtilityUseCase {
@McpFunction(register = false, displayName = "register_vacation 툴", name = "register_vacation", description = "휴가 등록", prompt = "내일 하루 연차 휴가를 등록해줘.", mappingId = "HR_VAC_01")
@Override
public Object registerVacation(VacationRegisterRequest data) {
return executeLegacy("HTTP", "HR_VAC_01", data);
}
@McpFunction(register = false, displayName = "get_leave_count 툴", name = "get_leave_count", description = "연차 갯수 조회", prompt = "현재 사용 가능한 남은 연차 일수를 알려줘.", mappingId = "HR_VAC_02")
public Object getLeaveCount(LeaveCountRequest data) {
return executeLegacy("HTTP", "HR_VAC_02", data);
}
@McpFunction(register = false, displayName = "secret_tool 툴", name = "secret_tool", description = "비공개 툴 테스트", prompt = "숨겨진 툴 강제 호출", mappingId = "SECRET_001", visible = false)
public Object secretTool(LeaveCountRequest data) {
return executeLegacy("HTTP", "SECRET_001", data);
}
}

View File

@@ -0,0 +1,40 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase.impl;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.cmm.usecase.ContractInquiryUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import io.shinhanlife.dap.mcc.biz.cmm.dto.ContractDetailRequest;
import io.shinhanlife.dap.mcc.biz.cmm.dto.ContractStatusRequest;
@McpTool(
routingType = "HTTP",
categoryKey = "contract"
)
/**
* @package io.shinhanlife.dap.mcc.service
* @className ContractInquiryService
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
public class ContractInquiryUseCaseImpl extends AbstractMcpToolService implements ContractInquiryUseCase {
@McpFunction(register = false, displayName = "contract_status 툴", name = "contract_status", description = "계약상태 조회", prompt = "김신한 고객의 현재 계약 상태를 조회해줘.", mappingId = "CNTR_001")
@Override
public Object getStatus(ContractStatusRequest data) {
return executeLegacy("HTTP", "CNTR_001", data);
}
@McpFunction(register = false, displayName = "contract_detail 툴", name = "contract_detail", description = "계약상세 조회", prompt = "김신한 고객의 계약 상세 내역을 알려줘.", mappingId = "CNTR_002")
public Object getDetail(ContractDetailRequest data) {
return executeLegacy("HTTP", "CNTR_002", data);
}
}

View File

@@ -0,0 +1,40 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase.impl;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.cmm.usecase.CustomerInfoUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import io.shinhanlife.dap.mcc.biz.cmm.dto.CustomerDetailRequest;
import io.shinhanlife.dap.mcc.biz.cmm.dto.CustomerGradeRequest;
@McpTool(
routingType = "TCP",
categoryKey = "customer"
)
/**
* @package io.shinhanlife.dap.mcc.service
* @className CustomerInfoService
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
public class CustomerInfoUseCaseImpl extends AbstractMcpToolService implements CustomerInfoUseCase {
@McpFunction(register = false, displayName = "grade 툴", name = "grade", description = "고객등급 조회", prompt = "이 고객의 VIP 등급을 조회해줘.", mappingId = "CRM_001")
@Override
public Object getGrade(CustomerGradeRequest req) {
return executeLegacy("TCP", "CRM_001", req);
}
@McpFunction(register = false, displayName = "detail 툴", name = "detail", description = "고객상세 정보 조회", prompt = "이 고객의 상세 기본정보(주소, 연락처 등)를 알려줘.", mappingId = "CRM_002")
public Object getDetail(CustomerDetailRequest data) {
return executeLegacy("TCP", "CRM_002", data);
}
}

View File

@@ -0,0 +1,90 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase.impl;
import io.shinhanlife.dap.mcc.biz.cmm.io.CUST_INQ_001_I;
import io.shinhanlife.dap.lib.adapter.sender.ShinhanMciSender;
import io.shinhanlife.dap.lib.integration.mci.dto.MciRequestWrapper;
import io.shinhanlife.dap.lib.integration.mci.dto.ShinhanCommonHeaderDto;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.cmm.usecase.SampleMciToolUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
/**
* @package io.shinhanlife.dap.mcc.service
* @className SampleMciToolService
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Slf4j
@RequiredArgsConstructor
@McpTool(routingType = "MCI", categoryKey = "other") // MCP Tool 등록 어노테이션
public class SampleMciToolUseCaseImpl implements SampleMciToolUseCase {
// EIMS/MCI 발송을 담당하는 Sender 주입
private final ShinhanMciSender shinhanMciSender;
@Value("${shinhan.integration.mci.default-url:http://localhost:8081/api/mock/esb/api}")
private String mciTargetUrl;
// AI가 인식할 파라미터 DTO
@Data
public static class SampleMciRequest {
private String customerId;
private String inquiryType;
}
/**
* AI Agent가 호출하게 될 메서드입니다.
*/
@McpFunction(register = false, name = "inquiry_customer_mci",
displayName = "고객 정보 조회 (MCI)",
description = "MCI 연동을 통해 고객의 상세 정보를 조회합니다.",
prompt = "고객 정보를 조회해줘.",
mappingId = "CUST_INQ_001"
)
public Object inquiryCustomerInfo(SampleMciRequest req) {
log.info("[MCI Tool] 고객 정보 조회 요청 수신. 고객ID: {}", req.getCustomerId());
try {
// 1. MCI 전문 통신을 위한 Wrapper 객체 생성
MciRequestWrapper<CUST_INQ_001_I> wrapper = new MciRequestWrapper<>();
// 2. 공통 헤더 세팅 (인터페이스 ID, 서비스 ID 등 업무에 맞게 설정)
ShinhanCommonHeaderDto header = new ShinhanCommonHeaderDto();
header.setItrIfId("CUST_INQ_001");
header.setRcvSvcId("INQ9040");
wrapper.setTgrmCmnnhddValu(header);
// 3. 비즈니스 데이터(Body) 세팅 (인터페이스 IO 매핑)
CUST_INQ_001_I mciReq = new CUST_INQ_001_I();
mciReq.setCustomerId(req.getCustomerId());
mciReq.setInquiryType(req.getInquiryType());
wrapper.setBody(mciReq);
// 4. ShinhanMciSender를 통해 실제 연동 수행 및 응답 수신
log.info("[MCI Tool] ShinhanMciSender 연동 시작... (URL: {})", mciTargetUrl);
String responseJson = shinhanMciSender.send(mciTargetUrl, wrapper);
log.info("[MCI Tool] MCI 연동 성공. 응답 수신 완료");
// 결과 반환 (이 문자열은 JSON 파싱되거나 그대로 AI에게 전달됩니다)
return responseJson;
} catch (Exception e) {
log.error("[MCI Tool] MCI 연동 중 오류 발생: {}", e.getMessage(), e);
return "{\"status\":\"ERROR\", \"message\":\"MCI 통신 실패: " + e.getMessage() + "\"}";
}
}
}

View File

@@ -0,0 +1,59 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase.impl;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.cmm.usecase.SampleStringToolUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import io.shinhanlife.dap.mcc.biz.cmm.dto.MciSampleStringResponse;
import io.shinhanlife.dap.mcc.biz.cmm.dto.SampleStringRequest;
import io.shinhanlife.glow.util.GlowMciParser;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* @package io.shinhanlife.dap.mcc.service
* @className SampleStringToolService
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Service
@McpTool(
routingType = "MCI",
categoryKey = "cmm"
)
public class SampleStringToolUseCaseImpl extends AbstractMcpToolService implements SampleStringToolUseCase {
@McpFunction(register = false, displayName = "get_sample_string 툴", name = "get_sample_string",
description = "MCI String 버전과 GlowTrgmField 파싱을 테스트하는 샘플 툴입니다.",
prompt = "MCI 전문(String) 연계 및 고정 길이 파싱 테스트 해줘.",
mappingId = "TRGM_001"
)
@Override
public Object execute(SampleStringRequest req) {
// 1. EIMS(Legacy)를 통해 원본 고정 길이 문자열을 받아옵니다.
// 스펙에 mciFormat = STRING 힌트를 주어 전문 통신으로 자동 분기되게 합니다.
List<Map<String, Object>> spec = List.of(
Map.of("mciFormat", "STRING")
);
Map<String, Object> result = executeLegacy("MCI", "TRGM_001", req, spec);
if (!"SUCCESS".equals(result.get("status"))) {
return result;
}
String rawStringResponse = (String) result.get("legacy_response");
// 2. 받아온 고정 길이 전문(String)을 GlowMciParser를 이용해 DTO로 파싱합니다.
return GlowMciParser.parse(rawStringResponse, MciSampleStringResponse.class);
}
}

View File

@@ -0,0 +1,67 @@
package io.shinhanlife.dap.mcc.biz.cmm.usecase.impl;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.cmm.usecase.TemplateUtilityUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import io.shinhanlife.dap.mcc.biz.cmm.dto.TemplateDownloadRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Service
@McpTool(
routingType = "HTTP",
categoryKey = "cmm"
)
/**
* @package io.shinhanlife.dap.mcc.service
* @className TemplateUtilityService
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
public class TemplateUtilityUseCaseImpl extends AbstractMcpToolService implements TemplateUtilityUseCase {
@Override
@McpFunction(register = false, displayName = "get_template_file_url 툴", name = "get_template_file_url",
description = "특정 템플릿의 양식 파일(엑셀, 워드 등)을 다운로드 받을 수 있는 시스템 URL을 반환합니다. AI는 이 URL을 사용자에게 마크다운 링크 형태로 제공해야 합니다.",
prompt = "요청하신 템플릿 양식 파일 다운로드 URL은 다음과 같습니다. 클릭하여 다운로드하세요:"
)
public Map<String, Object> getTemplateFileUrl(TemplateDownloadRequest data) {
try {
String templateId = (data != null && data.getTemplateId() != null) ? data.getTemplateId().toLowerCase() : "default";
log.info("MCP 툴 호출됨: get_template_file_url, 요청 템플릿 ID: {}", templateId);
String fileName = "sample_" + templateId + ".xlsx";
String downloadUrl = "https://axhub-file-server.shinhanlife.io/downloads/" + fileName;
Map<String, Object> result = new HashMap<>();
result.put("status", "success");
Map<String, Object> contract = new HashMap<>();
contract.put("fileName", fileName);
contract.put("downloadUrl", downloadUrl);
contract.put("message", "다운로드 링크가 성공적으로 생성되었습니다. AI는 이 링크를 마크다운 형식으로 사용자에게 전달해야 합니다.");
contract.put("status", "success");
result.put("contracts", Collections.singletonList(contract));
return result;
} catch (Exception e) {
log.error("getTemplateFileUrl 내부 예외 발생", e);
throw new RuntimeException("템플릿 URL 생성 실패", e);
}
}
}

View File

@@ -0,0 +1,119 @@
package io.shinhanlife.dap.mcc.biz.other.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import lombok.Data;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className Onnba3011ReqDto
* @description 보종By가입설계한도계산조회 MCI 요청 전문 (ONNBA3011_I)
* @author 0986406
* @create 2026.09.01
*/
@Data
public class Onnba3011Request {
@JsonPropertyDescription("통합기계약보험 (유형: gs, 길이: 72)")
@JsonProperty("unfcPrbuIrcoAddu")
private UnfcPrbuIrcoAdduDto unfcPrbuIrcoAddu;
@JsonPropertyDescription("처리구분코드 (길이: 1)")
@JsonProperty("dalScCd")
private String dalScCd;
@JsonPropertyDescription("고객청약관계 (길이: 2)")
@JsonProperty("cstSucoRltyCd")
private String cstSucoRltyCd;
@JsonPropertyDescription("고객번호 (길이: 12)")
@JsonProperty("csNo")
private String csNo;
@JsonPropertyDescription("주민등록번호 (길이: 50)")
@JsonProperty("rdreNo")
private String rdreNo;
@JsonPropertyDescription("통합급부계산 (길이: 1)")
@JsonProperty("unfcPvsCalReqYn")
private String unfcPvsCalReqYn;
@JsonPropertyDescription("한국신용정보 (길이: 1)")
@JsonProperty("kcisPymmTnnrRequest")
private String kcisPymmTnnrRequest;
@JsonPropertyDescription("한도초과여부 (길이: 1)")
@JsonProperty("lmovYn")
private String lmovYn;
@JsonPropertyDescription("일반경유승인 (길이: 1)")
@JsonProperty("genPsthApvTrgtYn")
private String genPsthApvTrgtYn;
@JsonPropertyDescription("보험사한도초과 (길이: 1)")
@JsonProperty("ircoLmovEcpbTrgtYn")
private String ircoLmovEcpbTrgtYn;
@JsonPropertyDescription("진단계산여부 (길이: 1)")
@JsonProperty("digCalYn")
private String digCalYn;
@JsonPropertyDescription("기계약포함진단 (길이: 1)")
@JsonProperty("prbuIciDigCalYn")
private String prbuIciDigCalYn;
@JsonPropertyDescription("청약심사기본Dto (유형: gs, 길이: 2532)")
@JsonProperty("sucoIspaBasDto")
private SucoIspaBasDto sucoIspaBasDto;
// ----- Nested DTO Classes -----
@Data
public static class UnfcPrbuIrcoAdduDto {
// 실제 필요한 하위 필드들 추가 (사진 생략부분)
}
@Data
public static class SucoIspaBasDto {
@JsonPropertyDescription("계약처리유형 (길이: 2)")
@JsonProperty("ccnDalTypCd")
private String ccnDalTypCd;
@JsonPropertyDescription("신계약입력경로 (길이: 2)")
@JsonProperty("nwcnptCursCd")
private String nwcnptCursCd;
@JsonPropertyDescription("개인단체계약 (길이: 2)")
@JsonProperty("induAsctScCd")
private String induAsctScCd;
@JsonPropertyDescription("모집조직번호 (길이: 7)")
@JsonProperty("cepeOgnzNo")
private String cepeOgnzNo;
@JsonPropertyDescription("모집자사번번호 (길이: 8)")
@JsonProperty("cepePrafNo")
private String cepePrafNo;
@JsonPropertyDescription("수금조직번호 (길이: 7)")
@JsonProperty("clmoOgnzNo")
private String clmoOgnzNo;
@JsonPropertyDescription("수금자사번번호 (길이: 8)")
@JsonProperty("clmoPrafNo")
private String clmoPrafNo;
@JsonPropertyDescription("청약일자 (길이: 20)")
@JsonProperty("sucoYmd")
private String sucoYmd;
@JsonPropertyDescription("발행일자 (길이: 20)")
@JsonProperty("ispDt")
private String ispDt;
@JsonPropertyDescription("계약일자 (길이: 20)")
@JsonProperty("contYmd")
private String contYmd;
}
}

View File

@@ -0,0 +1,91 @@
package io.shinhanlife.dap.mcc.biz.other.io;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* @package io.shinhanlife.dap.mcc.infra.itrf.mci.cfp.a.io
* @className CLCNNB00001_I
* @description 보장분석결과조회 MCI 요청 전문
* @author 0986406
* @create 2026.09.01
*/
@Data
public class CLCNNB00001_I {
@JsonProperty("unfcPrbuIrcoAddu")
private UnfcPrbuIrcoAdduDto unfcPrbuIrcoAddu;
@JsonProperty("dalScCd")
private String dalScCd;
@JsonProperty("cstSucoRltyCd")
private String cstSucoRltyCd;
@JsonProperty("csNo")
private String csNo;
@JsonProperty("rdreNo")
private String rdreNo;
@JsonProperty("unfcPvsCalReqYn")
private String unfcPvsCalReqYn;
@JsonProperty("kcisPymmTnnrRequest")
private String kcisPymmTnnrRequest;
@JsonProperty("lmovYn")
private String lmovYn;
@JsonProperty("genPsthApvTrgtYn")
private String genPsthApvTrgtYn;
@JsonProperty("ircoLmovEcpbTrgtYn")
private String ircoLmovEcpbTrgtYn;
@JsonProperty("digCalYn")
private String digCalYn;
@JsonProperty("prbuIciDigCalYn")
private String prbuIciDigCalYn;
@JsonProperty("sucoIspaBasDto")
private SucoIspaBasDto sucoIspaBasDto;
@Data
public static class UnfcPrbuIrcoAdduDto {
}
@Data
public static class SucoIspaBasDto {
@JsonProperty("ccnDalTypCd")
private String ccnDalTypCd;
@JsonProperty("nwcnptCursCd")
private String nwcnptCursCd;
@JsonProperty("induAsctScCd")
private String induAsctScCd;
@JsonProperty("cepeOgnzNo")
private String cepeOgnzNo;
@JsonProperty("cepePrafNo")
private String cepePrafNo;
@JsonProperty("clmoOgnzNo")
private String clmoOgnzNo;
@JsonProperty("clmoPrafNo")
private String clmoPrafNo;
@JsonProperty("sucoYmd")
private String sucoYmd;
@JsonProperty("ispDt")
private String ispDt;
@JsonProperty("contYmd")
private String contYmd;
}
}

View File

@@ -0,0 +1,16 @@
package io.shinhanlife.dap.mcc.biz.other.io;
import lombok.Data;
/**
* @package io.shinhanlife.dap.mcc.infra.itrf.mci.cfp.a.io
* @className CLCNNB00001_O
* @description 보장분석결과조회 MCI 응답 전문
* @author 0986406
* @create 2026.09.01
*/
@Data
public class CLCNNB00001_O {
// 응답 전문 필드 정의 (필요에 따라 추가)
private Object resultData;
}

View File

@@ -0,0 +1,104 @@
package io.shinhanlife.dap.mcc.biz.other.io;
import io.shinhanlife.dap.mcc.biz.other.io.CLCNNB00001_I;
import io.shinhanlife.dap.mcc.biz.other.io.CLCNNB00001_O;
import io.shinhanlife.dap.lib.integration.mci.component.AxhubMciComponent;
import io.shinhanlife.dap.mcc.biz.other.dto.Onnba3011Request;
import io.shinhanlife.glow.communication.dto.Transfer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @package io.shinhanlife.dap.mcc.infra.itrf.mci.cfp.a.io
* @className MciCfpaClient
* @description 보장분석결과조회 MCI 호출 클라이언트
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class MciCfpaClient {
private final AxhubMciComponent mci;
// 인터페이스 코드 상수
private static final String INTERFACE_CODE = "CLCNNB00001"; // CLCCFP00001 (Onnba용 코드 유지)
// 정상 응답 코드 상수
private static final String SUCCESS_CODE_COM = "COM00139";
private static final String SUCCESS_CODE_CFP = "CFP00000";
private static final String NO_DATA_CODE = "COM00150";
// 예외 코드 상수
private static final String ERROR_CODE_PROCESS = "CLC00007";
private static final String ERROR_CODE_MESSAGE = "CLC00043";
/**
* 보장분석결과조회
*
* @param inDto 입력 DTO
* @return 출력 객체
*/
public Object callCfpa0001(Onnba3011Request inDto) throws Exception {
// 인터페이스 IO 객체 생성 및 매핑
CLCNNB00001_I mciReq = new CLCNNB00001_I();
mciReq.setDalScCd(inDto.getDalScCd());
mciReq.setCstSucoRltyCd(inDto.getCstSucoRltyCd());
mciReq.setCsNo(inDto.getCsNo());
mciReq.setRdreNo(inDto.getRdreNo());
mciReq.setUnfcPvsCalReqYn(inDto.getUnfcPvsCalReqYn());
mciReq.setKcisPymmTnnrRequest(inDto.getKcisPymmTnnrRequest());
mciReq.setLmovYn(inDto.getLmovYn());
mciReq.setGenPsthApvTrgtYn(inDto.getGenPsthApvTrgtYn());
mciReq.setIrcoLmovEcpbTrgtYn(inDto.getIrcoLmovEcpbTrgtYn());
mciReq.setDigCalYn(inDto.getDigCalYn());
mciReq.setPrbuIciDigCalYn(inDto.getPrbuIciDigCalYn());
if (inDto.getUnfcPrbuIrcoAddu() != null) {
mciReq.setUnfcPrbuIrcoAddu(new CLCNNB00001_I.UnfcPrbuIrcoAdduDto());
}
if (inDto.getSucoIspaBasDto() != null) {
CLCNNB00001_I.SucoIspaBasDto sucoIspa = new CLCNNB00001_I.SucoIspaBasDto();
sucoIspa.setCcnDalTypCd(inDto.getSucoIspaBasDto().getCcnDalTypCd());
sucoIspa.setNwcnptCursCd(inDto.getSucoIspaBasDto().getNwcnptCursCd());
sucoIspa.setInduAsctScCd(inDto.getSucoIspaBasDto().getInduAsctScCd());
sucoIspa.setCepeOgnzNo(inDto.getSucoIspaBasDto().getCepeOgnzNo());
sucoIspa.setCepePrafNo(inDto.getSucoIspaBasDto().getCepePrafNo());
sucoIspa.setClmoOgnzNo(inDto.getSucoIspaBasDto().getClmoOgnzNo());
sucoIspa.setClmoPrafNo(inDto.getSucoIspaBasDto().getClmoPrafNo());
sucoIspa.setSucoYmd(inDto.getSucoIspaBasDto().getSucoYmd());
sucoIspa.setIspDt(inDto.getSucoIspaBasDto().getIspDt());
sucoIspa.setContYmd(inDto.getSucoIspaBasDto().getContYmd());
mciReq.setSucoIspaBasDto(sucoIspa);
}
// 인터페이스 호출
Transfer<CLCNNB00001_O> resTransfer = mci.callTo(INTERFACE_CODE, mciReq, CLCNNB00001_O.class);
// 응답 검증
validateResponse(resTransfer);
// 메시지 검증
validateMessage(String.valueOf(resTransfer.getMessage()));
return resTransfer.getBody();
}
private void validateResponse(Transfer<?> resTransfer) {
log.info("응답 검증 로직 수행");
}
private void validateMessage(String message) {
log.info("메시지 검증 로직 수행: {}", message);
}
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.other.usecase;
import io.shinhanlife.dap.mcc.biz.other.dto.*;
public interface OnnbaMciToolUseCase {
Object callOnnba3011(Onnba3011Request req);
}

View File

@@ -0,0 +1,69 @@
package io.shinhanlife.dap.mcc.biz.other.usecase.impl;
import io.shinhanlife.dap.mcc.biz.other.io.MciCfpaClient;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.other.usecase.OnnbaMciToolUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import io.shinhanlife.dap.mcc.biz.other.dto.Onnba3011Request;
import io.shinhanlife.glow.communication.dto.Transfer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @package io.shinhanlife.dap.mcc.service
* @className OnnbaMciToolService
* @description 보종By가입설계한도계산조회 MCI 연동 툴
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Slf4j
@Service
@RequiredArgsConstructor
@McpTool(routingType = "MCI", categoryKey = "other")
public class OnnbaMciToolUseCaseImpl implements OnnbaMciToolUseCase {
private static final String INTERFACE_CODE_3011 = "CLCNNB00001";
// 공통 MCI Client 주입
private final MciCfpaClient mciCfpClient;
/**
* AI Agent가 호출하게 될 메서드입니다.
* @McpFunction 어노테이션 하나로 AI 도구로 자동 노출 및 라우팅됩니다.
*/
@McpFunction(
register = false,
name = "calculate_subscription_limit",
displayName = "보종By가입설계한도계산조회",
description = "MCI 연동을 통해 보종By가입설계한도계산조회를 수행합니다.",
prompt = "가입설계 한도를 계산하고 조회해줘.",
mappingId = INTERFACE_CODE_3011
)
@Override
public Object callOnnba3011(Onnba3011Request req) {
log.info("[MCI Tool] 보종By가입설계한도계산조회 요청 수신.");
try {
// MciCfpaClient를 통한 호출
Object response = mciCfpClient.callCfpa0001(req);
log.info("[MCI Tool] Glow 기반 MCI 연동 성공.");
// 결과 반환
return response != null ? response : "{\"status\":\"SUCCESS\", \"message\":\"GlowMciComponent 통신 완료\"}";
} catch (Exception e) {
log.error("[MCI Tool] MCI 연동 중 오류 발생: {}", e.getMessage(), e);
return "{\"status\":\"ERROR\", \"message\":\"MCI 통신 실패: " + e.getMessage() + "\"}";
}
}
}

View File

@@ -0,0 +1,25 @@
package io.shinhanlife.dap.mcc.biz.smp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className WeatherRequest
* @description 기상 조회 요청 클래스
* @author 0986406
* @create 2026.07.14
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.07.14 0986406 최초생성
*
* </pre>
*/
public record WeatherRequest(
@JsonProperty(required = true, value = "city")
@JsonPropertyDescription("날씨를 조회할 도시 이름 (예: 서울, 부산, 제주)")
String city
) {
}

View File

@@ -0,0 +1,24 @@
package io.shinhanlife.dap.mcc.biz.smp.dto;
/**
* @package io.shinhanlife.dap.mcc.dto
* @className WeatherResponse
* @description 기상 조회 응답 클래스
* @author 0986406
* @create 2026.07.14
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.07.14 0986406 최초생성
*
* </pre>
*/
public record WeatherResponse(
String city,
double temperature,
double windSpeed,
String reportTime,
String summary
) {
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.smp.usecase;
import io.shinhanlife.dap.mcc.biz.smp.dto.*;
public interface DailyQuoteToolUseCase {
io.shinhanlife.dap.mcc.biz.smp.usecase.impl.DailyQuoteToolUseCaseImpl.DailyQuoteResponse execute(io.shinhanlife.dap.mcc.biz.smp.usecase.impl.DailyQuoteToolUseCaseImpl.DailyQuoteRequest req);
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.smp.usecase;
import io.shinhanlife.dap.mcc.biz.smp.dto.*;
public interface ExchangeRateToolUseCase {
io.shinhanlife.dap.mcc.biz.smp.usecase.impl.ExchangeRateToolUseCaseImpl.ExchangeRateResponse execute(io.shinhanlife.dap.mcc.biz.smp.usecase.impl.ExchangeRateToolUseCaseImpl.ExchangeRateRequest req);
}

View File

@@ -0,0 +1,7 @@
package io.shinhanlife.dap.mcc.biz.smp.usecase;
import io.shinhanlife.dap.mcc.biz.smp.dto.*;
public interface WeatherToolUseCase {
WeatherResponse execute(WeatherRequest req);
}

View File

@@ -0,0 +1,57 @@
package io.shinhanlife.dap.mcc.biz.smp.usecase.impl;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.smp.usecase.DailyQuoteToolUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Random;
/**
* @package io.shinhanlife.dap.mcc.service
* @className DailyQuoteToolService
* @description 랜덤 명언 제공 툴
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Slf4j
@Service
@McpTool(
routingType = "DIRECT",
categoryKey = "smp"
)
public class DailyQuoteToolUseCaseImpl extends AbstractMcpToolService implements DailyQuoteToolUseCase {
public record DailyQuoteRequest(String category) {}
public record DailyQuoteResponse(String quote, String author) {}
private final List<DailyQuoteResponse> quotes = List.of(
new DailyQuoteResponse("성공은 매일 반복한 작은 노력들의 합이다.", "로버트 콜리어"),
new DailyQuoteResponse("시작이 반이다.", "아리스토텔레스"),
new DailyQuoteResponse("포기하지 않는 한 실패는 없다.", "알베르트 아인슈타인"),
new DailyQuoteResponse("가장 큰 위험은 위험 없는 삶이다.", "스티븐 코비")
);
@McpFunction(register = false, displayName = "랜덤 명언 툴", name = "daily_quote",
description = "무작위로 영감을 주는 명언을 하나 가져옵니다.",
prompt = "오늘의 명언 하나 알려줘, 동기부여 명언 등",
mappingId = "QUOTE_001"
)
public DailyQuoteResponse execute(DailyQuoteRequest req) {
int index = new Random().nextInt(quotes.size());
DailyQuoteResponse selected = quotes.get(index);
log.info("[DailyQuoteTool] 명언 제공 완료: {}", selected.author());
return selected;
}
}

View File

@@ -0,0 +1,61 @@
package io.shinhanlife.dap.mcc.biz.smp.usecase.impl;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.smp.usecase.ExchangeRateToolUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
/**
* @package io.shinhanlife.dap.mcc.service
* @className ExchangeRateToolService
* @description 실시간 환율 조회 툴
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
@Slf4j
@Service
@McpTool(
routingType = "DIRECT",
categoryKey = "smp"
)
public class ExchangeRateToolUseCaseImpl extends AbstractMcpToolService implements ExchangeRateToolUseCase {
public record ExchangeRateRequest(String currencyCode) {}
public record ExchangeRateResponse(String baseCurrency, String targetCurrency, double rate) {}
private final RestClient restClient;
public ExchangeRateToolUseCaseImpl() {
this.restClient = RestClient.create();
}
@McpFunction(register = false, displayName = "실시간 환율 조회 툴", name = "exchange_rate",
description = "원하는 통화의 실시간 환율을 조회합니다. (예: USD, EUR, JPY)",
prompt = "현재 달러 환율 알려줘, 엔화 환율은?",
mappingId = "EXCHANGE_001"
)
public ExchangeRateResponse execute(ExchangeRateRequest req) {
String targetCurrency = req.currencyCode() != null ? req.currencyCode().toUpperCase().trim() : "USD";
// 간단한 모의 데이터로 반환 (실제 구현 시 외부 연동)
double dummyRate = 1350.50;
if (targetCurrency.contains("JPY")) {
dummyRate = 905.20;
} else if (targetCurrency.contains("EUR")) {
dummyRate = 1450.30;
}
log.info("[ExchangeRateTool] 환율 조회 완료: {} -> {}", targetCurrency, dummyRate);
return new ExchangeRateResponse("KRW", targetCurrency, dummyRate);
}
}

View File

@@ -0,0 +1,117 @@
package io.shinhanlife.dap.mcc.biz.smp.usecase.impl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.shinhanlife.dap.lib.annotation.McpFunction;
import io.shinhanlife.dap.lib.annotation.McpTool;
import io.shinhanlife.dap.mcc.biz.smp.usecase.WeatherToolUseCase;
import io.shinhanlife.dap.mcc.service.AbstractMcpToolService;
import io.shinhanlife.dap.mcc.biz.smp.dto.WeatherRequest;
import io.shinhanlife.dap.mcc.biz.smp.dto.WeatherResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @package io.shinhanlife.dap.mcc.service
* @className WeatherToolService
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.07.14
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.07.14 0986406 최초생성
*
* </pre>
*/
@Slf4j
@Service
@McpTool(
routingType = "DIRECT",
categoryKey = "smp"
)
public class WeatherToolUseCaseImpl extends AbstractMcpToolService implements WeatherToolUseCase {
private final RestClient restClient;
public WeatherToolUseCaseImpl() {
this.restClient = RestClient.create();
}
@McpFunction(register = false, displayName = "날씨 조회 툴", name = "weather",
description = "특정 도시의 현재 날씨, 온도, 풍속 정보를 조회합니다.",
prompt = "서울 날씨 알려줘, 부산 기온 알려줘 등 실시간 기상 조회",
mappingId = "WEATHER_001"
)
public WeatherResponse execute(WeatherRequest req) {
String city = req.city() != null ? req.city().trim() : "서울";
// 지역별 위경도 매핑 (간단한 예시)
double lat = 37.566;
double lon = 126.978;
if (city.contains("부산")) {
lat = 35.179;
lon = 129.075;
} else if (city.contains("제주")) {
lat = 33.499;
lon = 126.531;
} else if (city.contains("인천")) {
lat = 37.456;
lon = 126.705;
}
try {
String newRequestId = java.util.UUID.randomUUID().toString();
String url = String.format("https://api.open-meteo.com/v1/forecast?latitude=%f&longitude=%f&current_weather=true", lat, lon);
log.info("[WeatherTool] OUTBOUND HTTP IN - request-id: {}", newRequestId);
log.info("[WeatherTool] 날씨 조회 요청 URL: {}", url);
String responseStr = restClient.get()
.uri(url)
.header("request-id", newRequestId)
.retrieve()
.body(String.class);
log.info("[WeatherTool] OUTBOUND HTTP OUT - request-id: {}", newRequestId);
ObjectMapper mapper = new ObjectMapper();
JsonNode response = mapper.readTree(responseStr);
if (response != null && response.has("current_weather")) {
JsonNode current = response.get("current_weather");
double temp = current.path("temperature").asDouble();
double windSpeed = current.path("windspeed").asDouble();
String time = current.path("time").asText();
int weatherCode = current.path("weathercode").asInt();
String summary = parseWeatherCode(weatherCode);
String formattedTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
return new WeatherResponse(city, temp, windSpeed, formattedTime, summary);
}
} catch (Exception e) {
log.error("[WeatherTool] 날씨 API 연동 실패: {}", e.getMessage());
return new WeatherResponse(city, 0.0, 0.0, "", "날씨 정보를 불러오는데 실패했습니다.");
}
return new WeatherResponse(city, 0.0, 0.0, "", "알 수 없는 응답입니다.");
}
private String parseWeatherCode(int code) {
if (code == 0) return "맑음 (Clear)";
if (code >= 1 && code <= 3) return "구름조금/흐림 (Cloudy)";
if (code >= 45 && code <= 48) return "안개 (Fog)";
if (code >= 51 && code <= 67) return "비/이슬비 (Rain)";
if (code >= 71 && code <= 77) return "눈 (Snow)";
if (code >= 95) return "뇌우/천둥번개 (Thunderstorm)";
return "알 수 없음 (Unknown)";
}
}

View File

@@ -0,0 +1,30 @@
package io.shinhanlife.dap.mcc.oth;
/**
* @package io.shinhanlife.dap.mcc.oth
* @className DapToolOthApplication
* @description AX HUB 시스템 처리 클래스
* @author 0986406
* @create 2026.09.01
* <pre>
* ---------- 개정이력 ----------
* 수정일 수정자 수정내용
* ---------- -------- ---------------------------
* 2026.09.01 0986406 최초생성
*
* </pre>
*/
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication(scanBasePackages = {"io.shinhanlife.dap.mcc", "io.shinhanlife.dap.lib.adapter", "io.shinhanlife.dap.lib.mcp", "io.shinhanlife.dap.lib.config", "io.shinhanlife.dap.lib.integration", "io.shinhanlife.dap.other"})
@ConfigurationPropertiesScan(basePackages = {"io.shinhanlife.dap.mcc", "io.shinhanlife.dap.lib.adapter", "io.shinhanlife.dap.lib.mcp", "io.shinhanlife.dap.lib.config", "io.shinhanlife.dap.lib.integration", "io.shinhanlife.dap.other"})
@EnableCaching
public class DapToolOthApplication {
public static void main(String[] args) {
SpringApplication.run(DapToolOthApplication.class, args);
}
}

View File

@@ -0,0 +1,36 @@
# OCI ?대씪?곕뱶 ?섍꼍 ?꾩슜 ?ㅼ젙
server:
port: ${PORT:8084}
axhub:
gateway:
url: https://axhubmcp.devjun.net
eims:
http:
url: http://localhost:${server.port}/api/gateway
tcp:
host: 127.0.0.1
port: 8090
timeout: 5000
jsp:
form:
url: http://localhost:${server.port}/mock/jsp-form
json:
url: http://localhost:${server.port}/mock/jsp-json
mci:
url: http://localhost:${server.port}/api/mock/esb/api
mcistring:
url: http://localhost:${server.port}/api/mock/esb/string
shinhan:
integration:
envrTypeCd: D
eai:
url: http://10.176.32.181
internalMci:
url: http://10.176.32.173
bancaMci:
url: http://10.176.32.117
externalMci:
url: http://10.176.32.176

View File

@@ -0,0 +1,39 @@
# Local ?섍꼍 ?꾩슜 ?ㅼ젙 (H2 硫붾え由?DB ??
spring:
datasource:
url: jdbc:p6spy:h2:mem:testdb;DB_CLOSE_DELAY=-1;
driverClassName: com.p6spy.engine.spy.P6SpyDriver
username: sa
password: password
h2:
console:
enabled: true
eims:
http:
url: http://localhost:${server.port}/api/gateway
tcp:
host: 127.0.0.1
port: 8090
timeout: 5000
jsp:
form:
url: http://localhost:${server.port}/mock/jsp-form
json:
url: http://localhost:${server.port}/mock/jsp-json
mci:
url: http://localhost:${server.port}/api/mock/esb/api
mcistring:
url: http://localhost:${server.port}/api/mock/esb/string
mcp:
security:
tenant-domains:
mcp-client-1: CUSTOMER,COMMON
mcp-client-2: ALL
axhub:
gateway:
url: http://localhost:8081
tool:
url: ${AXHUB_TOOL_URL:http://localhost:${server.port}}

View File

@@ -0,0 +1,15 @@
server:
port: 8084
spring:
application:
name: dap-tool-oth
profiles:
active: local
logging:
level:
org.apache.kafka: ERROR
mcp:
namespace: ""
security:
tenant-domains:
TESTER-DEV: ALL

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 1. 로그 패턴 설정 (MDC traceId 포함) -->
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n" />
<!-- 2. 콘솔(Console) 출력 설정 (로컬 개발용) -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 3. 파일(File) 출력 설정 (서버 운영용) -->
<!-- Logback에서 시스템 Hostname을 가져오기 위한 설정 -->
<property name="HOSTNAME" value="${HOSTNAME}" />
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/swlog/dap-tool-oth/A01/${HOSTNAME}_A01.log</file> <!-- 현재 로그가 쌓이는 파일 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 매일 자정에 날짜를 붙여서 지난 로그를 분리 저장 -->
<fileNamePattern>/swlog/dap-tool-oth/A01/${HOSTNAME}_A01_%d{yyyyMMdd}.log</fileNamePattern>
<!-- 최대 30일치 로그만 보관하고 오래된 것은 자동 삭제 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 4. 기본 로깅 레벨 설정 -->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
<!-- 5. 우리 프로젝트 패키지는 디버그 레벨까지 상세히 보기 -->
<logger name="io.shinhanlife" level="DEBUG" />
</configuration>