Commit 69a974ef02f1ce829dbf20acb9fca72199c12862

Authored by YunaiV
1 parent bac476c1

📖 CRM:线索的跟进逻辑

yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
@@ -16,8 +16,7 @@ public interface ErrorCodeConstants { @@ -16,8 +16,7 @@ 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_NOT_EXISTS_ANY = new ErrorCode(1_020_001_001, "线索【{}】不存在");  
20 - ErrorCode CLUE_TRANSFORM_FAIL_ALREADY = new ErrorCode(1_020_001_002, "线索【{}】已经转化过了,请勿重复转化"); 19 + ErrorCode CLUE_TRANSFORM_FAIL_ALREADY = new ErrorCode(1_020_001_001, "线索已经转化过了,请勿重复转化");
21 20
22 // ========== 商机管理 1-020-002-000 ========== 21 // ========== 商机管理 1-020-002-000 ==========
23 ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在"); 22 ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在");
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
@@ -8,19 +8,21 @@ package cn.iocoder.yudao.module.crm.enums; @@ -8,19 +8,21 @@ package cn.iocoder.yudao.module.crm.enums;
8 */ 8 */
9 public interface LogRecordConstants { 9 public interface LogRecordConstants {
10 10
11 - // ======================= CRM_LEADS 线索 =======================  
12 -  
13 - String CRM_LEADS_TYPE = "CRM 线索";  
14 - String CRM_LEADS_CREATE_SUB_TYPE = "创建线索";  
15 - String CRM_LEADS_CREATE_SUCCESS = "创建了线索{{#clue.name}}";  
16 - String CRM_LEADS_UPDATE_SUB_TYPE = "更新线索";  
17 - String CRM_LEADS_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReq}}";  
18 - String CRM_LEADS_DELETE_SUB_TYPE = "删除线索";  
19 - String CRM_LEADS_DELETE_SUCCESS = "删除了线索【{{#clueName}}】";  
20 - String CRM_LEADS_TRANSFER_SUB_TYPE = "转移线索";  
21 - String CRM_LEADS_TRANSFER_SUCCESS = "将线索【{{#clue.name}}】的负责人从【{getAdminUserById{#clue.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";  
22 - String CRM_LEADS_TRANSLATE_SUB_TYPE = "线索转化为客户";  
23 - String CRM_LEADS_TRANSLATE_SUCCESS = "将线索【{{#clue.name}}】转化为客户"; 11 + // ======================= CRM_CLUE 线索 =======================
  12 +
  13 + String CRM_CLUE_TYPE = "CRM 线索";
  14 + String CRM_CLUE_CREATE_SUB_TYPE = "创建线索";
  15 + String CRM_CLUE_CREATE_SUCCESS = "创建了线索{{#clue.name}}";
  16 + String CRM_CLUE_UPDATE_SUB_TYPE = "更新线索";
  17 + String CRM_CLUE_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReq}}";
  18 + String CRM_CLUE_DELETE_SUB_TYPE = "删除线索";
  19 + String CRM_CLUE_DELETE_SUCCESS = "删除了线索【{{#clueName}}】";
  20 + String CRM_CLUE_TRANSFER_SUB_TYPE = "转移线索";
  21 + String CRM_CLUE_TRANSFER_SUCCESS = "将线索【{{#clue.name}}】的负责人从【{getAdminUserById{#clue.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
  22 + String CRM_CLUE_TRANSLATE_SUB_TYPE = "线索转化为客户";
  23 + String CRM_CLUE_TRANSLATE_SUCCESS = "将线索【{{#clueName}}】转化为客户";
  24 + String CRM_CLUE_FOLLOW_UP_SUB_TYPE = "线索跟进";
  25 + String CRM_CLUE_FOLLOW_UP_SUCCESS = "线索跟进【{{#clueName}}】";
