forked from kimhyungsik/ax_hub_mcp_tool
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package io.shinhanlife.dat.mcc.biz.pro.converter;
|
||||
|
||||
import io.shinhanlife.dat.mcc.biz.pro.dto.IndividualCustomerDetailInquiryRequest;
|
||||
import io.shinhanlife.dat.mcc.biz.pro.dto.IndividualCustomerDetailInquiryResponse;
|
||||
import io.shinhanlife.dat.mcc.infra.itrf.mci.ncs.c.io.ONCSC1340_I;
|
||||
import io.shinhanlife.dat.mcc.infra.itrf.mci.ncs.c.io.ONCSC1340_O;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface IndividualCustomerDetailInquiryConverter {
|
||||
// Field names differ? Add mappings like this before the method.
|
||||
// @Mapping(source = "sourceField", target = "targetField")
|
||||
ONCSC1340_I toLegacyRequest(IndividualCustomerDetailInquiryRequest request);
|
||||
IndividualCustomerDetailInquiryRequest toRequest(ONCSC1340_I mciRequest);
|
||||
IndividualCustomerDetailInquiryResponse toResponse(ONCSC1340_O mciRes);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
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;
|
||||
|
||||
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class IndividualCustomerDetailInquiryRequest {
|
||||
@Schema(description = "조회할 고객의 고유 ID (형식: ^[A-Za-z0-9]{1,20}$) (예시: 12345, CUST00001)", example = "12345", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Pattern(regexp = "^[A-Za-z0-9]{1,20}$")
|
||||
private String customerId;
|
||||
|
||||
@Schema(description = "고객의 이름 (선택적 검색 조건) (형식: ^[가-힣a-zA-Z\s]{2,50}$) (예시: 김철수, 이영희)", example = "김철수")
|
||||
@Pattern(regexp = "^[가-힣a-zA-Z\s]{2,50}$")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "고객의 연락처 번호 (선택적 검색 조건) (형식: {10,11}$) (예시: 010-1234-5678, 01012345678)", example = "010-1234-5678")
|
||||
private String phoneNumber;
|
||||
|
||||
@Schema(description = "고객의 이메일 주소 (선택적 검색 조건) (형식: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$) (예시: test@example.com, user@test.co.kr)", example = "test@example.com")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "고객의 생년월일 (선택적 검색 조건, YYYY-MM-DD 형식) (형식: {2}$) (예시: 1990-01-15, 1985-12-31)", example = "1990-01-15")
|
||||
private String birthDate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
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;
|
||||
|
||||
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class IndividualCustomerDetailInquiryResponse {
|
||||
private String resultCode;
|
||||
|
||||
private String resultMessage;
|
||||
@Schema(description = "고객의 고유 ID (예시: 12345, CUST00001)", example = "12345", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String customerId;
|
||||
|
||||
@Schema(description = "고객의 전체 이름 (예시: 김철수, 이영희)", example = "김철수", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String name;
|
||||
|
||||
@Schema(description = "고객의 연락처 번호 (예시: 010-1234-5678, 01012345678)", example = "010-1234-5678", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String phoneNumber;
|
||||
|
||||
@Schema(description = "고객의 이메일 주소 (예시: test@example.com, user@test.co.kr)", example = "test@example.com", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String email;
|
||||
|
||||
@Schema(description = "고객의 주소 정보 (예시: 서울시 강남구 테헤란로 123, 부산시 해운대구 해운대해변로 456)", example = "서울시 강남구 테헤란로 123", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String address;
|
||||
|
||||
@Schema(description = "고객 가입일 (형식: $) (예시: 2023-01-15, 2022-11-30)", example = "2023-01-15", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String registrationDate;
|
||||
|
||||
@Schema(description = "고객 등급 정보 (예시: VIP, GOLD, SILVER, BRONZE)", example = "VIP")
|
||||
private String grade;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.shinhanlife.dat.mcc.biz.pro.usecase;
|
||||
|
||||
import org.springaicommunity.mcp.annotation.McpTool;
|
||||
import io.shinhanlife.dat.lib.annotation.GrowToolHint;
|
||||
import io.shinhanlife.dat.mcc.biz.pro.dto.IndividualCustomerDetailInquiryRequest;
|
||||
import io.shinhanlife.dat.mcc.biz.pro.dto.IndividualCustomerDetailInquiryResponse;
|
||||
|
||||
/**
|
||||
* @package io.shinhanlife.dat.mcc.biz.pro.usecase
|
||||
* @className IndividualCustomerDetailInquiryUseCase
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author jade
|
||||
* @create 2026.08.25
|
||||
* <pre>
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2026.08.25 jade 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public interface IndividualCustomerDetailInquiryUseCase {
|
||||
|
||||
@McpTool(name = "pro_individual_inquiry", title = "개인고객 상세조회", description = "개인고객의 상세 정보를 조회하는 도구로, 기본 정보부터 연락처, 주소까지 모든 고객 데이터를 제공합니다.")
|
||||
@GrowToolHint(
|
||||
requiresApproval = false,
|
||||
categoryKey = "pro",
|
||||
mappingId = "DATNCSO00001",
|
||||
functionDescription = "등록된 개인고객의 상세 정보를 조회하여 고객 관리 및 서비스 제공에 필요한 모든 데이터를 반환합니다.",
|
||||
whenToUse = "특정 고객의 상세 정보가 필요한 경우, 예를 들어 고객 지원, 마케팅, 또는 서비스 제공 시 사용됩니다.",
|
||||
whenNotToUse = "집계된 통계 데이터만 필요한 경우, 개별 고객 정보 조회는 적합하지 않습니다.",
|
||||
ioLimits = "최대 100명의 고객 정보를 한 번에 조회할 수 있으며, 각 고객 정보는 최대 5KB까지 지원됩니다.",
|
||||
displayDescription = "개인고객의 모든 상세 정보를 한눈에 확인할 수 있는 조회 도구입니다.",
|
||||
exampleQueries = {"고객 ID 12345에 대한 상세 정보를 조회해주세요.", "김철수 고객의 연락처 정보를 알려주세요.", "주민등록번호 800101-123456으로 등록된 고객의 주소를 조회해주세요.", "최근 가입한 고객 10명의 정보를 조회해주세요.", "이메일 주소가 test@example.com인 고객의 상세 정보를 찾아주세요.", "전화번호가 010-1234-5678인 고객의 정보를 조회해주세요.", "2023년에 가입한 고객의 상세 정보를 조회해주세요.", "주소가 서울인 고객의 정보를 조회해주세요.", "VIP 등급의 고객 정보를 조회해주세요.", "최근 30일 이내에 활동한 고객의 상세 정보를 조회해주세요.", "고객 ID 99999에 대한 모든 정보를 조회해주세요.", "고객 이름 '이영희'로 검색해주세요.", "마지막 활동일이 지난 고객의 정보를 조회해주세요.", "마케팅 동의한 고객의 연락처 정보를 조회해주세요.", "신규 가입 고객의 기본 정보를 조회해주세요."},
|
||||
destructive = false,
|
||||
idempotent = true,
|
||||
tags = {"customer", "inquiry"},
|
||||
ownerOrg = "MCP_TOOL"
|
||||
)
|
||||
IndividualCustomerDetailInquiryResponse execute(IndividualCustomerDetailInquiryRequest req);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package io.shinhanlife.dat.mcc.biz.pro.usecase.impl;
|
||||
|
||||
import io.shinhanlife.dat.mcc.biz.pro.dto.IndividualCustomerDetailInquiryRequest;
|
||||
import io.shinhanlife.dat.mcc.biz.pro.dto.IndividualCustomerDetailInquiryResponse;
|
||||
import io.shinhanlife.dat.mcc.biz.pro.usecase.IndividualCustomerDetailInquiryUseCase;
|
||||
import io.shinhanlife.dat.lib.integration.mci.component.AxhubMciComponent;
|
||||
import io.shinhanlife.glow.communication.dto.Transfer;
|
||||
import org.springframework.stereotype.Service;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import io.shinhanlife.dat.mcc.biz.pro.converter.IndividualCustomerDetailInquiryConverter;
|
||||
import io.shinhanlife.dat.mcc.infra.itrf.mci.ncs.c.io.ONCSC1340_I;
|
||||
import io.shinhanlife.dat.mcc.infra.itrf.mci.ncs.c.io.ONCSC1340_O;
|
||||
import io.shinhanlife.dat.mcc.infra.itrf.mci.ncs.c.MciNcscClient;
|
||||
|
||||
|
||||
/**
|
||||
* @package io.shinhanlife.dat.mcc.biz.pro.usecase.impl
|
||||
* @className IndividualCustomerDetailInquiryUseCaseImpl
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author jade
|
||||
* @create 2026.08.25
|
||||
* <pre>
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2026.08.25 jade 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class IndividualCustomerDetailInquiryUseCaseImpl implements IndividualCustomerDetailInquiryUseCase {
|
||||
|
||||
private final MciNcscClient mci;
|
||||
private final IndividualCustomerDetailInquiryConverter converter;
|
||||
|
||||
@Override
|
||||
public IndividualCustomerDetailInquiryResponse execute(IndividualCustomerDetailInquiryRequest req) {
|
||||
log.info("[MCI Tool] {} 요청 수신.", "pro_individual_inquiry");
|
||||
try {
|
||||
// MapStruct를 이용한 자동 매핑 (AI DTO -> MCI DTO)
|
||||
ONCSC1340_I mciReq = converter.toLegacyRequest(req);
|
||||
|
||||
Transfer<ONCSC1340_O> resTransfer = mci.callTo(
|
||||
"DATNCSO00001",
|
||||
null,
|
||||
mciReq,
|
||||
ONCSC1340_O.class
|
||||
);
|
||||
IndividualCustomerDetailInquiryResponse response = new IndividualCustomerDetailInquiryResponse();
|
||||
if (resTransfer.getBody() != null) {
|
||||
response = converter.toResponse(resTransfer.getBody());
|
||||
}
|
||||
response.setResultCode("SUCCESS");
|
||||
response.setResultMessage(resTransfer.getBody() != null
|
||||
? "MCI call completed."
|
||||
: "MCI call completed without a response body.");
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
log.error("[MCI Tool] 연동 중 오류 발생: {}", e.getMessage(), e);
|
||||
IndividualCustomerDetailInquiryResponse response = new IndividualCustomerDetailInquiryResponse();
|
||||
response.setResultCode("ERROR");
|
||||
response.setResultMessage(e.getMessage() != null ? e.getMessage() : "Unknown error");
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package io.shinhanlife.dat.mcc.infra.itrf.mci.ncs.c;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import io.shinhanlife.dat.lib.integration.mci.component.AxhubMciComponent;
|
||||
import io.shinhanlife.glow.communication.dto.Transfer;
|
||||
|
||||
/**
|
||||
* @package io.shinhanlife.dat.mcc.infra.itrf.mci.ncs.c
|
||||
* @className MciNcscClient
|
||||
* @description AX HUB 시스템 처리 클래스
|
||||
* @author jade
|
||||
* @create 2026.08.25
|
||||
* <pre>
|
||||
* ---------- 개정이력 ----------
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2026.08.25 jade 최초생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MciNcscClient {
|
||||
private final AxhubMciComponent mci;
|
||||
|
||||
public <O> Transfer<O> callTo(String interfaceId, String dummy, Object mciReq, Class<O> resType) throws Exception {
|
||||
return mci.callTo(interfaceId, dummy, mciReq, resType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.shinhanlife.dat.mcc.infra.itrf.mci.ncs.c.io;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
|
||||
|
||||
@Data
|
||||
public class ONCSC1340_I {
|
||||
@Schema(description = "조회할 고객의 고유 ID (형식: ^[A-Za-z0-9]{1,20}$) (예시: 12345, CUST00001)", example = "12345", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Pattern(regexp = "^[A-Za-z0-9]{1,20}")
|
||||
private String customerId;
|
||||
|
||||
@Schema(description = "고객의 이름 (선택적 검색 조건) (형식: ^[가-힣a-zA-Z\s]{2,50}$) (예시: 김철수, 이영희)", example = "김철수")
|
||||
@Pattern(regexp = "^[가-힣a-zA-Zs]{2,50}")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "고객의 연락처 번호 (선택적 검색 조건) (형식: 10,11}$) (예시: 010-1234-5678, 01012345678)", example = "010-1234-5678")
|
||||
private String phoneNumber;
|
||||
|
||||
@Schema(description = "고객의 이메일 주소 (선택적 검색 조건) (형식: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$) (예시: test@example.com, user@test.co.kr)", example = "test@example.com")
|
||||
@Pattern(regexp = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "고객의 생년월일 (선택적 검색 조건, YYYY-MM-DD 형식) (형식: ^d{4}-d{2}-d{2}$) (예시: 1990-01-15, 1985-12-31)", example = "1990-01-15")
|
||||
@Pattern(regexp = "d{4}-d{2}-d{2}")
|
||||
private String birthDate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.shinhanlife.dat.mcc.infra.itrf.mci.ncs.c.io;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
|
||||
|
||||
@Data
|
||||
public class ONCSC1340_O {
|
||||
@Schema(description = "조회 결과 코드 (예시: SUCCESS, ERROR_001)", example = "SUCCESS", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String resultCode;
|
||||
|
||||
@Schema(description = "고객의 고유 ID (예시: 12345, CUST00001)", example = "12345", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String customerId;
|
||||
|
||||
@Schema(description = "고객의 전체 이름 (예시: 김철수, 이영희)", example = "김철수", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String name;
|
||||
|
||||
@Schema(description = "고객의 연락처 번호 (예시: 010-1234-5678, 01012345678)", example = "010-1234-5678", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String phoneNumber;
|
||||
|
||||
@Schema(description = "고객의 이메일 주소 (예시: test@example.com, user@test.co.kr)", example = "test@example.com", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String email;
|
||||
|
||||
@Schema(description = "고객의 주소 정보 (예시: 서울시 강남구 테헤란로 123, 부산시 해운대구 해운대해변로 456)", example = "서울시 강남구 테헤란로 123", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String address;
|
||||
|
||||
@Schema(description = "고객 가입일 (형식: ^d{4}-d{2}-d{2}$) (예시: 2023-01-15, 2022-11-30)", example = "2023-01-15", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Pattern(regexp = "^d{4}-d{2}-d{2}$")
|
||||
private String registrationDate;
|
||||
|
||||
@Schema(description = "고객 등급 정보 (예시: VIP, GOLD, SILVER, BRONZE)", example = "VIP")
|
||||
private String grade;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"resultCode" : "SUCCESS",
|
||||
"customerId" : "12345",
|
||||
"name" : "김철수",
|
||||
"phoneNumber" : "010-1234-5678",
|
||||
"email" : "test@example.com",
|
||||
"address" : "서울시 강남구 테헤란로 123",
|
||||
"registrationDate" : "2023-01-15",
|
||||
"grade" : "VIP"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package io.shinhanlife.dat.mcc.biz.pro.usecase;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import io.shinhanlife.dat.mcc.biz.pro.dto.IndividualCustomerDetailInquiryRequest;
|
||||
import io.shinhanlife.dat.mcc.biz.pro.dto.IndividualCustomerDetailInquiryResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class IndividualCustomerDetailInquiryUseCaseTest {
|
||||
|
||||
@Test
|
||||
void createsToolRequestAndResponseDtos() {
|
||||
assertNotNull(new IndividualCustomerDetailInquiryRequest());
|
||||
assertNotNull(new IndividualCustomerDetailInquiryResponse());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user