Browse Source

Merge remote-tracking branch 'yudao/develop' into develop

puhui999 1 year ago
parent
commit
0f2d974e9c
15 changed files with 131 additions and 95 deletions
  1. 1 1
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
  2. 2 0
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
  3. 1 1
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java
  4. 8 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java
  5. 3 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java
  6. 0 34
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java
  7. 4 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactBusinessMapper.java
  8. 12 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java
  9. 13 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java
  10. 40 16
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
  11. 8 9
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java
  12. 6 16
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java
  13. 13 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java
  14. 15 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
  15. 5 8
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java

+ 1 - 1
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java

@@ -20,7 +20,7 @@ public interface ErrorCodeConstants {
 
     // ========== 商机管理 1-020-002-000 ==========
     ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在");
-    ErrorCode BUSINESS_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除");
+    ErrorCode BUSINESS_DELETE_FAIL_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除");
 
     // ========== 联系人管理 1-020-003-000 ==========
     ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在");

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

@@ -91,6 +91,8 @@ public interface LogRecordConstants {
     String CRM_BUSINESS_DELETE_SUCCESS = "删除了商机【{{#businessName}}】";
     String CRM_BUSINESS_TRANSFER_SUB_TYPE = "转移商机";
     String CRM_BUSINESS_TRANSFER_SUCCESS = "将商机【{{#business.name}}】的负责人从【{getAdminUserById{#business.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
+    String CRM_BUSINESS_FOLLOW_UP_SUB_TYPE = "商机跟进";
+    String CRM_BUSINESS_FOLLOW_UP_SUCCESS = "商机跟进【{{#businessName}}】";
 
     // ======================= CRM_CONTRACT 合同 =======================
 

+ 1 - 1
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java

@@ -65,7 +65,7 @@ public class CrmBusinessRespVO {
     private String statusName;
 
     @Schema
-    @ExcelProperty("1赢单2输单3无效")
+    @ExcelProperty("结束状态")
     private Integer endStatus;
 
     @ExcelProperty("结束时的备注")

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

@@ -139,6 +139,14 @@ public class CrmContactController {
         return success(new PageResult<>(buildContactDetailList(pageResult.getList()), pageResult.getTotal()));
     }
 
+    @GetMapping("/page-by-business")
+    @Operation(summary = "获得联系人分页,基于指定商机")
+    public CommonResult<PageResult<CrmContactRespVO>> getContactPageByBusiness(@Valid CrmContactPageReqVO pageVO) {
+        Assert.notNull(pageVO.getBusinessId(), "商机编号不能为空");
+        PageResult<CrmContactDO> pageResult = contactService.getContactPageByBusinessId(pageVO);
+        return success(new PageResult<>(buildContactDetailList(pageResult.getList()), pageResult.getTotal()));
+    }
+
     @GetMapping("/export-excel")
     @Operation(summary = "导出联系人 Excel")
     @PreAuthorize("@ss.hasPermission('crm:contact:export')")

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

@@ -39,4 +39,7 @@ public class CrmContactPageReqVO extends PageParam {
     @InEnum(CrmSceneTypeEnum.class)
     private Integer sceneType; // 场景类型,为 null 时则表示全部
 
+    @Schema(description = "商机编号", example = "10430")
+    private Long businessId;
+
 }

+ 0 - 34
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java

@@ -1,34 +0,0 @@
-package cn.iocoder.yudao.module.crm.convert.business;
-
-import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
-import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
-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;
-
-/**
- * 商机 Convert
- *
- * @author ljlleo
- */
-@Mapper
-public interface CrmBusinessConvert {
-
-    CrmBusinessConvert INSTANCE = Mappers.getMapper(CrmBusinessConvert.class);
-
-    @Mapping(target = "bizId", source = "reqVO.id")
-    CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId);
-
-    @Mapping(target = "id", source = "reqBO.bizId")
-    CrmBusinessDO convert(CrmUpdateFollowUpReqBO reqBO);
-
-    default List<CrmBusinessDO> convertList(List<CrmUpdateFollowUpReqBO> list) {
-        return CollectionUtils.convertList(list, INSTANCE::convert);
-    }
-
-}

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

@@ -31,4 +31,8 @@ public interface CrmContactBusinessMapper extends BaseMapperX<CrmContactBusiness
         return selectList(CrmContactBusinessDO::getContactId, contactId);
     }
 
+    default List<CrmContactBusinessDO> selectListByBusinessId(Long businessId) {
+        return selectList(CrmContactBusinessDO::getBusinessId, businessId);
+    }
+
 }

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

@@ -40,6 +40,18 @@ public interface CrmContactMapper extends BaseMapperX<CrmContactDO> {
                 .orderByDesc(CrmContactDO::getId));
     }
 
+    default PageResult<CrmContactDO> selectPageByBusinessId(CrmContactPageReqVO pageVO, Collection<Long> ids) {
+        return selectPage(pageVO, new LambdaQueryWrapperX<CrmContactDO>()
+                .in(CrmContactDO::getId, ids) // 指定联系人编号
+                .likeIfPresent(CrmContactDO::getName, pageVO.getName())
+                .eqIfPresent(CrmContactDO::getMobile, pageVO.getMobile())
+                .eqIfPresent(CrmContactDO::getTelephone, pageVO.getTelephone())
+                .eqIfPresent(CrmContactDO::getEmail, pageVO.getEmail())
+                .eqIfPresent(CrmContactDO::getQq, pageVO.getQq())
+                .eqIfPresent(CrmContactDO::getWechat, pageVO.getWechat())
+                .orderByDesc(CrmContactDO::getId));
+    }
+
     default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO pageReqVO, Long userId) {
         MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>();
         // 拼接数据权限的查询条件

+ 13 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java

@@ -9,9 +9,9 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
 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.business.bo.CrmBusinessUpdateProductReqBO;
-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;
 
@@ -41,9 +41,19 @@ public interface CrmBusinessService {
     /**
      * 更新商机相关跟进信息
      *
-     * @param updateFollowUpReqBOList 跟进信息
+     * @param id 编号
+     * @param contactNextTime 下次联系时间
+     * @param contactLastContent 最后联系内容
+     */
+    void updateBusinessFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
+
+    /**
+     * 更新商机的下次联系时间
+     *
+     * @param ids 编号数组
+     * @param contactNextTime 下次联系时间
      */
-    void updateBusinessFollowUpBatch(List<CrmUpdateFollowUpReqBO> updateFollowUpReqBOList);
+    void updateBusinessContactNextTime(Collection<Long> ids, LocalDateTime contactNextTime);
 
     /**
      * 删除商机

+ 40 - 16
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java

@@ -8,7 +8,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
-import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert;
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
@@ -22,9 +22,9 @@ import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService;
 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
 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.crm.service.product.CrmProductService;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import com.mzt.logapi.context.LogRecordContext;
@@ -37,12 +37,14 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import java.math.BigDecimal;
+import java.time.LocalDateTime;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
-import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_CONTRACT_EXISTS;
+import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_DELETE_FAIL_CONTRACT_EXISTS;
 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
 
@@ -100,14 +102,19 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
             businessProducts.forEach(item -> item.setBusinessId(business.getId()));
             businessProductMapper.insertBatch(businessProducts);
         }
-        // 在联系人的详情页,如果直接【新建商机】,则需要关联下。
-        contactBusinessService.createContactBusiness(createReqVO.getContactId(), business.getId());
+
         // 3. 创建数据权限
         // 设置当前操作的人为负责人
         permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
                 .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
 
-        // 4. 记录操作日志上下文
+        // 4. 在联系人的详情页,如果直接【新建商机】,则需要关联下
+        if (createReqVO.getContactId() != null) {
+            contactBusinessService.createContactBusinessList(new CrmContactBusinessReqVO().setContactId(createReqVO.getContactId())
+                    .setBusinessIds(Collections.singletonList(business.getId())));
+        }
+
+        // 5. 记录操作日志上下文
         LogRecordContext.putVariable("business", business);
         return business.getId();
     }
@@ -139,6 +146,28 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
         LogRecordContext.putVariable("businessName", oldBusiness.getName());
     }
 
+    @Override
+    @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}",
+            success = CRM_BUSINESS_FOLLOW_UP_SUCCESS)
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
+    public void updateBusinessFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {
+        // 1. 校验存在
+        CrmBusinessDO business = validateBusinessExists(id);
+
+        // 2. 更新联系人的跟进信息
+        businessMapper.updateById(new CrmBusinessDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime)
+                .setContactLastTime(LocalDateTime.now()));
+
+        // 3. 记录操作日志上下文
+        LogRecordContext.putVariable("businessName", business.getName());
+    }
+
+    @Override
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#ids", level = CrmPermissionLevelEnum.WRITE)
+    public void updateBusinessContactNextTime(Collection<Long> ids, LocalDateTime contactNextTime) {
+        businessMapper.updateBatch(convertList(ids, id -> new CrmBusinessDO().setId(id).setContactNextTime(contactNextTime)));
+    }
+
     private void updateBusinessProduct(Long id, List<CrmBusinessProductDO> newList) {
         List<CrmBusinessProductDO> oldList = businessProductMapper.selectListByBusinessId(id);
         List<List<CrmBusinessProductDO>> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录
@@ -189,20 +218,15 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
         business.setTotalPrice(business.getTotalProductPrice().subtract(discountPrice));
     }
 
-    @Override
-    public void updateBusinessFollowUpBatch(List<CrmUpdateFollowUpReqBO> updateFollowUpReqBOList) {
-        businessMapper.updateBatch(CrmBusinessConvert.INSTANCE.convertList(updateFollowUpReqBOList));
-    }
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_DELETE_SUB_TYPE, bizNo = "{{#id}}",
             success = CRM_BUSINESS_DELETE_SUCCESS)
     @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
     public void deleteBusiness(Long id) {
-        // 校验存在
+        // 1.1 校验存在
         CrmBusinessDO business = validateBusinessExists(id);
-        // TODO @商机待定:需要校验有没关联合同。CrmContractDO 的 businessId 字段
+        // 1.2 校验是否关联合同
         validateContractExists(id);
 
         // 删除
@@ -222,7 +246,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
      */
     private void validateContractExists(Long businessId) {
         if (contractService.getContractCountByBusinessId(businessId) > 0) {
-            throw exception(BUSINESS_CONTRACT_EXISTS);
+            throw exception(BUSINESS_DELETE_FAIL_CONTRACT_EXISTS);
         }
     }
 
@@ -245,8 +269,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
         CrmBusinessDO business = validateBusinessExists(reqVO.getId());
 
         // 2.1 数据权限转移
-        permissionService.transferPermission(
-                CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()));
+        permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_BUSINESS.getType(),
+                reqVO.getNewOwnerUserId(), reqVO.getId(), CrmPermissionLevelEnum.OWNER.getLevel()));
         // 2.2 设置新的负责人
         businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
 

+ 8 - 9
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java

@@ -13,15 +13,6 @@ import java.util.List;
  */
 public interface CrmContactBusinessService {
 
-    /**
-     * 创建联系人人商机关联
-     *
-     * @param contactId  联系人编号
-     * @param businessId 商机编号
-     */
-    void createContactBusiness(Long contactId, Long businessId);
-
-
     /**
      * 创建联系人与商机的关联
      *
@@ -51,4 +42,12 @@ public interface CrmContactBusinessService {
      */
     List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId);
 
+    /**
+     * 获得联系人与商机的关联列表,基于商机编号
+     *
+     * @param businessId 商机编号
+     * @return 联系人商机关联
+     */
+    List<CrmContactBusinessDO> getContactBusinessListByBusinessId(Long businessId);
+
 }

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

@@ -41,22 +41,6 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
     @Lazy // 延迟加载,为了解决延迟加载
     private CrmContactService contactService;
 
-    @Override
-    public void createContactBusiness(Long contactId, Long businessId) {
-        // 校验存在
-        CrmContactDO contact = contactService.getContact(contactId);
-        if (contact == null) {
-            throw exception(CONTACT_NOT_EXISTS);
-        }
-        CrmBusinessDO business = businessService.getBusiness(businessId);
-        if (business == null) {
-            throw exception(BUSINESS_NOT_EXISTS);
-        }
-
-        // 插入
-        contactBusinessMapper.insert(new CrmContactBusinessDO(null, contactId, businessId));
-    }
-
     @Override
     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#createReqVO.contactId", level = CrmPermissionLevelEnum.WRITE)
     public void createContactBusinessList(CrmContactBusinessReqVO createReqVO) {
@@ -107,4 +91,10 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
         return contactBusinessMapper.selectListByContactId(contactId);
     }
 
+    @Override
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#businessId", level = CrmPermissionLevelEnum.READ)
+    public List<CrmContactBusinessDO> getContactBusinessListByBusinessId(Long businessId) {
+        return contactBusinessMapper.selectListByBusinessId(businessId);
+    }
+
 }

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

@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 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.dal.dataobject.business.CrmBusinessDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
 import jakarta.validation.Valid;
