Commit 19d5a0c2aa085bf5703099d4d906e8f57c390abb

Authored by YunaiV
1 parent 450cd1ba

📖 CRM:code review crm 联系人新增操作日志

Showing 23 changed files with 162 additions and 186 deletions
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
... ... @@ -24,7 +24,8 @@ public interface ErrorCodeConstants {
24 24 // ========== 联系人管理 1-020-003-000 ==========
25 25 ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在");
26 26 ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode( 1_020_003_001, "联系人商机关联不存在");
27   - ErrorCode CONTACT_CONTRACT_LINK_EXISTS = new ErrorCode( 1_020_003_002, "联系人已关联合同,不能删除");
  27 + ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode( 1_020_003_002, "联系人已关联合同,不能删除");
  28 +
28 29 // ========== 回款 1-020-004-000 ==========
29 30 ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在");
30 31  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.business;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4   -import cn.hutool.core.lang.Assert;
5   -import cn.hutool.core.util.StrUtil;
6 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
7 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
8 6 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
... ... @@ -29,7 +27,6 @@ import org.springframework.web.bind.annotation.*;
29 27  
30 28 import java.io.IOException;
31 29 import java.util.List;
32   -import java.util.Optional;
33 30  
34 31 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
35 32 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
... ... @@ -99,7 +96,7 @@ public class CrmBusinessController {
99 96 @GetMapping("/page-by-customer")
100 97 @Operation(summary = "获得商机分页,基于指定客户")
101 98 public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) {
102   - if(pageReqVO.getCustomerId() == null){
  99 + if (pageReqVO.getCustomerId() == null) {
103 100 throw exception(CUSTOMER_NOT_EXISTS);
104 101 }
105 102 PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO);
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java
... ... @@ -43,8 +43,7 @@ import java.util.stream.Stream;
43 43 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
44 44 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
45 45 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
46   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
47   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  46 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
48 47 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
49 48 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
50 49 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT;
... ... @@ -61,14 +60,13 @@ public class CrmContactController {
61 60 @Resource
62 61 private CrmCustomerService customerService;
63 62 @Resource
  63 + private CrmContactBusinessService contactBusinessLinkService;
  64 +
  65 + @Resource
64 66 private AdminUserApi adminUserApi;
65 67 @Resource
66 68 private OperateLogApi operateLogApi;
67 69  
68   - @Resource
69   - private CrmContactBusinessService contactBusinessLinkService;
70   -
71   -
72 70 @PostMapping("/create")
73 71 @Operation(summary = "创建联系人")
74 72 @PreAuthorize("@ss.hasPermission('crm:contact:create')")
... ... @@ -116,10 +114,12 @@ public class CrmContactController {
116 114 }
117 115  
118 116 @GetMapping("/simple-all-list")
119   - @Operation(summary = "获得联系人列表")
  117 + @Operation(summary = "获得联系人的精简列表")
120 118 @PreAuthorize("@ss.hasPermission('crm:contact:query')")
121   - public CommonResult<List<CrmContactSimpleRespVO>> getSimpleContactList() {
122   - return success(contactService.simpleContactList());
  119 + public CommonResult<List<CrmContactRespVO>> getSimpleContactList() {
  120 + List<CrmContactDO> list = contactService.getContactList();
  121 + return success(convertList(list, contact -> // 只返回 id、name 字段
  122 + new CrmContactRespVO().setId(contact.getId()).setName(contact.getName())));
123 123 }
124 124  
125 125 @GetMapping("/page")
... ... @@ -149,6 +149,7 @@ public class CrmContactController {
149 149 ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class,
150 150 buildContactDetailPage(pageResult).getList());
151 151 }
  152 +
152 153 @GetMapping("/operate-log-page")
153 154 @Operation(summary = "获得客户操作日志")
154 155 @PreAuthorize("@ss.hasPermission('crm:customer:query')")
... ... @@ -159,6 +160,7 @@ public class CrmContactController {
159 160 reqVO.setBizId(bizId);
160 161 return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class)));
161 162 }
  163 +
