From c32f684ccad74f2df04cac71f55ec4d4ef6d1712 Mon Sep 17 00:00:00 2001
From: chen.llin <1442464845@qq.comm>
Date: 星期六, 27 十二月 2025 17:00:41 +0800
Subject: [PATCH] 越库功能单独封装,并且融入入库单新增

---
 src/main/java/com/zy/asrs/service/CrossDockService.java          |   32 +++++
 src/main/java/com/zy/asrs/controller/OrderPakinController.java   |   12 ++
 src/main/java/com/zy/asrs/service/impl/CrossDockServiceImpl.java |  301 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 345 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/zy/asrs/controller/OrderPakinController.java b/src/main/java/com/zy/asrs/controller/OrderPakinController.java
index 5dc404f..62d7fbf 100644
--- a/src/main/java/com/zy/asrs/controller/OrderPakinController.java
+++ b/src/main/java/com/zy/asrs/controller/OrderPakinController.java
@@ -12,6 +12,7 @@
 import com.zy.asrs.entity.result.WrkTraceVo;
 import com.zy.asrs.service.*;
 import com.zy.common.model.DetlDto;
+import com.zy.common.properties.CrossDockProperties;
 import com.zy.common.web.BaseController;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -44,6 +45,10 @@
     private WrkMastLogService wrkMastLogService;
     @Autowired
     private ClientService clientService;
+    @Autowired
+    private CrossDockService crossDockService;
+    @Autowired
+    private CrossDockProperties crossDockProperties;
 
     @RequestMapping(value = "/order/list/pda/page/auth")
     @ManagerAuth
@@ -206,6 +211,13 @@
                 }
             }
         }
+        
+        // 瓒婂簱鍔熻兘锛氬鏋滄槸瓒婂簱鍏ュ簱鍗曪紝璋冪敤瓒婂簱鏈嶅姟澶勭悊
+        if (param.getDocType() != null && param.getDocType().equals(crossDockProperties.getInboundDocTypeId())) {
+            String outOrderNo = crossDockService.processCrossDockInbound(order, param, getUserId());
+            return R.ok("瓒婂簱鍏ュ簱鍗曞垱寤烘垚鍔燂紝宸茶嚜鍔ㄧ敓鎴愯秺搴撳嚭搴撳崟锛�" + outOrderNo);
+        }
+        
         return R.ok("璁㈠崟娣诲姞鎴愬姛");
     }
 
