📖 CRM:code review 跟进记录

This commit is contained in:
YunaiV 2024-01-26 23:46:02 +08:00
parent 1a7be60503
commit 814b6f688d
11 changed files with 38 additions and 72 deletions

View File

@ -74,7 +74,7 @@ function stop() {
if [ -n "$PID" ]; then if [ -n "$PID" ]; then
echo -e ".\c" echo -e ".\c"
else else
echo '[stop] 停止 $BASE_PATH/$SERVER_NAME 成功' echo "[stop] 停止 $BASE_PATH/$SERVER_NAME 成功"
break break
fi fi
done done

View File

@ -70,6 +70,8 @@
<groupId>cn.iocoder.boot</groupId> <groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-test</artifactId> <artifactId>yudao-spring-boot-starter-test</artifactId>
</dependency> </dependency>
<!-- TODO @puhui999放的位置要整齐哈。 -->
<dependency> <dependency>
<groupId>cn.iocoder.boot</groupId> <groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId> <artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>

View File

@ -13,76 +13,31 @@ public class CrmOperateLogV2RespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
private Long id; private Long id;
/**
* 链路追踪编号
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
private String traceId;
/**
* 用户编号
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long userId; private Long userId;
/**
* 用户名称
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
private String userName; private String userName;
/**
* 用户类型
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer userType; private Integer userType;
/**
* 操作模块类型
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
private String type; private String type;
/**
* 操作名
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "修改客户") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "修改客户")
private String subType; private String subType;
/**
* 操作模块业务编号
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
private Long bizId; private Long bizId;
/**
* 操作内容
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "将什么从什么改为了什么") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "将什么从什么改为了什么")
private String action; private String action;
/**
* 拓展字段
*/
@Schema(description = "编号", example = "{orderId: 1}") @Schema(description = "编号", example = "{orderId: 1}")
private String extra; private String extra;
/**
* 请求方法名
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
private String requestMethod;
/**
* 请求地址
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
private String requestUrl;
/**
* 用户 IP
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
private String userIp;
/**
* 浏览器 UA
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
private String userAgent;
/**
* 创建时间
*/
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-01-01") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-01-01")
private LocalDateTime createTime; private LocalDateTime createTime;

View File

@ -103,6 +103,7 @@ public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
default List<CrmCustomerDO> selectListByLockStatusAndOwnerUserIdNotNull(Boolean lockStatus) { default List<CrmCustomerDO> selectListByLockStatusAndOwnerUserIdNotNull(Boolean lockStatus) {
return selectList(new LambdaQueryWrapper<CrmCustomerDO>() return selectList(new LambdaQueryWrapper<CrmCustomerDO>()
.eq(CrmCustomerDO::getLockStatus, lockStatus) .eq(CrmCustomerDO::getLockStatus, lockStatus)
// TODO @puhui999not null 可以转化成大于 0
.isNotNull(CrmCustomerDO::getOwnerUserId)); .isNotNull(CrmCustomerDO::getOwnerUserId));
} }

View File

@ -30,6 +30,7 @@ public class CrmPermissionUtils {
return SingletonManager.getPermissionApi().hasAnyRoles(getLoginUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); return SingletonManager.getPermissionApi().hasAnyRoles(getLoginUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode());
} }
// TODO @puhui999这个貌似直接放到 CrmPermissionService 会更好
/** /**
* 校验权限 * 校验权限
* *

View File

@ -1 +1,4 @@
/**
* TODO 芋艿临时占位后续可删除
*/
package cn.iocoder.yudao.module.crm.job; package cn.iocoder.yudao.module.crm.job;

View File

