Commit 814b6f688d8751f61f16ddc124c41de91bc5270c

Authored by YunaiV
1 parent 1a7be605

📖 CRM:code review 跟进记录

script/shell/deploy.sh
@@ -74,7 +74,7 @@ function stop() { @@ -74,7 +74,7 @@ function stop() {
74 if [ -n "$PID" ]; then 74 if [ -n "$PID" ]; then
75 echo -e ".\c" 75 echo -e ".\c"
76 else 76 else
77 - echo '[stop] 停止 $BASE_PATH/$SERVER_NAME 成功' 77 + echo "[stop] 停止 $BASE_PATH/$SERVER_NAME 成功"
78 break 78 break
79 fi 79 fi
80 done 80 done
yudao-module-crm/yudao-module-crm-biz/pom.xml
@@ -70,6 +70,8 @@ @@ -70,6 +70,8 @@
70 <groupId>cn.iocoder.boot</groupId> 70 <groupId>cn.iocoder.boot</groupId>
71 <artifactId>yudao-spring-boot-starter-test</artifactId> 71 <artifactId>yudao-spring-boot-starter-test</artifactId>
72 </dependency> 72 </dependency>
  73 +
  74 + <!-- TODO @puhui999:放的位置,要整齐哈。 -->
73 <dependency> 75 <dependency>
74 <groupId>cn.iocoder.boot</groupId> 76 <groupId>cn.iocoder.boot</groupId>
75 <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> 77 <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java
@@ -13,76 +13,31 @@ public class CrmOperateLogV2RespVO { @@ -13,76 +13,31 @@ public class CrmOperateLogV2RespVO {
13 13
14 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") 14 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
15 private Long id; 15 private Long id;
16 - /**  
17 - * 链路追踪编号  
18 - */  
19 - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")  
20 - private String traceId;  
21 - /**  
22 - * 用户编号  
23 - */ 16 +
24 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") 17 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
25 private Long userId; 18 private Long userId;
26 - /**  
27 - * 用户名称  
28 - */ 19 +
29 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") 20 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
30 private String userName; 21 private String userName;
31 - /**  
32 - * 用户类型  
33 - */ 22 +
34 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 23 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
35 private Integer userType; 24 private Integer userType;
36 - /**  
37 - * 操作模块类型  
38 - */ 25 +
39 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") 26 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
40 private String type; 27 private String type;
41 - /**  
42 - * 操作名  
43 - */ 28 +
44 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "修改客户") 29 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "修改客户")
45 private String subType; 30 private String subType;
46 - /**  
47 - * 操作模块业务编号  
48 - */ 31 +
49 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") 32 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
50 private Long bizId; 33 private Long bizId;
51 - /**  
52 - * 操作内容  
53 - */ 34 +
54 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "将什么从什么改为了什么") 35 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "将什么从什么改为了什么")
55 private String action; 36 private String action;
56 - /**  
57 - * 拓展字段  
58 - */ 37 +
59 @Schema(description = "编号", example = "{orderId: 1}") 38 @Schema(description = "编号", example = "{orderId: 1}")
60 private String extra; 39 private String extra;
61 40
62 - /**  
63 - * 请求方法名  
64 - */  
65 - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")  
66 - private String requestMethod;  
67 - /**  
68 - * 请求地址  
69 - */  
70 - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")  
71 - private String requestUrl;  
72 - /**  
73 - * 用户 IP  
74 - */  
75 - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")  
76 - private String userIp;  
77 - /**  
78 - * 浏览器 UA  
79 - */  
80 - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")  
81 - private String userAgent;  
82 -  
83 - /**  
84 - * 创建时间  
85 - */  
86 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-01-01") 41 @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-01-01")
87 private LocalDateTime createTime; 42 private LocalDateTime createTime;
88 43
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
@@ -103,6 +103,7 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; { @@ -103,6 +103,7 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
103 default List<CrmCustomerDO> selectListByLockStatusAndOwnerUserIdNotNull(Boolean lockStatus) { 103 default List<CrmCustomerDO> selectListByLockStatusAndOwnerUserIdNotNull(Boolean lockStatus) {
104 return selectList(new LambdaQueryWrapper<CrmCustomerDO>() 104 return selectList(new LambdaQueryWrapper<CrmCustomerDO>()
105 .eq(CrmCustomerDO::getLockStatus, lockStatus) 105 .eq(CrmCustomerDO::getLockStatus, lockStatus)
  106 + // TODO @puhui999:not null 可以转化成大于 0
106 .isNotNull(CrmCustomerDO::getOwnerUserId)); 107 .isNotNull(CrmCustomerDO::getOwnerUserId));
107 } 108 }
108 109
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java
@@ -30,6 +30,7 @@ public class CrmPermissionUtils { @@ -30,6 +30,7 @@ public class CrmPermissionUtils {
30 return SingletonManager.getPermissionApi().hasAnyRoles(getLoginUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); 30 return SingletonManager.getPermissionApi().hasAnyRoles(getLoginUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode());
31 } 31 }
32 32
  33 + // TODO @puhui999:这个貌似直接放到 CrmPermissionService 会更好?
33 /** 34 /**
34 * 校验权限 35 * 校验权限
35 * 36 *
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java
  1 +/**
  2 + * TODO 芋艿:临时占位,后续可删除
  3 + */
1 package cn.iocoder.yudao.module.crm.job; 4 package cn.iocoder.yudao.module.crm.job;
2 \ No newline at end of file 5 \ No newline at end of file
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
@@ -190,32 +190,36 @@ public class CrmClueServiceImpl implements CrmClueService { @@ -190,32 +190,36 @@ public class CrmClueServiceImpl implements CrmClueService {
190 throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, convertSet(translatedClues, CrmClueDO::getId)); 190 throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, convertSet(translatedClues, CrmClueDO::getId));
191 } 191 }
192 192
193 - // 2. 遍历线索(未转化的线索),创建对应的客户 193 + // 2.1 遍历线索(未转化的线索),创建对应的客户
194 clues.forEach(clue -> { 194 clues.forEach(clue -> {
195 Long customerId = customerService.createCustomer(BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class), userId); 195 Long customerId = customerService.createCustomer(BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class), userId);
196 clue.setCustomerId(customerId); 196 clue.setCustomerId(customerId);
197 }); 197 });
  198 + // 2.2 更新线索
  199 + clueMapper.updateBatch(convertList(clues, clue -> new CrmClueDO().setId(clue.getId())
  200 + .setTransformStatus(Boolean.TRUE).setCustomerId(clue.getCustomerId())));
  201 + // 2.3 复制跟进记录
  202 + copyFollowUpRecords(clues);
