Commit 9ee6a27b86009e2dc5c86d5682b6ba5e0b19e40e

Authored by 芋道源码
Committed by Gitee
2 parents e6d79eaf 64db1a9c

!715 feat: 客户详情 + review 修改

Merge pull request !715 from wanwan/feature/crm
Showing 12 changed files with 105 additions and 31 deletions
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLevelEnum.java
@@ -19,13 +19,12 @@ public enum CrmCustomerLevelEnum implements IntArrayValuable { @@ -19,13 +19,12 @@ public enum CrmCustomerLevelEnum implements IntArrayValuable {
19 GENERAL(2, "B(普通客户)"), 19 GENERAL(2, "B(普通客户)"),
20 LOW_PRIORITY(3, "C(非优先客户)"); 20 LOW_PRIORITY(3, "C(非优先客户)");
21 21
22 - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLevelEnum::getStatus).toArray(); 22 + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLevelEnum::getLevel).toArray();
23 23
24 - // TODO @wanwan:这里的 status 字段,可以考虑改成 level  
25 /** 24 /**
26 * 状态 25 * 状态
27 */ 26 */
28 - private final Integer status; 27 + private final Integer level;
29 /** 28 /**
30 * 状态名 29 * 状态名
31 */ 30 */
yudao-module-crm/yudao-module-crm-biz/pom.xml
@@ -57,6 +57,12 @@ @@ -57,6 +57,12 @@
57 <artifactId>yudao-spring-boot-starter-excel</artifactId> 57 <artifactId>yudao-spring-boot-starter-excel</artifactId>
58 </dependency> 58 </dependency>
59 59
  60 + <!-- 地址相关 -->
  61 + <dependency>
  62 + <groupId>cn.iocoder.boot</groupId>
  63 + <artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
  64 + </dependency>
  65 +
60 <!-- Test 测试相关 --> 66 <!-- Test 测试相关 -->
61 <dependency> 67 <dependency>
62 <groupId>cn.iocoder.boot</groupId> 68 <groupId>cn.iocoder.boot</groupId>
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
1 package cn.iocoder.yudao.module.crm.controller.admin.customer; 1 package cn.iocoder.yudao.module.crm.controller.admin.customer;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.NumberUtil;
  5 +import cn.hutool.core.util.ObjectUtil;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 6 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 8 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  9 +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
6 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 10 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
7 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; 11 import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*;
8 import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; 12 import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert;
9 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 13 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
10 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; 14 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
  15 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  16 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  17 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  18 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  19 +import com.google.common.collect.Lists;
11 import io.swagger.v3.oas.annotations.Operation; 20 import io.swagger.v3.oas.annotations.Operation;
12 import io.swagger.v3.oas.annotations.Parameter; 21 import io.swagger.v3.oas.annotations.Parameter;
13 import io.swagger.v3.oas.annotations.tags.Tag; 22 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -19,7 +28,9 @@ import javax.annotation.Resource; @@ -19,7 +28,9 @@ import javax.annotation.Resource;
19 import javax.servlet.http.HttpServletResponse; 28 import javax.servlet.http.HttpServletResponse;
20 import javax.validation.Valid; 29 import javax.validation.Valid;
21 import java.io.IOException; 30 import java.io.IOException;
22 -import java.util.List; 31 +import java.util.*;
  32 +import java.util.stream.Collectors;
  33 +import java.util.stream.Stream;
