mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	📖 CRM:code review 合同的代码实现
This commit is contained in:
		| @@ -99,9 +99,17 @@ public class CrmContractController { | ||||
|     @Parameter(name = "id", description = "编号", required = true, example = "1024") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:contract:query')") | ||||
|     public CommonResult<CrmContractRespVO> getContract(@RequestParam("id") Long id) { | ||||
|         // 1. 查询合同 | ||||
|         CrmContractDO contract = contractService.getContract(id); | ||||
|         List<CrmContractRespVO> respVOList = buildContractDetail(Collections.singletonList(contract)); | ||||
|         CrmContractRespVO respVO = respVOList.getFirst(); | ||||
|         if (contract == null) { | ||||
|             return success(null); | ||||
|         } | ||||
|  | ||||
|         // 2.1 拼接合同信息 | ||||
|         List<CrmContractRespVO> respVOList = buildContractDetailList(Collections.singletonList(contract)); | ||||
|         // 2.2 拼接产品信息 | ||||
|         // TODO @puhui999:下面这块也可以搞到 convert 里哈;可以在 ContractDetailList 加个开关,是不是查询商品信息;ps:jdk21 的方法不太能去用,因为 jdk8 项目要兼容; | ||||
|         CrmContractRespVO respVO = respVOList.get(0); | ||||
|         List<CrmBusinessProductDO> businessProductList = businessProductService.getBusinessProductListByContractId(id); | ||||
|         Map<Long, CrmBusinessProductDO> businessProductMap = convertMap(businessProductList, CrmBusinessProductDO::getProductId); | ||||
|         List<CrmProductDO> productList = productService.getProductListByIds(convertSet(businessProductList, CrmBusinessProductDO::getProductId)); | ||||
| @@ -120,7 +128,7 @@ public class CrmContractController { | ||||
|     @PreAuthorize("@ss.hasPermission('crm:contract:query')") | ||||
|     public CommonResult<PageResult<CrmContractRespVO>> getContractPage(@Valid CrmContractPageReqVO pageVO) { | ||||
|         PageResult<CrmContractDO> pageResult = contractService.getContractPage(pageVO, getLoginUserId()); | ||||
|         return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetail(pageResult.getList()))); | ||||
|         return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetailList(pageResult.getList()))); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/page-by-customer") | ||||
| @@ -128,7 +136,7 @@ public class CrmContractController { | ||||
|     public CommonResult<PageResult<CrmContractRespVO>> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) { | ||||
|         Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); | ||||
|         PageResult<CrmContractDO> pageResult = contractService.getContractPageByCustomerId(pageVO); | ||||
|         return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetail(pageResult.getList()))); | ||||
|         return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetailList(pageResult.getList()))); | ||||
|     } | ||||
|  | ||||
|     @GetMapping("/export-excel") | ||||
| @@ -149,7 +157,7 @@ public class CrmContractController { | ||||
|      * @param contractList 原始合同信息 | ||||
|      * @return 细的合同结果 | ||||
|      */ | ||||
|     private List<CrmContractRespVO> buildContractDetail(List<CrmContractDO> contractList) { | ||||
|     private List<CrmContractRespVO> buildContractDetailList(List<CrmContractDO> contractList) { | ||||
|         if (CollUtil.isEmpty(contractList)) { | ||||
|             return Collections.emptyList(); | ||||
|         } | ||||
|   | ||||
| @@ -133,25 +133,25 @@ public class CrmContractRespVO { | ||||
|     @AllArgsConstructor | ||||
|     public static class CrmContractProductItemRespVO { | ||||
|  | ||||
|         @Schema(description = "产品编号", example = "20529") | ||||
|         @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") | ||||
|         private Long id; | ||||
|  | ||||
|         @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") | ||||
|         @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是产品") | ||||
|         private String name; | ||||
|  | ||||
|         @Schema(description = "产品编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") | ||||
|         @Schema(description = "产品编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "N881") | ||||
|         private String no; | ||||
|  | ||||
|         @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") | ||||
|         @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||||
|         private Integer unit; | ||||
|  | ||||
|         @Schema(description = "价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") | ||||
|         @Schema(description = "价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | ||||
|         private Integer price; | ||||
|  | ||||
|         @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") | ||||
|         @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") | ||||
|         private Integer count; | ||||
|  | ||||
|         @Schema(description = "产品折扣") | ||||
|         @Schema(description = "产品折扣", example = "99") | ||||
|         private Integer discountPercent; | ||||
|  | ||||
|     } | ||||
|   | ||||
| @@ -188,6 +188,7 @@ public class CrmCustomerController { | ||||
|                 new CrmCustomerRespVO().setId(customer.getId()).setName(customer.getName()))); | ||||
|     } | ||||
|  | ||||
|     // TODO @puhui999:公海的导出,前端可以接下 | ||||
|     @GetMapping("/export-excel") | ||||
|     @Operation(summary = "导出客户 Excel") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:export')") | ||||
|   | ||||
| @@ -41,6 +41,7 @@ public class CrmBusinessProductDO extends BaseDO { | ||||
|      * 关联 {@link CrmProductDO#getId()} | ||||
|      */ | ||||
|     private Long productId; | ||||
|     // TODO 芋艿:需要在看下 CRM | ||||
|     /** | ||||
|      * 合同编号 | ||||
|      * | ||||
|   | ||||
| @@ -38,6 +38,7 @@ public interface CrmProductMapper extends BaseMapperX<CrmProductDO> { | ||||
|         return selectOne(CrmProductDO::getNo, no); | ||||
|     } | ||||
|  | ||||
|     // TODO @puhui999:selectBatchIds | ||||
|     default List<CrmProductDO> selectListByIds(Collection<Long> ids) { | ||||
|         return selectList(new LambdaQueryWrapperX<CrmProductDO>().in(CrmProductDO::getId, ids)); | ||||
|     } | ||||
|   | ||||
| @@ -4,8 +4,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| // TODO @lzxhqs:方法名上,带下 BusinessProduct;主要考虑不精简的原因,是因为一个逻辑,可能会出现一些超越它自身方法,省略不容易懂; | ||||
|  | ||||
| /** | ||||
|  * 商机产品关联表 Service 接口 | ||||
|  * | ||||
| @@ -20,13 +18,6 @@ public interface CrmBusinessProductService { | ||||
|      */ | ||||
|     void createBusinessProductBatch(List<CrmBusinessProductDO> list); | ||||
|  | ||||
|     /** | ||||
|      * 根据商机id获取商机产品关联数据集合 | ||||
|      * | ||||
|      * @param businessId 商机id | ||||
|      */ | ||||
|     List<CrmBusinessProductDO> getBusinessProductListByBusinessId(Long businessId); | ||||
|  | ||||
|     /** | ||||
|      * 批量更新商机产品表 | ||||
|      * | ||||
| @@ -42,14 +33,21 @@ public interface CrmBusinessProductService { | ||||
|     void deleteBusinessProductBatch(List<CrmBusinessProductDO> list); | ||||
|  | ||||
|     /** | ||||
|      * 根据商机id删除商机产品关联数据 | ||||
|      * 根据商机编号,删除商机产品关联数据 | ||||
|      * | ||||
|      * @param businessId 商机id | ||||
|      */ | ||||
|     void deleteBusinessProductByBusinessId(Long businessId); | ||||
|  | ||||
|     /** | ||||
|      * 获得合同关联的商品列表 | ||||
|      * 根据商机编号,获取商机产品关联数据集合 | ||||
|      * | ||||
|      * @param businessId 商机编号 | ||||
|      */ | ||||
|     List<CrmBusinessProductDO> getBusinessProductListByBusinessId(Long businessId); | ||||
|  | ||||
|     /** | ||||
|      * 根据合同编号,获得合同关联的商品列表 | ||||
|      * | ||||
|      * @param contractId 合同编号 | ||||
|      * @return 关联的商品列表 | ||||
|   | ||||
| @@ -26,17 +26,12 @@ public class CrmBusinessProductServiceImpl implements CrmBusinessProductService | ||||
|         businessProductMapper.insertBatch(list); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmBusinessProductDO> getBusinessProductListByBusinessId(Long businessId) { | ||||
|         return businessProductMapper.selectList(CrmBusinessProductDO::getBusinessId, businessId); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void updateBusinessProductBatch(List<CrmBusinessProductDO> list) { | ||||
|         businessProductMapper.updateBatch(list); | ||||
|     } | ||||
|  | ||||
|     // TODO @lzxhqs:这个方法,可以直接调用 deleteList 方法,然后传递 ids 就好了; | ||||
|     // TODO @puhui999:这个方法,可以直接调用 deleteList 方法,然后传递 ids 就好了; | ||||
|     @Override | ||||
|     public void deleteBusinessProductBatch(List<CrmBusinessProductDO> list) { | ||||
|         businessProductMapper.deleteBatchIds(CollectionUtils.convertList(list, CrmBusinessProductDO::getId)); | ||||
| @@ -52,4 +47,9 @@ public class CrmBusinessProductServiceImpl implements CrmBusinessProductService | ||||
|         return businessProductMapper.selectList(CrmBusinessProductDO::getContractId, contractId); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<CrmBusinessProductDO> getBusinessProductListByBusinessId(Long businessId) { | ||||
|         return businessProductMapper.selectList(CrmBusinessProductDO::getBusinessId, businessId); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -195,9 +195,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { | ||||
|      * @author lzxhqs | ||||
|      */ | ||||
|     private void validateContractExists(Long businessId) { | ||||
|         // TODO @lzxhqs:保持风格的统一,selectCountByBusinessId 改成 getContractCountByBusinessId;另外,可以不用声明 count,因为就一次性使用,直接把 197 和 198 合并成一行; | ||||
|         Long count = contractService.getContractCountByBusinessId(businessId); | ||||
|         if (count > 0) { | ||||
|         if (contractService.getContractCountByBusinessId(businessId) > 0) { | ||||
|             throw exception(BUSINESS_CONTRACT_EXISTS); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -72,6 +72,7 @@ public interface CrmContractService { | ||||
|      * @param event 审批结果 | ||||
|      */ | ||||
|     void updateContractAuditStatus(BpmResultListenerRespDTO event); | ||||
|  | ||||
|     /** | ||||
|      * 获得合同 | ||||
|      * | ||||
|   | ||||
| @@ -113,24 +113,24 @@ public class CrmContractServiceImpl implements CrmContractService { | ||||
|     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) | ||||
|     public void updateContract(CrmContractSaveReqVO updateReqVO) { | ||||
|         Assert.notNull(updateReqVO.getId(), "合同编号不能为空"); | ||||
|         // 1.1 校验存在 | ||||
|         CrmContractDO contract = validateContractExists(updateReqVO.getId()); | ||||
|         // 只有草稿、审批中,可以编辑; | ||||
|         // 1.2 只有草稿、审批中,可以编辑; | ||||
|         if (!ObjectUtils.equalsAny(contract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), | ||||
|                 CrmAuditStatusEnum.PROCESS.getStatus())) { | ||||
|             throw exception(CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED); | ||||
|         } | ||||
|         validateRelationDataExists(updateReqVO); | ||||
|         // 校验存在 | ||||
|         CrmContractDO oldContract = validateContractExists(updateReqVO.getId()); | ||||
|         // 更新合同 | ||||
|  | ||||
|         // 2.1 更新合同 | ||||
|         CrmContractDO updateObj = BeanUtils.toBean(updateReqVO, CrmContractDO.class); | ||||
|         contractMapper.updateById(updateObj); | ||||
|         // 更新合同关联商品 | ||||
|         // 2.2 更新合同关联商品 | ||||
|         updateContractProduct(updateReqVO, updateObj.getId()); | ||||
|  | ||||
|         // 3. 记录操作日志上下文 | ||||
|         LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractSaveReqVO.class)); | ||||
|         LogRecordContext.putVariable("contractName", oldContract.getName()); | ||||
|         LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(contract, CrmContractSaveReqVO.class)); | ||||
|         LogRecordContext.putVariable("contractName", contract.getName()); | ||||
|     } | ||||
|  | ||||
|     private void updateContractProduct(CrmContractSaveReqVO updateReqVO, Long contractId) { | ||||
| @@ -248,23 +248,26 @@ public class CrmContractServiceImpl implements CrmContractService { | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     // TODO @puhui999:操作日志; | ||||
|     public void submitContract(Long id, Long userId) { | ||||
|         // 1. 校验合同是否在审批 | ||||
|         CrmContractDO contract = validateContractExists(id); | ||||
|         if (ObjUtil.notEqual(contract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus())) { | ||||
|             throw exception(CONTRACT_SUBMIT_FAIL_NOT_DRAFT); | ||||
|         } | ||||
|         // 创建合同审批流程实例 | ||||
|  | ||||
|         // 2. 创建合同审批流程实例 | ||||
|         String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() | ||||
|                 .setProcessDefinitionKey(CONTRACT_APPROVE).setBusinessKey(String.valueOf(id))); | ||||
|  | ||||
|         // 更新合同工作流编号 | ||||
|         // 3. 更新合同工作流编号 | ||||
|         contractMapper.updateById(new CrmContractDO().setId(id).setProcessInstanceId(processInstanceId) | ||||
|                 .setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus())); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void updateContractAuditStatus(BpmResultListenerRespDTO event) { | ||||
|         // TODO @puhui999:可能要判断下状态是否符合预期 | ||||
|         contractMapper.updateById(new CrmContractDO().setId(Long.parseLong(event.getBusinessKey())) | ||||
|                 .setAuditStatus(event.getResult())); | ||||
|     } | ||||
|   | ||||
| @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl; | ||||
| import jakarta.annotation.Resource; | ||||
| import org.springframework.stereotype.Component; | ||||
|  | ||||
| // TODO @芋艿:后续改成支持 RPC | ||||
| /** | ||||
|  * 合同审批的结果的监听器实现类 | ||||
|  * | ||||
|   | ||||
| @@ -105,6 +105,18 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|         return customer.getId(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 初始化客户的通用字段 | ||||
|      * | ||||
|      * @param customer 客户信息 | ||||
|      * @param ownerUserId 负责人编号 | ||||
|      * @return 客户信息 DO | ||||
|      */ | ||||
|     private static CrmCustomerDO initCustomer(Object customer, Long ownerUserId) { | ||||
|         return BeanUtils.toBean(customer, CrmCustomerDO.class).setOwnerUserId(ownerUserId) | ||||
|                 .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", | ||||
| @@ -248,44 +260,47 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|                 respVO.getFailureCustomerNames().put(importCustomer.getName(), ex.getMessage()); | ||||
|                 return; | ||||
|             } | ||||
|             // 判断如果不存在,在进行插入 | ||||
|             // 情况一:判断如果不存在,在进行插入 | ||||
|             CrmCustomerDO existCustomer = customerMapper.selectByCustomerName(importCustomer.getName()); | ||||
|             if (existCustomer == null) { | ||||
|                 // 1.1 插入客户信息 | ||||
|                 CrmCustomerDO customer = initCustomer(importCustomer, userId); | ||||
|                 customerMapper.insert(customer); | ||||
|                 respVO.getCreateCustomerNames().add(importCustomer.getName()); | ||||
|                 // 创建数据权限 | ||||
|                 // 1.2 创建数据权限 | ||||
|                 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) | ||||
|                         .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 | ||||
|                 // 记录操作日志 | ||||
|                 // 1.3 记录操作日志 | ||||
|                 getSelf().importCustomerLog(customer, false); | ||||
|                 return; | ||||
|             } | ||||
|             // 如果存在,判断是否允许更新 | ||||
|  | ||||
|             // 情况二:如果存在,判断是否允许更新 | ||||
|             if (!isUpdateSupport) { | ||||
|                 respVO.getFailureCustomerNames().put(importCustomer.getName(), | ||||
|                         StrUtil.format(CUSTOMER_NAME_EXISTS.getMsg(), importCustomer.getName())); | ||||
|                 return; | ||||
|             } | ||||
|             CrmCustomerDO updateCustomer = BeanUtils.toBean(importCustomer, CrmCustomerDO.class); | ||||
|             updateCustomer.setId(existCustomer.getId()); | ||||
|             // 2.1 更新客户信息 | ||||
|             CrmCustomerDO updateCustomer = BeanUtils.toBean(importCustomer, CrmCustomerDO.class) | ||||
|                     .setId(existCustomer.getId()); | ||||
|             customerMapper.updateById(updateCustomer); | ||||
|             respVO.getUpdateCustomerNames().add(importCustomer.getName()); | ||||
|             // 记录操作日志 | ||||
|             // 2.2 记录操作日志 | ||||
|             getSelf().importCustomerLog(updateCustomer, true); | ||||
|         }); | ||||
|         return respVO; | ||||
|     } | ||||
|  | ||||
|     private static CrmCustomerDO initCustomer(Object customer, Long userId) { | ||||
|         return BeanUtils.toBean(customer, CrmCustomerDO.class).setOwnerUserId(userId) | ||||
|                 .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 记录导入客户时的操作日志 | ||||
|      * | ||||
|      * @param customer 客户信息 | ||||
|      * @param isUpdate 是否更新;true - 更新,false - 新增 | ||||
|      */ | ||||
|     @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_IMPORT_SUB_TYPE, bizNo = "{{#customer.id}}", | ||||
|             success = CRM_CUSTOMER_IMPORT_SUCCESS) | ||||
|     public void importCustomerLog(CrmCustomerDO customer, boolean isUpdate) { | ||||
|         // 记录操作日志上下文 | ||||
|         LogRecordContext.putVariable("customer", customer); | ||||
|         LogRecordContext.putVariable("isUpdate", isUpdate); | ||||
|     } | ||||
| @@ -382,6 +397,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|         } | ||||
|         // 1.1 获取没有锁定的不在公海的客户 | ||||
|         List<CrmCustomerDO> customerList = customerMapper.selectListByLockAndNotPool(Boolean.FALSE); | ||||
|         // TODO @puhui999:下面也搞到 sql 里去哈;写 or 查询,问题不大的;低 393 到 402;原因是,避免无用的太多数据查询到 java 进程里; | ||||
|         List<CrmCustomerDO> poolCustomerList = new ArrayList<>(); | ||||
|         poolCustomerList.addAll(filterList(customerList, customer -> | ||||
|                 !customer.getDealStatus() && (poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime())) <= 0)); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV