diff --git a/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/presentation/ScaffoldingController.java b/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/presentation/ScaffoldingController.java index fd909143..b46030e3 100644 --- a/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/presentation/ScaffoldingController.java +++ b/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/presentation/ScaffoldingController.java @@ -63,8 +63,9 @@ public class ScaffoldingController { String date = req.get("date"); if (date == null || date.trim().isEmpty()) date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy.MM.dd")); boolean register = Boolean.parseBoolean(req.getOrDefault("register", "true")); + String clientSystemCode = req.get("clientSystemCode"); - return ToolScaffolder.scaffold(baseName, interfaceId, description, group, routingType, moduleName, author, date, register); + return ToolScaffolder.scaffold(baseName, interfaceId, description, group, routingType, moduleName, author, date, register, clientSystemCode); } catch (Exception e) { return "오류 발생: " + e.getMessage(); } diff --git a/dap-gateway/src/main/resources/static/admin/scaffold.html b/dap-gateway/src/main/resources/static/admin/scaffold.html index 108c9e94..cea50134 100644 --- a/dap-gateway/src/main/resources/static/admin/scaffold.html +++ b/dap-gateway/src/main/resources/static/admin/scaffold.html @@ -500,6 +500,14 @@
Controls dynamic routing exposure.
+ +
+
+ + +
Required for MCI Protocol (4 letters).
+
+
diff --git a/dap-tool-core/src/main/java/io/shinhanlife/dap/lib/util/ToolScaffolder.java b/dap-tool-core/src/main/java/io/shinhanlife/dap/lib/util/ToolScaffolder.java index 6cbfb61c..54cf8b38 100644 --- a/dap-tool-core/src/main/java/io/shinhanlife/dap/lib/util/ToolScaffolder.java +++ b/dap-tool-core/src/main/java/io/shinhanlife/dap/lib/util/ToolScaffolder.java @@ -68,7 +68,7 @@ public class ToolScaffolder { String createDate = getOrAsk(args, 7, scanner, "8. 작성일 (엔터 입력 시 '" + defaultDate + "'): "); if (createDate.trim().isEmpty()) createDate = defaultDate; - String result = scaffold(baseName, interfaceId, description, group, routingType, moduleName, author, createDate, true); + String result = scaffold(baseName, interfaceId, description, group, routingType, moduleName, author, createDate, true, null); System.out.println(result); } @@ -80,7 +80,7 @@ public class ToolScaffolder { return scanner.nextLine().trim(); } - public static String scaffold(String baseName, String interfaceId, String description, String group, String routingType, String moduleName, String author, String createDate, boolean register) throws IOException { + public static String scaffold(String baseName, String interfaceId, String description, String group, String routingType, String moduleName, String author, String createDate, boolean register, String clientSystemCode) throws IOException { baseName = toPascalCase(baseName); String envSourceDir = System.getenv("AXHUB_SOURCE_DIR"); Path rootDir = envSourceDir != null ? Paths.get(envSourceDir) : Paths.get("."); @@ -95,6 +95,18 @@ public class ToolScaffolder { String bizPackage = BASE_PACKAGE + ".biz." + group.toLowerCase(); boolean isMci = "MCI".equalsIgnoreCase(routingType); String mciGroupPath = "infra/itrf/mci/" + group.toLowerCase(); + String clientPkgSuffix = ""; + String clientPrefixCap = ""; + Path mciClientDir = null; + + if (isMci && clientSystemCode != null && clientSystemCode.length() == 4) { + String clientPrefix = clientSystemCode.toLowerCase(); + clientPkgSuffix = clientPrefix.substring(0, 3) + "." + clientPrefix.substring(3, 4); + clientPrefixCap = toPascalCase(clientSystemCode); + mciGroupPath = "infra/itrf/mci/" + clientPrefix.substring(0, 3) + "/" + clientPrefix.substring(3, 4); + mciClientDir = rootDir.resolve(Paths.get(moduleName, BASE_PACKAGE_PATH, mciGroupPath, "client")); + } + Path mciIoDir = rootDir.resolve(Paths.get(moduleName, BASE_PACKAGE_PATH, mciGroupPath, "io")); Files.createDirectories(usecaseDir); @@ -102,6 +114,9 @@ public class ToolScaffolder { Files.createDirectories(dtoDir); if (isMci) { Files.createDirectories(mciIoDir); + if (mciClientDir != null) { + Files.createDirectories(mciClientDir); + } } else { Files.createDirectories(legacyDtoDir); } @@ -227,7 +242,8 @@ public class ToolScaffolder { import lombok.extern.slf4j.Slf4j; import java.util.Map; import %s.converter.%sLegacyConverter; - import %s.infra.itrf.mci.%s.io.%s_I; + import %s.%s.io.%s_I; +%s /** * @package %s.usecase.impl @@ -248,7 +264,7 @@ public class ToolScaffolder { @RequiredArgsConstructor public class %sUseCaseImpl implements %sUseCase { - private final AxhubMciComponent mci; +%s private final %sLegacyConverter converter; @Override @@ -277,7 +293,9 @@ public class ToolScaffolder { bizPackage, baseName, bizPackage, baseName, bizPackage, baseName, - BASE_PACKAGE, group.toLowerCase(), interfaceId, + bizPackage, baseName, + BASE_PACKAGE, mciGroupPath.replace("/", "."), interfaceId, + (clientPrefixCap.isEmpty() ? "" : " import " + BASE_PACKAGE + "." + mciGroupPath.replace("/", ".") + ".client.Mci" + clientPrefixCap + "Client;\n"), bizPackage, baseName, author, @@ -285,6 +303,7 @@ public class ToolScaffolder { createDate, author, baseName, baseName, + (clientPrefixCap.isEmpty() ? " private final AxhubMciComponent mci;" : " private final Mci" + clientPrefixCap + "Client mci;"), baseName, baseName, toolName, @@ -383,7 +402,7 @@ public class ToolScaffolder { */ private String content; } - """.formatted(BASE_PACKAGE, group.toLowerCase(), BASE_PACKAGE, group.toLowerCase(), interfaceId, author, createDate, createDate, author, interfaceId); + """.formatted(BASE_PACKAGE, mciGroupPath.replace("/", "."), BASE_PACKAGE, mciGroupPath.replace("/", "."), interfaceId, author, createDate, createDate, author, interfaceId); Files.writeString(mciIoDir.resolve(interfaceId + "_I.java"), mciReqContent); String mciResContent = """ @@ -409,7 +428,7 @@ public class ToolScaffolder { public class %s_O { // TODO: Add response fields here } - """.formatted(BASE_PACKAGE, group.toLowerCase(), BASE_PACKAGE, group.toLowerCase(), interfaceId, author, createDate, createDate, author, interfaceId); + """.formatted(BASE_PACKAGE, mciGroupPath.replace("/", "."), BASE_PACKAGE, mciGroupPath.replace("/", "."), interfaceId, author, createDate, createDate, author, interfaceId); Files.writeString(mciIoDir.resolve(interfaceId + "_O.java"), mciResContent); String converterContent = """ @@ -454,8 +473,8 @@ public class ToolScaffolder { bizPackage, bizPackage, baseName, bizPackage, baseName, - BASE_PACKAGE, group.toLowerCase(), interfaceId, - BASE_PACKAGE, group.toLowerCase(), interfaceId, + BASE_PACKAGE, mciGroupPath.replace("/", "."), interfaceId, + BASE_PACKAGE, mciGroupPath.replace("/", "."), interfaceId, bizPackage, baseName, author, createDate, createDate, author, baseName, interfaceId, baseName, baseName, interfaceId, @@ -474,6 +493,46 @@ public class ToolScaffolder { log.append("[MCI Response IO] ").append(mciIoDir.resolve(interfaceId + "_O.java")).append("\n"); log.append("[MCI Converter] ").append(converterDir.resolve(baseName + "LegacyConverter.java")).append("\n"); + if (!clientPrefixCap.isEmpty()) { + String mciClientContent = """ + package %s.%s.client; + + import org.springframework.stereotype.Component; + import lombok.RequiredArgsConstructor; + import io.shinhanlife.dap.lib.integration.mci.component.AxhubMciComponent; + import io.shinhanlife.glow.communication.dto.Transfer; + + /** + * @package %s.%s.client + * @className Mci%sClient + * @description AX HUB 시스템 처리 클래스 + * @author %s + * @create %s + *
+                     * ---------- 개정이력 ----------
+                     * 수정일      수정자    수정내용
+                     * ---------- -------- ---------------------------
+                     * %s  %s    최초생성
+                     * 
+                     * 
+ */ + @Component + @RequiredArgsConstructor + public class Mci%sClient { + private final AxhubMciComponent mci; + + public Transfer callTo(String interfaceId, Object dummy, Object mciReq, Class resType) { + return mci.callTo(interfaceId, dummy, mciReq, resType); + } + } + """.formatted( + BASE_PACKAGE, mciGroupPath.replace("/", "."), + BASE_PACKAGE, mciGroupPath.replace("/", "."), clientPrefixCap, author, createDate, createDate, author, clientPrefixCap + ); + Files.writeString(mciClientDir.resolve("Mci" + clientPrefixCap + "Client.java"), mciClientContent); + log.append("[MCI Client] ").append(mciClientDir.resolve("Mci" + clientPrefixCap + "Client.java")).append("\n"); + } + } else { String legacyReqContent = """ package %s.legacy; diff --git a/dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/OnnbaMciToolUseCase.java b/dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/Onnba3011UseCase.java similarity index 88% rename from dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/OnnbaMciToolUseCase.java rename to dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/Onnba3011UseCase.java index e8427cc4..b214d073 100644 --- a/dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/OnnbaMciToolUseCase.java +++ b/dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/Onnba3011UseCase.java @@ -5,6 +5,6 @@ import io.shinhanlife.dap.lib.annotation.McpFunction; import io.shinhanlife.dap.mcc.biz.oth.dto.*; @McpTool(routingType = "MCI", categoryKey = "oth") -public interface OnnbaMciToolUseCase { +public interface Onnba3011UseCase { Object callOnnba3011(Onnba3011Request req); } diff --git a/dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/OnnbaMciToolUseCaseImpl.java b/dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/Onnba3011UseCaseImpl.java similarity index 93% rename from dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/OnnbaMciToolUseCaseImpl.java rename to dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/Onnba3011UseCaseImpl.java index 1e6bcf5a..c96edf38 100644 --- a/dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/OnnbaMciToolUseCaseImpl.java +++ b/dap-tool-oth/src/main/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/Onnba3011UseCaseImpl.java @@ -3,7 +3,7 @@ package io.shinhanlife.dap.mcc.biz.oth.usecase.impl; import io.shinhanlife.dap.mcc.biz.oth.converter.Onnba3011Converter; import io.shinhanlife.dap.mcc.infra.itrf.mci.cfp.a.MciCfpaClient; import io.shinhanlife.dap.mcc.infra.itrf.mci.cfp.a.io.CLCNNB00001_I; -import io.shinhanlife.dap.mcc.biz.oth.usecase.OnnbaMciToolUseCase; +import io.shinhanlife.dap.mcc.biz.oth.usecase.Onnba3011UseCase; import io.shinhanlife.dap.mcc.biz.oth.dto.Onnba3011Request; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -26,14 +26,13 @@ import org.springframework.stereotype.Service; @Slf4j @Service @RequiredArgsConstructor -public class OnnbaMciToolUseCaseImpl implements OnnbaMciToolUseCase { +public class Onnba3011UseCaseImpl implements Onnba3011UseCase { private static final String INTERFACE_CODE_3011 = "CLCNNB00001"; // 공통 MCI Client 주입 private final MciCfpaClient mciCfpaClient; private final Onnba3011Converter onnba3011Converter; - /** * AI Agent가 호출하게 될 메서드입니다. * @McpFunction 어노테이션 하나로 AI 도구로 자동 노출 및 라우팅됩니다. diff --git a/dap-tool-oth/src/test/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/OnnbaMciToolUseCaseImplTest.java b/dap-tool-oth/src/test/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/Onnba3011UseCaseImplTest.java similarity index 92% rename from dap-tool-oth/src/test/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/OnnbaMciToolUseCaseImplTest.java rename to dap-tool-oth/src/test/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/Onnba3011UseCaseImplTest.java index 031de830..cc909c81 100644 --- a/dap-tool-oth/src/test/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/OnnbaMciToolUseCaseImplTest.java +++ b/dap-tool-oth/src/test/java/io/shinhanlife/dap/mcc/biz/oth/usecase/impl/Onnba3011UseCaseImplTest.java @@ -24,13 +24,13 @@ import org.mockito.Mockito; * 2026.07.27 0986406 initial creation * */ -class OnnbaMciToolUseCaseImplTest { +class Onnba3011UseCaseImplTest { @Test void convertsToolRequestBeforeCallingMciClient() throws Exception { MciCfpaClient mciCfpaClient = Mockito.mock(MciCfpaClient.class); Onnba3011Converter converter = Mockito.mock(Onnba3011Converter.class); - OnnbaMciToolUseCaseImpl useCase = new OnnbaMciToolUseCaseImpl(mciCfpaClient, converter); + Onnba3011UseCaseImpl useCase = new Onnba3011UseCaseImpl(mciCfpaClient, converter); Onnba3011Request request = new Onnba3011Request(); CLCNNB00001_I mciRequest = new CLCNNB00001_I();