23 34
24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 35 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
25 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 36 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
@@ -33,6 +44,10 @@ public class CrmCustomerController { @@ -33,6 +44,10 @@ public class CrmCustomerController {
33 44
34 @Resource 45 @Resource
35 private CrmCustomerService customerService; 46 private CrmCustomerService customerService;
  47 + @Resource
  48 + private DeptApi deptApi;
  49 + @Resource
  50 + private AdminUserApi adminUserApi;
36 51
37 @PostMapping("/create") 52 @PostMapping("/create")
38 @Operation(summary = "创建客户") 53 @Operation(summary = "创建客户")
@@ -64,7 +79,21 @@ public class CrmCustomerController { @@ -64,7 +79,21 @@ public class CrmCustomerController {
64 @PreAuthorize("@ss.hasPermission('crm:customer:query')") 79 @PreAuthorize("@ss.hasPermission('crm:customer:query')")
65 public CommonResult<CrmCustomerRespVO> getCustomer(@RequestParam("id") Long id) { 80 public CommonResult<CrmCustomerRespVO> getCustomer(@RequestParam("id") Long id) {
66 CrmCustomerDO customer = customerService.getCustomer(id); 81 CrmCustomerDO customer = customerService.getCustomer(id);
67 - return success(CrmCustomerConvert.INSTANCE.convert(customer)); 82 + CrmCustomerRespVO customerRespVO = CrmCustomerConvert.INSTANCE.convert(customer);
  83 + if (ObjectUtil.isAllNotEmpty(customer, customer.getAreaId())) {
  84 + customerRespVO.setAreaName(AreaUtils.format(customer.getAreaId()));
  85 + }
  86 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(CollUtil.removeNull(Lists.newArrayList(NumberUtil.parseLong(customerRespVO.getCreator()), customerRespVO.getOwnerUserId())));
  87 + customerRespVO.setCreatorName(Optional.ofNullable(userMap.get(NumberUtil.parseLong(customerRespVO.getCreator()))).map(AdminUserRespDTO::getNickname).orElse(null));
  88 + AdminUserRespDTO ownerUser = userMap.get(customer.getOwnerUserId());
  89 + if (Objects.nonNull(ownerUser)) {
  90 + customerRespVO.setOwnerUserName(ownerUser.getNickname());
  91 + DeptRespDTO dept = deptApi.getDept(ownerUser.getDeptId());
  92 + if (Objects.nonNull(dept)) {
  93 + customerRespVO.setOwnerUserDept(dept.getName());
  94 + }
  95 + }
  96 + return success(customerRespVO);
68 } 97 }
69 98
70 @GetMapping("/page") 99 @GetMapping("/page")
@@ -72,7 +101,23 @@ public class CrmCustomerController { @@ -72,7 +101,23 @@ public class CrmCustomerController {
72 @PreAuthorize("@ss.hasPermission('crm:customer:query')") 101 @PreAuthorize("@ss.hasPermission('crm:customer:query')")
73 public CommonResult<PageResult<CrmCustomerRespVO>> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { 102 public CommonResult<PageResult<CrmCustomerRespVO>> getCustomerPage(@Valid CrmCustomerPageReqVO pageVO) {
74 PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(pageVO); 103 PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(pageVO);
75 - return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult)); 104 + PageResult<CrmCustomerRespVO> pageVo = CrmCustomerConvert.INSTANCE.convertPage(pageResult);
  105 + Set<Long> userSet = pageVo.getList().stream().flatMap(i -> Stream.of(NumberUtil.parseLong(i.getCreator()), i.getOwnerUserId())).collect(Collectors.toSet());
  106 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userSet);
  107 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(userMap.values().stream().map(AdminUserRespDTO::getDeptId).collect(Collectors.toSet()));
  108 + pageVo.getList().forEach(customerRespVO -> {
  109 + customerRespVO.setAreaName(AreaUtils.format(customerRespVO.getAreaId()));
  110 + customerRespVO.setCreatorName(Optional.ofNullable(userMap.get(NumberUtil.parseLong(customerRespVO.getCreator()))).map(AdminUserRespDTO::getNickname).orElse(null));
  111 + AdminUserRespDTO ownerUser = userMap.get(customerRespVO.getOwnerUserId());
  112 + if (Objects.nonNull(ownerUser)) {
  113 + customerRespVO.setOwnerUserName(ownerUser.getNickname());
  114 + DeptRespDTO dept = deptMap.get(ownerUser.getDeptId());
  115 + if (Objects.nonNull(dept)) {
  116 + customerRespVO.setOwnerUserDept(dept.getName());
  117 + }
  118 + }
  119 + });
  120 + return success(pageVo);
76 } 121 }
77 122
78 @GetMapping("/export-excel") 123 @GetMapping("/export-excel")
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java
@@ -68,7 +68,7 @@ public class CrmCustomerBaseVO { @@ -68,7 +68,7 @@ public class CrmCustomerBaseVO {
68 private String remark; 68 private String remark;
69 69
70 @Schema(description = "地区编号", example = "20158") 70 @Schema(description = "地区编号", example = "20158")
71 - private Long areaId; 71 + private Integer areaId;
72 72
73 @Schema(description = "详细地址", example = "北京市海淀区") 73 @Schema(description = "详细地址", example = "北京市海淀区")
74 private String detailAddress; 74 private String detailAddress;
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerCreateReqVO.java
@@ -5,12 +5,16 @@ import lombok.Data; @@ -5,12 +5,16 @@ import lombok.Data;
5 import lombok.EqualsAndHashCode; 5 import lombok.EqualsAndHashCode;
6 import lombok.ToString; 6 import lombok.ToString;
7 7
  8 +import javax.validation.constraints.NotNull;
  9 +
8 @Schema(description = "管理后台 - CRM 客户创建 Request VO") 10 @Schema(description = "管理后台 - CRM 客户创建 Request VO")
9 @Data 11 @Data
10 @EqualsAndHashCode(callSuper = true) 12 @EqualsAndHashCode(callSuper = true)
11 @ToString(callSuper = true) 13 @ToString(callSuper = true)
12 public class CrmCustomerCreateReqVO extends CrmCustomerBaseVO { 14 public class CrmCustomerCreateReqVO extends CrmCustomerBaseVO {
13 15
14 - // TODO @wanwan:负责人 16 + @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
  17 + @NotNull(message = "负责人不能为空")
  18 + private Long ownerUserId;
15 19
16 } 20 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerExcelVO.java
@@ -76,7 +76,7 @@ public class CrmCustomerExcelVO { @@ -76,7 +76,7 @@ public class CrmCustomerExcelVO {
76 private Long ownerUserId; 76 private Long ownerUserId;
77 77
78 @ExcelProperty("地区编号") 78 @ExcelProperty("地区编号")
79 - private Long areaId; 79 + private Integer areaId;
80 80
81 @ExcelProperty("详细地址") 81 @ExcelProperty("详细地址")
82 private String detailAddress; 82 private String detailAddress;
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java
@@ -18,5 +18,14 @@ public class CrmCustomerPageReqVO extends PageParam { @@ -18,5 +18,14 @@ public class CrmCustomerPageReqVO extends PageParam {
18 @Schema(description = "手机", example = "18000000000") 18 @Schema(description = "手机", example = "18000000000")
19 private String mobile; 19 private String mobile;
20 20
  21 + @Schema(description = "所属行业", example = "1")
  22 + private Integer industryId;
  23 +
  24 + @Schema(description = "客户等级", example = "1")
  25 + private Integer level;
  26 +
  27 + @Schema(description = "客户来源", example = "1")
  28 + private Integer source;
  29 +
21 // TODO @芋艿:场景; 30 // TODO @芋艿:场景;
22 } 31 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java
@@ -31,6 +31,15 @@ public class CrmCustomerRespVO extends CrmCustomerBaseVO { @@ -31,6 +31,15 @@ public class CrmCustomerRespVO extends CrmCustomerBaseVO {
31 @Schema(description = "负责人的用户编号", example = "25682") 31 @Schema(description = "负责人的用户编号", example = "25682")
32 private Long ownerUserId; 32 private Long ownerUserId;
33 33
  34 + @Schema(description = "负责人名字", example = "25682")
  35 + private String ownerUserName;
  36 +
  37 + @Schema(description = "负责人部门")
  38 + private String ownerUserDept;
  39 +
  40 + @Schema(description = "地区名称", example = "北京市")
  41 + private String areaName;
  42 +
34 @Schema(description = "最后跟进时间") 43 @Schema(description = "最后跟进时间")
35 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 44 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
36 private LocalDateTime contactLastTime; 45 private LocalDateTime contactLastTime;
@@ -38,4 +47,12 @@ public class CrmCustomerRespVO extends CrmCustomerBaseVO { @@ -38,4 +47,12 @@ public class CrmCustomerRespVO extends CrmCustomerBaseVO {
38 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 47 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
39 private LocalDateTime createTime; 48 private LocalDateTime createTime;
40 49
  50 + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
  51 + private LocalDateTime updateTime;
  52 +
  53 + @Schema(description = "创建人")
  54 + private String creator;
  55 +
  56 + @Schema(description = "创建人名字")
  57 + private String creatorName;
41 } 58 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java
@@ -97,9 +97,21 @@ public class CrmCustomerDO extends BaseDO { @@ -97,9 +97,21 @@ public class CrmCustomerDO extends BaseDO {
97 */ 97 */
98 private String remark; 98 private String remark;
99 /** 99 /**
  100 + * 负责人的用户编号
  101 + */
  102 + private Long ownerUserId;
  103 + /**
  104 + * 只读权限的用户编号数组
  105 + */
  106 + private String roUserIds;
  107 + /**
  108 + * 读写权限的用户编号数组
  109 + */
  110 + private String rwUserIds;
  111 + /**
100 * 地区编号 112 * 地区编号
101 */ 113 */
102 - private Long areaId; 114 + private Integer areaId;
103 /** 115 /**
104 * 详细地址 116 * 详细地址
105 */ 117 */
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
@@ -19,10 +19,12 @@ import java.util.List; @@ -19,10 +19,12 @@ import java.util.List;
19 public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> { 19 public interface CrmCustomerMapper extends BaseMapperX<CrmCustomerDO> {
20 20
21 default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO reqVO) { 21 default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO reqVO) {
22 - // TODO @Wanwan 填充负责人,所属部门字段;这个可以在 controller 填哈;  
23 return selectPage(reqVO, new LambdaQueryWrapperX<CrmCustomerDO>() 22 return selectPage(reqVO, new LambdaQueryWrapperX<CrmCustomerDO>()
24 .likeIfPresent(CrmCustomerDO::getName, reqVO.getName()) 23 .likeIfPresent(CrmCustomerDO::getName, reqVO.getName())
25 .eqIfPresent(CrmCustomerDO::getMobile, reqVO.getMobile()) 24 .eqIfPresent(CrmCustomerDO::getMobile, reqVO.getMobile())
  25 + .eqIfPresent(CrmCustomerDO::getIndustryId, reqVO.getIndustryId())
  26 + .eqIfPresent(CrmCustomerDO::getLevel, reqVO.getLevel())
  27 + .eqIfPresent(CrmCustomerDO::getSource, reqVO.getSource())
26 .orderByDesc(CrmCustomerDO::getId)); 28 .orderByDesc(CrmCustomerDO::getId));
27 } 29 }
28 30
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
@@ -47,14 +47,6 @@ public interface CrmCustomerService { @@ -47,14 +47,6 @@ public interface CrmCustomerService {
47 CrmCustomerDO getCustomer(Long id); 47 CrmCustomerDO getCustomer(Long id);
48 48
49 /** 49 /**
50 - * 获得客户列表  
51 - *  
52 - * @param ids 编号  
53 - * @return 客户列表  
54 - */  
55 - List<CrmCustomerDO> getCustomerList(Collection<Long> ids);  
56 -  
57 - /**  
58 * 获得客户分页 50 * 获得客户分页
59 * 51 *
60 * @param pageReqVO 分页查询 52 * @param pageReqVO 分页查询
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
@@ -37,8 +37,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -37,8 +37,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
37 @Resource 37 @Resource
38 private CrmCustomerMapper customerMapper; 38 private CrmCustomerMapper customerMapper;
39 @Resource 39 @Resource
40 - private DeptApi deptApi; // TODO @wanwan:拼接数据,可以放到 controller;所以这里的引入,可以考虑放到 controller 哈;  
41 - @Resource  
42 private CrmPermissionService crmPermissionService; 40 private CrmPermissionService crmPermissionService;
43 41
44 @Override 42 @Override
@@ -94,14 +92,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -94,14 +92,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
94 } 92 }
95 93
96 @Override 94 @Override
97 - public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) {  
98 - if (CollUtil.isEmpty(ids)) {  
99 - return ListUtil.empty();  
100 - }  
101 - return customerMapper.selectBatchIds(ids);  
102 - }  
103 -  
104 - @Override  
105 public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO) { 95 public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO) {
106 // TODO 芋艿:数据权限,是否可以查询到; 96 // TODO 芋艿:数据权限,是否可以查询到;
107 return customerMapper.selectPage(pageReqVO); 97 return customerMapper.selectPage(pageReqVO);
@@ -112,8 +102,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -112,8 +102,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
112 return customerMapper.selectList(exportReqVO); 102 return customerMapper.selectList(exportReqVO);
113 } 103 }
114 104
115 - // TODO wanwan:service 接口已经注释,实现类就不需要了。  
116 -  
117 /** 105 /**
118 * 校验客户是否存在 106 * 校验客户是否存在
119 * 107 *