@@ -72,13 +73,12 @@ public interface CrmContactService {
     void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
 
     /**
-     * 更新联系人相关跟进信息
+     * 更新联系人的下次联系时间
      *
      * @param ids                编号数组
      * @param contactNextTime    下次联系时间
-     * @param contactLastContent 最后联系内容
      */
-    void updateContactFollowUpBatch(Collection<Long> ids, LocalDateTime contactNextTime, String contactLastContent);
+    void updateContactContactNextTime(Collection<Long> ids, LocalDateTime contactNextTime);
 
     /**
      * 获得联系人
@@ -151,6 +151,16 @@ public interface CrmContactService {
      */
     PageResult<CrmContactDO> getContactPageByCustomerId(CrmContactPageReqVO pageVO);
 
+    /**
+     * 获得联系人分页
+     *
+     * 数据权限:基于 {@link CrmBusinessDO}
+     *
+     * @param pageVO 分页查询
+     * @return 联系人分页
+     */
+    PageResult<CrmContactDO> getContactPageByBusinessId(CrmContactPageReqVO pageVO);
+
     /**
      * 获取关联客户的联系人数量
      *

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

@@ -8,6 +8,7 @@ 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.dal.dataobject.contact.CrmContactBusinessDO;
 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;
@@ -36,6 +37,7 @@ 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.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
 import static java.util.Collections.singletonList;
@@ -225,7 +227,7 @@ public class CrmContactServiceImpl implements CrmContactService {
             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 校验存在
+        // 1. 校验存在
         CrmContactDO contact = validateContactExists(id);
 
         // 2. 更新联系人的跟进信息
@@ -238,9 +240,8 @@ public class CrmContactServiceImpl implements CrmContactService {
 
     @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)));
+    public void updateContactContactNextTime(Collection<Long> ids, LocalDateTime contactNextTime) {
+        contactMapper.updateBatch(convertList(ids, id -> new CrmContactDO().setId(id).setContactNextTime(contactNextTime)));
     }
 
     //======================= 查询相关 =======================
@@ -290,6 +291,16 @@ public class CrmContactServiceImpl implements CrmContactService {
         return contactMapper.selectPageByCustomerId(pageVO);
     }
 
+    @Override
+    @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#pageVO.businessId", level = CrmPermissionLevelEnum.READ)
+    public PageResult<CrmContactDO> getContactPageByBusinessId(CrmContactPageReqVO pageVO) {
+        List<CrmContactBusinessDO> contactBusinessList = contactBusinessService.getContactBusinessListByBusinessId(pageVO.getBusinessId());
+        if (CollUtil.isEmpty(contactBusinessList)) {
+            return PageResult.empty();
+        }
+        return contactMapper.selectPageByBusinessId(pageVO, convertSet(contactBusinessList, CrmContactBusinessDO::getContactId));
+    }
+
     @Override
     public Long getContactCountByCustomerId(Long customerId) {
         return contactMapper.selectCount(CrmContactDO::getCustomerId, customerId);

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

@@ -26,11 +26,9 @@ import org.springframework.validation.annotation.Validated;
 
 import java.time.LocalDateTime;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_DELETE_DENIED;
 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_NOT_EXISTS;
 
@@ -77,7 +75,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService {
                 .setContactLastTime(LocalDateTime.now())
                 .setContactNextTime(record.getNextTime()).setContactLastContent(record.getContent());
         if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), record.getBizType())) { // 更新商机跟进信息
-            businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO));
+            businessService.updateBusinessFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
         }
         if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), record.getBizType())) { // 更新线索跟进信息
             clueService.updateClueFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
@@ -92,14 +90,13 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService {
             customerService.updateCustomerFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
         }
 
-        // 3.1 更新 contactIds 对应的记录,不更新 lastTime 和 lastContent
+        // 3.1 更新 contactIds 对应的记录,只更新 nextTime
         if (CollUtil.isNotEmpty(createReqVO.getContactIds())) {
-            contactService.updateContactFollowUpBatch(createReqVO.getContactIds(), null, null);
+            contactService.updateContactContactNextTime(createReqVO.getContactIds(), createReqVO.getNextTime());
         }
-        // 3.2 需要更新 businessIds 对应的记录,不更新 lastTime 和 lastContent
+        // 3.2 需要更新 businessIds 对应的记录,只更新 nextTime
         if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) {
-            businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(),
-                    businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null)));
+            businessService.updateBusinessContactNextTime(createReqVO.getBusinessIds(), createReqVO.getNextTime());
         }
         return record.getId();
     }