198 203
199 - // 2.1 更新线索  
200 - clueMapper.updateBatch(convertList(clues, clue -> new CrmClueDO().setId(clue.getId()).setTransformStatus(Boolean.TRUE)  
201 - .setCustomerId(clue.getCustomerId())));  
202 - // 2.3 复制跟进  
203 - updateFollowUpRecords(clues);  
204 // 3. 记录操作日志 204 // 3. 记录操作日志
205 for (CrmClueDO clue : clues) { 205 for (CrmClueDO clue : clues) {
206 getSelf().translateCustomerLog(clue); 206 getSelf().translateCustomerLog(clue);
207 } 207 }
208 } 208 }
209 209
210 - private void updateFollowUpRecords(List<CrmClueDO> clues) { 210 + /**
  211 + * 线索被转换客户后,需要将线索的跟进记录,复制到客户上
  212 + *
  213 + * @param clues 被转化的线索
  214 + */
  215 + private void copyFollowUpRecords(List<CrmClueDO> clues) {
211 List<CrmFollowUpRecordDO> followUpRecords = followUpRecordService.getFollowUpRecordByBiz( 216 List<CrmFollowUpRecordDO> followUpRecords = followUpRecordService.getFollowUpRecordByBiz(
212 CrmBizTypeEnum.CRM_LEADS.getType(), convertSet(clues, CrmClueDO::getId)); 217 CrmBizTypeEnum.CRM_LEADS.getType(), convertSet(clues, CrmClueDO::getId));
213 if (CollUtil.isEmpty(followUpRecords)) { 218 if (CollUtil.isEmpty(followUpRecords)) {
214 return; 219 return;
215 } 220 }
216 -  
217 - Map<Long, CrmClueDO> clueMap = convertMap(clues, CrmClueDO::getId);  
218 // 创建跟进 221 // 创建跟进
  222 + Map<Long, CrmClueDO> clueMap = convertMap(clues, CrmClueDO::getId);
219 followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, followUpRecord -> 223 followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, followUpRecord ->
220 BeanUtils.toBean(followUpRecord, CrmFollowUpCreateReqBO.class).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) 224 BeanUtils.toBean(followUpRecord, CrmFollowUpCreateReqBO.class).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
221 .setBizId(clueMap.get(followUpRecord.getBizId()).getCustomerId()))); 225 .setBizId(clueMap.get(followUpRecord.getBizId()).getCustomerId())));
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
@@ -126,6 +126,7 @@ public interface CrmCustomerService { @@ -126,6 +126,7 @@ public interface CrmCustomerService {
126 */ 126 */
127 void receiveCustomer(List<Long> ids, Long ownerUserId, Boolean isReceive); 127 void receiveCustomer(List<Long> ids, Long ownerUserId, Boolean isReceive);
128 128
  129 + // TODO @puhui999:autoPutCustomerPool,注释说明是系统就好哈;
129 /** 130 /**
130 * 【系统】客户自动掉入公海 131 * 【系统】客户自动掉入公海
131 * 132 *
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java
@@ -28,9 +28,9 @@ public interface CrmFollowUpRecordService { @@ -28,9 +28,9 @@ public interface CrmFollowUpRecordService {
28 /** 28 /**
29 * 创建更进 29 * 创建更进
30 * 30 *
31 - * @param followUpCreateReqBOs 请求 31 + * @param list 请求
32 */ 32 */
33 - void createFollowUpRecordBatch(List<CrmFollowUpCreateReqBO> followUpCreateReqBOs); 33 + void createFollowUpRecordBatch(List<CrmFollowUpCreateReqBO> list);
34 34
35 /** 35 /**
36 * 删除跟进记录 (数据权限基于 bizType、 bizId) 36 * 删除跟进记录 (数据权限基于 bizType、 bizId)
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java
@@ -93,12 +93,12 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { @@ -93,12 +93,12 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService {
93 customerService.updateCustomerFollowUp(updateFollowUpReqBO); 93 customerService.updateCustomerFollowUp(updateFollowUpReqBO);
94 } 94 }
95 95
96 - // 3.1 更新 contactIds 对应的记录 96 + // 3.1 更新 contactIds 对应的记录,不更新 lastTime 和 lastContent
97 if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { 97 if (CollUtil.isNotEmpty(createReqVO.getContactIds())) {
98 contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), 98 contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(),
99 contactId -> updateFollowUpReqBO.setBizId(contactId).setContactLastTime(null).setContactLastContent(null))); 99 contactId -> updateFollowUpReqBO.setBizId(contactId).setContactLastTime(null).setContactLastContent(null)));
100 } 100 }
101 - // 3.2 需要更新 businessIds、contactIds 对应的记录 101 + // 3.2 需要更新 businessIds 对应的记录,不更新 lastTime 和 lastContent
102 if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) { 102 if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) {
103 businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), 103 businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(),
104 businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null))); 104 businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null)));
@@ -107,12 +107,11 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { @@ -107,12 +107,11 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService {
107 } 107 }
108 108
109 @Override 109 @Override
110 - public void createFollowUpRecordBatch(List<CrmFollowUpCreateReqBO> followUpCreateReqBOs) {  
111 - if (CollUtil.isEmpty(followUpCreateReqBOs)) { 110 + public void createFollowUpRecordBatch(List<CrmFollowUpCreateReqBO> list) {
  111 + if (CollUtil.isEmpty(list)) {
112 return; 112 return;
113 } 113 }
114 -  
115 - crmFollowUpRecordMapper.insertBatch(BeanUtils.toBean(followUpCreateReqBOs, CrmFollowUpRecordDO.class)); 114 + crmFollowUpRecordMapper.insertBatch(BeanUtils.toBean(list, CrmFollowUpRecordDO.class));
116 } 115 }
117 116
118 @Override 117 @Override
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
@@ -98,7 +98,7 @@ public interface ErrorCodeConstants { @@ -98,7 +98,7 @@ public interface ErrorCodeConstants {
98 ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用"); 98 ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用");
99 ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1_002_014_003, "验证码不正确"); 99 ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1_002_014_003, "验证码不正确");
100 ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量"); 100 ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量");
101 - ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频率"); 101 + ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频繁");
102 ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1_002_014_006, "手机号已被使用"); 102 ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1_002_014_006, "手机号已被使用");
103 ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1_002_014_007, "验证码未被使用"); 103 ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1_002_014_007, "验证码未被使用");
104 104