From 98d88ac8caf7f0991d741079474c262f1e252927 Mon Sep 17 00:00:00 2001
From: chen.lin <1442464845@qq.com>
Date: 星期五, 06 三月 2026 08:14:54 +0800
Subject: [PATCH] 拣货过程中的出库库存匹配
---
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java | 202 +++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 156 insertions(+), 46 deletions(-)
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
index 13c551f..f1dd469 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/WcsServiceImpl.java
@@ -39,6 +39,7 @@
import com.vincent.rsf.server.manager.enums.LocStsType;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import lombok.extern.slf4j.Slf4j;
+import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -322,22 +323,47 @@
// 2. 鑻ユ湭鍛戒腑鎷f枡/鐩樼偣鍏ュ簱锛屽啀鏍¢獙缁勬墭骞剁户缁叾浠栧叆搴撻�昏緫
if (pickInTask == null && checkInTask == null) {
- waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
- .eq(WaitPakin::getBarcode, param.getBarcode())
- .in(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val));
- // 绌烘墭鐩樻棤缁勬墭鏃讹細鑻ラ厤缃惎鐢ㄥ垯鎸� AUTO_FULL_OUT_MATNR_CODE 鑷姩缁勬墭骞剁敓鎴愬叆搴撳崟锛屽啀缁х画鍏ュ簱浠诲姟閫昏緫
- if (waitPakin == null) {
- tryAutoPakinForBarcode(param.getBarcode());
+ String barcode = param.getBarcode();
+ // 璇ユ墭鐩樺凡鍦ㄥ簱瀛樹腑锛屼笉鍙噸澶嶇敵璇峰叆搴�
+ List<Loc> inStock = locService.list(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, barcode));
+ if (!inStock.isEmpty()) {
+ throw new CoolException("barcode=" + barcode + ": 璇ユ墭鐩樺凡鍦ㄥ簱锛屼笉鍙噸澶嶇敵璇峰叆搴�");
+ }
+ // 璇ユ墭鐩樺嚭搴撲腑鏈畬鎴愶紝涓嶅彲鐢宠鍏ュ簱
+ List<Integer> outboundTaskTypes = Arrays.asList(
+ TaskType.TASK_TYPE_OUT.type,
+ TaskType.TASK_TYPE_PICK_AGAIN_OUT.type,
+ TaskType.TASK_TYPE_MERGE_OUT.type,
+ TaskType.TASK_TYPE_CHECK_OUT.type,
+ TaskType.TASK_TYPE_EMPITY_OUT.type
+ );
+ Task outboundTask = taskService.getOne(new LambdaQueryWrapper<Task>()
+ .eq(Task::getBarcode, barcode)
+ .in(Task::getTaskType, outboundTaskTypes)
+ .lt(Task::getTaskStatus, TaskStsType.COMPLETE_OUT.id));
+ if (outboundTask != null) {
+ throw new CoolException("barcode=" + barcode + ": 璇ユ墭鐩樺嚭搴撲腑鏈畬鎴愶紝涓嶅彲鐢宠鍏ュ簱");
+ }
+
+ // 鎸� barcode 鍔犻攣锛岄伩鍏嶅悓涓� barcode 骞跺彂璇锋眰閲嶅鑷姩缁勬墭銆侀噸澶嶇敓鎴愬叆搴撳崟
+ String barcodeForLock = param.getBarcode();
+ synchronized ((barcodeForLock != null ? barcodeForLock : "").intern()) {
waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
.eq(WaitPakin::getBarcode, param.getBarcode())
.in(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val));
+ // 绌烘墭鐩樻棤缁勬墭鏃讹細鑻ラ厤缃惎鐢ㄥ垯鎸� AUTO_FULL_OUT_MATNR_CODE 鑷姩缁勬墭骞剁敓鎴愬叆搴撳崟锛屽啀缁х画鍏ュ簱浠诲姟閫昏緫
+ if (waitPakin == null) {
+ tryAutoPakinForBarcode(param.getBarcode());
+ waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
+ .eq(WaitPakin::getBarcode, param.getBarcode())
+ .in(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val));
+ }
}
waitPakin = validateWaitPakin(param.getBarcode());
waitPakinItems = waitPakinItemService.list(
new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, waitPakin.getId()));
}
- // 妫�鏌ュ叾浠栧叆搴撲换鍔$被鍨嬶紙鐢ㄧ鍙锋煡璇紝鐘舵�佷负1鎴�2锛�
- // 娉ㄦ剰锛氱洏鐐瑰叆搴撳凡鍗曠嫭澶勭悊锛屼笉鍐嶅寘鍚湪姝ゅ垪琛ㄤ腑
+ // 妫�鏌ヨ鎵樼洏鍙锋槸鍚﹀凡鏈夊叆搴撲换鍔★紙鍚繘琛屼腑銆佸凡瀹屾垚锛夛紝鏈夊垯鐩存帴澶嶇敤杩斿洖锛屾嫤鎴噸澶嶆彁浜�
List<Integer> otherInboundTaskTypes = Arrays.asList(
TaskType.TASK_TYPE_IN.type,
TaskType.TASK_TYPE_MERGE_IN.type,
@@ -347,48 +373,35 @@
Task existingInTask = taskService.getOne(new LambdaQueryWrapper<Task>()
.eq(Task::getBarcode, param.getBarcode())
.in(Task::getTaskType, otherInboundTaskTypes)
- .in(Task::getTaskStatus, TaskStsType.GENERATE_IN.id, TaskStsType.WCS_EXECUTE_IN.id)
.orderByDesc(Task::getCreateTime)
.last("LIMIT 1"));
if (Objects.nonNull(existingInTask)) {
- log.info("鎵惧埌鍖归厤鐨勫叾浠栧叆搴撲换鍔� - 浠诲姟缂栫爜锛歿}锛屼换鍔$被鍨嬶細{}锛岀鍙凤細{}",
- existingInTask.getTaskCode(), existingInTask.getTaskType(), param.getBarcode());
+ log.info("鎵惧埌璇ユ墭鐩樺彿宸叉湁鍏ュ簱浠诲姟锛屽鐢ㄥ苟鎷︽埅閲嶅鎻愪氦 - 浠诲姟缂栫爜锛歿}锛岀鍙凤細{}锛岀姸鎬侊細{}",
+ existingInTask.getTaskCode(), param.getBarcode(), existingInTask.getTaskStatus());
- // 妫�鏌ョ粍鎵樻槑缁嗘槸鍚︽湁璁㈠崟缂栫爜锛堜换鍔$紪鍙凤級
- List<WaitPakinItem> itemsWithAsnCode = waitPakinItems.stream()
- .filter(item -> StringUtils.isNotBlank(item.getAsnCode()))
- .collect(Collectors.toList());
-
- if (!itemsWithAsnCode.isEmpty()) {
- log.info("缁勬墭妗f湁浠诲姟缂栧彿锛屼娇鐢ㄧ幇鏈夊叆搴撲换鍔″崟鍙� - 浠诲姟缂栫爜锛歿}锛岀鍙凤細{}锛屼换鍔$紪鍙锋暟閲忥細{}",
- existingInTask.getTaskCode(), param.getBarcode(), itemsWithAsnCode.size());
-
- // 鏇存柊鍏ュ簱绔欑偣淇℃伅锛堝鏋滀笌褰撳墠鐢宠鐨勭珯鐐逛笉鍚岋級
- if (StringUtils.isNotBlank(param.getSourceStaNo()) &&
- !param.getSourceStaNo().equals(existingInTask.getOrgSite())) {
- log.info("鏇存柊鍏ュ簱浠诲姟鐨勫叆搴撶珯鐐� - 浠诲姟缂栫爜锛歿}锛屽師绔欑偣锛歿}锛屾柊绔欑偣锛歿}",
- existingInTask.getTaskCode(), existingInTask.getOrgSite(), param.getSourceStaNo());
- existingInTask.setOrgSite(param.getSourceStaNo());
- if (!taskService.updateById(existingInTask)) {
- log.warn("鏇存柊鍏ュ簱浠诲姟鐨勫叆搴撶珯鐐瑰け璐� - 浠诲姟缂栫爜锛歿}", existingInTask.getTaskCode());
- }
+ // 鏇存柊鍏ュ簱绔欑偣淇℃伅锛堝鏋滀笌褰撳墠鐢宠鐨勭珯鐐逛笉鍚岋級
+ if (StringUtils.isNotBlank(param.getSourceStaNo()) &&
+ !param.getSourceStaNo().equals(existingInTask.getOrgSite())) {
+ log.info("鏇存柊鍏ュ簱浠诲姟鐨勫叆搴撶珯鐐� - 浠诲姟缂栫爜锛歿}锛屽師绔欑偣锛歿}锛屾柊绔欑偣锛歿}",
+ existingInTask.getTaskCode(), existingInTask.getOrgSite(), param.getSourceStaNo());
+ existingInTask.setOrgSite(param.getSourceStaNo());
+ if (!taskService.updateById(existingInTask)) {
+ log.warn("鏇存柊鍏ュ簱浠诲姟鐨勫叆搴撶珯鐐瑰け璐� - 浠诲姟缂栫爜锛歿}", existingInTask.getTaskCode());
}
-
- // 杩斿洖鐜版湁鍏ュ簱浠诲姟鐨勪俊鎭�
- InTaskMsgDto msgDto = new InTaskMsgDto();
- msgDto.setWorkNo(existingInTask.getTaskCode());
- msgDto.setTaskId(existingInTask.getId());
- msgDto.setLocNo(existingInTask.getTargLoc());
- msgDto.setSourceStaNo(existingInTask.getOrgSite());
- msgDto.setStaNo(existingInTask.getTargSite());
- return msgDto;
- } else {
- log.info("缁勬墭妗f病鏈変换鍔$紪鍙凤紝缁х画鍒涘缓鏂颁换鍔� - 绠卞彿锛歿}", param.getBarcode());
}
- } else {
- log.info("鏈壘鍒板尮閰嶇殑鍏朵粬鍏ュ簱浠诲姟锛岀户缁垱寤烘柊浠诲姟 - 绠卞彿锛歿}", param.getBarcode());
+
+ // 鐩存帴杩斿洖宸叉湁浠诲姟淇℃伅锛屼笉鍐嶆柊寤轰换鍔�
+ InTaskMsgDto msgDto = new InTaskMsgDto();
+ msgDto.setWorkNo(existingInTask.getTaskCode());
+ msgDto.setTaskId(existingInTask.getId());
+ msgDto.setLocNo(existingInTask.getTargLoc());
+ msgDto.setSourceStaNo(existingInTask.getOrgSite());
+ msgDto.setStaNo(existingInTask.getTargSite());
+ return msgDto;
}
+
+ log.info("鏈壘鍒拌鎵樼洏鍙峰凡鏈夊叆搴撲换鍔★紝缁х画鍒涘缓鏂颁换鍔� - 绠卞彿锛歿}", param.getBarcode());
// 鐢熸垚浠诲姟缂栫爜
String ruleCode = generateTaskCode();
@@ -439,6 +452,14 @@
if (matnrConfig == null || StringUtils.isBlank(matnrConfig.getVal())) {
return;
}
+ // 浜屾纭锛氬凡鏈夎 barcode 鐨勭粍鎵樺垯鐩存帴杩斿洖锛岀敱澶栧眰澶嶇敤锛岄伩鍏嶉噸澶嶈姹傜敓鎴愬鏉″叆搴撳崟
+ WaitPakin existing = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>()
+ .eq(WaitPakin::getBarcode, barcode)
+ .in(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_DONE.val, PakinIOStatus.PAKIN_IO_STATUS_TASK_EXCE.val));
+ if (existing != null) {
+ log.info("[RCS鍏ュ簱鐢宠-鑷姩缁勬墭] barcode={} 宸叉湁缁勬墭锛岃烦杩囪嚜鍔ㄧ粍鎵�", barcode);
+ return;
+ }
Config qtyConfig = configService.getOne(new LambdaQueryWrapper<Config>().eq(Config::getFlag, GlobalConfigCode.AUTO_PAKIN_QTY));
double autoQty = 1.0;
if (qtyConfig != null && StringUtils.isNotBlank(qtyConfig.getVal())) {
@@ -470,13 +491,15 @@
waitPakin = mobileService.mergeItems(param, 1L);
} catch (Exception e) {
log.warn("[RCS鍏ュ簱鐢宠-鑷姩缁勬墭] 缁勬墭澶辫触, barcode={}: {}", barcode, e.getMessage());
- return;
+ throw new CoolException("barcode=" + barcode + ": " + e.getMessage());
}
String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_ASN_ORDER, null);
if (StringUtils.isBlank(ruleCode)) {
log.warn("[RCS鍏ュ簱鐢宠-鑷姩缁勬墭] 鍏ュ簱鍗曠紪鐮佽鍒欐湭閰嶇疆");
return;
}
+// val orderWorkTypeOtherIn = OrderWorkType.ORDER_WORK_TYPE_OTHER_IN.type;
+ // .setWkType(orderWorkTypeOtherIn)
WkOrder order = new WkOrder();
order.setCode(ruleCode)
.setType(OrderType.ORDER_IN.type)
@@ -558,10 +581,18 @@
*/
private Task createTask(String ruleCode, String targetLoc, String barcode,
String targetSite, String sourceSiteNo, Long loginUserId) {
+ return createTask(ruleCode, targetLoc, barcode, targetSite, sourceSiteNo, loginUserId, TaskType.TASK_TYPE_IN.type);
+ }
+
+ /**
+ * 鍒涘缓骞朵繚瀛樹换鍔★紙鏀寔鎸囧畾浠诲姟绫诲瀷锛屽绌烘澘鍏ュ簱锛�
+ */
+ private Task createTask(String ruleCode, String targetLoc, String barcode,
+ String targetSite, String sourceSiteNo, Long loginUserId, Integer taskType) {
Task task = new Task();
task.setTaskCode(ruleCode)
.setTaskStatus(TaskStsType.GENERATE_IN.id)
- .setTaskType(TaskType.TASK_TYPE_IN.type)
+ .setTaskType(taskType != null ? taskType : TaskType.TASK_TYPE_IN.type)
.setWarehType(WarehType.WAREHOUSE_TYPE_CRN.val)
.setTargLoc(targetLoc)
.setBarcode(barcode)
@@ -587,6 +618,75 @@
if (!updated) {
throw new CoolException("搴撲綅棰勭害澶辫触锛侊紒");
}
+ }
+
+ /**
+ * 绌烘澘鍏ュ簱锛歊CS 鐢宠鏃� full=true锛屾棤闇�缁勬墭锛屽垎閰嶅簱浣嶅苟鍒涘缓 TASK_TYPE_EMPITY_IN 浠诲姟銆�
+ * 闇�鍦ㄨ澶囩珯鐐逛腑閰嶇疆 type=10锛堢┖鏉垮叆搴擄級鐨勭珯鐐硅矾寰勩��
+ */
+ private InTaskMsgDto createInTaskForEmptyPallet(String barcode, String staNo, Integer type) {
+ TaskInParam param = new TaskInParam();
+ param.setBarcode(barcode);
+ param.setSourceStaNo(staNo);
+ param.setLocType1(type != null ? type : 1);
+ param.setIoType(TaskType.TASK_TYPE_EMPITY_IN.type);
+ param.setUser(1L);
+
+ // 鏍¢獙璁惧绔欑偣锛堥渶閰嶇疆 type=10 绌烘澘鍏ュ簱鐨勭珯鐐癸級
+ DeviceSite deviceSite = validateDeviceSite(param);
+
+ // 妫�鏌ヨ鎵樼洏鍙锋槸鍚﹀凡鏈夌┖鏉垮叆搴撲换鍔★紝鏈夊垯澶嶇敤
+ Task existingInTask = taskService.getOne(new LambdaQueryWrapper<Task>()
+ .eq(Task::getBarcode, barcode)
+ .eq(Task::getTaskType, TaskType.TASK_TYPE_EMPITY_IN.type)
+ .orderByDesc(Task::getCreateTime)
+ .last("LIMIT 1"));
+ if (existingInTask != null) {
+ log.info("鎵惧埌璇ユ墭鐩樺彿宸叉湁绌烘澘鍏ュ簱浠诲姟锛屽鐢� - 浠诲姟缂栫爜锛歿}锛岀鍙凤細{}", existingInTask.getTaskCode(), barcode);
+ if (StringUtils.isNotBlank(staNo) && !staNo.equals(existingInTask.getOrgSite())) {
+ existingInTask.setOrgSite(staNo);
+ taskService.updateById(existingInTask);
+ }
+ InTaskMsgDto msgDto = new InTaskMsgDto();
+ msgDto.setWorkNo(existingInTask.getTaskCode());
+ msgDto.setTaskId(existingInTask.getId());
+ msgDto.setLocNo(existingInTask.getTargLoc());
+ msgDto.setSourceStaNo(existingInTask.getOrgSite());
+ msgDto.setStaNo(existingInTask.getTargSite());
+ return msgDto;
+ }
+
+ // 璇ユ墭鐩樺凡鍦ㄥ簱鎴栧嚭搴撲腑锛屼笉鍙噸澶嶇敵璇风┖鏉垮叆搴�
+ List<Loc> inStock = locService.list(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, barcode));
+ if (!inStock.isEmpty()) {
+ throw new CoolException("barcode=" + barcode + ": 璇ユ墭鐩樺凡鍦ㄥ簱锛屼笉鍙噸澶嶇敵璇峰叆搴�");
+ }
+ Task outboundTask = taskService.getOne(new LambdaQueryWrapper<Task>()
+ .eq(Task::getBarcode, barcode)
+ .in(Task::getTaskType, Arrays.asList(TaskType.TASK_TYPE_OUT.type, TaskType.TASK_TYPE_EMPITY_OUT.type,
+ TaskType.TASK_TYPE_PICK_AGAIN_OUT.type, TaskType.TASK_TYPE_CHECK_OUT.type))
+ .lt(Task::getTaskStatus, TaskStsType.COMPLETE_OUT.id));
+ if (outboundTask != null) {
+ throw new CoolException("barcode=" + barcode + ": 璇ユ墭鐩樺嚭搴撲腑鏈畬鎴愶紝涓嶅彲鐢宠鍏ュ簱");
+ }
+
+ InTaskMsgDto locNo;
+ try {
+ locNo = getLocNo(param);
+ } catch (Exception e) {
+ throw new CoolException("鑾峰彇绌烘澘鍏ュ簱搴撲綅澶辫触锛�" + e.getMessage());
+ }
+ if (locNo == null || StringUtils.isBlank(locNo.getLocNo())) {
+ throw new CoolException("鏈壘鍒板彲鐢ㄧ殑绌哄簱浣嶏紝璇锋鏌ュ簱鍖轰笌璁惧绔欑偣閰嶇疆锛堢┖鏉垮叆搴撻渶閰嶇疆 type=10 鐨勭珯鐐癸級");
+ }
+ String ruleCode = generateTaskCode();
+ String targetSite = StringUtils.isNotBlank(deviceSite.getDeviceSite()) ? deviceSite.getDeviceSite() : staNo;
+ Task task = createTask(ruleCode, locNo.getLocNo(), barcode, targetSite, staNo, param.getUser(), TaskType.TASK_TYPE_EMPITY_IN.type);
+ updateLocStatus(task.getTargLoc(), barcode);
+ locNo.setWorkNo(ruleCode);
+ locNo.setTaskId(task.getId());
+ log.info("[绌烘澘鍏ュ簱] 宸插垱寤轰换鍔�: {}, 搴撲綅: {}, 鏂欑: {}", ruleCode, locNo.getLocNo(), barcode);
+ return locNo;
}
/**
@@ -1456,9 +1556,19 @@
*/
@Override
@Transactional(rollbackFor = Exception.class)
- public R allocateLocation(String barcode, String staNo, Integer type) {
+ public R allocateLocation(String barcode, String staNo, Integer type, Boolean full) {
log.info("========== 寮�濮嬬敵璇峰叆搴撲换鍔★紝鍒嗛厤搴撲綅 ==========");
- log.info("鏂欑鐮侊細{}锛屽叆搴撶珯鐐癸細{}锛屽叆搴撶被鍨嬶細{}", barcode, staNo, type);
+ log.info("鏂欑鐮侊細{}锛屽叆搴撶珯鐐癸細{}锛屽叆搴撶被鍨嬶細{}锛岀┖鏉匡細{}", barcode, staNo, type, full);
+
+ // full=true 鏃惰蛋绌烘澘鍏ュ簱锛堟棤闇�缁勬墭锛夛紱鍚﹀垯璧版櫘閫氬叆搴擄紙闇�缁勬墭鎴栬嚜鍔ㄧ粍鎵橈級
+ if (Boolean.TRUE.equals(full)) {
+ InTaskMsgDto msgDto = createInTaskForEmptyPallet(barcode, staNo, type);
+ JSONObject result = new JSONObject();
+ result.put("locNo", msgDto.getLocNo());
+ result.put("batchNo", msgDto.getWorkNo());
+ result.put("taskNo", msgDto.getWorkNo());
+ return R.ok(result);
+ }
// 鏋勫缓 TaskInParam 鍙傛暟锛屼笌 /wcs/create/in/task 鎺ュ彛鍙傛暟涓�鑷�
TaskInParam param = new TaskInParam();
--
Gitblit v1.9.1