From ca9f3c522d9c0d89a9168e5c630d5b583c81057c Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 22 Jan 2024 22:46:52 +0800 Subject: [PATCH] =?UTF-8?q?CRM-=E7=BA=BF=E7=B4=A2=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 6 +- .../admin/clue/vo/CrmClueSaveReqVO.java | 8 ++ .../crm/service/clue/CrmClueServiceImpl.java | 114 ++++++++++++------ 3 files changed, 90 insertions(+), 38 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java index 198886e68..a0b4559ef 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java @@ -14,9 +14,13 @@ public interface LogRecordConstants { String CRM_LEADS_CREATE_SUB_TYPE = "创建线索"; String CRM_LEADS_CREATE_SUCCESS = "创建了线索{{#clue.name}}"; String CRM_LEADS_UPDATE_SUB_TYPE = "更新线索"; - String CRM_LEADS_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReqVO}}"; + String CRM_LEADS_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReq}}"; String CRM_LEADS_DELETE_SUB_TYPE = "删除线索"; String CRM_LEADS_DELETE_SUCCESS = "删除了线索【{{#clueName}}】"; + String CRM_LEADS_TRANSFER_SUB_TYPE = "转移线索"; + String CRM_LEADS_TRANSFER_SUCCESS = "将线索【{{#clue.name}}】的负责人从【{getAdminUserById{#clue.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; + String CRM_LEADS_TRANSLATE_SUB_TYPE = "线索转化为客户"; + String CRM_LEADS_TRANSLATE_SUCCESS = "将线索【{{#clue.name}}】转化为客户"; // ======================= CRM_CUSTOMER 客户 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java index adbc650b9..8ceaae2c8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; import cn.iocoder.yudao.framework.common.validation.Mobile; import cn.iocoder.yudao.framework.common.validation.Telephone; +import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import lombok.Data; @@ -19,32 +20,39 @@ public class CrmClueSaveReqVO { private Long id; @Schema(description = "线索名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "线索xxx") + @DiffLogField(name = "线索名称") @NotEmpty(message = "线索名称不能为空") private String name; @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") + @DiffLogField(name = "下次联系时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime contactNextTime; @Schema(description = "电话", example = "18000000000") + @DiffLogField(name = "电话") @Telephone private String telephone; @Schema(description = "手机号", example = "18000000000") + @DiffLogField(name = "手机号") @Mobile private String mobile; @Schema(description = "地址", example = "北京市海淀区") + @DiffLogField(name = "地址") private String address; @Schema(description = "最后跟进时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @DiffLogField(name = "最后跟进时间") private LocalDateTime contactLastTime; @Schema(description = "负责人编号", example = "2048") private Long ownerUserId; @Schema(description = "备注", example = "随便") + @DiffLogField(name = "备注") private String remark; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 898a576a0..da721ef5a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; @@ -76,7 +77,7 @@ public class CrmClueServiceImpl implements CrmClueService { validateRelationDataExists(createReqVO); // 2. 插入 - CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class); + CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class).setId(null); if (ObjUtil.isNull(createReqVO.getOwnerUserId())) { clue.setOwnerUserId(userId); // 如果没有设置负责人那么默认操作人为负责人 } else { @@ -99,16 +100,16 @@ public class CrmClueServiceImpl implements CrmClueService { @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", success = CRM_LEADS_UPDATE_SUCCESS) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) - public void updateClue(CrmClueSaveReqVO updateReqVO) { - Assert.notNull(updateReqVO.getId(), "线索编号不能为空"); + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER) + public void updateClue(CrmClueSaveReqVO updateReq) { + Assert.notNull(updateReq.getId(), "线索编号不能为空"); // 1. 校验线索是否存在 - CrmClueDO oldClue = validateClueExists(updateReqVO.getId()); + CrmClueDO oldClue = validateClueExists(updateReq.getId()); // 2. 校验关联数据 - validateRelationDataExists(updateReqVO); + validateRelationDataExists(updateReq); // 3. 更新 - CrmClueDO updateObj = BeanUtils.toBean(updateReqVO, CrmClueDO.class); + CrmClueDO updateObj = BeanUtils.toBean(updateReq, CrmClueDO.class); clueMapper.updateById(updateObj); // 3. 记录操作日志上下文 @@ -117,8 +118,19 @@ public class CrmClueServiceImpl implements CrmClueService { } @Override - public void updateClueFollowUp(CrmUpdateFollowUpReqBO clueUpdateFollowUpReqBO) { - clueMapper.updateById(BeanUtils.toBean(clueUpdateFollowUpReqBO, CrmClueDO.class).setId(clueUpdateFollowUpReqBO.getBizId())); + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_UPDATE_SUB_TYPE, bizNo = "{{#updateReq.bizId}", + success = CRM_LEADS_UPDATE_SUCCESS) + public void updateClueFollowUp(CrmUpdateFollowUpReqBO updateReq) { + // 校验线索是否存在 + CrmClueDO oldClue = validateClueExists(updateReq.getBizId()); + + // 更新 + clueMapper.updateById(BeanUtils.toBean(updateReq, CrmClueDO.class).setId(updateReq.getBizId())); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmUpdateFollowUpReqBO.class)); + LogRecordContext.putVariable("clueName", oldClue.getName()); + } @Override @@ -143,48 +155,28 @@ public class CrmClueServiceImpl implements CrmClueService { LogRecordContext.putVariable("clueName", clue.getName()); } - private CrmClueDO validateClueExists(Long id) { - CrmClueDO crmClueDO = clueMapper.selectById(id); - if (crmClueDO == null) { - throw exception(CLUE_NOT_EXISTS); - } - return crmClueDO; - } - - @Override - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.READ) - public CrmClueDO getClue(Long id) { - return clueMapper.selectById(id); - } - - @Override - public List getClueList(Collection ids, Long userId) { - if (CollUtil.isEmpty(ids)) { - return ListUtil.empty(); - } - return clueMapper.selectBatchIds(ids, userId); - } - - @Override - public PageResult getCluePage(CrmCluePageReqVO pageReqVO, Long userId) { - return clueMapper.selectPage(pageReqVO, userId); - } @Override + @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}", + success = CRM_LEADS_TRANSFER_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void transferClue(CrmClueTransferReqVO reqVO, Long userId) { // 1 校验线索是否存在 - validateClueExists(reqVO.getId()); + CrmClueDO clue = validateClueExists(reqVO.getId()); // 2.1 数据权限转移 crmPermissionService.transferPermission(CrmClueConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_LEADS.getType())); // 2.2 设置新的负责人 clueMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); - // 3. TODO 记录转移日志 + // 3. 记录转移日志 + LogRecordContext.putVariable("clue", clue); } @Override @Transactional(rollbackFor = Exception.class) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void translateCustomer(CrmClueTransformReqVO reqVO, Long userId) { // 1.1 校验线索都存在 Set clueIds = reqVO.getIds(); @@ -214,6 +206,11 @@ public class CrmClueServiceImpl implements CrmClueService { })); // 2.3 复制跟进 updateFollowUpRecords(clueCustomerIdMap); + + // 3. 记录操作日志 + for (CrmClueDO clue : translateClues) { + getSelf().receiveClueLog(clue); + } } private void updateFollowUpRecords(Map clueCustomerIdMap) { @@ -229,6 +226,13 @@ public class CrmClueServiceImpl implements CrmClueService { .setBizId(clueCustomerIdMap.get(followUpRecord.getBizId())))); } + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSLATE_SUB_TYPE, bizNo = "{{#clue.id}}", + success = CRM_LEADS_TRANSLATE_SUCCESS) + public void receiveClueLog(CrmClueDO clue) { + // 记录操作日志上下文 + LogRecordContext.putVariable("clue", clue); + } + private void validateRelationDataExists(CrmClueSaveReqVO reqVO) { // 校验负责人 if (Objects.nonNull(reqVO.getOwnerUserId()) && @@ -237,4 +241,40 @@ public class CrmClueServiceImpl implements CrmClueService { } } + private CrmClueDO validateClueExists(Long id) { + CrmClueDO crmClueDO = clueMapper.selectById(id); + if (crmClueDO == null) { + throw exception(CLUE_NOT_EXISTS); + } + return crmClueDO; + } + + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.READ) + public CrmClueDO getClue(Long id) { + return clueMapper.selectById(id); + } + + @Override + public List getClueList(Collection ids, Long userId) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return clueMapper.selectBatchIds(ids, userId); + } + + @Override + public PageResult getCluePage(CrmCluePageReqVO pageReqVO, Long userId) { + return clueMapper.selectPage(pageReqVO, userId); + } + + /** + * 获得自身的代理对象,解决 AOP 生效问题 + * + * @return 自己 + */ + private CrmClueServiceImpl getSelf() { + return SpringUtil.getBean(getClass()); + } + }