From b3fe06c151dc8455649bf0a46e481ceb83e3ea2a Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期六, 07 十一月 2026 13:37:54 +0800
Subject: [PATCH] feat: 完成好水川 MOM 需求1/2/4/5/8(装箱、BOM成本、销售合同、劳动合同、留样)
---
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java | 95 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 95 insertions(+), 0 deletions(-)
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
index 4852463..5561170 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
@@ -10,11 +10,13 @@
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
+import cn.iocoder.yudao.framework.operatelog.core.util.OperateLogUtils;
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.service.definition.BpmCategoryService;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
+import cn.iocoder.yudao.module.crm.api.contract.dto.CrmContractCreateFromSaleOrderReqDTO;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractPageReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractSaveReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractImportExcelVO;
@@ -56,6 +58,7 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
@@ -272,6 +275,8 @@
@Override
@Transactional(rollbackFor = Exception.class)
+ @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_IMPORT_SUB_TYPE, bizNo = "0",
+ success = CRM_CONTRACT_IMPORT_SUCCESS)
public CrmContractImportRespVO importContractList(List<CrmContractImportExcelVO> importList) {
CrmContractImportRespVO respVO = CrmContractImportRespVO.builder()
.createList(new ArrayList<>())
@@ -279,6 +284,8 @@
.failureList(new LinkedHashMap<>())
.build();
if (CollUtil.isEmpty(importList)) {
+ // 绌烘枃浠朵篃瑕佺粰鏃ュ織鏂囨鍏滃簳锛岄伩鍏� {{#importSummary}} 鍙栦笉鍒板��
+ OperateLogUtils.putImportSummary(respVO.getCreateList(), respVO.getUpdateList(), respVO.getFailureList());
return respVO;
}
@@ -317,6 +324,8 @@
respVO.getFailureList().put(label, resolveImportErrorMessage(ex));
}
}
+ // 璁板綍瀵煎叆缁撴灉姹囨�伙紝渚� @LogRecord 鐨� success 鏂囨寮曠敤
+ OperateLogUtils.putImportSummary(respVO.getCreateList(), respVO.getUpdateList(), respVO.getFailureList());
return respVO;
}
@@ -546,6 +555,15 @@
}
// 2. 鏍¢獙鍒嗙被鍜屾祦绋嬪畾涔夋槸鍚﹀瓨鍦�
+ // 鍏ㄥ眬鍏嶅鎵癸細涓氬姟鏍¢獙閫氳繃鍚庣洿鎺ユ墽琛屽鎵归�氳繃閫昏緫锛屾棤闇�娴佺▼妯″瀷銆�
+ if (bpmProcessInstanceApi.isGlobalAutoApprove()) {
+ contractMapper.updateById(new CrmContractDO().setId(id).setProcessInstanceId("")
+ .setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus()));
+ updateContractAuditStatus(id, cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum.APPROVE.getStatus());
+ LogRecordContext.putVariable("contractName", contract.getName());
+ return;
+ }
+
validateContractApproveCategoryAndProcessDefinition();
// 3. 鏍¢獙浼犲叆鐨勬祦绋嬪畾涔� Key 鏄惁灞炰簬璇ュ垎绫讳笖澶勪簬婵�娲荤姸鎬�
@@ -721,6 +739,16 @@
}
@Override
+ public Map<Long, Long> getContractCountMapByCustomerIds(Collection<Long> customerIds) {
+ return contractMapper.selectContractCountMapByCustomerIds(customerIds);
+ }
+
+ @Override
+ public Map<Long, BigDecimal> getContractPriceMapByCustomerIds(Collection<Long> customerIds) {
+ return contractMapper.selectContractPriceMapByCustomerIds(customerIds);
+ }
+
+ @Override
public List<CrmContractProductDO> getContractProductListByContractId(Long contactId) {
return contractProductMapper.selectListByContractId(contactId);
}
@@ -808,6 +836,73 @@
}
@Override
+ @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
+ public CrmContractDO createContractDraftFromSaleOrder(CrmContractCreateFromSaleOrderReqDTO reqDTO) {
+ // 1. 骞傜瓑锛氬悓涓�閿�鍞鍗曞彧鐢熸垚涓�寮犲悎鍚�
+ CrmContractDO existed = contractMapper.selectByOrderId(reqDTO.getOrderId());
+ if (existed != null) {
+ log.info("[createContractDraftFromSaleOrder] 閿�鍞鍗�({}) 宸茬敓鎴愬悎鍚�({})锛岃烦杩囧垱寤�",
+ reqDTO.getOrderNo(), existed.getNo());
+ return existed;
+ }
+ // 2. 鏍¢獙瀹㈡埛涓庤礋璐d汉
+ CrmCustomerDO customer = customerService.getCustomer(reqDTO.getCustomerId());
+ if (customer == null) {
+ throw new IllegalArgumentException("閿�鍞鍗昜" + reqDTO.getOrderNo()
+ + "]鍏宠仈鐨勫鎴蜂笉瀛樺湪鎴栧凡琚垹闄わ紝鏃犳硶鑷姩鐢熸垚閿�鍞悎鍚�");
+ }
+ if (reqDTO.getOwnerUserId() == null) {
+ throw new IllegalArgumentException("閿�鍞鍗昜" + reqDTO.getOrderNo()
+ + "]鏈~鍐欓攢鍞憳锛屾棤娉曠‘瀹氳嚜鍔ㄧ敓鎴愰攢鍞悎鍚岀殑璐熻矗浜�");
+ }
+ if (CollUtil.isEmpty(reqDTO.getItems())) {
+ throw new IllegalArgumentException("閿�鍞鍗昜" + reqDTO.getOrderNo()
+ + "]娌℃湁鏄庣粏锛屾棤娉曡嚜鍔ㄧ敓鎴愰攢鍞悎鍚�");
+ }
+
+ // 3. 缁勮鍚堝悓鏄庣粏
+ List<CrmContractProductDO> products = new ArrayList<>(reqDTO.getItems().size());
+ for (CrmContractCreateFromSaleOrderReqDTO.Item item : reqDTO.getItems()) {
+ CrmContractProductDO product = new CrmContractProductDO();
+ product.setItemId(item.getItemId());
+ product.setItemUnitId(item.getItemUnitId());
+ product.setItemPrice(item.getPrice());
+ product.setContractPrice(item.getPrice());
+ product.setCount(item.getCount());
+ product.setTotalPrice(MoneyUtils.priceMultiply(item.getPrice(), item.getCount()));
+ products.add(product);
+ }
+
+ // 4. 缁勮鍚堝悓锛堟湭鎻愪氦鑽夌锛屼笉鍙戣捣瀹℃壒锛�
+ CrmContractDO contract = new CrmContractDO();
+ contract.setNo(noRedisDAO.generate(CrmNoRedisDAO.CONTRACT_NO_PREFIX));
+ contract.setName(customer.getName() + "-閿�鍞悎鍚�-" + reqDTO.getOrderNo());
+ contract.setCustomerId(reqDTO.getCustomerId());
+ contract.setOwnerUserId(reqDTO.getOwnerUserId());
+ contract.setOrderDate(reqDTO.getOrderTime());
+ contract.setDiscountPercent(reqDTO.getDiscountPercent() != null ? reqDTO.getDiscountPercent() : BigDecimal.ZERO);
+ contract.setDepositPrice(reqDTO.getDepositPrice() != null ? reqDTO.getDepositPrice() : BigDecimal.ZERO);
+ contract.setOrderId(reqDTO.getOrderId());
+ contract.setOrderNo(reqDTO.getOrderNo());
+ contract.setRemark("鐢遍攢鍞鍗曘��" + reqDTO.getOrderNo() + "銆戝鎵归�氳繃鍚庤嚜鍔ㄧ敓鎴�");
+ contract.setAuditStatus(CrmAuditStatusEnum.DRAFT.getStatus());
+ calculateTotalPrice(contract, products);
+
+ // 5. 钀藉簱
+ contractMapper.insert(contract);
+ products.forEach(product -> product.setContractId(contract.getId()));
+ contractProductMapper.insertBatch(products);
+
+ // 6. 鍒涘缓鏁版嵁鏉冮檺锛屼繚璇佽礋璐d汉鑳界湅鍒拌鍚堝悓
+ crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(contract.getOwnerUserId())
+ .setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId())
+ .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
+ log.info("[createContractDraftFromSaleOrder] 閿�鍞鍗�({}) 鑷姩鐢熸垚鍚堝悓({}) 鎴愬姛",
+ reqDTO.getOrderNo(), contract.getNo());
+ return contract;
+ }
+
+ @Override
public void updateContractStatus(Long id, Integer status) {
contractMapper.updateById(new CrmContractDO()
.setId(id)
--
Gitblit v1.9.3