fix: ACI POD 배송중 추적 및 배송완료 전환 보정
This commit is contained in:
@@ -30,7 +30,7 @@ import java.math.BigInteger;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
// ACI 배송자료 조회 및 배송처리 배치 Tasklet
|
// ACI 배송자료 조회 및 배송처리 배치 Tasklet
|
||||||
// 흐름: gc_order_shipping(DLIVY_STTUS_CD=55) 조회 → 토큰 발급 → ACI API 호출 → BLNO 추출 → 배송처리
|
// 흐름: gc_goods_export(DLIVY_STTUS_CD=55,65) 조회 -> 토큰 발급 -> ACI API 호출 -> BLNO 검증 -> 배송처리
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -57,7 +57,9 @@ public class AciPodTasklet implements Tasklet {
|
|||||||
@Value("${acikey.apikey}")
|
@Value("${acikey.apikey}")
|
||||||
private String apiKey;
|
private String apiKey;
|
||||||
|
|
||||||
private static final String DLIVY_STTUS_CD = "55"; // 출고완료 코드
|
private static final String DLIVY_STTUS_CD_EXPORT_COMPLETE = "55"; // 출고완료 코드
|
||||||
|
private static final String DLIVY_STTUS_CD_DELIVERY_IN_PROGRESS = "65"; // 배송중 코드
|
||||||
|
private static final String DLIVY_STTUS_CD_DELIVERY_COMPLETE = "75"; // 배송완료 코드
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
|
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
|
||||||
@@ -66,8 +68,8 @@ public class AciPodTasklet implements Tasklet {
|
|||||||
// 토큰 발급 (yaml 고정 apikey → ACIKey 토큰 발급, 메모리에만 유지)
|
// 토큰 발급 (yaml 고정 apikey → ACIKey 토큰 발급, 메모리에만 유지)
|
||||||
String aciKeyToken = issueAciKeyToken();
|
String aciKeyToken = issueAciKeyToken();
|
||||||
|
|
||||||
// 대상 주문 목록 조회 (DLIVY_STTUS_CD = '55')
|
// 대상 주문 목록 조회 (DLIVY_STTUS_CD IN ('55', '65'))
|
||||||
List<AciDlivyOrderVO> goodsExportList = AciDlivyMapper.selectGoodsExportList(DLIVY_STTUS_CD);
|
List<AciDlivyOrderVO> goodsExportList = AciDlivyMapper.selectGoodsExportList();
|
||||||
log.info("[AciPodBatch] 대상 출고 건수: {}", goodsExportList.size());
|
log.info("[AciPodBatch] 대상 출고 건수: {}", goodsExportList.size());
|
||||||
|
|
||||||
if (goodsExportList.isEmpty()) {
|
if (goodsExportList.isEmpty()) {
|
||||||
@@ -87,28 +89,39 @@ public class AciPodTasklet implements Tasklet {
|
|||||||
try {
|
try {
|
||||||
// 건별 ACI 출고자료 API 호출
|
// 건별 ACI 출고자료 API 호출
|
||||||
List<DataMap> podInfoList = callAciPodApi(dlivyOrderVO, aciKeyToken);
|
List<DataMap> podInfoList = callAciPodApi(dlivyOrderVO, aciKeyToken);
|
||||||
if (podInfoList.isEmpty()) {
|
if (CollectionUtils.isEmpty(podInfoList)) {
|
||||||
skipCnt++;
|
skipCnt++;
|
||||||
} else {
|
} else {
|
||||||
boolean dlvyInPrg = podInfoList.stream()
|
boolean dlvyInPrg = podInfoList.stream()
|
||||||
.anyMatch(podInfo -> !isBlank(podInfo, "dateLocalwhin"));
|
.anyMatch(podInfo -> !isBlank(podInfo, "dateLocalwhin"));
|
||||||
boolean dlvyCompt = podInfoList.stream()
|
boolean dlvyCompt = podInfoList.stream()
|
||||||
.allMatch(podInfo -> !isBlank(podInfo, "dateDelivery"));
|
.anyMatch(podInfo -> !isBlank(podInfo, "dateDelivery"));
|
||||||
|
|
||||||
// 건별 배송처리
|
// 건별 배송처리
|
||||||
BODlivyUpdtVO boDlivyUpdtVO = new BODlivyUpdtVO();
|
BODlivyUpdtVO boDlivyUpdtVO = new BODlivyUpdtVO();
|
||||||
boDlivyUpdtVO.setDlivyInnb(dlivyOrderVO.getDlivyInnb());
|
boDlivyUpdtVO.setDlivyInnb(dlivyOrderVO.getDlivyInnb());
|
||||||
boDlivyUpdtVO.setDlivySttusCd(dlivyOrderVO.getDlivySttusCd());
|
boDlivyUpdtVO.setDlivySttusCd(dlivyOrderVO.getDlivySttusCd());
|
||||||
boDlivyUpdtVO.setSopmalCd(dlivyOrderVO.getSopmalCd());
|
boDlivyUpdtVO.setSopmalCd(dlivyOrderVO.getSopmalCd());
|
||||||
if(dlvyInPrg) {
|
|
||||||
boDlivyUpdtVO.setDlivySttusCd("65");
|
String currentDlivySttusCd = dlivyOrderVO.getDlivySttusCd();
|
||||||
|
if (dlvyCompt) {
|
||||||
|
boDlivyUpdtVO.setDlivySttusCd(DLIVY_STTUS_CD_DELIVERY_COMPLETE);
|
||||||
processDeliveryPod(boDlivyUpdtVO);
|
processDeliveryPod(boDlivyUpdtVO);
|
||||||
}
|
|
||||||
if(dlvyCompt) {
|
|
||||||
boDlivyUpdtVO.setDlivySttusCd("75");
|
|
||||||
processDeliveryPod(boDlivyUpdtVO);
|
|
||||||
}
|
|
||||||
successCnt++;
|
successCnt++;
|
||||||
|
} else if (dlvyInPrg && DLIVY_STTUS_CD_EXPORT_COMPLETE.equals(currentDlivySttusCd)) {
|
||||||
|
boDlivyUpdtVO.setDlivySttusCd(DLIVY_STTUS_CD_DELIVERY_IN_PROGRESS);
|
||||||
|
processDeliveryPod(boDlivyUpdtVO);
|
||||||
|
successCnt++;
|
||||||
|
} else {
|
||||||
|
if (dlvyInPrg && DLIVY_STTUS_CD_DELIVERY_IN_PROGRESS.equals(currentDlivySttusCd)) {
|
||||||
|
log.info("[AciPodBatch] 스킵 - 이미 배송중 상태 유지 - DLIVY_INNB={}, INVCNB={}",
|
||||||
|
dlivyOrderVO.getDlivyInnb(), dlivyOrderVO.getInvcnb());
|
||||||
|
} else {
|
||||||
|
log.info("[AciPodBatch] 스킵 - ACI 배송상태 판단 불가 - DLIVY_INNB={}, INVCNB={}",
|
||||||
|
dlivyOrderVO.getDlivyInnb(), dlivyOrderVO.getInvcnb());
|
||||||
|
}
|
||||||
|
skipCnt++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[AciPodBatch] 배송처리 실패 - DLIVY_INNB={}, 오류={}",
|
log.error("[AciPodBatch] 배송처리 실패 - DLIVY_INNB={}, 오류={}",
|
||||||
@@ -188,7 +201,7 @@ public class AciPodTasklet implements Tasklet {
|
|||||||
|
|
||||||
HttpEntity<Map<String, Object>> apiRequest =
|
HttpEntity<Map<String, Object>> apiRequest =
|
||||||
new HttpEntity<>(body, headers);
|
new HttpEntity<>(body, headers);
|
||||||
log.info("[AciPodBatch] API 응답: {}", apiRequest.toString());
|
log.info("[AciPodBatch] API 요청: {}", apiRequest.toString());
|
||||||
|
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
RestTemplate restTemplate = new RestTemplate();
|
||||||
ResponseEntity<String> response = restTemplate.exchange(
|
ResponseEntity<String> response = restTemplate.exchange(
|
||||||
@@ -201,70 +214,100 @@ public class AciPodTasklet implements Tasklet {
|
|||||||
ObjectMapper objectMapper = new ObjectMapper();
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
JsonNode jsonNode = objectMapper.readTree(response.getBody());
|
JsonNode jsonNode = objectMapper.readTree(response.getBody());
|
||||||
|
|
||||||
log.info("[AciPodBatch] API 응답 Status: {}", jsonNode.get("Status").asText());
|
String status = getText(jsonNode, "Status");
|
||||||
log.info("[AciPodBatch] API 응답 RstMsg: {}", jsonNode.get("RstMsg").asText());
|
log.info("[AciPodBatch] API 응답 Status: {}", status);
|
||||||
|
log.info("[AciPodBatch] API 응답 RstMsg: {}", getText(jsonNode, "RstMsg"));
|
||||||
|
|
||||||
|
if (!"success".equals(status)) {
|
||||||
|
log.info("[AciPodBatch] 스킵 - ACI 응답 Status 실패 - DLIVY_INNB={}, Status={}, ErrMsg={}",
|
||||||
|
orderVO.getDlivyInnb(), status, getText(jsonNode, "ErrMsg"));
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
JsonNode podInfoNode = jsonNode.get("PODInfo");
|
JsonNode podInfoNode = jsonNode.get("PODInfo");
|
||||||
if(!podInfoNode.isNull()) {
|
if(podInfoNode != null && podInfoNode.isArray() && podInfoNode.size() > 0) {
|
||||||
List<DataMap> podInfoList = new ArrayList<>();
|
List<DataMap> podInfoList = new ArrayList<>();
|
||||||
for(JsonNode podInfoItem : podInfoNode) {
|
for(JsonNode podInfoItem : podInfoNode) {
|
||||||
|
String blno = getText(podInfoItem, "BLNO");
|
||||||
|
if (!Objects.equals(trimToEmpty(orderVO.getInvcnb()), trimToEmpty(blno))) {
|
||||||
|
log.info("[AciPodBatch] 스킵 - 요청 송장번호와 ACI 응답 BLNO 불일치 - DLIVY_INNB={}, INVCNB={}, BLNO={}",
|
||||||
|
orderVO.getDlivyInnb(), orderVO.getInvcnb(), blno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
DataMap PODInfo = new DataMap();
|
DataMap PODInfo = new DataMap();
|
||||||
PODInfo.put("blno", podInfoItem.get("BLNO").asText());
|
PODInfo.put("blno", blno);
|
||||||
PODInfo.put("dateLocalwhin", podInfoItem.get("DATE_LOCALWHIN").asText());
|
PODInfo.put("dateLocalwhin", getText(podInfoItem, "DATE_LOCALWHIN"));
|
||||||
PODInfo.put("dateLocaldeparture", podInfoItem.get("DATE_LOCALDEPARTURE").asText());
|
PODInfo.put("dateLocaldeparture", getText(podInfoItem, "DATE_LOCALDEPARTURE"));
|
||||||
PODInfo.put("dateIcnarrival", podInfoItem.get("DATE_ICNARRIVAL").asText());
|
PODInfo.put("dateIcnarrival", getText(podInfoItem, "DATE_ICNARRIVAL"));
|
||||||
PODInfo.put("dateCustomes", podInfoItem.get("DATE_CUSTOMES").asText());
|
PODInfo.put("dateCustomes", getText(podInfoItem, "DATE_CUSTOMES"));
|
||||||
PODInfo.put("dateDelivery", podInfoItem.get("DATE_DELIVERY").asText());
|
PODInfo.put("dateDelivery", getText(podInfoItem, "DATE_DELIVERY"));
|
||||||
PODInfo.put("recipient", podInfoItem.get("RECIPIENT").asText());
|
PODInfo.put("recipient", getText(podInfoItem, "RECIPIENT"));
|
||||||
PODInfo.put("wta", podInfoItem.get("WTA").asText());
|
PODInfo.put("wta", getText(podInfoItem, "WTA"));
|
||||||
PODInfo.put("wtdan", podInfoItem.get("WTDAN").asText());
|
PODInfo.put("wtdan", getText(podInfoItem, "WTDAN"));
|
||||||
|
|
||||||
List<DataMap> volumeList = new ArrayList<>();
|
List<DataMap> volumeList = new ArrayList<>();
|
||||||
for(JsonNode volumeItem : podInfoItem.get("VOLUME")) {
|
JsonNode volumeNode = podInfoItem.get("VOLUME");
|
||||||
|
if (volumeNode != null && volumeNode.isArray()) {
|
||||||
|
for(JsonNode volumeItem : volumeNode) {
|
||||||
DataMap volume = new DataMap();
|
DataMap volume = new DataMap();
|
||||||
volume.put("width", volumeItem.get("WIDTH").asText());
|
volume.put("width", getText(volumeItem, "WIDTH"));
|
||||||
volume.put("length", volumeItem.get("LENGTH").asText());
|
volume.put("length", getText(volumeItem, "LENGTH"));
|
||||||
volume.put("height", volumeItem.get("HEIGHT").asText());
|
volume.put("height", getText(volumeItem, "HEIGHT"));
|
||||||
|
|
||||||
volumeList.add(volume);
|
volumeList.add(volume);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
PODInfo.put("volume", volumeList);
|
PODInfo.put("volume", volumeList);
|
||||||
|
|
||||||
List<List> customsList = new ArrayList<>();
|
List<List> customsList = new ArrayList<>();
|
||||||
for(JsonNode customsItem : podInfoItem.get("CUSTOMS")) {
|
JsonNode customsNode = podInfoItem.get("CUSTOMS");
|
||||||
|
if (customsNode != null && customsNode.isArray()) {
|
||||||
|
for(JsonNode customsItem : customsNode) {
|
||||||
List<DataMap> customDetail = new ArrayList<>();
|
List<DataMap> customDetail = new ArrayList<>();
|
||||||
for(JsonNode customItem : customsItem) {
|
for(JsonNode customItem : customsItem) {
|
||||||
DataMap Custom = new DataMap();
|
DataMap Custom = new DataMap();
|
||||||
Custom.put("dateEvent", customItem.get("DATE_EVENT").asText());
|
Custom.put("dateEvent", getText(customItem, "DATE_EVENT"));
|
||||||
Custom.put("traceStatus", customItem.get("TRACE_STATUS").asText());
|
Custom.put("traceStatus", getText(customItem, "TRACE_STATUS"));
|
||||||
|
|
||||||
customDetail.add(Custom);
|
customDetail.add(Custom);
|
||||||
}
|
}
|
||||||
customsList.add(customDetail);
|
customsList.add(customDetail);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
PODInfo.put("customs", customsList);
|
PODInfo.put("customs", customsList);
|
||||||
|
|
||||||
List<DataMap> localPodList = new ArrayList<>();
|
List<DataMap> localPodList = new ArrayList<>();
|
||||||
for(JsonNode localPodItem : podInfoItem.get("LOCAL_POD")) {
|
JsonNode localPodNode = podInfoItem.get("LOCAL_POD");
|
||||||
|
if (localPodNode != null && localPodNode.isArray()) {
|
||||||
|
for(JsonNode localPodItem : localPodNode) {
|
||||||
DataMap localPod = new DataMap();
|
DataMap localPod = new DataMap();
|
||||||
localPod.put("traceStatus", localPodItem.get("TRACE_STATUS").asText());
|
localPod.put("traceStatus", getText(localPodItem, "TRACE_STATUS"));
|
||||||
localPod.put("dateEvent", localPodItem.get("DATE_EVENT").asText());
|
localPod.put("dateEvent", getText(localPodItem, "DATE_EVENT"));
|
||||||
localPod.put("position", localPodItem.get("POSITION").asText());
|
localPod.put("position", getText(localPodItem, "POSITION"));
|
||||||
|
|
||||||
localPodList.add(localPod);
|
localPodList.add(localPod);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
PODInfo.put("localPod", localPodList);
|
PODInfo.put("localPod", localPodList);
|
||||||
|
|
||||||
podInfoList.add(PODInfo);
|
podInfoList.add(PODInfo);
|
||||||
}
|
}
|
||||||
|
if (podInfoList.isEmpty()) {
|
||||||
|
log.info("[AciPodBatch] 스킵 - 요청 송장번호와 일치하는 ACI PODInfo 없음 - DLIVY_INNB={}, INVCNB={}",
|
||||||
|
orderVO.getDlivyInnb(), orderVO.getInvcnb());
|
||||||
|
} else {
|
||||||
log.info("[AciPodBatch] API 응답 PODInfo: {}", podInfoList);
|
log.info("[AciPodBatch] API 응답 PODInfo: {}", podInfoList);
|
||||||
|
}
|
||||||
return podInfoList;
|
return podInfoList;
|
||||||
} else {
|
} else {
|
||||||
log.info("[AciPodBatch] API 응답 ErrMsg: {}", jsonNode.get("ErrMsg").asText());
|
log.info("[AciPodBatch] 스킵 - ACI PODInfo 없음 - DLIVY_INNB={}, ErrMsg={}",
|
||||||
return null;
|
orderVO.getDlivyInnb(), getText(jsonNode, "ErrMsg"));
|
||||||
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[AciPodBatch] API 호출 오류 - DLIVY_INNB={}, 오류={}", orderVO.getDlivyInnb(), e.getMessage(), e);
|
log.error("[AciPodBatch] API 호출 오류 - DLIVY_INNB={}, 오류={}", orderVO.getDlivyInnb(), e.getMessage(), e);
|
||||||
return null;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,4 +478,16 @@ public class AciPodTasklet implements Tasklet {
|
|||||||
return podInfo.get(key) == null
|
return podInfo.get(key) == null
|
||||||
|| podInfo.get(key).toString().trim().isEmpty();
|
|| podInfo.get(key).toString().trim().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getText(JsonNode jsonNode, String key) {
|
||||||
|
JsonNode valueNode = jsonNode.get(key);
|
||||||
|
if (valueNode == null || valueNode.isNull()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return valueNode.asText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String trimToEmpty(String value) {
|
||||||
|
return value == null ? "" : value.trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ public interface AciDlivyMapper {
|
|||||||
/** GC_ORDER_LOG INSERT */
|
/** GC_ORDER_LOG INSERT */
|
||||||
int insertOrderLog(DataMap logMap);
|
int insertOrderLog(DataMap logMap);
|
||||||
|
|
||||||
/** 배송처리 대상 주문 목록 조회 (gc_goods_export.DLIVY_STTUS_CD = '55') */
|
/** 배송처리 대상 주문 목록 조회 (gc_goods_export.DLIVY_STTUS_CD IN ('55', '65')) */
|
||||||
List<AciDlivyOrderVO> selectGoodsExportList(String dlivySttusCd);
|
List<AciDlivyOrderVO> selectGoodsExportList();
|
||||||
|
|
||||||
/** 출고 상태 일괄 변경 다건 */
|
/** 출고 상태 일괄 변경 다건 */
|
||||||
public Integer updateBODlivySttusGetbackUpdtArr(BODlivyUpdtVO dlivyVO);
|
public Integer updateBODlivySttusGetbackUpdtArr(BODlivyUpdtVO dlivyVO);
|
||||||
|
|||||||
@@ -367,18 +367,18 @@
|
|||||||
]]>
|
]]>
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<!-- 배송처리 대상 주문 목록 조회 (DLIVY_STTUS_CD = '55' 출고완료) -->
|
<!-- 배송처리 대상 주문 목록 조회 (DLIVY_STTUS_CD IN ('55', '65')) -->
|
||||||
<select id="selectGoodsExportList" parameterType="java.lang.String"
|
<select id="selectGoodsExportList" resultType="com.wb.domainserver.acidlivy.vo.AciDlivyOrderVO">
|
||||||
resultType="com.wb.domainserver.acidlivy.vo.AciDlivyOrderVO">
|
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
SELECT
|
SELECT
|
||||||
DLIVY_INNB,
|
DLIVY_INNB,
|
||||||
ORDR_INNB,
|
ORDR_INNB,
|
||||||
ORDR_DLVY_INNB,
|
ORDR_DLVY_INNB,
|
||||||
SOPMAL_CD,
|
SOPMAL_CD,
|
||||||
INVCNB
|
INVCNB,
|
||||||
|
DLIVY_STTUS_CD
|
||||||
FROM GC_GOODS_EXPORT
|
FROM GC_GOODS_EXPORT
|
||||||
WHERE DLIVY_STTUS_CD = #{param}
|
WHERE DLIVY_STTUS_CD IN ('55', '65')
|
||||||
ORDER BY DLIVY_INNB ASC
|
ORDER BY DLIVY_INNB ASC
|
||||||
]]>
|
]]>
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
Reference in New Issue
Block a user