24 26
25 // ======================= CRM_CUSTOMER 客户 ======================= 27 // ======================= CRM_CUSTOMER 客户 =======================
26 28
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java
@@ -17,7 +17,7 @@ import java.util.Arrays; @@ -17,7 +17,7 @@ import java.util.Arrays;
17 @Getter 17 @Getter
18 public enum CrmBizTypeEnum implements IntArrayValuable { 18 public enum CrmBizTypeEnum implements IntArrayValuable {
19 19
20 - CRM_LEADS(1, "线索"), 20 + CRM_CLUE(1, "线索"),
21 CRM_CUSTOMER(2, "客户"), 21 CRM_CUSTOMER(2, "客户"),
22 CRM_CONTACT(3, "联系人"), 22 CRM_CONTACT(3, "联系人"),
23 CRM_BUSINESS(4, "商机"), 23 CRM_BUSINESS(4, "商机"),
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java
@@ -9,7 +9,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -9,7 +9,10 @@ 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.ip.core.utils.AreaUtils;
11 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 11 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
12 -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; 12 +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO;
  13 +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueRespVO;
  14 +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO;
  15 +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO;
13 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; 16 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
14 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 17 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
15 import cn.iocoder.yudao.module.crm.service.clue.CrmClueService; 18 import cn.iocoder.yudao.module.crm.service.clue.CrmClueService;
@@ -36,7 +39,8 @@ import java.util.stream.Stream; @@ -36,7 +39,8 @@ import java.util.stream.Stream;
36 39
37 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 40 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
38 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; 41 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
39 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 42 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
  43 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
40 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 44 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
41 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 45 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
42 46
@@ -151,18 +155,18 @@ public class CrmClueController { @@ -151,18 +155,18 @@ public class CrmClueController {
151 155
152 @PutMapping("/transform") 156 @PutMapping("/transform")
153 @Operation(summary = "线索转化为客户") 157 @Operation(summary = "线索转化为客户")
154 - @Parameter(name = "ids", description = "线索编号数组", required = true) 158 + @Parameter(name = "id", description = "编号", required = true)
155 @PreAuthorize("@ss.hasPermission('crm:clue:update')") 159 @PreAuthorize("@ss.hasPermission('crm:clue:update')")
156 - public CommonResult<Boolean> transformClue(@RequestParam("ids") List<Long> ids) {  
157 - clueService.transformClue(ids, getLoginUserId()); 160 + public CommonResult<Boolean> transformClue(@RequestParam("id") Long id) {
  161 + clueService.transformClue(id, getLoginUserId());
158 return success(Boolean.TRUE); 162 return success(Boolean.TRUE);
159 } 163 }
160 164
161 - @GetMapping("/follow-leads-count")  
162 - @Operation(summary = "获得分配给我的线索数量") 165 + @GetMapping("/follow-count")
  166 + @Operation(summary = "获得分配给我的、待跟进的线索数量")
163 @PreAuthorize("@ss.hasPermission('crm:clue:query')") 167 @PreAuthorize("@ss.hasPermission('crm:clue:query')")
164 - public CommonResult<Long> getFollowLeadsCount() {  
165 - return success(clueService.getFollowLeadsCount(getLoginUserId())); 168 + public CommonResult<Long> getFollowClueCount() {
  169 + return success(clueService.getFollowClueCount(getLoginUserId()));
166 } 170 }
167 171
168 } 172 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java
@@ -41,7 +41,7 @@ public class CrmOperateLogController { @@ -41,7 +41,7 @@ public class CrmOperateLogController {
41 private static final Map<Integer, String> BIZ_TYPE_MAP = new HashMap<>(); 41 private static final Map<Integer, String> BIZ_TYPE_MAP = new HashMap<>();
42 42
43 static { 43 static {
44 - BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_LEADS.getType(), CRM_LEADS_TYPE); 44 + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CLUE.getType(), CRM_CLUE_TYPE);
45 BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CUSTOMER.getType(), CRM_CUSTOMER_TYPE); 45 BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CUSTOMER.getType(), CRM_CUSTOMER_TYPE);
46 BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CONTACT.getType(), CRM_CONTACT_TYPE); 46 BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CONTACT.getType(), CRM_CONTACT_TYPE);
47 BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_BUSINESS.getType(), CRM_BUSINESS_TYPE); 47 BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_BUSINESS.getType(), CRM_BUSINESS_TYPE);
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java deleted
1 -package cn.iocoder.yudao.module.crm.convert.clue;  
2 -  
3 -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO;  
4 -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;  
5 -import org.mapstruct.Mapper;  
6 -import org.mapstruct.Mapping;  
7 -import org.mapstruct.factory.Mappers;  
8 -  
9 -/**  
10 - * 线索 Convert  
11 - *  
12 - * @author Wanwan  
13 - */  
14 -@Mapper  
15 -public interface CrmClueConvert {  
16 -  
17 - CrmClueConvert INSTANCE = Mappers.getMapper(CrmClueConvert.class);  
18 -  
19 - @Mapping(target = "bizId", source = "reqVO.id")  
20 - CrmPermissionTransferReqBO convert(CrmClueTransferReqVO reqVO, Long userId);  
21 -  
22 -}  
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java
@@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; @@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
8 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 8 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
9 import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; 9 import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
10 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; 10 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
11 -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;  
12 import org.apache.ibatis.annotations.Mapper; 11 import org.apache.ibatis.annotations.Mapper;
13 12
14 import java.util.Collection; 13 import java.util.Collection;
@@ -22,16 +21,10 @@ import java.util.List; @@ -22,16 +21,10 @@ import java.util.List;
22 @Mapper 21 @Mapper
23 public interface CrmClueMapper extends BaseMapperX<CrmClueDO> { 22 public interface CrmClueMapper extends BaseMapperX<CrmClueDO> {
24 23
25 - default int updateOwnerUserIdById(Long id, Long ownerUserId) {  
26 - return update(new LambdaUpdateWrapper<CrmClueDO>()  
27 - .eq(CrmClueDO::getId, id)  
28 - .set(CrmClueDO::getOwnerUserId, ownerUserId));  
29 - }  
30 -  
31 default PageResult<CrmClueDO> selectPage(CrmCluePageReqVO pageReqVO, Long userId) { 24 default PageResult<CrmClueDO> selectPage(CrmCluePageReqVO pageReqVO, Long userId) {
32 MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>(); 25 MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>();
33 // 拼接数据权限的查询条件 26 // 拼接数据权限的查询条件
34 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), 27 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(),
35 CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); 28 CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool());
36 // 拼接自身的查询条件 29 // 拼接自身的查询条件
37 query.selectAll(CrmClueDO.class) 30 query.selectAll(CrmClueDO.class)
@@ -50,16 +43,16 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; { @@ -50,16 +43,16 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; {
50 default List<CrmClueDO> selectBatchIds(Collection<Long> ids, Long userId) { 43 default List<CrmClueDO> selectBatchIds(Collection<Long> ids, Long userId) {
51 MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>(); 44 MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>();
52 // 拼接数据权限的查询条件 45 // 拼接数据权限的查询条件
53 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId); 46 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(), ids, userId);
54 query.selectAll(CrmClueDO.class).in(CrmClueDO::getId, ids).orderByDesc(CrmClueDO::getId); 47 query.selectAll(CrmClueDO.class).in(CrmClueDO::getId, ids).orderByDesc(CrmClueDO::getId);
55 // 拼接自身的查询条件 48 // 拼接自身的查询条件
56 return selectJoinList(CrmClueDO.class, query); 49 return selectJoinList(CrmClueDO.class, query);
57 } 50 }
58 51
59 - default Long selectFollowLeadsCount(Long userId) { 52 + default Long selectCountByFollow(Long userId) {
60 MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>(); 53 MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>();
61 // 我负责的 + 非公海 54 // 我负责的 + 非公海
62 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), 55 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CLUE.getType(),
63 CrmClueDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); 56 CrmClueDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
64 // 未跟进 + 未转化 57 // 未跟进 + 未转化
65 query.eq(CrmClueDO::getFollowUpStatus, false) 58 query.eq(CrmClueDO::getFollowUpStatus, false)
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java
@@ -5,9 +5,9 @@ import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; @@ -5,9 +5,9 @@ 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.dal.dataobject.clue.CrmClueDO; 7 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
8 -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;  
9 import jakarta.validation.Valid; 8 import jakarta.validation.Valid;
10 9
  10 +import java.time.LocalDateTime;
11 import java.util.Collection; 11 import java.util.Collection;
12 import java.util.List; 12 import java.util.List;
13 13
@@ -36,9 +36,11 @@ public interface CrmClueService { @@ -36,9 +36,11 @@ public interface CrmClueService {
36 /** 36 /**
37 * 更新线索相关的跟进信息 37 * 更新线索相关的跟进信息
38 * 38 *
39 - * @param clueUpdateFollowUpReqBO 信息 39 + * @param id 编号
  40 + * @param contactNextTime 下次联系时间
  41 + * @param contactLastContent 最后联系内容
40 */ 42 */
41 - void updateClueFollowUp(CrmUpdateFollowUpReqBO clueUpdateFollowUpReqBO); 43 + void updateClueFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
42 44
43 /** 45 /**
44 * 删除线索 46 * 删除线索
@@ -83,17 +85,17 @@ public interface CrmClueService { @@ -83,17 +85,17 @@ public interface CrmClueService {
83 /** 85 /**
84 * 线索转化为客户 86 * 线索转化为客户
85 * 87 *
86 - * @param ids 线索编号数组 88 + * @param id 线索编号
87 * @param userId 用户编号 89 * @param userId 用户编号
88 */ 90 */
89 - void transformClue(List<Long> ids, Long userId); 91 + void transformClue(Long id, Long userId);
90 92
91 /** 93 /**
92 - * 获得分配给我的线索数量 94 + * 获得分配给我的、待跟进的线索数量
93 * 95 *
94 * @param userId 用户编号 96 * @param userId 用户编号
95 - * @return 提醒数量 97 + * @return 数量
96 */ 98 */
97 - Long getFollowLeadsCount(Long userId); 99 + Long getFollowClueCount(Long userId);
98 100
99 } 101 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
@@ -3,15 +3,12 @@ package cn.iocoder.yudao.module.crm.service.clue; @@ -3,15 +3,12 @@ package cn.iocoder.yudao.module.crm.service.clue;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.collection.ListUtil; 4 import cn.hutool.core.collection.ListUtil;
5 import cn.hutool.core.lang.Assert; 5 import cn.hutool.core.lang.Assert;
6 -import cn.hutool.core.util.ObjectUtil;  
7 -import cn.hutool.extra.spring.SpringUtil;  
8 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; 8 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO;
11 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; 9 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO;
12 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; 10 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO;
13 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; 11 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO;
14 -import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert;  
15 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; 12 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
16 import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; 13 import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO;
17 import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; 14 import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper;
@@ -25,6 +22,7 @@ import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; @@ -25,6 +22,7 @@ import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO;
25 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; 22 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
26 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; 23 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
27 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; 24 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
  25 +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
28 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 26 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
29 import com.mzt.logapi.context.LogRecordContext; 27 import com.mzt.logapi.context.LogRecordContext;
30 import com.mzt.logapi.service.impl.DiffParseFunction; 28 import com.mzt.logapi.service.impl.DiffParseFunction;
@@ -37,12 +35,13 @@ import org.springframework.validation.annotation.Validated; @@ -37,12 +35,13 @@ import org.springframework.validation.annotation.Validated;
37 import java.time.LocalDateTime; 35 import java.time.LocalDateTime;
38 import java.util.Collection; 36 import java.util.Collection;
39 import java.util.List; 37 import java.util.List;
40 -import java.util.Map;  
41 import java.util.Objects; 38 import java.util.Objects;
42 39
43 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 40 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
44 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;  
45 -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; 41 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  42 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.singleton;
  43 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CLUE_NOT_EXISTS;
  44 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CLUE_TRANSFORM_FAIL_ALREADY;
46 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; 45 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
47 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; 46 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
48 47
@@ -60,18 +59,18 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -60,18 +59,18 @@ public class CrmClueServiceImpl implements CrmClueService {
60 59
61 @Resource 60 @Resource
62 private CrmCustomerService customerService; 61 private CrmCustomerService customerService;
63 -  
64 @Resource 62 @Resource
65 private CrmPermissionService crmPermissionService; 63 private CrmPermissionService crmPermissionService;
66 @Resource 64 @Resource
67 private CrmFollowUpRecordService followUpRecordService; 65 private CrmFollowUpRecordService followUpRecordService;
  66 +
68 @Resource 67 @Resource
69 private AdminUserApi adminUserApi; 68 private AdminUserApi adminUserApi;
70 69
71 @Override 70 @Override
72 @Transactional(rollbackFor = Exception.class) 71 @Transactional(rollbackFor = Exception.class)
73 - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}",  
74 - success = CRM_LEADS_CREATE_SUCCESS) 72 + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}",
  73 + success = CRM_CLUE_CREATE_SUCCESS)
