Commit 38e410cae079fcdfdea8bcca3fd7330528db568a

Authored by YunaiV
1 parent fe330482

📖 CRM:线索的转化逻辑

yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
@@ -16,8 +16,8 @@ public interface ErrorCodeConstants { @@ -16,8 +16,8 @@ public interface ErrorCodeConstants {
16 16
17 // ========== 线索管理 1-020-001-000 ========== 17 // ========== 线索管理 1-020-001-000 ==========
18 ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在"); 18 ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在");
19 - ErrorCode CLUE_ANY_CLUE_NOT_EXISTS = new ErrorCode(1_020_001_001, "线索【{}】不存在");  
20 - ErrorCode CLUE_ANY_CLUE_ALREADY_TRANSLATED = new ErrorCode(1_020_001_002, "线索【{}】已经转化过了,请勿重复转化"); 19 + ErrorCode CLUE_NOT_EXISTS_ANY = new ErrorCode(1_020_001_001, "线索【{}】不存在");
  20 + ErrorCode CLUE_TRANSFORM_FAIL_ALREADY = new ErrorCode(1_020_001_002, "线索【{}】已经转化过了,请勿重复转化");
21 21
22 // ========== 商机管理 1-020-002-000 ========== 22 // ========== 商机管理 1-020-002-000 ==========
23 ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在"); 23 ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在");
@@ -25,7 +25,6 @@ public interface ErrorCodeConstants { @@ -25,7 +25,6 @@ public interface ErrorCodeConstants {
25 25
26 // TODO @lilleo:商机状态、商机类型,都单独错误码段 26 // TODO @lilleo:商机状态、商机类型,都单独错误码段
27 27
28 -  
29 // ========== 联系人管理 1-020-003-000 ========== 28 // ========== 联系人管理 1-020-003-000 ==========
30 ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); 29 ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在");
31 ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在"); 30 ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在");
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.MapUtils; @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
7 import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 7 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
9 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 9 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  10 +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
10 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 11 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
11 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; 12 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*;
12 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; 13 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
@@ -35,8 +36,7 @@ import java.util.stream.Stream; @@ -35,8 +36,7 @@ import java.util.stream.Stream;
35 36
36 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 37 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
37 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; 38 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
38 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;  
39 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 39 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
40 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 40 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
41 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 41 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
42 42
@@ -60,7 +60,7 @@ public class CrmClueController { @@ -60,7 +60,7 @@ public class CrmClueController {
60 @Operation(summary = "创建线索") 60 @Operation(summary = "创建线索")
61 @PreAuthorize("@ss.hasPermission('crm:clue:create')") 61 @PreAuthorize("@ss.hasPermission('crm:clue:create')")
62 public CommonResult<Long> createClue(@Valid @RequestBody CrmClueSaveReqVO createReqVO) { 62 public CommonResult<Long> createClue(@Valid @RequestBody CrmClueSaveReqVO createReqVO) {
63 - return success(clueService.createClue(createReqVO, getLoginUserId())); 63 + return success(clueService.createClue(createReqVO));
64 } 64 }
65 65
66 @PutMapping("/update") 66 @PutMapping("/update")
@@ -86,7 +86,14 @@ public class CrmClueController { @@ -86,7 +86,14 @@ public class CrmClueController {
86 @PreAuthorize("@ss.hasPermission('crm:clue:query')") 86 @PreAuthorize("@ss.hasPermission('crm:clue:query')")
87 public CommonResult<CrmClueRespVO> getClue(@RequestParam("id") Long id) { 87 public CommonResult<CrmClueRespVO> getClue(@RequestParam("id") Long id) {
88 CrmClueDO clue = clueService.getClue(id); 88 CrmClueDO clue = clueService.getClue(id);
89 - return success(BeanUtils.toBean(clue, CrmClueRespVO.class)); 89 + return success(buildClueDetail(clue));
  90 + }
  91 +
  92 + public CrmClueRespVO buildClueDetail(CrmClueDO clue) {
  93 + if (clue == null) {
  94 + return null;
  95 + }
  96 + return buildClueDetailList(Collections.singletonList(clue)).get(0);
90 } 97 }
91 98
92 @GetMapping("/page") 99 @GetMapping("/page")
@@ -121,6 +128,7 @@ public class CrmClueController { @@ -121,6 +128,7 @@ public class CrmClueController {
121 Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); 128 Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
122 // 2. 转换成 VO 129 // 2. 转换成 VO
123 return BeanUtils.toBean(list, CrmClueRespVO.class, clueVO -> { 130 return BeanUtils.toBean(list, CrmClueRespVO.class, clueVO -> {
  131 + clueVO.setAreaName(AreaUtils.format(clueVO.getAreaId()));
124 // 2.1 设置客户名称 132 // 2.1 设置客户名称
125 MapUtils.findAndThen(customerMap, clueVO.getCustomerId(), customer -> clueVO.setCustomerName(customer.getName())); 133 MapUtils.findAndThen(customerMap, clueVO.getCustomerId(), customer -> clueVO.setCustomerName(customer.getName()));
126 // 2.2 设置创建人、负责人名称 134 // 2.2 设置创建人、负责人名称
@@ -141,11 +149,12 @@ public class CrmClueController { @@ -141,11 +149,12 @@ public class CrmClueController {
141 return success(true); 149 return success(true);
142 } 150 }
143 151
144 - @PostMapping("/transform") 152 + @PutMapping("/transform")
145 @Operation(summary = "线索转化为客户") 153 @Operation(summary = "线索转化为客户")
  154 + @Parameter(name = "ids", description = "线索编号数组", required = true)
146 @PreAuthorize("@ss.hasPermission('crm:clue:update')") 155 @PreAuthorize("@ss.hasPermission('crm:clue:update')")
147 - public CommonResult<Boolean> translateCustomer(@Valid @RequestBody CrmClueTranslateReqVO reqVO) {  
148 - clueService.translateCustomer(reqVO, getLoginUserId()); 156 + public CommonResult<Boolean> transformClue(@RequestParam("ids") List<Long> ids) {
  157 + clueService.transformClue(ids, getLoginUserId());
149 return success(Boolean.TRUE); 158 return success(Boolean.TRUE);
150 } 159 }
151 160
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java
@@ -17,6 +17,9 @@ public class CrmCluePageReqVO extends PageParam { @@ -17,6 +17,9 @@ public class CrmCluePageReqVO extends PageParam {
17 @Schema(description = "线索名称", example = "线索xxx") 17 @Schema(description = "线索名称", example = "线索xxx")
18 private String name; 18 private String name;
19 19
  20 + @Schema(description = "转化状态", example = "2048")
  21 + private Boolean transformStatus;
  22 +
20 @Schema(description = "电话", example = "18000000000") 23 @Schema(description = "电话", example = "18000000000")
21 private String telephone; 24 private String telephone;
22 25
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java
@@ -13,6 +13,7 @@ import com.mzt.logapi.starter.annotation.DiffLogField; @@ -13,6 +13,7 @@ import com.mzt.logapi.starter.annotation.DiffLogField;
13 import io.swagger.v3.oas.annotations.media.Schema; 13 import io.swagger.v3.oas.annotations.media.Schema;
14 import jakarta.validation.constraints.Email; 14 import jakarta.validation.constraints.Email;
15 import jakarta.validation.constraints.NotEmpty; 15 import jakarta.validation.constraints.NotEmpty;
  16 +import jakarta.validation.constraints.NotNull;
16 import jakarta.validation.constraints.Size; 17 import jakarta.validation.constraints.Size;
17 import lombok.Data; 18 import lombok.Data;
18 import org.springframework.format.annotation.DateTimeFormat; 19 import org.springframework.format.annotation.DateTimeFormat;
@@ -45,6 +46,7 @@ public class CrmClueSaveReqVO { @@ -45,6 +46,7 @@ public class CrmClueSaveReqVO {
45 private LocalDateTime contactNextTime; 46 private LocalDateTime contactNextTime;
46 47
47 @Schema(description = "负责人编号", example = "2048") 48 @Schema(description = "负责人编号", example = "2048")
  49 + @NotNull(message = "负责人编号不能为空")
48 private Long ownerUserId; 50 private Long ownerUserId;
49 51
50 @Schema(description = "手机号", example = "18000000000") 52 @Schema(description = "手机号", example = "18000000000")
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTranslateReqVO.java deleted
1 -package cn.iocoder.yudao.module.crm.controller.admin.clue.vo;  
2 -  
3 -import io.swagger.v3.oas.annotations.media.Schema;  
4 -import jakarta.validation.constraints.NotEmpty;  
5 -import lombok.Data;  
6 -  
7 -import java.util.Set;  
8 -  
9 -@Schema(description = "管理后台 - 线索转化为客户 Request VO")  
10 -@Data  
11 -public class CrmClueTranslateReqVO {  
12 -  
13 - @Schema(description = "线索编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1024, 1025]")  
14 - @NotEmpty(message = "线索编号不能为空")  
15 - private Set<Long> ids;  
16 -  
17 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java
@@ -36,6 +36,7 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; { @@ -36,6 +36,7 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; {
36 // 拼接自身的查询条件 36 // 拼接自身的查询条件
37 query.selectAll(CrmClueDO.class) 37 query.selectAll(CrmClueDO.class)
38 .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) 38 .likeIfPresent(CrmClueDO::getName, pageReqVO.getName())
  39 + .eqIfPresent(CrmClueDO::getTransformStatus, pageReqVO.getTransformStatus())
39 .likeIfPresent(CrmClueDO::getTelephone, pageReqVO.getTelephone()) 40 .likeIfPresent(CrmClueDO::getTelephone, pageReqVO.getTelephone())
40 .likeIfPresent(CrmClueDO::getMobile, pageReqVO.getMobile()) 41 .likeIfPresent(CrmClueDO::getMobile, pageReqVO.getMobile())
41 .eqIfPresent(CrmClueDO::getIndustryId, pageReqVO.getIndustryId()) 42 .eqIfPresent(CrmClueDO::getIndustryId, pageReqVO.getIndustryId())
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java
@@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; 4 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO;
5 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; 5 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO;
6 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; 6 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO;
7 -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTranslateReqVO;  
8 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; 7 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
9 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; 8 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
10 import jakarta.validation.Valid; 9 import jakarta.validation.Valid;
@@ -23,10 +22,9 @@ public interface CrmClueService { @@ -23,10 +22,9 @@ public interface CrmClueService {
23 * 创建线索 22 * 创建线索
24 * 23 *
25 * @param createReqVO 创建信息 24 * @param createReqVO 创建信息
26 - * @param userId 用户编号  
27 * @return 编号 25 * @return 编号
28 */ 26 */
29 - Long createClue(@Valid CrmClueSaveReqVO createReqVO, Long userId); 27 + Long createClue(@Valid CrmClueSaveReqVO createReqVO);
30 28
31 /** 29 /**
32 * 更新线索 30 * 更新线索
@@ -85,10 +83,10 @@ public interface CrmClueService { @@ -85,10 +83,10 @@ public interface CrmClueService {
85 /** 83 /**
86 * 线索转化为客户 84 * 线索转化为客户
87 * 85 *
88 - * @param reqVO 线索编号 86 + * @param ids 线索编号数组
89 * @param userId 用户编号 87 * @param userId 用户编号
90 */ 88 */
91 - void translateCustomer(CrmClueTranslateReqVO reqVO, Long userId); 89 + void transformClue(List<Long> ids, Long userId);
92 90
93 /** 91 /**
94 * 获得分配给我的线索数量 92 * 获得分配给我的线索数量
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
@@ -10,7 +10,6 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -10,7 +10,6 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; 10 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO;
11 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; 11 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO;
12 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; 12 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO;
13 -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTranslateReqVO;  
14 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; 13 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO;
15 import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; 14 import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert;
16 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; 15 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
@@ -36,14 +35,16 @@ import org.springframework.transaction.annotation.Transactional; @@ -36,14 +35,16 @@ import org.springframework.transaction.annotation.Transactional;
36 import org.springframework.validation.annotation.Validated; 35 import org.springframework.validation.annotation.Validated;
37 36
38 import java.time.LocalDateTime; 37 import java.time.LocalDateTime;
39 -import java.util.*; 38 +import java.util.Collection;
  39 +import java.util.List;
  40 +import java.util.Map;
  41 +import java.util.Objects;
40 42
41 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 43 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
42 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 44 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
43 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; 45 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
44 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; 46 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
45 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; 47 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
46 -import static java.util.Collections.singletonList;  
47 48
48 /** 49 /**
49 * 线索 Service 实现类 50 * 线索 Service 实现类
@@ -71,17 +72,13 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -71,17 +72,13 @@ public class CrmClueServiceImpl implements CrmClueService {
71 @Transactional(rollbackFor = Exception.class) 72 @Transactional(rollbackFor = Exception.class)
72 @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}", 73 @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}",
73 success = CRM_LEADS_CREATE_SUCCESS) 74 success = CRM_LEADS_CREATE_SUCCESS)
74 - public Long createClue(CrmClueSaveReqVO createReqVO, Long userId) { 75 + public Long createClue(CrmClueSaveReqVO createReqVO) {
75 // 1.1 校验关联数据 76 // 1.1 校验关联数据
76 validateRelationDataExists(createReqVO); 77 validateRelationDataExists(createReqVO);
77 // 1.2 校验负责人是否存在 78 // 1.2 校验负责人是否存在
78 - if (createReqVO.getOwnerUserId() != null) {  
79 - adminUserApi.validateUserList(singletonList(createReqVO.getOwnerUserId()));  
80 - } else {  
81 - createReqVO.setOwnerUserId(userId); // 如果没有设置负责人那么默认操作人为负责人  
82 - } 79 + adminUserApi.validateUser(createReqVO.getOwnerUserId());
83 80
84 - // 2. 插入 81 + // 2. 插入线索
85 CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class) 82 CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class)
86 .setContactLastTime(LocalDateTime.now()); 83 .setContactLastTime(LocalDateTime.now());
87 clueMapper.insert(clue); 84 clueMapper.insert(clue);
@@ -103,12 +100,12 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -103,12 +100,12 @@ public class CrmClueServiceImpl implements CrmClueService {
103 @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER) 100 @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER)
104 public void updateClue(CrmClueSaveReqVO updateReq) { 101 public void updateClue(CrmClueSaveReqVO updateReq) {
105 Assert.notNull(updateReq.getId(), "线索编号不能为空"); 102 Assert.notNull(updateReq.getId(), "线索编号不能为空");
106 - // 1. 校验线索是否存在 103 + // 1.1 校验线索是否存在
107 CrmClueDO oldClue = validateClueExists(updateReq.getId()); 104 CrmClueDO oldClue = validateClueExists(updateReq.getId());
108 - // 2. 校验关联数据 105 + // 1.2 校验关联数据
109 validateRelationDataExists(updateReq); 106 validateRelationDataExists(updateReq);
110 107
111 - // 3. 更新 108 + // 2. 更新线索
112 CrmClueDO updateObj = BeanUtils.toBean(updateReq, CrmClueDO.class); 109 CrmClueDO updateObj = BeanUtils.toBean(updateReq, CrmClueDO.class);
113 clueMapper.updateById(updateObj); 110 clueMapper.updateById(updateObj);
114 111
@@ -130,7 +127,6 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -130,7 +127,6 @@ public class CrmClueServiceImpl implements CrmClueService {
130 // 3. 记录操作日志上下文 127 // 3. 记录操作日志上下文
131 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmUpdateFollowUpReqBO.class)); 128 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmUpdateFollowUpReqBO.class));
132 LogRecordContext.putVariable("clueName", oldClue.getName()); 129 LogRecordContext.putVariable("clueName", oldClue.getName());
133 -  
134 } 130 }
135 131
136 @Override 132 @Override
@@ -155,12 +151,11 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -155,12 +151,11 @@ public class CrmClueServiceImpl implements CrmClueService {
155 LogRecordContext.putVariable("clueName", clue.getName()); 151 LogRecordContext.putVariable("clueName", clue.getName());
156 } 152 }
157 153
158 -  
159 @Override 154 @Override
160 @Transactional(rollbackFor = Exception.class) 155 @Transactional(rollbackFor = Exception.class)
161 @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}", 156 @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}",
162 success = CRM_LEADS_TRANSFER_SUCCESS) 157 success = CRM_LEADS_TRANSFER_SUCCESS)
163 - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) 158 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER)
164 public void transferClue(CrmClueTransferReqVO reqVO, Long userId) { 159 public void transferClue(CrmClueTransferReqVO reqVO, Long userId) {
165 // 1 校验线索是否存在 160 // 1 校验线索是否存在
166 CrmClueDO clue = validateClueExists(reqVO.getId()); 161 CrmClueDO clue = validateClueExists(reqVO.getId());
@@ -176,20 +171,19 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -176,20 +171,19 @@ public class CrmClueServiceImpl implements CrmClueService {
176 171
177 @Override 172 @Override
178 @Transactional(rollbackFor = Exception.class) 173 @Transactional(rollbackFor = Exception.class)
179 - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)  
180 - public void translateCustomer(CrmClueTranslateReqVO reqVO, Long userId) { 174 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#ids", level = CrmPermissionLevelEnum.OWNER)
  175 + public void transformClue(List<Long> ids, Long userId) {
181 // 1.1 校验线索都存在 176 // 1.1 校验线索都存在
182 - Set<Long> clueIds = reqVO.getIds();  
183 - List<CrmClueDO> clues = getClueList(clueIds, userId);  
184 - if (CollUtil.isEmpty(clues) || ObjectUtil.notEqual(clues.size(), clueIds.size())) {  
185 - clueIds.removeAll(convertSet(clues, CrmClueDO::getId));  
186 - throw exception(CLUE_ANY_CLUE_NOT_EXISTS, clueIds); 177 + List<CrmClueDO> clues = getClueList(ids, userId);
  178 + if (CollUtil.isEmpty(clues) || ObjectUtil.notEqual(clues.size(), ids.size())) {
  179 + ids.removeAll(convertSet(clues, CrmClueDO::getId));
  180 + throw exception(CLUE_NOT_EXISTS_ANY, ids);
187 } 181 }
188 // 1.2 存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了 182 // 1.2 存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了
189 List<CrmClueDO> translatedClues = filterList(clues, 183 List<CrmClueDO> translatedClues = filterList(clues,
190 clue -> ObjectUtil.equal(Boolean.TRUE, clue.getTransformStatus())); 184 clue -> ObjectUtil.equal(Boolean.TRUE, clue.getTransformStatus()));
191 if (CollUtil.isNotEmpty(translatedClues)) { 185 if (CollUtil.isNotEmpty(translatedClues)) {
192 - throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, convertSet(translatedClues, CrmClueDO::getId)); 186 + throw exception(CLUE_TRANSFORM_FAIL_ALREADY, convertSet(translatedClues, CrmClueDO::getId));
193 } 187 }
194 188
195 // 2.1 遍历线索(未转化的线索),创建对应的客户 189 // 2.1 遍历线索(未转化的线索),创建对应的客户