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,7 +24,7 @@ public interface ErrorCodeConstants {
24 // ========== 联系人管理 1-020-003-000 ========== 24 // ========== 联系人管理 1-020-003-000 ==========
25 ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); 25 ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在");
26 ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode( 1_020_003_001, "联系人商机关联不存在"); 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 // ========== 回款 1-020-004-000 ========== 28 // ========== 回款 1-020-004-000 ==========
29 ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); 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,6 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.business;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
  5 +import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 6 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 8 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
@@ -28,12 +29,15 @@ import org.springframework.web.bind.annotation.*; @@ -28,12 +29,15 @@ import org.springframework.web.bind.annotation.*;
28 29
29 import java.io.IOException; 30 import java.io.IOException;
30 import java.util.List; 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 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 35 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
33 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; 36 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
34 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 37 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
35 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 38 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
36 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 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 @Tag(name = "管理后台 - 商机") 42 @Tag(name = "管理后台 - 商机")
39 @RestController 43 @RestController
@@ -95,7 +99,9 @@ public class CrmBusinessController { @@ -95,7 +99,9 @@ public class CrmBusinessController {
95 @GetMapping("/page-by-customer") 99 @GetMapping("/page-by-customer")
96 @Operation(summary = "获得商机分页,基于指定客户") 100 @Operation(summary = "获得商机分页,基于指定客户")
97 public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) { 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 PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO); 105 PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO);
100 return success(buildBusinessDetailPageResult(pageResult)); 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,6 +17,9 @@ import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants;
17 import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; 17 import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService;
18 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; 18 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
19 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; 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 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 23 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
21 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; 24 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
22 import com.google.common.collect.Lists; 25 import com.google.common.collect.Lists;
@@ -44,6 +47,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. @@ -44,6 +47,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
44 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 47 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
45 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 48 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
46 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 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 @Tag(name = "管理后台 - CRM 联系人") 52 @Tag(name = "管理后台 - CRM 联系人")
49 @RestController 53 @RestController
@@ -58,22 +62,25 @@ public class CrmContactController { @@ -58,22 +62,25 @@ public class CrmContactController {
58 private CrmCustomerService customerService; 62 private CrmCustomerService customerService;
59 @Resource 63 @Resource
60 private AdminUserApi adminUserApi; 64 private AdminUserApi adminUserApi;
  65 + @Resource
  66 + private OperateLogApi operateLogApi;
61 67
62 @Resource 68 @Resource
63 private CrmContactBusinessService contactBusinessLinkService; 69 private CrmContactBusinessService contactBusinessLinkService;
64 70
65 - // TODO @zyna:CrmContactCreateReqVO、CrmContactUpdateReqVO、CrmContactRespVO 按照新的 VO 规范搞哈;可以参考 dept 模块 71 +
66 @PostMapping("/create") 72 @PostMapping("/create")
67 @Operation(summary = "创建联系人") 73 @Operation(summary = "创建联系人")
68 @PreAuthorize("@ss.hasPermission('crm:contact:create')") 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 return success(contactService.createContact(createReqVO, getLoginUserId())); 76 return success(contactService.createContact(createReqVO, getLoginUserId()));
71 } 77 }
72 78
73 @PutMapping("/update") 79 @PutMapping("/update")
74 @Operation(summary = "更新联系人") 80 @Operation(summary = "更新联系人")
  81 + @OperateLog(enable = false)
