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-srm/src/main/java/cn/iocoder/yudao/module/srm/service/inquiry/SrmInquiryServiceImpl.java |  136 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 136 insertions(+), 0 deletions(-)

diff --git a/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/inquiry/SrmInquiryServiceImpl.java b/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/inquiry/SrmInquiryServiceImpl.java
index a750fba..2761cf4 100644
--- a/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/inquiry/SrmInquiryServiceImpl.java
+++ b/yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/inquiry/SrmInquiryServiceImpl.java
@@ -11,8 +11,10 @@
 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
 import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
 import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi;
+import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseRequestApi;
 import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderCreateReqDTO;
 import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderRespDTO;
+import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseRequestRespDTO;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
 import cn.iocoder.yudao.module.mdm.api.unit.MdmUnitMeasureApi;
@@ -49,6 +51,11 @@
 
     private static final DateTimeFormatter NO_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyyMM");
 
+    /**
+     * 閲囪喘鐢宠銆屽鏍搁�氳繃銆嶇姸鎬佸�硷紝涓� ERP 妯″潡 ErpPurchaseRequestStatusEnum.APPROVE 淇濇寔涓�鑷�
+     */
+    private static final Integer PURCHASE_REQUEST_STATUS_APPROVED = 20;
+
     @Resource
     private SrmInquiryMapper inquiryMapper;
     @Resource
@@ -69,6 +76,8 @@
     private MdmUnitMeasureApi mdmUnitMeasureApi;
     @Resource
     private ErpPurchaseOrderApi erpPurchaseOrderApi;
+    @Resource
+    private ErpPurchaseRequestApi erpPurchaseRequestApi;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -90,6 +99,73 @@
                 createReqVO.getSuppliers().stream()
                         .map(SrmInquirySaveReqVO.Supplier::getSupplierId)
                         .collect(Collectors.toSet()));
+        return inquiry.getId();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long createInquiryFromPurchaseRequest(Long purchaseRequestId) {
+        ErpPurchaseRequestRespDTO purchaseRequest = erpPurchaseRequestApi
+                .getPurchaseRequest(purchaseRequestId).getCheckedData();
+        if (purchaseRequest == null) {
+            throw ServiceExceptionUtil.exception(ErrorCodeConstants.INQUIRY_PURCHASE_REQUEST_NOT_EXISTS);
+        }
+        if (!PURCHASE_REQUEST_STATUS_APPROVED.equals(purchaseRequest.getStatus())) {
+            throw new ServiceException(ErrorCodeConstants.INQUIRY_PURCHASE_REQUEST_NOT_APPROVED.getCode(),
+                    "閲囪喘鐢宠銆�" + purchaseRequest.getNo() + "銆戝綋鍓嶇姸鎬佷笉鏄�屽鏍搁�氳繃銆嶏紝鏃犳硶鍙戣捣璇环銆�"
+                            + "璇峰厛鍦ㄩ噰璐敵璇蜂腑瀹屾垚瀹℃壒锛屽鎵归�氳繃鍚庡啀鍙戣捣璇环銆�");
+        }
+        if (purchaseRequest.getOrderId() != null) {
+            throw new ServiceException(ErrorCodeConstants.INQUIRY_PURCHASE_REQUEST_HAS_ORDER.getCode(),
+                    "閲囪喘鐢宠銆�" + purchaseRequest.getNo() + "銆戝凡鐢熸垚閲囪喘鍙拌处銆�"
+                            + StrUtil.blankToDefault(purchaseRequest.getOrderNo(), "ID=" + purchaseRequest.getOrderId())
+                            + "銆戯紝鏃犳硶鍐嶅彂璧疯浠枫�傝鍒伴噰璐彴璐︿腑鏌ョ湅浠锋牸鏄庣粏銆�");
+        }
+        SrmInquiryDO linkedInquiry = purchaseRequest.getInquiryId() != null
+                ? inquiryMapper.selectById(purchaseRequest.getInquiryId()) : null;
+        if (linkedInquiry != null
+                && !InquiryStatusEnum.CANCELLED.getStatus().equals(linkedInquiry.getStatus())) {
+            throw new ServiceException(ErrorCodeConstants.INQUIRY_PURCHASE_REQUEST_HAS_INQUIRY.getCode(),
+                    "閲囪喘鐢宠銆�" + purchaseRequest.getNo() + "銆戝凡鍙戣捣杩囪浠枫��"
+                            + StrUtil.blankToDefault(purchaseRequest.getInquiryNo(), "ID=" + purchaseRequest.getInquiryId())
+                            + "銆戯紝璇风洿鎺ユ墦寮�璇ヨ浠峰崟缁х画澶勭悊锛屼笉瑕侀噸澶嶅彂璧枫��");
+        }
+        List<ErpPurchaseRequestRespDTO.Item> requestItems = purchaseRequest.getItems();
+        if (CollUtil.isEmpty(requestItems)) {
+            throw new ServiceException(ErrorCodeConstants.INQUIRY_PURCHASE_REQUEST_ITEM_EMPTY.getCode(),
+                    "閲囪喘鐢宠銆�" + purchaseRequest.getNo() + "銆戞病鏈夋槑缁嗚锛屾棤娉曞彂璧疯浠枫�傝鍥炲埌閲囪喘鐢宠琛ュ厖鏄庣粏鍚庡啀璇曘��");
+        }
+
+        SrmInquiryDO inquiry = new SrmInquiryDO();
+        inquiry.setNo(generateInquiryNo());
+        inquiry.setTitle("閲囪喘鐢宠銆�" + purchaseRequest.getNo() + "銆戣浠�");
+        inquiry.setStatus(InquiryStatusEnum.DRAFT.getStatus());
+        inquiry.setInquiryDate(LocalDate.now());
+        inquiry.setPurchaserUserId(getLoginUserId());
+        inquiry.setRemark("鐢遍噰璐敵璇枫��" + purchaseRequest.getNo() + "銆戝彂璧�");
+        inquiry.setPurchaseRequestId(purchaseRequest.getId());
+        inquiry.setPurchaseRequestNo(purchaseRequest.getNo());
+        inquiryMapper.insert(inquiry);
+
+        List<SrmInquirySaveReqVO.Item> itemVOs = new ArrayList<>();
+        Set<Long> productIds = new HashSet<>();
+        for (ErpPurchaseRequestRespDTO.Item requestItem : requestItems) {
+            if (!productIds.add(requestItem.getProductId())) {
+                throw new ServiceException(ErrorCodeConstants.INQUIRY_PURCHASE_REQUEST_ITEM_EMPTY.getCode(),
+                        "閲囪喘鐢宠銆�" + purchaseRequest.getNo() + "銆戜腑浜у搧銆�"
+                                + resolveItemName(requestItem.getProductId()) + "銆戝瓨鍦ㄥ琛屾槑缁嗭紝鏃犳硶鐩存帴鍙戣捣璇环銆�"
+                                + "璇峰厛鍦ㄩ噰璐敵璇蜂腑鍚堝苟鍚屼竴浜у搧鐨勬暟閲忓悗鍐嶈瘯銆�");
+            }
+            SrmInquirySaveReqVO.Item itemVO = new SrmInquirySaveReqVO.Item();
+            itemVO.setProductId(requestItem.getProductId());
+            itemVO.setProductUnitId(requestItem.getProductUnitId());
+            itemVO.setQuantity(requestItem.getCount());
+            itemVO.setRemark(requestItem.getRemark());
+            itemVOs.add(itemVO);
+        }
+        saveItems(inquiry.getId(), itemVOs);
+
+        erpPurchaseRequestApi.updatePurchaseRequestInquiry(purchaseRequest.getId(), inquiry.getId(), inquiry.getNo());
         return inquiry.getId();
     }
 
@@ -139,6 +215,7 @@
         inquirySupplierMapper.deleteByInquiryId(id);
         inquiryQuoteMapper.deleteByInquiryId(id);
         inquiryMapper.deleteById(id);
+        clearPurchaseRequestLink(inquiry);
     }
 
     @Override
@@ -235,6 +312,8 @@
         }
         inquiryMapper.updateById(new SrmInquiryDO()
                 .setId(id).setStatus(InquiryStatusEnum.CANCELLED.getStatus()));
+        // 璇环鍙栨秷鍚庤В闄ら噰璐敵璇峰叧鑱旓紝閲囪喘鍛樺彲閲嶆柊閫夋嫨銆屽彂璧疯浠枫�嶆垨銆岀洿鎺ョ敓鎴愬彴璐︺��
+        clearPurchaseRequestLink(inquiry);
     }
 
     @Override
@@ -458,6 +537,7 @@
             createReqDTO.setSourceType(2);
             createReqDTO.setSourceNo(inquiry.getNo());
             createReqDTO.setSourceId(inquiry.getId());
+            createReqDTO.setPurchaseRequestId(inquiry.getPurchaseRequestId());
             createReqDTO.setRemark("SRM璇环鑷姩鐢熸垚锛岃浠峰崟鍙凤細" + inquiry.getNo());
             createReqDTO.setItems(orderItems);
 
@@ -490,6 +570,28 @@
             orderResult.setPurchaseOrderId(purchaseOrderId);
             orderResult.setPurchaseOrderNo(purchaseOrderNo);
             orders.add(orderResult);
