Commit 0f2d974e9c1a5e8b6e9affc9cc2c82c28098a556

Authored by puhui999
2 parents 41b8575b 740e9297

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

Showing 15 changed files with 131 additions and 95 deletions
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 { @@ -20,7 +20,7 @@ public interface ErrorCodeConstants {
20 20
21 // ========== 商机管理 1-020-002-000 ========== 21 // ========== 商机管理 1-020-002-000 ==========
22 ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在"); 22 ErrorCode BUSINESS_NOT_EXISTS = new ErrorCode(1_020_002_000, "商机不存在");
23 - ErrorCode BUSINESS_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除"); 23 + ErrorCode BUSINESS_DELETE_FAIL_CONTRACT_EXISTS = new ErrorCode(1_020_002_001, "商机已关联合同,不能删除");
24 24
25 // ========== 联系人管理 1-020-003-000 ========== 25 // ========== 联系人管理 1-020-003-000 ==========
26 ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); 26 ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在");
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 { @@ -91,6 +91,8 @@ public interface LogRecordConstants {
91 String CRM_BUSINESS_DELETE_SUCCESS = "删除了商机【{{#businessName}}】"; 91 String CRM_BUSINESS_DELETE_SUCCESS = "删除了商机【{{#businessName}}】";
92 String CRM_BUSINESS_TRANSFER_SUB_TYPE = "转移商机"; 92 String CRM_BUSINESS_TRANSFER_SUB_TYPE = "转移商机";
93 String CRM_BUSINESS_TRANSFER_SUCCESS = "将商机【{{#business.name}}】的负责人从【{getAdminUserById{#business.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; 93 String CRM_BUSINESS_TRANSFER_SUCCESS = "将商机【{{#business.name}}】的负责人从【{getAdminUserById{#business.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】";
  94 + String CRM_BUSINESS_FOLLOW_UP_SUB_TYPE = "商机跟进";
  95 + String CRM_BUSINESS_FOLLOW_UP_SUCCESS = "商机跟进【{{#businessName}}】";
94 96
95 // ======================= CRM_CONTRACT 合同 ======================= 97 // ======================= CRM_CONTRACT 合同 =======================
96 98
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 { @@ -65,7 +65,7 @@ public class CrmBusinessRespVO {
65 private String statusName; 65 private String statusName;
66 66
67 @Schema 67 @Schema
68 - @ExcelProperty("1赢单2输单3无效") 68 + @ExcelProperty("结束状态")
69 private Integer endStatus; 69 private Integer endStatus;
70 70
71 @ExcelProperty("结束时的备注") 71 @ExcelProperty("结束时的备注")
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 { @@ -139,6 +139,14 @@ public class CrmContactController {
139 return success(new PageResult<>(buildContactDetailList(pageResult.getList()), pageResult.getTotal())); 139 return success(new PageResult<>(buildContactDetailList(pageResult.getList()), pageResult.getTotal()));
140 } 140 }
141 141
  142 + @GetMapping("/page-by-business")
  143 + @Operation(summary = "获得联系人分页,基于指定商机")
  144 + public CommonResult<PageResult<CrmContactRespVO>> getContactPageByBusiness(@Valid CrmContactPageReqVO pageVO) {
  145 + Assert.notNull(pageVO.getBusinessId(), "商机编号不能为空");
  146 + PageResult<CrmContactDO> pageResult = contactService.getContactPageByBusinessId(pageVO);
  147 + return success(new PageResult<>(buildContactDetailList(pageResult.getList()), pageResult.getTotal()));
  148 + }
  149 +
142 @GetMapping("/export-excel") 150 @GetMapping("/export-excel")
143 @Operation(summary = "导出联系人 Excel") 151 @Operation(summary = "导出联系人 Excel")
144 @PreAuthorize("@ss.hasPermission('crm:contact:export')") 152 @PreAuthorize("@ss.hasPermission('crm:contact:export')")
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 { @@ -39,4 +39,7 @@ public class CrmContactPageReqVO extends PageParam {
39 @InEnum(CrmSceneTypeEnum.class) 39 @InEnum(CrmSceneTypeEnum.class)
40 private Integer sceneType; // 场景类型,为 null 时则表示全部 40 private Integer sceneType; // 场景类型,为 null 时则表示全部
41 41
  42 + @Schema(description = "商机编号", example = "10430")
  43 + private Long businessId;
  44 +
42 } 45 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java deleted
1 -package cn.iocoder.yudao.module.crm.convert.business;  
2 -  
3 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
4 -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;  
5 -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;  
6 -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;  
7 -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;  
8 -import org.mapstruct.Mapper;  
9 -import org.mapstruct.Mapping;  
10 -import org.mapstruct.factory.Mappers;  
11 -  
12 -import java.util.List;  
13 -  
14 -/**  
15 - * 商机 Convert  
16 - *  
17 - * @author ljlleo  
18 - */  
19 -@Mapper  
20 -public interface CrmBusinessConvert {  
21 -  
22 - CrmBusinessConvert INSTANCE = Mappers.getMapper(CrmBusinessConvert.class);  
23 -  
24 - @Mapping(target = "bizId", source = "reqVO.id")  
25 - CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId);  
26 -  
27 - @Mapping(target = "id", source = "reqBO.bizId")  
28 - CrmBusinessDO convert(CrmUpdateFollowUpReqBO reqBO);  
29 -  
30 - default List<CrmBusinessDO> convertList(List<CrmUpdateFollowUpReqBO> list) {  
31 - return CollectionUtils.convertList(list, INSTANCE::convert);  
32 - }  
33 -  
34 -}  
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&lt;CrmContactBusiness @@ -31,4 +31,8 @@ public interface CrmContactBusinessMapper extends BaseMapperX&lt;CrmContactBusiness
31 return selectList(CrmContactBusinessDO::getContactId, contactId); 31 return selectList(CrmContactBusinessDO::getContactId, contactId);
32 } 32 }
33 33
  34 + default List<CrmContactBusinessDO> selectListByBusinessId(Long businessId) {
  35 + return selectList(CrmContactBusinessDO::getBusinessId, businessId);
  36 + }
  37 +
34 } 38 }
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&lt;CrmContactDO&gt; { @@ -40,6 +40,18 @@ public interface CrmContactMapper extends BaseMapperX&lt;CrmContactDO&gt; {
40 .orderByDesc(CrmContactDO::getId)); 40 .orderByDesc(CrmContactDO::getId));
41 } 41 }
42 42
  43 + default PageResult<CrmContactDO> selectPageByBusinessId(CrmContactPageReqVO pageVO, Collection<Long> ids) {
  44 + return selectPage(pageVO, new LambdaQueryWrapperX<CrmContactDO>()
  45 + .in(CrmContactDO::getId, ids) // 指定联系人编号
  46 + .likeIfPresent(CrmContactDO::getName, pageVO.getName())
  47 + .eqIfPresent(CrmContactDO::getMobile, pageVO.getMobile())
  48 + .eqIfPresent(CrmContactDO::getTelephone, pageVO.getTelephone())
  49 + .eqIfPresent(CrmContactDO::getEmail, pageVO.getEmail())
  50 + .eqIfPresent(CrmContactDO::getQq, pageVO.getQq())
  51 + .eqIfPresent(CrmContactDO::getWechat, pageVO.getWechat())
  52 + .orderByDesc(CrmContactDO::getId));
  53 + }
  54 +
43 default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO pageReqVO, Long userId) { 55 default PageResult<CrmContactDO> selectPage(CrmContactPageReqVO pageReqVO, Long userId) {
44 MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>(); 56 MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>();
45 // 拼接数据权限的查询条件 57 // 拼接数据权限的查询条件
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; @@ -9,9 +9,9 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
9 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; 9 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
10 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 10 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
11 import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; 11 import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO;
12 -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;  
13 import jakarta.validation.Valid; 12 import jakarta.validation.Valid;
14 13
  14 +import java.time.LocalDateTime;
15 import java.util.Collection; 15 import java.util.Collection;
16 import java.util.List; 16 import java.util.List;
17 17
@@ -41,9 +41,19 @@ public interface CrmBusinessService { @@ -41,9 +41,19 @@ public interface CrmBusinessService {
41 /** 41 /**
42 * 更新商机相关跟进信息 42 * 更新商机相关跟进信息
43 * 43 *
44 - * @param updateFollowUpReqBOList 跟进信息 44 + * @param id 编号
  45 + * @param contactNextTime 下次联系时间
  46 + * @param contactLastContent 最后联系内容
  47 + */
  48 + void updateBusinessFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
  49 +
  50 + /**
  51 + * 更新商机的下次联系时间
  52 + *
  53 + * @param ids 编号数组
  54 + * @param contactNextTime 下次联系时间
45 */ 55 */
46 - void updateBusinessFollowUpBatch(List<CrmUpdateFollowUpReqBO> updateFollowUpReqBOList); 56 + void updateBusinessContactNextTime(Collection<Long> ids, LocalDateTime contactNextTime);
47 57
48 /** 58 /**
49 * 删除商机 59 * 删除商机
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; @@ -8,7 +8,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
8 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; 8 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO;
9 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; 9 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO;
10 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; 10 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO;
11 -import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; 11 +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO;
12 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; 12 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
13 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; 13 import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO;
14 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; 14 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
@@ -22,9 +22,9 @@ import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; @@ -22,9 +22,9 @@ import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService;
22 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; 22 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
23 import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; 23 import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
24 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; 24 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
25 -import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;  
26 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; 25 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
27 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; 26 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
  27 +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
28 import cn.iocoder.yudao.module.crm.service.product.CrmProductService; 28 import cn.iocoder.yudao.module.crm.service.product.CrmProductService;
29 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 29 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
30 import com.mzt.logapi.context.LogRecordContext; 30 import com.mzt.logapi.context.LogRecordContext;
@@ -37,12 +37,14 @@ import org.springframework.transaction.annotation.Transactional; @@ -37,12 +37,14 @@ import org.springframework.transaction.annotation.Transactional;
37 import org.springframework.validation.annotation.Validated; 37 import org.springframework.validation.annotation.Validated;
38 38
39 import java.math.BigDecimal; 39 import java.math.BigDecimal;
  40 +import java.time.LocalDateTime;
40 import java.util.Collection; 41 import java.util.Collection;
  42 +import java.util.Collections;
41 import java.util.List; 43 import java.util.List;
42 44
43 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 45 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
44 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; 46 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
45 -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_CONTRACT_EXISTS; 47 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_DELETE_FAIL_CONTRACT_EXISTS;
46 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; 48 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS;
47 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; 49 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
48 50
@@ -100,14 +102,19 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -100,14 +102,19 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
100 businessProducts.forEach(item -> item.setBusinessId(business.getId())); 102 businessProducts.forEach(item -> item.setBusinessId(business.getId()));
101 businessProductMapper.insertBatch(businessProducts); 103 businessProductMapper.insertBatch(businessProducts);
102 } 104 }
103 - // 在联系人的详情页,如果直接【新建商机】,则需要关联下。  
104 - contactBusinessService.createContactBusiness(createReqVO.getContactId(), business.getId()); 105 +
105 // 3. 创建数据权限 106 // 3. 创建数据权限
106 // 设置当前操作的人为负责人 107 // 设置当前操作的人为负责人
107 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) 108 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())
108 .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); 109 .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
109 110
110 - // 4. 记录操作日志上下文 111 + // 4. 在联系人的详情页,如果直接【新建商机】,则需要关联下
  112 + if (createReqVO.getContactId() != null) {
  113 + contactBusinessService.createContactBusinessList(new CrmContactBusinessReqVO().setContactId(createReqVO.getContactId())
  114 + .setBusinessIds(Collections.singletonList(business.getId())));
  115 + }
  116 +
  117 + // 5. 记录操作日志上下文
111 LogRecordContext.putVariable("business", business); 118 LogRecordContext.putVariable("business", business);
112 return business.getId(); 119 return business.getId();
113 } 120 }
@@ -139,6 +146,28 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -139,6 +146,28 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
139 LogRecordContext.putVariable("businessName", oldBusiness.getName()); 146 LogRecordContext.putVariable("businessName", oldBusiness.getName());
140 } 147 }
141 148
  149 + @Override
  150 + @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_FOLLOW_UP_SUB_TYPE, bizNo = "{{#id}",
  151 + success = CRM_BUSINESS_FOLLOW_UP_SUCCESS)
  152 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
  153 + public void updateBusinessFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {
  154 + // 1. 校验存在
  155 + CrmBusinessDO business = validateBusinessExists(id);
  156 +
  157 + // 2. 更新联系人的跟进信息
  158 + businessMapper.updateById(new CrmBusinessDO().setId(id).setFollowUpStatus(true).setContactNextTime(contactNextTime)
  159 + .setContactLastTime(LocalDateTime.now()));
  160 +
  161 + // 3. 记录操作日志上下文
  162 + LogRecordContext.putVariable("businessName", business.getName());
  163 + }
  164 +
  165 + @Override
  166 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#ids", level = CrmPermissionLevelEnum.WRITE)
  167 + public void updateBusinessContactNextTime(Collection<Long> ids, LocalDateTime contactNextTime) {
  168 + businessMapper.updateBatch(convertList(ids, id -> new CrmBusinessDO().setId(id).setContactNextTime(contactNextTime)));
  169 + }
  170 +
142 private void updateBusinessProduct(Long id, List<CrmBusinessProductDO> newList) { 171 private void updateBusinessProduct(Long id, List<CrmBusinessProductDO> newList) {
143 List<CrmBusinessProductDO> oldList = businessProductMapper.selectListByBusinessId(id); 172 List<CrmBusinessProductDO> oldList = businessProductMapper.selectListByBusinessId(id);
144 List<List<CrmBusinessProductDO>> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 173 List<List<CrmBusinessProductDO>> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录
@@ -190,19 +219,14 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -190,19 +219,14 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
190 } 219 }
191 220
192 @Override 221 @Override
193 - public void updateBusinessFollowUpBatch(List<CrmUpdateFollowUpReqBO> updateFollowUpReqBOList) {  
194 - businessMapper.updateBatch(CrmBusinessConvert.INSTANCE.convertList(updateFollowUpReqBOList));  
195 - }  
196 -  
197 - @Override  
198 @Transactional(rollbackFor = Exception.class) 222 @Transactional(rollbackFor = Exception.class)
199 @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_DELETE_SUB_TYPE, bizNo = "{{#id}}", 223 @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_DELETE_SUB_TYPE, bizNo = "{{#id}}",
200 success = CRM_BUSINESS_DELETE_SUCCESS) 224 success = CRM_BUSINESS_DELETE_SUCCESS)
201 @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) 225 @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
202 public void deleteBusiness(Long id) { 226 public void deleteBusiness(Long id) {
203 - // 校验存在 227 + // 1.1 校验存在
204 CrmBusinessDO business = validateBusinessExists(id); 228 CrmBusinessDO business = validateBusinessExists(id);
205 - // TODO @商机待定:需要校验有没关联合同。CrmContractDO 的 businessId 字段 229 + // 1.2 校验是否关联合同
206 validateContractExists(id); 230 validateContractExists(id);
207 231
208 // 删除 232 // 删除
@@ -222,7 +246,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -222,7 +246,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
222 */ 246 */
223 private void validateContractExists(Long businessId) { 247 private void validateContractExists(Long businessId) {
224 if (contractService.getContractCountByBusinessId(businessId) > 0) { 248 if (contractService.getContractCountByBusinessId(businessId) > 0) {
225 - throw exception(BUSINESS_CONTRACT_EXISTS); 249 + throw exception(BUSINESS_DELETE_FAIL_CONTRACT_EXISTS);
226 } 250 }
227 } 251 }
228 252
@@ -245,8 +269,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @@ -245,8 +269,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
245 CrmBusinessDO business = validateBusinessExists(reqVO.getId()); 269 CrmBusinessDO business = validateBusinessExists(reqVO.getId());
246 270
247 // 2.1 数据权限转移 271 // 2.1 数据权限转移
248 - permissionService.transferPermission(  
249 - CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())); 272 + permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_BUSINESS.getType(),
  273 + reqVO.getNewOwnerUserId(), reqVO.getId(), CrmPermissionLevelEnum.OWNER.getLevel()));
250 // 2.2 设置新的负责人 274 // 2.2 设置新的负责人
251 businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); 275 businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
252 276
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java
@@ -14,15 +14,6 @@ import java.util.List; @@ -14,15 +14,6 @@ import java.util.List;
14 public interface CrmContactBusinessService { 14 public interface CrmContactBusinessService {
15 15
16 /** 16 /**
17 - * 创建联系人人商机关联  
18 - *  
19 - * @param contactId 联系人编号  
20 - * @param businessId 商机编号  
21 - */  
22 - void createContactBusiness(Long contactId, Long businessId);  
23 -  
24 -  
25 - /**  
26 * 创建联系人与商机的关联 17 * 创建联系人与商机的关联
27 * 18 *
28 * @param createReqVO 创建信息 19 * @param createReqVO 创建信息
@@ -51,4 +42,12 @@ public interface CrmContactBusinessService { @@ -51,4 +42,12 @@ public interface CrmContactBusinessService {
51 */ 42 */
52 List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId); 43 List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId);
53 44
  45 + /**
  46 + * 获得联系人与商机的关联列表,基于商机编号
  47 + *
  48 + * @param businessId 商机编号
  49 + * @return 联系人商机关联
  50 + */
  51 + List<CrmContactBusinessDO> getContactBusinessListByBusinessId(Long businessId);
  52 +
