Commit 44d828023cd5aa6bbc2cc2ccd494cc3cd7f4901e

Authored by zyna
1 parent a259e032

crm联系人新增操作日志

Showing 19 changed files with 457 additions and 112 deletions
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
... ... @@ -24,7 +24,7 @@ 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   -
  27 + ErrorCode CONTACT_CONTRACT_LINK_EXISTS = new ErrorCode( 1_020_003_002, "联系人已关联合同,不能删除");
28 28 // ========== 回款 1-020-004-000 ==========
29 29 ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在");
30 30  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.business;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.lang.Assert;
  5 +import cn.hutool.core.util.StrUtil;
5 6 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 8 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
... ... @@ -28,12 +29,15 @@ import org.springframework.web.bind.annotation.*;
28 29  
29 30 import java.io.IOException;
30 31 import java.util.List;
  32 +import java.util.Optional;
31 33  
  34 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
32 35 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
33 36 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
34 37 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
35 38 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
36 39 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  40 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS;
37 41  
38 42 @Tag(name = "管理后台 - 商机")
39 43 @RestController
... ... @@ -95,7 +99,9 @@ public class CrmBusinessController {
95 99 @GetMapping("/page-by-customer")
96 100 @Operation(summary = "获得商机分页,基于指定客户")
97 101 public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) {
98   - Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空");
  102 + if(pageReqVO.getCustomerId() == null){
  103 + throw exception(CUSTOMER_NOT_EXISTS);
  104 + }
99 105 PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO);
100 106 return success(buildBusinessDetailPageResult(pageResult));
101 107 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java
... ... @@ -17,6 +17,9 @@ import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants;
17 17 import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService;
18 18 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
19 19 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
  20 +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi;
  21 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO;
  22 +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO;
20 23 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
21 24 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
22 25 import com.google.common.collect.Lists;
... ... @@ -44,6 +47,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
44 47 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
45 48 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
46 49 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
  50 +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT;
47 51  
48 52 @Tag(name = "管理后台 - CRM 联系人")
49 53 @RestController
... ... @@ -58,22 +62,25 @@ public class CrmContactController {
58 62 private CrmCustomerService customerService;
59 63 @Resource
60 64 private AdminUserApi adminUserApi;
  65 + @Resource
  66 + private OperateLogApi operateLogApi;
61 67  
62 68 @Resource
63 69 private CrmContactBusinessService contactBusinessLinkService;
64 70  
65   - // TODO @zyna:CrmContactCreateReqVO、CrmContactUpdateReqVO、CrmContactRespVO 按照新的 VO 规范搞哈;可以参考 dept 模块
  71 +
66 72 @PostMapping("/create")
67 73 @Operation(summary = "创建联系人")
68 74 @PreAuthorize("@ss.hasPermission('crm:contact:create')")
69   - public CommonResult<Long> createContact(@Valid @RequestBody CrmContactCreateReqVO createReqVO) {
  75 + public CommonResult<Long> createContact(@Valid @RequestBody CrmContactSaveReqVO createReqVO) {
70 76 return success(contactService.createContact(createReqVO, getLoginUserId()));
71 77 }
72 78  
73 79 @PutMapping("/update")
74 80 @Operation(summary = "更新联系人")
  81 + @OperateLog(enable = false)
75 82 @PreAuthorize("@ss.hasPermission('crm:contact:update')")
76   - public CommonResult<Boolean> updateContact(@Valid @RequestBody CrmContactUpdateReqVO updateReqVO) {
  83 + public CommonResult<Boolean> updateContact(@Valid @RequestBody CrmContactSaveReqVO updateReqVO) {
77 84 contactService.updateContact(updateReqVO);
78 85 return success(true);
79 86 }
... ... @@ -112,11 +119,7 @@ public class CrmContactController {
112 119 @Operation(summary = "获得联系人列表")
113 120 @PreAuthorize("@ss.hasPermission('crm:contact:query')")
114 121 public CommonResult<List<CrmContactSimpleRespVO>> getSimpleContactList() {
115   - // TODO @zyna:建议 contactService 单独搞个 list 接口哈
116   - CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO();
117   - pageReqVO.setPageSize(PAGE_SIZE_NONE);
118   - List<CrmContactDO> list = contactService.getContactPage(pageReqVO, getLoginUserId()).getList();
119   - return success(BeanUtils.toBean(list, CrmContactSimpleRespVO.class));
  122 + return success(contactService.simpleContactList());
120 123 }
121 124  
122 125 @GetMapping("/page")
... ... @@ -146,7 +149,16 @@ public class CrmContactController {
146 149 ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class,
147 150 buildContactDetailPage(pageResult).getList());
148 151 }
149   -
  152 + @GetMapping("/operate-log-page")
  153 + @Operation(summary = "获得客户操作日志")
  154 + @PreAuthorize("@ss.hasPermission('crm:customer:query')")
  155 + public CommonResult<PageResult<OperateLogV2RespDTO>> getCustomerOperateLog(@RequestParam("bizId")Long bizId) {
  156 + OperateLogV2PageReqDTO reqVO = new OperateLogV2PageReqDTO();
  157 + reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页
  158 + reqVO.setBizType(CRM_CONTACT);
  159 + reqVO.setBizId(bizId);
  160 + return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class)));
  161 + }