75 public Long createClue(CrmClueSaveReqVO createReqVO) { 74 public Long createClue(CrmClueSaveReqVO createReqVO) {
76 // 1.1 校验关联数据 75 // 1.1 校验关联数据
77 validateRelationDataExists(createReqVO); 76 validateRelationDataExists(createReqVO);
@@ -84,7 +83,7 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -84,7 +83,7 @@ public class CrmClueServiceImpl implements CrmClueService {
84 clueMapper.insert(clue); 83 clueMapper.insert(clue);
85 84
86 // 3. 创建数据权限 85 // 3. 创建数据权限
87 - CrmPermissionCreateReqBO createReqBO = new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_LEADS.getType()) 86 + CrmPermissionCreateReqBO createReqBO = new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CLUE.getType())
88 .setBizId(clue.getId()).setUserId(clue.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()); 87 .setBizId(clue.getId()).setUserId(clue.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel());
89 crmPermissionService.createPermission(createReqBO); 88 crmPermissionService.createPermission(createReqBO);
90 89
@@ -95,9 +94,9 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -95,9 +94,9 @@ public class CrmClueServiceImpl implements CrmClueService {
95 94
96 @Override 95 @Override
97 @Transactional(rollbackFor = Exception.class) 96 @Transactional(rollbackFor = Exception.class)
98 - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",  
99 - success = CRM_LEADS_UPDATE_SUCCESS)  
100 - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER) 97 + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
  98 + success = CRM_CLUE_UPDATE_SUCCESS)
  99 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER)
