Commit 3e6524932b06cea91cff375ea31cb9a88e34c680

Authored by YunaiV
1 parent 69a974ef

✨ CRM:优化客户的详情、更新成交状态

Showing 19 changed files with 204 additions and 229 deletions
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
... ... @@ -51,6 +51,7 @@ public interface ErrorCodeConstants {
51 51 ErrorCode CUSTOMER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_020_006_012, "导入客户数据不能为空!");
52 52 ErrorCode CUSTOMER_CREATE_NAME_NOT_NULL = new ErrorCode(1_020_006_013, "客户名称不能为空!");
53 53 ErrorCode CUSTOMER_NAME_EXISTS = new ErrorCode(1_020_006_014, "已存在名为【{}】的客户!");
  54 + ErrorCode CUSTOMER_UPDATE_DEAL_STATUS_FAIL = new ErrorCode(1_020_006_015, "更新客户的成交状态失败,原因:已经是该状态,无需更新");
54 55  
55 56 // ========== 权限管理 1_020_007_000 ==========
56 57 ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在");
... ...
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
... ... @@ -43,6 +43,8 @@ public interface LogRecordConstants {
43 43 String CRM_CUSTOMER_RECEIVE_SUCCESS = "{{#ownerUserName != null ? '将客户【' + #customer.name + '】分配给【' + #ownerUserName + '】' : '领取客户【' + #customer.name + '】'}}";
44 44 String CRM_CUSTOMER_IMPORT_SUB_TYPE = "{{#isUpdate ? '导入并更新客户' : '导入客户'}}";
45 45 String CRM_CUSTOMER_IMPORT_SUCCESS = "{{#isUpdate ? '导入并更新了客户【'+ #customer.name +'】' : '导入了客户【'+ #customer.name +'】'}}";
  46 + String CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUB_TYPE = "更新客户成交状态";
  47 + String CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUCCESS = "更新了客户【{{#customerName}}】的成交状态为【{{#dealStatus ? '已成交' : '未成交'}}】";
46 48  
47 49 // ======================= CRM_CUSTOMER_LIMIT_CONFIG 客户限制配置 =======================
48 50  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http deleted
1   -### 请求 /transfer
2   -PUT {{baseUrl}}/crm/customer/transfer
3   -Content-Type: application/-id: {{adminTenentId}}json
4   -Authorization: Bearer {{token}}
5   -tenant
6   -
7   -{
8   - "id": 10,
9   - "newOwnerUserId": 127
10   -}
11   -
12   -### 自定义日志记录结果
13   -### 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=客户转移, bizId=10, content=把客户【张三】的负责人从【芋道源码(15612345678)】变更为了【tttt】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/transfer, userIp=127.0.0.1, userAgent=Apache-HttpClient/4.5.14 (Java/17.0.9))
14   -
15   -### diff 日志
16   -### | 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=更新客户, bizId=11, content=更新了客户【所属行业】从【H 住宿和餐饮业】修改为【D 电力、热力、燃气及水生产和供应业】;【客户等级】从【C (非优先客户)】修改为【A (重点客户)】;【客户来源】从【线上咨询】修改为【预约上门】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/update, userIp=0:0:0:0:0:0:0:1, userAgent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36)
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
... ... @@ -5,12 +5,14 @@ import cn.hutool.core.map.MapUtil;
5 5 import cn.hutool.core.util.ObjUtil;
6 6 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
7 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  8 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
8 9 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
  10 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
9 11 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 12 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  13 +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
11 14 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
12   -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
13   -import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
  15 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*;
14 16 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
15 17 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
16 18 import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum;
... ... @@ -22,11 +24,11 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
22 24 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
23 25 import io.swagger.v3.oas.annotations.Operation;
24 26 import io.swagger.v3.oas.annotations.Parameter;
  27 +import io.swagger.v3.oas.annotations.Parameters;
25 28 import io.swagger.v3.oas.annotations.tags.Tag;
26 29 import jakarta.annotation.Resource;
27 30 import jakarta.servlet.http.HttpServletResponse;
28 31 import jakarta.validation.Valid;
29   -import org.mapstruct.ap.internal.util.Collections;
30 32 import org.springframework.security.access.prepost.PreAuthorize;
31 33 import org.springframework.validation.annotation.Validated;
32 34 import org.springframework.web.bind.annotation.*;
... ... @@ -45,6 +47,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
45 47 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
46 48 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
47 49 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED;
  50 +import static java.util.Collections.singletonList;
48 51  
49 52 @Tag(name = "管理后台 - CRM 客户")
50 53 @RestController
... ... @@ -77,6 +80,18 @@ public class CrmCustomerController {
77 80 return success(true);
78 81 }
79 82  
  83 + @PutMapping("/update-deal-status")
  84 + @Operation(summary = "更新客户的成交状态")
  85 + @Parameters({
  86 + @Parameter(name = "id", description = "客户编号", required = true),
  87 + @Parameter(name = "dealStatus", description = "成交状态", required = true)
  88 + })
  89 + public CommonResult<Boolean> updateCustomerDealStatus(@RequestParam("id") Long id,
  90 + @RequestParam("dealStatus") Boolean dealStatus) {
  91 + customerService.updateCustomerDealStatus(id, dealStatus);
  92 + return success(true);
  93 + }
  94 +
80 95 @DeleteMapping("/delete")
81 96 @Operation(summary = "删除客户")
82 97 @Parameter(name = "id", description = "客户编号", required = true)
... ... @@ -93,14 +108,15 @@ public class CrmCustomerController {
93 108 public CommonResult<CrmCustomerRespVO> getCustomer(@RequestParam("id") Long id) {
94 109 // 1. 获取客户
95 110 CrmCustomerDO customer = customerService.getCustomer(id);
  111 + // 2. 拼接数据
  112 + return success(buildCustomerDetail(customer));
  113 + }
  114 +
  115 + public CrmCustomerRespVO buildCustomerDetail(CrmCustomerDO customer) {
96 116 if (customer == null) {
97   - return success(null);
  117 + return null;
98 118 }
99   - // 2. 拼接数据
100   - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
101   - Collections.asSet(Long.valueOf(customer.getCreator()), customer.getOwnerUserId()));
102   - Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
103   - return success(CrmCustomerConvert.INSTANCE.convert(customer, userMap, deptMap));
  119 + return buildCustomerDetailList(singletonList(customer)).get(0);
104 120 }
105 121  
106 122 @GetMapping("/page")
... ... @@ -112,16 +128,38 @@ public class CrmCustomerController {
112 128 if (CollUtil.isEmpty(pageResult.getList())) {
113 129 return success(PageResult.empty(pageResult.getTotal()));
114 130 }
115   -
116 131 // 2. 拼接数据
117   - Map<Long, Long> poolDayMap = Boolean.TRUE.equals(pageVO.getPool()) ? null :
118   - getPoolDayMap(pageResult.getList()); // 客户界面,需要查看距离进入公海的时间
119   - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
120   - convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId())));
  132 + return success(new PageResult<>(buildCustomerDetailList(pageResult.getList()), pageResult.getTotal()));
  133 + }
  134 +
  135 + public List<CrmCustomerRespVO> buildCustomerDetailList(List<CrmCustomerDO> list) {
  136 + if (CollUtil.isEmpty(list)) {
  137 + return java.util.Collections.emptyList();
  138 + }
  139 + // 1.1 获取创建人、负责人列表
  140 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(list,
  141 + contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
121 142 Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
122   - return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap));
  143 + // 1.2 获取距离进入公海的时间
  144 + Map<Long, Long> poolDayMap = getPoolDayMap(list);
  145 + // 2. 转换成 VO
  146 + return BeanUtils.toBean(list, CrmCustomerRespVO.class, customerVO -> {
  147 + customerVO.setAreaName(AreaUtils.format(customerVO.getAreaId()));
  148 + // 2.1 设置创建人、负责人名称
  149 + MapUtils.findAndThen(userMap, NumberUtils.parseLong(customerVO.getCreator()),
  150 + user -> customerVO.setCreatorName(user.getNickname()));
  151 + MapUtils.findAndThen(userMap, customerVO.getOwnerUserId(), user -> {
  152 + customerVO.setOwnerUserName(user.getNickname());
  153 + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> customerVO.setOwnerUserDeptName(dept.getName()));
  154 + });
  155 + // 2.2 设置距离进入公海的时间
  156 + if (customerVO.getOwnerUserId() != null) {
  157 + customerVO.setPoolDay(poolDayMap.get(customerVO.getId()));
  158 + }
  159 + });