150 162 /**
151 163 * 构建详细的联系人分页结果
152 164 *
... ... @@ -181,7 +193,7 @@ public class CrmContactController {
181 193 // ================== 关联/取关联系人 ===================
182 194  
183 195 @PostMapping("/create-business-list")
184   - @Operation(summary = "创建联系人与联系人的关联")
  196 + @Operation(summary = "创建联系人与商机的关联")
185 197 @PreAuthorize("@ss.hasPermission('crm:contact:create-business')")
186 198 public CommonResult<Boolean> createContactBusinessList(@Valid @RequestBody CrmContactBusinessReqVO createReqVO) {
187 199 contactBusinessLinkService.createContactBusinessList(createReqVO);
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactCreateReqVO.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.EqualsAndHashCode;
6   -import lombok.ToString;
7   -
8   -@Schema(description = "管理后台 - CRM 联系人创建 Request VO")
9   -@Data
10   -@EqualsAndHashCode(callSuper = true)
11   -@ToString(callSuper = true)
12   -public class CrmContactCreateReqVO extends CrmContactBaseVO {
13   -
14   -}
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 +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;
3 8 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
4 9 import com.alibaba.excel.annotation.ExcelProperty;
  10 +import com.mzt.logapi.starter.annotation.DiffLogField;
5 11 import io.swagger.v3.oas.annotations.media.Schema;
  12 +import jakarta.validation.constraints.Email;
  13 +import jakarta.validation.constraints.NotNull;
6 14 import lombok.*;
  15 +import org.springframework.format.annotation.DateTimeFormat;
  16 +
7 17 import java.time.LocalDateTime;
8 18  
  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 +
9 22 @Schema(description = "管理后台 - CRM 联系人 Response VO")
10 23 @Data
11   -@EqualsAndHashCode(callSuper = true)
12 24 @ToString(callSuper = true)
13 25 @ExcelIgnoreUnannotated
14   -public class CrmContactRespVO extends CrmContactBaseVO {
  26 +public class CrmContactRespVO {
15 27  
16 28 @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
17 29 private Long id;
18 30  
19   - @Schema(description = "创建时间")
20   - @ExcelProperty(value = "创建时间", order = 8)
21   - private LocalDateTime createTime;
  31 + @ExcelProperty(value = "姓名",order = 1)
  32 + @Schema(description = "姓名", example = "芋艿")
  33 + private String name;
  34 +
  35 + @Schema(description = "客户编号", example = "10795")
  36 + private Long customerId;
  37 +
  38 + @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3)
  39 + @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
  40 + @Schema(description = "性别")
  41 + private Integer sex;
  42 +
  43 + @Schema(description = "职位")
  44 + @ExcelProperty(value = "职位", order = 3)
  45 + private String post;
  46 +
  47 + @Schema(description = "是否关键决策人")
  48 + @ExcelProperty(value = "是否关键决策人", converter = DictConvert.class, order = 3)
  49 + @DictFormat(DictTypeConstants.BOOLEAN_STRING)
  50 + private Boolean master;
  51 +
  52 + @Schema(description = "直属上级", example = "23457")
  53 + private Long parentId;
  54 +
  55 + @Schema(description = "手机号",example = "1387171766")
  56 + @ExcelProperty(value = "手机号",order = 4)
  57 + private String mobile;
  58 +
  59 + @Schema(description = "电话",example = "021-0029922")
  60 + @ExcelProperty(value = "电话",order = 4)
  61 + private String telephone;
22 62  
23   - @Schema(description = "更新时间")
24   - @ExcelProperty(value = "更新时间", order = 8)
25   - private LocalDateTime updateTime;
  63 + @ExcelProperty(value = "QQ",order = 4)
  64 + @Schema(description = "QQ",example = "197272662")
  65 + private Long qq;
  66 +
  67 + @ExcelProperty(value = "微信",order = 4)
  68 + @Schema(description = "微信",example = "zzz3883")
  69 + private String wechat;
  70 +
  71 + @Schema(description = "电子邮箱",example = "1111@22.com")
  72 + @ExcelProperty(value = "邮箱",order = 4)
  73 + private String email;
  74 +
  75 + @Schema(description = "地区编号", example = "20158")
  76 + private Integer areaId;
  77 +
  78 + @ExcelProperty(value = "地址",order = 5)
  79 + @Schema(description = "地址")
  80 + private String detailAddress;
  81 +
  82 + @Schema(description = "备注", example = "你说的对")
  83 + @ExcelProperty(value = "备注",order = 6)
  84 + private String remark;
  85 +
  86 + @Schema(description = "负责人用户编号", example = "14334")
  87 + @NotNull(message = "负责人不能为空")
  88 + private Long ownerUserId;
  89 +
  90 + @Schema(description = "最后跟进时间")
  91 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  92 + @ExcelProperty(value = "最后跟进时间",order = 6)
  93 + private LocalDateTime contactLastTime;
  94 +
  95 + @Schema(description = "下次联系时间")
  96 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
  97 + @ExcelProperty(value = "下次联系时间",order = 6)
  98 + private LocalDateTime contactNextTime;
26 99  
27 100 @Schema(description = "创建人", example = "25682")
28 101 private String creator;
29 102  
30 103 @Schema(description = "创建人名字", example = "test")
31   - @ExcelProperty(value = "创建人", order = 8)
  104 + @ExcelProperty(value = "创建人",order = 8)
32 105 private String creatorName;
33 106  
34 107 @ExcelProperty(value = "客户名称",order = 2)
... ... @@ -36,15 +109,14 @@ public class CrmContactRespVO extends CrmContactBaseVO {
36 109 private String customerName;
37 110  
38 111 @Schema(description = "负责人", example = "test")
39   - @ExcelProperty(value = "负责人", order = 7)
  112 + @ExcelProperty(value = "负责人",order = 7)
40 113 private String ownerUserName;
41 114  
42   - @Schema(description = "直属上级名", example = "芋头")
43   - @ExcelProperty(value = "直属上级", order = 4)
  115 + @Schema(description = "直属上级名",example = "芋头")
  116 + @ExcelProperty(value = "直属上级",order = 4)
44 117 private String parentName;
45 118  
46   - @Schema(description = "地区名", example = "上海上海市浦东新区")
47   - @ExcelProperty(value = "地区", order = 5)
  119 + @Schema(description = "地区名",example = "上海上海市浦东新区")
  120 + @ExcelProperty(value = "地区",order = 5)
48 121 private String areaName;
49   -
50 122 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBaseVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java
... ... @@ -5,12 +5,14 @@ import cn.iocoder.yudao.framework.common.validation.Telephone;
5 5 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
6 6 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
7 7 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
8   -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
9 8 import com.alibaba.excel.annotation.ExcelProperty;
  9 +import com.mzt.logapi.starter.annotation.DiffLogField;
10 10 import io.swagger.v3.oas.annotations.media.Schema;
11 11 import jakarta.validation.constraints.Email;
12 12 import jakarta.validation.constraints.NotNull;
13 13 import lombok.Data;
  14 +import lombok.EqualsAndHashCode;
  15 +import lombok.ToString;
14 16 import org.springframework.format.annotation.DateTimeFormat;
15 17  
16 18 import java.time.LocalDateTime;
... ... @@ -18,86 +20,91 @@ import java.time.LocalDateTime;
18 20 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
19 21 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
20 22  
21   -// TODO zyna:要不按照新的,干掉这个 basevo,都放子类里
22   -/**
23   - * CRM 联系人 Base VO,提供给添加、修改、详细的子 VO 使用
24   - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
25   - */
  23 +@Schema(description = "管理后台 - CRM 联系人创建/更新 Request VO")