@ -190,32 +190,36 @@ public class CrmClueServiceImpl implements CrmClueService {
throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, convertSet(translatedClues, CrmClueDO::getId)); throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, convertSet(translatedClues, CrmClueDO::getId));
} }
// 2. 遍历线索(未转化的线索)创建对应的客户 // 2.1 遍历线索(未转化的线索)创建对应的客户
clues.forEach(clue -> { clues.forEach(clue -> {
Long customerId = customerService.createCustomer(BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class), userId); Long customerId = customerService.createCustomer(BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class), userId);
clue.setCustomerId(customerId); clue.setCustomerId(customerId);
}); });
// 2.2 更新线索
clueMapper.updateBatch(convertList(clues, clue -> new CrmClueDO().setId(clue.getId())
.setTransformStatus(Boolean.TRUE).setCustomerId(clue.getCustomerId())));
// 2.3 复制跟进记录
copyFollowUpRecords(clues);
// 2.1 更新线索
clueMapper.updateBatch(convertList(clues, clue -> new CrmClueDO().setId(clue.getId()).setTransformStatus(Boolean.TRUE)
.setCustomerId(clue.getCustomerId())));
// 2.3 复制跟进
updateFollowUpRecords(clues);
// 3. 记录操作日志 // 3. 记录操作日志
for (CrmClueDO clue : clues) { for (CrmClueDO clue : clues) {
getSelf().translateCustomerLog(clue); getSelf().translateCustomerLog(clue);
} }
} }
private void updateFollowUpRecords(List<CrmClueDO> clues) { /**
* 线索被转换客户后需要将线索的跟进记录复制到客户上
*
* @param clues 被转化的线索
*/
private void copyFollowUpRecords(List<CrmClueDO> clues) {
List<CrmFollowUpRecordDO> followUpRecords = followUpRecordService.getFollowUpRecordByBiz( List<CrmFollowUpRecordDO> followUpRecords = followUpRecordService.getFollowUpRecordByBiz(
CrmBizTypeEnum.CRM_LEADS.getType(), convertSet(clues, CrmClueDO::getId)); CrmBizTypeEnum.CRM_LEADS.getType(), convertSet(clues, CrmClueDO::getId));
if (CollUtil.isEmpty(followUpRecords)) { if (CollUtil.isEmpty(followUpRecords)) {
return; return;
} }
Map<Long, CrmClueDO> clueMap = convertMap(clues, CrmClueDO::getId);
// 创建跟进 // 创建跟进
Map<Long, CrmClueDO> clueMap = convertMap(clues, CrmClueDO::getId);
followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, followUpRecord -> followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, followUpRecord ->
BeanUtils.toBean(followUpRecord, CrmFollowUpCreateReqBO.class).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) BeanUtils.toBean(followUpRecord, CrmFollowUpCreateReqBO.class).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())
.setBizId(clueMap.get(followUpRecord.getBizId()).getCustomerId()))); .setBizId(clueMap.get(followUpRecord.getBizId()).getCustomerId())));

View File

@ -126,6 +126,7 @@ public interface CrmCustomerService {
*/ */
void receiveCustomer(List<Long> ids, Long ownerUserId, Boolean isReceive); void receiveCustomer(List<Long> ids, Long ownerUserId, Boolean isReceive);
// TODO @puhui999autoPutCustomerPool注释说明是系统就好哈
/** /**
* 系统客户自动掉入公海 * 系统客户自动掉入公海
* *

View File

@ -28,9 +28,9 @@ public interface CrmFollowUpRecordService {
/** /**
* 创建更进 * 创建更进
* *
* @param followUpCreateReqBOs 请求 * @param list 请求
*/ */
void createFollowUpRecordBatch(List<CrmFollowUpCreateReqBO> followUpCreateReqBOs); void createFollowUpRecordBatch(List<CrmFollowUpCreateReqBO> list);
/** /**
* 删除跟进记录 (数据权限基于 bizType bizId) * 删除跟进记录 (数据权限基于 bizType bizId)

View File

@ -93,12 +93,12 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService {
customerService.updateCustomerFollowUp(updateFollowUpReqBO); customerService.updateCustomerFollowUp(updateFollowUpReqBO);
} }
// 3.1 更新 contactIds 对应的记录 // 3.1 更新 contactIds 对应的记录不更新 lastTime lastContent
if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { if (CollUtil.isNotEmpty(createReqVO.getContactIds())) {
contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(),
contactId -> updateFollowUpReqBO.setBizId(contactId).setContactLastTime(null).setContactLastContent(null))); contactId -> updateFollowUpReqBO.setBizId(contactId).setContactLastTime(null).setContactLastContent(null)));
} }
// 3.2 需要更新 businessIdscontactIds 对应的记录 // 3.2 需要更新 businessIds 对应的记录不更新 lastTime lastContent
if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) { if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) {
businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(),
businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null))); businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null)));
@ -107,12 +107,11 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService {
} }
@Override @Override
public void createFollowUpRecordBatch(List<CrmFollowUpCreateReqBO> followUpCreateReqBOs) { public void createFollowUpRecordBatch(List<CrmFollowUpCreateReqBO> list) {
if (CollUtil.isEmpty(followUpCreateReqBOs)) { if (CollUtil.isEmpty(list)) {
return; return;
} }
crmFollowUpRecordMapper.insertBatch(BeanUtils.toBean(list, CrmFollowUpRecordDO.class));
crmFollowUpRecordMapper.insertBatch(BeanUtils.toBean(followUpCreateReqBOs, CrmFollowUpRecordDO.class));
} }
@Override @Override

View File

@ -98,7 +98,7 @@ public interface ErrorCodeConstants {
ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用"); ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用");
ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1_002_014_003, "验证码不正确"); ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1_002_014_003, "验证码不正确");
ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量"); ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量");
ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频"); ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频");
ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1_002_014_006, "手机号已被使用"); ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1_002_014_006, "手机号已被使用");
ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1_002_014_007, "验证码未被使用"); ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1_002_014_007, "验证码未被使用");