Jelajahi Sumber

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

YunaiV 1 tahun lalu
induk
melakukan
19d5a0c2aa
23 mengubah file dengan 162 tambahan dan 186 penghapusan
  1. 2 1
      yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
  2. 1 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
  3. 11 9
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java
  4. 26 36
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java
  5. 15 22
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java
  6. 0 18
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSimpleRespVO.java
  7. 6 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java
  8. 0 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java
  9. 4 0
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
  10. 4 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmBooleanParseFunction.java
  11. 4 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContactParseFunction.java
  12. 5 6
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerParseFunction.java
  13. 4 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmIndustryParseFunction.java
  14. 4 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmLevelParseFunction.java
  15. 4 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSexParseFunction.java
  16. 4 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSourceParseFunction.java
  17. 4 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSysUserParseFunction.java
  18. 7 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java
  19. 4 4
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java
  20. 7 6
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java
  21. 41 47
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
  22. 3 2
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
  23. 2 3
      yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java

+ 2 - 1
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java

@@ -24,7 +24,8 @@ public interface ErrorCodeConstants {
     // ========== 联系人管理 1-020-003-000 ==========
     ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在");
     ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode( 1_020_003_001, "联系人商机关联不存在");
-    ErrorCode CONTACT_CONTRACT_LINK_EXISTS = new ErrorCode( 1_020_003_002, "联系人已关联合同,不能删除");
+    ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode( 1_020_003_002, "联系人已关联合同,不能删除");
+
     // ========== 回款 1-020-004-000 ==========
     ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在");
 

+ 1 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java

@@ -1,8 +1,6 @@
 package cn.iocoder.yudao.module.crm.controller.admin.business;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.lang.Assert;
-import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
@@ -29,7 +27,6 @@ import org.springframework.web.bind.annotation.*;
 
 import java.io.IOException;
 import java.util.List;
-import java.util.Optional;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -99,7 +96,7 @@ public class CrmBusinessController {
     @GetMapping("/page-by-customer")
     @Operation(summary = "获得商机分页,基于指定客户")
     public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) {
-        if(pageReqVO.getCustomerId() == null){
+        if (pageReqVO.getCustomerId() == null) {
             throw exception(CUSTOMER_NOT_EXISTS);
         }
         PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO);

+ 11 - 9
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java

@@ -43,8 +43,7 @@ import java.util.stream.Stream;
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT;
@@ -60,15 +59,14 @@ public class CrmContactController {
     private CrmContactService contactService;
     @Resource
     private CrmCustomerService customerService;
+    @Resource
+    private CrmContactBusinessService contactBusinessLinkService;
+
     @Resource
     private AdminUserApi adminUserApi;
     @Resource
     private OperateLogApi operateLogApi;
 
-    @Resource
-    private CrmContactBusinessService contactBusinessLinkService;
-
-
     @PostMapping("/create")
     @Operation(summary = "创建联系人")
     @PreAuthorize("@ss.hasPermission('crm:contact:create')")
@@ -116,10 +114,12 @@ public class CrmContactController {
     }
 
     @GetMapping("/simple-all-list")
-    @Operation(summary = "获得联系人列表")
+    @Operation(summary = "获得联系人的精简列表")
     @PreAuthorize("@ss.hasPermission('crm:contact:query')")
-    public CommonResult<List<CrmContactSimpleRespVO>> getSimpleContactList() {
-        return success(contactService.simpleContactList());
+    public CommonResult<List<CrmContactRespVO>> getSimpleContactList() {
+        List<CrmContactDO> list = contactService.getContactList();
+        return success(convertList(list, contact -> // 只返回 id、name 字段
+                new CrmContactRespVO().setId(contact.getId()).setName(contact.getName())));
     }
 
     @GetMapping("/page")
@@ -149,6 +149,7 @@ public class CrmContactController {
         ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class,
                 buildContactDetailPage(pageResult).getList());
     }
+
     @GetMapping("/operate-log-page")
     @Operation(summary = "获得客户操作日志")
     @PreAuthorize("@ss.hasPermission('crm:customer:query')")
@@ -159,6 +160,7 @@ public class CrmContactController {
         reqVO.setBizId(bizId);
         return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class)));
     }