162 164 /**
163 165 * 构建详细的联系人分页结果
164 166 *
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
2 2  
3   -import cn.iocoder.yudao.framework.common.validation.Mobile;
4   -import cn.iocoder.yudao.framework.common.validation.Telephone;
5 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
6 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
7 5 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
8 6 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
9 7 import com.alibaba.excel.annotation.ExcelProperty;
10   -import com.mzt.logapi.starter.annotation.DiffLogField;
11 8 import io.swagger.v3.oas.annotations.media.Schema;
12   -import jakarta.validation.constraints.Email;
13   -import jakarta.validation.constraints.NotNull;
14   -import lombok.*;
15   -import org.springframework.format.annotation.DateTimeFormat;
  9 +import lombok.Data;
  10 +import lombok.ToString;
16 11  
17 12 import java.time.LocalDateTime;
18 13  
19   -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
20   -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
21   -
22 14 @Schema(description = "管理后台 - CRM 联系人 Response VO")
23 15 @Data
24 16 @ToString(callSuper = true)
... ... @@ -28,16 +20,16 @@ public class CrmContactRespVO {
28 20 @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
29 21 private Long id;
30 22  
31   - @ExcelProperty(value = "姓名",order = 1)
32 23 @Schema(description = "姓名", example = "芋艿")
  24 + @ExcelProperty(value = "姓名", order = 1)
33 25 private String name;
34 26  
35 27 @Schema(description = "客户编号", example = "10795")
36 28 private Long customerId;
37 29  
  30 + @Schema(description = "性别")
38 31 @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3)
39 32 @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
40   - @Schema(description = "性别")
41 33 private Integer sex;
42 34  
43 35 @Schema(description = "职位")
... ... @@ -52,71 +44,69 @@ public class CrmContactRespVO {
52 44 @Schema(description = "直属上级", example = "23457")
53 45 private Long parentId;
54 46  
55   - @Schema(description = "手机号",example = "1387171766")
56   - @ExcelProperty(value = "手机号",order = 4)
  47 + @Schema(description = "手机号", example = "1387171766")
  48 + @ExcelProperty(value = "手机号", order = 4)
57 49 private String mobile;
58 50  
59   - @Schema(description = "电话",example = "021-0029922")
60   - @ExcelProperty(value = "电话",order = 4)
  51 + @Schema(description = "电话", example = "021-0029922")
  52 + @ExcelProperty(value = "电话", order = 4)
61 53 private String telephone;
62 54  
63   - @ExcelProperty(value = "QQ",order = 4)
64   - @Schema(description = "QQ",example = "197272662")
  55 + @Schema(description = "QQ", example = "197272662")
  56 + @ExcelProperty(value = "QQ", order = 4)
65 57 private Long qq;
66 58  
67   - @ExcelProperty(value = "微信",order = 4)
68   - @Schema(description = "微信",example = "zzz3883")
  59 + @Schema(description = "微信", example = "zzz3883")
  60 + @ExcelProperty(value = "微信", order = 4)
69 61 private String wechat;
70 62  
71   - @Schema(description = "电子邮箱",example = "1111@22.com")
72   - @ExcelProperty(value = "邮箱",order = 4)
  63 + @Schema(description = "电子邮箱", example = "1111@22.com")
  64 + @ExcelProperty(value = "邮箱", order = 4)
73 65 private String email;
74 66  
75 67 @Schema(description = "地区编号", example = "20158")
76 68 private Integer areaId;
77 69  
78   - @ExcelProperty(value = "地址",order = 5)
79 70 @Schema(description = "地址")
  71 + @ExcelProperty(value = "地址", order = 5)
80 72 private String detailAddress;
81 73  
82 74 @Schema(description = "备注", example = "你说的对")
83   - @ExcelProperty(value = "备注",order = 6)
  75 + @ExcelProperty(value = "备注", order = 6)
84 76 private String remark;
85 77  
86 78 @Schema(description = "负责人用户编号", example = "14334")
87   - @NotNull(message = "负责人不能为空")
88 79 private Long ownerUserId;
89 80  
90 81 @Schema(description = "最后跟进时间")
91   - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
92   - @ExcelProperty(value = "最后跟进时间",order = 6)
  82 + @ExcelProperty(value = "最后跟进时间", order = 6)
93 83 private LocalDateTime contactLastTime;
94 84  
95 85 @Schema(description = "下次联系时间")
96   - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
97   - @ExcelProperty(value = "下次联系时间",order = 6)
  86 + @ExcelProperty(value = "下次联系时间", order = 6)
98 87 private LocalDateTime contactNextTime;
99 88  
100 89 @Schema(description = "创建人", example = "25682")
101 90 private String creator;
102 91  
103 92 @Schema(description = "创建人名字", example = "test")
104   - @ExcelProperty(value = "创建人",order = 8)
  93 + @ExcelProperty(value = "创建人", order = 8)
105 94 private String creatorName;
106 95  
107   - @ExcelProperty(value = "客户名称",order = 2)
  96 + @ExcelProperty(value = "客户名称", order = 2)
108 97 @Schema(description = "客户名字", example = "test")
109 98 private String customerName;
110 99  
111 100 @Schema(description = "负责人", example = "test")
112   - @ExcelProperty(value = "负责人",order = 7)
  101 + @ExcelProperty(value = "负责人", order = 7)
113 102 private String ownerUserName;
114 103  
115   - @Schema(description = "直属上级名",example = "芋头")
116   - @ExcelProperty(value = "直属上级",order = 4)
  104 + @Schema(description = "直属上级名", example = "芋头")
  105 + @ExcelProperty(value = "直属上级", order = 4)
117 106 private String parentName;
118 107  
119   - @Schema(description = "地区名",example = "上海上海市浦东新区")
120   - @ExcelProperty(value = "地区",order = 5)
  108 + @Schema(description = "地区名", example = "上海上海市浦东新区")
  109 + @ExcelProperty(value = "地区", order = 5)
121 110 private String areaName;
  111 +
122 112 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java
... ... @@ -2,17 +2,12 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
2 2  
3 3 import cn.iocoder.yudao.framework.common.validation.Mobile;
4 4 import cn.iocoder.yudao.framework.common.validation.Telephone;
5   -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
6   -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
7   -import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
8   -import com.alibaba.excel.annotation.ExcelProperty;
  5 +import cn.iocoder.yudao.module.crm.framework.operatelog.core.*;
9 6 import com.mzt.logapi.starter.annotation.DiffLogField;
10 7 import io.swagger.v3.oas.annotations.media.Schema;
11 8 import jakarta.validation.constraints.Email;
12 9 import jakarta.validation.constraints.NotNull;
13 10 import lombok.Data;
14   -import lombok.EqualsAndHashCode;
15   -import lombok.ToString;
16 11 import org.springframework.format.annotation.DateTimeFormat;
17 12  
18 13 import java.time.LocalDateTime;
... ... @@ -22,10 +17,9 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
22 17  
23 18 @Schema(description = "管理后台 - CRM 联系人创建/更新 Request VO")
24 19 @Data
25   -@ToString(callSuper = true)
26 20 public class CrmContactSaveReqVO {
27 21  
28   - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
  22 + @Schema(description = "主键", example = "3167")
29 23 private Long id;
30 24  
31 25 @Schema(description = "姓名", example = "芋艿")
... ... @@ -34,12 +28,11 @@ public class CrmContactSaveReqVO {
34 28 private String name;
35 29  
36 30 @Schema(description = "客户编号", example = "10795")
37   - @DiffLogField(name = "姓名",function = "getCustomerById")
  31 + @DiffLogField(name = "姓名", function = CrmCustomerParseFunction.NAME)
38 32 private Long customerId;
39 33  
40   - @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
41 34 @Schema(description = "性别")
42   - @DiffLogField(name = "性别",function = "getSexById")
  35 + @DiffLogField(name = "性别", function = CrmSexParseFunction.NAME)
43 36 private Integer sex;
44 37  
45 38 @Schema(description = "职位")
... ... @@ -47,33 +40,32 @@ public class CrmContactSaveReqVO {
47 40 private String post;
48 41  
49 42 @Schema(description = "是否关键决策人")
50   - @DictFormat(DictTypeConstants.BOOLEAN_STRING)
51   - @DiffLogField(name = "关键决策人", function = "getBooleanById")
  43 + @DiffLogField(name = "关键决策人", function = CrmBooleanParseFunction.NAME)
52 44 private Boolean master;
53 45  
54 46 @Schema(description = "直属上级", example = "23457")
55   - @DiffLogField(name = "直属上级",function = "getContactById")
  47 + @DiffLogField(name = "直属上级", function = CrmContactParseFunction.NAME)
56 48 private Long parentId;
57 49  
58   - @Schema(description = "手机号",example = "1387171766")
  50 + @Schema(description = "手机号", example = "1387171766")
59 51 @Mobile
60 52 @DiffLogField(name = "手机号")
61 53 private String mobile;
62 54  
63   - @Schema(description = "电话",example = "021-0029922")
  55 + @Schema(description = "电话", example = "021-0029922")
64 56 @Telephone
65 57 @DiffLogField(name = "电话")
66 58 private String telephone;
67 59  
68   - @Schema(description = "QQ",example = "197272662")
  60 + @Schema(description = "QQ", example = "197272662")
69 61 @DiffLogField(name = "QQ")
70 62 private Long qq;
71 63  
72   - @Schema(description = "微信",example = "zzz3883")
  64 + @Schema(description = "微信", example = "zzz3883")
73 65 @DiffLogField(name = "微信")
74 66 private String wechat;
75 67  
76   - @Schema(description = "电子邮箱",example = "1111@22.com")
  68 + @Schema(description = "电子邮箱", example = "1111@22.com")
77 69 @DiffLogField(name = "邮箱")
78 70 @Email
79 71 private String email;
... ... @@ -92,7 +84,7 @@ public class CrmContactSaveReqVO {
92 84  
93 85 @Schema(description = "负责人用户编号", example = "14334")
94 86 @NotNull(message = "负责人不能为空")
95   - @DiffLogField(name = "负责人",function = "getUserById")
  87 + @DiffLogField(name = "负责人", function = CrmSysUserParseFunction.NAME)
96 88 private Long ownerUserId;
97 89  
98 90 @Schema(description = "最后跟进时间")
... ... @@ -105,6 +97,7 @@ public class CrmContactSaveReqVO {
105 97 @DiffLogField(name = "下次联系时间")
106 98 private LocalDateTime contactNextTime;
107 99  
108   - @Schema(description = "关联商机ID", example = "122233")
109   - private Long businessId;
  100 + @Schema(description = "关联商机 ID", example = "122233")
  101 + private Long businessId; // 注意:该字段用于在【商机】详情界面「新建联系人」时,自动进行关联
  102 +
110 103 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSimpleRespVO.java deleted
1   -package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
2   -
3   -import io.swagger.v3.oas.annotations.media.Schema;
4   -import lombok.Data;
5   -import lombok.ToString;
6   -
7   -@Schema(description = "管理后台 - CRM 联系人的精简 Response VO")
8   -@Data
9   -@ToString(callSuper = true)
10   -public class CrmContactSimpleRespVO {
11   -
12   - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
13   - private Long id;
14   -
15   - @Schema(description = "姓名", example = "芋艿")
16   - private String name;
17   -
18   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java
... ... @@ -5,6 +5,9 @@ import cn.iocoder.yudao.framework.common.validation.Mobile;
5 5 import cn.iocoder.yudao.framework.common.validation.Telephone;
6 6 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
7 7 import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum;
  8 +import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmIndustryParseFunction;
  9 +import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmLevelParseFunction;
  10 +import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmSourceParseFunction;
8 11 import com.mzt.logapi.starter.annotation.DiffLogField;
9 12 import io.swagger.v3.oas.annotations.media.Schema;
10 13 import jakarta.validation.constraints.Email;
... ... @@ -31,17 +34,17 @@ public class CrmCustomerBaseVO {
31 34 private String name;
32 35  
33 36 @Schema(description = "所属行业", example = "1")
34   - @DiffLogField(name = "所属行业", function = "getIndustryById")
  37 + @DiffLogField(name = "所属行业", function = CrmIndustryParseFunction.NAME)
35 38 @DictFormat(CRM_CUSTOMER_INDUSTRY)
36 39 private Integer industryId;
37 40  
38 41 @Schema(description = "客户等级", example = "2")
39   - @DiffLogField(name = "客户等级", function = "getLevel")
  42 + @DiffLogField(name = "客户等级", function = CrmLevelParseFunction.NAME)
40 43 @InEnum(CrmCustomerLevelEnum.class)
41 44 private Integer level;
42 45  
43 46 @Schema(description = "客户来源", example = "3")
44   - @DiffLogField(name = "客户来源", function = "getSource")
  47 + @DiffLogField(name = "客户来源", function = CrmSourceParseFunction.NAME)
45 48 private Integer source;
46 49  
47 50 @Schema(description = "手机", example = "18000000000")
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java
... ... @@ -29,8 +29,6 @@ public interface CrmContactConvert {
29 29  
30 30 CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class);
31 31  
32   - CrmContactDO convert(CrmContactSaveReqVO bean);
33   -
34 32 CrmContactRespVO convert(CrmContactDO bean);
35 33  
36 34 List<CrmContactRespVO> convertList(List<CrmContactDO> list);
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
... ... @@ -60,4 +60,8 @@ public interface CrmContractMapper extends BaseMapperX&lt;CrmContractDO&gt; {
60 60 return selectJoinList(CrmContractDO.class, mpjLambdaWrapperX);
61 61 }
62 62  
  63 + default Long selectCountByContactId(Long contactId) {
  64 + return selectCount(CrmContractDO::getContactId, contactId);
  65 + }
  66 +
63 67 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmBooleanParseFunction.java
... ... @@ -12,10 +12,12 @@ import org.springframework.stereotype.Component;
12 12 *
13 13 * @author HUIHUI
14 14 */
15   -@Slf4j
16 15 @Component
  16 +@Slf4j