75 @PreAuthorize("@ss.hasPermission('crm:contact:update')") 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 contactService.updateContact(updateReqVO); 84 contactService.updateContact(updateReqVO);
78 return success(true); 85 return success(true);
79 } 86 }
@@ -112,11 +119,7 @@ public class CrmContactController { @@ -112,11 +119,7 @@ public class CrmContactController {
112 @Operation(summary = "获得联系人列表") 119 @Operation(summary = "获得联系人列表")
113 @PreAuthorize("@ss.hasPermission('crm:contact:query')") 120 @PreAuthorize("@ss.hasPermission('crm:contact:query')")
114 public CommonResult<List<CrmContactSimpleRespVO>> getSimpleContactList() { 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 @GetMapping("/page") 125 @GetMapping("/page")
@@ -146,7 +149,16 @@ public class CrmContactController { @@ -146,7 +149,16 @@ public class CrmContactController {
146 ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class, 149 ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class,
147 buildContactDetailPage(pageResult).getList()); 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,7 +193,7 @@ public class CrmContactController {
181 // ================== 关联/取关联系人 =================== 193 // ================== 关联/取关联系人 ===================
182 194
183 @PostMapping("/create-business-list") 195 @PostMapping("/create-business-list")
184 - @Operation(summary = "创建联系人与联系人的关联") 196 + @Operation(summary = "创建联系人与商机的关联")
185 @PreAuthorize("@ss.hasPermission('crm:contact:create-business')") 197 @PreAuthorize("@ss.hasPermission('crm:contact:create-business')")
186 public CommonResult<Boolean> createContactBusinessList(@Valid @RequestBody CrmContactBusinessReqVO createReqVO) { 198 public CommonResult<Boolean> createContactBusinessList(@Valid @RequestBody CrmContactBusinessReqVO createReqVO) {
187 contactBusinessLinkService.createContactBusinessList(createReqVO); 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 package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; 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 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; 8 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
4 import com.alibaba.excel.annotation.ExcelProperty; 9 import com.alibaba.excel.annotation.ExcelProperty;
  10 +import com.mzt.logapi.starter.annotation.DiffLogField;
5 import io.swagger.v3.oas.annotations.media.Schema; 11 import io.swagger.v3.oas.annotations.media.Schema;
  12 +import jakarta.validation.constraints.Email;
  13 +import jakarta.validation.constraints.NotNull;
6 import lombok.*; 14 import lombok.*;
  15 +import org.springframework.format.annotation.DateTimeFormat;
  16 +
7 import java.time.LocalDateTime; 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 @Schema(description = "管理后台 - CRM 联系人 Response VO") 22 @Schema(description = "管理后台 - CRM 联系人 Response VO")
10 @Data 23 @Data
11 -@EqualsAndHashCode(callSuper = true)  
12 @ToString(callSuper = true) 24 @ToString(callSuper = true)
13 @ExcelIgnoreUnannotated 25 @ExcelIgnoreUnannotated
14 -public class CrmContactRespVO extends CrmContactBaseVO { 26 +public class CrmContactRespVO {
15 27
16 @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167") 28 @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
17 private Long id; 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 @Schema(description = "创建人", example = "25682") 100 @Schema(description = "创建人", example = "25682")
28 private String creator; 101 private String creator;
29 102
30 @Schema(description = "创建人名字", example = "test") 103 @Schema(description = "创建人名字", example = "test")
31 - @ExcelProperty(value = "创建人", order = 8) 104 + @ExcelProperty(value = "创建人",order = 8)
32 private String creatorName; 105 private String creatorName;
33 106
34 @ExcelProperty(value = "客户名称",order = 2) 107 @ExcelProperty(value = "客户名称",order = 2)
@@ -36,15 +109,14 @@ public class CrmContactRespVO extends CrmContactBaseVO { @@ -36,15 +109,14 @@ public class CrmContactRespVO extends CrmContactBaseVO {
36 private String customerName; 109 private String customerName;
37 110
38 @Schema(description = "负责人", example = "test") 111 @Schema(description = "负责人", example = "test")
39 - @ExcelProperty(value = "负责人", order = 7) 112 + @ExcelProperty(value = "负责人",order = 7)
40 private String ownerUserName; 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 private String parentName; 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 private String areaName; 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,12 +5,14 @@ import cn.iocoder.yudao.framework.common.validation.Telephone;
5 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; 5 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
6 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; 6 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
7 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; 7 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
8 -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;  
9 import com.alibaba.excel.annotation.ExcelProperty; 8 import com.alibaba.excel.annotation.ExcelProperty;
  9 +import com.mzt.logapi.starter.annotation.DiffLogField;
10 import io.swagger.v3.oas.annotations.media.Schema; 10 import io.swagger.v3.oas.annotations.media.Schema;
11 import jakarta.validation.constraints.Email; 11 import jakarta.validation.constraints.Email;
12 import jakarta.validation.constraints.NotNull; 12 import jakarta.validation.constraints.NotNull;
13 import lombok.Data; 13 import lombok.Data;
  14 +import lombok.EqualsAndHashCode;
  15 +import lombok.ToString;
14 import org.springframework.format.annotation.DateTimeFormat; 16 import org.springframework.format.annotation.DateTimeFormat;
15 17
16 import java.time.LocalDateTime; 18 import java.time.LocalDateTime;
@@ -18,86 +20,91 @@ import java.time.LocalDateTime; @@ -18,86 +20,91 @@ import java.time.LocalDateTime;
18 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;
19 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 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 @Data 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 @Schema(description = "姓名", example = "芋艿") 31 @Schema(description = "姓名", example = "芋艿")
32 @NotNull(message = "姓名不能为空") 32 @NotNull(message = "姓名不能为空")
  33 + @DiffLogField(name = "姓名")
33 private String name; 34 private String name;
34 35
35 @Schema(description = "客户编号", example = "10795") 36 @Schema(description = "客户编号", example = "10795")
  37 + @DiffLogField(name = "姓名",function = "getCustomerById")
36 private Long customerId; 38 private Long customerId;
37 39
38 - @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3)  
39 @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX) 40 @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
40 @Schema(description = "性别") 41 @Schema(description = "性别")
  42 + @DiffLogField(name = "性别",function = "getSexById")
41 private Integer sex; 43 private Integer sex;
42 44
43 @Schema(description = "职位") 45 @Schema(description = "职位")
44 - @ExcelProperty(value = "职位", order = 3) 46 + @DiffLogField(name = "职位")
45 private String post; 47 private String post;
46 48
47 @Schema(description = "是否关键决策人") 49 @Schema(description = "是否关键决策人")
48 - @ExcelProperty(value = "是否关键决策人", converter = DictConvert.class, order = 3)  
49 @DictFormat(DictTypeConstants.BOOLEAN_STRING) 50 @DictFormat(DictTypeConstants.BOOLEAN_STRING)
  51 + @DiffLogField(name = "关键决策人", function = "getBooleanById")
50 private Boolean master; 52 private Boolean master;
51 53
52 @Schema(description = "直属上级", example = "23457") 54 @Schema(description = "直属上级", example = "23457")
  55 + @DiffLogField(name = "直属上级",function = "getContactById")
53 private Long parentId; 56 private Long parentId;
54 57
55 @Schema(description = "手机号",example = "1387171766") 58 @Schema(description = "手机号",example = "1387171766")
56 @Mobile 59 @Mobile
57 - @ExcelProperty(value = "手机号",order = 4) 60 + @DiffLogField(name = "手机号")
58 private String mobile; 61 private String mobile;
59 62
60 - @Schema(description = "座机",example = "021-0029922") 63 + @Schema(description = "电话",example = "021-0029922")
61 @Telephone 64 @Telephone
62 - @ExcelProperty(value = "座机",order = 4) 65 + @DiffLogField(name = "电话")
63 private String telephone; 66 private String telephone;
64 67
65 - @ExcelProperty(value = "QQ",order = 4)  
66 @Schema(description = "QQ",example = "197272662") 68 @Schema(description = "QQ",example = "197272662")
  69 + @DiffLogField(name = "QQ")
67 private Long qq; 70 private Long qq;
68 71
69 - @ExcelProperty(value = "微信",order = 4)  
70 @Schema(description = "微信",example = "zzz3883") 72 @Schema(description = "微信",example = "zzz3883")
  73 + @DiffLogField(name = "微信")
71 private String wechat; 74 private String wechat;
72 75
73 @Schema(description = "电子邮箱",example = "1111@22.com") 76 @Schema(description = "电子邮箱",example = "1111@22.com")
  77 + @DiffLogField(name = "邮箱")
74 @Email 78 @Email
75 - @ExcelProperty(value = "邮箱",order = 4)  
76 private String email; 79 private String email;
77 80
78 @Schema(description = "地区编号", example = "20158") 81 @Schema(description = "地区编号", example = "20158")
  82 + @DiffLogField(name = "所在地", function = "getAreaById")
79 private Integer areaId; 83 private Integer areaId;
80 84
81 - @ExcelProperty(value = "地址",order = 5)  
82 @Schema(description = "地址") 85 @Schema(description = "地址")
  86 + @DiffLogField(name = "地址")
83 private String detailAddress; 87 private String detailAddress;
84 88
85 @Schema(description = "备注", example = "你说的对") 89 @Schema(description = "备注", example = "你说的对")
86 - @ExcelProperty(value = "备注",order = 6) 90 + @DiffLogField(name = "备注")
87 private String remark; 91 private String remark;
88 92
89 @Schema(description = "负责人用户编号", example = "14334") 93 @Schema(description = "负责人用户编号", example = "14334")
90 @NotNull(message = "负责人不能为空") 94 @NotNull(message = "负责人不能为空")
  95 + @DiffLogField(name = "负责人",function = "getUserById")
91 private Long ownerUserId; 96 private Long ownerUserId;
92 97
93 @Schema(description = "最后跟进时间") 98 @Schema(description = "最后跟进时间")
94 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 99 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
95 - @ExcelProperty(value = "最后跟进时间",order = 6) 100 + @DiffLogField(name = "最后跟进时间")
96 private LocalDateTime contactLastTime; 101 private LocalDateTime contactLastTime;
97 102
98 @Schema(description = "下次联系时间") 103 @Schema(description = "下次联系时间")
99 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) 104 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
100 - @ExcelProperty(value = "下次联系时间",order = 6) 105 + @DiffLogField(name = "下次联系时间")
101 private LocalDateTime contactNextTime; 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,9 +29,7 @@ public interface CrmContactConvert {
29 29
30 CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class); 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 CrmContactRespVO convert(CrmContactDO bean); 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,4 +35,7 @@ public interface CrmContactBusinessService {
35 */ 35 */
36 List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId); 36 List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId);
37 37
  38 +
  39 + void deleteContactBusinessByContactId(Long contactId);
  40 +
38 } 41 }
39 \ No newline at end of file 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,4 +80,9 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
80 return contactBusinessMapper.selectListByContactId(contactId); 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 \ No newline at end of file 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 package cn.iocoder.yudao.module.crm.service.contact; 1 package cn.iocoder.yudao.module.crm.service.contact;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 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 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; 5 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
9 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; 6 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
10 import jakarta.validation.Valid; 7 import jakarta.validation.Valid;
@@ -26,14 +23,14 @@ public interface CrmContactService { @@ -26,14 +23,14 @@ public interface CrmContactService {
26 * @param userId 用户编号 23 * @param userId 用户编号
27 * @return 编号 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 * @param updateReqVO 更新信息 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,4 +85,10 @@ public interface CrmContactService {
88 */ 85 */
89 void transferContact(CrmContactTransferReqVO reqVO, Long userId); 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,29 +2,43 @@ package cn.iocoder.yudao.module.crm.service.contact;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.collection.ListUtil; 4 import cn.hutool.core.collection.ListUtil;
  5 +import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; 8 import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
7 import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert; 9 import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert;
  10 +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
8 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; 11 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
  12 +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
9 import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; 13 import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper;
10 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 14 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
11 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; 15 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
12 import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; 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 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; 19 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
14 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; 20 import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService;
15 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; 21 import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO;
16 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 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 import jakarta.annotation.Resource; 26 import jakarta.annotation.Resource;
18 import org.springframework.stereotype.Service; 27 import org.springframework.stereotype.Service;
19 import org.springframework.transaction.annotation.Transactional; 28 import org.springframework.transaction.annotation.Transactional;
20 import org.springframework.validation.annotation.Validated; 29 import org.springframework.validation.annotation.Validated;
21 30
  31 +import java.util.Arrays;
22 import java.util.Collection; 32 import java.util.Collection;
23 import java.util.List; 33 import java.util.List;
  34 +import java.util.Optional;
24 35
25 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 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 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; 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,45 +52,68 @@ public class CrmContactServiceImpl implements CrmContactService {
38 52
39 @Resource 53 @Resource
40 private CrmContactMapper contactMapper; 54 private CrmContactMapper contactMapper;
41 -  
42 @Resource 55 @Resource
43 private CrmCustomerService customerService; 56 private CrmCustomerService customerService;
44 @Resource 57 @Resource
45 private CrmPermissionService crmPermissionService; 58 private CrmPermissionService crmPermissionService;
46 @Resource 59 @Resource
47 private AdminUserApi adminUserApi; 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 @Override 68 @Override
50 @Transactional(rollbackFor = Exception.class) 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 // 1. 校验 72 // 1. 校验
54 validateRelationDataExists(createReqVO); 73 validateRelationDataExists(createReqVO);
55 74
56 // 2. 插入联系人 75 // 2. 插入联系人
57 CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO); 76 CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO);
58 - contactMapper.insert(contact); 77 + int contactId = contactMapper.insert(contact);
59 78
60 // 3. 创建数据权限 79 // 3. 创建数据权限
61 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) 80 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
62 .setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()).setBizId(contact.getId()) 81 .setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()).setBizId(contact.getId())
63 .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); 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 return contact.getId(); 99 return contact.getId();
67 } 100 }
68 101
69 @Override 102 @Override
  103 + @Transactional(rollbackFor = Exception.class)
  104 + @LogRecord(type = CRM_CONTACT, subType = "更新联系人", bizNo = "{{#updateReqVO.id}}", success = "更新了联系人{_DIFF{#updateReqVO}}")
70 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) 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 // 1. 校验存在 107 // 1. 校验存在
74 - validateContactExists(updateReqVO.getId()); 108 + CrmContactDO contactDO = validateContactExists(updateReqVO.getId());
75 validateRelationDataExists(updateReqVO); 109 validateRelationDataExists(updateReqVO);
76 110
77 // 2. 更新联系人 111 // 2. 更新联系人
78 CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO); 112 CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO);
79 contactMapper.updateById(updateObj); 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,7 +121,7 @@ public class CrmContactServiceImpl implements CrmContactService {
84 * 121 *
85 * @param saveReqVO 新增/修改请求 VO 122 * @param saveReqVO 新增/修改请求 VO
86 */ 123 */
87 - private void validateRelationDataExists(CrmContactBaseVO saveReqVO) { 124 + private void validateRelationDataExists(CrmContactSaveReqVO saveReqVO) {
88 // 1. 校验客户 125 // 1. 校验客户
89 if (saveReqVO.getCustomerId() != null && customerService.getCustomer(saveReqVO.getCustomerId()) == null) { 126 if (saveReqVO.getCustomerId() != null && customerService.getCustomer(saveReqVO.getCustomerId()) == null) {
90 throw exception(CUSTOMER_NOT_EXISTS); 127 throw exception(CUSTOMER_NOT_EXISTS);
@@ -101,24 +138,30 @@ public class CrmContactServiceImpl implements CrmContactService { @@ -101,24 +138,30 @@ public class CrmContactServiceImpl implements CrmContactService {
101 138
102 @Override 139 @Override
103 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) 140 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
  141 + @Transactional(rollbackFor = Exception.class)
104 public void deleteContact(Long id) { 142 public void deleteContact(Long id) {
105 - // 校验存在 143 + //1. 校验存在
106 validateContactExists(id); 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 contactMapper.deleteById(id); 151 contactMapper.deleteById(id);
111 - // 删除数据权限 152 + //4.删除数据权限
112 crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id); 153 crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id);
113 - // TODO @zyna:删除商机联系人关联  
114 - 154 + //5.删除商机关联
  155 + contactBusinessService.deleteContactBusinessByContactId(id);
115 // TODO @puhui999:删除跟进记录 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 throw exception(CONTACT_NOT_EXISTS); 162 throw exception(CONTACT_NOT_EXISTS);
121 } 163 }
  164 + return contactDO;
122 } 165 }
123 166
124 @Override 167 @Override
@@ -162,4 +205,12 @@ public class CrmContactServiceImpl implements CrmContactService { @@ -162,4 +205,12 @@ public class CrmContactServiceImpl implements CrmContactService {
162 // 3. TODO 记录转移日志 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 \ No newline at end of file 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,4 +87,11 @@ public interface CrmContractService {
87 */ 87 */
88 void transferContract(CrmContractTransferReqVO reqVO, Long userId); 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,6 +2,7 @@ package cn.iocoder.yudao.module.crm.service.contract;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.collection.ListUtil; 4 import cn.hutool.core.collection.ListUtil;
  5 +import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO; 7 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO;
7 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; 8 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
@@ -135,5 +136,10 @@ public class CrmContractServiceImpl implements CrmContractService { @@ -135,5 +136,10 @@ public class CrmContractServiceImpl implements CrmContractService {
135 contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); 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 // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒; 144 // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒;
139 } 145 }