+
     /**
      * 构建详细的联系人分页结果
      *

+ 26 - 36
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java

@@ -1,24 +1,16 @@
 package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
 
-import cn.iocoder.yudao.framework.common.validation.Mobile;
-import cn.iocoder.yudao.framework.common.validation.Telephone;
 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
 import com.alibaba.excel.annotation.ExcelProperty;
-import com.mzt.logapi.starter.annotation.DiffLogField;
 import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.NotNull;
-import lombok.*;
-import org.springframework.format.annotation.DateTimeFormat;
+import lombok.Data;
+import lombok.ToString;
 
 import java.time.LocalDateTime;
 
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
 @Schema(description = "管理后台 - CRM 联系人 Response VO")
 @Data
 @ToString(callSuper = true)
@@ -28,16 +20,16 @@ public class CrmContactRespVO {
     @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
     private Long id;
 
-    @ExcelProperty(value = "姓名",order = 1)
     @Schema(description = "姓名", example = "芋艿")
+    @ExcelProperty(value = "姓名", order = 1)
     private String name;
 
     @Schema(description = "客户编号", example = "10795")
     private Long customerId;
 
+    @Schema(description = "性别")
     @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3)
     @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
-    @Schema(description = "性别")
     private Integer sex;
 
     @Schema(description = "职位")
@@ -52,71 +44,69 @@ public class CrmContactRespVO {
     @Schema(description = "直属上级", example = "23457")
     private Long parentId;
 
-    @Schema(description = "手机号",example = "1387171766")
-    @ExcelProperty(value = "手机号",order = 4)
+    @Schema(description = "手机号", example = "1387171766")
+    @ExcelProperty(value = "手机号", order = 4)
     private String mobile;
 
-    @Schema(description = "电话",example = "021-0029922")
-    @ExcelProperty(value = "电话",order = 4)
+    @Schema(description = "电话", example = "021-0029922")
+    @ExcelProperty(value = "电话", order = 4)
     private String telephone;
 
-    @ExcelProperty(value = "QQ",order = 4)
-    @Schema(description = "QQ",example = "197272662")
+    @Schema(description = "QQ", example = "197272662")
+    @ExcelProperty(value = "QQ", order = 4)
     private Long qq;
 
-    @ExcelProperty(value = "微信",order = 4)
-    @Schema(description = "微信",example = "zzz3883")
+    @Schema(description = "微信", example = "zzz3883")
+    @ExcelProperty(value = "微信", order = 4)
     private String wechat;
 
-    @Schema(description = "电子邮箱",example = "1111@22.com")
-    @ExcelProperty(value = "邮箱",order = 4)
+    @Schema(description = "电子邮箱", example = "1111@22.com")
+    @ExcelProperty(value = "邮箱", order = 4)
     private String email;
 
     @Schema(description = "地区编号", example = "20158")
     private Integer areaId;
 
-    @ExcelProperty(value = "地址",order = 5)
     @Schema(description = "地址")
+    @ExcelProperty(value = "地址", order = 5)
     private String detailAddress;
 
     @Schema(description = "备注", example = "你说的对")
-    @ExcelProperty(value = "备注",order = 6)
+    @ExcelProperty(value = "备注", order = 6)
     private String remark;
 
     @Schema(description = "负责人用户编号", example = "14334")
-    @NotNull(message = "负责人不能为空")
     private Long ownerUserId;
 
     @Schema(description = "最后跟进时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    @ExcelProperty(value = "最后跟进时间",order = 6)
+    @ExcelProperty(value = "最后跟进时间", order = 6)
     private LocalDateTime contactLastTime;
 
     @Schema(description = "下次联系时间")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
-    @ExcelProperty(value = "下次联系时间",order = 6)
+    @ExcelProperty(value = "下次联系时间", order = 6)
     private LocalDateTime contactNextTime;
 
     @Schema(description = "创建人", example = "25682")
     private String creator;
 
     @Schema(description = "创建人名字", example = "test")
-    @ExcelProperty(value = "创建人",order = 8)
+    @ExcelProperty(value = "创建人", order = 8)
     private String creatorName;
 
-    @ExcelProperty(value = "客户名称",order = 2)
+    @ExcelProperty(value = "客户名称", order = 2)
     @Schema(description = "客户名字", example = "test")
     private String customerName;
 
     @Schema(description = "负责人", example = "test")
-    @ExcelProperty(value = "负责人",order = 7)
+    @ExcelProperty(value = "负责人", order = 7)
     private String ownerUserName;
 
-    @Schema(description = "直属上级名",example = "芋头")
-    @ExcelProperty(value = "直属上级",order = 4)
+    @Schema(description = "直属上级名", example = "芋头")
+    @ExcelProperty(value = "直属上级", order = 4)
     private String parentName;
 
-    @Schema(description = "地区名",example = "上海上海市浦东新区")
-    @ExcelProperty(value = "地区",order = 5)
+    @Schema(description = "地区名", example = "上海上海市浦东新区")
+    @ExcelProperty(value = "地区", order = 5)
     private String areaName;
+
 }

+ 15 - 22
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSaveReqVO.java

@@ -2,17 +2,12 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
 
 import cn.iocoder.yudao.framework.common.validation.Mobile;
 import cn.iocoder.yudao.framework.common.validation.Telephone;
-import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
-import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
-import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
-import com.alibaba.excel.annotation.ExcelProperty;
+import cn.iocoder.yudao.module.crm.framework.operatelog.core.*;
 import com.mzt.logapi.starter.annotation.DiffLogField;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.Email;
 import jakarta.validation.constraints.NotNull;
 import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDateTime;
@@ -22,10 +17,9 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 
 @Schema(description = "管理后台 - CRM 联系人创建/更新 Request VO")
 @Data
-@ToString(callSuper = true)
 public class CrmContactSaveReqVO  {
 
-    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
+    @Schema(description = "主键", example = "3167")
     private Long id;
 
     @Schema(description = "姓名", example = "芋艿")
@@ -34,12 +28,11 @@ public class CrmContactSaveReqVO  {
     private String name;
 
     @Schema(description = "客户编号", example = "10795")
-    @DiffLogField(name = "姓名",function = "getCustomerById")
+    @DiffLogField(name = "姓名", function = CrmCustomerParseFunction.NAME)
     private Long customerId;
 
-    @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX)
     @Schema(description = "性别")
-    @DiffLogField(name = "性别",function = "getSexById")
+    @DiffLogField(name = "性别", function = CrmSexParseFunction.NAME)
     private Integer sex;
 
     @Schema(description = "职位")
@@ -47,33 +40,32 @@ public class CrmContactSaveReqVO  {
     private String post;
 
     @Schema(description = "是否关键决策人")
-    @DictFormat(DictTypeConstants.BOOLEAN_STRING)
-    @DiffLogField(name = "关键决策人", function = "getBooleanById")
+    @DiffLogField(name = "关键决策人", function = CrmBooleanParseFunction.NAME)
     private Boolean master;
 
     @Schema(description = "直属上级", example = "23457")
-    @DiffLogField(name = "直属上级",function = "getContactById")
+    @DiffLogField(name = "直属上级", function = CrmContactParseFunction.NAME)
     private Long parentId;
 
-    @Schema(description = "手机号",example = "1387171766")
+    @Schema(description = "手机号", example = "1387171766")
     @Mobile
     @DiffLogField(name = "手机号")
     private String mobile;
 
-    @Schema(description = "电话",example = "021-0029922")
+    @Schema(description = "电话", example = "021-0029922")
     @Telephone
     @DiffLogField(name = "电话")
     private String telephone;
 
-    @Schema(description = "QQ",example = "197272662")
+    @Schema(description = "QQ", example = "197272662")
     @DiffLogField(name = "QQ")
     private Long qq;
 
-    @Schema(description = "微信",example = "zzz3883")
+    @Schema(description = "微信", example = "zzz3883")
     @DiffLogField(name = "微信")
     private String wechat;
 
-    @Schema(description = "电子邮箱",example = "1111@22.com")
+    @Schema(description = "电子邮箱", example = "1111@22.com")
     @DiffLogField(name = "邮箱")
     @Email
     private String email;
@@ -92,7 +84,7 @@ public class CrmContactSaveReqVO  {
 
     @Schema(description = "负责人用户编号", example = "14334")
     @NotNull(message = "负责人不能为空")
-    @DiffLogField(name = "负责人",function = "getUserById")
+    @DiffLogField(name = "负责人", function = CrmSysUserParseFunction.NAME)
     private Long ownerUserId;
 
     @Schema(description = "最后跟进时间")
@@ -105,6 +97,7 @@ public class CrmContactSaveReqVO  {
     @DiffLogField(name = "下次联系时间")
     private LocalDateTime contactNextTime;
 
-    @Schema(description = "关联商机ID", example = "122233")
-    private Long businessId;
+    @Schema(description = "关联商机 ID", example = "122233")
+    private Long businessId; // 注意:该字段用于在【商机】详情界面「新建联系人」时,自动进行关联
+
 }

+ 0 - 18
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSimpleRespVO.java

@@ -1,18 +0,0 @@
-package cn.iocoder.yudao.module.crm.controller.admin.contact.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.ToString;
-
-@Schema(description = "管理后台 - CRM 联系人的精简 Response VO")
-@Data
-@ToString(callSuper = true)
-public class CrmContactSimpleRespVO {
-
-    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167")
-    private Long id;
-
-    @Schema(description = "姓名", example = "芋艿")
-    private String name;
-
-}

+ 6 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java

@@ -5,6 +5,9 @@ import cn.iocoder.yudao.framework.common.validation.Mobile;
 import cn.iocoder.yudao.framework.common.validation.Telephone;
 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
 import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum;
+import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmIndustryParseFunction;
+import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmLevelParseFunction;
+import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmSourceParseFunction;
 import com.mzt.logapi.starter.annotation.DiffLogField;
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.Email;
@@ -31,17 +34,17 @@ public class CrmCustomerBaseVO {
     private String name;
 
     @Schema(description = "所属行业", example = "1")
-    @DiffLogField(name = "所属行业", function = "getIndustryById")
+    @DiffLogField(name = "所属行业", function = CrmIndustryParseFunction.NAME)
     @DictFormat(CRM_CUSTOMER_INDUSTRY)
     private Integer industryId;
 
     @Schema(description = "客户等级", example = "2")
-    @DiffLogField(name = "客户等级", function = "getLevel")
+    @DiffLogField(name = "客户等级", function = CrmLevelParseFunction.NAME)
     @InEnum(CrmCustomerLevelEnum.class)
     private Integer level;
 
     @Schema(description = "客户来源", example = "3")
-    @DiffLogField(name = "客户来源", function = "getSource")
+    @DiffLogField(name = "客户来源", function = CrmSourceParseFunction.NAME)
     private Integer source;
 
     @Schema(description = "手机", example = "18000000000")

+ 0 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java

@@ -29,8 +29,6 @@ public interface CrmContactConvert {
 
     CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class);
 
-    CrmContactDO convert(CrmContactSaveReqVO bean);
-
     CrmContactRespVO convert(CrmContactDO bean);
 
     List<CrmContactRespVO> convertList(List<CrmContactDO> list);

+ 4 - 0
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java

@@ -60,4 +60,8 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> {
         return selectJoinList(CrmContractDO.class, mpjLambdaWrapperX);
     }
 
+    default Long selectCountByContactId(Long contactId) {
+        return selectCount(CrmContractDO::getContactId, contactId);
+    }
+
 }

+ 4 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmBooleanParseFunction.java

@@ -12,10 +12,12 @@ import org.springframework.stereotype.Component;
  *
  * @author HUIHUI
  */
