From 88e384da863bb2f7324cb1e1474885df3b7cce91 Mon Sep 17 00:00:00 2001
From: liyong <18434998025@163.com>
Date: 星期一, 13 七月 2026 11:27:49 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_business' into dev_business

---
 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java |  156 +--------------------------------------------------
 1 files changed, 5 insertions(+), 151 deletions(-)

diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java
index 6a3f4d8..e5ad277 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/quotation/CrmSaleQuotationServiceImpl.java
@@ -1,16 +1,9 @@
 package cn.iocoder.yudao.module.crm.service.quotation;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.Assert;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
-import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
-import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO;
-import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
-import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService;
-import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractSaveReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.quotation.vo.CrmSaleQuotationPageReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.quotation.vo.CrmSaleQuotationSaveReqVO;
@@ -33,7 +26,6 @@
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
-import org.flowable.engine.repository.ProcessDefinition;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
@@ -54,11 +46,6 @@
 @Validated
 @Slf4j
 public class CrmSaleQuotationServiceImpl implements CrmSaleQuotationService {
-
-    /**
-     * 閿�鍞姤浠� BPM 鍒嗙被缂栫爜
-     */
-    private static final String SALE_QUOTATION_APPROVE_CATEGORY_CODE = "sale_quotation_approve";
 
     @Resource
     private CrmSaleQuotationMapper saleQuotationMapper;
@@ -81,13 +68,6 @@
     private CrmPermissionService permissionService;
     @Resource
     private CrmContractService contractService;
-
-    @Resource
-    private BpmCategoryService bpmCategoryService;
-    @Resource
-    private BpmProcessDefinitionService bpmProcessDefinitionService;
-    @Resource
-    private BpmProcessInstanceApi bpmProcessInstanceApi;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -186,7 +166,8 @@
                 throw exception(SALE_QUOTATION_ITEM_NOT_EXISTS);
             }
             item.setItemUnitId(mdmItem.getUnitMeasureId());
-            item.setItemPrice(mdmItem.getSalesPrice());
+            // 鐗╂枡鍘熶环锛屽鏋� MDM 涓病鏈夊垯榛樿涓� 0
+            item.setItemPrice(mdmItem.getSalesPrice() != null ? mdmItem.getSalesPrice() : BigDecimal.ZERO);
             if (item.getQuotationPrice() != null && item.getCount() != null) {
                 item.setTotalPrice(MoneyUtils.priceMultiply(item.getQuotationPrice(), item.getCount()));
                 if (item.getTaxPercent() != null) {
@@ -276,138 +257,11 @@
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void submitSaleQuotation(Long id, String processDefinitionKey, Long userId) {
+    public Long convertToContract(Long id, Long userId) {
         // 1. 鏍¢獙鎶ヤ环鍗曞瓨鍦ㄤ笖涓鸿崏绋跨姸鎬�
         CrmSaleQuotationDO saleQuotation = validateSaleQuotationExists(id);
         if (!CrmSaleQuotationStatusEnum.DRAFT.getStatus().equals(saleQuotation.getStatus())) {
-            throw exception(SALE_QUOTATION_SUBMIT_FAIL_NOT_DRAFT);
-        }
-
-        // 2. 鏍¢獙鍒嗙被鍜屾祦绋嬪畾涔夋槸鍚﹀瓨鍦�
-        validateSaleQuotationApproveCategoryAndProcessDefinition();
-
-        // 3. 鏍¢獙浼犲叆鐨勬祦绋嬪畾涔� Key 鏄惁灞炰簬璇ュ垎绫讳笖澶勪簬婵�娲荤姸鎬�
-        ProcessDefinition processDefinition = bpmProcessDefinitionService.getActiveProcessDefinition(processDefinitionKey);
-        if (processDefinition == null) {
-            throw exception(SALE_QUOTATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
-        }
-
-        // 4. 鍒涘缓娴佺▼瀹炰緥
-        String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId,
-                new BpmProcessInstanceCreateReqDTO()
-                        .setProcessDefinitionKey(processDefinitionKey)
-                        .setBusinessKey(String.valueOf(id)));
-
-        // 5. 鏇存柊鎶ヤ环鍗曠姸鎬�
-        saleQuotationMapper.updateById(new CrmSaleQuotationDO()
-                .setId(id)
-                .setProcessInstanceId(processInstanceId)
-                .setStatus(CrmSaleQuotationStatusEnum.PROCESS.getStatus()));
-    }
-
-    /**
-     * 鏍¢獙 BPM 閿�鍞姤浠峰鎵瑰垎绫诲拰娴佺▼瀹氫箟鏄惁瀛樺湪
-     */
-    private void validateSaleQuotationApproveCategoryAndProcessDefinition() {
-        // 1. 鏍¢獙鍒嗙被鏄惁瀛樺湪
-        List<String> codes = Collections.singletonList(SALE_QUOTATION_APPROVE_CATEGORY_CODE);
-        Map<String, ?> categoryMap = bpmCategoryService.getCategoryMap(codes);
-        if (!categoryMap.containsKey(SALE_QUOTATION_APPROVE_CATEGORY_CODE)) {
-            throw exception(SALE_QUOTATION_BPM_CATEGORY_NOT_EXISTS);
-        }
-
-        // 2. 鏍¢獙鍒嗙被涓嬫槸鍚︽湁鍙敤鐨勬祦绋嬪畾涔�
-        List<BpmProcessDefinitionInfoDO> definitionInfoList = bpmProcessDefinitionService
-                .getProcessDefinitionInfoListByCategory(SALE_QUOTATION_APPROVE_CATEGORY_CODE);
-        if (CollUtil.isEmpty(definitionInfoList)) {
-            throw exception(SALE_QUOTATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
-        }
-
-        // 3. 鏍¢獙鏄惁鏈夋縺娲荤姸鎬佺殑娴佺▼瀹氫箟
-        Set<String> processDefinitionIds = convertSet(definitionInfoList, BpmProcessDefinitionInfoDO::getProcessDefinitionId);
-        List<ProcessDefinition> processDefinitions = bpmProcessDefinitionService.getProcessDefinitionList(processDefinitionIds);
-        boolean hasActiveDefinition = processDefinitions.stream()
-                .anyMatch(pd -> !pd.isSuspended());
-        if (!hasActiveDefinition) {
-            throw exception(SALE_QUOTATION_BPM_PROCESS_DEFINITION_NOT_EXISTS);
-        }
-    }
-
-    @Override
-    public void updateSaleQuotationAuditStatus(Long id, Integer bpmResult) {
-        // 1. 鏍¢獙鎶ヤ环鍗曞瓨鍦ㄤ笖涓哄鎵逛腑鐘舵��
-        CrmSaleQuotationDO saleQuotation = validateSaleQuotationExists(id);
-        if (!CrmSaleQuotationStatusEnum.PROCESS.getStatus().equals(saleQuotation.getStatus())) {
-            log.error("[updateSaleQuotationAuditStatus] 鎶ヤ环鍗�({}) 涓嶅浜庡鎵逛腑", id);
-            throw exception(SALE_QUOTATION_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS);
-        }
-
-        // 2. 杞崲瀹℃壒缁撴灉
-        Integer auditStatus = convertBpmResultToAuditStatus(bpmResult);
-        saleQuotationMapper.updateById(new CrmSaleQuotationDO()
-                .setId(id)
-                .setStatus(auditStatus));
-    }
-
-    /**
-     * BPM 瀹℃壒缁撴灉杞崲
-     */
-    private Integer convertBpmResultToAuditStatus(Integer bpmResult) {
-        Integer auditStatus = BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmResult)
-                ? CrmSaleQuotationStatusEnum.APPROVE.getStatus()
-                : BpmTaskStatusEnum.REJECT.getStatus().equals(bpmResult)
-                ? CrmSaleQuotationStatusEnum.REJECT.getStatus()
-                : BpmTaskStatusEnum.CANCEL.getStatus().equals(bpmResult)
-                ? CrmSaleQuotationStatusEnum.CANCEL.getStatus() : null;
-        Assert.notNull(auditStatus, "BPM 瀹℃壒缁撴灉({}) 杞崲澶辫触", bpmResult);
-        return auditStatus;
-    }
-
-    @Override
-    public List<Map<String, Object>> getSaleQuotationApproveProcessDefinitionList() {
-        // 1. 鏍¢獙鍒嗙被鍜屾祦绋嬪畾涔夋槸鍚﹀瓨鍦�
-        validateSaleQuotationApproveCategoryAndProcessDefinition();
-
-        // 2. 鑾峰彇鍒嗙被涓嬬殑娴佺▼瀹氫箟淇℃伅
-        List<BpmProcessDefinitionInfoDO> definitionInfoList = bpmProcessDefinitionService
-                .getProcessDefinitionInfoListByCategory(SALE_QUOTATION_APPROVE_CATEGORY_CODE);
-
-        // 3. 鑾峰彇娴佺▼瀹氫箟璇︽儏
-        Set<String> processDefinitionIds = convertSet(definitionInfoList, BpmProcessDefinitionInfoDO::getProcessDefinitionId);
-        List<ProcessDefinition> processDefinitions = bpmProcessDefinitionService.getProcessDefinitionList(processDefinitionIds);
-
-        // 4. 杩囨护锛氬彧淇濈暀婵�娲荤姸鎬侊紝涓旂浉鍚� key 鍙繚鐣欐渶鏂扮増鏈�
-        Map<String, ProcessDefinition> latestVersionMap = new HashMap<>();
-        for (ProcessDefinition pd : processDefinitions) {
-            if (pd.isSuspended()) {
-                continue;
-            }
-            ProcessDefinition existing = latestVersionMap.get(pd.getKey());
-            if (existing == null || pd.getVersion() > existing.getVersion()) {
-                latestVersionMap.put(pd.getKey(), pd);
-            }
-        }
-
-        // 5. 杩斿洖娴佺▼瀹氫箟鍒楄〃
-        List<Map<String, Object>> result = new ArrayList<>();
-        for (ProcessDefinition pd : latestVersionMap.values()) {
-            Map<String, Object> item = new HashMap<>();
-            item.put("id", pd.getId());
-            item.put("key", pd.getKey());
-            item.put("name", pd.getName());
-            item.put("version", pd.getVersion());
-            result.add(item);
-        }
-        return result;
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public Long convertToContract(Long id, Long userId) {
-        // 1. 鏍¢獙鎶ヤ环鍗曞瓨鍦ㄤ笖宸插鎵归�氳繃
-        CrmSaleQuotationDO saleQuotation = validateSaleQuotationExists(id);
-        if (!CrmSaleQuotationStatusEnum.APPROVE.getStatus().equals(saleQuotation.getStatus())) {
-            throw exception(SALE_QUOTATION_NOT_APPROVE);
+            throw exception(SALE_QUOTATION_CONVERT_FAIL_NOT_DRAFT, saleQuotation.getNo());
         }
         // 鏍¢獙鏄惁宸茶浆鍚堝悓
         if (saleQuotation.getContractId() != null) {
@@ -437,7 +291,7 @@
         });
         contractVO.setProducts(contractProducts);
 
-        // 4. 鍒涘缓鍚堝悓
+        // 4. 鍒涘缓鍚堝悓锛堜細鑷姩妫�娴嬪悎鍚屽鎵规祦绋嬪苟鎻愪氦瀹℃壒锛�
         Long contractId = contractService.createContract(contractVO, userId);
 
         // 5. 鏇存柊鎶ヤ环鍗曞叧鑱斾俊鎭�

--
Gitblit v1.9.3