123 160 }
124 161  
  162 + // TODO @芋艿:需要 review 下
125 163 @GetMapping("/put-in-pool-remind-page")
126 164 @Operation(summary = "获得待进入公海客户分页")
127 165 @PreAuthorize("@ss.hasPermission('crm:customer:query')")
... ... @@ -141,12 +179,7 @@ public class CrmCustomerController {
141 179 }
142 180  
143 181 // 2. 拼接数据
144   - // TODO @芋艿:合并 getCustomerPage 和 getPutInPoolRemindCustomerPage 的后置处理;
145   - Map<Long, Long> poolDayMap = getPoolDayMap(pageResult.getList()); // 客户界面,需要查看距离进入公海的时间
146   - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
147   - convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId())));
148   - Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
149   - return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap));
  182 + return success(new PageResult<>(buildCustomerDetailList(pageResult.getList()), pageResult.getTotal()));
150 183 }
151 184  
152 185 @GetMapping("/put-in-pool-remind-count")
... ... @@ -182,22 +215,26 @@ public class CrmCustomerController {
182 215 }
183 216  
184 217 /**
185   - * 获取距离进入公海的时间
  218 + * 获取距离进入公海的时间 Map
186 219 *
187   - * @param customerList 客户列表
188   - * @return Map<key 客户编号, value 距离进入公海的时间>
  220 + * @param list 客户列表
  221 + * @return key 客户编号, value 距离进入公海的时间
189 222 */
190   - private Map<Long, Long> getPoolDayMap(List<CrmCustomerDO> customerList) {
  223 + private Map<Long, Long> getPoolDayMap(List<CrmCustomerDO> list) {
191 224 CrmCustomerPoolConfigDO poolConfig = customerPoolConfigService.getCustomerPoolConfig();
192 225 if (poolConfig == null || !poolConfig.getEnabled()) {
193 226 return MapUtil.empty();
194 227 }
195   - return convertMap(customerList, CrmCustomerDO::getId, customer -> {
  228 + return convertMap(list, CrmCustomerDO::getId, customer -> {
  229 + // TODO 芋艿:这样计算,貌似有点问题
196 230 // 1.1 未成交放入公海天数
197 231 long dealExpireDay = 0;
198 232 if (!customer.getDealStatus()) {
199 233 dealExpireDay = poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime());
200 234 }
  235 + if (dealExpireDay < 0) {
  236 + dealExpireDay = 0;
  237 + }
201 238 // 1.2 未跟进放入公海天数
202 239 LocalDateTime lastTime = ObjUtil.defaultIfNull(customer.getContactLastTime(), customer.getCreateTime());
203 240 long contactExpireDay = poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime);
... ... @@ -230,7 +267,7 @@ public class CrmCustomerController {
230 267 List<CrmCustomerDO> list = customerService.getCustomerPage(pageVO, getLoginUserId()).getList();
231 268 // 导出 Excel
232 269 ExcelUtils.write(response, "客户.xls", "数据", CrmCustomerRespVO.class,
233   - BeanUtils.toBean(list, CrmCustomerRespVO.class));
  270 + buildCustomerDetailList(list));
234 271 }
235 272  
236 273 @GetMapping("/get-import-template")
... ... @@ -238,12 +275,12 @@ public class CrmCustomerController {
238 275 public void importTemplate(HttpServletResponse response) throws IOException {
239 276 // 手动创建导出 demo
240 277 List<CrmCustomerImportExcelVO> list = Arrays.asList(
241   - CrmCustomerImportExcelVO.builder().name("芋道").industryId(1).level(1).source(1).mobile("15601691300").telephone("")
242   - .qq("").wechat("").email("yunai@iocoder.cn").description("").remark("")
243   - .areaId(null).detailAddress("").build(),
244   - CrmCustomerImportExcelVO.builder().name("源码").industryId(1).level(1).source(1).mobile("15601691300").telephone("")
245   - .qq("").wechat("").email("yunai@iocoder.cn").description("").remark("")
246   - .areaId(null).detailAddress("").build()
  278 + CrmCustomerImportExcelVO.builder().name("芋道").industryId(1).level(1).source(1)
  279 + .mobile("15601691300").telephone("").qq("").wechat("").email("yunai@iocoder.cn")
  280 + .areaId(null).detailAddress("").remark("").build(),
  281 + CrmCustomerImportExcelVO.builder().name("源码").industryId(1).level(1).source(1)
  282 + .mobile("15601691300").telephone("").qq("").wechat("").email("yunai@iocoder.cn")
  283 + .areaId(null).detailAddress("").remark("").build()
247 284 );
248 285 // 输出
249 286 ExcelUtils.write(response, "客户导入模板.xls", "客户列表", CrmCustomerImportExcelVO.class, list);
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerDistributeReqVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerDistributeReqVO.java
1   -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import jakarta.validation.constraints.NotEmpty;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java
1   -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
... ... @@ -24,19 +24,6 @@ public class CrmCustomerImportExcelVO {
24 24 @ExcelProperty("客户名称")
25 25 private String name;
26 26  
27   - // TODO @puhui999:industryId、level、source 字段,可以研究下怎么搞下拉框
28   - @ExcelProperty(value = "所属行业", converter = DictConvert.class)
29   - @DictFormat(CRM_CUSTOMER_INDUSTRY)
30   - private Integer industryId;
31   -
32   - @ExcelProperty(value = "客户等级", converter = DictConvert.class)
33   - @DictFormat(CRM_CUSTOMER_LEVEL)
34   - private Integer level;
35   -
36   - @ExcelProperty(value = "客户来源", converter = DictConvert.class)
37   - @DictFormat(CRM_CUSTOMER_SOURCE)
38   - private Integer source;
39   -
40 27 @ExcelProperty("手机")
41 28 private String mobile;
42 29  
... ... @@ -52,12 +39,6 @@ public class CrmCustomerImportExcelVO {
52 39 @ExcelProperty("邮箱")
53 40 private String email;
54 41  
55   - @ExcelProperty("客户描述")
56   - private String description;
57   -
58   - @ExcelProperty("备注")
59   - private String remark;
60   -
61 42 // TODO @puhui999:需要选择省市区,需要研究下,怎么搞合理点;
62 43 @ExcelProperty("地区编号")
63 44 private Integer areaId;
... ... @@ -65,4 +46,20 @@ public class CrmCustomerImportExcelVO {
65 46 @ExcelProperty("详细地址")
66 47 private String detailAddress;
67 48  
  49 + // TODO @puhui999:industryId、level、source 字段,可以研究下怎么搞下拉框
  50 + @ExcelProperty(value = "所属行业", converter = DictConvert.class)
  51 + @DictFormat(CRM_CUSTOMER_INDUSTRY)
  52 + private Integer industryId;
  53 +
  54 + @ExcelProperty(value = "客户等级", converter = DictConvert.class)
  55 + @DictFormat(CRM_CUSTOMER_LEVEL)
  56 + private Integer level;
  57 +
  58 + @ExcelProperty(value = "客户来源", converter = DictConvert.class)
  59 + @DictFormat(CRM_CUSTOMER_SOURCE)
  60 + private Integer source;
  61 +
  62 + @ExcelProperty("备注")
  63 + private String remark;
  64 +
68 65 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportReqVO.java
1   -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import jakarta.validation.constraints.NotNull;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportRespVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportRespVO.java
1   -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Builder;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerLockReqVO.java
1   -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerPageReqVO.java
1   -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java
1   -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
... ... @@ -7,12 +7,9 @@ import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
7 7 import com.alibaba.excel.annotation.ExcelProperty;
8 8 import io.swagger.v3.oas.annotations.media.Schema;
9 9 import lombok.Data;
10   -import org.springframework.format.annotation.DateTimeFormat;
11 10  
12 11 import java.time.LocalDateTime;
13 12  
14   -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
15   -
16 13 @Schema(description = "管理后台 - CRM 客户 Response VO")
17 14 @Data
18 15 @ExcelIgnoreUnannotated
... ... @@ -31,6 +28,28 @@ public class CrmCustomerRespVO {
31 28 @DictFormat(DictTypeConstants.BOOLEAN_STRING)
32 29 private Boolean followUpStatus;
33 30  
  31 + @Schema(description = "最后跟进时间")
  32 + @ExcelProperty("最后跟进时间")
  33 + private LocalDateTime contactLastTime;
  34 +
  35 + @Schema(description = "最后跟进内容", example = "吃饭、睡觉、打逗逗")
  36 + @ExcelProperty("最后跟进内容")
  37 + private String contactLastContent;
  38 +
  39 + @Schema(description = "下次联系时间")
  40 + @ExcelProperty("下次联系时间")
  41 + private LocalDateTime contactNextTime;
  42 +
  43 + @Schema(description = "负责人的用户编号", example = "25682")
  44 + @ExcelProperty("负责人的用户编号")
  45 + private Long ownerUserId;
  46 + @Schema(description = "负责人名字", example = "25682")
  47 + @ExcelProperty("负责人名字")
  48 + private String ownerUserName;
  49 + @Schema(description = "负责人部门")
  50 + @ExcelProperty("负责人部门")
  51 + private String ownerUserDeptName;
  52 +
34 53 @Schema(description = "锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
35 54 @ExcelProperty(value = "锁定状态", converter = DictConvert.class)
36 55 @DictFormat(DictTypeConstants.BOOLEAN_STRING)
... ... @@ -41,55 +60,26 @@ public class CrmCustomerRespVO {
41 60 @DictFormat(DictTypeConstants.BOOLEAN_STRING)
42 61 private Boolean dealStatus;
43 62  
44   - @Schema(description = "所属行业", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
45   - @ExcelProperty(value = "所属行业", converter = DictConvert.class)
46   - @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY)
47   - private Integer industryId;
48   -
49   - @Schema(description = "客户等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
50   - @ExcelProperty(value = "客户等级", converter = DictConvert.class)
51   - @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL)
52   - private Integer level;
53   -
54   - @Schema(description = "客户来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
55   - @ExcelProperty(value = "客户来源", converter = DictConvert.class)
56   - @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE)
57   - private Integer source;
58   -
59   - @Schema(description = "负责人的用户编号", example = "25682")
  63 + @Schema(description = "手机", example = "25682")
60 64 @ExcelProperty("手机")
61 65 private String mobile;
62 66  
63   - @Schema(description = "负责人的用户编号", example = "25682")
  67 + @Schema(description = "电话", example = "25682")
64 68 @ExcelProperty("电话")
65 69 private String telephone;
66 70  
67   - @Schema(description = "负责人的用户编号", example = "25682")
  71 + @Schema(description = "QQ", example = "25682")
68 72 @ExcelProperty("QQ")
69 73 private String qq;
70 74  
71   - @Schema(description = "负责人的用户编号", example = "25682")
  75 + @Schema(description = "wechat", example = "25682")
72 76 @ExcelProperty("wechat")
73 77 private String wechat;
74 78  
75   - @Schema(description = "负责人的用户编号", example = "25682")
  79 + @Schema(description = "email", example = "25682")
76 80 @ExcelProperty("email")
77 81 private String email;
78 82  
79   - @Schema(description = "负责人的用户编号", example = "25682")
80   - @ExcelProperty("备注")
81   - private String remark;
82   -
83   - @Schema(description = "负责人的用户编号", example = "25682")
84   - @ExcelProperty("负责人的用户编号")
85   - private Long ownerUserId;
86   - @Schema(description = "负责人名字", example = "25682")
87   - @ExcelProperty("负责人名字")
88   - private String ownerUserName;
89   - @Schema(description = "负责人部门")
90   - @ExcelProperty("负责人部门")
91   - private String ownerUserDeptName;
92   -
93 83 @Schema(description = "地区编号", example = "1024")
94 84 @ExcelProperty("地区编号")
95 85 private Integer areaId;
... ... @@ -100,14 +90,24 @@ public class CrmCustomerRespVO {
100 90 @ExcelProperty("详细地址")
101 91 private String detailAddress;
102 92  
103   - @Schema(description = "最后跟进时间")
104   - @ExcelProperty("最后跟进时间")
105   - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
106   - private LocalDateTime contactLastTime;
  93 + @Schema(description = "所属行业", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
  94 + @ExcelProperty(value = "所属行业", converter = DictConvert.class)
  95 + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY)
  96 + private Integer industryId;
107 97  
108   - @Schema(description = "下次联系时间")
109   - @ExcelProperty("下次联系时间")
110   - private LocalDateTime contactNextTime;
  98 + @Schema(description = "客户等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
  99 + @ExcelProperty(value = "客户等级", converter = DictConvert.class)
  100 + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL)
  101 + private Integer level;
  102 +
  103 + @Schema(description = "客户来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
  104 + @ExcelProperty(value = "客户来源", converter = DictConvert.class)
  105 + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE)
  106 + private Integer source;
  107 +
  108 + @Schema(description = "负责人的用户编号", example = "25682")
  109 + @ExcelProperty("备注")
  110 + private String remark;
111 111  
112 112 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
113 113 @ExcelProperty("创建时间")
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerSaveReqVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerSaveReqVO.java
1   -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer;
2 2  
3 3 import cn.iocoder.yudao.framework.common.validation.InEnum;
4 4 import cn.iocoder.yudao.framework.common.validation.Mobile;
... ... @@ -13,6 +13,7 @@ import com.mzt.logapi.starter.annotation.DiffLogField;
13 13 import io.swagger.v3.oas.annotations.media.Schema;
14 14 import jakarta.validation.constraints.Email;
15 15 import jakarta.validation.constraints.NotEmpty;
  16 +import jakarta.validation.constraints.NotNull;
16 17 import jakarta.validation.constraints.Size;
17 18 import lombok.Data;
18 19 import org.springframework.format.annotation.DateTimeFormat;
... ... @@ -34,19 +35,14 @@ public class CrmCustomerSaveReqVO {
34 35 @NotEmpty(message = "客户名称不能为空")
35 36 private String name;
36 37  
37   - @Schema(description = "所属行业", example = "1")
38   - @DiffLogField(name = "所属行业", function = CrmCustomerIndustryParseFunction.NAME)
39   - @DictFormat(CRM_CUSTOMER_INDUSTRY)
40   - private Integer industryId;
41   -
42   - @Schema(description = "客户等级", example = "2")
43   - @DiffLogField(name = "客户等级", function = CrmCustomerLevelParseFunction.NAME)
44   - @InEnum(CrmCustomerLevelEnum.class)
45   - private Integer level;
  38 + @Schema(description = "下次联系时间")
  39 + @DiffLogField(name = "下次联系时间")
  40 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  41 + private LocalDateTime contactNextTime;
46 42  
47   - @Schema(description = "客户来源", example = "3")
48   - @DiffLogField(name = "客户来源", function = CrmCustomerSourceParseFunction.NAME)
49   - private Integer source;
  43 + @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
  44 + @NotNull(message = "负责人的用户编号不能为空")
  45 + private Long ownerUserId;
50 46  
51 47 @Schema(description = "手机", example = "18000000000")
52 48 @DiffLogField(name = "手机")
... ... @@ -74,15 +70,6 @@ public class CrmCustomerSaveReqVO {
74 70 @Size(max = 255, message = "邮箱长度不能超过 255 个字符")
75 71 private String email;
76 72  
77   - @Schema(description = "客户描述", example = "任意文字")
78   - @DiffLogField(name = "客户描述")
79   - @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符")
80   - private String description;
81   -
82   - @Schema(description = "备注", example = "随便")
83   - @DiffLogField(name = "备注")
84   - private String remark;
85   -
86 73 @Schema(description = "地区编号", example = "20158")
87 74 @DiffLogField(name = "地区编号", function = SysAreaParseFunction.NAME)
88 75 private Integer areaId;
... ... @@ -91,12 +78,22 @@ public class CrmCustomerSaveReqVO {
91 78 @DiffLogField(name = "详细地址")
92 79 private String detailAddress;
93 80  
94   - @Schema(description = "下次联系时间")
95   - @DiffLogField(name = "下次联系时间")
96   - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
97   - private LocalDateTime contactNextTime;
  81 + @Schema(description = "所属行业", example = "1")
  82 + @DiffLogField(name = "所属行业", function = CrmCustomerIndustryParseFunction.NAME)
  83 + @DictFormat(CRM_CUSTOMER_INDUSTRY)
  84 + private Integer industryId;
98 85  
99   - @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
100   - private Long ownerUserId;
  86 + @Schema(description = "客户等级", example = "2")
  87 + @DiffLogField(name = "客户等级", function = CrmCustomerLevelParseFunction.NAME)
  88 + @InEnum(CrmCustomerLevelEnum.class)
  89 + private Integer level;
  90 +
  91 + @Schema(description = "客户来源", example = "3")
  92 + @DiffLogField(name = "客户来源", function = CrmCustomerSourceParseFunction.NAME)
  93 + private Integer source;
  94 +
  95 + @Schema(description = "备注", example = "随便")
  96 + @DiffLogField(name = "备注")
  97 + private String remark;
101 98  
102 99 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerTransferReqVO.java
1   -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo;
  1 +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer;
2 2  
3 3 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
4 4 import io.swagger.v3.oas.annotations.media.Schema;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java deleted
1   -package cn.iocoder.yudao.module.crm.convert.customer;
2   -
3   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
4   -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5   -import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
6   -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerRespVO;
7   -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO;
8   -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
9   -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
10   -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
11   -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
12   -import org.mapstruct.Mapper;
13   -import org.mapstruct.Mapping;
14   -import org.mapstruct.factory.Mappers;
15   -
16   -import java.util.Map;
17   -
18   -import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
19   -
20   -/**
21   - * 客户 Convert
22   - *
23   - * @author Wanwan
24   - */
25   -@Mapper
26   -public interface CrmCustomerConvert {
27   -
28   - CrmCustomerConvert INSTANCE = Mappers.getMapper(CrmCustomerConvert.class);
29   -
30   - default CrmCustomerRespVO convert(CrmCustomerDO customer, Map<Long, AdminUserRespDTO> userMap,
31   - Map<Long, DeptRespDTO> deptMap) {
32   - CrmCustomerRespVO customerResp = BeanUtils.toBean(customer, CrmCustomerRespVO.class);
33   - setUserInfo(customerResp, userMap, deptMap);
34   - return customerResp;
35   - }
36   -
37   - default PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
38   - Map<Long, DeptRespDTO> deptMap, Map<Long, Long> poolDayMap) {
39   - PageResult<CrmCustomerRespVO> result = BeanUtils.toBean(pageResult, CrmCustomerRespVO.class);
40   - result.getList().forEach(item -> {
41   - setUserInfo(item, userMap, deptMap);
42   - findAndThen(poolDayMap, item.getId(), item::setPoolDay);
43   - });
44   - return result;
45   - }
46   -
47   - /**
48   - * 设置用户信息
49   - *
50   - * @param customer CRM 客户 Response VO
51   - * @param userMap 用户信息 map
52   - * @param deptMap 用户部门信息 map
53   - */
54   - static void setUserInfo(CrmCustomerRespVO customer, Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
55   - customer.setAreaName(AreaUtils.format(customer.getAreaId()));
56   - findAndThen(userMap, customer.getOwnerUserId(), user -> {
57   - customer.setOwnerUserName(user.getNickname());
58   - findAndThen(deptMap, user.getDeptId(), dept -> customer.setOwnerUserDeptName(dept.getName()));
59   - });
60   - findAndThen(userMap, Long.parseLong(customer.getCreator()), user -> customer.setCreatorName(user.getNickname()));
61   - }
62   -
63   - @Mapping(target = "bizId", source = "reqVO.id")
64   - CrmPermissionTransferReqBO convert(CrmCustomerTransferReqVO reqVO, Long userId);
65   -
66   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java
... ... @@ -57,10 +57,6 @@ public class CrmCustomerDO extends BaseDO {
57 57 * 关联 AdminUserDO 的 id 字段
58 58 */
59 59 private Long ownerUserId;
60   - /**
61   - * 最后接收时间
62   - */
63   - private LocalDateTime receiveTime;
64 60  
65 61 /**
66 62 * 锁定状态
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
... ... @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 6 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
7 7 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
8 8 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
9   -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO;
  9 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.CrmCustomerPageReqVO;
10 10 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
11 11 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
12 12 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
... ... @@ -8,7 +8,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
8 8 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO;
9 9 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO;
10 10 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO;
11   -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO;
  11 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.CrmCustomerSaveReqVO;
12 12 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
13 13 import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO;
14 14 import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
1 1 package cn.iocoder.yudao.module.crm.service.customer;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4   -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*;
5 5 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
6 6 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
7 7 import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO;
... ... @@ -38,6 +38,14 @@ public interface CrmCustomerService {
38 38 void updateCustomer(@Valid CrmCustomerSaveReqVO updateReqVO);
39 39  
40 40 /**
  41 + * 更新客户的跟进状态
  42 + *
  43 + * @param id 编号
  44 + * @param dealStatus 跟进状态
  45 + */
  46 + void updateCustomerDealStatus(Long id, Boolean dealStatus);
  47 +
  48 + /**
41 49 * 删除客户
42 50 *
43 51 * @param id 编号
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
... ... @@ -10,8 +10,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
10 10 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
11 11 import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
12 12 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
13   -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
14   -import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
  13 +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.*;
15 14 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
16 15 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
17 16 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
... ... @@ -27,6 +26,7 @@ import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO;
27 26 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
28 27 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
29 28 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
  29 +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
30 30 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
31 31 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
32 32 import com.mzt.logapi.context.LogRecordContext;
... ... @@ -138,6 +138,26 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
138 138 }
139 139  
140 140 @Override
  141 + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUB_TYPE, bizNo = "{{#id}}",
  142 + success = CRM_CUSTOMER_UPDATE_DEAL_STATUS_SUCCESS)
  143 + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.WRITE)
  144 + public void updateCustomerDealStatus(Long id, Boolean dealStatus) {
  145 + // 1.1 校验存在
  146 + CrmCustomerDO customer = validateCustomerExists(id);
  147 + // 1.2 校验是否重复操作
  148 + if (Objects.equals(customer.getDealStatus(), dealStatus)) {
  149 + throw exception(CUSTOMER_UPDATE_DEAL_STATUS_FAIL);
  150 + }
  151 +
  152 + // 2. 更新客户的成交状态
  153 + customerMapper.updateById(new CrmCustomerDO().setId(id).setDealStatus(dealStatus));
  154 +
  155 + // 3. 记录操作日志上下文
  156 + LogRecordContext.putVariable("customerName", customer.getName());
  157 + LogRecordContext.putVariable("dealStatus", dealStatus);
  158 + }
  159 +
  160 + @Override
141 161 @Transactional(rollbackFor = Exception.class)
142 162 @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_DELETE_SUB_TYPE, bizNo = "{{#id}}",
143 163 success = CRM_CUSTOMER_DELETE_SUCCESS)
... ... @@ -146,7 +166,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
146 166 // 1.1 校验存在
147 167 CrmCustomerDO customer = validateCustomerExists(id);
148 168 // 1.2 检查引用
149   - checkCustomerReference(id);
  169 + validateCustomerReference(id);
150 170  
151 171 // 2. 删除
152 172 customerMapper.deleteById(id);
... ... @@ -162,7 +182,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
162 182 *
163 183 * @param id 客户编号
164 184 */
165   - private void checkCustomerReference(Long id) {
  185 + private void validateCustomerReference(Long id) {
166 186 if (contactService.getContactCountByCustomerId(id) > 0) {
167 187 throw exception(CUSTOMER_DELETE_FAIL_HAVE_REFERENCE, CrmBizTypeEnum.CRM_CONTACT.getName());
168 188 }
... ... @@ -186,8 +206,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
186 206 validateCustomerExceedOwnerLimit(reqVO.getNewOwnerUserId(), 1);
187 207  
188 208 // 2.1 数据权限转移
189   - permissionService.transferPermission(
190   - CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()));
  209 + permissionService.transferPermission(new CrmPermissionTransferReqBO(userId, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
  210 + reqVO.getId(), reqVO.getNewOwnerUserId(), reqVO.getOldOwnerPermissionLevel()));
191 211 // 2.2 转移后重新设置负责人
192 212 customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
193 213  
... ... @@ -230,8 +250,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
230 250 success = CRM_CUSTOMER_CREATE_SUCCESS)
231 251 public Long createCustomer(CrmCustomerCreateReqBO customerCreateReq, Long userId) {
232 252 // 1. 插入客户
233   - CrmCustomerDO customer = BeanUtils.toBean(customerCreateReq, CrmCustomerDO.class).setOwnerUserId(userId)
234   - .setLockStatus(false).setDealStatus(false).setReceiveTime(LocalDateTime.now());
  253 + CrmCustomerDO customer = BeanUtils.toBean(customerCreateReq, CrmCustomerDO.class).setOwnerUserId(userId);
235 254 customerMapper.insert(customer);
236 255  
237 256 // 2. 创建数据权限
... ...