diff --git a/src/main/java/com/wb/domainserver/acidlivy/tasklet/AciPodTasklet.java b/src/main/java/com/wb/domainserver/acidlivy/tasklet/AciPodTasklet.java index 640fdb3..712c6f7 100644 --- a/src/main/java/com/wb/domainserver/acidlivy/tasklet/AciPodTasklet.java +++ b/src/main/java/com/wb/domainserver/acidlivy/tasklet/AciPodTasklet.java @@ -27,6 +27,9 @@ import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; import java.math.BigInteger; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.*; // ACI 배송자료 조회 및 배송처리 배치 Tasklet @@ -60,6 +63,7 @@ public class AciPodTasklet implements Tasklet { 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"; // 배송완료 코드 + private static final DateTimeFormatter ACI_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) { @@ -92,10 +96,22 @@ public class AciPodTasklet implements Tasklet { if (CollectionUtils.isEmpty(podInfoList)) { skipCnt++; } else { - boolean dlvyInPrg = podInfoList.stream() - .anyMatch(podInfo -> !isBlank(podInfo, "dateLocalwhin")); boolean dlvyCompt = podInfoList.stream() .anyMatch(podInfo -> !isBlank(podInfo, "dateDelivery")); + /* + * ACI POD API의 DATE_LOCALWHIN은 "현지 창고 입고 시간"이지만, 실제 응답에는 + * 아직 입고되지 않은 건도 입고 예정 시간이 미래 시각으로 내려올 수 있다. + * + * 기존처럼 DATE_LOCALWHIN 값 존재 여부만으로 배송중(65)을 판단하면, + * 실제 창고 입고 전 주문이 배송중으로 전환되고 주문 로그까지 생성된다. + * 2026-07-10 운영 데이터 원복 건(미래 DATE_LOCALWHIN 응답)에서 이 문제가 확인되었다. + * + * 따라서 배송완료(DATE_DELIVERY)는 기존 기준을 유지하되, 배송중 판단은 + * DATE_LOCALWHIN 값이 있고 그 시간이 현재 시스템 시간보다 과거/현재인 경우에만 허용한다. + * DATE_LOCALWHIN이 비어 있거나 미래 시간이면 아직 미입고/입고예정으로 보고 상태 변경을 skip한다. + */ + boolean dlvyInPrg = podInfoList.stream() + .anyMatch(this::isLocalWarehouseIn); // 건별 배송처리 BODlivyUpdtVO boDlivyUpdtVO = new BODlivyUpdtVO(); @@ -479,6 +495,24 @@ public class AciPodTasklet implements Tasklet { || podInfo.get(key).toString().trim().isEmpty(); } + /** + * DATE_LOCALWHIN 값이 현재 시스템 시간 기준으로 실제 입고 처리 가능한 시간인지 확인한다. + */ + private boolean isLocalWarehouseIn(DataMap podInfo) { + if (isBlank(podInfo, "dateLocalwhin")) { + return false; + } + + String dateLocalwhin = podInfo.get("dateLocalwhin").toString().trim(); + try { + LocalDateTime localWhInDateTime = LocalDateTime.parse(dateLocalwhin, ACI_DATE_TIME_FORMATTER); + return !localWhInDateTime.isAfter(LocalDateTime.now()); + } catch (DateTimeParseException e) { + log.info("[AciPodBatch] 스킵 - DATE_LOCALWHIN 파싱 실패 - DATE_LOCALWHIN={}", dateLocalwhin); + return false; + } + } + private String getText(JsonNode jsonNode, String key) { JsonNode valueNode = jsonNode.get(key); if (valueNode == null || valueNode.isNull()) {