Commit 66a34a6d9022d12c820bbcdd8ca611213b85bb2f

Authored by YunaiV
1 parent 4b41c3c6

✨ CRM:完善联系人的列表

yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java
... ... @@ -2,24 +2,24 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.lang.Assert;
5   -import cn.hutool.core.util.NumberUtil;
6 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
7 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
8 8 import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
9 9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 10 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  11 +import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
11 12 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
12 13 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
13   -import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert;
14 14 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
15 15 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
16   -import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants;
17 16 import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService;
18 17 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
19 18 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
  19 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  20 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
20 21 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
21 22 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
22   -import com.google.common.collect.Lists;
23 23 import io.swagger.v3.oas.annotations.Operation;
24 24 import io.swagger.v3.oas.annotations.Parameter;
25 25 import io.swagger.v3.oas.annotations.tags.Tag;
... ... @@ -37,12 +37,13 @@ import java.util.List;
37 37 import java.util.Map;
38 38 import java.util.stream.Stream;
39 39  
40   -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
41 40 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
42 41 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
43 42 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
  43 +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
44 44 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
45 45 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  46 +import static java.util.Collections.singletonList;
46 47  
47 48 @Tag(name = "管理后台 - CRM 联系人")
48 49 @RestController
... ... @@ -60,6 +61,8 @@ public class CrmContactController {
60 61  
61 62 @Resource
62 63 private AdminUserApi adminUserApi;
  64 + @Resource
  65 + private DeptApi deptApi;
63 66  
64 67 @PostMapping("/create")
65 68 @Operation(summary = "创建联系人")
... ... @@ -92,19 +95,14 @@ public class CrmContactController {
92 95 @PreAuthorize("@ss.hasPermission('crm:contact:query')")
93 96 public CommonResult<CrmContactRespVO> getContact(@RequestParam("id") Long id) {
94 97 CrmContactDO contact = contactService.getContact(id);
  98 + return success(buildContactDetail(contact));
  99 + }
  100 +
  101 + private CrmContactRespVO buildContactDetail(CrmContactDO contact) {
95 102 if (contact == null) {
96   - throw exception(ErrorCodeConstants.CONTACT_NOT_EXISTS);
  103 + return null;
97 104 }
98   - // 1. 获取用户名
99   - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(CollUtil.removeNull(Lists.newArrayList(
100   - NumberUtil.parseLong(contact.getCreator()), contact.getOwnerUserId())));
101   - // 2. 获取客户信息
102   - List<CrmCustomerDO> customerList = customerService.getCustomerList(
103   - Collections.singletonList(contact.getCustomerId()));
104   - // 3. 直属上级
105   - List<CrmContactDO> parentContactList = contactService.getContactListByIds(
106   - Collections.singletonList(contact.getParentId()), getLoginUserId());
107   - return success(CrmContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList));
  105 + return buildContactDetailList(singletonList(contact)).get(0);
108 106 }
109 107  
110 108 @GetMapping("/list-by-ids")
... ... @@ -112,7 +110,8 @@ public class CrmContactController {
112 110 @Parameter(name = "ids", description = "编号", required = true, example = "[1024]")
113 111 @PreAuthorize("@ss.hasPermission('crm:contact:query')")
114 112 public CommonResult<List<CrmContactRespVO>> getContactListByIds(@RequestParam("ids") List<Long> ids) {
115   - return success(BeanUtils.toBean(contactService.getContactListByIds(ids, getLoginUserId()), CrmContactRespVO.class));
  113 + List<CrmContactDO> list = contactService.getContactListByIds(ids, getLoginUserId());
  114 + return success(BeanUtils.toBean(list, CrmContactRespVO.class));
116 115 }
117 116  
118 117 @GetMapping("/simple-all-list")
... ... @@ -129,7 +128,7 @@ public class CrmContactController {
129 128 @PreAuthorize("@ss.hasPermission('crm:contact:query')")
130 129 public CommonResult<PageResult<CrmContactRespVO>> getContactPage(@Valid CrmContactPageReqVO pageVO) {
131 130 PageResult<CrmContactDO> pageResult = contactService.getContactPage(pageVO, getLoginUserId());
132   - return success(buildContactDetailPage(pageResult));
  131 + return success(new PageResult<>(buildContactDetailList(pageResult.getList()), pageResult.getTotal()));
133 132 }
134 133  
135 134 @GetMapping("/page-by-customer")
... ... @@ -137,7 +136,7 @@ public class CrmContactController {
137 136 public CommonResult<PageResult<CrmContactRespVO>> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) {
138 137 Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空");
139 138 PageResult<CrmContactDO> pageResult = contactService.getContactPageByCustomerId(pageVO);
140   - return success(buildContactDetailPage(pageResult));
  139 + return success(new PageResult<>(buildContactDetailList(pageResult.getList()), pageResult.getTotal()));
141 140 }
142 141  
143 142 @GetMapping("/export-excel")
... ... @@ -147,32 +146,39 @@ public class CrmContactController {
147 146 public void exportContactExcel(@Valid CrmContactPageReqVO exportReqVO,
148 147 HttpServletResponse response) throws IOException {
149 148 exportReqVO.setPageNo(PAGE_SIZE_NONE);
150   - PageResult<CrmContactDO> pageResult = contactService.getContactPage(exportReqVO, getLoginUserId());
151   - ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class,
152   - buildContactDetailPage(pageResult).getList());
  149 + List<CrmContactDO> list = contactService.getContactPage(exportReqVO, getLoginUserId()).getList();
  150 + ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class, buildContactDetailList(list));
153 151 }
154 152  
155   - /**
156   - * 构建详细的联系人分页结果
157   - *
158   - * @param pageResult 简单的联系人分页结果
159   - * @return 详细的联系人分页结果
160   - */
161   - private PageResult<CrmContactRespVO> buildContactDetailPage(PageResult<CrmContactDO> pageResult) {
162   - List<CrmContactDO> contactList = pageResult.getList();
  153 + private List<CrmContactRespVO> buildContactDetailList(List<CrmContactDO> contactList) {
163 154 if (CollUtil.isEmpty(contactList)) {
164   - return PageResult.empty(pageResult.getTotal());
  155 + return Collections.emptyList();
165 156 }
166   - // 1. 获取客户列表
167   - List<CrmCustomerDO> crmCustomerDOList = customerService.getCustomerList(
  157 + // 1.1 获取客户列表
  158 + Map<Long, CrmCustomerDO> customerMap = customerService.getCustomerMap(
168 159 convertSet(contactList, CrmContactDO::getCustomerId));
169   - // 2. 获取创建人、负责人列表
  160 + // 1.2 获取创建人、负责人列表
170 161 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList,
171 162 contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
172   - // 3. 直属上级
173   - List<CrmContactDO> parentContactList = contactService.getContactListByIds(
174   - convertSet(contactList, CrmContactDO::getParentId), getLoginUserId());
175   - return CrmContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList);
  163 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
  164 + // 1.3 直属上级 Map
  165 + Map<Long, CrmContactDO> parentContactMap = contactService.getContactMap(
  166 + convertSet(contactList, CrmContactDO::getParentId));
  167 + // 2. 转换成 VO
  168 + return BeanUtils.toBean(contactList, CrmContactRespVO.class, contactVO -> {
  169 + contactVO.setAreaName(AreaUtils.format(contactVO.getAreaId()));
  170 + // 2.1 设置客户名称
  171 + MapUtils.findAndThen(customerMap, contactVO.getCustomerId(), customer -> contactVO.setCustomerName(customer.getName()));
  172 + // 2.2 设置创建人、负责人名称
  173 + MapUtils.findAndThen(userMap, NumberUtils.parseLong(contactVO.getCreator()),
  174 + user -> contactVO.setCreatorName(user.getNickname()));
  175 + MapUtils.findAndThen(userMap, contactVO.getOwnerUserId(), user -> {
  176 + contactVO.setOwnerUserName(user.getNickname());
  177 + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> contactVO.setOwnerUserDeptName(dept.getName()));
  178 + });
  179 + // 2.3 设置直属上级名称
  180 + findAndThen(parentContactMap, contactVO.getParentId(), contact -> contactVO.setParentName(contact.getName()));
  181 + });
176 182 }
177 183  
178 184 @PutMapping("/transfer")
... ... @@ -183,7 +189,7 @@ public class CrmContactController {
183 189 return success(true);
184 190 }
185 191  
186   - // ================== 关联/取关联系人 ===================
  192 + // ================== 关联/取关商机 ===================
187 193  
188 194 @PostMapping("/create-business-list")
189 195 @Operation(summary = "创建联系人与商机的关联")
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java
... ... @@ -20,29 +20,36 @@ public class CrmContactRespVO {
20 20 @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
21 21 private Long id;
22 22  
23   - @Schema(description = "姓名", example = "芋艿")
24   - @ExcelProperty(value = "姓名", order = 1)
  23 + @Schema(description = "联系人姓名", example = "芋艿")
  24 + @ExcelProperty(value = "联系人姓名", order = 1)
25 25 private String name;
26 26  
27 27 @Schema(description = "客户编号", example = "10795")
28 28 private Long customerId;
  29 + @ExcelProperty(value = "客户名称", order = 2)
  30 + @Schema(description = "客户名字", example = "test")
  31 + private String customerName;
29 32  
30   - @Schema(description = "性别")
31   - @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3)
32   - @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
33   - private Integer sex;
  33 + @Schema(description = "最后跟进时间")
  34 + @ExcelProperty(value = "最后跟进时间", order = 6)
  35 + private LocalDateTime contactLastTime;
34 36  
35   - @Schema(description = "职位")
36   - @ExcelProperty(value = "职位", order = 3)
37   - private String post;
  37 + @Schema(description = "最后跟进内容")
  38 + @ExcelProperty(value = "最后跟进内容", order = 6)
  39 + private String contactLastContent;
38 40  
39   - @Schema(description = "是否关键决策人")
40   - @ExcelProperty(value = "是否关键决策人", converter = DictConvert.class, order = 3)
41   - @DictFormat(DictTypeConstants.BOOLEAN_STRING)
42   - private Boolean master;
  41 + @Schema(description = "下次联系时间")
  42 + @ExcelProperty(value = "下次联系时间", order = 6)
  43 + private LocalDateTime contactNextTime;
43 44  
44   - @Schema(description = "直属上级", example = "23457")
45   - private Long parentId;
  45 + @Schema(description = "负责人编号")
  46 + private Long ownerUserId;
  47 + @Schema(description = "负责人名字", example = "25682")
  48 + @ExcelProperty("负责人名字")
  49 + private String ownerUserName;
  50 + @Schema(description = "负责人部门")
  51 + @ExcelProperty("负责人部门")
  52 + private String ownerUserDeptName;
46 53  
47 54 @Schema(description = "手机号", example = "1387171766")
48 55 @ExcelProperty(value = "手机号", order = 4)
... ... @@ -52,6 +59,10 @@ public class CrmContactRespVO {
52 59 @ExcelProperty(value = "电话", order = 4)
53 60 private String telephone;
54 61  
  62 + @Schema(description = "电子邮箱", example = "1111@22.com")
  63 + @ExcelProperty(value = "邮箱", order = 4)
  64 + private String email;
  65 +
55 66 @Schema(description = "QQ", example = "197272662")
56 67 @ExcelProperty(value = "QQ", order = 4)
57 68 private Long qq;
... ... @@ -60,53 +71,52 @@ public class CrmContactRespVO {
60 71 @ExcelProperty(value = "微信", order = 4)
61 72 private String wechat;
62 73  
63   - @Schema(description = "电子邮箱", example = "1111@22.com")
64   - @ExcelProperty(value = "邮箱", order = 4)
65   - private String email;
66   -
67 74 @Schema(description = "地区编号", example = "20158")
68 75 private Integer areaId;
  76 + @Schema(description = "地区名", example = "上海上海市浦东新区")
  77 + @ExcelProperty(value = "地区", order = 5)
  78 + private String areaName;
69 79  
70 80 @Schema(description = "地址")
71 81 @ExcelProperty(value = "地址", order = 5)
72 82 private String detailAddress;
73 83  
74   - @Schema(description = "备注", example = "你说的对")
75   - @ExcelProperty(value = "备注", order = 6)
76   - private String remark;
  84 + @Schema(description = "性别")
  85 + @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3)
  86 + @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
  87 + private Integer sex;
77 88  
78   - @Schema(description = "负责人用户编号", example = "14334")
79   - private Long ownerUserId;
  89 + @Schema(description = "是否关键决策人")
  90 + @ExcelProperty(value = "是否关键决策人", converter = DictConvert.class, order = 3)
  91 + @DictFormat(DictTypeConstants.BOOLEAN_STRING)
  92 + private Boolean master;
80 93  
81   - @Schema(description = "最后跟进时间")
82   - @ExcelProperty(value = "最后跟进时间", order = 6)
83   - private LocalDateTime contactLastTime;
  94 + @Schema(description = "职位")
  95 + @ExcelProperty(value = "职位", order = 3)
  96 + private String post;
84 97  
85   - @Schema(description = "下次联系时间")
86   - @ExcelProperty(value = "下次联系时间", order = 6)
87   - private LocalDateTime contactNextTime;
  98 + @Schema(description = "直属上级", example = "23457")
  99 + private Long parentId;
  100 + @Schema(description = "直属上级名", example = "芋头")
  101 + @ExcelProperty(value = "直属上级", order = 4)
  102 + private String parentName;
  103 +
  104 + @Schema(description = "备注", example = "你说的对")
  105 + @ExcelProperty(value = "备注", order = 6)
  106 + private String remark;
88 107  
89 108 @Schema(description = "创建人", example = "25682")
90 109 private String creator;
91   -
92 110 @Schema(description = "创建人名字", example = "test")
93 111 @ExcelProperty(value = "创建人", order = 8)
94 112 private String creatorName;
95 113  
96   - @ExcelProperty(value = "客户名称", order = 2)
97   - @Schema(description = "客户名字", example = "test")
98   - private String customerName;
  114 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  115 + @ExcelProperty("创建时间")
  116 + private LocalDateTime createTime;
99 117  
100   - @Schema(description = "负责人", example = "test")
101   - @ExcelProperty(value = "负责人", order = 7)
102   - private String ownerUserName;
103   -
104   - @Schema(description = "直属上级名", example = "芋头")
105   - @ExcelProperty(value = "直属上级", order = 4)
106   - private String parentName;
107   -
108   - @Schema(description = "地区名", example = "上海上海市浦东新区")
109   - @ExcelProperty(value = "地区", order = 5)
110   - private String areaName;
  118 + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
  119 + @ExcelProperty("更新时间")
  120 + private LocalDateTime updateTime;
111 121  
112 122 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java
... ... @@ -13,7 +13,6 @@ import org.springframework.format.annotation.DateTimeFormat;
13 13 import java.time.LocalDateTime;
14 14  
15 15 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
16   -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
17 16  
18 17 @Schema(description = "管理后台 - CRM 联系人创建/更新 Request VO")
19 18 @Data
... ... @@ -31,21 +30,15 @@ public class CrmContactSaveReqVO {
31 30 @DiffLogField(name = "客户", function = CrmCustomerParseFunction.NAME)
32 31 private Long customerId;
33 32  
34   - @Schema(description = "性别")
35   - @DiffLogField(name = "性别", function = SysSexParseFunction.NAME)
36   - private Integer sex;
37   -
38   - @Schema(description = "职位")
39   - @DiffLogField(name = "职位")
40   - private String post;
41   -
42   - @Schema(description = "是否关键决策人")
43   - @DiffLogField(name = "关键决策人", function = SysBooleanParseFunction.NAME)
44   - private Boolean master;
  33 + @Schema(description = "下次联系时间")
  34 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
  35 + @DiffLogField(name = "下次联系时间")
  36 + private LocalDateTime contactNextTime;
45 37  
46   - @Schema(description = "直属上级", example = "23457")
47   - @DiffLogField(name = "直属上级", function = CrmContactParseFunction.NAME)
48   - private Long parentId;
  38 + @Schema(description = "负责人用户编号", example = "14334")
  39 + @NotNull(message = "负责人不能为空")
  40 + @DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME)
  41 + private Long ownerUserId;
49 42  
50 43 @Schema(description = "手机号", example = "1387171766")
51 44 @Mobile
... ... @@ -78,24 +71,25 @@ public class CrmContactSaveReqVO {
78 71 @DiffLogField(name = "地址")
79 72 private String detailAddress;
80 73  
81   - @Schema(description = "备注", example = "你说的对")
82   - @DiffLogField(name = "备注")
83   - private String remark;
  74 + @Schema(description = "性别")
  75 + @DiffLogField(name = "性别", function = SysSexParseFunction.NAME)
  76 + private Integer sex;
84 77  
85   - @Schema(description = "负责人用户编号", example = "14334")
86   - @NotNull(message = "负责人不能为空")
87   - @DiffLogField(name = "负责人", function = SysAdminUserParseFunction.NAME)
88   - private Long ownerUserId;
  78 + @Schema(description = "是否关键决策人")
  79 + @DiffLogField(name = "关键决策人", function = SysBooleanParseFunction.NAME)
  80 + private Boolean master;
  81 +
  82 + @Schema(description = "职位")
  83 + @DiffLogField(name = "职位")
  84 + private String post;
89 85  
90   - @Schema(description = "最后跟进时间")
91   - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
92   - @DiffLogField(name = "最后跟进时间")
93   - private LocalDateTime contactLastTime;
  86 + @Schema(description = "直属上级", example = "23457")
  87 + @DiffLogField(name = "直属上级", function = CrmContactParseFunction.NAME)
  88 + private Long parentId;
94 89  
95   - @Schema(description = "下次联系时间")
96   - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
97   - @DiffLogField(name = "下次联系时间")
98   - private LocalDateTime contactNextTime;
  90 + @Schema(description = "备注", example = "你说的对")
  91 + @DiffLogField(name = "备注")
  92 + private String remark;
99 93  
100 94 @Schema(description = "关联商机 ID", example = "122233")
101 95 private Long businessId; // 注意:该字段用于在【商机】详情界面「新建联系人」时,自动进行关联
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
... ... @@ -168,7 +168,7 @@ public class CrmContractController {
168 168 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(contractList,
169 169 contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId())));
170 170 // 3. 获取联系人
171   - Map<Long, CrmContactDO> contactMap = convertMap(contactService.getContactListByIds(convertSet(contractList,
  171 + Map<Long, CrmContactDO> contactMap = convertMap(contactService.getContactList(convertSet(contractList,
172 172 CrmContractDO::getContactId)), CrmContactDO::getId);
173 173 // 4. 获取商机
174 174 Map<Long, CrmBusinessDO> businessMap = convertMap(businessService.getBusinessList(convertSet(contractList,
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/CrmFollowUpRecordController.java
... ... @@ -75,7 +75,7 @@ public class CrmFollowUpRecordController {
75 75 public CommonResult<PageResult<CrmFollowUpRecordRespVO>> getFollowUpRecordPage(@Valid CrmFollowUpRecordPageReqVO pageReqVO) {
76 76 PageResult<CrmFollowUpRecordDO> pageResult = followUpRecordService.getFollowUpRecordPage(pageReqVO);
77 77 /// 拼接数据
78   - Map<Long, CrmContactDO> contactMap = convertMap(contactService.getContactListByIds(
  78 + Map<Long, CrmContactDO> contactMap = convertMap(contactService.getContactList(
79 79 convertSetByFlatMap(pageResult.getList(), item -> item.getContactIds().stream())), CrmContactDO::getId);
80 80 Map<Long, CrmBusinessDO> businessMap = convertMap(businessService.getBusinessList(
81 81 convertSetByFlatMap(pageResult.getList(), item -> item.getBusinessIds().stream())), CrmBusinessDO::getId);
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java
1 1 package cn.iocoder.yudao.module.crm.convert.contact;
2 2  
3   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 3 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
5   -import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6   -import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
7 4 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactRespVO;
8 5 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
9 6 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
10   -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
11 7 import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO;
12 8 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO;
13   -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
14 9 import org.mapstruct.Mapper;
15 10 import org.mapstruct.Mapping;
16 11 import org.mapstruct.factory.Mappers;
17 12  
18 13 import java.util.List;
19   -import java.util.Map;
20   -
21   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
22   -import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
23 14  
24 15 /**
25 16 * CRM 联系人 Convert
... ... @@ -31,42 +22,9 @@ public interface CrmContactConvert {
31 22  
32 23 CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class);
33 24  
34   - CrmContactRespVO convert(CrmContactDO bean);
35   -
36 25 @Mapping(target = "bizId", source = "reqVO.id")
37 26 CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId);
38 27  
39   - default PageResult<CrmContactRespVO> convertPage(PageResult<CrmContactDO> pageResult, Map<Long, AdminUserRespDTO> userMap,
40   - List<CrmCustomerDO> customerList, List<CrmContactDO> parentContactList) {
41   - PageResult<CrmContactRespVO> voPageResult = BeanUtils.toBean(pageResult, CrmContactRespVO.class);
42   - // 拼接关联字段
43   - Map<Long, CrmContactDO> parentContactMap = convertMap(parentContactList, CrmContactDO::getId);
44   - Map<Long, CrmCustomerDO> customerMap = convertMap(customerList, CrmCustomerDO::getId);
45   - voPageResult.getList().forEach(item -> {
46   - setUserInfo(item, userMap);
47   - findAndThen(customerMap, item.getCustomerId(), customer -> item.setCustomerName(customer.getName()));
48   - findAndThen(parentContactMap, item.getParentId(), contactDO -> item.setParentName(contactDO.getName()));
49   - });
50   - return voPageResult;
51   - }
52   -
53   - default CrmContactRespVO convert(CrmContactDO contactDO, Map<Long, AdminUserRespDTO> userMap,
54   - List<CrmCustomerDO> customerList, List<CrmContactDO> parentContactList) {
55   - CrmContactRespVO contactVO = convert(contactDO);
56   - setUserInfo(contactVO, userMap);
57   - Map<Long, CrmCustomerDO> customerMap = CollectionUtils.convertMap(customerList, CrmCustomerDO::getId);
58   - Map<Long, CrmContactDO> contactMap = CollectionUtils.convertMap(parentContactList, CrmContactDO::getId);
59   - findAndThen(customerMap, contactDO.getCustomerId(), customer -> contactVO.setCustomerName(customer.getName()));
60   - findAndThen(contactMap, contactDO.getParentId(), contact -> contactVO.setParentName(contact.getName()));
61   - return contactVO;
62   - }
63   -
64   - static void setUserInfo(CrmContactRespVO contactRespVO, Map<Long, AdminUserRespDTO> userMap) {
65   - contactRespVO.setAreaName(AreaUtils.format(contactRespVO.getAreaId()));
66   - findAndThen(userMap, contactRespVO.getOwnerUserId(), user -> contactRespVO.setOwnerUserName(user.getNickname()));
67   - findAndThen(userMap, Long.parseLong(contactRespVO.getCreator()), user -> contactRespVO.setCreatorName(user.getNickname()));
68   - }
69   -
70 28 @Mapping(target = "id", source = "reqBO.bizId")
71 29 CrmContactDO convert(CrmUpdateFollowUpReqBO reqBO);
72 30  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java
... ... @@ -30,52 +30,48 @@ public class CrmContactDO extends BaseDO {
30 30 @TableId
31 31 private Long id;
32 32 /**
  33 + * 联系人姓名
  34 + */
  35 + private String name;
  36 + /**
33 37 * 客户编号
34 38 *
35 39 * 关联 {@link CrmCustomerDO#getId()}
36 40 */
37 41 private Long customerId;
  42 +
38 43 /**
39   - * 手机号
  44 + * 最后跟进时间
40 45 */
41   - private String mobile;
  46 + private LocalDateTime contactLastTime;
42 47 /**
43   - * 电话
  48 + * 最后跟进内容
44 49 */
45   - private String telephone;
  50 + private String contactLastContent;
46 51 /**
47   - * 电子邮箱
  52 + * 下次联系时间
48 53 */
49   - private String email;
  54 + private LocalDateTime contactNextTime;
  55 +
50 56 /**
51   - * 所在地
  57 + * 负责人用户编号
52 58 *
53   - * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段
54   - */
55   - private Integer areaId;
56   - /**
57   - * 详细地址
58   - */
59   - private String detailAddress;
60   - /**
61   - * 备注
  59 + * 关联 AdminUserDO 的 id 字段
62 60 */
63   - private String remark;
  61 + private Long ownerUserId;
64 62  
65 63 /**
66   - * 直属上级
67   - *
68   - * 关联 {@link CrmContactDO#id}
  64 + * 手机号
69 65 */
70   - private Long parentId;
  66 + private String mobile;
71 67 /**
72   - * 姓名
  68 + * 电话
73 69 */
74   - private String name;
  70 + private String telephone;
75 71 /**
76   - * 职位
  72 + * 电子邮箱
77 73 */
78   - private String post;
  74 + private String email;
79 75 /**
80 76 * QQ
81 77 */
... ... @@ -85,6 +81,16 @@ public class CrmContactDO extends BaseDO {
85 81 */
86 82 private String wechat;
87 83 /**
  84 + * 所在地
  85 + *
  86 + * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段
  87 + */
  88 + private Integer areaId;
  89 + /**
  90 + * 详细地址
  91 + */
  92 + private String detailAddress;
  93 + /**
88 94 * 性别
89 95 *
90 96 * 枚举 {@link cn.iocoder.yudao.module.system.enums.common.SexEnum}
... ... @@ -95,23 +101,18 @@ public class CrmContactDO extends BaseDO {
95 101 */
96 102 private Boolean master;
97 103 /**
98   - * 负责人用户编号
99   - *
100   - * 关联 AdminUserDO 的 id 字段
101   - */
102   - private Long ownerUserId;
103   -
104   - /**
105   - * 最后跟进时间
  104 + * 职位
106 105 */
107   - private LocalDateTime contactLastTime;
  106 + private String post;
108 107 /**
109   - * 最后跟进内容
  108 + * 直属上级
  109 + *
  110 + * 关联 {@link CrmContactDO#id}
110 111 */
111   - private String contactLastContent;
  112 + private Long parentId;
112 113 /**
113   - * 下次联系时间
  114 + * 备注
114 115 */
115   - private LocalDateTime contactNextTime;
  116 + private String remark;
116 117  
117 118 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java
... ... @@ -63,11 +63,10 @@ public interface CrmContactMapper extends BaseMapperX&lt;CrmContactDO&gt; {
63 63 return selectJoinPage(pageReqVO, CrmContactDO.class, query);
64 64 }
65 65  
66   - default List<CrmContactDO> selectBatchIds(Collection<Long> ids, Long userId) {
  66 + default List<CrmContactDO> selectBatchIds(Collection<Long> ids, Long ownerUserId) {
67 67 MPJLambdaWrapperX<CrmContactDO> query = new MPJLambdaWrapperX<>();
68 68 // 拼接数据权限的查询条件
69   - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId);
70   - // 拼接自身的查询条件
  69 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, ownerUserId);
71 70 query.selectAll(CrmContactDO.class).in(CrmContactDO::getId, ids).orderByDesc(CrmContactDO::getId);
72 71 return selectJoinList(CrmContactDO.class, query);
73 72 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java
... ... @@ -11,6 +11,9 @@ import jakarta.validation.Valid;
11 11  
12 12 import java.util.Collection;
13 13 import java.util.List;
  14 +import java.util.Map;
  15 +
  16 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
14 17  
15 18 /**
16 19 * CRM 联系人 Service 接口
... ... @@ -88,7 +91,17 @@ public interface CrmContactService {
88 91 * @param ids 编号
89 92 * @return 联系人列表
90 93 */
91   - List<CrmContactDO> getContactListByIds(Collection<Long> ids);
  94 + List<CrmContactDO> getContactList(Collection<Long> ids);
  95 +
  96 + /**
  97 + * 获得联系人 Map
  98 + *
  99 + * @param ids 编号
  100 + * @return 联系人 Map
  101 + */
  102 + default Map<Long, CrmContactDO> getContactMap(Collection<Long> ids) {
  103 + return convertMap(getContactList(ids), CrmContactDO::getId);
  104 + }
92 105  
93 106 /**
94 107 * 获得联系人列表
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
... ... @@ -218,7 +218,7 @@ public class CrmContactServiceImpl implements CrmContactService {
218 218 }
219 219  
220 220 @Override
221   - public List<CrmContactDO> getContactListByIds(Collection<Long> ids) {
  221 + public List<CrmContactDO> getContactList(Collection<Long> ids) {
222 222 if (CollUtil.isEmpty(ids)) {
223 223 return ListUtil.empty();
224 224 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
... ... @@ -264,7 +264,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService {
264 264 .updateCustomerNames(new ArrayList<>()).failureCustomerNames(new LinkedHashMap<>()).build();
265 265 importCustomers.forEach(importCustomer -> {
266 266 // 校验,判断是否有不符合的原因
267   - // TODO @puhui999:可以用 ValidationUtils 做参数校验;可能要封装一个方法,返回 message;这样的话,就可以在 CrmCustomerImportExcelVO 写需要校验的参数啦;
268 267 try {
269 268 validateCustomerForCreate(importCustomer);
270 269 } catch (ServiceException ex) {
... ...