From 8168aef3c7557c9e1361892270a1ebe35dbddba5 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 10 十一月 2026 11:42:19 +0800
Subject: [PATCH] refactor(erp): 采购申请与询价比价流程重构

---
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java |   71 +++++++++++++++++++++++++++++------
 1 files changed, 58 insertions(+), 13 deletions(-)

diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java
index e1f91d4..3e77826 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java
@@ -136,15 +136,16 @@
             accountService.validateAccount(createReqVO.getAccountId());
         }
         // 1.4 鐢熸垚璁㈠崟鍙凤紝骞舵牎楠屽敮涓�鎬�
-        String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_ORDER_NO_PREFIX);
-        if (purchaseOrderMapper.selectByNo(no) != null) {
-            throw exception(PURCHASE_ORDER_NO_EXISTS);
-        }
+        String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_ORDER_NO_PREFIX,
+                candidate -> purchaseOrderMapper.selectByNo(candidate) != null);
 
         // 2.1 鎻掑叆璁㈠崟锛坰ubmit=false 鏃朵繚瀛樹负鑽夌锛岀瓑寰呬笟鍔$‘璁ゅ悗鎵嬪姩鎻愪氦瀹℃壒锛�
         ErpPurchaseOrderDO purchaseOrder = BeanUtils.toBean(createReqVO, ErpPurchaseOrderDO.class, in -> in
                 .setNo(no).setStatus(submit ? ErpAuditStatus.PROCESS.getStatus() : ErpAuditStatus.DRAFT.getStatus())
                 .setInCount(BigDecimal.ZERO).setInStatus(ErpPurchaseOrderInStatusEnum.NOT_IN.getStatus()));
+        if (purchaseOrder.getDepositPrice() == null) {
+            purchaseOrder.setDepositPrice(BigDecimal.ZERO);
+        }
         calculateTotalPrice(purchaseOrder, purchaseOrderItems);
         purchaseOrderMapper.insert(purchaseOrder);
         // 2.2 鎻掑叆璁㈠崟椤�
@@ -184,6 +185,9 @@
 
         // 2.1 鏇存柊璁㈠崟
         ErpPurchaseOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpPurchaseOrderDO.class);
+        if (updateObj.getDepositPrice() == null) {
+            updateObj.setDepositPrice(BigDecimal.ZERO);
+        }
         calculateTotalPrice(updateObj, purchaseOrderItems);
         purchaseOrderMapper.updateById(updateObj);
         // 2.2 鏇存柊璁㈠崟椤�
@@ -301,10 +305,15 @@
         }
 
         // 3. 鍗曞彿锛氬~浜嗗氨鐢紙鏍¢獙鍞竴锛夛紝娌″~鑷姩鐢熸垚
-        String no = StrUtil.isNotBlank(head.getNo()) ? head.getNo().trim()
-                : noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_ORDER_NO_PREFIX);
-        if (purchaseOrderMapper.selectByNo(no) != null) {
-            throw new IllegalArgumentException("閲囪喘鍗曠紪鍙峰凡瀛樺湪锛�" + no);
+        String no;
+        if (StrUtil.isNotBlank(head.getNo())) {
+            no = head.getNo().trim();
+            if (purchaseOrderMapper.selectByNo(no) != null) {
+                throw new IllegalArgumentException("閲囪喘鍗曠紪鍙峰凡瀛樺湪锛�" + no);
+            }
+        } else {
+            no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_ORDER_NO_PREFIX,
+                    candidate -> purchaseOrderMapper.selectByNo(candidate) != null);
         }
 
         // 4. 缁勮涓昏〃锛氬嬀閫夆�滄槸鍚﹀鏍糕�� => 宸插鏍�(20)锛屽惁鍒欐湭瀹℃牳(10)
@@ -444,6 +453,43 @@
         }
     }
 
