mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	Merge remote-tracking branch 'yudao/develop' into develop
# Conflicts: # yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
This commit is contained in:
		| @@ -43,6 +43,7 @@ public class BpmModelController { | ||||
|         return success(model); | ||||
|     } | ||||
|  | ||||
|     // TODO @puhui999:这个接口的目的是啥呀? | ||||
|     @GetMapping("/get-by-key") | ||||
|     @Operation(summary = "获得模型") | ||||
|     @Parameter(name = "key", description = "流程标识", required = true, example = "oa_leave") | ||||
|   | ||||
| @@ -132,6 +132,7 @@ public class CrmContractController { | ||||
|         return CrmContractConvert.INSTANCE.convertPage(pageResult, userMap, customerList); | ||||
|     } | ||||
|  | ||||
|     // TODO @puhui999:transferContract | ||||
|     @PutMapping("/transfer") | ||||
|     @Operation(summary = "合同转移") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:contract:update')") | ||||
| @@ -140,6 +141,7 @@ public class CrmContractController { | ||||
|         return success(true); | ||||
|     } | ||||
|  | ||||
|     // TODO @puhui999:方法名不对哈;要不改成 submit?提交审核的意思 | ||||
|     @PutMapping("/approve") | ||||
|     @Operation(summary = "发起合同审批流程") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:contract:update')") | ||||
|   | ||||
| @@ -89,6 +89,7 @@ public class CrmContractSaveReqVO { | ||||
|     @DiffLogField(name = "备注") | ||||
|     private String remark; | ||||
|  | ||||
|     // TODO @puhui999:这个字段,按道理不用传递? | ||||
|     @Schema(description = "审批状态", example = "1") | ||||
|     private Integer auditStatus; | ||||
|  | ||||
|   | ||||
| @@ -217,6 +217,8 @@ public class CrmCustomerController { | ||||
|         ExcelUtils.write(response, "客户导入模板.xls", "客户列表", CrmCustomerImportExcelVO.class, list); | ||||
|     } | ||||
|  | ||||
|     // TODO @puhui999:updateSupport 要不改成前端必须传递;哈哈哈,代码排版看着有点乱; | ||||
|     // TODO @puhui999:加一个选择负责人;允许空,空就进入公海; | ||||
|     @PostMapping("/import") | ||||
|     @Operation(summary = "导入客户") | ||||
|     @Parameters({ | ||||
| @@ -224,13 +226,12 @@ public class CrmCustomerController { | ||||
|             @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true") | ||||
|     }) | ||||
|     @PreAuthorize("@ss.hasPermission('system:customer:import')") | ||||
|     public CommonResult<CrmCustomerImportRespVO> importExcel(@RequestParam("file") MultipartFile file, | ||||
|                                                              @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { | ||||
|     public CommonResult<CrmCustomerImportRespVO> importExcel(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) | ||||
|             throws Exception { | ||||
|         List<CrmCustomerImportExcelVO> list = ExcelUtils.read(file, CrmCustomerImportExcelVO.class); | ||||
|         return success(customerService.importCustomerList(list, updateSupport, getLoginUserId())); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @PutMapping("/transfer") | ||||
|     @Operation(summary = "转移客户") | ||||
|     @PreAuthorize("@ss.hasPermission('crm:customer:update')") | ||||
|   | ||||
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | ||||
| import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | ||||
| import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | ||||
| import com.alibaba.excel.annotation.ExcelProperty; | ||||
| import jakarta.validation.constraints.Size; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Builder; | ||||
| import lombok.Data; | ||||
| @@ -25,6 +24,7 @@ public class CrmCustomerImportExcelVO { | ||||
|     @ExcelProperty("客户名称") | ||||
|     private String name; | ||||
|  | ||||
|     // TODO @puhui999:industryId、level、source 字段,可以研究下怎么搞下拉框 | ||||
|     @ExcelProperty(value = "所属行业", converter = DictConvert.class) | ||||
|     @DictFormat(CRM_CUSTOMER_INDUSTRY) | ||||
|     private Integer industryId; | ||||
| @@ -46,25 +46,22 @@ public class CrmCustomerImportExcelVO { | ||||
|     @ExcelProperty("网址") | ||||
|     private String website; | ||||
|  | ||||
|     @Size(max = 20, message = "QQ长度不能超过 20 个字符") | ||||
|     @ExcelProperty("QQ") | ||||
|     private String qq; | ||||
|  | ||||
|     @Size(max = 255, message = "微信长度不能超过 255 个字符") | ||||
|     @ExcelProperty("微信") | ||||
|     private String wechat; | ||||
|  | ||||
|     @Size(max = 255, message = "邮箱长度不能超过 255 个字符") | ||||
|     @ExcelProperty("邮箱") | ||||
|     private String email; | ||||
|  | ||||
|     @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") | ||||
|     @ExcelProperty("客户描述") | ||||
|     private String description; | ||||
|  | ||||
|     @ExcelProperty("备注") | ||||
|     private String remark; | ||||
|  | ||||
|     // TODO @puhui999:需要选择省市区,需要研究下,怎么搞合理点; | ||||
|     @ExcelProperty("地区编号") | ||||
|     private Integer areaId; | ||||
|  | ||||
|   | ||||
| @@ -125,6 +125,7 @@ public interface CrmContractService { | ||||
|      */ | ||||
|     Long getContractCountByCustomerId(Long customerId); | ||||
|  | ||||
|     // TODO @puhui999:要不改成 getContractCountByBusinessId | ||||
|     /** | ||||
|      * 根据商机ID获取关联客户的合同数量 | ||||
|      * | ||||
|   | ||||
| @@ -6,7 +6,6 @@ import cn.hutool.core.util.ObjUtil; | ||||
| 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.listener.dto.BpmResultListenerRespDTO; | ||||
| import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; | ||||
| import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; | ||||
| import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; | ||||
| @@ -23,7 +22,6 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | ||||
| import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; | ||||
| import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService; | ||||
| import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; | ||||
| import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; | ||||
| import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | ||||
| import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; | ||||
| import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; | ||||
| @@ -34,7 +32,6 @@ import com.mzt.logapi.context.LogRecordContext; | ||||
| import com.mzt.logapi.service.impl.DiffParseFunction; | ||||
| import com.mzt.logapi.starter.annotation.LogRecord; | ||||
| import jakarta.annotation.Resource; | ||||
| import org.springframework.context.annotation.Lazy; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| @@ -71,17 +68,14 @@ public class CrmContractServiceImpl implements CrmContractService { | ||||
|     @Resource | ||||
|     private CrmProductService productService; | ||||
|     @Resource | ||||
|     private BpmProcessInstanceApi bpmProcessInstanceApi; | ||||
|     @Resource | ||||
|     private CrmCustomerService customerService; | ||||
|     @Resource | ||||
|     @Lazy | ||||
|     private CrmContactService contactService; | ||||
|     @Resource | ||||
|     @Lazy | ||||
|     private CrmBusinessService businessService; | ||||
|  | ||||
|     @Resource | ||||
|     private AdminUserApi adminUserApi; | ||||
|     @Resource | ||||
|     private BpmProcessInstanceApi bpmProcessInstanceApi; | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
| @@ -89,19 +83,19 @@ public class CrmContractServiceImpl implements CrmContractService { | ||||
|             success = CRM_CONTRACT_CREATE_SUCCESS) | ||||
|     public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) { | ||||
|         validateRelationDataExists(createReqVO); | ||||
|         // 插入合同 | ||||
|         // 1.1 插入合同 | ||||
|         CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null); | ||||
|         contractMapper.insert(contract); | ||||
|         // 1.2 插入商机关联商品 | ||||
|         List<CrmBusinessProductDO> businessProduct = convertBusinessProductList(createReqVO); | ||||
|         businessProductService.insertBatch(businessProduct); | ||||
|  | ||||
|         // 创建数据权限 | ||||
|         // 2. 创建数据权限 | ||||
|         crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) | ||||
|                 .setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId()) | ||||
|                 .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); | ||||
|  | ||||
|         // 插入商机关联商品 | ||||
|         List<CrmBusinessProductDO> businessProduct = convertBusinessProductList(createReqVO); | ||||
|         businessProductService.insertBatch(businessProduct); | ||||
|         // 4. 记录操作日志上下文 | ||||
|         // 3. 记录操作日志上下文 | ||||
|         LogRecordContext.putVariable("contract", contract); | ||||
|         return contract.getId(); | ||||
|     } | ||||
| @@ -125,6 +119,7 @@ public class CrmContractServiceImpl implements CrmContractService { | ||||
|         contractMapper.updateById(updateObj); | ||||
|  | ||||
|         // TODO puhui999: @芋艿:合同变更关联的商机后商品怎么处理? | ||||
|         // TODO @puhui999:和商品 spu、sku 编辑一样;新增的插入;修改的更新;删除的删除 | ||||
|         //List<CrmBusinessProductDO> businessProduct = convertBusinessProductList(updateReqVO); | ||||
|         //businessProductService.selectListByBusinessId() | ||||
|         //diffList() | ||||
| @@ -145,6 +140,7 @@ public class CrmContractServiceImpl implements CrmContractService { | ||||
|         } | ||||
|         Map<Long, CrmProductDO> productMap = convertMap(productList, CrmProductDO::getId); | ||||
|         return convertList(reqVO.getProductItems(), productItem -> { | ||||
|             // TODO @puhui999:这里可以改成直接 return,不用弄一个 businessProduct 变量哈; | ||||
|             CrmBusinessProductDO businessProduct = BeanUtils.toBean(productMap.get(productItem.getId()), CrmBusinessProductDO.class); | ||||
|             businessProduct.setId(null).setBusinessId(reqVO.getBusinessId()).setProductId(productItem.getId()) | ||||
|                     .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()).setTotalPrice(calculator(businessProduct)); | ||||
| @@ -158,6 +154,7 @@ public class CrmContractServiceImpl implements CrmContractService { | ||||
|      * @param businessProduct 关联商品 | ||||
|      * @return 商品总价 | ||||
|      */ | ||||
|     // TODO @puhui999:这个逻辑的计算,是不是可以封装到 calculateRatePriceFloor 里; | ||||
|     private Integer calculator(CrmBusinessProductDO businessProduct) { | ||||
|         int price = businessProduct.getPrice() * businessProduct.getCount(); | ||||
|         if (businessProduct.getDiscountPercent() == null) { | ||||
| @@ -180,7 +177,7 @@ public class CrmContractServiceImpl implements CrmContractService { | ||||
|         if (reqVO.getOwnerUserId() != null && adminUserApi.getUser(reqVO.getOwnerUserId()) == null) { | ||||
|             throw exception(USER_NOT_EXISTS); | ||||
|         } | ||||
|         // 4. 如果有关联商机,则需要校验存在 | ||||
|         // 3. 如果有关联商机,则需要校验存在 | ||||
|         if (reqVO.getBusinessId() != null && businessService.getBusiness(reqVO.getBusinessId()) == null) { | ||||
|             throw exception(BUSINESS_NOT_EXISTS); | ||||
|         } | ||||
| @@ -239,6 +236,8 @@ public class CrmContractServiceImpl implements CrmContractService { | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public void handleApprove(Long id, Long userId) { | ||||
|         // TODO @puhui999:需要做状态检查 | ||||
|  | ||||
|         // 创建合同审批流程实例 | ||||
|         String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() | ||||
|                 .setProcessDefinitionKey(CONTRACT_APPROVE).setBusinessKey(String.valueOf(id))); | ||||
| @@ -248,12 +247,6 @@ public class CrmContractServiceImpl implements CrmContractService { | ||||
|                 .setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus())); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public void updateContractAuditStatus(BpmResultListenerRespDTO event) { | ||||
|         contractMapper.updateById(new CrmContractDO().setId(Long.parseLong(event.getBusinessKey())).setAuditStatus(event.getResult())); | ||||
|     } | ||||
|  | ||||
|     //======================= 查询相关 ======================= | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -232,8 +232,10 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|         return customer.getId(); | ||||
|     } | ||||
|  | ||||
|     // TODO @puhui999:操作日志 | ||||
|     @Override | ||||
|     public CrmCustomerImportRespVO importCustomerList(List<CrmCustomerImportExcelVO> importCustomers, Boolean isUpdateSupport, Long userId) { | ||||
|     public CrmCustomerImportRespVO importCustomerList(List<CrmCustomerImportExcelVO> importCustomers, | ||||
|                                                       Boolean isUpdateSupport, Long userId) { | ||||
|         if (CollUtil.isEmpty(importCustomers)) { | ||||
|             throw exception(CUSTOMER_IMPORT_LIST_IS_EMPTY); | ||||
|         } | ||||
| @@ -241,6 +243,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|                 .updateCustomerNames(new ArrayList<>()).failureCustomerNames(new LinkedHashMap<>()).build(); | ||||
|         importCustomers.forEach(importCustomer -> { | ||||
|             // 校验,判断是否有不符合的原因 | ||||
|             // TODO @puhui999:可以用 ValidationUtils 做参数校验;可能要封装一个方法,返回 message;这样的话,就可以在 CrmCustomerImportExcelVO 写需要校验的参数啦; | ||||
|             try { | ||||
|                 validateCustomerForCreate(importCustomer); | ||||
|             } catch (ServiceException ex) { | ||||
| @@ -250,6 +253,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|             // 判断如果不存在,在进行插入 | ||||
|             CrmCustomerDO existCustomer = customerMapper.selectByCustomerName(importCustomer.getName()); | ||||
|             if (existCustomer == null) { | ||||
|                 // TODO @puhui999:可以搞个 initCustomer 方法;这样可以把 create 和导入复用下这个方法; | ||||
|                 CrmCustomerDO customer = BeanUtils.toBean(importCustomer, CrmCustomerDO.class).setOwnerUserId(userId) | ||||
|                         .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); | ||||
|                 customerMapper.insert(customer); | ||||
| @@ -366,6 +370,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|         // 1.1 获取没有锁定的不在公海的客户且没有成交的 | ||||
|         List<CrmCustomerDO> notDealCustomerList = customerMapper.selectListByLockAndDealStatusAndNotPool(Boolean.FALSE, Boolean.FALSE); | ||||
|         // 1.2 获取没有锁定的不在公海的客户且成交的 | ||||
|         // TODO @puhui999:下面也搞到 sql 里去哈;写 or 查询,问题不大的; | ||||
|         List<CrmCustomerDO> dealCustomerList = customerMapper.selectListByLockAndDealStatusAndNotPool(Boolean.FALSE, Boolean.TRUE); | ||||
|         List<CrmCustomerDO> poolCustomerList = new ArrayList<>(); | ||||
|         poolCustomerList.addAll(filterList(notDealCustomerList, customer -> | ||||
| @@ -382,7 +387,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { | ||||
|                 getSelf().putCustomerPool(customer); | ||||
|                 count++; | ||||
|             } catch (Throwable e) { | ||||
|                 log.error("[customerAutoPutPoolBySystem][Customer 客户({}) 放入公海异常]", customer.getId(), e); | ||||
|                 log.error("[autoPutCustomerPool][Customer 客户({}) 放入公海异常]", customer.getId(), e); | ||||
|             } | ||||
|         } | ||||
|         return count; | ||||
|   | ||||
| @@ -109,14 +109,14 @@ public interface CrmPermissionService { | ||||
|     List<CrmPermissionDO> getPermissionListByBizTypeAndUserId(Integer bizType, Long userId); | ||||
|  | ||||
|     /** | ||||
|      * 校验权限 | ||||
|      * 校验是否有指定数据的操作权限 | ||||
|      * | ||||
|      * @param bizType   数据类型,关联 {@link CrmBizTypeEnum} | ||||
|      * @param bizId     数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId() | ||||
|      * @param userId    用户编号 | ||||
|      * @param levelEnum 权限级别 | ||||
|      * @return boolean | ||||
|      * @param level 权限级别 | ||||
|      * @return 是否有权限 | ||||
|      */ | ||||
|     boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum levelEnum); | ||||
|     boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum level); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -213,10 +213,10 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum levelEnum) { | ||||
|     public boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum level) { | ||||
|         List<CrmPermissionDO> permissionList = permissionMapper.selectByBizTypeAndBizId(bizType, bizId); | ||||
|         return anyMatch(permissionList, permission -> | ||||
|                 ObjUtil.equal(permission.getUserId(), userId) && ObjUtil.equal(permission.getLevel(), levelEnum.getLevel())); | ||||
|                 ObjUtil.equal(permission.getUserId(), userId) && ObjUtil.equal(permission.getLevel(), level.getLevel())); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 puhui999
					puhui999