-@Slf4j
 @Component
+@Slf4j
 public class CrmBooleanParseFunction implements IParseFunction {
 
+    public static final String NAME = "getBooleanById";
+
     @Override
     public boolean executeBefore() {
         return true; // 先转换值后对比
@@ -23,7 +25,7 @@ public class CrmBooleanParseFunction implements IParseFunction {
 
     @Override
     public String functionName() {
-        return "getBooleanById";
+        return NAME;
     }
 
     @Override

+ 4 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContactParseFunction.java

@@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.crm.framework.operatelog.core;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
 import cn.iocoder.yudao.module.crm.service.contact.CrmContactService;
-import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
-import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import com.mzt.logapi.service.IParseFunction;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
@@ -15,10 +13,12 @@ import org.springframework.stereotype.Component;
  *
  * @author HUIHUI
  */
-@Slf4j
 @Component
+@Slf4j
 public class CrmContactParseFunction implements IParseFunction {
 
+    public static final String NAME = "getContactById";
+
     @Resource
     private CrmContactService contactService;
 
@@ -29,7 +29,7 @@ public class CrmContactParseFunction implements IParseFunction {
 
     @Override
     public String functionName() {
-        return "getContactById";
+        return NAME;
     }
 
     @Override

+ 5 - 6
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmCustomerParseFunction.java

@@ -1,28 +1,27 @@
 package cn.iocoder.yudao.module.crm.framework.operatelog.core;
 
 import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
 import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
 import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService;
-import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
 import com.mzt.logapi.service.IParseFunction;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
-import java.util.Optional;
-
 /**
  * 行业的 {@link IParseFunction} 实现类
  *
  * @author HUIHUI
  */
-@Slf4j
 @Component
+@Slf4j
 public class CrmCustomerParseFunction implements IParseFunction {
 
+    public static final String NAME = "getCustomerById";
+
     @Resource
     private CrmCustomerService customerService;
+
     @Override
     public boolean executeBefore() {
         return true; // 先转换值后对比
@@ -30,7 +29,7 @@ public class CrmCustomerParseFunction implements IParseFunction {
 
     @Override
     public String functionName() {
-        return "getCustomerById";
+        return NAME;
     }
 
     @Override

+ 4 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmIndustryParseFunction.java

@@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_I
  *
  * @author HUIHUI
  */
-@Slf4j
 @Component
+@Slf4j
 public class CrmIndustryParseFunction implements IParseFunction {
 
+    public static final String NAME = "getIndustryById";
+
     @Override
     public boolean executeBefore() {
         return true; // 先转换值后对比
@@ -24,7 +26,7 @@ public class CrmIndustryParseFunction implements IParseFunction {
 
     @Override
     public String functionName() {
-        return "getIndustryById";
+        return NAME;
     }
 
     @Override

+ 4 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmLevelParseFunction.java

@@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_L
  *
  * @author HUIHUI
  */
-@Slf4j
 @Component
+@Slf4j
 public class CrmLevelParseFunction implements IParseFunction {
 
+    public static final String NAME = "getLevel";
+
     @Override
     public boolean executeBefore() {
         return true; // 先转换值后对比
@@ -24,7 +26,7 @@ public class CrmLevelParseFunction implements IParseFunction {
 
     @Override
     public String functionName() {
-        return "getLevel";
+        return NAME;
     }
 
     @Override

+ 4 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSexParseFunction.java

@@ -7,17 +7,17 @@ import com.mzt.logapi.service.IParseFunction;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
-import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY;
-
 /**
  * 行业的 {@link IParseFunction} 实现类
  *
  * @author HUIHUI
  */
-@Slf4j
 @Component
+@Slf4j
 public class CrmSexParseFunction implements IParseFunction {
 
+    public static final String NAME = "getSexById";
+
     @Override
     public boolean executeBefore() {
         return true; // 先转换值后对比
@@ -25,7 +25,7 @@ public class CrmSexParseFunction implements IParseFunction {
 
     @Override
     public String functionName() {
-        return "getSexById";
+        return NAME;
     }
 
     @Override

+ 4 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSourceParseFunction.java

@@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_S
  *
  * @author HUIHUI
  */
-@Slf4j
 @Component
+@Slf4j
 public class CrmSourceParseFunction implements IParseFunction {
 
+    public static final String NAME = "getSource";
+
     @Override
     public boolean executeBefore() {
         return true; // 先转换值后对比
@@ -24,7 +26,7 @@ public class CrmSourceParseFunction implements IParseFunction {
 
     @Override
     public String functionName() {
-        return "getSource";
+        return NAME;
     }
 
     @Override

+ 4 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSysUserParseFunction.java

@@ -1,10 +1,8 @@
 package cn.iocoder.yudao.module.crm.framework.operatelog.core;
 
 import cn.hutool.core.util.StrUtil;
-import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
-import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
 import com.mzt.logapi.service.IParseFunction;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
@@ -15,10 +13,12 @@ import org.springframework.stereotype.Component;
  *
  * @author HUIHUI
  */
-@Slf4j
 @Component
+@Slf4j
 public class CrmSysUserParseFunction implements IParseFunction {
 
+    public static final String NAME = "getUserById";
+
     @Resource
     private AdminUserApi adminUserApi;
 
@@ -29,7 +29,7 @@ public class CrmSysUserParseFunction implements IParseFunction {
 
     @Override
     public String functionName() {
-        return "getUserById";
+        return NAME;
     }
 
     @Override

+ 7 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java

@@ -27,6 +27,13 @@ public interface CrmContactBusinessService {
      */
     void deleteContactBusinessList(@Valid CrmContactBusinessReqVO deleteReqVO);
 
+    /**
+     * 删除联系人与商机的关联,基于联系人编号
+     *
+     * @param contactId 联系人编号
+     */
+    void deleteContactBusinessByContactId(Long contactId);
+
     /**
      * 获得联系人与商机的关联列表,基于联系人编号
      *
@@ -35,7 +42,4 @@ public interface CrmContactBusinessService {
      */
     List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId);
 
-
-    void deleteContactBusinessByContactId(Long contactId);
-
 }

+ 4 - 4
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java

@@ -76,13 +76,13 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService
     }
 
     @Override
-    public List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId) {
-        return contactBusinessMapper.selectListByContactId(contactId);
+    public void deleteContactBusinessByContactId(Long contactId) {
+        contactBusinessMapper.delete(CrmContactBusinessDO::getContactId,contactId);
     }
 
     @Override
-    public void deleteContactBusinessByContactId(Long contactId) {
-        contactBusinessMapper.delete(CrmContactBusinessDO::getContactId,contactId);
+    public List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId) {
+        return contactBusinessMapper.selectListByContactId(contactId);
     }
 
 }

+ 7 - 6
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java

@@ -56,6 +56,13 @@ public interface CrmContactService {
      */
     List<CrmContactDO> getContactList(Collection<Long> ids, Long userId);
 
+    /**
+     * 获得联系人列表
+     *
+     * @return 联系人列表
+     */
+    List<CrmContactDO> getContactList();
+
     /**
      * 获得联系人分页
      *
@@ -85,10 +92,4 @@ public interface CrmContactService {
      */
     void transferContact(CrmContactTransferReqVO reqVO, Long userId);
 
-    /**
-     * 获取联系人简单列表
-     * @return 联系人
-     */
-    List<CrmContactSimpleRespVO> simpleContactList();
-
 }

+ 41 - 47
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java

@@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.crm.service.contact;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.ListUtil;
-import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*;
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO;
+import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO;
 import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert;
-import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO;
 import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO;
-import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
 import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper;
 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
 import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum;
@@ -28,18 +28,14 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
-import java.util.Optional;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE;
-import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;
 import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT;
-import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ERROR_CODE_DUPLICATE;
 import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS;
+import static java.util.Collections.singletonList;
 
 /**
  * CRM 联系人 Service 实现类
@@ -52,46 +48,42 @@ public class CrmContactServiceImpl implements CrmContactService {
 
     @Resource
     private CrmContactMapper contactMapper;
+
     @Resource
     private CrmCustomerService customerService;
     @Resource
-    private CrmPermissionService crmPermissionService;
-    @Resource
-    private AdminUserApi adminUserApi;
+    private CrmPermissionService permissionService;
     @Resource
-    private CrmContractService crmContractService;
+    private CrmContractService contractService;
     @Resource
     private CrmContactBusinessService contactBusinessService;
     @Resource
     private CrmBusinessService businessService;
 
+    @Resource
+    private AdminUserApi adminUserApi;
+
     @Override
     @Transactional(rollbackFor = Exception.class)
-    @LogRecord(type = CRM_CONTACT, subType = "创建联系人[{{#contactName}}]", bizNo = "{{#contactId}}", success = "创建了联系人")
+    @LogRecord(type = CRM_CONTACT, subType = "创建联系人", bizNo = "{{#contactId}}", success = "创建了联系人[{{#contactName}}]")
     public Long createContact(CrmContactSaveReqVO createReqVO, Long userId) {
         // 1. 校验
         validateRelationDataExists(createReqVO);
 
         // 2. 插入联系人
-        CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO);
-        int contactId = contactMapper.insert(contact);
+        CrmContactDO contact = BeanUtils.toBean(createReqVO, CrmContactDO.class);
+        contactMapper.insert(contact);
 
         // 3. 创建数据权限
-        crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
+        permissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId)
                 .setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()).setBizId(contact.getId())
                 .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()));
 
-        //4.若传businessId自动关联商机
-        Optional.ofNullable(createReqVO.getBusinessId()).ifPresent(businessId -> {
-            CrmBusinessDO crmBusinessDO = businessService.getBusiness(createReqVO.getBusinessId());
-            if(crmBusinessDO == null){
-                throw exception(BUSINESS_NOT_EXISTS);
-            }
-            CrmContactBusinessReqVO crmContactBusinessReqVO = new CrmContactBusinessReqVO();
-            crmContactBusinessReqVO.setContactId(contact.getId());
-            crmContactBusinessReqVO.setBusinessIds(List.of(businessId));
-            contactBusinessService.createContactBusinessList(crmContactBusinessReqVO);
-        });
+        // 4. 如果有关联商机,则需要创建关联
+        if (createReqVO.getBusinessId() != null) {
+            contactBusinessService.createContactBusinessList(new CrmContactBusinessReqVO()
+                    .setContactId(contact.getId()).setBusinessIds(singletonList(createReqVO.getBusinessId())));
+        }
 
         // 5. 记录操作日志
         LogRecordContext.putVariable("contactId", contact.getId());
@@ -109,7 +101,7 @@ public class CrmContactServiceImpl implements CrmContactService {
         validateRelationDataExists(updateReqVO);
 
         // 2. 更新联系人
-        CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO);
+        CrmContactDO updateObj = BeanUtils.toBean(updateReqVO, CrmContactDO.class);
         contactMapper.updateById(updateObj);
 
         // 3. 记录操作日志
@@ -134,24 +126,29 @@ public class CrmContactServiceImpl implements CrmContactService {
         if (saveReqVO.getParentId() != null && contactMapper.selectById(saveReqVO.getParentId()) == null) {
             throw exception(CONTACT_NOT_EXISTS);
         }
+        // 4. 如果有关联商机,则需要校验存在
+        if (saveReqVO.getBusinessId() != null && businessService.getBusiness(saveReqVO.getBusinessId()) == null) {
+            throw exception(BUSINESS_NOT_EXISTS);
+        }
     }
 
     @Override
     @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER)
     @Transactional(rollbackFor = Exception.class)
     public void deleteContact(Long id) {
-        //1. 校验存在
+        // 1.1 校验存在
         validateContactExists(id);
-        //2.校验是否关联合同
-        CrmContractDO crmContractDO = crmContractService.getContractByContactId(id);
-        if(crmContractDO != null){
-            throw exception(CONTACT_CONTRACT_LINK_EXISTS);
+        // 1.2 校验是否关联合同
+        if (contractService.getContractCountByContactId(id) > 0) {
+            throw exception(CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS);
         }
-        //3.删除联系人
+
+        // 2. 删除联系人
         contactMapper.deleteById(id);
-        //4.删除数据权限
-        crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id);
-        //5.删除商机关联
+
+        // 4.1 删除数据权限
+        permissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id);
+        // 4.2 删除商机关联
         contactBusinessService.deleteContactBusinessByContactId(id);
         // TODO @puhui999:删除跟进记录
     }
@@ -178,6 +175,11 @@ public class CrmContactServiceImpl implements CrmContactService {
         return contactMapper.selectBatchIds(ids, userId);
     }
 
+    @Override
+    public List<CrmContactDO> getContactList() {
+        return contactMapper.selectList();
+    }
+
     @Override
     public PageResult<CrmContactDO> getContactPage(CrmContactPageReqVO pageReqVO, Long userId) {
         return contactMapper.selectPage(pageReqVO, userId);
@@ -197,7 +199,7 @@ public class CrmContactServiceImpl implements CrmContactService {
         validateContactExists(reqVO.getId());
 
         // 2.1 数据权限转移
-        crmPermissionService.transferPermission(
+        permissionService.transferPermission(
                 CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()));
         // 2.2 设置新的负责人
         contactMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId());
@@ -205,12 +207,4 @@ public class CrmContactServiceImpl implements CrmContactService {
         // 3. TODO 记录转移日志
     }
 
-    @Override
-    public List<CrmContactSimpleRespVO> simpleContactList() {
-        CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO();
-        pageReqVO.setPageSize(PAGE_SIZE_NONE);
-        List<CrmContactDO> list =contactMapper.selectPage(pageReqVO, getLoginUserId()).getList();
-        return BeanUtils.toBean(list, CrmContactSimpleRespVO.class);
-    }
-
 }

+ 3 - 2
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java

@@ -88,10 +88,11 @@ public interface CrmContractService {
     void transferContract(CrmContractTransferReqVO reqVO, Long userId);
 
     /**
-     * 查询合同,基于联系人
+     * 查询属于某个联系人的合同数量
+     *
      * @param contactId 联系人ID
      * @return 合同
      */
-    CrmContractDO getContractByContactId(Long contactId);
+    Long getContractCountByContactId(Long contactId);
 
 }

+ 2 - 3
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java

@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.crm.service.contract;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.ListUtil;
-import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO;
 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
@@ -137,8 +136,8 @@ public class CrmContractServiceImpl implements CrmContractService {
     }
 
     @Override
-    public CrmContractDO getContractByContactId(Long contactId) {
-        return contractMapper.selectOne(CrmContractDO::getContactId, contactId);
+    public Long getContractCountByContactId(Long contactId) {
+        return contractMapper.selectCountByContactId(contactId);
     }
 
     // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒;