Browse Source

✨ CRM:完善联系人的编辑、详情

YunaiV 1 year ago
parent
commit
7dd35f3295

+ 2 - 0
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java

@@ -75,6 +75,8 @@ public interface LogRecordConstants {
     String CRM_CONTACT_DELETE_SUCCESS = "删除了联系人【{{#contactName}}】";
     String CRM_CONTACT_TRANSFER_SUB_TYPE = "转移联系人";
     String CRM_CONTACT_TRANSFER_SUCCESS = "将联系人【{{#contact.name}}】的负责人从【{getAdminUserById{#contact.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
+    String CRM_CONTACT_FOLLOW_UP_SUB_TYPE = "联系人跟进";
+    String CRM_CONTACT_FOLLOW_UP_SUCCESS = "联系人跟进【{{#contactName}}】";
 
     // ======================= CRM_BUSINESS 商机 =======================
 

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java

@@ -118,7 +118,7 @@ public class CrmContactController {
     @Operation(summary = "获得联系人的精简列表")
     @PreAuthorize("@ss.hasPermission('crm:contact:query')")
     public CommonResult<List<CrmContactRespVO>> getSimpleContactList() {
-        List<CrmContactDO> list = contactService.getSimpleContactList(getLoginUserId());
+        List<CrmContactDO> list = contactService.getContactList(getLoginUserId());
         return success(convertList(list, contact -> // 只返回 id、name 字段
                 new CrmContactRespVO().setId(contact.getId()).setName(contact.getName())));
     }

+ 1 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java

@@ -27,6 +27,7 @@ public class CrmContactSaveReqVO {
     private String name;
 
     @Schema(description = "客户编号", example = "10795")
+    @NotNull(message = "客户编号不能为空")
     @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME)
     private Long customerId;
 

+ 0 - 35
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java

@@ -1,35 +0,0 @@
-package cn.iocoder.yudao.module.crm.convert.contact;
-
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactRespVO;
-import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
-import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
-import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
-import org.mapstruct.Mapper;
-import org.mapstruct.Mapping;
-import org.mapstruct.factory.Mappers;
-
-import java.util.List;
-
-/**
- * CRM 联系人 Convert
- *
- * @author 芋道源码
- */
-@Mapper
-public interface CrmContactConvert {
-
-    CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class);
-
-    @Mapping(target = "bizId", source = "reqVO.id")
-    CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId);
-
-    @Mapping(target = "id", source = "reqBO.bizId")
-    CrmContactDO convert(CrmUpdateFollowUpReqBO reqBO);
-
-    default List<CrmContactDO> convertList(List<CrmUpdateFollowUpReqBO> list) {
-        return CollectionUtils.convertList(list, INSTANCE::convert);
-    }
-
-}

+ 0 - 6
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java

@@ -22,12 +22,6 @@ import java.util.List;
 @Mapper
 public interface CrmContactMapper extends BaseMapperX<CrmContactDO> {
 
-    default int updateOwnerUserIdById(Long id, Long ownerUserId) {
-        return update(new LambdaUpdateWrapper<CrmContactDO>()
-                .eq(CrmContactDO::getId, id)
-                .set(CrmContactDO::getOwnerUserId, ownerUserId));
-    }
-
     default int updateOwnerUserIdByCustomerId(Long customerId, Long ownerUserId) {
         return update(new LambdaUpdateWrapper<CrmContactDO>()
                 .eq(CrmContactDO::getCustomerId, customerId)

+ 16 - 12
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java

@@ -6,9 +6,9 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReq
 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
-import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
 import jakarta.validation.Valid;
 
+import java.time.LocalDateTime;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -54,7 +54,7 @@ public interface CrmContactService {
     void transferContact(CrmContactTransferReqVO reqVO, Long userId);
 
     /**
-     * 更新客户联系人负责人
+     * 更新指定客户联系人负责人
      *
      * @param customerId  客户编号
      * @param ownerUserId 用户编号
@@ -64,9 +64,20 @@ public interface CrmContactService {
     /**
      * 更新联系人相关跟进信息
      *
-     * @param updateFollowUpReqBOList 跟进信息
+     * @param id 编号
+     * @param contactNextTime 下次联系时间
+     * @param contactLastContent 最后联系内容
+     */
+    void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
+
+    /**
+     * 更新联系人相关跟进信息
+     *
+     * @param ids 编号数组
+     * @param contactNextTime 下次联系时间
+     * @param contactLastContent 最后联系内容
      */
-    void updateContactFollowUpBatch(List<CrmUpdateFollowUpReqBO> updateFollowUpReqBOList);
+    void updateContactFollowUpBatch(Collection<Long> ids, LocalDateTime contactNextTime, String contactLastContent);
 
     /**
      * 获得联系人
@@ -103,20 +114,13 @@ public interface CrmContactService {
         return convertMap(getContactList(ids), CrmContactDO::getId);
     }
 
-    /**
-     * 获得联系人列表
-     *
-     * @return 联系人列表
-     */
-    List<CrmContactDO> getContactList();
-
     /**
      * 获取联系人列表(校验权限)
      *
      * @param userId 用户编号
      * @return 联系人列表
      */
-    List<CrmContactDO> getSimpleContactList(Long userId);
+    List<CrmContactDO> getContactList(Long userId);
 
     /**
      * 获得联系人分页

+ 39 - 24
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java

@@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusines
 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
-import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
 import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper;
 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
@@ -17,9 +16,9 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm
 import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
 import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
-import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
+import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import com.mzt.logapi.context.LogRecordContext;
 import com.mzt.logapi.service.impl.DiffParseFunction;
@@ -30,14 +29,15 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
+import java.time.LocalDateTime;
 import java.util.Collection;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
-import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
 import static java.util.Collections.singletonList;
 
 /**
@@ -73,7 +73,7 @@ public class CrmContactServiceImpl implements CrmContactService {
             success = CRM_CONTACT_CREATE_SUCCESS)
     public Long createContact(CrmContactSaveReqVO createReqVO, Long userId) {
         createReqVO.setId(null);
-        // 1. 校验
+        // 1. 校验关联数据
         validateRelationDataExists(createReqVO);
 
         // 2. 插入联系人
@@ -102,8 +102,9 @@ public class CrmContactServiceImpl implements CrmContactService {
             success = CRM_CONTACT_UPDATE_SUCCESS)
     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
     public void updateContact(CrmContactSaveReqVO updateReqVO) {
-        // 1. 校验存在
+        // 1.1 校验存在
         CrmContactDO oldContact = validateContactExists(updateReqVO.getId());
+        // 1.2 校验关联数据
         validateRelationDataExists(updateReqVO);
 
         // 2. 更新联系人
@@ -123,15 +124,15 @@ public class CrmContactServiceImpl implements CrmContactService {
     private void validateRelationDataExists(CrmContactSaveReqVO saveReqVO) {
         // 1. 校验客户
         if (saveReqVO.getCustomerId() != null && customerService.getCustomer(saveReqVO.getCustomerId()) == null) {
-            throw exception(CUSTOMER_NOT_EXISTS);
+            customerService.validateCustomer(saveReqVO.getCustomerId());
         }
         // 2. 校验负责人
-        if (saveReqVO.getOwnerUserId() != null && adminUserApi.getUser(saveReqVO.getOwnerUserId()) == null) {
-            throw exception(USER_NOT_EXISTS);
+        if (saveReqVO.getOwnerUserId() != null) {
+            adminUserApi.validateUser(saveReqVO.getOwnerUserId());
         }
         // 3. 直属上级
-        if (saveReqVO.getParentId() != null && contactMapper.selectById(saveReqVO.getParentId()) == null) {
-            throw exception(CONTACT_NOT_EXISTS);
+        if (saveReqVO.getParentId() != null) {
+            validateContactExists(saveReqVO.getParentId());
         }
         // 4. 如果有关联商机,则需要校验存在
         if (saveReqVO.getBusinessId() != null && businessService.getBusiness(saveReqVO.getBusinessId()) == null) {
@@ -165,11 +166,11 @@ public class CrmContactServiceImpl implements CrmContactService {
     }
 
     private CrmContactDO validateContactExists(Long id) {
-        CrmContactDO contactDO = contactMapper.selectById(id);
-        if (contactDO == null) {
+        CrmContactDO contact = contactMapper.selectById(id);
+        if (contact == null) {
             throw exception(CONTACT_NOT_EXISTS);
         }
-        return contactDO;
+        return contact;
     }
 
     @Override
@@ -182,10 +183,10 @@ public class CrmContactServiceImpl implements CrmContactService {
         CrmContactDO contact = validateContactExists(reqVO.getId());
 
         // 2.1 数据权限转移
-        permissionService.transferPermission(
-                CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()));
+        permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CONTACT.getType(),
+                        reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel()));
         // 2.2 设置新的负责人
-        contactMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
+        contactMapper.updateById(new CrmContactDO().setId(reqVO.getId()).setOwnerUserId(reqVO.getNewOwnerUserId()));
 
         // 3. 记录转移日志
         LogRecordContext.putVariable("contact", contact);
@@ -194,11 +195,30 @@ public class CrmContactServiceImpl implements CrmContactService {
     @Override
     public void updateOwnerUserIdByCustomerId(Long customerId, Long ownerUserId) {
         contactMapper.updateOwnerUserIdByCustomerId(customerId, ownerUserId);
+        // TODO @puhui999:操作日志、数据权限;
     }
 
     @Override
-    public void updateContactFollowUpBatch(List<CrmUpdateFollowUpReqBO> updateFollowUpReqBOList) {
-        contactMapper.updateBatch(CrmContactConvert.INSTANCE.convertList(updateFollowUpReqBOList));
+    @LogRecord(type = CRM_CONTACT_TYPE, subType = CRM_CONTACT_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}",
+            success = CRM_CONTACT_FOLLOW_UP_SUCCESS)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
+    public void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {
+        // 1.1 校验存在
+        CrmContactDO contact = validateContactExists(id);
+
+        // 2. 更新联系人的跟进信息
+        contactMapper.updateById(new CrmContactDO().setId(id).setContactNextTime(contactNextTime)
+                .setContactLastTime(LocalDateTime.now()).setContactLastContent(contactLastContent));
+
+        // 3. 记录操作日志上下文
+        LogRecordContext.putVariable("contactName", contact.getName());
+    }
+
+    @Override
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#ids", level = CrmPermissionLevelEnum.WRITE)
+    public void updateContactFollowUpBatch(Collection<Long> ids, LocalDateTime contactNextTime, String contactLastContent) {
+        contactMapper.updateBatch(convertList(ids, id -> new CrmContactDO().setId(id).setContactLastTime(LocalDateTime.now())
+                .setContactNextTime(contactNextTime).setContactLastContent(contactLastContent)));
     }
 
     //======================= 查询相关 =======================
@@ -226,12 +246,7 @@ public class CrmContactServiceImpl implements CrmContactService {
     }
 
     @Override
-    public List<CrmContactDO> getContactList() {
-        return contactMapper.selectList();
-    }
-
-    @Override
-    public List<CrmContactDO> getSimpleContactList(Long userId) {
+    public List<CrmContactDO> getContactList(Long userId) {
         CrmContactPageReqVO reqVO = new CrmContactPageReqVO();
         reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页
         return contactMapper.selectPage(reqVO, userId).getList();

+ 2 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java

@@ -132,9 +132,9 @@ public interface CrmCustomerService {
     /**
      * 校验客户是否存在
      *
-     * @param customerId 客户 id
+     * @param id 编号
      */
-    void validateCustomer(Long customerId);
+    void validateCustomer(Long id);
 
     /**
      * 客户转移

+ 4 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java

@@ -164,7 +164,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
 
         // 2. 更新客户的跟进信息
         customerMapper.updateById(new CrmCustomerDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime)
-                .setContactLastTime(LocalDateTime.now()));
+                .setContactLastTime(LocalDateTime.now()).setContactLastContent(contactLastContent));
 
         // 3. 记录操作日志上下文
         LogRecordContext.putVariable("customerName", customer.getName());
@@ -521,11 +521,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
     /**
      * 校验客户是否存在
      *
-     * @param customerId 客户 id
+     * @param id 客户 id
      */
     @Override
-    public void validateCustomer(Long customerId) {
-        validateCustomerExists(customerId);
+    public void validateCustomer(Long id) {
+        validateCustomerExists(id);
     }
 
     private void validateCustomerOwnerExists(CrmCustomerDO customer, Boolean pool) {

+ 16 - 17
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java

@@ -68,41 +68,40 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService {
     @Override
     @CrmPermission(bizTypeValue = "#createReqVO.bizType", bizId = "#createReqVO.bizId", level = CrmPermissionLevelEnum.WRITE)
     public Long createFollowUpRecord(CrmFollowUpRecordSaveReqVO createReqVO) {
-        // 创建更进记录
-        CrmFollowUpRecordDO followUpRecord = BeanUtils.toBean(createReqVO, CrmFollowUpRecordDO.class);
-        crmFollowUpRecordMapper.insert(followUpRecord);
+        // 1. 创建更进记录
+        CrmFollowUpRecordDO record = BeanUtils.toBean(createReqVO, CrmFollowUpRecordDO.class);
+        crmFollowUpRecordMapper.insert(record);
 
-        // 2. 更新 bizId 对应的记录
-        CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId())
+        // 2. 更新 bizId 对应的记录
+        CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(record.getBizId())
                 .setContactLastTime(LocalDateTime.now())
-                .setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent());
-        if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { // 更新商机跟进信息
+                .setContactNextTime(record.getNextTime()).setContactLastContent(record.getContent());
+        if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), record.getBizType())) { // 更新商机跟进信息
             businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO));
         }
-        if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息
-            clueService.updateClueFollowUp(followUpRecord.getId(), followUpRecord.getNextTime(), followUpRecord.getContent());
+        if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), record.getBizType())) { // 更新线索跟进信息
+            clueService.updateClueFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
         }
-        if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { // 更新联系人跟进信息
-            contactService.updateContactFollowUpBatch(Collections.singletonList(updateFollowUpReqBO));
+        if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTACT.getType(), record.getBizType())) { // 更新联系人跟进信息
+            contactService.updateContactFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
         }
-        if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTRACT.getType(), followUpRecord.getBizType())) { // 更新合同跟进信息
+        if (ObjUtil.equal(CrmBizTypeEnum.CRM_CONTRACT.getType(), record.getBizType())) { // 更新合同跟进信息
             contractService.updateContractFollowUp(updateFollowUpReqBO);
         }
-        if (ObjUtil.equal(CrmBizTypeEnum.CRM_CUSTOMER.getType(), followUpRecord.getBizType())) { // 更新客户跟进信息
-            customerService.updateCustomerFollowUp(followUpRecord.getBizId(), followUpRecord.getNextTime(), followUpRecord.getContent());
+        if (ObjUtil.equal(CrmBizTypeEnum.CRM_CUSTOMER.getType(), record.getBizType())) { // 更新客户跟进信息
+            customerService.updateCustomerFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
         }
 
         // 3.1 更新 contactIds 对应的记录,不更新 lastTime 和 lastContent
         if (CollUtil.isNotEmpty(createReqVO.getContactIds())) {
-            contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(),
-                    contactId -> updateFollowUpReqBO.setBizId(contactId).setContactLastTime(null).setContactLastContent(null)));
+            contactService.updateContactFollowUpBatch(createReqVO.getContactIds(), null, null);
         }
         // 3.2 需要更新 businessIds 对应的记录,不更新 lastTime 和 lastContent
         if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) {
             businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(),
                     businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null)));
         }
-        return followUpRecord.getId();
+        return record.getId();
     }
 
     @Override