+    /**
+     * 鎻愪氦瀹℃壒鍓嶆牎楠岄噰璐彴璐︽暟鎹槸鍚﹀凡琛ラ綈
+     *
+     * <p>閲囪喘鐢宠鐩存帴鐢熸垚鐨勫彴璐﹀彧鏈夌墿鏂欎笌鏁伴噺锛堥浂閲戦銆佹棤渚涘簲鍟嗭級锛�
+     * 閲囪喘鍛橀渶瑕佸湪鍙拌处閲岃ˉ褰曚緵搴斿晢銆佸崟浠枫�佷粯娆炬棩鏈熷悗鎵嶈兘鎻愪氦瀹℃壒銆傞�愰」鏍¢獙锛屽懡涓涓�澶勫嵆鎻愮ず鍏蜂綋鎬庝箞鏀广��</p>
+     *
+     * @param purchaseOrder 閲囪喘鍙拌处
+     */
+    private void validatePurchaseOrderReadyForSubmit(ErpPurchaseOrderDO purchaseOrder) {
+        // 2.1 渚涘簲鍟嗗繀閫�
+        if (purchaseOrder.getSupplierId() == null) {
+            throw exception(PURCHASE_ORDER_SUBMIT_SUPPLIER_REQUIRED, purchaseOrder.getNo());
+        }
+        // 2.2 浠樻鏃ユ湡蹇呴�夛細閲囪喘鐢宠鑷姩鐢熸垚鐨勮崏绋胯鍗曟病鏈変粯娆炬棩鏈�
+        if (purchaseOrder.getPaymentDate() == null) {
+            throw exception(PURCHASE_ORDER_PAYMENT_DATE_REQUIRED);
+        }
+        // 2.3 鏄庣粏鍗曚环蹇呴』琛ュ綍锛堝ぇ浜� 0锛�
+        List<ErpPurchaseOrderItemDO> items = purchaseOrderItemMapper.selectListByOrderId(purchaseOrder.getId());
+        if (CollUtil.isEmpty(items)) {
+            throw exception(PURCHASE_ORDER_SUBMIT_ITEM_REQUIRED, purchaseOrder.getNo());
+        }
+        Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
+                convertSet(items, ErpPurchaseOrderItemDO::getProductId));
+        for (ErpPurchaseOrderItemDO item : items) {
+            BigDecimal productPrice = item.getProductPrice();
+            if (productPrice != null && productPrice.compareTo(BigDecimal.ZERO) > 0) {
+                continue;
+            }
+            MdmItemRespDTO itemDTO = itemMap.get(item.getProductId());
+            String itemName = itemDTO != null && StrUtil.isNotBlank(itemDTO.getName())
+                    ? itemDTO.getName() : "ID=" + item.getProductId();
+            throw exception(PURCHASE_ORDER_SUBMIT_PRICE_REQUIRED, itemName,
+                    productPrice == null ? "鏈~鍐�" : productPrice.toPlainString());
+        }
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void submitPurchaseOrder(Long id, String processDefinitionKey, Long userId) {
@@ -454,10 +500,9 @@
         if (!submitable) {
             throw exception(PURCHASE_ORDER_SUBMIT_FAIL_STATUS);
         }
-        // 2. 浠樻鏃ユ湡蹇呴�夛細閲囪喘鐢宠鑷姩鐢熸垚鐨勮崏绋胯鍗曟病鏈変粯娆炬棩鏈燂紝鎻愪氦鍓嶅繀椤诲厛缂栬緫琛ラ綈
-        if (purchaseOrder.getPaymentDate() == null) {
-            throw exception(PURCHASE_ORDER_PAYMENT_DATE_REQUIRED);
-        }
+        // 2. 鎻愪氦鍓嶆牎楠屽彴璐︽暟鎹凡琛ラ綈锛氶噰璐敵璇风洿鎺ョ敓鎴愮殑鑽夌鍙湁鐗╂枡涓庢暟閲忥紝
+        //    渚涘簲鍟嗐�佸崟浠风瓑闇�瑕侀噰璐憳鍦ㄥ彴璐︿腑琛ュ綍鍚庢墠鑳芥彁浜ゅ鎵�
+        validatePurchaseOrderReadyForSubmit(purchaseOrder);
 
         // 3. 鍒涘缓 BPM 娴佺▼瀹炰緥
         // 鍏ㄥ眬鍏嶅鎵癸細涓氬姟鏍¢獙閫氳繃鍚庣洿鎺ユ墽琛屽鎵归�氳繃閫昏緫锛屾棤闇�娴佺▼妯″瀷銆�
@@ -893,4 +938,4 @@
         return arrivalNoticeId;
     }
 
-}
\ No newline at end of file
+}

--
Gitblit v1.9.3