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