54 } 53 }
55 \ No newline at end of file 54 \ No newline at end of file
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java
@@ -42,22 +42,6 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService @@ -42,22 +42,6 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
42 private CrmContactService contactService; 42 private CrmContactService contactService;
43 43
44 @Override 44 @Override
45 - public void createContactBusiness(Long contactId, Long businessId) {  
46 - // 校验存在  
47 - CrmContactDO contact = contactService.getContact(contactId);  
48 - if (contact == null) {  
49 - throw exception(CONTACT_NOT_EXISTS);  
50 - }  
51 - CrmBusinessDO business = businessService.getBusiness(businessId);  
52 - if (business == null) {  
53 - throw exception(BUSINESS_NOT_EXISTS);  
54 - }  
55 -  
56 - // 插入  
57 - contactBusinessMapper.insert(new CrmContactBusinessDO(null, contactId, businessId));  
58 - }  
59 -  
60 - @Override  
61 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#createReqVO.contactId", level = CrmPermissionLevelEnum.WRITE) 45 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#createReqVO.contactId", level = CrmPermissionLevelEnum.WRITE)
62 public void createContactBusinessList(CrmContactBusinessReqVO createReqVO) { 46 public void createContactBusinessList(CrmContactBusinessReqVO createReqVO) {
63 CrmContactDO contact = contactService.getContact(createReqVO.getContactId()); 47 CrmContactDO contact = contactService.getContact(createReqVO.getContactId());
@@ -107,4 +91,10 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService @@ -107,4 +91,10 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
107 return contactBusinessMapper.selectListByContactId(contactId); 91 return contactBusinessMapper.selectListByContactId(contactId);
108 } 92 }
109 93
  94 + @Override
  95 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#businessId", level = CrmPermissionLevelEnum.READ)
  96 + public List<CrmContactBusinessDO> getContactBusinessListByBusinessId(Long businessId) {
  97 + return contactBusinessMapper.selectListByBusinessId(businessId);
  98 + }
  99 +