17 17 public class CrmBooleanParseFunction implements IParseFunction {
18 18  
  19 + public static final String NAME = "getBooleanById";
  20 +
19 21 @Override
20 22 public boolean executeBefore() {
21 23 return true; // 先转换值后对比
... ... @@ -23,7 +25,7 @@ public class CrmBooleanParseFunction implements IParseFunction {
23 25  
24 26 @Override
25 27 public String functionName() {
26   - return "getBooleanById";
  28 + return NAME;
27 29 }
28 30  
29 31 @Override
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContactParseFunction.java
... ... @@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.crm.framework.operatelog.core;
3 3 import cn.hutool.core.util.StrUtil;
4 4 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
5 5 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
6   -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
7   -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
8 6 import com.mzt.logapi.service.IParseFunction;
9 7 import jakarta.annotation.Resource;
10 8 import lombok.extern.slf4j.Slf4j;
... ... @@ -15,10 +13,12 @@ import org.springframework.stereotype.Component;
15 13 *
16 14 * @author HUIHUI
17 15 */
18   -@Slf4j
19 16 @Component
  17 +@Slf4j
20 18 public class CrmContactParseFunction implements IParseFunction {
21 19  
  20 + public static final String NAME = "getContactById";
  21 +
22 22 @Resource
23 23 private CrmContactService contactService;
24 24  
... ... @@ -29,7 +29,7 @@ public class CrmContactParseFunction implements IParseFunction {
29 29  
30 30 @Override
31 31 public String functionName() {
32   - return "getContactById";
  32 + return NAME;
33 33 }
34 34  
35 35 @Override
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerParseFunction.java
1 1 package cn.iocoder.yudao.module.crm.framework.operatelog.core;
2 2  
3 3 import cn.hutool.core.util.StrUtil;
4   -import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
5 4 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
6 5 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
7   -import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
8 6 import com.mzt.logapi.service.IParseFunction;
9 7 import jakarta.annotation.Resource;
10 8 import lombok.extern.slf4j.Slf4j;
11 9 import org.springframework.stereotype.Component;
12 10  
13   -import java.util.Optional;
14   -
15 11 /**
16 12 * 行业的 {@link IParseFunction} 实现类
17 13 *
18 14 * @author HUIHUI
19 15 */
20   -@Slf4j
21 16 @Component
  17 +@Slf4j
22 18 public class CrmCustomerParseFunction implements IParseFunction {
23 19  
  20 + public static final String NAME = "getCustomerById";
  21 +
24 22 @Resource
25 23 private CrmCustomerService customerService;
  24 +
26 25 @Override
27 26 public boolean executeBefore() {
28 27 return true; // 先转换值后对比
... ... @@ -30,7 +29,7 @@ public class CrmCustomerParseFunction implements IParseFunction {
30 29  
31 30 @Override
32 31 public String functionName() {
33   - return "getCustomerById";
  32 + return NAME;
34 33 }
35 34  
36 35 @Override
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmIndustryParseFunction.java
... ... @@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_I
13 13 *
14 14 * @author HUIHUI
15 15 */
16   -@Slf4j
17 16 @Component
  17 +@Slf4j
18 18 public class CrmIndustryParseFunction implements IParseFunction {
19 19  
  20 + public static final String NAME = "getIndustryById";
  21 +
20 22 @Override
21 23 public boolean executeBefore() {
22 24 return true; // 先转换值后对比
... ... @@ -24,7 +26,7 @@ public class CrmIndustryParseFunction implements IParseFunction {
24 26  
25 27 @Override
26 28 public String functionName() {
27   - return "getIndustryById";
  29 + return NAME;
28 30 }
29 31  
30 32 @Override
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmLevelParseFunction.java
... ... @@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_L
13 13 *
14 14 * @author HUIHUI
15 15 */
16   -@Slf4j
17 16 @Component
  17 +@Slf4j
18 18 public class CrmLevelParseFunction implements IParseFunction {
19 19  
  20 + public static final String NAME = "getLevel";
  21 +
20 22 @Override
21 23 public boolean executeBefore() {
22 24 return true; // 先转换值后对比
... ... @@ -24,7 +26,7 @@ public class CrmLevelParseFunction implements IParseFunction {
24 26  
25 27 @Override
26 28 public String functionName() {
27   - return "getLevel";
  29 + return NAME;
28 30 }
29 31  
30 32 @Override
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSexParseFunction.java
... ... @@ -7,17 +7,17 @@ import com.mzt.logapi.service.IParseFunction;
7 7 import lombok.extern.slf4j.Slf4j;
8 8 import org.springframework.stereotype.Component;
9 9  
10   -import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY;
11   -
12 10 /**
13 11 * 行业的 {@link IParseFunction} 实现类
14 12 *
15 13 * @author HUIHUI
16 14 */
17   -@Slf4j
18 15 @Component
  16 +@Slf4j
19 17 public class CrmSexParseFunction implements IParseFunction {
20 18  
  19 + public static final String NAME = "getSexById";
  20 +
21 21 @Override
22 22 public boolean executeBefore() {
23 23 return true; // 先转换值后对比
... ... @@ -25,7 +25,7 @@ public class CrmSexParseFunction implements IParseFunction {
25 25  
26 26 @Override
27 27 public String functionName() {
28   - return "getSexById";
  28 + return NAME;
29 29 }
30 30  
31 31 @Override
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSourceParseFunction.java
... ... @@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_S
13 13 *
14 14 * @author HUIHUI
15 15 */
16   -@Slf4j
17 16 @Component
  17 +@Slf4j
18 18 public class CrmSourceParseFunction implements IParseFunction {
19 19  
  20 + public static final String NAME = "getSource";
  21 +
20 22 @Override
21 23 public boolean executeBefore() {
22 24 return true; // 先转换值后对比
... ... @@ -24,7 +26,7 @@ public class CrmSourceParseFunction implements IParseFunction {
24 26  
25 27 @Override
26 28 public String functionName() {
27   - return "getSource";
  29 + return NAME;
28 30 }
29 31  
30 32 @Override
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSysUserParseFunction.java
1 1 package cn.iocoder.yudao.module.crm.framework.operatelog.core;
2 2  
3 3 import cn.hutool.core.util.StrUtil;
4   -import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
5 4 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
6 5 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
7   -import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
8 6 import com.mzt.logapi.service.IParseFunction;
9 7 import jakarta.annotation.Resource;
10 8 import lombok.extern.slf4j.Slf4j;
... ... @@ -15,10 +13,12 @@ import org.springframework.stereotype.Component;
15 13 *
16 14 * @author HUIHUI
17 15 */
18   -@Slf4j
19 16 @Component
  17 +@Slf4j
20 18 public class CrmSysUserParseFunction implements IParseFunction {
21 19  
  20 + public static final String NAME = "getUserById";
  21 +
22 22 @Resource
23 23 private AdminUserApi adminUserApi;
24 24  
... ... @@ -29,7 +29,7 @@ public class CrmSysUserParseFunction implements IParseFunction {
29 29  
30 30 @Override
31 31 public String functionName() {
32   - return "getUserById";
  32 + return NAME;
33 33 }
34 34  
35 35 @Override
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java
... ... @@ -28,6 +28,13 @@ public interface CrmContactBusinessService {
28 28 void deleteContactBusinessList(@Valid CrmContactBusinessReqVO deleteReqVO);
29 29  
30 30 /**
  31 + * 删除联系人与商机的关联,基于联系人编号
  32 + *
  33 + * @param contactId 联系人编号
  34 + */
  35 + void deleteContactBusinessByContactId(Long contactId);
  36 +
  37 + /**
31 38 * 获得联系人与商机的关联列表,基于联系人编号
32 39 *
33 40 * @param contactId 联系人编号
... ... @@ -35,7 +42,4 @@ public interface CrmContactBusinessService {
35 42 */
36 43 List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId);
37 44  
38   -
39   - void deleteContactBusinessByContactId(Long contactId);
40   -
41 45 }
42 46 \ No newline at end of file
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java
... ... @@ -76,13 +76,13 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
76 76 }
77 77  
78 78 @Override
79   - public List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId) {
80   - return contactBusinessMapper.selectListByContactId(contactId);
  79 + public void deleteContactBusinessByContactId(Long contactId) {
  80 + contactBusinessMapper.delete(CrmContactBusinessDO::getContactId,contactId);
81 81 }
82 82  
83 83 @Override
84   - public void deleteContactBusinessByContactId(Long contactId) {
85   - contactBusinessMapper.delete(CrmContactBusinessDO::getContactId,contactId);
  84 + public List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId) {
  85 + return contactBusinessMapper.selectListByContactId(contactId);
86 86 }
87 87  
88 88 }
89 89 \ No newline at end of file
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java
... ... @@ -57,6 +57,13 @@ public interface CrmContactService {
57 57 List<CrmContactDO> getContactList(Collection<Long> ids, Long userId);
58 58  
59 59 /**
  60 + * 获得联系人列表
  61 + *
  62 + * @return 联系人列表
  63 + */
  64 + List<CrmContactDO> getContactList();
  65 +
  66 + /**
60 67 * 获得联系人分页
61 68 *
62 69 * 数据权限:基于 {@link CrmContactDO}
... ... @@ -85,10 +92,4 @@ public interface CrmContactService {
85 92 */
86 93 void transferContact(CrmContactTransferReqVO reqVO, Long userId);
87 94  
88   - /**
89   - * 获取联系人简单列表
90   - * @return 联系人
91   - */
92   - List<CrmContactSimpleRespVO> simpleContactList();
93   -
94 95 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
... ... @@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.crm.service.contact;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.collection.ListUtil;
5   -import cn.hutool.core.util.StrUtil;
6 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
8   -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
  7 +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO;
  8 +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
  9 +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO;
  10 +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
9 11 import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert;
10   -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
11 12 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
12   -import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
13 13 import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper;
14 14 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
15 15 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
... ... @@ -28,18 +28,14 @@ import org.springframework.stereotype.Service;
28 28 import org.springframework.transaction.annotation.Transactional;
29 29 import org.springframework.validation.annotation.Validated;
30 30  
31   -import java.util.Arrays;
32 31 import java.util.Collection;
33 32 import java.util.List;
34   -import java.util.Optional;
35 33  
36 34 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
37   -import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
38   -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
39 35 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
40 36 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT;
41   -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_DUPLICATE;
42 37 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
  38 +import static java.util.Collections.singletonList;
43 39  
44 40 /**
45 41 * CRM 联系人 Service 实现类
... ... @@ -52,46 +48,42 @@ public class CrmContactServiceImpl implements CrmContactService {
52 48  
53 49 @Resource
54 50 private CrmContactMapper contactMapper;
  51 +
55 52 @Resource
56 53 private CrmCustomerService customerService;
57 54 @Resource
58   - private CrmPermissionService crmPermissionService;
59   - @Resource
60   - private AdminUserApi adminUserApi;
  55 + private CrmPermissionService permissionService;
61 56 @Resource
62   - private CrmContractService crmContractService;
  57 + private CrmContractService contractService;
63 58 @Resource
64 59 private CrmContactBusinessService contactBusinessService;
65 60 @Resource
66 61 private CrmBusinessService businessService;
67 62  
  63 + @Resource
  64 + private AdminUserApi adminUserApi;
  65 +
68 66 @Override
69 67 @Transactional(rollbackFor = Exception.class)
70   - @LogRecord(type = CRM_CONTACT, subType = "创建联系人[{{#contactName}}]", bizNo = "{{#contactId}}", success = "创建了联系人")
  68 + @LogRecord(type = CRM_CONTACT, subType = "创建联系人", bizNo = "{{#contactId}}", success = "创建了联系人[{{#contactName}}]")
71 69 public Long createContact(CrmContactSaveReqVO createReqVO, Long userId) {
72 70 // 1. 校验
73 71 validateRelationDataExists(createReqVO);
74 72  
75 73 // 2. 插入联系人
76   - CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO);
77   - int contactId = contactMapper.insert(contact);
  74 + CrmContactDO contact = BeanUtils.toBean(createReqVO, CrmContactDO.class);
  75 + contactMapper.insert(contact);
78 76  
79 77 // 3. 创建数据权限
80   - crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
  78 + permissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
81 79 .setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()).setBizId(contact.getId())
82 80 .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
83 81  
84   - //4.若传businessId自动关联商机
85   - Optional.ofNullable(createReqVO.getBusinessId()).ifPresent(businessId -> {
86   - CrmBusinessDO crmBusinessDO = businessService.getBusiness(createReqVO.getBusinessId());
87   - if(crmBusinessDO == null){
88   - throw exception(BUSINESS_NOT_EXISTS);
89   - }
90   - CrmContactBusinessReqVO crmContactBusinessReqVO = new CrmContactBusinessReqVO();
91   - crmContactBusinessReqVO.setContactId(contact.getId());
92   - crmContactBusinessReqVO.setBusinessIds(List.of(businessId));
93   - contactBusinessService.createContactBusinessList(crmContactBusinessReqVO);
94   - });
  82 + // 4. 如果有关联商机,则需要创建关联
  83 + if (createReqVO.getBusinessId() != null) {
  84 + contactBusinessService.createContactBusinessList(new CrmContactBusinessReqVO()
  85 + .setContactId(contact.getId()).setBusinessIds(singletonList(createReqVO.getBusinessId())));
  86 + }
95 87  
96 88 // 5. 记录操作日志
97 89 LogRecordContext.putVariable("contactId", contact.getId());
... ... @@ -109,7 +101,7 @@ public class CrmContactServiceImpl implements CrmContactService {
109 101 validateRelationDataExists(updateReqVO);
110 102  
111 103 // 2. 更新联系人
112   - CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO);
  104 + CrmContactDO updateObj = BeanUtils.toBean(updateReqVO, CrmContactDO.class);
113 105 contactMapper.updateById(updateObj);
114 106  
115 107 // 3. 记录操作日志
... ... @@ -134,24 +126,29 @@ public class CrmContactServiceImpl implements CrmContactService {
134 126 if (saveReqVO.getParentId() != null && contactMapper.selectById(saveReqVO.getParentId()) == null) {
135 127 throw exception(CONTACT_NOT_EXISTS);
136 128 }
  129 + // 4. 如果有关联商机,则需要校验存在
  130 + if (saveReqVO.getBusinessId() != null && businessService.getBusiness(saveReqVO.getBusinessId()) == null) {
  131 + throw exception(BUSINESS_NOT_EXISTS);
  132 + }
137 133 }
138 134  
139 135 @Override
140 136 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
141 137 @Transactional(rollbackFor = Exception.class)
142 138 public void deleteContact(Long id) {
143   - //1. 校验存在
  139 + // 1.1 校验存在
144 140 validateContactExists(id);
145   - //2.校验是否关联合同
146   - CrmContractDO crmContractDO = crmContractService.getContractByContactId(id);
147   - if(crmContractDO != null){
148   - throw exception(CONTACT_CONTRACT_LINK_EXISTS);
  141 + // 1.2 校验是否关联合同
  142 + if (contractService.getContractCountByContactId(id) > 0) {
  143 + throw exception(CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS);
149 144 }
150   - //3.删除联系人
  145 +
  146 + // 2. 删除联系人
151 147 contactMapper.deleteById(id);
152   - //4.删除数据权限
153   - crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id);
154   - //5.删除商机关联
  148 +
  149 + // 4.1 删除数据权限
  150 + permissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id);
  151 + // 4.2 删除商机关联
155 152 contactBusinessService.deleteContactBusinessByContactId(id);
156 153 // TODO @puhui999:删除跟进记录
157 154 }
... ... @@ -179,6 +176,11 @@ public class CrmContactServiceImpl implements CrmContactService {
179 176 }
180 177  
181 178 @Override
  179 + public List<CrmContactDO> getContactList() {
  180 + return contactMapper.selectList();
  181 + }
  182 +
  183 + @Override
182 184 public PageResult<CrmContactDO> getContactPage(CrmContactPageReqVO pageReqVO, Long userId) {
183 185 return contactMapper.selectPage(pageReqVO, userId);
184 186 }
... ... @@ -197,7 +199,7 @@ public class CrmContactServiceImpl implements CrmContactService {
197 199 validateContactExists(reqVO.getId());
198 200  
199 201 // 2.1 数据权限转移
200   - crmPermissionService.transferPermission(
  202 + permissionService.transferPermission(
201 203 CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()));
202 204 // 2.2 设置新的负责人
203 205 contactMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
... ... @@ -205,12 +207,4 @@ public class CrmContactServiceImpl implements CrmContactService {
205 207 // 3. TODO 记录转移日志
206 208 }
207 209  
208   - @Override
209   - public List<CrmContactSimpleRespVO> simpleContactList() {
210   - CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO();
211   - pageReqVO.setPageSize(PAGE_SIZE_NONE);
212   - List<CrmContactDO> list =contactMapper.selectPage(pageReqVO, getLoginUserId()).getList();
213   - return BeanUtils.toBean(list, CrmContactSimpleRespVO.class);
214   - }
215   -
216 210 }
217 211 \ No newline at end of file
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
... ... @@ -88,10 +88,11 @@ public interface CrmContractService {
88 88 void transferContract(CrmContractTransferReqVO reqVO, Long userId);
89 89  
90 90 /**
91   - * 查询合同,基于联系人
  91 + * 查询属于某个联系人的合同数量
  92 + *
92 93 * @param contactId 联系人ID
93 94 * @return 合同
94 95 */
95   - CrmContractDO getContractByContactId(Long contactId);
  96 + Long getContractCountByContactId(Long contactId);
96 97  
97 98 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
... ... @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.crm.service.contract;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.collection.ListUtil;
5   -import cn.hutool.core.util.StrUtil;
6 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 6 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO;
8 7 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
... ... @@ -137,8 +136,8 @@ public class CrmContractServiceImpl implements CrmContractService {
137 136 }
138 137  
139 138 @Override
140   - public CrmContractDO getContractByContactId(Long contactId) {
141   - return contractMapper.selectOne(CrmContractDO::getContactId, contactId);
  139 + public Long getContractCountByContactId(Long contactId) {
  140 + return contractMapper.selectCountByContactId(contactId);
142 141 }
143 142  
144 143 // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒;
... ...