Commit 4418a7bebce6497e63c19d1626f4b772f4025e7a

Authored by puhui999
1 parent ea6752f1

CRM-合同:完善新增合同插入关联的商品

yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
... ... @@ -11,6 +11,7 @@ public interface ErrorCodeConstants {
11 11  
12 12 // ========== 合同管理 1-020-000-000 ==========
13 13 ErrorCode CONTRACT_NOT_EXISTS = new ErrorCode(1_020_000_000, "合同不存在");
  14 + ErrorCode CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED = new ErrorCode(1_020_000_001, "更新合同失败,原因:禁止编辑");
14 15  
15 16 // ========== 线索管理 1-020-001-000 ==========
16 17 ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在");
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java
... ... @@ -89,6 +89,9 @@ public class CrmContractSaveReqVO {
89 89 @DiffLogField(name = "备注")
90 90 private String remark;
91 91  
  92 + @Schema(description = "审批状态", example = "1")
  93 + private Integer auditStatus;
  94 +
92 95 @Schema(description = "产品列表")
93 96 private List<CrmContractProductItem> productItems;
94 97  
... ... @@ -104,7 +107,7 @@ public class CrmContractSaveReqVO {
104 107  
105 108 @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911")
106 109 @NotNull(message = "产品数量不能为空")
107   - private Long count;
  110 + private Integer count;
108 111  
109 112 @Schema(description = "产品折扣")
110 113 private Integer discountPercent;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
... ... @@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.crm.service.contract;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.collection.ListUtil;
  5 +import cn.hutool.core.util.ObjUtil;
5 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
6 8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 9 import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
8 10 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
... ... @@ -10,16 +12,23 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR
10 12 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
11 13 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
12 14 import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert;
  15 +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
13 16 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
  17 +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO;
14 18 import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper;
15 19 import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum;
16 20 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
17 21 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
18 22 import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
19 23 import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService;
  24 +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
  25 +import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
  26 +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
20 27 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
21 28 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
22 29 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
  30 +import cn.iocoder.yudao.module.crm.service.product.CrmProductService;
  31 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
23 32 import com.mzt.logapi.context.LogRecordContext;
24 33 import com.mzt.logapi.service.impl.DiffParseFunction;
25 34 import com.mzt.logapi.starter.annotation.LogRecord;
... ... @@ -30,10 +39,14 @@ import org.springframework.validation.annotation.Validated;
30 39  
31 40 import java.util.Collection;
32 41 import java.util.List;
  42 +import java.util.Map;
  43 +import java.util.Set;
33 44  
34 45 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
35   -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS;
  46 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
  47 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
36 48 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
  49 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
37 50  
38 51 /**
39 52 * CRM 合同 Service 实现类
... ... @@ -53,16 +66,25 @@ public class CrmContractServiceImpl implements CrmContractService {
53 66 private CrmPermissionService crmPermissionService;
54 67 @Resource
55 68 private CrmBusinessProductService businessProductService;
56   -
  69 + @Resource
  70 + private CrmProductService productService;
57 71 @Resource
58 72 private BpmProcessInstanceApi bpmProcessInstanceApi;
  73 + @Resource
  74 + private CrmCustomerService customerService;
  75 + @Resource
  76 + private CrmContactService contactService;
  77 + @Resource
  78 + private CrmBusinessService businessService;
  79 + @Resource
  80 + private AdminUserApi adminUserApi;
59 81  
60 82 @Override
61 83 @Transactional(rollbackFor = Exception.class)
62 84 @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_CREATE_SUB_TYPE, bizNo = "{{#contract.id}}",
63 85 success = CRM_CONTRACT_CREATE_SUCCESS)
64 86 public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) {
65   - // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO
  87 + validateRelationDataExists(createReqVO);
66 88 // 插入合同
67 89 CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null);
68 90 contractMapper.insert(contract);
... ... @@ -71,6 +93,10 @@ public class CrmContractServiceImpl implements CrmContractService {
71 93 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
72 94 .setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId())
73 95 .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
  96 +
  97 + // 插入商机关联商品
  98 + List<CrmBusinessProductDO> businessProduct = convertBusinessProductList(createReqVO);
  99 + businessProductService.insertBatch(businessProduct);
74 100 // 4. 记录操作日志上下文
75 101 LogRecordContext.putVariable("contract", contract);
76 102 return contract.getId();
... ... @@ -83,12 +109,21 @@ public class CrmContractServiceImpl implements CrmContractService {
83 109 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
84 110 public void updateContract(CrmContractSaveReqVO updateReqVO) {
85 111 // TODO @合同待定:只有草稿、审批中,可以编辑;
  112 + if (ObjUtil.notEqual(updateReqVO.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus()) ||
  113 + ObjUtil.notEqual(updateReqVO.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) {
  114 + throw exception(CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED);
  115 + }
  116 + validateRelationDataExists(updateReqVO);
86 117 // 校验存在
87 118 CrmContractDO oldContract = validateContractExists(updateReqVO.getId());
88 119 // 更新合同
89 120 CrmContractDO updateObj = BeanUtils.toBean(updateReqVO, CrmContractDO.class);
90 121 contractMapper.updateById(updateObj);
91   - // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO
  122 +
  123 + // TODO puhui999: @芋艿:合同变更关联的商机后商品怎么处理?
  124 + //List<CrmBusinessProductDO> businessProduct = convertBusinessProductList(updateReqVO);
  125 + //businessProductService.selectListByBusinessId()
  126 + //diffList()
92 127  
93 128 // 3. 记录操作日志上下文
94 129 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractSaveReqVO.class));
... ... @@ -97,8 +132,55 @@ public class CrmContractServiceImpl implements CrmContractService {
97 132  
98 133 // TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum
99 134  
100   - // TODO @合同待定:缺一个发起审批的接口;只有草稿可以发起审批;CrmAuditStatusEnum
  135 + private List<CrmBusinessProductDO> convertBusinessProductList(CrmContractSaveReqVO reqVO) {
  136 + // 校验商品存在
  137 + Set<Long> productIds = convertSet(reqVO.getProductItems(), CrmContractSaveReqVO.CrmContractProductItem::getId);
  138 + List<CrmProductDO> productList = productService.getProductList(productIds);
  139 + if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) {
  140 + throw exception(PRODUCT_NOT_EXISTS);
  141 + }
  142 + Map<Long, CrmProductDO> productMap = convertMap(productList, CrmProductDO::getId);
  143 + return convertList(reqVO.getProductItems(), productItem -> {
  144 + CrmBusinessProductDO businessProduct = BeanUtils.toBean(productMap.get(productItem.getId()), CrmBusinessProductDO.class);
  145 + businessProduct.setId(null).setBusinessId(reqVO.getBusinessId()).setProductId(productItem.getId())
  146 + .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()).setTotalPrice(calculator(businessProduct));
  147 + return businessProduct;
  148 + });
  149 + }
101 150  
  151 + /**
  152 + * 计算商品总价
  153 + *
  154 + * @param businessProduct 关联商品
  155 + * @return 商品总价
  156 + */
  157 + private Integer calculator(CrmBusinessProductDO businessProduct) {
  158 + int price = businessProduct.getPrice() * businessProduct.getCount();
  159 + if (businessProduct.getDiscountPercent() == null) {
  160 + return price;
  161 + }
  162 + return MoneyUtils.calculateRatePriceFloor(price, (double) (businessProduct.getDiscountPercent() / 100));
  163 + }
  164 +
  165 + /**
  166 + * 校验关联数据是否存在
  167 + *
  168 + * @param reqVO 请求
  169 + */
  170 + private void validateRelationDataExists(CrmContractSaveReqVO reqVO) {
  171 + // 1. 校验客户
  172 + if (reqVO.getCustomerId() != null && customerService.getCustomer(reqVO.getCustomerId()) == null) {
  173 + throw exception(CUSTOMER_NOT_EXISTS);
  174 + }
  175 + // 2. 校验负责人
  176 + if (reqVO.getOwnerUserId() != null && adminUserApi.getUser(reqVO.getOwnerUserId()) == null) {
  177 + throw exception(USER_NOT_EXISTS);
  178 + }
  179 + // 4. 如果有关联商机,则需要校验存在
  180 + if (reqVO.getBusinessId() != null && businessService.getBusiness(reqVO.getBusinessId()) == null) {
  181 + throw exception(BUSINESS_NOT_EXISTS);
  182 + }
  183 + }
102 184  
103 185 @Override
104 186 @Transactional(rollbackFor = Exception.class)
... ... @@ -151,6 +233,7 @@ public class CrmContractServiceImpl implements CrmContractService {
151 233 }
152 234  
153 235 @Override
  236 + @Transactional(rollbackFor = Exception.class)
154 237 public void handleApprove(Long id, Long userId) {
155 238 // 创建合同审批流程实例
156 239 String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO()
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java
1 1 package cn.iocoder.yudao.module.crm.service.contract.listener;
2 2  
3 3 public class CrmContractResultListener {
  4 + // TODO puhui999: @芋艿: 艿艿写一下这个,没研究明白哈哈
4 5 }
... ...