26 24 @Data
27   -@ExcelIgnoreUnannotated
28   -public class CrmContactBaseVO {
  25 +@ToString(callSuper = true)
  26 +public class CrmContactSaveReqVO {
  27 +
  28 + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
  29 + private Long id;
29 30  
30   - @ExcelProperty(value = "姓名",order = 1)
31 31 @Schema(description = "姓名", example = "芋艿")
32 32 @NotNull(message = "姓名不能为空")
  33 + @DiffLogField(name = "姓名")
33 34 private String name;
34 35  
35 36 @Schema(description = "客户编号", example = "10795")
  37 + @DiffLogField(name = "姓名",function = "getCustomerById")
36 38 private Long customerId;
37 39  
38   - @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3)
39 40 @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
40 41 @Schema(description = "性别")
  42 + @DiffLogField(name = "性别",function = "getSexById")
41 43 private Integer sex;
42 44  
43 45 @Schema(description = "职位")
44   - @ExcelProperty(value = "职位", order = 3)
  46 + @DiffLogField(name = "职位")
45 47 private String post;
46 48  
47 49 @Schema(description = "是否关键决策人")
48   - @ExcelProperty(value = "是否关键决策人", converter = DictConvert.class, order = 3)
49 50 @DictFormat(DictTypeConstants.BOOLEAN_STRING)
  51 + @DiffLogField(name = "关键决策人", function = "getBooleanById")
50 52 private Boolean master;
51 53  
52 54 @Schema(description = "直属上级", example = "23457")
  55 + @DiffLogField(name = "直属上级",function = "getContactById")
53 56 private Long parentId;
54 57  
55 58 @Schema(description = "手机号",example = "1387171766")
56 59 @Mobile
57   - @ExcelProperty(value = "手机号",order = 4)
  60 + @DiffLogField(name = "手机号")
58 61 private String mobile;
59 62  
60   - @Schema(description = "座机",example = "021-0029922")
  63 + @Schema(description = "电话",example = "021-0029922")
61 64 @Telephone
62   - @ExcelProperty(value = "座机",order = 4)
  65 + @DiffLogField(name = "电话")
63 66 private String telephone;
64 67  
65   - @ExcelProperty(value = "QQ",order = 4)
66 68 @Schema(description = "QQ",example = "197272662")
  69 + @DiffLogField(name = "QQ")
67 70 private Long qq;
68 71  
69   - @ExcelProperty(value = "微信",order = 4)
70 72 @Schema(description = "微信",example = "zzz3883")
  73 + @DiffLogField(name = "微信")
71 74 private String wechat;
72 75  
73 76 @Schema(description = "电子邮箱",example = "1111@22.com")
  77 + @DiffLogField(name = "邮箱")
74 78 @Email
75   - @ExcelProperty(value = "邮箱",order = 4)
76 79 private String email;
77 80  
78 81 @Schema(description = "地区编号", example = "20158")
  82 + @DiffLogField(name = "所在地", function = "getAreaById")
79 83 private Integer areaId;
80 84  
81   - @ExcelProperty(value = "地址",order = 5)
82 85 @Schema(description = "地址")
  86 + @DiffLogField(name = "地址")
83 87 private String detailAddress;
84 88  
85 89 @Schema(description = "备注", example = "你说的对")
86   - @ExcelProperty(value = "备注",order = 6)
  90 + @DiffLogField(name = "备注")
87 91 private String remark;
88 92  
89 93 @Schema(description = "负责人用户编号", example = "14334")
90 94 @NotNull(message = "负责人不能为空")
  95 + @DiffLogField(name = "负责人",function = "getUserById")
91 96 private Long ownerUserId;
92 97  
93 98 @Schema(description = "最后跟进时间")
94 99 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
95   - @ExcelProperty(value = "最后跟进时间",order = 6)
  100 + @DiffLogField(name = "最后跟进时间")
96 101 private LocalDateTime contactLastTime;
97 102  
98 103 @Schema(description = "下次联系时间")
99 104 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
100   - @ExcelProperty(value = "下次联系时间",order = 6)
  105 + @DiffLogField(name = "下次联系时间")
101 106 private LocalDateTime contactNextTime;
102 107  
  108 + @Schema(description = "关联商机ID", example = "122233")
  109 + private Long businessId;
103 110 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactUpdateReqVO.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.EqualsAndHashCode;
6   -import lombok.ToString;
7   -
8   -import jakarta.validation.constraints.NotNull;
9   -
10   -@Schema(description = "管理后台 - CRM 联系人更新 Request VO")
11   -@Data
12   -@EqualsAndHashCode(callSuper = true)
13   -@ToString(callSuper = true)
14   -public class CrmContactUpdateReqVO extends CrmContactBaseVO {
15   -
16   - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
17   - @NotNull(message = "主键不能为空")
18   - private Long id;
19   -
20   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java
... ... @@ -29,9 +29,7 @@ public interface CrmContactConvert {
29 29  
30 30 CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class);
31 31  
32   - CrmContactDO convert(CrmContactCreateReqVO bean);
33   -
34   - CrmContactDO convert(CrmContactUpdateReqVO bean);
  32 + CrmContactDO convert(CrmContactSaveReqVO bean);
35 33  
36 34 CrmContactRespVO convert(CrmContactDO bean);
37 35  
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmBooleanParseFunction.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.framework.operatelog.core;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
  5 +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
  6 +import com.mzt.logapi.service.IParseFunction;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +/**
  11 + * 行业的 {@link IParseFunction} 实现类
  12 + *
  13 + * @author HUIHUI
  14 + */
  15 +@Slf4j
  16 +@Component
  17 +public class CrmBooleanParseFunction implements IParseFunction {
  18 +
  19 + @Override
  20 + public boolean executeBefore() {
  21 + return true; // 先转换值后对比
  22 + }
  23 +
  24 + @Override
  25 + public String functionName() {
  26 + return "getBooleanById";
  27 + }
  28 +
  29 + @Override
  30 + public String apply(Object value) {
  31 + if (StrUtil.isEmptyIfStr(value)) {
  32 + return "";
  33 + }
  34 + return DictFrameworkUtils.getDictDataLabel(DictTypeConstants.BOOLEAN_STRING, value.toString());
  35 + }
  36 +
  37 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContactParseFunction.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.framework.operatelog.core;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
  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 +import com.mzt.logapi.service.IParseFunction;
  9 +import jakarta.annotation.Resource;
  10 +import lombok.extern.slf4j.Slf4j;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +/**
  14 + * 行业的 {@link IParseFunction} 实现类
  15 + *
  16 + * @author HUIHUI
  17 + */
  18 +@Slf4j
  19 +@Component
  20 +public class CrmContactParseFunction implements IParseFunction {
  21 +
  22 + @Resource
  23 + private CrmContactService contactService;
  24 +
  25 + @Override
  26 + public boolean executeBefore() {
  27 + return true; // 先转换值后对比
  28 + }
  29 +
  30 + @Override
  31 + public String functionName() {
  32 + return "getContactById";
  33 + }
  34 +
  35 + @Override
  36 + public String apply(Object value) {
  37 + if (StrUtil.isEmptyIfStr(value)) {
  38 + return "";
  39 + }
  40 + CrmContactDO contactDO = contactService.getContact(Long.parseLong(value.toString()));
  41 + return contactDO == null ? "" : contactDO.getName();
  42 + }
  43 +
  44 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerParseFunction.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.framework.operatelog.core;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
  5 +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
  6 +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
  7 +import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
  8 +import com.mzt.logapi.service.IParseFunction;
  9 +import jakarta.annotation.Resource;
  10 +import lombok.extern.slf4j.Slf4j;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +import java.util.Optional;
  14 +
  15 +/**
  16 + * 行业的 {@link IParseFunction} 实现类
  17 + *
  18 + * @author HUIHUI
  19 + */
  20 +@Slf4j
  21 +@Component
  22 +public class CrmCustomerParseFunction implements IParseFunction {
  23 +
  24 + @Resource
  25 + private CrmCustomerService customerService;
  26 + @Override
  27 + public boolean executeBefore() {
  28 + return true; // 先转换值后对比
  29 + }
  30 +
  31 + @Override
  32 + public String functionName() {
  33 + return "getCustomerById";
  34 + }
  35 +
  36 + @Override
  37 + public String apply(Object value) {
  38 + if (StrUtil.isEmptyIfStr(value)) {
  39 + return "";
  40 + }
  41 + CrmCustomerDO crmCustomerDO = customerService.getCustomer(Long.parseLong(value.toString()));
  42 + return crmCustomerDO == null ? "" : crmCustomerDO.getName();
  43 + }
  44 +
  45 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSexParseFunction.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.framework.operatelog.core;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
  5 +import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
  6 +import com.mzt.logapi.service.IParseFunction;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY;
  11 +
  12 +/**
  13 + * 行业的 {@link IParseFunction} 实现类
  14 + *
  15 + * @author HUIHUI
  16 + */
  17 +@Slf4j
  18 +@Component
  19 +public class CrmSexParseFunction implements IParseFunction {
  20 +
  21 + @Override
  22 + public boolean executeBefore() {
  23 + return true; // 先转换值后对比
  24 + }
  25 +
  26 + @Override
  27 + public String functionName() {
  28 + return "getSexById";
  29 + }
  30 +
  31 + @Override
  32 + public String apply(Object value) {
  33 + if (StrUtil.isEmptyIfStr(value)) {
  34 + return "";
  35 + }
  36 + return DictFrameworkUtils.getDictDataLabel(DictTypeConstants.USER_SEX, value.toString());
  37 + }
  38 +
  39 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSysUserParseFunction.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.framework.operatelog.core;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
  5 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  6 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  7 +import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
  8 +import com.mzt.logapi.service.IParseFunction;
  9 +import jakarta.annotation.Resource;
  10 +import lombok.extern.slf4j.Slf4j;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +/**
  14 + * 行业的 {@link IParseFunction} 实现类
  15 + *
  16 + * @author HUIHUI
  17 + */
  18 +@Slf4j
  19 +@Component
  20 +public class CrmSysUserParseFunction implements IParseFunction {
  21 +
  22 + @Resource
  23 + private AdminUserApi adminUserApi;
  24 +
  25 + @Override
  26 + public boolean executeBefore() {
  27 + return true; // 先转换值后对比
  28 + }
  29 +
  30 + @Override
  31 + public String functionName() {
  32 + return "getUserById";
  33 + }
  34 +
  35 + @Override
  36 + public String apply(Object value) {
  37 + if (StrUtil.isEmptyIfStr(value)) {
  38 + return "";
  39 + }
  40 + AdminUserRespDTO adminUserRespDTO = adminUserApi.getUser(Long.parseLong(value.toString()));
  41 + return adminUserRespDTO == null ? "" : adminUserRespDTO.getNickname();
  42 + }
  43 +
  44 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java
... ... @@ -35,4 +35,7 @@ public interface CrmContactBusinessService {
35 35 */
36 36 List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId);
37 37  
  38 +
  39 + void deleteContactBusinessByContactId(Long contactId);
  40 +
38 41 }
39 42 \ 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
... ... @@ -80,4 +80,9 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
80 80 return contactBusinessMapper.selectListByContactId(contactId);
81 81 }
82 82  
  83 + @Override
  84 + public void deleteContactBusinessByContactId(Long contactId) {
  85 + contactBusinessMapper.delete(CrmContactBusinessDO::getContactId,contactId);
  86 + }
  87 +
83 88 }
84 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
1 1 package cn.iocoder.yudao.module.crm.service.contact;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4   -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO;
5   -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
6   -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
7   -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
8 5 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
9 6 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
10 7 import jakarta.validation.Valid;
... ... @@ -26,14 +23,14 @@ public interface CrmContactService {
26 23 * @param userId 用户编号
27 24 * @return 编号
28 25 */
29   - Long createContact(@Valid CrmContactCreateReqVO createReqVO, Long userId);
  26 + Long createContact(@Valid CrmContactSaveReqVO createReqVO, Long userId);
30 27  
31 28 /**
32 29 * 更新联系人
33 30 *
34 31 * @param updateReqVO 更新信息
35 32 */
36   - void updateContact(@Valid CrmContactUpdateReqVO updateReqVO);
  33 + void updateContact(@Valid CrmContactSaveReqVO updateReqVO);
37 34  
38 35 /**
39 36 * 删除联系人
... ... @@ -88,4 +85,10 @@ public interface CrmContactService {
88 85 */
89 86 void transferContact(CrmContactTransferReqVO reqVO, Long userId);
90 87  
  88 + /**
  89 + * 获取联系人简单列表
  90 + * @return 联系人
  91 + */
  92 + List<CrmContactSimpleRespVO> simpleContactList();
  93 +
91 94 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
... ... @@ -2,29 +2,43 @@ 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;
5 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 8 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
7 9 import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert;
  10 +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
8 11 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
  12 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
9 13 import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper;
10 14 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
11 15 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
12 16 import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission;
  17 +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService;
  18 +import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
13 19 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
14 20 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
15 21 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
16 22 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  23 +import com.mzt.logapi.context.LogRecordContext;
  24 +import com.mzt.logapi.service.impl.DiffParseFunction;
  25 +import com.mzt.logapi.starter.annotation.LogRecord;
17 26 import jakarta.annotation.Resource;
18 27 import org.springframework.stereotype.Service;
19 28 import org.springframework.transaction.annotation.Transactional;
20 29 import org.springframework.validation.annotation.Validated;
21 30  
  31 +import java.util.Arrays;
22 32 import java.util.Collection;
23 33 import java.util.List;
  34 +import java.util.Optional;
24 35  
25 36 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
26   -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTACT_NOT_EXISTS;
27   -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS;
  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 +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
  40 +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT;
  41 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_DUPLICATE;
28 42 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
29 43  
30 44 /**
... ... @@ -38,45 +52,68 @@ public class CrmContactServiceImpl implements CrmContactService {
38 52  
39 53 @Resource
40 54 private CrmContactMapper contactMapper;
41   -
42 55 @Resource
43 56 private CrmCustomerService customerService;
44 57 @Resource
45 58 private CrmPermissionService crmPermissionService;
46 59 @Resource
47 60 private AdminUserApi adminUserApi;
  61 + @Resource
  62 + private CrmContractService crmContractService;
  63 + @Resource
  64 + private CrmContactBusinessService contactBusinessService;
  65 + @Resource
  66 + private CrmBusinessService businessService;
48 67  
49 68 @Override
50 69 @Transactional(rollbackFor = Exception.class)
51   - // TODO @zyna:增加操作日志,可以参考 CustomerService;内容是 新建了联系人【名字】
52   - public Long createContact(CrmContactCreateReqVO createReqVO, Long userId) {
  70 + @LogRecord(type = CRM_CONTACT, subType = "创建联系人[{{#contactName}}]", bizNo = "{{#contactId}}", success = "创建了联系人")
  71 + public Long createContact(CrmContactSaveReqVO createReqVO, Long userId) {
53 72 // 1. 校验
54 73 validateRelationDataExists(createReqVO);
55 74  
56 75 // 2. 插入联系人
57 76 CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO);
58   - contactMapper.insert(contact);
  77 + int contactId = contactMapper.insert(contact);
59 78  
60 79 // 3. 创建数据权限
61 80 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
62 81 .setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()).setBizId(contact.getId())
63 82 .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
64 83  
65   - // TODO @zyna:特殊逻辑:如果在【商机】详情那,点击【新增联系人】时,可以自动绑定商机
  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 + });
  95 +
  96 + // 5. 记录操作日志
  97 + LogRecordContext.putVariable("contactId", contact.getId());
  98 + LogRecordContext.putVariable("contactName", contact.getName());
66 99 return contact.getId();
67 100 }
68 101  
69 102 @Override
  103 + @Transactional(rollbackFor = Exception.class)
  104 + @LogRecord(type = CRM_CONTACT, subType = "更新联系人", bizNo = "{{#updateReqVO.id}}", success = "更新了联系人{_DIFF{#updateReqVO}}")
70 105 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE)
71   - // TODO @zyna:增加操作日志,可以参考 CustomerService;需要 diff 出字段
72   - public void updateContact(CrmContactUpdateReqVO updateReqVO) {
  106 + public void updateContact(CrmContactSaveReqVO updateReqVO) {
73 107 // 1. 校验存在
74   - validateContactExists(updateReqVO.getId());
  108 + CrmContactDO contactDO = validateContactExists(updateReqVO.getId());
75 109 validateRelationDataExists(updateReqVO);
76 110  
77 111 // 2. 更新联系人
78 112 CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO);
79 113 contactMapper.updateById(updateObj);
  114 +
  115 + // 3. 记录操作日志
  116 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(contactDO, CrmContactSaveReqVO.class));
80 117 }
81 118  
82 119 /**
... ... @@ -84,7 +121,7 @@ public class CrmContactServiceImpl implements CrmContactService {
84 121 *
85 122 * @param saveReqVO 新增/修改请求 VO
86 123 */
87   - private void validateRelationDataExists(CrmContactBaseVO saveReqVO) {
  124 + private void validateRelationDataExists(CrmContactSaveReqVO saveReqVO) {
88 125 // 1. 校验客户
89 126 if (saveReqVO.getCustomerId() != null && customerService.getCustomer(saveReqVO.getCustomerId()) == null) {
90 127 throw exception(CUSTOMER_NOT_EXISTS);
... ... @@ -101,24 +138,30 @@ public class CrmContactServiceImpl implements CrmContactService {
101 138  
102 139 @Override
103 140 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
  141 + @Transactional(rollbackFor = Exception.class)
104 142 public void deleteContact(Long id) {
105   - // 校验存在
  143 + //1. 校验存在
106 144 validateContactExists(id);
107   - // TODO @zyna:如果有关联的合同,不允许删除;Contract.contactId
108   -
109   - // 删除
  145 + //2.校验是否关联合同
  146 + CrmContractDO crmContractDO = crmContractService.getContractByContactId(id);
  147 + if(crmContractDO != null){
  148 + throw exception(CONTACT_CONTRACT_LINK_EXISTS);
  149 + }
  150 + //3.删除联系人
110 151 contactMapper.deleteById(id);
111   - // 删除数据权限
  152 + //4.删除数据权限
112 153 crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id);
113   - // TODO @zyna:删除商机联系人关联
114   -
  154 + //5.删除商机关联
  155 + contactBusinessService.deleteContactBusinessByContactId(id);
115 156 // TODO @puhui999:删除跟进记录
116 157 }
117 158  
118   - private void validateContactExists(Long id) {
119   - if (contactMapper.selectById(id) == null) {
  159 + private CrmContactDO validateContactExists(Long id) {
  160 + CrmContactDO contactDO = contactMapper.selectById(id);
  161 + if (contactDO == null) {
120 162 throw exception(CONTACT_NOT_EXISTS);
121 163 }
  164 + return contactDO;
122 165 }
123 166  
124 167 @Override
... ... @@ -162,4 +205,12 @@ public class CrmContactServiceImpl implements CrmContactService {
162 205 // 3. TODO 记录转移日志
163 206 }
164 207  
  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 +
165 216 }
166 217 \ 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
... ... @@ -87,4 +87,11 @@ public interface CrmContractService {
87 87 */
88 88 void transferContract(CrmContractTransferReqVO reqVO, Long userId);
89 89  
  90 + /**
  91 + * 查询合同,基于联系人
  92 + * @param contactId 联系人ID
  93 + * @return 合同
  94 + */
  95 + CrmContractDO getContractByContactId(Long contactId);
  96 +
90 97 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
... ... @@ -2,6 +2,7 @@ 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;
5 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 7 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO;
7 8 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
... ... @@ -135,5 +136,10 @@ public class CrmContractServiceImpl implements CrmContractService {
135 136 contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
136 137 }
137 138  
  139 + @Override
  140 + public CrmContractDO getContractByContactId(Long contactId) {
  141 + return contractMapper.selectOne(CrmContractDO::getContactId, contactId);
  142 + }
  143 +
138 144 // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒;
139 145 }
... ...