101 public void updateClue(CrmClueSaveReqVO updateReq) { 100 public void updateClue(CrmClueSaveReqVO updateReq) {
102 Assert.notNull(updateReq.getId(), "线索编号不能为空"); 101 Assert.notNull(updateReq.getId(), "线索编号不能为空");
103 // 1.1 校验线索是否存在 102 // 1.1 校验线索是否存在
@@ -114,15 +113,25 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -114,15 +113,25 @@ public class CrmClueServiceImpl implements CrmClueService {
114 LogRecordContext.putVariable("clueName", oldClue.getName()); 113 LogRecordContext.putVariable("clueName", oldClue.getName());
115 } 114 }
116 115
  116 + private void validateRelationDataExists(CrmClueSaveReqVO reqVO) {
  117 + // 校验负责人
  118 + if (Objects.nonNull(reqVO.getOwnerUserId()) &&
  119 + Objects.isNull(adminUserApi.getUser(reqVO.getOwnerUserId()))) {
  120 + throw exception(USER_NOT_EXISTS);
  121 + }
  122 + }
  123 +
117 @Override 124 @Override
118 - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_UPDATE_SUB_TYPE, bizNo = "{{#updateReq.bizId}",  
119 - success = CRM_LEADS_UPDATE_SUCCESS)  
120 - public void updateClueFollowUp(CrmUpdateFollowUpReqBO updateReq) { 125 + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}",
  126 + success = CRM_CLUE_FOLLOW_UP_SUCCESS)
  127 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
  128 + public void updateClueFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {
121 // 校验线索是否存在 129 // 校验线索是否存在
122 - CrmClueDO oldClue = validateClueExists(updateReq.getBizId()); 130 + CrmClueDO oldClue = validateClueExists(id);
123 131
124 // 更新 132 // 更新
125 - clueMapper.updateById(BeanUtils.toBean(updateReq, CrmClueDO.class).setId(updateReq.getBizId())); 133 + clueMapper.updateById(new CrmClueDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime)
  134 + .setContactLastTime(LocalDateTime.now()).setContactLastContent(contactLastContent));