diff --git a/src/main/java/com/zy/asrs/service/CrossDockService.java b/src/main/java/com/zy/asrs/service/CrossDockService.java
new file mode 100644
index 0000000..2aa022b
--- /dev/null
+++ b/src/main/java/com/zy/asrs/service/CrossDockService.java
@@ -0,0 +1,32 @@
+package com.zy.asrs.service;
+
+import com.zy.asrs.entity.OrderPakin;
+import com.zy.asrs.entity.param.OrderDomainParam;
+
+/**
+ * 瓒婂簱鏈嶅姟鎺ュ彛
+ * 鐢ㄤ簬澶勭悊瓒婂簱鍏ュ簱鍗曠殑鍒涘缓銆佸簱瀛樼鐞嗗拰鑷姩鐢熸垚瓒婂簱鍑哄簱鍗�
+ * 
+ * @author system
+ */
+public interface CrossDockService {
+
+    /**
+     * 澶勭悊瓒婂簱鍏ュ簱鍗�
+     * 
+     * 鍔熻兘璇存槑锛�
+     * 1. 灏嗗叆搴撳崟鐘舵�佽缃负宸蹭笂鎶ワ紙璺宠繃ERP涓婃姤娴佺▼锛�
+     * 2. 鏇存柊鏄庣粏瀹屾垚鏁伴噺
+     * 3. 鍦ㄨ櫄鎷熷簱浣嶅垱寤哄簱瀛樻槑缁嗚褰�
+     * 4. 鑷姩鐢熸垚瀵瑰簲鐨勮秺搴撳嚭搴撳崟
+     * 5. 浠庤櫄鎷熷簱浣嶆墸鍑忓簱瀛�
+     * 
+     * @param order 鍏ュ簱鍗曞璞�
+     * @param param 璁㈠崟鍙傛暟锛堝寘鍚槑缁嗕俊鎭級
+     * @param userId 鎿嶄綔浜篒D
+     * @return 鐢熸垚鐨勫嚭搴撳崟缂栧彿
+     * @throws com.core.exception.CoolException 澶勭悊澶辫触鏃舵姏鍑哄紓甯�
+     */
+    String processCrossDockInbound(OrderPakin order, OrderDomainParam param, Long userId);
+}
+
diff --git a/src/main/java/com/zy/asrs/service/impl/CrossDockServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/CrossDockServiceImpl.java
new file mode 100644
index 0000000..fa50be8
--- /dev/null
+++ b/src/main/java/com/zy/asrs/service/impl/CrossDockServiceImpl.java
@@ -0,0 +1,301 @@
+package com.zy.asrs.service.impl;
+
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.core.common.SnowflakeIdWorker;
+import com.core.exception.CoolException;
+import com.zy.asrs.entity.*;
+import com.zy.asrs.entity.param.OrderDomainParam;
+import com.zy.asrs.service.*;
+import com.zy.common.properties.CrossDockProperties;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 瓒婂簱鏈嶅姟瀹炵幇绫�
+ * 
+ * 鍔熻兘璇存槑锛�
+ * - 瓒婂簱鍏ュ簱锛氳揣鐗╀笉杩涘叆瀹為檯搴撲綅锛岀洿鎺ラ�氳繃铏氭嫙搴撲綅瀹屾垚鍏ュ簱鍜屽嚭搴撴祦绋�
+ * - 涓嶈蛋澶栭儴璁惧锛氳烦杩嘩CS绛夊閮ㄧ郴缁熻皟鐢�
+ * - 涓嶈蛋ERP涓婃姤锛氱洿鎺ヨ缃负宸蹭笂鎶ョ姸鎬侊紝璺宠繃ERP鍚屾
+ * 
+ * @author system
+ */
+@Slf4j
+@Service("crossDockService")
+public class CrossDockServiceImpl implements CrossDockService {
+
+    @Autowired
+    private OrderPakinService orderPakinService;
+    @Autowired
+    private OrderDetlPakinService orderDetlPakinService;
+    @Autowired
+    private OrderPakoutService orderPakoutService;
+    @Autowired
+    private OrderDetlPakoutService orderDetlPakoutService;
+    @Autowired
+    private DocTypeService docTypeService;
+    @Autowired
+    private LocDetlService locDetlService;
+    @Autowired
+    private MatService matService;
+    @Autowired
+    private ClientService clientService;
+    @Autowired
+    private SnowflakeIdWorker snowflakeIdWorker;
+    @Autowired
+    private CrossDockProperties crossDockProperties;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public String processCrossDockInbound(OrderPakin order, OrderDomainParam param, Long userId) {
+        log.info("寮�濮嬪鐞嗚秺搴撳叆搴撳崟锛岃鍗曞彿锛歿}", order.getOrderNo());
+        
+        Date now = new Date();
+        
+        // 姝ラ1锛氳缃叆搴撳崟涓哄凡涓婃姤鐘舵�侊紙璺宠繃ERP涓婃姤娴佺▼锛�
+        log.info("姝ラ1锛氳缃叆搴撳崟[{}]涓哄凡涓婃姤鐘舵��", order.getOrderNo());
+        if (!orderPakinService.updateSettle(order.getId(), 6L, userId)) {
+            throw new CoolException("璁剧疆鍏ュ簱鍗曚负宸蹭笂鎶ョ姸鎬佸け璐�");
+        }
+        
+        // 姝ラ2锛氭洿鏂版槑缁嗗畬鎴愭暟閲忓苟鍒涘缓铏氭嫙搴撲綅搴撳瓨
+        log.info("姝ラ2锛氭洿鏂版槑缁嗗畬鎴愭暟閲忓苟鍒涘缓铏氭嫙搴撲綅搴撳瓨");
+        List<OrderDetlPakin> orderDetls = orderDetlPakinService.selectList(
+            new EntityWrapper<OrderDetlPakin>().eq("order_id", order.getId()));
+        
+        for (OrderDetlPakin orderDetl : orderDetls) {
+            // 2.1 鏇存柊瀹屾垚鏁伴噺
+            orderDetl.setQty(orderDetl.getAnfme());
+            orderDetl.setUpdateBy(userId);
+            orderDetl.setUpdateTime(now);
+            if (!orderDetlPakinService.updateById(orderDetl)) {
+                throw new CoolException("鏇存柊璁㈠崟鏄庣粏瀹屾垚鏁伴噺澶辫触锛岀墿鏂欙細" + orderDetl.getMatnr());
+            }
+            
+            // 2.2 鍒涘缓鎴栨洿鏂拌櫄鎷熷簱浣嶅簱瀛�
+            createOrUpdateVirtualLocationStock(order, orderDetl, userId, now);
+        }
+        
+        // 姝ラ3锛氳幏鍙栬秺搴撳嚭搴撳崟绫诲瀷
+        Long outboundDocTypeId = crossDockProperties.getOutboundDocTypeId();
+        log.info("姝ラ3锛氳幏鍙栬秺搴撳嚭搴撳崟绫诲瀷锛宒ocId={}", outboundDocTypeId);
+        DocType crossDockOutDocType = docTypeService.selectById(outboundDocTypeId);
+        if (crossDockOutDocType == null) {
+            throw new CoolException("瓒婂簱鍑哄簱鍗曠被鍨嬩笉瀛樺湪锛宒ocId=" + outboundDocTypeId);
+        }
+        
+        // 姝ラ4锛氬垱寤鸿秺搴撳嚭搴撳崟涓绘。
+        log.info("姝ラ4锛氬垱寤鸿秺搴撳嚭搴撳崟涓绘。");
+        String outOrderNo = "CK" + snowflakeIdWorker.nextId();
+        OrderPakout outOrder = createCrossDockOutboundOrder(
+            order, param, crossDockOutDocType, outOrderNo, userId, now);
+        
+        if (!orderPakoutService.insert(outOrder)) {
+            throw new CoolException("鍒涘缓瓒婂簱鍑哄簱鍗曞け璐�");
+        }
+        log.info("瓒婂簱鍑哄簱鍗曞垱寤烘垚鍔燂紝鍑哄簱鍗曞彿锛歿}", outOrderNo);
+        
+        // 姝ラ5锛氬垱寤哄嚭搴撳崟鏄庣粏骞舵墸鍑忚櫄鎷熷簱浣嶅簱瀛�
+        log.info("姝ラ5锛氬垱寤哄嚭搴撳崟鏄庣粏骞舵墸鍑忚櫄鎷熷簱浣嶅簱瀛�");
+        for (OrderDetlPakin orderDetl : orderDetls) {
+            // 5.1 鍒涘缓鍑哄簱鍗曟槑缁�
+            createOutboundOrderDetail(outOrder, orderDetl, outOrderNo, userId, now);
+            
+            // 5.2 浠庤櫄鎷熷簱浣嶆墸鍑忓簱瀛�
+            reduceVirtualLocationStock(orderDetl, userId);
+        }
+        
+        log.info("瓒婂簱鍏ュ簱鍗曞鐞嗗畬鎴愶紝鍏ュ簱鍗曞彿锛歿}锛屽嚭搴撳崟鍙凤細{}", order.getOrderNo(), outOrderNo);
+        return outOrderNo;
+    }
+
+    /**
+     * 鍒涘缓鎴栨洿鏂拌櫄鎷熷簱浣嶅簱瀛�
+     * 
+     * @param order 鍏ュ簱鍗�
+     * @param orderDetl 璁㈠崟鏄庣粏
+     * @param userId 鎿嶄綔浜篒D
+     * @param now 褰撳墠鏃堕棿
+     */
+    private void createOrUpdateVirtualLocationStock(OrderPakin order, OrderDetlPakin orderDetl, 
+                                                    Long userId, Date now) {
+        log.debug("澶勭悊铏氭嫙搴撲綅搴撳瓨锛岀墿鏂欙細{}锛屾壒娆★細{}锛屾暟閲忥細{}", 
+            orderDetl.getMatnr(), orderDetl.getBatch(), orderDetl.getAnfme());
+        
+        // 鏌ヨ鐗╂枡淇℃伅
+        Mat mat = matService.selectByMatnr(orderDetl.getMatnr());
+        if (mat == null) {
+            throw new CoolException("鐗╂枡涓嶅瓨鍦細" + orderDetl.getMatnr());
+        }
+        
+        // 鏌ヨ铏氭嫙搴撲綅鏄惁宸叉湁璇ョ墿鏂欏簱瀛�
+        String virtualLocNo = crossDockProperties.getVirtualLocationNo();
+        LocDetl locDetl = locDetlService.selectItem(
+            virtualLocNo, orderDetl.getMatnr(), orderDetl.getBatch(), orderDetl.getBrand(),
+            orderDetl.getStandby1(), orderDetl.getStandby2(), orderDetl.getStandby3(),
+            orderDetl.getBoxType1(), orderDetl.getBoxType2(), orderDetl.getBoxType3());
+        
+        if (locDetl != null) {
+            // 濡傛灉宸插瓨鍦紝澧炲姞鏁伴噺
+            log.debug("铏氭嫙搴撲綅宸插瓨鍦ㄨ鐗╂枡搴撳瓨锛屽鍔犳暟閲忥細{}", orderDetl.getAnfme());
+            if (!locDetlService.updateAnfme(
+                locDetl.getAnfme() + orderDetl.getAnfme(),
+                virtualLocNo, orderDetl.getMatnr(), orderDetl.getBatch(), orderDetl.getBrand(),
+                orderDetl.getStandby1(), orderDetl.getStandby2(), orderDetl.getStandby3(),
+                orderDetl.getBoxType1(), orderDetl.getBoxType2(), orderDetl.getBoxType3())) {
+                throw new CoolException("鏇存柊铏氭嫙搴撲綅搴撳瓨澶辫触锛岀墿鏂欙細" + orderDetl.getMatnr());
+            }
+        } else {
+            // 鍒涘缓鏂扮殑搴撳瓨鏄庣粏
+            log.debug("鍒涘缓鏂扮殑铏氭嫙搴撲綅搴撳瓨璁板綍");
+            locDetl = new LocDetl();
+            BeanUtils.copyProperties(mat, locDetl);
+            locDetl.setBatch(orderDetl.getBatch());
+            locDetl.setBrand(orderDetl.getBrand());
+            locDetl.setStandby1(orderDetl.getStandby1());
+            locDetl.setStandby2(orderDetl.getStandby2());
+            locDetl.setStandby3(orderDetl.getStandby3());
+            locDetl.setBoxType1(orderDetl.getBoxType1());
+            locDetl.setBoxType2(orderDetl.getBoxType2());
+            locDetl.setBoxType3(orderDetl.getBoxType3());
+            locDetl.setLocNo(virtualLocNo);
+            locDetl.setZpallet("VIRTUAL-" + order.getOrderNo());
+            locDetl.setAnfme(orderDetl.getAnfme());
+            locDetl.setOrderNo(order.getOrderNo());
+            locDetl.setModiUser(userId);
+            locDetl.setModiTime(now);
+            locDetl.setAppeUser(userId);
+            locDetl.setAppeTime(now);
+            if (!locDetlService.insert(locDetl)) {
+                throw new CoolException("鍒涘缓铏氭嫙搴撲綅搴撳瓨澶辫触锛岀墿鏂欙細" + orderDetl.getMatnr());
+            }
+        }
+    }
+
+    /**
+     * 鍒涘缓瓒婂簱鍑哄簱鍗曚富妗�
+     * 
+     * @param inOrder 鍏ュ簱鍗�
+     * @param param 璁㈠崟鍙傛暟
+     * @param docType 鍑哄簱鍗曠被鍨�
+     * @param outOrderNo 鍑哄簱鍗曠紪鍙�
+     * @param userId 鎿嶄綔浜篒D
+     * @param now 褰撳墠鏃堕棿
+     * @return 鍑哄簱鍗曞璞�
+     */
+    private OrderPakout createCrossDockOutboundOrder(OrderPakin inOrder, OrderDomainParam param,
+                                                     DocType docType, String outOrderNo,
+                                                     Long userId, Date now) {
+        // 鑾峰彇瀹㈡埛淇℃伅
+        Client client = clientService.selectOne(
+            new EntityWrapper<Client>().eq("name", param.getCstmrName()));
+        if (client == null) {
+            throw new CoolException("瀹㈡埛涓嶅瓨鍦細" + param.getCstmrName());
+        }
+        
+        return new OrderPakout(
+            String.valueOf(snowflakeIdWorker.nextId()),
+            outOrderNo,
+            param.getOrderTime(),
+            docType.getDocId(),
+            null, // itemId
+            null, // itemName
+            null, // allotItemId
+            null, // defNumber
+            null, // number
+            client.getCode(), // cstmr
+            client.getName(), // cstmrName
+            null, // tel
+            null, // operMemb
+            null, // totalFee
+            null, // discount
+            null, // discountFee
+            null, // otherFee
+            null, // actFee
+            null, // payType
+            null, // salesman
+            null, // accountDay
+            null, // postFeeType
+            null, // postFee
+            null, // payTime
+            null, // sendTime
+            null, // shipName
+            null, // shipCode
+            6L, // settle - 鐩存帴璁剧疆涓哄凡涓婃姤鐘舵�侊紝璺宠繃ERP涓婃姤娴佺▼
+            1, // status
+            userId, // createBy
+            now, // createTime
+            userId, // updateBy
+            now, // updateTime
+            "瓒婂簱鍑哄簱鍗曪紝鍏宠仈鍏ュ簱鍗曪細" + inOrder.getOrderNo() // memo
+        );
+    }
+
+    /**
+     * 鍒涘缓鍑哄簱鍗曟槑缁�
+     * 
+     * @param outOrder 鍑哄簱鍗�
+     * @param inDetl 鍏ュ簱鍗曟槑缁�
+     * @param outOrderNo 鍑哄簱鍗曠紪鍙�
+     * @param userId 鎿嶄綔浜篒D
+     * @param now 褰撳墠鏃堕棿
+     */
+    private void createOutboundOrderDetail(OrderPakout outOrder, OrderDetlPakin inDetl,
+                                          String outOrderNo, Long userId, Date now) {
+        OrderDetlPakout outDetl = new OrderDetlPakout();
+        BeanUtils.copyProperties(inDetl, outDetl);
+        outDetl.setId(null); // 娓呴櫎ID锛岃鏁版嵁搴撹嚜鍔ㄧ敓鎴�
+        outDetl.setOrderId(outOrder.getId());
+        outDetl.setOrderNo(outOrderNo);
+        outDetl.setQty(inDetl.getAnfme()); // 瀹屾垚鏁伴噺绛変簬鐢宠鏁伴噺
+        outDetl.setWorkQty(inDetl.getAnfme());
+        outDetl.setCreateBy(userId);
+        outDetl.setCreateTime(now);
+        outDetl.setUpdateBy(userId);
+        outDetl.setUpdateTime(now);
+        outDetl.setStatus(1);
+        if (!orderDetlPakoutService.insert(outDetl)) {
+            throw new CoolException("鍒涘缓鍑哄簱鍗曟槑缁嗗け璐ワ紝鐗╂枡锛�" + inDetl.getMatnr());
+        }
+    }
+
+    /**
+     * 浠庤櫄鎷熷簱浣嶆墸鍑忓簱瀛�
+     * 
+     * @param orderDetl 璁㈠崟鏄庣粏
+     * @param userId 鎿嶄綔浜篒D
+     */
+    private void reduceVirtualLocationStock(OrderDetlPakin orderDetl, Long userId) {
+        log.debug("浠庤櫄鎷熷簱浣嶆墸鍑忓簱瀛橈紝鐗╂枡锛歿}锛屾壒娆★細{}锛屾暟閲忥細{}", 
+            orderDetl.getMatnr(), orderDetl.getBatch(), orderDetl.getAnfme());
+        
+        String virtualLocNo = crossDockProperties.getVirtualLocationNo();
+        LocDetl virtualLocDetl = locDetlService.selectItem(
+            virtualLocNo, orderDetl.getMatnr(), orderDetl.getBatch(), orderDetl.getBrand(),
+            orderDetl.getStandby1(), orderDetl.getStandby2(), orderDetl.getStandby3(),
+            orderDetl.getBoxType1(), orderDetl.getBoxType2(), orderDetl.getBoxType3());
+        
+        if (virtualLocDetl != null) {
+            double newQty = virtualLocDetl.getAnfme() - orderDetl.getAnfme();
+            // 浣跨敤 updateAnfme 鏂规硶锛屽綋鏁伴噺<=0鏃朵細鑷姩鍒犻櫎璁板綍
+            if (!locDetlService.updateAnfme(
+                newQty,
+                virtualLocNo, orderDetl.getMatnr(), orderDetl.getBatch(), orderDetl.getBrand(),
+                orderDetl.getStandby1(), orderDetl.getStandby2(), orderDetl.getStandby3(),
+                orderDetl.getBoxType1(), orderDetl.getBoxType2(), orderDetl.getBoxType3())) {
+                throw new CoolException("鎵e噺铏氭嫙搴撲綅搴撳瓨澶辫触锛岀墿鏂欙細" + orderDetl.getMatnr());
+            }
+            log.debug("铏氭嫙搴撲綅搴撳瓨鎵e噺瀹屾垚锛屽墿浣欐暟閲忥細{}", newQty);
+        } else {
+            log.warn("铏氭嫙搴撲綅鏈壘鍒板搴斿簱瀛樿褰曪紝鐗╂枡锛歿}锛屾壒娆★細{}", 
+                orderDetl.getMatnr(), orderDetl.getBatch());
+        }
+    }
+}
+

--
Gitblit v1.9.1