From 9145f8a44c6ae733019e43c775cc30243032e502 Mon Sep 17 00:00:00 2001
From: zwl <1051256694@qq.com>
Date: 星期三, 29 四月 2026 16:16:43 +0800
Subject: [PATCH] 拍照触发修改
---
src/main/java/com/zy/asrs/service/impl/OpenServiceImpl.java | 1494 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 1,420 insertions(+), 74 deletions(-)
diff --git a/src/main/java/com/zy/asrs/service/impl/OpenServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/OpenServiceImpl.java
index 97badcc..92a24f6 100644
--- a/src/main/java/com/zy/asrs/service/impl/OpenServiceImpl.java
+++ b/src/main/java/com/zy/asrs/service/impl/OpenServiceImpl.java
@@ -14,11 +14,14 @@
import com.zy.asrs.mapper.TagMapper;
import com.zy.asrs.service.*;
import com.zy.asrs.task.core.ReturnT;
+import com.zy.asrs.task.support.OutboundBatchSeqReleaseGuard;
+import com.zy.asrs.task.support.WorkPublishLockKeys;
import com.zy.asrs.utils.MatUtils;
import com.zy.asrs.utils.OrderInAndOutUtil;
import com.zy.asrs.utils.Utils;
import com.zy.common.constant.AgvConstant;
import com.zy.common.constant.ArmConstant;
+import com.zy.common.entity.Parameter;
import com.zy.common.model.DetlDto;
import com.zy.common.model.LocDetlDto;
import com.zy.common.model.LocDto;
@@ -27,13 +30,15 @@
import com.zy.common.service.CommonService;
import com.zy.common.utils.HttpHandler;
import com.zy.common.utils.NodeUtils;
+import com.zy.common.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
-import javax.rmi.CORBA.Util;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@@ -44,10 +49,29 @@
@Service
public class OpenServiceImpl implements OpenService {
+ private static final Map<Integer, BigDecimal> INBOUND_WEIGHT_FACTOR_BY_SOURCE_STA;
+ private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+ private static final int DEFAULT_OUT_ORDER_BATCH_PRIORITY = 100;
+ private static final int DEFAULT_OUT_ORDER_BATCH_PRIORITY_THRESHOLD = 1;
+ // ERP 鍑哄簱鍙eぇ浜庤闃堝�兼椂锛�/outOrder 鍙惤鍑哄簱璁㈠崟锛岀敱瀹氭椂鍣ㄥ悗缁敓鎴愪换鍔°��
+ private static final int PENDING_OUT_ORDER_STATION_THRESHOLD = 600;
+ // 寤惰繜鍑哄簱璁㈠崟浣跨敤鐙珛鍗曟嵁绫诲瀷锛屼究浜庡拰浜哄伐/椤甸潰鍒涘缓鐨勫嚭搴撳崟鍖哄垎鏉ユ簮銆�
+ private static final String OUT_ORDER_PENDING_DOC_TYPE = "鎺ュ彛鍑哄簱鍗�";
+
+ static {
+ Map<Integer, BigDecimal> factorMap = new HashMap<>();
+ factorMap.put(112, new BigDecimal("0.98"));
+ INBOUND_WEIGHT_FACTOR_BY_SOURCE_STA = Collections.unmodifiableMap(factorMap);
+ }
+
@Autowired
private OrderService orderService;
@Autowired
private OrderDetlService orderDetlService;
+ @Autowired
+ private OrderPakoutService orderPakoutService;
+ @Autowired
+ private OrderDetlPakoutService orderDetlPakoutService;
@Autowired
private SnowflakeIdWorker snowflakeIdWorker;
@Autowired
@@ -88,16 +112,36 @@
private String mesUrl;
@Value("${mes.stationaddress}")
private String stationAddress;
+ @Value("${erp.address.URL:}")
+ private String erpUrl;
+ @Value("${erp.switch.ErpReportOld}")
+ private boolean erpReportOld;
+ @Value("${erp.address.Inaddress:}")
+ private String erpInAddress;
+ @Value("${erp.address.OutErroraddress:}")
+ private String erpOutErrorAddress;
@Autowired
private WaitPakinService waitPakinService;
@Autowired
+ private WaitPakinLogService waitPakinLogService;
+ @Autowired
private WrkMastService wrkMastService;
+ @Autowired
+ private WrkMastLogService wrkMastLogService;
+ @Autowired
+ private WrkDetlLogService wrkDetlLogService;
@Autowired
private WcsApiService wcsApiService;
@Autowired
private WorkService workService;
@Autowired
+ private RedisUtil redisUtil;
+ @Autowired
private BasCrnpService basCrnpService;
+ @Autowired
+ private ApiLogService apiLogService;
+ @Autowired
+ private OutboundBatchSeqReleaseGuard outboundBatchSeqReleaseGuard;
@Override
@Transactional
@@ -375,76 +419,154 @@
@Transactional
public R pakoutOrderPause(OpenOrderPakoutPauseParam param) {
if (param == null || Cools.isEmpty(param.getOrderId())) {
- throw new CoolException("orderNo is empty");
+ throw new CoolException("orderNo涓嶈兘涓虹┖");
}
- Order order = orderService.selectByNo(param.getOrderId());
- if (order == null) {
- order = OrderInAndOutUtil.selectByNo(Boolean.FALSE, param.getOrderId());
+ if (param.getExecute() == null) {
+ throw new CoolException("execute涓嶈兘涓虹┖");
}
- if (order == null) {
- throw new CoolException("order not found: " + param.getOrderId());
+ // 涓鏃跺厛閬垮紑姝e湪涓嬪彂缁� WCS 鐨勭獥鍙o紝闃叉鏈湴鎶婅鍗曠疆鍋滃悗锛�
+ // WCS 渚т粛鏀跺埌鍚屼竴鎵逛换鍔★紝閫犳垚璁㈠崟鐘舵�佸拰璁惧鎵ц鐘舵�佸垎鍙夈��
+ if (Objects.equals(param.getExecute(), 2)
+ && redisUtil.hasKey(WorkPublishLockKeys.outboundUserNoLock(param.getOrderId()))) {
+ return R.error("姝e湪涓嬪彂浠诲姟缁橶CS锛屾棤娉曚腑姝�");
}
+ OrderPakout orderPakout = orderPakoutService.selectByNo(param.getOrderId());
List<WrkMast> activeTasks = findActiveOutboundTasks(param.getOrderId());
- if (activeTasks.isEmpty()) {
- return R.ok("no active out tasks");
+ if (Objects.equals(param.getExecute(), 1)) {
+ // execute=1 鍚屾椂澶勭悊涓ょ被瀵硅薄锛�
+ // 1. 鏈敓鎴愪换鍔$殑鍑哄簱璁㈠崟锛氭仮澶� order.status=1锛岃瀹氭椂鍣ㄥ彲浠ョ户缁壂鎻忋��
+ // 2. 宸茬敓鎴愪絾寰呬笅鍙戠殑浠诲姟锛氳缃� pdcType=Y锛屽厑璁� WorkMastScheduler 涓嬪彂缁� WCS銆�
+ Map<String, Object> result = new HashMap<>();
+ result.put("orderNo", param.getOrderId());
+ result.put("execute", param.getExecute());
+ boolean orderStatusUpdated = false;
+ if (orderPakout != null && !Objects.equals(orderPakout.getStatus(), 1)) {
+ orderPakout.setStatus(1);
+ orderPakout.setUpdateBy(9527L);
+ orderPakout.setUpdateTime(new Date());
+ if (!orderPakoutService.updateById(orderPakout)) {
+ throw new CoolException("鍚姩鍑哄簱璁㈠崟澶辫触锛�" + param.getOrderId());
+ }
+ orderStatusUpdated = true;
+ }
+ int confirmedCount = confirmPendingOutboundTasks(activeTasks);
+ R generateResult = null;
+ int generatedConfirmedCount = 0;
+ if (orderPakout != null) {
+ // 鍚姩鍚庣珛鍗冲皾璇曠敓鎴愬綋鍓嶅彲鏀捐鐨勮繘浠撶紪鍙锋壒娆★紝閬垮厤蹇呴』绛夊緟涓嬩竴杞畾鏃舵壂鎻忋��
+ generateResult = generatePendingPakoutOrderTasks(param.getOrderId());
+ // 鍒氱敓鎴愮殑浠诲姟鍒濆鐘舵�佷粛鏄� 11锛岃繖閲屽啀娆$‘璁わ紝淇濇寔鈥滃惎鍔ㄦ帴鍙h皟鐢ㄥ悗鍗冲彲涓嬪彂鈥濈殑璇箟銆�
+ generatedConfirmedCount = confirmPendingOutboundTasks(findActiveOutboundTasks(param.getOrderId()));
+ }
+ result.put("orderStatusUpdated", orderStatusUpdated);
+ result.put("confirmedCount", confirmedCount + generatedConfirmedCount);
+ result.put("generatedConfirmedCount", generatedConfirmedCount);
+ result.put("generateResult", generateResult);
+ return R.ok("鍑哄簱璁㈠崟鍚姩鎴愬姛").add(result);
}
+ if (Objects.equals(param.getExecute(), 2)) {
+ // execute=2 鍏堝叧闂鍗曞紑鍏筹紝闃绘瀹氭椂鍣ㄧ户缁负鏈敓鎴愪换鍔$殑鏄庣粏寤� WrkMast銆�
+ // 宸茬粡鐢熸垚鐨勪换鍔℃寜鐘舵�佸垎娴侊細11 灏氭湭涓嬪彂锛岃蛋鏈湴鍙栨秷锛�12/13 宸蹭笅鍙戞垨鎵ц涓紝闇�瑕侀�氱煡 WCS 鍙栨秷銆�
+ Map<String, Object> result = new HashMap<>();
+ result.put("orderNo", param.getOrderId());
+ result.put("execute", param.getExecute());
+ result.put("taskCount", activeTasks.size());
+ boolean orderStatusUpdated = false;
+ if (orderPakout != null && !Objects.equals(orderPakout.getStatus(), 0)) {
+ orderPakout.setStatus(0);
+ orderPakout.setUpdateBy(9527L);
+ orderPakout.setUpdateTime(new Date());
+ if (!orderPakoutService.updateById(orderPakout)) {
+ throw new CoolException("涓鍑哄簱璁㈠崟澶辫触锛�" + param.getOrderId());
+ }
+ orderStatusUpdated = true;
+ }
+ result.put("orderStatusUpdated", orderStatusUpdated);
+ if (activeTasks.isEmpty()) {
+ result.put("cancelledLocalTaskCount", 0);
+ result.put("pausedWcsTaskCount", 0);
+ return R.ok("鍑哄簱璁㈠崟宸蹭腑姝�").add(result);
+ }
+ List<HashMap<String,Object>> taskList = new ArrayList<>();
+ List<WrkMast> wcsCancelTasks = new ArrayList<>();
+ int cancelledLocalTaskCount = 0;
+ for (WrkMast wrkMast : activeTasks) {
+ HashMap<String,Object> hashMap = new HashMap<>();
+ hashMap.put("taskNo", wrkMast.getWrkNo());
+ if (!Cools.isEmpty(wrkMast) && Objects.equals(wrkMast.getWrkSts(), 11L)) {
+ // wrk_sts=11 杩樻病鍙戝埌 WCS锛屾湰鍦板彇娑堝嵆鍙紝涓嶉渶瑕佷骇鐢� WCS 鏆傚仠鎸囦护銆�
+ workService.cancelWrkMast(wrkMast.getWrkNo()+"", 9955L);
+ cancelledLocalTaskCount++;
+ continue;
+ }
+ taskList.add(hashMap);
+ wcsCancelTasks.add(wrkMast);
+ }
+ int cancelledWcsTaskCount = 0;
+ if (!taskList.isEmpty()) {
+ // wrk_sts=12/13 绛夊凡杩涘叆 WCS 渚х殑浠诲姟蹇呴』鏍¢獙 WCS 杩斿洖锛屽け璐ュ垯浜嬪姟鍥炴粴锛岄伩鍏嶆湰鍦拌鎶ュ凡鍙栨秷銆�
+ R wcsR = wcsApiService.pauseOutTasks(taskList);
+ requireWcsPauseOk(wcsR);
+ // WCS 宸茬‘璁ゅ彇娑堝悗锛屾湰鍦颁篃瑕佸彇娑堜换鍔″苟鍥炴粴璁㈠崟鏄庣粏 work_qty銆�
+ // 鍥炴粴閫昏緫鍦� WorkService.cancelWrkMast 涓粺涓�澶勭悊锛岀‘淇� WCS 鍥炶皟 task_cancel 璧板悓涓�濂楀彛寰勩��
+ for (WrkMast wrkMast : wcsCancelTasks) {
+ workService.cancelWrkMast(wrkMast.getWrkNo()+"", 9955L);
+ cancelledWcsTaskCount++;
+ }
+ }
+ result.put("cancelledLocalTaskCount", cancelledLocalTaskCount);
+ result.put("pausedWcsTaskCount", taskList.size());
+ result.put("cancelledWcsTaskCount", cancelledWcsTaskCount);
+ return R.ok("鍑哄簱璁㈠崟宸蹭腑姝�").add(result);
+ }
+ throw new CoolException("reason浠呮敮鎸�1鎴�2");
+ }
+ /**
+ * 灏嗗凡鐢熸垚浣嗚繕鏈厑璁镐笅鍙戠殑鍑哄簱浠诲姟缃负鍙笅鍙戙��
+ *
+ * pdcType 鏄幇鏈� WorkMastScheduler 鐨勪笅鍙戝紑鍏筹細
+ * - wrk_sts=11 涓� pdcType=Y 鏃讹紝璋冨害鍣ㄥ彲浠ョ户缁笅鍙戠粰 WCS銆�
+ * - 宸茬粡鏄� Y 鐨勪换鍔′繚鎸佸箓绛夛紝涓嶉噸澶嶆洿鏂般��
+ */
+ private int confirmPendingOutboundTasks(List<WrkMast> activeTasks) {
+ if (Cools.isEmpty(activeTasks)) {
+ return 0;
+ }
Date now = new Date();
- int pausedCount = 0;
- List<WrkMast> issuedTasks = new ArrayList<>();
+ int confirmedCount = 0;
for (WrkMast wrkMast : activeTasks) {
- if (wrkMast == null || "Y".equalsIgnoreCase(wrkMast.getPauseMk())) {
+ if (wrkMast == null || !Objects.equals(wrkMast.getWrkSts(), 11L) || "Y".equalsIgnoreCase(wrkMast.getPdcType())) {
continue;
}
- wrkMast.setPauseMk("Y");
- wrkMast.setUpdMk(needNotifyWcsStop(wrkMast) ? "WCS_STOP_REQUESTED" : "WMS_PAUSED");
- wrkMast.setManuType("ERP_PAUSE");
+ wrkMast.setPdcType("Y");
wrkMast.setModiTime(now);
wrkMast.setModiUser(9527L);
if (!wrkMastService.updateById(wrkMast)) {
- throw new CoolException("pause out task failed: " + wrkMast.getWrkNo());
+ throw new CoolException("纭鎵ц鍑哄簱浠诲姟澶辫触: " + wrkMast.getWrkNo());
}
- pausedCount++;
- if (needNotifyWcsStop(wrkMast)) {
- issuedTasks.add(wrkMast);
- }
+ confirmedCount++;
}
+ return confirmedCount;
+ }
- if (pausedCount == 0) {
- return R.ok("tasks already paused");
+ /** WCS 杩斿洖闈炴垚鍔熺爜鏃舵姏閿� */
+ private void requireWcsPauseOk(R wcsR) {
+ if (wcsR == null) {
+ throw new CoolException("WCS鍙栨秷鍑哄簱浠诲姟鏃犺繑鍥�");
}
-
- if (!issuedTasks.isEmpty()) {
- wcsApiService.pauseOutTasks(buildStopOutTaskParams(param, issuedTasks));
+ Object codeObj = wcsR.get("code");
+ int code = codeObj instanceof Number ? ((Number) codeObj).intValue() : -1;
+ if (code != 200) {
+ Object msgObj = wcsR.get("msg");
+ throw new CoolException(msgObj == null ? "WCS鍙栨秷鍑哄簱浠诲姟澶辫触" : String.valueOf(msgObj));
}
-
- Map<String, Object> result = new HashMap<>();
- result.put("orderNo", param.getOrderId());
- result.put("pausedCount", pausedCount);
- result.put("wcsStopCount", issuedTasks.size());
- return R.ok("pause out success").add(result);
}
@Override
- @Transactional
public R pakoutOrderExecute(OpenOrderPakoutExecuteParam param) {
- if (param == null || Cools.isEmpty(param.getOrderId())) {
- throw new CoolException("orderId is empty");
- }
- if (param.getExecute() == null) {
- throw new CoolException("execute is empty");
- }
- if (Objects.equals(param.getExecute(), 1)) {
- return createPakoutTasks(param.getOrderId());
- }
- if (Objects.equals(param.getExecute(), 2)) {
- OpenOrderPakoutPauseParam pauseParam = new OpenOrderPakoutPauseParam();
-// pauseParam.getOrderId(param.getOrderId());
-// pauseParam.setReason("OPEN_API_PAUSE");
- return pakoutOrderPause(pauseParam);
- }
- throw new CoolException("execute only supports 1 or 2");
+ return null;
}
private List<WrkMast> findActiveOutboundTasks(String orderNo) {
@@ -461,8 +583,8 @@
}
List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
.in("wrk_no", wrkNos)
- .in("io_type", Arrays.asList(101, 103, 107, 108, 110))
- .lt("wrk_sts", 14L));
+ .in("io_type", Arrays.asList(101, 103, 104, 107, 108, 110))
+ .in("wrk_sts", Arrays.asList(11L, 12L, 13L)));
if (wrkMasts == null || wrkMasts.isEmpty()) {
return Collections.emptyList();
}
@@ -573,24 +695,12 @@
return orderDetl.getMatnr() + "|batch=" + (orderDetl.getBatch() == null ? "" : orderDetl.getBatch()) + "|lack=" + lackQty;
}
- private boolean needNotifyWcsStop(WrkMast wrkMast) {
- return wrkMast != null
- && wrkMast.getWrkSts() != null
- && wrkMast.getWrkSts() >= 12L
- && wrkMast.getWrkSts() < 14L;
- }
-
- private StopOutTaskParams buildStopOutTaskParams(OpenOrderPakoutPauseParam param, List<WrkMast> wrkMasts) {
+ private StopOutTaskParams buildStopOutTaskParams(List<WrkMast> wrkMasts) {
StopOutTaskParams stopParams = new StopOutTaskParams();
- stopParams.setOrderNo(param.getOrderId());
- stopParams.setReason(param.getReason());
+ // WCS鍙栨秷鎺ュ彛浠呮帴鏀� taskList.taskNo銆�
for (WrkMast wrkMast : wrkMasts) {
StopOutTaskParams.TaskItem item = new StopOutTaskParams.TaskItem();
item.setTaskNo(String.valueOf(wrkMast.getWrkNo()));
- if (wrkMast.getStaNo() != null) {
- item.setStaNo(String.valueOf(wrkMast.getStaNo()));
- }
- item.setLocNo(wrkMast.getSourceLocNo());
stopParams.getTasks().add(item);
}
return stopParams;
@@ -655,6 +765,117 @@
@Transactional
public List<StockVo> queryStock() {
return locDetlService.queryStockTotal();
+ }
+
+ @Override
+ public R reportPakinHistoryToErp(List<String> barcodes) {
+ List<String> normalizedBarcodes = normalizeBarcodes(barcodes);
+ if (normalizedBarcodes.isEmpty()) {
+ return R.error("鎵樼洏鐮侀泦鍚堜笉鑳戒负绌�");
+ }
+ if (!isErpReportEnabled()) {
+ return R.error("ERP reporting is disabled");
+ }
+ if (Cools.isEmpty(erpInAddress)) {
+ return R.error("ERP鍏ュ簱涓婃姤鍦板潃鏈厤缃�");
+ }
+
+ Map<String, WrkMastLog> latestInboundLogMap = loadLatestInboundHistoryLogMap(normalizedBarcodes);
+ Map<Integer, List<WrkDetlLog>> wrkDetlLogMap = loadWrkDetlLogMap(latestInboundLogMap.values());
+ Map<String, WaitPakinLog> waitPakinLogMap = loadWaitPakinLogMap(normalizedBarcodes);
+ String requestUrl = buildErpInboundRequestUrl();
+
+ List<Map<String, Object>> rows = new ArrayList<>();
+ int successCount = 0;
+ int failCount = 0;
+
+ for (String barcode : normalizedBarcodes) {
+ Map<String, Object> row = new LinkedHashMap<>();
+ row.put("barcode", barcode);
+
+ WrkMastLog wrkMastLog = latestInboundLogMap.get(barcode);
+ if (wrkMastLog == null) {
+ row.put("success", false);
+ row.put("message", "鏈壘鍒版渶鏂板叆搴撳巻鍙茶褰�");
+ rows.add(row);
+ failCount++;
+ continue;
+ }
+
+ WaitPakinLog waitPakinLog = waitPakinLogMap.get(barcode);
+ List<WrkDetlLog> wrkDetlLogs = wrkDetlLogMap.getOrDefault(wrkMastLog.getWrkNo(), Collections.emptyList());
+ ErpPakinReportParam param = buildInboundErpParam(barcode, wrkMastLog, wrkDetlLogs, waitPakinLog);
+ if (Cools.isEmpty(param.getPalletId())) {
+ row.put("success", false);
+ row.put("message", "鎵樼洏鐮佺己灏戜笂鎶ュ瓧娈礫palletId]");
+ rows.add(row);
+ failCount++;
+ continue;
+ }
+ if (Cools.isEmpty(param.getLocId())) {
+ row.put("success", false);
+ row.put("message", "鎵樼洏鐮佺己灏戜笂鎶ュ瓧娈礫locId]");
+ rows.add(row);
+ failCount++;
+ continue;
+ }
+
+ String request = JSON.toJSONString(param);
+ String response = "";
+ boolean success = false;
+ String errorMsg = null;
+ try {
+ response = new HttpHandler.Builder()
+ .setUri(erpUrl)
+ .setPath(erpInAddress)
+ .setJson(request)
+ .build()
+ .doPost();
+ success = isErpCallSuccess(response);
+ if (!success) {
+ errorMsg = extractErpCallError(response);
+ }
+ } catch (Exception e) {
+ errorMsg = e.getMessage();
+ } finally {
+ try {
+ apiLogService.save(
+ "Inbound ERP Report",
+ requestUrl,
+ null,
+ "127.0.0.1",
+ request,
+ response,
+ success,
+ "barcode=" + barcode + ",workNo=" + wrkMastLog.getWrkNo()
+ );
+ } catch (Exception logEx) {
+ log.error("save inbound erp api log failed", logEx);
+ }
+ }
+
+ row.put("workNo", wrkMastLog.getWrkNo());
+ Integer sourceStaNo = resolveInboundSourceStaNo(wrkMastLog);
+ row.put("sourceStaNo", sourceStaNo);
+ row.put("weightFactor", resolveInboundWeightFactor(sourceStaNo));
+ row.put("erpWeight", param.getWeight());
+ row.put("success", success);
+ row.put("message", success ? "OK" : errorMsg);
+ rows.add(row);
+
+ if (success) {
+ successCount++;
+ } else {
+ failCount++;
+ }
+ }
+
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("total", normalizedBarcodes.size());
+ result.put("successCount", successCount);
+ result.put("failCount", failCount);
+ result.put("rows", rows);
+ return R.ok().add(result);
}
@Override
@@ -1239,7 +1460,10 @@
stationParams.add(stationParam);
}
}
+ String requestJson = JSON.toJSONString(stationParams);
String response = "";
+ boolean pushOk = false;
+ String pushUrl = buildMesStationRequestUrl();
try {
//鑾峰彇Cookie鍊�
HashMap<String, Object> headers = new HashMap<>();
@@ -1249,21 +1473,55 @@
.setHeaders(headers)
.setUri(mesUrl)
.setPath(stationAddress)
- .setJson(JSON.toJSONString(stationParams))
+ .setJson(requestJson)
.build()
.doPost();
JSONObject jsonResponse = JSON.parseObject(response);
- if (jsonResponse.getInteger("code") == 200) {
-
+ if (jsonResponse != null && Integer.valueOf(200).equals(jsonResponse.getInteger("code"))) {
+ pushOk = true;
} else {
return R.error();
}
} catch (Exception e) {
e.printStackTrace();
+ } finally {
+ try {
+ apiLogService.save(
+ "鎺‥RP-绔欑偣鍚屾",
+ pushUrl,
+ null,
+ "127.0.0.1",
+ requestJson,
+ response,
+ pushOk,
+ "绔欑偣鍚屾鎺ㄥ鏂�"
+ );
+ } catch (Exception logEx) {
+ log.error("save station sync api log failed", logEx);
+ }
}
return R.ok();
}
+ private String buildMesStationRequestUrl() {
+ if (Cools.isEmpty(mesUrl)) {
+ return stationAddress;
+ }
+ if (stationAddress == null) {
+ return mesUrl;
+ }
+ if (mesUrl.endsWith("/") && stationAddress.startsWith("/")) {
+ return mesUrl + stationAddress.substring(1);
+ }
+ if (!mesUrl.endsWith("/") && !stationAddress.startsWith("/")) {
+ return mesUrl + "/" + stationAddress;
+ }
+ return mesUrl + stationAddress;
+ }
+
+ /**
+ * 7.3 缁勬墭淇℃伅涓嬪彂銆�
+ */
@Override
public R mesToComb(MesToCombParam param) {
if (Cools.isEmpty(param.getPalletId())) {
@@ -1276,7 +1534,12 @@
if (param.getFull() == 1) {
//婊℃墭鐩�
- mat = matService.selectByMatnr(param.getMatnr());
+ if(param.getBoxType1().equals("aws")){
+ mat = matService.selectByMatnr("amazon");
+ }else {
+ mat = matService.selectByMatnr("cloudWarehouse");
+ }
+
} else if (param.getFull() == 0) {
//绌烘墭鐩�
mat = matService.selectByMatnr("emptyPallet");
@@ -1285,36 +1548,76 @@
WaitPakin waitPakin = new WaitPakin();
waitPakin.sync(mat);
+// waitPakin.setMatnr(param.getMatnr());
waitPakin.setBatch(String.valueOf(param.getBatchId()));
waitPakin.setZpallet(param.getPalletId()); // 鎵樼洏鐮�
waitPakin.setIoStatus("N"); // 鍏ュ嚭鐘舵��
waitPakin.setAnfme(param.getAnfme()); // 鏁伴噺
+ waitPakin.setFreqType(param.getFreqType());
+ waitPakin.setContainerNo(param.getContainerNo());
+ waitPakin.setTeu(param.getTeu());
+ waitPakin.setPlateNo(param.getPlateNo());
+ waitPakin.setTrainNo(param.getTrainNo());
+ waitPakin.setCubeNumber(param.getCubeNumber());
waitPakin.setStatus("Y"); // 鐘舵��
waitPakin.setAppeUser(9995L);
waitPakin.setAppeTime(now);
waitPakin.setModiUser(9995L);
waitPakin.setModiTime(now);
- waitPakin.setOrderNo(String.valueOf(param.getOrderId()));
+ waitPakin.setOrderNo(String.valueOf(param.getBizNo()));
waitPakin.setOrigin(String.valueOf(param.getStorageArea()));//寤鸿鍏ュ簱鍖哄煙
waitPakin.setManu(String.valueOf(param.getLocId()));//mes鍏蜂綋搴撲綅缂栧彿
waitPakin.setThreeCode(param.getBizNo());
+ // 7.3 鏂板瀛楁澶嶇敤鐜版湁缁勬墭妗f壙杞戒綅锛屼笉鏂板鍒椼��
+ waitPakin.setSuppCode(param.getCustomerId());
+ waitPakin.setSupp(param.getCustomerName());
+ waitPakin.setStandby3(param.getItem());
+ waitPakin.setStandby1(param.getEntryWmsCode());
+ waitPakin.setStandby2(param.getOutDoorNo());
waitPakin.setBeBatch(param.getPackage1());//鏄惁鏁h揣锛�0 闈炴暎璐э紱1 鏁h揣锛涗负浜嗙鎺у嚭璐ч�熺巼锛屾暎璐у彲浠ュ嚭鎱㈢偣銆�
+ // ERP 鍏ュ彛榛樿鎵� erp锛孧QTT 缁勬墭浼氬湪鍙傛暟閲屾樉寮忎紶 aws銆�
+ waitPakin.setBoxType1(Cools.isEmpty(param.getBoxType1()) ? "erp" : param.getBoxType1());
if (!waitPakinService.insert(waitPakin)) {
throw new CoolException("淇濆瓨鍏ュ簱閫氱煡妗eけ璐�");
}
- return null;
+ return R.ok().add(Cools.add("palletId", param.getPalletId()).add("orderId", param.getOrderId()));
}
+ /**
+ * 7.11 鍑哄簱閫氱煡鍗曪紙浼犻�掓湁搴忔棤搴忚鍒欙級鍗曟潯寤哄崟銆�
+ */
@Override
- public R outOrder(OutTaskParam param) {
+ public R outOrder(OutTaskParam param,int count,int i) {
+ return outOrder(param, count, 0 ,i);
+ }
+
+ private R outOrder(OutTaskParam param, int count, int teu , int i) {
LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_sts", "F").eq("barcode", param.getPalletId()));
if (locMast == null) {
- return R.error("娌℃湁鎵惧埌鎵樼洏鐮�=" + param.getPalletId() + "瀵瑰簲鐨勫簱浣�");
+ throw new CoolException("娌℃湁鎵惧埌鎵樼洏鐮�=" + param.getPalletId() + "瀵瑰簲鐨勫簱浣�");
+ }
+ if (Cools.isEmpty(param.getStationId())) {
+ throw new CoolException("鍑哄簱鍙g紪鐮佷笉鑳戒负绌�");
+ }
+ if (Cools.isEmpty(param.getBatchSeq())) {
+ throw new CoolException("鎵规鏍囪瘑涓嶈兘涓虹┖");
+ }
+ if (param.getSeq() == null || param.getSeq() < 0) {
+ throw new CoolException("鍑哄簱椤哄簭涓嶈兘涓虹┖涓斾笉鑳藉皬浜�0");
}
Integer ioType = 101;
// 鑾峰彇璺緞
- StaDesc staDesc = staDescService.queryCrnStn(ioType, locMast.getCrnNo(), Integer.valueOf(param.getStationId()));
+ Integer stationId;
+ try {
+ stationId = Integer.valueOf(param.getStationId());
+ } catch (NumberFormatException ex) {
+ throw new CoolException("鍑哄簱鍙g紪鐮佹牸寮忛敊璇細" + param.getStationId());
+ }
+ StaDesc staDesc = staDescService.queryCrnStn(ioType, locMast.getCrnNo(), stationId);
+ if (staDesc == null) {
+ throw new CoolException("鏈壘鍒板嚭搴撳彛=" + param.getStationId() + "瀵瑰簲璺緞");
+ }
Date now = new Date();
// 鐢熸垚宸ヤ綔鍙�
int workNo = commonService.getWorkNo(WorkNoType.getWorkNoType(ioType));
@@ -1324,7 +1627,7 @@
wrkMast.setIoTime(now);
wrkMast.setWrkSts(11L); // 宸ヤ綔鐘舵�侊細11.鐢熸垚鍑哄簱ID
wrkMast.setIoType(ioType); // 鍏ュ嚭搴撶姸鎬�
- wrkMast.setIoPri(13D); // 浼樺厛绾э細13
+ wrkMast.setIoPri(Double.valueOf(i)); // 浼樺厛绾�
wrkMast.setCrnNo(locMast.getCrnNo());
wrkMast.setSourceStaNo(staDesc.getCrnStn()); // 婧愮珯
wrkMast.setStaNo(staDesc.getStnNo()); // 鐩爣绔�
@@ -1335,7 +1638,16 @@
wrkMast.setExitMk("N"); // 閫�鍑�
wrkMast.setEmptyMk("N"); // 绌烘澘
wrkMast.setLinkMis("N");
+ wrkMast.setContainerNo(param.getContainerNo());
+ wrkMast.setTeu(teu);
+ wrkMast.setPdcType(locMast.getCrnNo()>=19?"Y":"N");//鑷姩浠诲姟涓嬪彂鏍囪
+ wrkMast.setPlateNo(param.getPlateNo());
+ wrkMast.setTrainNo(param.getTrainNo());
+ wrkMast.setFreqType(param.getFreqType());
+ wrkMast.setCubeNumber(param.getCubeNumber());
+ // 7.11锛歰rderId 瀛� userNo锛宐atchSeq 瀛樻壒娆℃爣璇嗭紝seq 瀛樻壒娆″唴椤哄簭銆�
wrkMast.setUserNo(param.getOrderId());//璁㈠崟鍙�
+ wrkMast.setBatchSeq(param.getBatchSeq());//璁㈠崟鍐呮壒娆℃爣璇�
wrkMast.setPltType(param.getSeq());//鍑哄簱椤哄簭锛屼粠1寮�濮�
wrkMast.setTakeNone("0"); //0闈炶嚜鍔�
wrkMast.setAppeUser(9995L); // 鎿嶄綔浜哄憳鏁版嵁
@@ -1362,6 +1674,17 @@
wrkDetl.setAppeUser(9995L);
wrkDetl.setModiTime(now);
wrkDetl.setModiUser(9995L);
+ wrkDetl.setTeu(teu);
+ wrkDetl.setContainerNo(param.getContainerNo());
+ wrkDetl.setPlateNo(param.getPlateNo());
+ wrkDetl.setTrainNo(param.getTrainNo());
+ wrkDetl.setFreqType(param.getFreqType());
+ wrkDetl.setCubeNumber(param.getCubeNumber());
+ // 7.11锛歟ntryWmsCode銆乷utDoorNo 澶嶇敤鏄庣粏澶囩敤瀛楁銆�
+ wrkDetl.setStandby1(param.getEntryWmsCode());
+ wrkDetl.setStandby2(param.getOutDoorNo());
+ wrkDetl.setSupp(count+"");
+ wrkDetl.setTeu(param.getTeu());
if (!wrkDetlService.insert(wrkDetl)) {
throw new CoolException("淇濆瓨宸ヤ綔妗f槑缁嗗け璐�");
@@ -1380,7 +1703,1030 @@
log.error(locMast.getLocNo() + "搴撲綅涓嶆槸鍦ㄥ簱鐘舵��");
throw new CoolException(locMast.getLocNo() + "搴撲綅涓嶆槸鍦ㄥ簱鐘舵��");
}
+ return R.ok().add(Cools.add("wrkNo", workNo).add("orderId", param.getOrderId()));
+ }
+
+ /**
+ * 7.11 鍑哄簱閫氱煡鍗曪紙浼犻�掓湁搴忔棤搴忚鍒欙級鎵归噺寤哄崟銆�
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public R outOrderBatch(Map<String, List<OutTaskParam>> linesByBatchSeq,int count) {
+
+ for (Map.Entry<String, List<OutTaskParam>> entry : linesByBatchSeq.entrySet()) {
+ int i = DEFAULT_OUT_ORDER_BATCH_PRIORITY;
+ int j = 0;
+ int priorityThreshold = getOutOrderBatchPriorityThreshold();
+ for (OutTaskParam outTaskParam : entry.getValue()) {
+ int teu = Cools.isEmpty(outTaskParam.getTeu())?0:outTaskParam.getTeu();
+ R r = outOrder(outTaskParam, count, teu ,i);
+ if (!Objects.equals(r.get("code"), 200)) {
+ throw new CoolException("鍑哄簱寤哄崟澶辫触");
+ }
+ j++;
+ if (j >= priorityThreshold) {
+ i--;
+ j = 0;
+ }
+ }
+
+ }
return R.ok();
}
+
+ private int getOutOrderBatchPriorityThreshold() {
+ Parameter parameter = Parameter.get();
+ if (parameter == null || Cools.isEmpty(parameter.getOutOrderBatchPriorityThreshold())) {
+ return DEFAULT_OUT_ORDER_BATCH_PRIORITY_THRESHOLD;
+ }
+ try {
+ int threshold = Integer.parseInt(parameter.getOutOrderBatchPriorityThreshold().trim());
+ return threshold <= 0 ? DEFAULT_OUT_ORDER_BATCH_PRIORITY_THRESHOLD : threshold;
+ } catch (NumberFormatException ignored) {
+ return DEFAULT_OUT_ORDER_BATCH_PRIORITY_THRESHOLD;
+ }
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public R outOrderCreatePakoutOrder(List<OutTaskParam> params) {
+ if (Cools.isEmpty(params)) {
+ return R.ok();
+ }
+
+ // 涓�涓� /outOrder 璇锋眰鍙兘鍖呭惈澶氫釜 orderId銆傛寜璁㈠崟鍙峰垎缁勫悗鍒嗗埆鍒涘缓璁㈠崟澶达紝
+ // 淇濊瘉 orderId 濮嬬粓瀵瑰簲 man_order_pakout.order_no锛屾槑缁嗘寕鍦ㄥ搴旇鍗曚笅銆�
+ Map<String, List<OutTaskParam>> paramsByOrderNo = new LinkedHashMap<>();
+ for (OutTaskParam param : params) {
+ validatePendingOutOrderParam(param);
+ paramsByOrderNo.computeIfAbsent(param.getOrderId(), key -> new ArrayList<>()).add(param);
+ }
+
+ Date now = new Date();
+ int orderCount = 0;
+ int detailCount = 0;
+ int removedUndispatchedDetailCount = 0;
+ List<String> orderNos = new ArrayList<>();
+ for (Map.Entry<String, List<OutTaskParam>> entry : paramsByOrderNo.entrySet()) {
+ String orderNo = entry.getKey();
+ // 寤惰繜寤哄崟鍏佽鍚屼竴涓� orderNo 鍐嶆涓嬪彂锛�
+ // 宸蹭笅鍙�/宸插畬鎴愭槑缁嗕繚鐣欒拷婧紱鏈笅鍙戞槑缁嗗垹闄ゅ悗锛屼娇鐢ㄦ湰娆℃帴鍙e弬鏁伴噸鏂版彃鍏ャ��
+ assertPendingPakoutOrderCanReplace(orderNo);
+
+ OrderPakout order = orderPakoutService.selectByNo(orderNo);
+ if (order == null) {
+ order = createPendingPakoutOrderHeader(orderNo, now);
+ } else {
+ assertNoNonReplaceablePendingDetailConflict(order, entry.getValue());
+ removedUndispatchedDetailCount += removeUndispatchedPendingDetails(order.getId());
+ refreshPendingPakoutOrderForResubmit(order, now);
+ }
+
+ for (OutTaskParam param : entry.getValue()) {
+ // 鏄庣粏瀹屾暣淇濆瓨鎺ュ彛瀛楁锛屽悗缁畾鏃跺櫒鍙互鏃犳崯杩樺師 OutTaskParam 鍐嶅鐢� outOrderBatch銆�
+ OrderDetlPakout detail = buildPendingPakoutOrderDetl(order, param, now);
+ if (!orderDetlPakoutService.insert(detail)) {
+ throw new CoolException("鐢熸垚鍑哄簱璁㈠崟鏄庣粏澶辫触锛�" + orderNo);
+ }
+ detailCount++;
+ }
+ orderCount++;
+ orderNos.add(orderNo);
+ }
+
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("orderCount", orderCount);
+ result.put("detailCount", detailCount);
+ result.put("removedUndispatchedDetailCount", removedUndispatchedDetailCount);
+ result.put("orderNos", orderNos);
+ return R.ok("鍑哄簱璁㈠崟鐢熸垚鎴愬姛").add(result);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public R generatePendingPakoutOrderTasks() {
+ // 瀹氭椂鍏ュ彛鍙壂鎻忓惎鐢ㄤ腑鐨勫嚭搴撹鍗曪細
+ // status=1 琛ㄧず鏈 pakoutOrderPause 涓锛�
+ // settle in (1,2) 琛ㄧず鏈畬鎴愬叏閮ㄤ换鍔$敓鎴愶紱
+ // pakin_pakout_status=2 闄愬畾鍑哄簱鍗曪紝閬垮厤璇壂鍏ュ簱/鍏朵粬鏂瑰悜鍗曟嵁銆�
+ List<OrderPakout> orders = orderPakoutService.selectList(new EntityWrapper<OrderPakout>()
+ .eq("status", 1)
+ .in("settle", Arrays.asList(1L, 2L))
+ .eq("pakin_pakout_status", 2)
+ .orderBy("create_time", true));
+ Map<String, Object> result = new LinkedHashMap<>();
+ int scannedOrderCount = 0;
+ int generatedOrderCount = 0;
+ int generatedTaskCount = 0;
+ List<Object> details = new ArrayList<>();
+ if (!Cools.isEmpty(orders)) {
+ for (OrderPakout order : orders) {
+ if (order == null || Cools.isEmpty(order.getOrderNo())) {
+ continue;
+ }
+ scannedOrderCount++;
+ // 姣忎釜璁㈠崟鍗曠嫭璧扮敓鎴愰�昏緫銆傚崟璁㈠崟鏂规硶鍐呴儴鍙細鐢熸垚褰撳墠鍏佽鐨勪竴涓� entryWmsCode 鎵规锛�
+ // 鍥犳瀹氭椂鍣ㄩ噸澶嶆墽琛屼篃涓嶄細涓�娆℃�ф妸鍚庣画鎵�鏈夎繘浠撶紪鍙峰叏閮ㄩ噴鏀俱��
+ R r = generatePendingPakoutOrderTasks(order.getOrderNo());
+ details.add(r);
+ int taskCount = extractGeneratedTaskCount(r);
+ if (taskCount > 0) {
+ generatedOrderCount++;
+ generatedTaskCount += taskCount;
+ }
+ }
+ }
+ result.put("scannedOrderCount", scannedOrderCount);
+ result.put("generatedOrderCount", generatedOrderCount);
+ result.put("generatedTaskCount", generatedTaskCount);
+ result.put("details", details);
+ return R.ok().add(result);
+ }
+
+ private int extractGeneratedTaskCount(R r) {
+ if (r == null) {
+ return 0;
+ }
+ Object generatedObj = r.get("generatedTaskCount");
+ if (generatedObj instanceof Number) {
+ return ((Number) generatedObj).intValue();
+ }
+ Object dataObj = r.get("data");
+ if (dataObj instanceof Map) {
+ Object dataGeneratedObj = ((Map) dataObj).get("generatedTaskCount");
+ if (dataGeneratedObj instanceof Number) {
+ return ((Number) dataGeneratedObj).intValue();
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public R generatePendingPakoutOrderTasks(String orderNo) {
+ if (Cools.isEmpty(orderNo)) {
+ throw new CoolException("orderNo涓嶈兘涓虹┖");
+ }
+ OrderPakout order = orderPakoutService.selectByNo(orderNo);
+ if (order == null) {
+ return R.ok("鍑哄簱璁㈠崟涓嶅瓨鍦�").add(buildGeneratePendingResult(orderNo, null, 0, 0, "order not found"));
+ }
+ if (!Objects.equals(order.getStatus(), 1)) {
+ return R.ok("鍑哄簱璁㈠崟宸蹭腑姝�").add(buildGeneratePendingResult(orderNo, null, 0, 0, "order status disabled"));
+ }
+ if (!Objects.equals(order.getSettle(), 1L) && !Objects.equals(order.getSettle(), 2L)) {
+ return R.ok("鍑哄簱璁㈠崟宸插鐞�").add(buildGeneratePendingResult(orderNo, null, 0, 0, "order settle not pending"));
+ }
+
+ // 鎸夊師鏄庣粏 id 椤哄簭璇诲彇锛孡inkedHashMap 浼氫繚鎸侀娆″嚭鐜扮殑 entryWmsCode 椤哄簭銆�
+ // 杩欐牱鈥滆繘浠撶紪鍙� A 鍋氬畬鍚庡啀鐢熸垚 B鈥濈殑椤哄簭鍜� ERP 鍘熷鏄庣粏椤哄簭涓�鑷淬��
+ List<OrderDetlPakout> details = orderDetlPakoutService.selectList(new EntityWrapper<OrderDetlPakout>()
+ .eq("order_id", order.getId())
+ .eq("status", 1)
+ .orderBy("id", true));
+ LinkedHashMap<String, List<OrderDetlPakout>> detailsByEntryWmsCode = new LinkedHashMap<>();
+ for (OrderDetlPakout detail : details) {
+ if (!isPendingPakoutDetail(detail)) {
+ continue;
+ }
+ detailsByEntryWmsCode
+ .computeIfAbsent(detail.getEntryWmsCode(), key -> new ArrayList<>())
+ .add(detail);
+ }
+ if (detailsByEntryWmsCode.isEmpty()) {
+ return R.ok("鏃犲緟鐢熸垚鍑哄簱浠诲姟").add(buildGeneratePendingResult(orderNo, null, 0, 0, "no pending detail"));
+ }
+
+ // 涓�娆″彧鍙栧綋鍓嶆渶闈犲墠鐨勮繘浠撶紪鍙锋壒娆°�傚悗缁繘浠撶紪鍙锋槸鍚﹀厑璁哥敓鎴愶紝
+ // 鐢� OutboundBatchSeqReleaseGuard 鏍规嵁宸叉湁 WrkMast 鐨� batchSeq銆亀rk_sts=25 鏁伴噺闃堝�肩瓑鍒ゆ柇銆�
+ Map.Entry<String, List<OrderDetlPakout>> candidate = detailsByEntryWmsCode.entrySet().iterator().next();
+ String entryWmsCode = candidate.getKey();
+ String blockMsg = outboundBatchSeqReleaseGuard.validateReady(orderNo, entryWmsCode);
+ if (!Cools.isEmpty(blockMsg)) {
+ return R.ok("鍑哄簱杩涗粨缂栧彿鏆備笉婊¤冻鐢熸垚鏉′欢").add(buildGeneratePendingResult(orderNo, entryWmsCode, 0, candidate.getValue().size(), blockMsg));
+ }
+
+ List<OutTaskParam> outTaskParams = new ArrayList<>();
+ for (OrderDetlPakout detail : candidate.getValue()) {
+ outTaskParams.add(buildOutTaskParam(orderNo, entryWmsCode, detail));
+ }
+ Map<String, List<OutTaskParam>> linesByBatchSeq = new LinkedHashMap<>();
+ // outOrderBatch 鐨勫垎缁� key 灏辨槸浠诲姟 batchSeq銆傝繖閲屽己鍒朵娇鐢� entryWmsCode锛�
+ // 纭繚 WrkMast.userNo=orderId 涓� WrkMast.batchSeq=entryWmsCode锛岀幇鏈夋壒娆″畧鍗墠鑳界敓鏁堛��
+ linesByBatchSeq.put(entryWmsCode, outTaskParams);
+ R r = outOrderBatch(linesByBatchSeq, outTaskParams.size());
+ if (!Objects.equals(r.get("code"), 200)) {
+ throw new CoolException("鍑哄簱璁㈠崟鐢熸垚浠诲姟澶辫触锛�" + orderNo);
+ }
+
+ for (OrderDetlPakout detail : candidate.getValue()) {
+ double remaining = getPendingDetailQty(detail);
+ // work_qty 琛ㄧず鈥滃凡鐢熸垚浠诲姟鏁伴噺鈥濓紝涓嶆槸瀹屾垚鏁伴噺銆�
+ // 浠诲姟瀹屾垚鍚庣敱 WorkMastHandler 閫掑 qty锛屽洜姝ら噸澶嶅畾鏃舵壂鎻忎笉浼氫负鍚屼竴鎵樼洏閲嶅寤轰换鍔°��
+ detail.setWorkQty(safeDouble(detail.getWorkQty()) + remaining);
+ detail.setUpdateBy(9527L);
+ detail.setUpdateTime(new Date());
+ if (!orderDetlPakoutService.updateById(detail)) {
+ throw new CoolException("鏇存柊鍑哄簱璁㈠崟鏄庣粏浣滀笟鏁伴噺澶辫触锛�" + orderNo);
+ }
+ }
+ if (Objects.equals(order.getSettle(), 1L)) {
+ // 璁㈠崟涓�鏃︾敓鎴愯繃浠诲姟鍗崇疆涓� 2銆傛槸鍚﹁繕鏈夋槑缁嗘湭鐢熸垚锛屼粛浠ユ槑缁� anfme - work_qty 鍒ゆ柇銆�
+ order.setSettle(2L);
+ order.setUpdateBy(9527L);
+ order.setUpdateTime(new Date());
+ if (!orderPakoutService.updateById(order)) {
+ throw new CoolException("鏇存柊鍑哄簱璁㈠崟鐘舵�佸け璐ワ細" + orderNo);
+ }
+ }
+
+ return R.ok("鍑哄簱璁㈠崟鐢熸垚浠诲姟鎴愬姛").add(buildGeneratePendingResult(orderNo, entryWmsCode, outTaskParams.size(), candidate.getValue().size(), null));
+ }
+
+ private void validatePendingOutOrderParam(OutTaskParam param) {
+ if (param == null || Cools.isEmpty(param.getOrderId())) {
+ throw new CoolException("鍑哄簱鍗曞彿涓嶈兘涓虹┖");
+ }
+ if (Cools.isEmpty(param.getPalletId())) {
+ throw new CoolException("鎵樼洏鍙蜂笉鑳戒负绌�");
+ }
+ if (Cools.isEmpty(param.getEntryWmsCode())) {
+ throw new CoolException("鎵樼洏銆�" + param.getPalletId() + "銆嶈繘浠撶紪鍙蜂笉鑳戒负绌�");
+ }
+ if (!isPendingOutOrderStation(param.getStationId())) {
+ throw new CoolException("鎵樼洏銆�" + param.getPalletId() + "銆嶅嚭搴撳彛涓嶅睘浜庡欢杩熺敓鎴愪换鍔¤寖鍥�");
+ }
+ }
+
+ private OrderPakout createPendingPakoutOrderHeader(String orderNo, Date now) {
+ DocType docType = docTypeService.selectOrAdd(OUT_ORDER_PENDING_DOC_TYPE, Boolean.FALSE);
+ OrderPakout order = new OrderPakout();
+ order.setUuid(String.valueOf(snowflakeIdWorker.nextId()));
+ order.setOrderNo(orderNo);
+ order.setOrderTime(DateUtils.convert(now));
+ order.setDocType(docType.getDocId());
+ // settle=1 琛ㄧず寰呯敓鎴愪换鍔★紱鐢熸垚杩囪嚦灏戜竴涓繘浠撶紪鍙锋壒娆″悗缃负 2銆�
+ // status=1 鏄惎鍔ㄥ紑鍏筹紝pakoutOrderPause(execute=2) 浼氱疆 0 闃绘瀹氭椂鍣ㄧ户缁敓鎴愩��
+ order.setSettle(1L);
+ order.setStatus(1);
+ order.setCreateBy(9527L);
+ order.setCreateTime(now);
+ order.setUpdateBy(9527L);
+ order.setUpdateTime(now);
+ // moveStatus 淇濈暀鐜版湁鈥滃璐�/绉诲簱鈥濊涔夛紝杩欓噷涓嶅鐢ㄥ畠鍋氭殏鍋滃紑鍏炽��
+ order.setMoveStatus(0);
+ // 2 琛ㄧず鍑哄簱鏂瑰悜锛屽拰 man_order_detl_pakout 鏄庣粏淇濇寔涓�鑷淬��
+ order.setPakinPakoutStatus(2);
+ if (!orderPakoutService.insert(order)) {
+ throw new CoolException("鐢熸垚鍑哄簱璁㈠崟澶辫触锛�" + orderNo);
+ }
+ return order;
+ }
+
+ private void refreshPendingPakoutOrderForResubmit(OrderPakout order, Date now) {
+ if (order == null) {
+ return;
+ }
+ boolean hasDispatchedDetail = hasDispatchedPendingDetail(order.getId());
+ order.setStatus(1);
+ order.setSettle(hasDispatchedDetail ? 2L : 1L);
+ order.setUpdateBy(9527L);
+ order.setUpdateTime(now);
+ order.setPakinPakoutStatus(2);
+ if (!orderPakoutService.updateById(order)) {
+ throw new CoolException("鏇存柊鍑哄簱璁㈠崟澶辫触锛�" + order.getOrderNo());
+ }
+ }
+
+ private boolean hasDispatchedPendingDetail(Long orderId) {
+ List<OrderDetlPakout> details = orderDetlPakoutService.selectList(new EntityWrapper<OrderDetlPakout>()
+ .eq("order_id", orderId)
+ .eq("status", 1));
+ if (Cools.isEmpty(details)) {
+ return false;
+ }
+ for (OrderDetlPakout detail : details) {
+ if (!isUndispatchedPendingDetail(detail)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 鍒犻櫎鍚岃鍗曚腑灏氭湭涓嬪彂鐨勬槑缁嗐��
+ *
+ * 鍒ゆ柇鍙e緞锛�
+ * - work_qty <= 0锛氬皻鏈敓鎴愭湁鏁堜换鍔★紝鎴栦腑姝㈠悗浠诲姟宸茶鍙栨秷骞跺畬鎴愬洖婊氥��
+ * - qty <= 0锛氭病鏈変笟鍔″畬鎴愰噺锛屽垹闄ゅ悗涓嶄細涓㈠け宸插畬鎴愬嚭搴撹褰曘��
+ */
+ private int removeUndispatchedPendingDetails(Long orderId) {
+ List<OrderDetlPakout> details = orderDetlPakoutService.selectList(new EntityWrapper<OrderDetlPakout>()
+ .eq("order_id", orderId)
+ .eq("status", 1));
+ if (Cools.isEmpty(details)) {
+ return 0;
+ }
+ int removed = 0;
+ for (OrderDetlPakout detail : details) {
+ if (!isUndispatchedPendingDetail(detail)) {
+ continue;
+ }
+ if (!orderDetlPakoutService.deleteById(detail.getId())) {
+ throw new CoolException("鍒犻櫎鏈笅鍙戝嚭搴撹鍗曟槑缁嗗け璐ワ細" + detail.getOrderNo());
+ }
+ removed++;
+ }
+ return removed;
+ }
+
+ private void assertNoNonReplaceablePendingDetailConflict(OrderPakout order, List<OutTaskParam> params) {
+ if (order == null || Cools.isEmpty(params)) {
+ return;
+ }
+ Set<String> newPalletIds = params.stream()
+ .filter(Objects::nonNull)
+ .map(OutTaskParam::getPalletId)
+ .filter(palletId -> !Cools.isEmpty(palletId))
+ .collect(Collectors.toCollection(LinkedHashSet::new));
+ if (newPalletIds.isEmpty()) {
+ return;
+ }
+ List<OrderDetlPakout> details = orderDetlPakoutService.selectList(new EntityWrapper<OrderDetlPakout>()
+ .eq("order_id", order.getId())
+ .eq("status", 1));
+ if (Cools.isEmpty(details)) {
+ return;
+ }
+ for (OrderDetlPakout detail : details) {
+ if (detail == null || !newPalletIds.contains(detail.getPalletId()) || isUndispatchedPendingDetail(detail)) {
+ continue;
+ }
+ throw new CoolException("鎵樼洏銆�" + detail.getPalletId() + "銆嶅凡瀛樺湪宸蹭笅鍙戞垨宸插畬鎴愬嚭搴撴槑缁嗭紝鏃犳硶瑕嗙洊");
+ }
+ }
+
+ private boolean isUndispatchedPendingDetail(OrderDetlPakout detail) {
+ return detail != null
+ && safeDouble(detail.getWorkQty()) <= 0.0D
+ && safeDouble(detail.getQty()) <= 0.0D;
+ }
+
+ /**
+ * 鍒ゆ柇寤惰繜鍑哄簱璁㈠崟鏄惁杩樿兘琚綋鍓嶆帴鍙h姹傝鐩栥��
+ *
+ * 娲诲姩浠诲姟浠嶇劧瀛樺湪鏃朵笉鍏佽瑕嗙洊锛屽洜涓轰换鍔°�佸簱浣嶃�乄CS 鎸囦护杩樺湪鎵ц閾捐矾涓娿��
+ * 宸茬粡鍙栨秷骞跺綊妗e埌 WrkMastLog 鐨勪换鍔″厑璁搁噸涓嬪彂锛涘叾璁㈠崟鏄庣粏 work_qty 宸插湪鍙栨秷鏃跺洖婊氾紝
+ * 鏈鎺ュ彛浼氬垹闄ゆ湭涓嬪彂鏄庣粏骞舵彃鍏ユ柊鏄庣粏銆�
+ */
+ private void assertPendingPakoutOrderCanReplace(String orderNo) {
+ List<WrkMast> activeTasks = findActiveOutboundTasks(orderNo);
+ if (!Cools.isEmpty(activeTasks)) {
+ throw new CoolException("鍑哄簱璁㈠崟宸插瓨鍦ㄦ椿鍔ㄤ换鍔★紝鏃犳硶瑕嗙洊锛�" + orderNo);
+ }
+ int activeWrkCount = wrkMastService.selectCount(new EntityWrapper<WrkMast>()
+ .eq("io_type", 101)
+ .eq("user_no", orderNo));
+ if (activeWrkCount > 0) {
+ throw new CoolException("鍑哄簱璁㈠崟宸插瓨鍦ㄤ换鍔℃。锛屾棤娉曡鐩栵細" + orderNo);
+ }
+ OrderPakout order = orderPakoutService.selectByNo(orderNo);
+ if (order != null && order.getSettle() != null && order.getSettle() > 2L) {
+ throw new CoolException(orderNo + "姝e湪鍑哄簱锛屾棤娉曚慨鏀瑰崟鎹�");
+ }
+ }
+
+ /**
+ * 鎶� OutTaskParam 钀芥垚鍑哄簱璁㈠崟鏄庣粏銆�
+ *
+ * detail.sync(locDetl) 璐熻矗澶嶅埗搴撳瓨缁村害瀛楁锛堢墿鏂欍�佹壒娆°�佸搧鐗屻�佹墿灞曞瓧娈电瓑锛夛紱
+ * 鍚庣画 setXxx 淇濆瓨鎺ュ彛鍘熷瀛楁锛屼繚璇佸畾鏃跺櫒鍙互杩樺師瀹屾暣 OutTaskParam銆�
+ */
+ private OrderDetlPakout buildPendingPakoutOrderDetl(OrderPakout order, OutTaskParam param, Date now) {
+ LocDetl locDetl = locDetlService.selectOne(new EntityWrapper<LocDetl>().eq("zpallet", param.getPalletId()));
+ if (locDetl == null) {
+ throw new CoolException("搴撳瓨涓笉瀛樺湪璇ユ墭鐩橈細" + param.getPalletId());
+ }
+ if (!Cools.isEmpty(param.getMatnr()) && !Objects.equals(param.getMatnr(), locDetl.getMatnr())) {
+ throw new CoolException("鎵樼洏銆�" + param.getPalletId() + "銆嶇墿鏂欑紪鐮佷笌搴撳瓨涓嶄竴鑷�");
+ }
+ OrderDetlPakout detail = new OrderDetlPakout();
+ detail.sync(locDetl);
+ detail.setOrderId(order.getId());
+ detail.setOrderNo(order.getOrderNo());
+ detail.setAnfme(resolvePendingOrderAnfme(param, locDetl));
+ detail.setWorkQty(0.0D);
+ detail.setQty(0.0D);
+ detail.setStatus(1);
+ detail.setCreateBy(9527L);
+ detail.setCreateTime(now);
+ detail.setUpdateBy(9527L);
+ detail.setUpdateTime(now);
+ detail.setPakinPakoutStatus(2);
+ detail.setBatchSeq(param.getBatchSeq());
+ detail.setSeq(param.getSeq());
+ detail.setPalletId(param.getPalletId());
+ detail.setStationId(param.getStationId());
+ detail.setEntryWmsCode(param.getEntryWmsCode());
+ detail.setContainerNo(param.getContainerNo());
+ detail.setOutDoorNo(param.getOutDoorNo());
+ detail.setPlateNo(param.getPlateNo());
+ detail.setTrainNo(param.getTrainNo());
+ detail.setFreqType(param.getFreqType());
+ detail.setCubeNumber(param.getCubeNumber());
+ detail.setTeu(param.getTeu());
+ // standby1/standby2 缁х画闀滃儚杩涗粨缂栧彿鍜屽嚭搴撻棬鍙凤紝鍏煎鐜版湁瀹屾垚鍥炲啓鐨� selectItem 鍖归厤閫昏緫銆�
+ detail.setStandby1(param.getEntryWmsCode());
+ detail.setStandby2(param.getOutDoorNo());
+ return detail;
+ }
+
+ /**
+ * 鏄庣粏鏁伴噺浼樺厛浣跨敤 ERP 鍙傛暟涓殑 anfme銆�
+ * 濡傛灉 ERP 鏈紶鏁伴噺锛屽垯浣跨敤褰撳墠搴撳瓨鏁伴噺锛涗袱鑰呴兘涓嶅彲鐢ㄦ椂鎸夋暣鎵� 1 澶勭悊锛岄伩鍏嶇敓鎴� 0 鏁伴噺浠诲姟銆�
+ */
+ private double resolvePendingOrderAnfme(OutTaskParam param, LocDetl locDetl) {
+ if (param.getAnfme() > 0.0D) {
+ return param.getAnfme();
+ }
+ if (locDetl != null && locDetl.getAnfme() != null && locDetl.getAnfme() > 0.0D) {
+ return locDetl.getAnfme();
+ }
+ return 1.0D;
+ }
+
+ /**
+ * 鍒ゆ柇璁㈠崟鏄庣粏鏄惁杩橀渶瑕佺敓鎴愪换鍔°��
+ *
+ * work_qty 鏄换鍔$敓鎴愯繘搴︼紝qty 鏄换鍔″畬鎴愯繘搴︺��
+ * 杩欓噷鍙湅 anfme - work_qty锛岄伩鍏嶅畾鏃跺櫒鍥犱负浠诲姟鏈畬鎴愯�岄噸澶嶇敓鎴愬悓涓�鎵樼洏浠诲姟銆�
+ */
+ private boolean isPendingPakoutDetail(OrderDetlPakout detail) {
+ return detail != null
+ && isPendingOutOrderStation(detail.getStationId())
+ && !Cools.isEmpty(detail.getEntryWmsCode())
+ && getPendingDetailQty(detail) > 0.0D;
+ }
+
+ /**
+ * 浠庤鍗曟槑缁嗚繕鍘� outOrderBatch 闇�瑕佺殑鍙傛暟銆�
+ *
+ * batchSeq 蹇呴』寮哄埗鏀逛负 entryWmsCode锛岃�屼笉鏄部鐢� ERP 鍘熷 batchSeq锛�
+ * 杩欐牱鍚庣画 WCS 涓嬪彂瀹堝崼鎵嶈兘浠ヨ繘浠撶紪鍙蜂负椤哄簭杈圭晫銆�
+ */
+ private OutTaskParam buildOutTaskParam(String orderNo, String entryWmsCode, OrderDetlPakout detail) {
+ OutTaskParam param = new OutTaskParam();
+ param.setOrderId(orderNo);
+ param.setBatchSeq(entryWmsCode);
+ param.setSeq(detail.getSeq());
+ param.setPalletId(detail.getPalletId());
+ param.setStationId(detail.getStationId());
+ param.setMatnr(detail.getMatnr());
+ param.setAnfme(getPendingDetailQty(detail));
+ param.setEntryWmsCode(detail.getEntryWmsCode());
+ param.setContainerNo(detail.getContainerNo());
+ param.setOutDoorNo(detail.getOutDoorNo());
+ param.setPlateNo(detail.getPlateNo());
+ param.setTrainNo(detail.getTrainNo());
+ param.setFreqType(detail.getFreqType());
+ param.setCubeNumber(detail.getCubeNumber());
+ param.setTeu(detail.getTeu());
+ return param;
+ }
+
+ private Map<String, Object> buildGeneratePendingResult(String orderNo, String entryWmsCode, int generatedTaskCount, int pendingDetailCount, String reason) {
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("orderNo", orderNo);
+ result.put("entryWmsCode", entryWmsCode);
+ result.put("generatedTaskCount", generatedTaskCount);
+ result.put("pendingDetailCount", pendingDetailCount);
+ if (!Cools.isEmpty(reason)) {
+ result.put("reason", reason);
+ }
+ return result;
+ }
+
+ private boolean isPendingOutOrderStation(String stationId) {
+ if (Cools.isEmpty(stationId)) {
+ return false;
+ }
+ try {
+ return Integer.valueOf(stationId) > PENDING_OUT_ORDER_STATION_THRESHOLD;
+ } catch (NumberFormatException ignored) {
+ return false;
+ }
+ }
+
+ private double getPendingDetailQty(OrderDetlPakout detail) {
+ return safeDouble(detail.getAnfme()) - safeDouble(detail.getWorkQty());
+ }
+
+ private double safeDouble(Double value) {
+ return value == null ? 0.0D : value;
+ }
+
+ /**
+ * 7.9 鍑哄簱寮傚父鍙樺姩涓婃姤銆�
+ * WCS 鍙紶 palletId銆乪rrorMsg锛學MS 瑙f瀽 orderId 鍚庤浆鍙� ERP銆�
+ */
+ @Override
+ public R outOrderAbnormalReport(OutOrderAbnormalReportParam param) {
+ if (param == null || Cools.isEmpty(param.getPalletId())) {
+ return R.error("palletId涓嶈兘涓虹┖");
+ }
+ String orderId = resolveOutboundOrderId(param.getPalletId());
+ if (Cools.isEmpty(orderId)) {
+ return R.error("鏈壘鍒版墭鐩樺搴斿嚭搴撳崟鍙凤細" + param.getPalletId());
+ }
+ if (Cools.isEmpty(erpOutErrorAddress)) {
+ return R.error("ERP鍑哄簱寮傚父涓婃姤鍦板潃鏈厤缃�");
+ }
+
+ ErpOutOrderAbnormalReportParam erpParam = new ErpOutOrderAbnormalReportParam();
+ erpParam.setPalletId(param.getPalletId());
+ erpParam.setErrorMsg(param.getErrorMsg());
+ erpParam.setOrderId(orderId);
+
+ String requestJson = JSON.toJSONString(erpParam);
+ String response = "";
+ boolean pushOk = false;
+ String errorMsg = null;
+ String pushUrl = buildErpOutErrorRequestUrl();
+ try {
+ response = new HttpHandler.Builder()
+ .setUri(erpUrl)
+ .setPath(erpOutErrorAddress)
+ .setJson(requestJson)
+ .build()
+ .doPost();
+ pushOk = isErpCallSuccess(response);
+ if (!pushOk) {
+ errorMsg = extractErpCallError(response);
+ }
+ } catch (Exception e) {
+ errorMsg = e.getMessage();
+ log.error("鎺‥RP鍑哄簱寮傚父涓婃姤澶辫触, palletId={}, orderId={}", param.getPalletId(), orderId, e);
+ } finally {
+ try {
+ apiLogService.save(
+ "鎺‥RP-鍑哄簱寮傚父涓婃姤",
+ pushUrl,
+ null,
+ "127.0.0.1",
+ requestJson,
+ response,
+ pushOk,
+ "palletId=" + param.getPalletId() + ",orderId=" + orderId
+ );
+ } catch (Exception logEx) {
+ log.error("save out abnormal api log failed", logEx);
+ }
+ }
+ if (!pushOk) {
+ return R.error(Cools.isEmpty(errorMsg) ? "ERP鍑哄簱寮傚父涓婃姤澶辫触" : errorMsg);
+ }
+ return R.ok().add(Cools.add("palletId", param.getPalletId()).add("orderId", orderId));
+ }
+
+ /**
+ * 7.10 鍑哄簱寮傚父鍙樺姩澶勭悊銆�
+ * 鏈湡鍙帴鏀躲�佹牎楠屽拰璁板綍锛屼笉鏀规湰鍦颁换鍔★紝涔熶笉杞彂 WCS銆�
+ */
+ @Override
+ public R outOrderAbnormalHandle(OutOrderAbnormalHandleParam param) {
+ if (param == null || Cools.isEmpty(param.getPalletId())) {
+ return R.error("palletId涓嶈兘涓虹┖");
+ }
+ if (param.getOperateType() == null || !(Objects.equals(param.getOperateType(), 0) || Objects.equals(param.getOperateType(), 2))) {
+ return R.error("operateType鍙厑璁�0鎴�2");
+ }
+ if (!existsOutboundPallet(param.getPalletId())) {
+ return R.error("鏈壘鍒版墭鐩橈細" + param.getPalletId());
+ }
+ log.info("鎺ユ敹鍑哄簱寮傚父澶勭悊鎸囦护, palletId={}, operateType={}", param.getPalletId(), param.getOperateType());
+ return R.ok().add(Cools.add("palletId", param.getPalletId()).add("operateType", param.getOperateType()));
+ }
+
+ private String buildOutOrderBatchKey(OutTaskParam param) {
+ return param.getOrderId() + "#" + param.getBatchSeq();
+ }
+
+ private Map<String, Integer> buildOutOrderBatchTeuCounts(List<OutTaskParam> params) {
+ Map<String, Set<String>> batchOrderIds = new HashMap<>();
+ for (OutTaskParam param : params) {
+ batchOrderIds.computeIfAbsent(param.getBatchSeq(), k -> new LinkedHashSet<>()).add(param.getOrderId());
+ }
+ Map<String, Integer> batchTeuCounts = new HashMap<>();
+ for (Map.Entry<String, Set<String>> entry : batchOrderIds.entrySet()) {
+ batchTeuCounts.put(entry.getKey(), entry.getValue().size());
+ }
+ return batchTeuCounts;
+ }
+
+ private String resolveOutboundOrderId(String palletId) {
+ List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
+ .eq("io_type", 101)
+ .eq("barcode", palletId)
+ .orderBy("io_time", false)
+ .orderBy("wrk_no", false));
+ if (!Cools.isEmpty(wrkMasts)) {
+ for (WrkMast wrkMast : wrkMasts) {
+ if (!Cools.isEmpty(wrkMast.getUserNo())) {
+ return wrkMast.getUserNo();
+ }
+ }
+ }
+ List<WrkDetl> wrkDetls = wrkDetlService.selectList(new EntityWrapper<WrkDetl>()
+ .eq("zpallet", palletId)
+ .orderBy("io_time", false)
+ .orderBy("wrk_no", false));
+ if (!Cools.isEmpty(wrkDetls)) {
+ for (WrkDetl wrkDetl : wrkDetls) {
+ if (!Cools.isEmpty(wrkDetl.getOrderNo())) {
+ return wrkDetl.getOrderNo();
+ }
+ }
+ }
+ return null;
+ }
+
+ private boolean existsOutboundPallet(String palletId) {
+ if (locDetlService.selectCount(new EntityWrapper<LocDetl>().eq("zpallet", palletId)) > 0) {
+ return true;
+ }
+ if (wrkMastService.selectCount(new EntityWrapper<WrkMast>().eq("io_type", 101).eq("barcode", palletId)) > 0) {
+ return true;
+ }
+ return wrkDetlService.selectCount(new EntityWrapper<WrkDetl>().eq("zpallet", palletId)) > 0;
+ }
+
+ private boolean isErpCallSuccess(String response) {
+ if (Cools.isEmpty(response)) {
+ return false;
+ }
+ try {
+ JSONObject jsonObject = JSON.parseObject(response);
+ if (jsonObject == null) {
+ return false;
+ }
+ Boolean success = jsonObject.getBoolean("success");
+ if (success != null) {
+ return success;
+ }
+ Integer code = jsonObject.getInteger("code");
+ if (code != null) {
+ return code == 200 || code == 0;
+ }
+ Integer status = jsonObject.getInteger("status");
+ if (status != null) {
+ return status == 200 || status == 0;
+ }
+ String result = jsonObject.getString("result");
+ if (!Cools.isEmpty(result)) {
+ return "success".equalsIgnoreCase(result) || "ok".equalsIgnoreCase(result) || "true".equalsIgnoreCase(result);
+ }
+ } catch (Exception ignore) {
+ return response.toLowerCase().contains("success") && response.toLowerCase().contains("true");
+ }
+ return false;
+ }
+
+ private String extractErpCallError(String response) {
+ if (Cools.isEmpty(response)) {
+ return "empty erp response";
+ }
+ try {
+ JSONObject jsonObject = JSON.parseObject(response);
+ if (jsonObject == null) {
+ return response;
+ }
+ String[] keys = new String[]{"msg", "message", "error", "errMsg"};
+ for (String key : keys) {
+ String value = jsonObject.getString(key);
+ if (!Cools.isEmpty(value)) {
+ return value;
+ }
+ }
+ } catch (Exception ignore) {
+ }
+ return response;
+ }
+
+ private boolean isErpReportEnabled() {
+ if (!erpReportOld) {
+ return false;
+ }
+ String erpReport = Parameter.get().getErpReport();
+ return Cools.isEmpty(erpReport) || "true".equalsIgnoreCase(erpReport);
+ }
+
+ private List<String> normalizeBarcodes(List<String> barcodes) {
+ if (barcodes == null || barcodes.isEmpty()) {
+ return Collections.emptyList();
+ }
+ LinkedHashSet<String> normalized = new LinkedHashSet<>();
+ for (String barcode : barcodes) {
+ if (barcode == null) {
+ continue;
+ }
+ String value = barcode.trim();
+ if (!value.isEmpty()) {
+ normalized.add(value);
+ }
+ }
+ return new ArrayList<>(normalized);
+ }
+
+ private Map<String, WrkMastLog> loadLatestInboundHistoryLogMap(List<String> barcodes) {
+ Map<String, WrkMastLog> latestInboundLogMap = new LinkedHashMap<>();
+ if (barcodes == null || barcodes.isEmpty()) {
+ return latestInboundLogMap;
+ }
+ List<WrkMastLog> wrkMastLogs = wrkMastLogService.selectList(new EntityWrapper<WrkMastLog>()
+ .in("barcode", barcodes)
+ .orderBy("barcode", true)
+ .orderBy("io_time", false)
+ .orderBy("wrk_no", false));
+ if (Cools.isEmpty(wrkMastLogs)) {
+ return latestInboundLogMap;
+ }
+ for (WrkMastLog wrkMastLog : wrkMastLogs) {
+ if (wrkMastLog == null || Cools.isEmpty(wrkMastLog.getBarcode())) {
+ continue;
+ }
+ if (!isInboundHistoryLog(wrkMastLog.getIoType())) {
+ continue;
+ }
+ latestInboundLogMap.putIfAbsent(wrkMastLog.getBarcode(), wrkMastLog);
+ }
+ return latestInboundLogMap;
+ }
+
+ private boolean isInboundHistoryLog(Integer ioType) {
+ if (ioType == null) {
+ return false;
+ }
+ // 鍘嗗彶琛ㄩ噷鏃㈡湁鍏ュ簱瀹屾垚锛屼篃鏈夊簱瀛樿皟鏁达紱杩欓噷鍙彇鐪熸鐨勫叆搴撶被璁板綍銆�
+ return ioType < 19 || ioType == 53 || ioType == 54 || ioType == 57;
+ }
+
+ private Map<Integer, List<WrkDetlLog>> loadWrkDetlLogMap(Collection<WrkMastLog> wrkMastLogs) {
+ Map<Integer, List<WrkDetlLog>> wrkDetlLogMap = new HashMap<>();
+ if (wrkMastLogs == null || wrkMastLogs.isEmpty()) {
+ return wrkDetlLogMap;
+ }
+ LinkedHashSet<Integer> wrkNos = new LinkedHashSet<>();
+ for (WrkMastLog wrkMastLog : wrkMastLogs) {
+ if (wrkMastLog != null && wrkMastLog.getWrkNo() != null) {
+ wrkNos.add(wrkMastLog.getWrkNo());
+ }
+ }
+ if (wrkNos.isEmpty()) {
+ return wrkDetlLogMap;
+ }
+ List<WrkDetlLog> wrkDetlLogs = wrkDetlLogService.selectList(new EntityWrapper<WrkDetlLog>().in("wrk_no", wrkNos));
+ if (Cools.isEmpty(wrkDetlLogs)) {
+ return wrkDetlLogMap;
+ }
+ for (WrkDetlLog wrkDetlLog : wrkDetlLogs) {
+ if (wrkDetlLog == null || wrkDetlLog.getWrkNo() == null) {
+ continue;
+ }
+ wrkDetlLogMap.computeIfAbsent(wrkDetlLog.getWrkNo(), k -> new ArrayList<>()).add(wrkDetlLog);
+ }
+ return wrkDetlLogMap;
+ }
+
+ private Map<String, WaitPakinLog> loadWaitPakinLogMap(List<String> barcodes) {
+ Map<String, WaitPakinLog> waitPakinLogMap = new LinkedHashMap<>();
+ if (barcodes == null || barcodes.isEmpty()) {
+ return waitPakinLogMap;
+ }
+ List<WaitPakinLog> waitPakinLogs = waitPakinLogService.selectList(new EntityWrapper<WaitPakinLog>()
+ .in("zpallet", barcodes)
+ .orderBy("zpallet", true)
+ .orderBy("appe_time", false)
+ .orderBy("modi_time", false));
+ if (Cools.isEmpty(waitPakinLogs)) {
+ return waitPakinLogMap;
+ }
+ for (WaitPakinLog waitPakinLog : waitPakinLogs) {
+ if (waitPakinLog == null || Cools.isEmpty(waitPakinLog.getZpallet())) {
+ continue;
+ }
+ waitPakinLogMap.putIfAbsent(waitPakinLog.getZpallet(), waitPakinLog);
+ }
+ return waitPakinLogMap;
+ }
+
+ private ErpPakinReportParam buildInboundErpParam(String barcode,
+ WrkMastLog wrkMastLog,
+ List<WrkDetlLog> wrkDetlLogs,
+ WaitPakinLog waitPakinLog) {
+ ErpPakinReportParam param = new ErpPakinReportParam();
+ param.setPalletId(resolvePalletId(barcode, wrkMastLog, wrkDetlLogs, waitPakinLog));
+ param.setAnfme(resolveInboundAnfme(wrkDetlLogs, waitPakinLog));
+ param.setLocId(transformInboundLocId(resolveInboundLocNo(wrkMastLog, waitPakinLog)));
+ param.setWeight(resolveInboundWeight(wrkMastLog, waitPakinLog));
+ param.setCreateTime(formatDate(resolveInboundCreateTime(wrkMastLog)));
+ param.setBizNo(resolveInboundBizNo(wrkDetlLogs, waitPakinLog));
+ param.setStartTime(formatDate(resolveInboundStartTime(wrkMastLog, waitPakinLog)));
+ return param;
+ }
+
+ private String resolvePalletId(String barcode,
+ WrkMastLog wrkMastLog,
+ List<WrkDetlLog> wrkDetlLogs,
+ WaitPakinLog waitPakinLog) {
+ if (wrkMastLog != null && !Cools.isEmpty(wrkMastLog.getBarcode())) {
+ return wrkMastLog.getBarcode();
+ }
+ if (wrkDetlLogs != null) {
+ for (WrkDetlLog wrkDetlLog : wrkDetlLogs) {
+ if (wrkDetlLog != null && !Cools.isEmpty(wrkDetlLog.getZpallet())) {
+ return wrkDetlLog.getZpallet();
+ }
+ }
+ }
+ if (waitPakinLog != null && !Cools.isEmpty(waitPakinLog.getZpallet())) {
+ return waitPakinLog.getZpallet();
+ }
+ return barcode;
+ }
+
+ private Double resolveInboundAnfme(List<WrkDetlLog> wrkDetlLogs, WaitPakinLog waitPakinLog) {
+ double total = 0D;
+ boolean hasDetail = false;
+ if (wrkDetlLogs != null) {
+ for (WrkDetlLog wrkDetlLog : wrkDetlLogs) {
+ if (wrkDetlLog == null || wrkDetlLog.getAnfme() == null) {
+ continue;
+ }
+ total += wrkDetlLog.getAnfme();
+ hasDetail = true;
+ }
+ }
+ if (hasDetail) {
+ return total;
+ }
+ if (waitPakinLog != null && waitPakinLog.getAnfme() != null) {
+ return waitPakinLog.getAnfme();
+ }
+ return total;
+ }
+
+ private BigDecimal resolveInboundWeight(WrkMastLog wrkMastLog, WaitPakinLog waitPakinLog) {
+ BigDecimal baseWeight = BigDecimal.ZERO;
+ if (wrkMastLog != null && wrkMastLog.getScWeight() != null) {
+ baseWeight = BigDecimal.valueOf(wrkMastLog.getScWeight());
+ } else if (waitPakinLog != null && waitPakinLog.getWeight() != null) {
+ baseWeight = BigDecimal.valueOf(waitPakinLog.getWeight());
+ }
+ Integer sourceStaNo = resolveInboundSourceStaNo(wrkMastLog);
+ return baseWeight.multiply(resolveInboundWeightFactor(sourceStaNo));
+ }
+
+ private Integer resolveInboundSourceStaNo(WrkMastLog wrkMastLog) {
+ if (wrkMastLog == null) {
+ return null;
+ }
+ if (wrkMastLog.getSourceStaNo() != null) {
+ return wrkMastLog.getSourceStaNo();
+ }
+ return wrkMastLog.getStaNo();
+ }
+
+ private BigDecimal resolveInboundWeightFactor(Integer sourceStaNo) {
+ if (sourceStaNo == null) {
+ return BigDecimal.ONE;
+ }
+ BigDecimal factor = INBOUND_WEIGHT_FACTOR_BY_SOURCE_STA.get(sourceStaNo);
+ return factor == null ? BigDecimal.ONE : factor;
+ }
+
+ private String resolveInboundLocNo(WrkMastLog wrkMastLog, WaitPakinLog waitPakinLog) {
+ if (wrkMastLog != null && !Cools.isEmpty(wrkMastLog.getLocNo())) {
+ return wrkMastLog.getLocNo();
+ }
+ if (waitPakinLog != null && !Cools.isEmpty(waitPakinLog.getLocNo())) {
+ return waitPakinLog.getLocNo();
+ }
+ return null;
+ }
+
+ private Date resolveInboundCreateTime(WrkMastLog wrkMastLog) {
+ if (wrkMastLog == null) {
+ return new Date();
+ }
+ if (wrkMastLog.getCrnEndTime() != null) {
+ return wrkMastLog.getCrnEndTime();
+ }
+ if (wrkMastLog.getModiTime() != null) {
+ return wrkMastLog.getModiTime();
+ }
+ if (wrkMastLog.getIoTime() != null) {
+ return wrkMastLog.getIoTime();
+ }
+ return new Date();
+ }
+
+ private Date resolveInboundStartTime(WrkMastLog wrkMastLog, WaitPakinLog waitPakinLog) {
+ if (waitPakinLog != null && waitPakinLog.getAppeTime() != null) {
+ return waitPakinLog.getAppeTime();
+ }
+ if (wrkMastLog == null) {
+ return new Date();
+ }
+ if (wrkMastLog.getAppeTime() != null) {
+ return wrkMastLog.getAppeTime();
+ }
+ if (wrkMastLog.getIoTime() != null) {
+ return wrkMastLog.getIoTime();
+ }
+ if (wrkMastLog.getModiTime() != null) {
+ return wrkMastLog.getModiTime();
+ }
+ return new Date();
+ }
+
+ private String resolveInboundBizNo(List<WrkDetlLog> wrkDetlLogs, WaitPakinLog waitPakinLog) {
+ if (wrkDetlLogs != null) {
+ for (WrkDetlLog wrkDetlLog : wrkDetlLogs) {
+ if (wrkDetlLog != null && !Cools.isEmpty(wrkDetlLog.getThreeCode())) {
+ return wrkDetlLog.getThreeCode();
+ }
+ }
+ }
+ if (waitPakinLog != null && !Cools.isEmpty(waitPakinLog.getThreeCode())) {
+ return waitPakinLog.getThreeCode();
+ }
+ return null;
+ }
+
+ private String transformInboundLocId(String locId) {
+ if (Cools.isEmpty(locId)) {
+ return null;
+ }
+ String trimmed = locId.trim();
+ if (trimmed.length() < 7) {
+ return trimmed;
+ }
+ String row = trimmed.substring(0, 2);
+ String col = trimmed.substring(2, 5);
+ String lev = trimmed.substring(5, 7);
+ try {
+ int rowNo = Integer.parseInt(row);
+ if (rowNo >= 37) {
+ row = "C" + row;
+ } else if (rowNo >= 13) {
+ row = "B" + row;
+ } else {
+ row = "A" + row;
+ }
+ } catch (Exception ignore) {
+ return trimmed;
+ }
+ return row + "-" + col + "-" + lev;
+ }
+
+ private String formatDate(Date date) {
+ if (date == null) {
+ return null;
+ }
+ return new SimpleDateFormat(DATE_TIME_PATTERN).format(date);
+ }
+
+ private String buildErpInboundRequestUrl() {
+ if (Cools.isEmpty(erpUrl)) {
+ return erpInAddress;
+ }
+ if (erpInAddress == null) {
+ return erpUrl;
+ }
+ if (erpUrl.endsWith("/") && erpInAddress.startsWith("/")) {
+ return erpUrl + erpInAddress.substring(1);
+ }
+ if (!erpUrl.endsWith("/") && !erpInAddress.startsWith("/")) {
+ return erpUrl + "/" + erpInAddress;
+ }
+ return erpUrl + erpInAddress;
+ }
+
+ private String buildErpOutErrorRequestUrl() {
+ if (Cools.isEmpty(erpUrl)) {
+ return erpOutErrorAddress;
+ }
+ if (erpOutErrorAddress == null) {
+ return erpUrl;
+ }
+ if (erpUrl.endsWith("/") && erpOutErrorAddress.startsWith("/")) {
+ return erpUrl + erpOutErrorAddress.substring(1);
+ }
+ if (!erpUrl.endsWith("/") && !erpOutErrorAddress.startsWith("/")) {
+ return erpUrl + "/" + erpOutErrorAddress;
+ }
+ return erpUrl + erpOutErrorAddress;
+ }
}
+
--
Gitblit v1.9.1