126 135
127 // 3. 记录操作日志上下文 136 // 3. 记录操作日志上下文
128 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmUpdateFollowUpReqBO.class)); 137 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmUpdateFollowUpReqBO.class));
@@ -131,9 +140,9 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -131,9 +140,9 @@ public class CrmClueServiceImpl implements CrmClueService {
131 140
132 @Override 141 @Override
133 @Transactional(rollbackFor = Exception.class) 142 @Transactional(rollbackFor = Exception.class)
134 - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_DELETE_SUB_TYPE, bizNo = "{{#id}}",  
135 - success = CRM_LEADS_DELETE_SUCCESS)  
136 - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) 143 + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_DELETE_SUB_TYPE, bizNo = "{{#id}}",
  144 + success = CRM_CLUE_DELETE_SUCCESS)
  145 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
137 public void deleteClue(Long id) { 146 public void deleteClue(Long id) {
138 // 1. 校验存在 147 // 1. 校验存在
139 CrmClueDO clue = validateClueExists(id); 148 CrmClueDO clue = validateClueExists(id);
@@ -142,28 +151,29 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -142,28 +151,29 @@ public class CrmClueServiceImpl implements CrmClueService {
142 clueMapper.deleteById(id); 151 clueMapper.deleteById(id);
143 152
144 // 3. 删除数据权限 153 // 3. 删除数据权限
145 - crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_LEADS.getType(), id); 154 + crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CLUE.getType(), id);
146 155
147 // 4. 删除跟进 156 // 4. 删除跟进
148 - followUpRecordService.deleteFollowUpRecordByBiz(CrmBizTypeEnum.CRM_LEADS.getType(), id); 157 + followUpRecordService.deleteFollowUpRecordByBiz(CrmBizTypeEnum.CRM_CLUE.getType(), id);
149 158
150 - // 记录操作日志上下文 159 + // 5. 记录操作日志上下文
151 LogRecordContext.putVariable("clueName", clue.getName()); 160 LogRecordContext.putVariable("clueName", clue.getName());
152 } 161 }
153 162
154 @Override 163 @Override
155 @Transactional(rollbackFor = Exception.class) 164 @Transactional(rollbackFor = Exception.class)
156 - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}",  
157 - success = CRM_LEADS_TRANSFER_SUCCESS)  
158 - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) 165 + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}",
  166 + success = CRM_CLUE_TRANSFER_SUCCESS)
  167 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER)
