From 4bc513be11e671caf20ec6013a51dee42c2ed96e Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期六, 07 十一月 2026 18:31:26 +0800
Subject: [PATCH] fix(crm): 禁止物料类合同开票
---
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 168 insertions(+), 9 deletions(-)
diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
index 263b383..4cb7956 100644
--- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
+++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
@@ -3,9 +3,15 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
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.crm.controller.admin.business.vo.business.CrmBusinessImportExcelVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessImportReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessImportRespVO;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
@@ -17,8 +23,10 @@
import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
+import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper;
+import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper;
import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
@@ -43,14 +51,17 @@
import java.math.BigDecimal;
import java.time.LocalDateTime;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
@@ -67,6 +78,8 @@
private CrmBusinessMapper businessMapper;
@Resource
private CrmBusinessProductMapper businessProductMapper;
+ @Resource
+ private CrmCustomerMapper customerMapper;
@Resource
private CrmBusinessStatusService businessStatusService;
@@ -113,6 +126,9 @@
permissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(business.getOwnerUserId())
.setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()).setBizId(business.getId())
.setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
+ // 3.1 瀹㈡埛璐熻矗浜鸿嚜鍔ㄦ嫢鏈夎鍟嗘満鐨勮鍐欐潈闄�
+ permissionService.createPermissionForCustomerOwner(CrmBizTypeEnum.CRM_BUSINESS.getType(),
+ business.getId(), business.getCustomerId(), business.getOwnerUserId());
// 4. 鍦ㄨ仈绯讳汉鐨勮鎯呴〉锛屽鏋滅洿鎺ャ�愭柊寤哄晢鏈恒�戯紝鍒欓渶瑕佸叧鑱斾笅
if (createReqVO.getContactId() != null) {
@@ -134,8 +150,9 @@
updateReqVO.setOwnerUserId(null).setStatusTypeId(null); // 涓嶅厑璁告洿鏂扮殑瀛楁
// 1.1 鏍¢獙瀛樺湪
CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId());
- // 1.2 鏍¢獙浜у搧椤圭殑鏈夋晥鎬�
- List<CrmBusinessProductDO> businessProducts = validateBusinessProducts(updateReqVO.getProducts());
+ // 1.2 鏍¢獙浜у搧椤圭殑鏈夋晥鎬э紙浼犲叆鏃т骇鍝佸垪琛ㄧ敤浜庡悎骞� null 瀛楁锛�
+ List<CrmBusinessProductDO> oldProducts = businessProductMapper.selectListByBusinessId(updateReqVO.getId());
+ List<CrmBusinessProductDO> businessProducts = validateBusinessProducts(updateReqVO.getProducts(), oldProducts);
// 1.3 鏍¢獙鍏宠仈瀛楁
validateRelationDataExists(updateReqVO);
@@ -147,7 +164,7 @@
updateBusinessProduct(updateObj.getId(), businessProducts);
// 3. 璁板綍鎿嶄綔鏃ュ織涓婁笅鏂�
- updateReqVO.setOwnerUserId(oldBusiness.getOwnerUserId()); // 閬垮厤鎿嶄綔鏃ュ織鍑虹幇鈥滃垹闄よ礋璐d汉鈥濈殑鎯呭喌
+ updateReqVO.setOwnerUserId(oldBusiness.getOwnerUserId()); // 閬垮厤鎿嶄綔鏃ュ織鍑虹幇"鍒犻櫎璐熻矗浜�"鐨勬儏鍐�
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldBusiness, CrmBusinessSaveReqVO.class));
LogRecordContext.putVariable("businessName", oldBusiness.getName());
}
@@ -216,6 +233,18 @@
}
private List<CrmBusinessProductDO> validateBusinessProducts(List<CrmBusinessSaveReqVO.BusinessProduct> list) {
+ return validateBusinessProducts(list, Collections.emptyList());
+ }
+
+ /**
+ * 鏍¢獙浜у搧椤圭殑鏈夋晥鎬э紙鏇存柊鍦烘櫙鍚堝苟鏃ф暟鎹級
+ *
+ * @param list 鍓嶇浼犲叆鐨勪骇鍝佸垪琛�
+ * @param oldProducts 宸叉湁浜у搧鍒楄〃锛堢敤浜庡悎骞� null 瀛楁锛�
+ * @return 澶勭悊鍚庣殑浜у搧 DO 鍒楄〃
+ */
+ private List<CrmBusinessProductDO> validateBusinessProducts(List<CrmBusinessSaveReqVO.BusinessProduct> list,
+ List<CrmBusinessProductDO> oldProducts) {
// 1. 鏍¢獙鐗╂枡瀛樺湪
Set<Long> itemIds = convertSet(list, CrmBusinessSaveReqVO.BusinessProduct::getItemId);
Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(itemIds);
@@ -224,15 +253,50 @@
throw exception(PRODUCT_NOT_EXISTS);
}
}
- // 2. 杞寲涓� CrmBusinessProductDO 鍒楄〃
- return convertList(list, o -> BeanUtils.toBean(o, CrmBusinessProductDO.class,
- item -> item.setTotalPrice(MoneyUtils.priceMultiply(item.getBusinessPrice(), item.getCount()))));
+ // 2. 鏋勫缓鏃т骇鍝� Map锛堟寜 id 绱㈠紩锛�
+ Map<Long, CrmBusinessProductDO> oldProductMap = convertMap(oldProducts, CrmBusinessProductDO::getId);
+ // 3. 杞寲涓� CrmBusinessProductDO 鍒楄〃锛堝悎骞舵棫鏁版嵁锛�
+ return convertList(list, o -> {
+ CrmBusinessProductDO product = BeanUtils.toBean(o, CrmBusinessProductDO.class);
+ // 鏇存柊鍦烘櫙锛氬鏋滀骇鍝佸凡鏈� id 涓旀湁鏃ф暟鎹紝鍒欏悎骞� null 瀛楁
+ if (o.getId() != null && oldProductMap.containsKey(o.getId())) {
+ CrmBusinessProductDO old = oldProductMap.get(o.getId());
+ if (product.getBusinessPrice() == null) {
+ product.setBusinessPrice(old.getBusinessPrice());
+ }
+ if (product.getItemPrice() == null) {
+ product.setItemPrice(old.getItemPrice());
+ }
+ if (product.getCount() == null) {
+ product.setCount(old.getCount());
+ }
+ if (product.getItemUnitId() == null) {
+ product.setItemUnitId(old.getItemUnitId());
+ }
+ } else {
+ // 鏂颁骇鍝侊細娓呴櫎鍓嶇鐢熸垚鐨勪复鏃� ID锛岃鏁版嵁搴� AUTO_INCREMENT 鎺ョ
+ product.setId(null);
+ }
+ // 浼樺厛浣跨敤鍓嶇浼犲叆鐨� totalPrice锛屽惁鍒欓�氳繃 businessPrice * count 璁$畻
+ if (o.getTotalPrice() != null) {
+ product.setTotalPrice(o.getTotalPrice());
+ } else {
+ product.setTotalPrice(MoneyUtils.priceMultiply(product.getBusinessPrice(), product.getCount()));
+ }
+ return product;
+ });
}
private void calculateTotalPrice(CrmBusinessDO business, List<CrmBusinessProductDO> businessProducts) {
- business.setTotalProductPrice(getSumValue(businessProducts, CrmBusinessProductDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO));
- BigDecimal discountPrice = MoneyUtils.priceMultiplyPercent(business.getTotalProductPrice(), business.getDiscountPercent());
- business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice));
+ // totalProductPrice锛氫紭鍏堜娇鐢ㄥ墠绔紶鍏ュ�硷紝鍚﹀垯浠庝骇鍝佹眹鎬�
+ if (business.getTotalProductPrice() == null) {
+ business.setTotalProductPrice(getSumValue(businessProducts, CrmBusinessProductDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO));
+ }
+ // totalPrice锛氫紭鍏堜娇鐢ㄥ墠绔紶鍏ュ�硷紝鍚﹀垯鎸夋姌鎵h绠�
+ if (business.getTotalPrice() == null) {
+ BigDecimal discountPrice = MoneyUtils.priceMultiplyPercent(business.getTotalProductPrice(), business.getDiscountPercent());
+ business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice));
+ }
}
@Override
@@ -417,4 +481,99 @@
return businessMapper.selectPage(pageVO);
}
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public CrmBusinessImportRespVO importBusinessList(List<CrmBusinessImportExcelVO> importBusinesses,
+ CrmBusinessImportReqVO importReqVO) {
+ // 1. 鏍¢獙闈炵┖
+ importBusinesses = filterList(importBusinesses, item -> StrUtil.isNotBlank(item.getName()));
+ if (CollUtil.isEmpty(importBusinesses)) {
+ throw exception(BUSINESS_IMPORT_LIST_IS_EMPTY);
+ }
+ // 2. 鏍¢獙璐熻矗浜猴紙涓虹┖鍒欓粯璁ゅ綋鍓嶆搷浣滀汉锛�
+ Long ownerUserId = importReqVO.getOwnerUserId() != null ? importReqVO.getOwnerUserId() : getLoginUserId();
+ adminUserApi.validateUser(ownerUserId);
+ // 3. 榛樿鍟嗘満鐘舵�佺粍 + 鐘舵��
+ Long defaultStatusTypeId = businessStatusService.getBusinessStatusTypeList().get(0).getId();
+ Long defaultStatusId = businessStatusService.getBusinessStatusListByTypeId(defaultStatusTypeId).get(0).getId();
+
+ // 4. 閫愭潯澶勭悊
+ CrmBusinessImportRespVO respVO = CrmBusinessImportRespVO.builder()
+ .createBusinessNames(new ArrayList<>())
+ .updateBusinessNames(new ArrayList<>())
+ .failureBusinessNames(new LinkedHashMap<>())
+ .build();
+ importBusinesses.forEach(importBusiness -> {
+ try {
+ // 4.1 瑙f瀽瀹㈡埛
+ CrmCustomerDO customer = customerMapper.selectByCustomerName(importBusiness.getCustomerName());
+ if (customer == null) {
+ throw exception(BUSINESS_IMPORT_CUSTOMER_NOT_EXISTS, importBusiness.getCustomerName());
+ }
+ // 4.2 鍒ゆ柇鏄惁瀛樺湪
+ CrmBusinessDO existBusiness = businessMapper.selectByNameAndCustomerId(
+ importBusiness.getName(), customer.getId());
+ if (existBusiness == null) {
+ // 4.2.1 鏂板
+ CrmBusinessDO business = BeanUtils.toBean(importBusiness, CrmBusinessDO.class)
+ .setCustomerId(customer.getId()).setOwnerUserId(ownerUserId)
+ .setStatusTypeId(defaultStatusTypeId).setStatusId(defaultStatusId);
+ if (business.getDiscountPercent() == null) {
+ business.setDiscountPercent(BigDecimal.ZERO);
+ }
+ calculateTotalPrice(business, Collections.emptyList());
+ businessMapper.insert(business);
+ // 鍒涘缓鏁版嵁鏉冮檺
+ permissionService.createPermission(new CrmPermissionCreateReqBO()
+ .setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()).setBizId(business.getId())
+ .setUserId(ownerUserId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
+ // 瀹㈡埛璐熻矗浜鸿嚜鍔ㄦ嫢鏈夎鍟嗘満鐨勮鍐欐潈闄�
+ permissionService.createPermissionForCustomerOwner(CrmBizTypeEnum.CRM_BUSINESS.getType(),
+ business.getId(), customer.getId(), ownerUserId);
+ respVO.getCreateBusinessNames().add(importBusiness.getName());
+ // 璁板綍鎿嶄綔鏃ュ織
+ getSelf().importBusinessLog(business, false);
+ return;
+ }
+ // 4.2.2 宸插瓨鍦紝鍒ゆ柇鏄惁鍏佽鏇存柊
+ if (!importReqVO.getUpdateSupport()) {
+ respVO.getFailureBusinessNames().put(importBusiness.getName(),
+ StrUtil.format(BUSINESS_NAME_EXISTS.getMsg(), importBusiness.getName()));
+ return;
+ }
+ CrmBusinessDO updateBusiness = BeanUtils.toBean(importBusiness, CrmBusinessDO.class)
+ .setId(existBusiness.getId()).setCustomerId(customer.getId());
+ businessMapper.updateById(updateBusiness);
+ respVO.getUpdateBusinessNames().add(importBusiness.getName());
+ // 璁板綍鎿嶄綔鏃ュ織
+ getSelf().importBusinessLog(updateBusiness, true);
+ } catch (ServiceException ex) {
+ respVO.getFailureBusinessNames().put(importBusiness.getName(), ex.getMessage());
+ }
+ });
+ return respVO;
+ }
+
+ /**
+ * 璁板綍瀵煎叆鍟嗘満鏃剁殑鎿嶄綔鏃ュ織
+ *
+ * @param business 鍟嗘満淇℃伅
+ * @param isUpdate 鏄惁鏇存柊锛泃rue - 鏇存柊锛宖alse - 鏂板
+ */
+ @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_IMPORT_SUB_TYPE, bizNo = "{{#business.id}}",
+ success = CRM_BUSINESS_IMPORT_SUCCESS)
+ public void importBusinessLog(CrmBusinessDO business, boolean isUpdate) {
+ LogRecordContext.putVariable("business", business);
+ LogRecordContext.putVariable("isUpdate", isUpdate);
+ }
+
+ /**
+ * 鑾峰緱鑷韩鐨勪唬鐞嗗璞★紝瑙e喅 AOP 鐢熸晥闂
+ *
+ * @return 鑷繁
+ */
+ private CrmBusinessServiceImpl getSelf() {
+ return SpringUtil.getBean(getClass());
+ }
+
}
--
Gitblit v1.9.3