Compare commits
2 Commits
V202601270
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 859041d758 | |||
| 19e077b45f |
533
src/com/pms/api/WarehouseApiClient.java
Normal file
533
src/com/pms/api/WarehouseApiClient.java
Normal file
@@ -0,0 +1,533 @@
|
||||
package com.pms.api;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.security.cert.X509Certificate;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* 창고 정보 조회 API 클라이언트
|
||||
* 회사의 창고정보를 조회하는 API를 호출합니다.
|
||||
*/
|
||||
public class WarehouseApiClient {
|
||||
|
||||
private static final String API_URL = "~/apiproxy/api20A00S00801";
|
||||
// 실제 키값 (기존 API 클라이언트와 동일)
|
||||
private static final String CALLER_NAME = "API_gcmsAmaranth40578";
|
||||
private static final String ACCESS_TOKEN = "MN5KzKBWRAa92BPxDlRLl3GcsxeZXc";
|
||||
private static final String HASH_KEY = "22519103205540290721741689643674301018832465";
|
||||
private static final String GROUP_SEQ = "gcmsAmaranth40578";
|
||||
|
||||
/**
|
||||
* 창고 정보를 조회합니다.
|
||||
*
|
||||
* @param baseUrl API 서버의 기본 URL (예: https://erp.rps-korea.com)
|
||||
* @param coCd 회사코드 (4자리, 필수)
|
||||
* @param baselocFg 기준위치구분 (0: 전체, 1: 기준위치만)
|
||||
* @return API 응답 결과 (JSON 문자열)
|
||||
* @throws Exception API 호출 중 발생하는 예외
|
||||
*/
|
||||
public String getWarehouseList(String baseUrl, String coCd, String baselocFg) throws Exception {
|
||||
if (coCd == null || coCd.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("회사코드(coCd)는 필수입니다.");
|
||||
}
|
||||
|
||||
// JDK 1.7에서 TLS 1.2 활성화
|
||||
System.setProperty("https.protocols", "TLSv1.2");
|
||||
|
||||
// SSL 인증서 검증 우회 (개발 환경용)
|
||||
TrustManager[] trustAllCerts = new TrustManager[] {
|
||||
new X509TrustManager() {
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
public void checkClientTrusted(X509Certificate[] certs, String authType) {
|
||||
}
|
||||
public void checkServerTrusted(X509Certificate[] certs, String authType) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SSLContext sc = SSLContext.getInstance("TLS");
|
||||
sc.init(null, trustAllCerts, new java.security.SecureRandom());
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {
|
||||
public boolean verify(String hostname, javax.net.ssl.SSLSession session) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// API URL 구성
|
||||
String urlPath = API_URL.replace("~", "");
|
||||
// baseUrl 끝에 슬래시가 있으면 제거
|
||||
String cleanBaseUrl = baseUrl.endsWith("/") ? baseUrl.substring(0, baseUrl.length() - 1) : baseUrl;
|
||||
String fullUrl = cleanBaseUrl + urlPath;
|
||||
URL url = new URL(fullUrl);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
// 연결 타임아웃 설정 (30초)
|
||||
connection.setConnectTimeout(30000);
|
||||
connection.setReadTimeout(30000);
|
||||
|
||||
// 리다이렉트 자동 따라가기 비활성화 (수동 처리)
|
||||
connection.setInstanceFollowRedirects(false);
|
||||
|
||||
try {
|
||||
// HTTP 메서드 설정
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
|
||||
// 인증 프로토콜 가이드에 따른 헤더 설정
|
||||
// 1. callerName: 호출 구분명
|
||||
connection.setRequestProperty("callerName", CALLER_NAME);
|
||||
|
||||
// 2. Authorization: Bearer + accessToken
|
||||
connection.setRequestProperty("Authorization", "Bearer " + ACCESS_TOKEN);
|
||||
|
||||
// 3. transaction-id: 32자리 랜덤 문자열
|
||||
String transactionId = generateTransactionId();
|
||||
connection.setRequestProperty("transaction-id", transactionId);
|
||||
|
||||
// 4. timestamp: Unix timestamp (초 단위)
|
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||
connection.setRequestProperty("timestamp", timestamp);
|
||||
|
||||
// 5. groupSeq: Amaranth10 그룹시퀀스
|
||||
connection.setRequestProperty("groupSeq", GROUP_SEQ);
|
||||
|
||||
// 6. wehago-sign: HMacSHA256 생성
|
||||
String wehagoSign = generateWehagoSign(ACCESS_TOKEN, transactionId, timestamp, urlPath);
|
||||
connection.setRequestProperty("wehago-sign", wehagoSign);
|
||||
|
||||
// 요청 본문 작성
|
||||
String requestBody = buildRequestBody(coCd, baselocFg);
|
||||
|
||||
// 요청 전송 설정
|
||||
connection.setDoOutput(true);
|
||||
connection.setDoInput(true);
|
||||
|
||||
// 요청 본문 전송
|
||||
OutputStreamWriter writer = new OutputStreamWriter(
|
||||
connection.getOutputStream(), StandardCharsets.UTF_8);
|
||||
writer.write(requestBody);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
// 응답 코드 확인
|
||||
int responseCode = connection.getResponseCode();
|
||||
|
||||
// 리다이렉트 처리 (301, 302, 303, 307, 308)
|
||||
if (responseCode == 301 || responseCode == 302 || responseCode == 303 ||
|
||||
responseCode == 307 || responseCode == 308) {
|
||||
String location = connection.getHeaderField("Location");
|
||||
connection.disconnect();
|
||||
|
||||
if (location != null) {
|
||||
// 리다이렉트 URL로 재시도
|
||||
URL redirectUrl = new URL(location);
|
||||
connection = (HttpURLConnection) redirectUrl.openConnection();
|
||||
connection.setConnectTimeout(30000);
|
||||
connection.setReadTimeout(30000);
|
||||
connection.setInstanceFollowRedirects(false);
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
|
||||
// 리다이렉트 시에도 동일한 인증 헤더 재설정
|
||||
connection.setRequestProperty("callerName", CALLER_NAME);
|
||||
connection.setRequestProperty("Authorization", "Bearer " + ACCESS_TOKEN);
|
||||
connection.setRequestProperty("transaction-id", transactionId);
|
||||
connection.setRequestProperty("timestamp", timestamp);
|
||||
connection.setRequestProperty("groupSeq", GROUP_SEQ);
|
||||
connection.setRequestProperty("wehago-sign", wehagoSign);
|
||||
|
||||
// 동일한 요청 본문 재사용
|
||||
connection.setDoOutput(true);
|
||||
connection.setDoInput(true);
|
||||
|
||||
OutputStreamWriter redirectWriter = new OutputStreamWriter(
|
||||
connection.getOutputStream(), StandardCharsets.UTF_8);
|
||||
redirectWriter.write(requestBody);
|
||||
redirectWriter.flush();
|
||||
redirectWriter.close();
|
||||
|
||||
responseCode = connection.getResponseCode();
|
||||
}
|
||||
}
|
||||
|
||||
// 응답 읽기
|
||||
BufferedReader reader = null;
|
||||
StringBuilder response = new StringBuilder();
|
||||
|
||||
try {
|
||||
if (responseCode >= 200 && responseCode < 300) {
|
||||
reader = new BufferedReader(new InputStreamReader(
|
||||
connection.getInputStream(), StandardCharsets.UTF_8));
|
||||
} else {
|
||||
// 에러 스트림이 null일 수 있으므로 체크
|
||||
java.io.InputStream errorStream = connection.getErrorStream();
|
||||
if (errorStream != null) {
|
||||
reader = new BufferedReader(new InputStreamReader(
|
||||
errorStream, StandardCharsets.UTF_8));
|
||||
} else {
|
||||
// 에러 스트림이 없으면 응답 코드만 반환
|
||||
throw new Exception("API 호출 실패: HTTP " + responseCode + " (에러 응답 본문 없음)");
|
||||
}
|
||||
}
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (responseCode >= 200 && responseCode < 300) {
|
||||
return response.toString();
|
||||
} else {
|
||||
throw new Exception("API 호출 실패: HTTP " + responseCode + " - " + response.toString());
|
||||
}
|
||||
|
||||
} finally {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 요청 본문 JSON을 생성합니다.
|
||||
*
|
||||
* @param coCd 회사코드
|
||||
* @param baselocFg 기준위치구분
|
||||
* @return JSON 문자열
|
||||
*/
|
||||
private String buildRequestBody(String coCd, String baselocFg) {
|
||||
StringBuilder json = new StringBuilder();
|
||||
json.append("{");
|
||||
json.append("\"coCd\":\"").append(escapeJson(coCd)).append("\"");
|
||||
|
||||
if (baselocFg != null && !baselocFg.trim().isEmpty()) {
|
||||
json.append(",\"baselocFg\":\"").append(escapeJson(baselocFg)).append("\"");
|
||||
}
|
||||
|
||||
json.append("}");
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON 문자열 이스케이프 처리
|
||||
*
|
||||
* @param value 원본 문자열
|
||||
* @return 이스케이프된 문자열
|
||||
*/
|
||||
private String escapeJson(String value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
return value.replace("\\", "\\\\")
|
||||
.replace("\"", "\\\"")
|
||||
.replace("\n", "\\n")
|
||||
.replace("\r", "\\r")
|
||||
.replace("\t", "\\t");
|
||||
}
|
||||
|
||||
/**
|
||||
* 32자리 랜덤 transaction-id 생성
|
||||
*
|
||||
* @return 32자리 랜덤 문자열
|
||||
*/
|
||||
private String generateTransactionId() {
|
||||
String chars = "0123456789abcdef";
|
||||
Random random = new Random();
|
||||
StringBuilder sb = new StringBuilder(32);
|
||||
for (int i = 0; i < 32; i++) {
|
||||
sb.append(chars.charAt(random.nextInt(chars.length())));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wehago-sign 생성
|
||||
* HMacSHA256(key=hashKey, value=accessToken+transactionId+timestamp+url) 후 Base64 인코딩
|
||||
*
|
||||
* @param accessToken 접근 토큰
|
||||
* @param transactionId 트랜잭션 ID
|
||||
* @param timestamp 타임스탬프
|
||||
* @param urlPath URL 경로
|
||||
* @return Base64 인코딩된 서명
|
||||
* @throws Exception 서명 생성 중 발생하는 예외
|
||||
*/
|
||||
private String generateWehagoSign(String accessToken, String transactionId,
|
||||
String timestamp, String urlPath) throws Exception {
|
||||
try {
|
||||
// value = accessToken + transactionId + timestamp + url
|
||||
String value = accessToken + transactionId + timestamp + urlPath;
|
||||
|
||||
// HMacSHA256 생성
|
||||
SecretKeySpec keySpec = new SecretKeySpec(
|
||||
HASH_KEY.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(keySpec);
|
||||
byte[] encrypted = mac.doFinal(value.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
// Base64 인코딩
|
||||
String base64Binary = Base64.encodeBase64String(encrypted);
|
||||
return base64Binary;
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Wehago-sign 생성 오류: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON 응답을 읽기 쉬운 텍스트 형식으로 출력
|
||||
*
|
||||
* @param jsonResponse JSON 응답 문자열
|
||||
*/
|
||||
private static void printWarehouseList(String jsonResponse) {
|
||||
try {
|
||||
// 간단한 JSON 파싱 (JDK 1.7 호환)
|
||||
if (jsonResponse == null || jsonResponse.trim().isEmpty()) {
|
||||
System.out.println("응답 데이터가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// resultData 배열 찾기
|
||||
int dataStart = jsonResponse.indexOf("\"resultData\":[");
|
||||
if (dataStart == -1) {
|
||||
System.out.println("창고 데이터를 찾을 수 없습니다.");
|
||||
System.out.println("원본 응답: " + jsonResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
// resultCode 확인
|
||||
int codeStart = jsonResponse.indexOf("\"resultCode\":");
|
||||
if (codeStart != -1) {
|
||||
int codeEnd = jsonResponse.indexOf(",", codeStart);
|
||||
if (codeEnd == -1) codeEnd = jsonResponse.indexOf("}", codeStart);
|
||||
String resultCode = jsonResponse.substring(codeStart + 13, codeEnd).trim();
|
||||
System.out.println("결과 코드: " + resultCode);
|
||||
}
|
||||
|
||||
// resultMsg 확인
|
||||
int msgStart = jsonResponse.indexOf("\"resultMsg\":\"");
|
||||
if (msgStart != -1) {
|
||||
int msgEnd = jsonResponse.indexOf("\"", msgStart + 13);
|
||||
String resultMsg = jsonResponse.substring(msgStart + 13, msgEnd);
|
||||
System.out.println("결과 메시지: " + resultMsg);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
// 창고 정보 파싱 및 출력
|
||||
String dataSection = jsonResponse.substring(dataStart + 14);
|
||||
int bracketCount = 0;
|
||||
int startIdx = -1;
|
||||
int warehouseCount = 0;
|
||||
|
||||
System.out.println("====================================");
|
||||
System.out.println("창고 목록");
|
||||
System.out.println("====================================");
|
||||
System.out.println();
|
||||
|
||||
for (int i = 0; i < dataSection.length(); i++) {
|
||||
char c = dataSection.charAt(i);
|
||||
|
||||
if (c == '{') {
|
||||
if (bracketCount == 0) {
|
||||
startIdx = i;
|
||||
}
|
||||
bracketCount++;
|
||||
} else if (c == '}') {
|
||||
bracketCount--;
|
||||
if (bracketCount == 0 && startIdx != -1) {
|
||||
// 창고 객체 추출
|
||||
String warehouseJson = dataSection.substring(startIdx, i + 1);
|
||||
printWarehouseInfo(warehouseJson, ++warehouseCount);
|
||||
startIdx = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.println("====================================");
|
||||
System.out.println("총 " + warehouseCount + "개 창고");
|
||||
System.out.println("====================================");
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("출력 중 오류 발생: " + e.getMessage());
|
||||
System.out.println("원본 응답: " + jsonResponse);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 개별 창고 정보를 읽기 쉬운 형식으로 출력
|
||||
*
|
||||
* @param warehouseJson 창고 JSON 문자열
|
||||
* @param index 순번
|
||||
*/
|
||||
private static void printWarehouseInfo(String warehouseJson, int index) {
|
||||
System.out.println("[" + index + "] 창고 정보");
|
||||
System.out.println("------------------------------------");
|
||||
|
||||
// API 문서 기준 필드 추출
|
||||
String coCd = extractJsonValue(warehouseJson, "coCd");
|
||||
String baselocCd = extractJsonValue(warehouseJson, "baselocCd");
|
||||
String baselocNm = extractJsonValue(warehouseJson, "baselocNm");
|
||||
String baselocFg = extractJsonValue(warehouseJson, "baselocFg");
|
||||
String divCd = extractJsonValue(warehouseJson, "divCd");
|
||||
String inlocCd = extractJsonValue(warehouseJson, "inlocCd");
|
||||
String inlocNm = extractJsonValue(warehouseJson, "inlocNm");
|
||||
String outlocCd = extractJsonValue(warehouseJson, "outlocCd");
|
||||
String outlocNm = extractJsonValue(warehouseJson, "outlocNm");
|
||||
String baselocDc = extractJsonValue(warehouseJson, "baselocDc");
|
||||
String useYn = extractJsonValue(warehouseJson, "useYn");
|
||||
String useYnNm = extractJsonValue(warehouseJson, "useYnNm");
|
||||
|
||||
System.out.println(" 회사코드: " + (coCd.isEmpty() ? "-" : coCd));
|
||||
System.out.println(" 창고코드: " + (baselocCd.isEmpty() ? "-" : baselocCd));
|
||||
System.out.println(" 창고명: " + (baselocNm.isEmpty() ? "-" : baselocNm));
|
||||
|
||||
// 구분코드 해석
|
||||
String baselocFgNm = "-";
|
||||
if ("0".equals(baselocFg)) baselocFgNm = "창고";
|
||||
else if ("1".equals(baselocFg)) baselocFgNm = "생산공정";
|
||||
else if ("2".equals(baselocFg)) baselocFgNm = "외주공정";
|
||||
System.out.println(" 구분: " + baselocFgNm + " (" + baselocFg + ")");
|
||||
|
||||
if (!divCd.isEmpty()) {
|
||||
System.out.println(" 사업장코드: " + divCd);
|
||||
}
|
||||
if (!inlocCd.isEmpty()) {
|
||||
System.out.println(" 입고기본장소: " + inlocCd + (inlocNm.isEmpty() ? "" : " (" + inlocNm + ")"));
|
||||
}
|
||||
if (!outlocCd.isEmpty()) {
|
||||
System.out.println(" 출고기본장소: " + outlocCd + (outlocNm.isEmpty() ? "" : " (" + outlocNm + ")"));
|
||||
}
|
||||
if (!baselocDc.isEmpty()) {
|
||||
System.out.println(" 비고: " + baselocDc);
|
||||
}
|
||||
if (!useYnNm.isEmpty()) {
|
||||
System.out.println(" 사용여부: " + useYnNm);
|
||||
} else if (!useYn.isEmpty()) {
|
||||
System.out.println(" 사용여부: " + (useYn.equals("1") ? "사용" : "미사용"));
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON 문자열에서 특정 필드의 값을 추출
|
||||
*
|
||||
* @param json JSON 문자열
|
||||
* @param fieldName 필드명
|
||||
* @return 필드 값 (없으면 빈 문자열)
|
||||
*/
|
||||
private static String extractJsonValue(String json, String fieldName) {
|
||||
String searchKey = "\"" + fieldName + "\":";
|
||||
int startIdx = json.indexOf(searchKey);
|
||||
if (startIdx == -1) {
|
||||
return "";
|
||||
}
|
||||
|
||||
startIdx += searchKey.length();
|
||||
|
||||
// 공백 제거
|
||||
while (startIdx < json.length() && Character.isWhitespace(json.charAt(startIdx))) {
|
||||
startIdx++;
|
||||
}
|
||||
|
||||
if (startIdx >= json.length()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
char firstChar = json.charAt(startIdx);
|
||||
|
||||
// 문자열 값인 경우
|
||||
if (firstChar == '"') {
|
||||
int endIdx = json.indexOf('"', startIdx + 1);
|
||||
if (endIdx == -1) return "";
|
||||
return json.substring(startIdx + 1, endIdx);
|
||||
}
|
||||
// 숫자나 null인 경우
|
||||
else {
|
||||
int endIdx = startIdx;
|
||||
while (endIdx < json.length() &&
|
||||
(Character.isDigit(json.charAt(endIdx)) ||
|
||||
json.charAt(endIdx) == '.' ||
|
||||
json.charAt(endIdx) == '-' ||
|
||||
json.charAt(endIdx) == 'n' || // null
|
||||
json.charAt(endIdx) == 'u' ||
|
||||
json.charAt(endIdx) == 'l')) {
|
||||
endIdx++;
|
||||
}
|
||||
String value = json.substring(startIdx, endIdx).trim();
|
||||
// null 체크
|
||||
if (value.startsWith("null")) {
|
||||
return "";
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 메인 메서드
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// JDK 1.7에서 TLS 1.2 활성화
|
||||
System.setProperty("https.protocols", "TLSv1.2");
|
||||
|
||||
WarehouseApiClient client = new WarehouseApiClient();
|
||||
|
||||
try {
|
||||
System.out.println("====================================");
|
||||
System.out.println("창고 조회 API 호출 테스트");
|
||||
System.out.println("====================================");
|
||||
System.out.println();
|
||||
|
||||
String baseUrl = "https://erp.rps-korea.com";
|
||||
String apiEndpoint = API_URL.replace("~", ""); // ~ 제거
|
||||
System.out.println("API 서버: " + baseUrl);
|
||||
System.out.println("API 엔드포인트: " + apiEndpoint);
|
||||
System.out.println();
|
||||
|
||||
// 회사코드 1000, baselocFg=0 으로 창고 조회
|
||||
System.out.println("[1] 회사코드 1000, baselocFg=0 으로 창고 조회");
|
||||
System.out.println("------------------------------------");
|
||||
String response = client.getWarehouseList(
|
||||
baseUrl,
|
||||
"1000", // 회사코드
|
||||
"0" // baselocFg: 0 (창고)
|
||||
);
|
||||
|
||||
// 원본 응답 출력
|
||||
System.out.println("원본 응답: " + response);
|
||||
System.out.println();
|
||||
|
||||
// JSON 응답을 읽기 쉬운 텍스트 형식으로 출력
|
||||
printWarehouseList(response);
|
||||
System.out.println();
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("====================================");
|
||||
System.err.println("오류 발생: " + e.getMessage());
|
||||
System.err.println("====================================");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5281,4 +5281,31 @@ public String clientImportFileProc(HttpServletRequest request, HttpSession sessi
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* ERP 창고 정보 동기화 수동 실행
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/admin/syncWarehouseDataManual.do")
|
||||
@ResponseBody
|
||||
public Map<String, Object> syncWarehouseDataManual(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
System.out.println("====================================");
|
||||
System.out.println("관리자 수동 ERP 창고 동기화 실행 요청");
|
||||
System.out.println("====================================");
|
||||
|
||||
resultMap = batchService.syncWarehouseDataManual();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("message", "창고 동기화 실행 중 오류가 발생했습니다: " + e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,5 +178,61 @@
|
||||
END,
|
||||
data_type = #{data_type}
|
||||
</insert>
|
||||
|
||||
<!-- 창고 정보 UPSERT -->
|
||||
<insert id="upsertWarehouse" parameterType="map">
|
||||
INSERT INTO warehouse_location (
|
||||
objid,
|
||||
location_code,
|
||||
location_name,
|
||||
location_description,
|
||||
out_code,
|
||||
out_co_name,
|
||||
fit_status,
|
||||
available_status,
|
||||
use_status,
|
||||
base_loc_cd,
|
||||
co_cd,
|
||||
loc_nmk,
|
||||
attr_nmk,
|
||||
insert_id,
|
||||
writer,
|
||||
regdate,
|
||||
status
|
||||
) VALUES (
|
||||
#{location_code},
|
||||
#{location_code},
|
||||
#{location_name},
|
||||
#{location_description},
|
||||
#{out_code},
|
||||
#{out_co_name},
|
||||
#{fit_status},
|
||||
#{available_status},
|
||||
#{use_status},
|
||||
#{base_loc_cd},
|
||||
#{co_cd},
|
||||
#{loc_nmk},
|
||||
#{attr_nmk},
|
||||
#{insert_id},
|
||||
#{writer},
|
||||
NOW(),
|
||||
#{status}
|
||||
) ON CONFLICT (location_code) DO
|
||||
UPDATE SET
|
||||
location_name = #{location_name},
|
||||
location_description = #{location_description},
|
||||
out_code = #{out_code},
|
||||
out_co_name = #{out_co_name},
|
||||
fit_status = #{fit_status},
|
||||
available_status = #{available_status},
|
||||
use_status = #{use_status},
|
||||
base_loc_cd = #{base_loc_cd},
|
||||
co_cd = #{co_cd},
|
||||
loc_nmk = #{loc_nmk},
|
||||
attr_nmk = #{attr_nmk},
|
||||
modify_id = #{insert_id},
|
||||
modify_dt = NOW(),
|
||||
status = #{status}
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import com.pms.api.CustomerApiClient;
|
||||
import com.pms.api.DepartmentApiClient;
|
||||
import com.pms.api.EmployeeApiClient;
|
||||
import com.pms.api.WarehouseApiClient;
|
||||
import com.pms.common.Message;
|
||||
import com.pms.common.SqlMapConfig;
|
||||
import com.pms.common.bean.PersonBean;
|
||||
@@ -285,6 +286,41 @@ public class BatchService extends BaseService {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 창고 정보만 동기화 (수동 실행)
|
||||
* @return 성공 여부 Map
|
||||
*/
|
||||
public Map<String, Object> syncWarehouseDataManual() {
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
SqlSession sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
System.out.println("====================================");
|
||||
System.out.println("ERP 창고 정보 동기화 시작 (수동)");
|
||||
System.out.println("====================================");
|
||||
|
||||
try {
|
||||
String baseUrl = "https://erp.rps-korea.com";
|
||||
String coCd = "1000";
|
||||
|
||||
syncWarehouseData(sqlSession, baseUrl, coCd);
|
||||
|
||||
sqlSession.commit();
|
||||
result.put("success", true);
|
||||
result.put("message", "창고 정보 동기화가 완료되었습니다.");
|
||||
System.out.println("ERP 창고 정보 동기화 완료");
|
||||
} catch (Exception e) {
|
||||
sqlSession.rollback();
|
||||
result.put("success", false);
|
||||
result.put("message", "창고 정보 동기화 중 오류가 발생했습니다: " + e.getMessage());
|
||||
System.err.println("창고 정보 동기화 오류: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
sqlSession.close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ERP 데이터 동기화 실제 실행 로직
|
||||
*/
|
||||
@@ -305,6 +341,9 @@ public class BatchService extends BaseService {
|
||||
// 3. 사원 정보 동기화
|
||||
syncEmployeeData(sqlSession, baseUrl, coCd);
|
||||
|
||||
// 4. 창고 정보 동기화
|
||||
syncWarehouseData(sqlSession, baseUrl, coCd);
|
||||
|
||||
sqlSession.commit();
|
||||
System.out.println("ERP 데이터 동기화 배치 완료");
|
||||
|
||||
@@ -458,6 +497,51 @@ public class BatchService extends BaseService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 창고 정보 동기화
|
||||
*/
|
||||
private void syncWarehouseData(SqlSession sqlSession, String baseUrl, String coCd) {
|
||||
try {
|
||||
System.out.println("창고 정보 동기화 시작...");
|
||||
|
||||
WarehouseApiClient warehouseClient = new WarehouseApiClient();
|
||||
String jsonResponse = warehouseClient.getWarehouseList(baseUrl, coCd, "0");
|
||||
|
||||
// JSON 파싱 및 DB 저장
|
||||
List<Map<String, Object>> warehouseList = parseWarehouseJson(jsonResponse);
|
||||
|
||||
int processCount = 0;
|
||||
|
||||
// 처음 10건 로그 출력
|
||||
System.out.println("====================================");
|
||||
System.out.println("창고 데이터 샘플 (최대 10건)");
|
||||
System.out.println("====================================");
|
||||
|
||||
for (Map<String, Object> warehouse : warehouseList) {
|
||||
// 처음 10건만 로그 출력
|
||||
if (processCount < 10) {
|
||||
System.out.println("[창고 " + (processCount + 1) + "]");
|
||||
System.out.println(" - LOCATION_CODE: " + warehouse.get("location_code"));
|
||||
System.out.println(" - LOCATION_NAME: " + warehouse.get("location_name"));
|
||||
System.out.println(" - OUT_CODE: " + warehouse.get("out_code"));
|
||||
System.out.println(" - USE_STATUS: " + warehouse.get("use_status"));
|
||||
System.out.println("---");
|
||||
}
|
||||
|
||||
// UPSERT 실행
|
||||
sqlSession.insert("batch.upsertWarehouse", warehouse);
|
||||
processCount++;
|
||||
}
|
||||
|
||||
System.out.println("====================================");
|
||||
System.out.println("창고 정보 동기화 완료 - 처리: " + processCount + "건");
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("창고 정보 동기화 실패: " + e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 거래처 JSON 파싱
|
||||
*/
|
||||
@@ -813,6 +897,89 @@ public class BatchService extends BaseService {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 창고 JSON 파싱
|
||||
*/
|
||||
private List<Map<String, Object>> parseWarehouseJson(String jsonResponse) {
|
||||
List<Map<String, Object>> warehouseList = new ArrayList<Map<String, Object>>();
|
||||
|
||||
try {
|
||||
// resultData 배열 찾기
|
||||
int dataStart = jsonResponse.indexOf("\"resultData\":[");
|
||||
if (dataStart == -1) {
|
||||
return warehouseList;
|
||||
}
|
||||
|
||||
String dataSection = jsonResponse.substring(dataStart + 14);
|
||||
int bracketCount = 0;
|
||||
int startIdx = -1;
|
||||
|
||||
for (int i = 0; i < dataSection.length(); i++) {
|
||||
char c = dataSection.charAt(i);
|
||||
|
||||
if (c == '{') {
|
||||
if (bracketCount == 0) {
|
||||
startIdx = i;
|
||||
}
|
||||
bracketCount++;
|
||||
} else if (c == '}') {
|
||||
bracketCount--;
|
||||
if (bracketCount == 0 && startIdx != -1) {
|
||||
String warehouseJson = dataSection.substring(startIdx, i + 1);
|
||||
Map<String, Object> warehouse = parseWarehouseObject(warehouseJson);
|
||||
if (warehouse != null) {
|
||||
warehouseList.add(warehouse);
|
||||
}
|
||||
startIdx = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("창고 JSON 파싱 오류: " + e.getMessage());
|
||||
}
|
||||
|
||||
return warehouseList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 창고 객체 파싱
|
||||
*/
|
||||
private Map<String, Object> parseWarehouseObject(String json) {
|
||||
Map<String, Object> warehouse = new HashMap<String, Object>();
|
||||
|
||||
// location_code를 objid에도 동일하게 저장
|
||||
String locationCode = extractJsonValue(json, "baselocCd");
|
||||
warehouse.put("objid", locationCode);
|
||||
warehouse.put("location_code", locationCode);
|
||||
|
||||
// 기본 정보
|
||||
warehouse.put("location_name", extractJsonValue(json, "baselocNm"));
|
||||
warehouse.put("location_description", extractJsonValue(json, "baselocDc"));
|
||||
warehouse.put("out_code", extractJsonValue(json, "outlocCd"));
|
||||
warehouse.put("out_co_name", extractJsonValue(json, "outlocNm"));
|
||||
|
||||
// 상태 정보
|
||||
String baselocFg = extractJsonValue(json, "baselocFg");
|
||||
warehouse.put("fit_status", baselocFg);
|
||||
|
||||
String useYn = extractJsonValue(json, "useYn");
|
||||
warehouse.put("available_status", useYn);
|
||||
warehouse.put("use_status", "1".equals(useYn) ? "Y" : "N");
|
||||
|
||||
// 추가 정보
|
||||
warehouse.put("base_loc_cd", extractJsonValue(json, "baselocCd"));
|
||||
warehouse.put("co_cd", extractJsonValue(json, "coCd"));
|
||||
warehouse.put("loc_nmk", extractJsonValue(json, "baselocNm"));
|
||||
warehouse.put("attr_nmk", extractJsonValue(json, "inlocNm"));
|
||||
|
||||
// 시스템 정보
|
||||
warehouse.put("insert_id", "batch_system");
|
||||
warehouse.put("writer", "batch_system");
|
||||
warehouse.put("status", "active");
|
||||
|
||||
return warehouse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user