159 public void transferClue(CrmClueTransferReqVO reqVO, Long userId) { 168 public void transferClue(CrmClueTransferReqVO reqVO, Long userId) {
160 // 1 校验线索是否存在 169 // 1 校验线索是否存在
161 CrmClueDO clue = validateClueExists(reqVO.getId()); 170 CrmClueDO clue = validateClueExists(reqVO.getId());
162 171
163 // 2.1 数据权限转移 172 // 2.1 数据权限转移
164 - crmPermissionService.transferPermission(CrmClueConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_LEADS.getType())); 173 + crmPermissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CLUE.getType(),
  174 + reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel()));
165 // 2.2 设置新的负责人 175 // 2.2 设置新的负责人
166 - clueMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); 176 + clueMapper.updateById(new CrmClueDO().setId(reqVO.getId()).setOwnerUserId(reqVO.getNewOwnerUserId()));
167 177
168 // 3. 记录转移日志 178 // 3. 记录转移日志
169 LogRecordContext.putVariable("clue", clue); 179 LogRecordContext.putVariable("clue", clue);
@@ -171,69 +181,32 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -171,69 +181,32 @@ public class CrmClueServiceImpl implements CrmClueService {
171 181
172 @Override 182 @Override
173 @Transactional(rollbackFor = Exception.class) 183 @Transactional(rollbackFor = Exception.class)
174 - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#ids", level = CrmPermissionLevelEnum.OWNER)  
175 - public void transformClue(List<Long> ids, Long userId) { 184 + @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_TRANSLATE_SUB_TYPE, bizNo = "{{#id}}",
  185 + success = CRM_CLUE_TRANSLATE_SUCCESS)
  186 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
  187 + public void transformClue(Long id, Long userId) {
176 // 1.1 校验线索都存在 188 // 1.1 校验线索都存在
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);  
181 - }  
182 - // 1.2 存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了  
183 - List<CrmClueDO> translatedClues = filterList(clues,  
184 - clue -> ObjectUtil.equal(Boolean.TRUE, clue.getTransformStatus()));  
185 - if (CollUtil.isNotEmpty(translatedClues)) {  
186 - throw exception(CLUE_TRANSFORM_FAIL_ALREADY, convertSet(translatedClues, CrmClueDO::getId)); 189 + CrmClueDO clue = validateClueExists(id);
  190 + // 1.2 存在已经转化的
  191 + if (clue.getTransformStatus()) {
  192 + throw exception(CLUE_TRANSFORM_FAIL_ALREADY);
187 } 193 }
188 194
189 // 2.1 遍历线索(未转化的线索),创建对应的客户 195 // 2.1 遍历线索(未转化的线索),创建对应的客户
190 - clues.forEach(clue -> {  
191 - Long customerId = customerService.createCustomer(BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class), userId);  
192 - clue.setCustomerId(customerId);  
193 - }); 196 + Long customerId = customerService.createCustomer(BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class), userId);
194 // 2.2 更新线索 197 // 2.2 更新线索
195 - clueMapper.updateBatch(convertList(clues, clue -> new CrmClueDO().setId(clue.getId())  
196 - .setTransformStatus(Boolean.TRUE).setCustomerId(clue.getCustomerId()))); 198 + clueMapper.updateById(new CrmClueDO().setId(id).setTransformStatus(Boolean.TRUE).setCustomerId(customerId));
197 // 2.3 复制跟进记录 199 // 2.3 复制跟进记录
198 - copyFollowUpRecords(clues);  
199 -  
200 - // 3. 记录操作日志  
201 - for (CrmClueDO clue : clues) {  
202 - getSelf().translateCustomerLog(clue);  
203 - }  
204 - }  
205 -  
206 - /**  
207 - * 线索被转换客户后,需要将线索的跟进记录,复制到客户上  
208 - *  
209 - * @param clues 被转化的线索  
210 - */  
211 - private void copyFollowUpRecords(List<CrmClueDO> clues) {  
212 List<CrmFollowUpRecordDO> followUpRecords = followUpRecordService.getFollowUpRecordByBiz( 200 List<CrmFollowUpRecordDO> followUpRecords = followUpRecordService.getFollowUpRecordByBiz(
213 - CrmBizTypeEnum.CRM_LEADS.getType(), convertSet(clues, CrmClueDO::getId));  
214 - if (CollUtil.isEmpty(followUpRecords)) {  
215 - return; 201 + CrmBizTypeEnum.CRM_CLUE.getType(), singleton(clue.getId()));
  202 + if (CollUtil.isNotEmpty(followUpRecords)) {
  203 + followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, record ->
  204 + BeanUtils.toBean(record, CrmFollowUpCreateReqBO.class)
  205 + .setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()).setBizId(customerId)));
