Commit 49bc70ed82eac0281d13f45017f45bd0b97fe194

Authored by YunaiV
1 parent 1bfb4060

📖 CRM:线索 clue 列表的完善

yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.clue;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
  7 +import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
5 8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 9 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
7 10 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
8 11 import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*;
9 12 import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
  13 +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
10 14 import cn.iocoder.yudao.module.crm.service.clue.CrmClueService;
  15 +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
  16 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  17 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  18 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  19 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
11 20 import io.swagger.v3.oas.annotations.Operation;
12 21 import io.swagger.v3.oas.annotations.Parameter;
13 22 import io.swagger.v3.oas.annotations.tags.Tag;
... ... @@ -19,10 +28,15 @@ import org.springframework.validation.annotation.Validated;
19 28 import org.springframework.web.bind.annotation.*;
20 29  
21 30 import java.io.IOException;
  31 +import java.util.Collections;
22 32 import java.util.List;
  33 +import java.util.Map;
  34 +import java.util.stream.Stream;
23 35  
24 36 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
25 37 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
  38 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
  39 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
26 40 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
27 41 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
28 42  
... ... @@ -34,6 +48,13 @@ public class CrmClueController {
34 48  
35 49 @Resource
36 50 private CrmClueService clueService;
  51 + @Resource
  52 + private CrmCustomerService customerService;
  53 +
  54 + @Resource
  55 + private AdminUserApi adminUserApi;
  56 + @Resource
  57 + private DeptApi deptApi;
37 58  
38 59 @PostMapping("/create")
39 60 @Operation(summary = "创建线索")
... ... @@ -73,7 +94,7 @@ public class CrmClueController {
73 94 @PreAuthorize("@ss.hasPermission('crm:clue:query')")
74 95 public CommonResult<PageResult<CrmClueRespVO>> getCluePage(@Valid CrmCluePageReqVO pageVO) {
75 96 PageResult<CrmClueDO> pageResult = clueService.getCluePage(pageVO, getLoginUserId());
76   - return success(BeanUtils.toBean(pageResult, CrmClueRespVO.class));
  97 + return success(new PageResult<>(buildClueDetailList(pageResult.getList()), pageResult.getTotal()));
77 98 }
78 99  
79 100 @GetMapping("/export-excel")
... ... @@ -84,8 +105,32 @@ public class CrmClueController {
84 105 pageReqVO.setPageSize(PAGE_SIZE_NONE);
85 106 List<CrmClueDO> list = clueService.getCluePage(pageReqVO, getLoginUserId()).getList();
86 107 // 导出 Excel
87   - List<CrmClueRespVO> datas = BeanUtils.toBean(list, CrmClueRespVO.class);
88   - ExcelUtils.write(response, "线索.xls", "数据", CrmClueRespVO.class, datas);
  108 + ExcelUtils.write(response, "线索.xls", "数据", CrmClueRespVO.class, buildClueDetailList(list));
  109 + }
  110 +
  111 + private List<CrmClueRespVO> buildClueDetailList(List<CrmClueDO> list) {
  112 + if (CollUtil.isEmpty(list)) {
  113 + return Collections.emptyList();
  114 + }
  115 + // 1.1 获取客户列表
  116 + Map<Long, CrmCustomerDO> customerMap = customerService.getCustomerMap(
  117 + convertSet(list, CrmClueDO::getCustomerId));
  118 + // 1.2 获取创建人、负责人列表
  119 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(list,
  120 + contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
  121 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
  122 + // 2. 转换成 VO
  123 + return BeanUtils.toBean(list, CrmClueRespVO.class, clueVO -> {
  124 + // 2.1 设置客户名称
  125 + MapUtils.findAndThen(customerMap, clueVO.getCustomerId(), customer -> clueVO.setCustomerName(customer.getName()));
  126 + // 2.2 设置创建人、负责人名称
  127 + MapUtils.findAndThen(userMap, NumberUtils.parseLong(clueVO.getCreator()),
  128 + user -> clueVO.setCreatorName(user.getNickname()));
  129 + MapUtils.findAndThen(userMap, clueVO.getOwnerUserId(), user -> {
  130 + clueVO.setOwnerUserName(user.getNickname());
  131 + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> clueVO.setOwnerUserDeptName(dept.getName()));
  132 + });
  133 + });
89 134 }
90 135  
91 136 @PutMapping("/transfer")
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java
... ... @@ -8,12 +8,9 @@ import com.alibaba.excel.annotation.ExcelProperty;
8 8 import io.swagger.v3.oas.annotations.media.Schema;
9 9 import lombok.Data;
10 10 import lombok.ToString;
11   -import org.springframework.format.annotation.DateTimeFormat;
12 11  
13 12 import java.time.LocalDateTime;
14 13  
15   -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
16   -
17 14 @Schema(description = "管理后台 - 线索 Response VO")
18 15 @Data
19 16 @ToString(callSuper = true)
... ... @@ -34,19 +31,25 @@ public class CrmClueRespVO {
34 31 private Boolean followUpStatus;
35 32  
36 33 @Schema(description = "最后跟进时间")
37   - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
38 34 @ExcelProperty("最后跟进时间")
39 35 private LocalDateTime contactLastTime;
40 36  
  37 + @Schema(description = "最后跟进内容", example = "吃饭、睡觉、打逗逗")
  38 + @ExcelProperty("最后跟进内容")
  39 + private String contactLastContent;
  40 +
41 41 @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00")
42   - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
43 42 @ExcelProperty("下次联系时间")
44 43 private LocalDateTime contactNextTime;
45 44  
46 45 @Schema(description = "负责人编号")
47   - @ExcelProperty("负责人的用户编号")
48   - // TODO 这里需要导出成负责人的名字
49 46 private Long ownerUserId;
  47 + @Schema(description = "负责人名字", example = "25682")
  48 + @ExcelProperty("负责人名字")
  49 + private String ownerUserName;
  50 + @Schema(description = "负责人部门")
  51 + @ExcelProperty("负责人部门")
  52 + private String ownerUserDeptName;
50 53  
51 54 @Schema(description = "转化状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
52 55 @ExcelProperty(value = "转化状态", converter = DictConvert.class)
... ... @@ -54,9 +57,10 @@ public class CrmClueRespVO {
54 57 private Boolean transformStatus;
55 58  
56 59 @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "520")
57   - // TODO 这里需要导出成客户名称
58   - @ExcelProperty("客户编号")
59 60 private Long customerId;
  61 + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "客户名称")
  62 + @ExcelProperty("客户名称")
  63 + private String customerName;
60 64  
61 65 @Schema(description = "手机号", example = "18000000000")
62 66 @ExcelProperty("手机号")
... ... @@ -109,8 +113,19 @@ public class CrmClueRespVO {
109 113 @ExcelProperty("备注")
110 114 private String remark;
111 115  
  116 + @Schema(description = "创建人", example = "1024")
  117 + @ExcelProperty("创建人")
  118 + private String creator;
  119 + @Schema(description = "创建人名字", example = "芋道源码")
  120 + @ExcelProperty("创建人名字")
  121 + private String creatorName;
  122 +
112 123 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
113 124 @ExcelProperty("创建时间")
114 125 private LocalDateTime createTime;
115 126  
  127 + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
  128 + @ExcelProperty("更新时间")
  129 + private LocalDateTime updateTime;
  130 +
116 131 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
... ... @@ -56,6 +56,7 @@ public class CrmCustomerController {
56 56 private CrmCustomerService customerService;
57 57 @Resource
58 58 private CrmCustomerPoolConfigService customerPoolConfigService;
  59 +
59 60 @Resource
60 61 private DeptApi deptApi;
61 62 @Resource
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java
... ... @@ -40,10 +40,14 @@ public class CrmClueDO extends BaseDO {
40 40 */
41 41 private Boolean followUpStatus;
42 42 /**
43   - * 最后跟进时间 TODO 添加跟进记录时更新该值
  43 + * 最后跟进时间
44 44 */
45 45 private LocalDateTime contactLastTime;
46 46 /**
  47 + * 最后跟进内容
  48 + */
  49 + private String contactLastContent;
  50 + /**
47 51 * 下次联系时间
48 52 */
49 53 private LocalDateTime contactNextTime;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
... ... @@ -35,6 +35,7 @@ import org.springframework.stereotype.Service;
35 35 import org.springframework.transaction.annotation.Transactional;
36 36 import org.springframework.validation.annotation.Validated;
37 37  
  38 +import java.time.LocalDateTime;
38 39 import java.util.*;
39 40  
40 41 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
... ... @@ -81,7 +82,8 @@ public class CrmClueServiceImpl implements CrmClueService {
81 82 }
82 83  
83 84 // 2. 插入
84   - CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class).setId(null);
  85 + CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class)
  86 + .setContactLastTime(LocalDateTime.now());
85 87 clueMapper.insert(clue);
86 88  
87 89 // 3. 创建数据权限
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
... ... @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR
6 6 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO;
7 7 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO;
8 8 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
  9 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO;
9 10 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
10 11 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
11 12 import jakarta.validation.Valid;
... ... @@ -127,13 +128,20 @@ public interface CrmContractService {
127 128 Long getContractCountByCustomerId(Long customerId);
128 129  
129 130 /**
130   - * 根据商机ID获取关联客户的合同数量
  131 + * 根据商机编号,获取关联客户的合同数量
131 132 *
132 133 * @param businessId 商机编号
133 134 * @return 数量
134 135 */
135 136 Long getContractCountByBusinessId(Long businessId);
136 137  
  138 + /**
  139 + * 根据合同编号,获得合同的产品列表
  140 + *
  141 + * @param contactId 合同编号
  142 + * @return 产品列表
  143 + */
  144 + List<CrmContractProductDO> getContractProductListByContractId(Long contactId);
137 145  
138 146 /**
139 147 * 获得待审核合同数量
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
... ... @@ -10,6 +10,9 @@ import jakarta.validation.Valid;
10 10  
11 11 import java.util.Collection;
12 12 import java.util.List;
  13 +import java.util.Map;
  14 +
  15 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
13 16  
14 17 /**
15 18 * 客户 Service 接口
... ... @@ -59,6 +62,16 @@ public interface CrmCustomerService {
59 62 List<CrmCustomerDO> getCustomerList(Collection<Long> ids);
60 63  
61 64 /**
  65 + * 获得客户 Map
  66 + *
  67 + * @param ids 客户编号数组
  68 + * @return 客户 Map
  69 + */
  70 + default Map<Long, CrmCustomerDO> getCustomerMap(Collection<Long> ids) {
  71 + return convertMap(getCustomerList(ids), CrmCustomerDO::getId);
  72 + }
  73 +
  74 + /**
62 75 * 获得客户分页
63 76 *
64 77 * @param pageReqVO 分页查询
... ...