110 } 100 }
111 \ No newline at end of file 101 \ No newline at end of file
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; @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; 4 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
5 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO; 5 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO;
6 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; 6 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
  7 +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
7 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; 8 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
8 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 9 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
9 import jakarta.validation.Valid; 10 import jakarta.validation.Valid;
@@ -72,13 +73,12 @@ public interface CrmContactService { @@ -72,13 +73,12 @@ public interface CrmContactService {
72 void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent); 73 void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent);
73 74
74 /** 75 /**
75 - * 更新联系人相关跟进信息 76 + * 更新联系人的下次联系时间
76 * 77 *
77 * @param ids 编号数组 78 * @param ids 编号数组
78 * @param contactNextTime 下次联系时间 79 * @param contactNextTime 下次联系时间
79 - * @param contactLastContent 最后联系内容  
80 */ 80 */
81 - void updateContactFollowUpBatch(Collection<Long> ids, LocalDateTime contactNextTime, String contactLastContent); 81 + void updateContactContactNextTime(Collection<Long> ids, LocalDateTime contactNextTime);
82 82
83 /** 83 /**
84 * 获得联系人 84 * 获得联系人
@@ -152,6 +152,16 @@ public interface CrmContactService { @@ -152,6 +152,16 @@ public interface CrmContactService {
152 PageResult<CrmContactDO> getContactPageByCustomerId(CrmContactPageReqVO pageVO); 152 PageResult<CrmContactDO> getContactPageByCustomerId(CrmContactPageReqVO pageVO);
153 153
154 /** 154 /**
  155 + * 获得联系人分页
  156 + *
  157 + * 数据权限:基于 {@link CrmBusinessDO}
  158 + *
  159 + * @param pageVO 分页查询
  160 + * @return 联系人分页
  161 + */
  162 + PageResult<CrmContactDO> getContactPageByBusinessId(CrmContactPageReqVO pageVO);
  163 +
  164 + /**
155 * 获取关联客户的联系人数量 165 * 获取关联客户的联系人数量
156 * 166 *
157 * @param customerId 客户编号 167 * @param customerId 客户编号
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 @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusines
8 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; 8 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
9 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO; 9 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO;
10 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; 10 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
  11 +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO;
11 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; 12 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
12 import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; 13 import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper;
13 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 14 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
@@ -36,6 +37,7 @@ import java.util.List; @@ -36,6 +37,7 @@ import java.util.List;
36 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 37 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
37 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; 38 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
38 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; 39 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  40 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
39 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; 41 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
40 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; 42 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*;
41 import static java.util.Collections.singletonList; 43 import static java.util.Collections.singletonList;
@@ -225,7 +227,7 @@ public class CrmContactServiceImpl implements CrmContactService { @@ -225,7 +227,7 @@ public class CrmContactServiceImpl implements CrmContactService {
225 success = CRM_CONTACT_FOLLOW_UP_SUCCESS) 227 success = CRM_CONTACT_FOLLOW_UP_SUCCESS)
226 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) 228 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
227 public void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) { 229 public void updateContactFollowUp(Long id, LocalDateTime contactNextTime, String contactLastContent) {
228 - // 1.1 校验存在 230 + // 1. 校验存在
229 CrmContactDO contact = validateContactExists(id); 231 CrmContactDO contact = validateContactExists(id);
230 232
231 // 2. 更新联系人的跟进信息 233 // 2. 更新联系人的跟进信息
@@ -238,9 +240,8 @@ public class CrmContactServiceImpl implements CrmContactService { @@ -238,9 +240,8 @@ public class CrmContactServiceImpl implements CrmContactService {
238 240
239 @Override 241 @Override
240 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#ids", level = CrmPermissionLevelEnum.WRITE) 242 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#ids", level = CrmPermissionLevelEnum.WRITE)
241 - public void updateContactFollowUpBatch(Collection<Long> ids, LocalDateTime contactNextTime, String contactLastContent) {  
242 - contactMapper.updateBatch(convertList(ids, id -> new CrmContactDO().setId(id).setContactLastTime(LocalDateTime.now())  
243 - .setContactNextTime(contactNextTime).setContactLastContent(contactLastContent))); 243 + public void updateContactContactNextTime(Collection<Long> ids, LocalDateTime contactNextTime) {
  244 + contactMapper.updateBatch(convertList(ids, id -> new CrmContactDO().setId(id).setContactNextTime(contactNextTime)));
244 } 245 }
245 246
246 //======================= 查询相关 ======================= 247 //======================= 查询相关 =======================
@@ -291,6 +292,16 @@ public class CrmContactServiceImpl implements CrmContactService { @@ -291,6 +292,16 @@ public class CrmContactServiceImpl implements CrmContactService {
291 } 292 }
292 293
293 @Override 294 @Override
  295 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#pageVO.businessId", level = CrmPermissionLevelEnum.READ)
  296 + public PageResult<CrmContactDO> getContactPageByBusinessId(CrmContactPageReqVO pageVO) {
  297 + List<CrmContactBusinessDO> contactBusinessList = contactBusinessService.getContactBusinessListByBusinessId(pageVO.getBusinessId());
  298 + if (CollUtil.isEmpty(contactBusinessList)) {
  299 + return PageResult.empty();
  300 + }
  301 + return contactMapper.selectPageByBusinessId(pageVO, convertSet(contactBusinessList, CrmContactBusinessDO::getContactId));
  302 + }
  303 +
  304 + @Override
294 public Long getContactCountByCustomerId(Long customerId) { 305 public Long getContactCountByCustomerId(Long customerId) {
295 return contactMapper.selectCount(CrmContactDO::getCustomerId, customerId); 306 return contactMapper.selectCount(CrmContactDO::getCustomerId, customerId);
296 } 307 }
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; @@ -26,11 +26,9 @@ import org.springframework.validation.annotation.Validated;
26 26
27 import java.time.LocalDateTime; 27 import java.time.LocalDateTime;
28 import java.util.Collection; 28 import java.util.Collection;
29 -import java.util.Collections;  
30 import java.util.List; 29 import java.util.List;
31 30
32 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 31 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
33 -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;  
34 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_DELETE_DENIED; 32 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_DELETE_DENIED;
35 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_NOT_EXISTS; 33 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_NOT_EXISTS;
36 34
@@ -77,7 +75,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { @@ -77,7 +75,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService {
77 .setContactLastTime(LocalDateTime.now()) 75 .setContactLastTime(LocalDateTime.now())
78 .setContactNextTime(record.getNextTime()).setContactLastContent(record.getContent()); 76 .setContactNextTime(record.getNextTime()).setContactLastContent(record.getContent());
79 if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), record.getBizType())) { // 更新商机跟进信息 77 if (ObjUtil.equal(CrmBizTypeEnum.CRM_BUSINESS.getType(), record.getBizType())) { // 更新商机跟进信息
80 - businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); 78 + businessService.updateBusinessFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
81 } 79 }
82 if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), record.getBizType())) { // 更新线索跟进信息 80 if (ObjUtil.equal(CrmBizTypeEnum.CRM_CLUE.getType(), record.getBizType())) { // 更新线索跟进信息
83 clueService.updateClueFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); 81 clueService.updateClueFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
@@ -92,14 +90,13 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { @@ -92,14 +90,13 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService {
92 customerService.updateCustomerFollowUp(record.getBizId(), record.getNextTime(), record.getContent()); 90 customerService.updateCustomerFollowUp(record.getBizId(), record.getNextTime(), record.getContent());
93 } 91 }
94 92
95 - // 3.1 更新 contactIds 对应的记录,不更新 lastTime 和 lastContent 93 + // 3.1 更新 contactIds 对应的记录,只更新 nextTime
96 if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { 94 if (CollUtil.isNotEmpty(createReqVO.getContactIds())) {
97 - contactService.updateContactFollowUpBatch(createReqVO.getContactIds(), null, null); 95 + contactService.updateContactContactNextTime(createReqVO.getContactIds(), createReqVO.getNextTime());
98 } 96 }
99 - // 3.2 需要更新 businessIds 对应的记录,不更新 lastTime 和 lastContent 97 + // 3.2 需要更新 businessIds 对应的记录,只更新 nextTime
100 if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) { 98 if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) {
101 - businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(),  
102 - businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null))); 99 + businessService.updateBusinessContactNextTime(createReqVO.getBusinessIds(), createReqVO.getNextTime());
103 } 100 }
104 return record.getId(); 101 return record.getId();
105 } 102 }