216 } 206 }
217 - // 创建跟进  
218 - Map<Long, CrmClueDO> clueMap = convertMap(clues, CrmClueDO::getId);  
219 - followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, followUpRecord ->  
220 - BeanUtils.toBean(followUpRecord, CrmFollowUpCreateReqBO.class).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())  
221 - .setBizId(clueMap.get(followUpRecord.getBizId()).getCustomerId())));  
222 - }  
223 -  
224 - @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSLATE_SUB_TYPE, bizNo = "{{#clue.id}}",  
225 - success = CRM_LEADS_TRANSLATE_SUCCESS)  
226 - public void translateCustomerLog(CrmClueDO clue) {  
227 - // 记录操作日志上下文  
228 - LogRecordContext.putVariable("clue", clue);  
229 - }  
230 207
231 - private void validateRelationDataExists(CrmClueSaveReqVO reqVO) {  
232 - // 校验负责人  
233 - if (Objects.nonNull(reqVO.getOwnerUserId()) &&  
234 - Objects.isNull(adminUserApi.getUser(reqVO.getOwnerUserId()))) {  
235 - throw exception(USER_NOT_EXISTS);  
236 - } 208 + // 3. 记录操作日志上下文
  209 + LogRecordContext.putVariable("clueName", clue.getName());
237 } 210 }
238 211
239 private CrmClueDO validateClueExists(Long id) { 212 private CrmClueDO validateClueExists(Long id) {
@@ -245,7 +218,7 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -245,7 +218,7 @@ public class CrmClueServiceImpl implements CrmClueService {
245 } 218 }
246 219
247 @Override 220 @Override
248 - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.READ) 221 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#id", level = CrmPermissionLevelEnum.READ)
249 public CrmClueDO getClue(Long id) { 222 public CrmClueDO getClue(Long id) {
250 return clueMapper.selectById(id); 223 return clueMapper.selectById(id);
251 } 224 }
@@ -263,18 +236,9 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -263,18 +236,9 @@ public class CrmClueServiceImpl implements CrmClueService {
263 return clueMapper.selectPage(pageReqVO, userId); 236 return clueMapper.selectPage(pageReqVO, userId);
264 } 237 }
265 238
266 - /**  
267 - * 获得自身的代理对象,解决 AOP 生效问题  
268 - *  
269 - * @return 自己  
270 - */  
271 - private CrmClueServiceImpl getSelf() {  
272 - return SpringUtil.getBean(getClass());  
273 - }  
274 -  
275 @Override 239 @Override
276 - public Long getFollowLeadsCount(Long userId) {  
277 - return clueMapper.selectFollowLeadsCount(userId); 240 + public Long getFollowClueCount(Long userId) {
  241 + return clueMapper.selectCountByFollow(userId);
278 } 242 }
279 243
280 } 244 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java
@@ -79,8 +79,8 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { @@ -79,8 +79,8 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService {
79 if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { // 更新商机跟进信息 79 if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { // 更新商机跟进信息
80 businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); 80 businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO));
81 } 81 }
82 - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_LEADS.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息  
83 - clueService.updateClueFollowUp(updateFollowUpReqBO); 82 + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CLUE.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息
  83 + clueService.updateClueFollowUp(followUpRecord.getId(), followUpRecord.getNextTime(), followUpRecord.getContent());