+        }
+
+        // 3.1 璇环鍗曟潵婧愪簬閲囪喘鐢宠鏃讹紝鍥炲啓閲囪喘鐢宠鍏宠仈鐨勯噰璐彴璐�
+        //     涓�涓浠峰崟鍙兘鎸変腑鏍囦緵搴斿晢鎷嗘垚澶氬紶鍙拌处锛岄噰璐敵璇峰彧璁板綍绗竴寮狅紝瀹屾暣娓呭崟鍙�氳繃鍙拌处鐨勯噰璐敵璇峰瓧娈靛弽鏌�
+        if (inquiry.getPurchaseRequestId() != null && CollUtil.isNotEmpty(orders)) {
+            SrmInquiryConfirmRespVO.Order firstOrder = orders.get(0);
+            if (orders.size() > 1) {
+                log.info("[confirmInquiry] 璇环鍗�({}) 涓洪噰璐敵璇�({}) 鐢熸垚 {} 寮犲彴璐︼紝閲囪喘鐢宠浠呭洖鍐欓寮犲彴璐�({})",
+                        inquiry.getNo(), inquiry.getPurchaseRequestNo(), orders.size(), firstOrder.getPurchaseOrderNo());
+            }
+            try {
+                erpPurchaseRequestApi.updatePurchaseRequestOrder(inquiry.getPurchaseRequestId(),
+                        firstOrder.getPurchaseOrderId(), firstOrder.getPurchaseOrderNo());
+            } catch (Exception ex) {
+                log.error("[confirmInquiry] 璇环鍗�({}) 鍥炲啓閲囪喘鐢宠({}) 鍏宠仈鍙拌处澶辫触",
+                        inquiry.getNo(), inquiry.getPurchaseRequestNo(), ex);
+                throw new ServiceException(ErrorCodeConstants.INQUIRY_ORDER_GENERATE_FAIL.getCode(),
+                        "璇环鍗曘��" + inquiry.getNo() + "銆戝凡鐢熸垚閲囪喘鍙拌处銆�"
+                                + StrUtil.blankToDefault(firstOrder.getPurchaseOrderNo(), "ID=" + firstOrder.getPurchaseOrderId())
+                                + "銆戯紝浣嗗洖鍐欓噰璐敵璇枫��" + inquiry.getPurchaseRequestNo() + "銆戝け璐ワ細" + ex.getMessage()
+                                + "銆傝鍒伴噰璐敵璇蜂腑鏍稿鍏宠仈鍙拌处锛屾垨鑱旂郴绠$悊鍛樺鐞嗐��");
+            }
         }
 
         // 4. 鏇存柊璇环鍗曚负宸茶浆璁㈠崟锛堢姸鎬佹潯浠舵洿鏂帮紝閬垮厤骞跺彂閲嶅鐢熸垚锛�
@@ -726,6 +828,40 @@
                 "璇环鍗曞彿鍦ㄥ娆″皾璇曞悗浠嶉噸澶嶏紝璇风◢鍚庨噸璇曘��");
     }
 
+    /**
+     * 璇环鍗曡鍙栨秷/鍒犻櫎鏃讹紝瑙i櫎瀵归噰璐敵璇风殑鍏宠仈锛岃閲囪喘鍛樺彲閲嶆柊閫夋嫨銆屽彂璧疯浠枫�嶆垨銆岀洿鎺ョ敓鎴愬彴璐︺�嶃��
+     * 瑙i櫎澶辫触鍙褰曟棩蹇楋紝涓嶉樆鏂彇娑堟搷浣滐紱鍙戣捣璇环鏃朵細鍐嶆寜璇环鍗曠姸鎬佸仛鍏滃簳鍒ゆ柇銆�
+     */
+    private void clearPurchaseRequestLink(SrmInquiryDO inquiry) {
+        if (inquiry.getPurchaseRequestId() == null) {
+            return;
+        }
+        try {
+            erpPurchaseRequestApi.clearPurchaseRequestInquiry(inquiry.getPurchaseRequestId());
+        } catch (Exception ex) {
+            log.warn("[clearPurchaseRequestLink] 璇环鍗�({}) 瑙i櫎閲囪喘鐢宠({}) 鍏宠仈澶辫触锛岃浜哄伐鏍稿",
+                    inquiry.getNo(), inquiry.getPurchaseRequestNo(), ex);
+        }
+    }
+
+    /**
+     * 瑙f瀽浜у搧鍚嶇О锛屼粎鐢ㄤ簬寮傚父鎻愮ず锛涜В鏋愬け璐ユ椂鍥為��涓哄彲璇� ID锛岄伩鍏嶄簩娆″紓甯�
+     */
+    private String resolveItemName(Long productId) {
+        if (productId == null) {
+            return "鏈�夋嫨";
+        }
+        try {
+            MdmItemRespDTO item = mdmItemApi.getItem(productId).getCheckedData();
+            if (item != null && StrUtil.isNotBlank(item.getName())) {
+                return item.getName();
+            }
+        } catch (Exception ex) {
+            log.warn("[resolveItemName] 鏌ヨ浜у搧({}) 鍚嶇О澶辫触", productId, ex);
+        }
+        return "ID=" + productId;
+    }
+
     private String statusName(Integer status) {
         for (InquiryStatusEnum e : InquiryStatusEnum.values()) {
             if (e.getStatus().equals(status)) {

--
Gitblit v1.9.3