84 } 84 }
85 if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { // 更新联系人跟进信息 85 if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { // 更新联系人跟进信息
86 contactService.updateContactFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); 86 contactService.updateContactFollowUpBatch(Collections.singletonList(updateFollowUpReqBO));
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionTransferReqBO.java
@@ -3,9 +3,11 @@ package cn.iocoder.yudao.module.crm.service.permission.bo; @@ -3,9 +3,11 @@ package cn.iocoder.yudao.module.crm.service.permission.bo;
3 import cn.iocoder.yudao.framework.common.validation.InEnum; 3 import cn.iocoder.yudao.framework.common.validation.InEnum;
4 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 4 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
5 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; 5 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
  6 +import lombok.AllArgsConstructor;
6 import lombok.Data; 7 import lombok.Data;
7 8
8 import jakarta.validation.constraints.NotNull; 9 import jakarta.validation.constraints.NotNull;
  10 +import lombok.NoArgsConstructor;
9 11
10 /** 12 /**
11 * 数据权限转移 Request BO 13 * 数据权限转移 Request BO
@@ -13,6 +15,8 @@ import jakarta.validation.constraints.NotNull; @@ -13,6 +15,8 @@ import jakarta.validation.constraints.NotNull;
13 * @author HUIHUI 15 * @author HUIHUI
14 */ 16 */
15 @Data 17 @Data
  18 +@NoArgsConstructor
  19 +@AllArgsConstructor
16 public class CrmPermissionTransferReqBO { 20 public class CrmPermissionTransferReqBO {
17 21
18 /** 22 /**