Commit 1bfb4060416046128693507fe506ae397d294787

Authored by YunaiV
1 parent 51f52ff4

📖 CRM:code review 待提醒逻辑

Showing 13 changed files with 199 additions and 205 deletions
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java
@@ -24,58 +24,67 @@ public class CrmClueRespVO { @@ -24,58 +24,67 @@ public class CrmClueRespVO {
24 @ExcelProperty("编号") 24 @ExcelProperty("编号")
25 private Long id; 25 private Long id;
26 26
27 - @Schema(description = "转化状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")  
28 - @ExcelProperty(value = "转化状态", converter = DictConvert.class)  
29 - @DictFormat(DictTypeConstants.BOOLEAN_STRING)  
30 - private Boolean transformStatus; 27 + @Schema(description = "线索名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "线索xxx")
  28 + @ExcelProperty("线索名称")
  29 + private String name;
31 30
32 @Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") 31 @Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
33 @ExcelProperty(value = "跟进状态", converter = DictConvert.class) 32 @ExcelProperty(value = "跟进状态", converter = DictConvert.class)
34 @DictFormat(DictTypeConstants.BOOLEAN_STRING) 33 @DictFormat(DictTypeConstants.BOOLEAN_STRING)
35 private Boolean followUpStatus; 34 private Boolean followUpStatus;
36 35
37 - @Schema(description = "线索名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "线索xxx")  
38 - @ExcelProperty("线索名称")  
39 - private String name;  
40 -  
41 - @Schema(description = "客户 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "520")  
42 - // TODO 这里需要导出成客户名称  
43 - @ExcelProperty("客户id")  
44 - private Long customerId; 36 + @Schema(description = "最后跟进时间")
  37 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  38 + @ExcelProperty("最后跟进时间")
  39 + private LocalDateTime contactLastTime;
45 40
46 @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") 41 @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00")
47 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 42 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
48 @ExcelProperty("下次联系时间") 43 @ExcelProperty("下次联系时间")
49 private LocalDateTime contactNextTime; 44 private LocalDateTime contactNextTime;
50 45
51 - @Schema(description = "电话", example = "18000000000")  
52 - @ExcelProperty("电话")  
53 - private String telephone; 46 + @Schema(description = "负责人编号")
  47 + @ExcelProperty("负责人的用户编号")
  48 + // TODO 这里需要导出成负责人的名字
  49 + private Long ownerUserId;
  50 +
  51 + @Schema(description = "转化状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
  52 + @ExcelProperty(value = "转化状态", converter = DictConvert.class)
  53 + @DictFormat(DictTypeConstants.BOOLEAN_STRING)
  54 + private Boolean transformStatus;
  55 +
  56 + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "520")
  57 + // TODO 这里需要导出成客户名称
  58 + @ExcelProperty("客户编号")
  59 + private Long customerId;
54 60
55 @Schema(description = "手机号", example = "18000000000") 61 @Schema(description = "手机号", example = "18000000000")
56 @ExcelProperty("手机号") 62 @ExcelProperty("手机号")
57 private String mobile; 63 private String mobile;
58 64
59 - @Schema(description = "地址", example = "北京市海淀区")  
60 - @ExcelProperty("地址")  
61 - private String address; 65 + @Schema(description = "电话", example = "18000000000")
  66 + @ExcelProperty("电话")
  67 + private String telephone;
62 68
63 - @Schema(description = "负责人编号")  
64 - @ExcelProperty("负责人的用户编号")  
65 - private Long ownerUserId; 69 + @Schema(description = "网址", example = "25682")
  70 + @ExcelProperty("网址")
  71 + private String website;
66 72
67 - @Schema(description = "最后跟进时间")  
68 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
69 - @ExcelProperty("最后跟进时间")  
70 - private LocalDateTime contactLastTime; 73 + @Schema(description = "QQ", example = "25682")
  74 + @ExcelProperty("QQ")
  75 + private String qq;
71 76
72 - @Schema(description = "备注", example = "随便")  
73 - @ExcelProperty("备注")  
74 - private String remark; 77 + @Schema(description = "wechat", example = "25682")
  78 + @ExcelProperty("wechat")
  79 + private String wechat;
75 80
76 - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)  
77 - @ExcelProperty("创建时间")  
78 - private LocalDateTime createTime; 81 + @Schema(description = "email", example = "25682")
  82 + @ExcelProperty("email")
  83 + private String email;
  84 +
  85 + @Schema(description = "地址", example = "北京市海淀区")
  86 + @ExcelProperty("地址")
  87 + private String address;
79 88
80 @Schema(description = "所属行业", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") 89 @Schema(description = "所属行业", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563")
81 @ExcelProperty(value = "所属行业", converter = DictConvert.class) 90 @ExcelProperty(value = "所属行业", converter = DictConvert.class)
@@ -92,24 +101,16 @@ public class CrmClueRespVO { @@ -92,24 +101,16 @@ public class CrmClueRespVO {
92 @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE) 101 @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE)
93 private Integer source; 102 private Integer source;
94 103
95 - @Schema(description = "网址", example = "25682")  
96 - @ExcelProperty("网址")  
97 - private String website;  
98 -  
99 - @Schema(description = "QQ", example = "25682")  
100 - @ExcelProperty("QQ")  
101 - private String qq;  
102 -  
103 - @Schema(description = "wechat", example = "25682")  
104 - @ExcelProperty("wechat")  
105 - private String wechat;  
106 -  
107 - @Schema(description = "email", example = "25682")  
108 - @ExcelProperty("email")  
109 - private String email;  
110 -  
111 @Schema(description = "客户描述", example = "25682") 104 @Schema(description = "客户描述", example = "25682")
112 @ExcelProperty("客户描述") 105 @ExcelProperty("客户描述")
113 private String description; 106 private String description;
114 107
  108 + @Schema(description = "备注", example = "随便")
  109 + @ExcelProperty("备注")
  110 + private String remark;
  111 +
  112 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  113 + @ExcelProperty("创建时间")
  114 + private LocalDateTime createTime;
  115 +
115 } 116 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java
@@ -21,7 +21,7 @@ import java.time.LocalDateTime; @@ -21,7 +21,7 @@ import java.time.LocalDateTime;
21 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;
22 import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; 22 import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY;
23 23
24 -@Schema(description = "管理后台 - CRM 线索 创建/更新 Request VO") 24 +@Schema(description = "管理后台 - CRM 线索创建/更新 Request VO")
25 @Data 25 @Data
26 public class CrmClueSaveReqVO { 26 public class CrmClueSaveReqVO {
27 27
@@ -33,50 +33,28 @@ public class CrmClueSaveReqVO { @@ -33,50 +33,28 @@ public class CrmClueSaveReqVO {
33 @NotEmpty(message = "线索名称不能为空") 33 @NotEmpty(message = "线索名称不能为空")
34 private String name; 34 private String name;
35 35
  36 + @Schema(description = "最后跟进时间")
  37 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  38 + @DiffLogField(name = "最后跟进时间")
  39 + private LocalDateTime contactLastTime;
  40 +
36 @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") 41 @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00")
37 @DiffLogField(name = "下次联系时间") 42 @DiffLogField(name = "下次联系时间")
38 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 43 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
39 private LocalDateTime contactNextTime; 44 private LocalDateTime contactNextTime;
40 45
41 - @Schema(description = "电话", example = "18000000000")  
42 - @DiffLogField(name = "电话")  
43 - @Telephone  
44 - private String telephone; 46 + @Schema(description = "负责人编号", example = "2048")
  47 + private Long ownerUserId;
45 48
46 @Schema(description = "手机号", example = "18000000000") 49 @Schema(description = "手机号", example = "18000000000")
47 @DiffLogField(name = "手机号") 50 @DiffLogField(name = "手机号")
48 @Mobile 51 @Mobile
49 private String mobile; 52 private String mobile;
50 53
51 - @Schema(description = "地址", example = "北京市海淀区")  
52 - @DiffLogField(name = "地址")  
53 - private String address;  
54 -  
55 - @Schema(description = "最后跟进时间")  
56 - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)  
57 - @DiffLogField(name = "最后跟进时间")  
58 - private LocalDateTime contactLastTime;  
59 -  
60 - @Schema(description = "负责人编号", example = "2048")  
61 - private Long ownerUserId;  
62 -  
63 - @Schema(description = "备注", example = "随便")  
64 - @DiffLogField(name = "备注")  
65 - private String remark;  
66 -  
67 - @Schema(description = "所属行业", example = "1")  
68 - @DiffLogField(name = "所属行业", function = CrmCustomerIndustryParseFunction.NAME)  
69 - @DictFormat(CRM_CUSTOMER_INDUSTRY)  
70 - private Integer industryId;  
71 -  
72 - @Schema(description = "客户等级", example = "2")  
73 - @DiffLogField(name = "客户等级", function = CrmCustomerLevelParseFunction.NAME)  
74 - @InEnum(CrmCustomerLevelEnum.class)  
75 - private Integer level;  
76 -  
77 - @Schema(description = "客户来源", example = "3")  
78 - @DiffLogField(name = "客户来源", function = CrmCustomerSourceParseFunction.NAME)  
79 - private Integer source; 54 + @Schema(description = "电话", example = "18000000000")
  55 + @DiffLogField(name = "电话")
  56 + @Telephone
  57 + private String telephone;
80 58
81 @Schema(description = "网址", example = "https://www.baidu.com") 59 @Schema(description = "网址", example = "https://www.baidu.com")
82 @DiffLogField(name = "网址") 60 @DiffLogField(name = "网址")
@@ -98,8 +76,31 @@ public class CrmClueSaveReqVO { @@ -98,8 +76,31 @@ public class CrmClueSaveReqVO {
98 @Size(max = 255, message = "邮箱长度不能超过 255 个字符") 76 @Size(max = 255, message = "邮箱长度不能超过 255 个字符")
99 private String email; 77 private String email;
100 78
  79 + @Schema(description = "地址", example = "北京市海淀区")
  80 + @DiffLogField(name = "地址")
  81 + private String address;
  82 +
  83 + @Schema(description = "所属行业", example = "1")
  84 + @DiffLogField(name = "所属行业", function = CrmCustomerIndustryParseFunction.NAME)
  85 + @DictFormat(CRM_CUSTOMER_INDUSTRY)
  86 + private Integer industryId;
  87 +
  88 + @Schema(description = "客户等级", example = "2")
  89 + @DiffLogField(name = "客户等级", function = CrmCustomerLevelParseFunction.NAME)
  90 + @InEnum(CrmCustomerLevelEnum.class)
  91 + private Integer level;
  92 +
  93 + @Schema(description = "客户来源", example = "3")
  94 + @DiffLogField(name = "客户来源", function = CrmCustomerSourceParseFunction.NAME)
  95 + private Integer source;
  96 +
101 @Schema(description = "客户描述", example = "任意文字") 97 @Schema(description = "客户描述", example = "任意文字")
102 @DiffLogField(name = "客户描述") 98 @DiffLogField(name = "客户描述")
103 @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") 99 @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符")
104 private String description; 100 private String description;
  101 +
  102 + @Schema(description = "备注", example = "随便")
  103 + @DiffLogField(name = "备注")
  104 + private String remark;
  105 +
105 } 106 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
@@ -191,7 +191,6 @@ public class CrmContractController { @@ -191,7 +191,6 @@ public class CrmContractController {
191 return success(contractService.getCheckContractCount(getLoginUserId())); 191 return success(contractService.getCheckContractCount(getLoginUserId()));
192 } 192 }
193 193
194 -  
195 @GetMapping("/end-contract-count") 194 @GetMapping("/end-contract-count")
196 @Operation(summary = "获得即将到期的合同数量") 195 @Operation(summary = "获得即将到期的合同数量")
197 @PreAuthorize("@ss.hasPermission('crm:contract:query')") 196 @PreAuthorize("@ss.hasPermission('crm:contract:query')")
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java
@@ -152,19 +152,17 @@ public class CrmCustomerController { @@ -152,19 +152,17 @@ public class CrmCustomerController {
152 @Operation(summary = "获得待进入公海客户数量") 152 @Operation(summary = "获得待进入公海客户数量")
153 @PreAuthorize("@ss.hasPermission('crm:customer:query')") 153 @PreAuthorize("@ss.hasPermission('crm:customer:query')")
154 public CommonResult<Long> getPutInPoolRemindCustomerCount() { 154 public CommonResult<Long> getPutInPoolRemindCustomerCount() {
155 - // 获取公海配置 TODO @dbh52:合并到 getPutInPoolRemindCustomerPage 会更合适哈; 155 + // 获取公海配置
156 CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig(); 156 CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig();
157 if (ObjUtil.isNull(poolConfigDO) 157 if (ObjUtil.isNull(poolConfigDO)
158 || Boolean.FALSE.equals(poolConfigDO.getEnabled()) 158 || Boolean.FALSE.equals(poolConfigDO.getEnabled())
159 || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) { 159 || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled())) {
160 throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED); 160 throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED);
161 } 161 }
162 -  
163 - CrmCustomerPageReqVO pageVO = new CrmCustomerPageReqVO();  
164 - pageVO.setPool(null);  
165 - pageVO.setContactStatus(CrmCustomerPageReqVO.CONTACT_TODAY);  
166 - pageVO.setSceneType(CrmSceneTypeEnum.OWNER.getType());  
167 - 162 + CrmCustomerPageReqVO pageVO = new CrmCustomerPageReqVO()
  163 + .setPool(null)
  164 + .setContactStatus(CrmCustomerPageReqVO.CONTACT_TODAY)
  165 + .setSceneType(CrmSceneTypeEnum.OWNER.getType());
168 return success(customerService.getPutInPoolRemindCustomerCount(pageVO, poolConfigDO, getLoginUserId())); 166 return success(customerService.getPutInPoolRemindCustomerCount(pageVO, poolConfigDO, getLoginUserId()));
169 } 167 }
170 168
@@ -182,7 +180,6 @@ public class CrmCustomerController { @@ -182,7 +180,6 @@ public class CrmCustomerController {
182 return success(customerService.getFollowCustomerCount(getLoginUserId())); 180 return success(customerService.getFollowCustomerCount(getLoginUserId()));
183 } 181 }
184 182
185 -  
186 /** 183 /**
187 * 获取距离进入公海的时间 184 * 获取距离进入公海的时间
188 * 185 *
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java
@@ -50,10 +50,7 @@ public class CrmCustomerPageReqVO extends PageParam { @@ -50,10 +50,7 @@ public class CrmCustomerPageReqVO extends PageParam {
50 private Boolean pool; // null 则表示为不是公海数据 50 private Boolean pool; // null 则表示为不是公海数据
51 51
52 @Schema(description = "联系状态", example = "1") 52 @Schema(description = "联系状态", example = "1")
53 - private Integer contactStatus; // backlog查询条件, null 则表示为不做查询  
54 -  
55 - @Schema(description = "跟进状态", example = "true")  
56 - private Boolean followUpStatus; // backlog查询条件, null 则表示为不做查询 53 + private Integer contactStatus; // backlog 查询条件
57 54
58 @Schema(description = "跟进状态", example = "true") 55 @Schema(description = "跟进状态", example = "true")
59 private Boolean followUpStatus; 56 private Boolean followUpStatus;
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java
@@ -10,7 +10,6 @@ import lombok.*; @@ -10,7 +10,6 @@ import lombok.*;
10 10
11 import java.time.LocalDateTime; 11 import java.time.LocalDateTime;
12 12
13 -// TODO 芋艿:字段的顺序,需要整理下;  
14 /** 13 /**
15 * 线索 DO 14 * 线索 DO
16 * 15 *
@@ -32,85 +31,96 @@ public class CrmClueDO extends BaseDO { @@ -32,85 +31,96 @@ public class CrmClueDO extends BaseDO {
32 @TableId 31 @TableId
33 private Long id; 32 private Long id;
34 /** 33 /**
35 - * 转化状态 34 + * 线索名称
36 */ 35 */
37 - private Boolean transformStatus; 36 + private String name;
  37 +
38 /** 38 /**
39 * 跟进状态 39 * 跟进状态
40 */ 40 */
41 private Boolean followUpStatus; 41 private Boolean followUpStatus;
42 /** 42 /**
43 - * 线索名称 43 + * 最后跟进时间 TODO 添加跟进记录时更新该值
44 */ 44 */
45 - private String name; 45 + private LocalDateTime contactLastTime;
  46 + /**
  47 + * 下次联系时间
  48 + */
  49 + private LocalDateTime contactNextTime;
  50 +
  51 + /**
  52 + * 负责人的用户编号
  53 + *
  54 + * 关联 AdminUserDO 的 id 字段
  55 + */
  56 + private Long ownerUserId;
  57 +
  58 + /**
  59 + * 转化状态
  60 + *
  61 + * true 表示已转换,会更新 {@link #customerId} 字段
  62 + */
  63 + private Boolean transformStatus;
46 /** 64 /**
47 - * 客户 id 65 + * 客户编号
48 * 66 *
49 * 关联 {@link CrmCustomerDO#getId()} 67 * 关联 {@link CrmCustomerDO#getId()}
50 */ 68 */
51 private Long customerId; 69 private Long customerId;
  70 +
52 /** 71 /**
53 - * 下次联系时间 72 + * 手机号
54 */ 73 */
55 - private LocalDateTime contactNextTime; 74 + private String mobile;
56 /** 75 /**
57 * 电话 76 * 电话
58 */ 77 */
59 private String telephone; 78 private String telephone;
60 /** 79 /**
61 - * 手机号 80 + * 网址
62 */ 81 */
63 - private String mobile; 82 + private String website;
64 /** 83 /**
65 - * 地址 84 + * QQ
66 */ 85 */
67 - private String address; 86 + private String qq;
68 /** 87 /**
69 - * 最后跟进时间 TODO 添加跟进记录时更新该值 88 + * wechat
70 */ 89 */
71 - private LocalDateTime contactLastTime; 90 + private String wechat;
72 /** 91 /**
73 - * 备注 92 + * email
74 */ 93 */
75 - private String remark; 94 + private String email;
76 /** 95 /**
77 - * 负责人的用户编号  
78 - * 关联 AdminUserDO 的 id 字段 96 + * 地址
79 */ 97 */
80 - private Long ownerUserId; 98 + private String address;
81 /** 99 /**
82 * 所属行业 100 * 所属行业
  101 + *
83 * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY} 102 * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY}
84 */ 103 */
85 private Integer industryId; 104 private Integer industryId;
86 /** 105 /**
87 * 客户等级 106 * 客户等级
  107 + *
88 * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL} 108 * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL}
89 */ 109 */
90 private Integer level; 110 private Integer level;
91 /** 111 /**
92 * 客户来源 112 * 客户来源
  113 + *
93 * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} 114 * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE}
94 */ 115 */
95 private Integer source; 116 private Integer source;
96 /** 117 /**
97 - * 网址  
98 - */  
99 - private String website;  
100 - /**  
101 - * QQ  
102 - */  
103 - private String qq;  
104 - /**  
105 - * wechat  
106 - */  
107 - private String wechat;  
108 - /**  
109 - * email  
110 - */  
111 - private String email;  
112 - /**  
113 * 客户描述 118 * 客户描述
114 */ 119 */
115 private String description; 120 private String description;
  121 + /**
  122 + * 备注
  123 + */
  124 + private String remark;
  125 +
116 } 126 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java
@@ -9,8 +9,6 @@ import lombok.*; @@ -9,8 +9,6 @@ import lombok.*;
9 9
10 import java.time.LocalDateTime; 10 import java.time.LocalDateTime;
11 11
12 -// TODO 芋艿:调整下字段  
13 -  
14 /** 12 /**
15 * CRM 客户 DO 13 * CRM 客户 DO
16 * 14 *
@@ -35,36 +33,44 @@ public class CrmCustomerDO extends BaseDO { @@ -35,36 +33,44 @@ public class CrmCustomerDO extends BaseDO {
35 * 客户名称 33 * 客户名称
36 */ 34 */
37 private String name; 35 private String name;
  36 +
38 /** 37 /**
39 * 跟进状态 38 * 跟进状态
40 */ 39 */
41 private Boolean followUpStatus; 40 private Boolean followUpStatus;
42 /** 41 /**
43 - * 锁定状态 42 + * 最后跟进时间
44 */ 43 */
45 - private Boolean lockStatus; 44 + private LocalDateTime contactLastTime;
46 /** 45 /**
47 - * 成交状态 46 + * 最后跟进内容
48 */ 47 */
49 - private Boolean dealStatus; 48 + private String contactLastContent;
50 /** 49 /**
51 - * 所属行业  
52 - *  
53 - * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY} 50 + * 下次联系时间
54 */ 51 */
55 - private Integer industryId; 52 + private LocalDateTime contactNextTime;
  53 +
56 /** 54 /**
57 - * 客户等级 55 + * 负责人的用户编号
58 * 56 *
59 - * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL} 57 + * 关联 AdminUserDO 的 id 字段
60 */ 58 */
61 - private Integer level; 59 + private Long ownerUserId;
62 /** 60 /**
63 - * 客户来源  
64 - *  
65 - * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} 61 + * 最后接收时间
66 */ 62 */
67 - private Integer source; 63 + private LocalDateTime receiveTime;
  64 +
  65 + /**
  66 + * 锁定状态
  67 + */
  68 + private Boolean lockStatus;
  69 + /**
  70 + * 成交状态
  71 + */
  72 + private Boolean dealStatus;
  73 +
68 /** 74 /**
69 * 手机 75 * 手机
70 */ 76 */
@@ -90,20 +96,6 @@ public class CrmCustomerDO extends BaseDO { @@ -90,20 +96,6 @@ public class CrmCustomerDO extends BaseDO {
90 */ 96 */
91 private String email; 97 private String email;
92 /** 98 /**
93 - * 客户描述  
94 - */  
95 - private String description;  
96 - /**  
97 - * 备注  
98 - */  
99 - private String remark;  
100 - /**  
101 - * 负责人的用户编号  
102 - *  
103 - * 关联 AdminUserDO 的 id 字段  
104 - */  
105 - private Long ownerUserId;  
106 - /**  
107 * 所在地 99 * 所在地
108 * 100 *
109 * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段 101 * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段
@@ -113,23 +105,31 @@ public class CrmCustomerDO extends BaseDO { @@ -113,23 +105,31 @@ public class CrmCustomerDO extends BaseDO {
113 * 详细地址 105 * 详细地址
114 */ 106 */
115 private String detailAddress; 107 private String detailAddress;
116 -  
117 /** 108 /**
118 - * 最后接收时间 109 + * 所属行业
  110 + *
  111 + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY}
119 */ 112 */
120 - private LocalDateTime receiveTime; 113 + private Integer industryId;
121 /** 114 /**
122 - * 最后跟进时间 115 + * 客户等级
  116 + *
  117 + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL}
123 */ 118 */
124 - private LocalDateTime contactLastTime;  
125 - 119 + private Integer level;
126 /** 120 /**
127 - * 最后跟进内容 121 + * 客户来源
  122 + *
  123 + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE}
128 */ 124 */
129 - private String contactLastContent; 125 + private Integer source;
130 /** 126 /**
131 - * 下次联系时间 127 + * 客户描述
132 */ 128 */
133 - private LocalDateTime contactNextTime; 129 + private String description;
  130 + /**
  131 + * 备注
  132 + */
  133 + private String remark;
134 134
135 } 135 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java
@@ -55,17 +55,16 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; { @@ -55,17 +55,16 @@ public interface CrmClueMapper extends BaseMapperX&lt;CrmClueDO&gt; {
55 return selectJoinList(CrmClueDO.class, query); 55 return selectJoinList(CrmClueDO.class, query);
56 } 56 }
57 57
  58 + // TODO @dhb52:db 统一都是 select 关键字;
58 default Long getFollowLeadsCount(Long userId) { 59 default Long getFollowLeadsCount(Long userId) {
59 MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>(); 60 MPJLambdaWrapperX<CrmClueDO> query = new MPJLambdaWrapperX<>();
60 -  
61 - // 我负责的, 非公海 61 + // 我负责的 + 非公海
62 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), 62 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(),
63 CrmClueDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); 63 CrmClueDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
64 -  
65 - // 未跟进, 未转化 64 + // 未跟进 + 未转化 TODO @dhb52:是不是 eq 会更好哈;mysql 不等于,对索引不友好
66 query.ne(CrmClueDO::getFollowUpStatus, true) 65 query.ne(CrmClueDO::getFollowUpStatus, true)
67 .ne(CrmClueDO::getTransformStatus, true); 66 .ne(CrmClueDO::getTransformStatus, true);
68 -  
69 return selectCount(query); 67 return selectCount(query);
70 } 68 }
  69 +
71 } 70 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
@@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
7 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; 7 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
8 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; 8 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
9 -import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;  
10 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; 9 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
11 import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; 10 import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum;
12 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 11 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
@@ -89,33 +88,31 @@ public interface CrmContractMapper extends BaseMapperX&lt;CrmContractDO&gt; { @@ -89,33 +88,31 @@ public interface CrmContractMapper extends BaseMapperX&lt;CrmContractDO&gt; {
89 return selectCount(CrmContractDO::getBusinessId, businessId); 88 return selectCount(CrmContractDO::getBusinessId, businessId);
90 } 89 }
91 90
  91 + // TODO @dhb52:db 统一都是 select 关键字;
92 default Long getCheckContractCount(Long userId) { 92 default Long getCheckContractCount(Long userId) {
93 MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>(); 93 MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>();
94 -  
95 - // 我负责的, 非公海 94 + // 我负责的 + 非公海
96 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), 95 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(),
97 CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); 96 CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
98 -  
99 // 未提交 or 审核不通过 97 // 未提交 or 审核不通过
100 query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus()); 98 query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus());
101 -  
102 return selectCount(query); 99 return selectCount(query);
103 } 100 }
104 101
  102 + // TODO @dhb52:db 统一都是 select 关键字;
105 default Long getEndContractCount(Long userId) { 103 default Long getEndContractCount(Long userId) {
106 MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>(); 104 MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>();
107 -  
108 - // 我负责的, 非公海 105 + // 我负责的 + 非公海
109 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), 106 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(),
110 CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); 107 CrmContractDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
111 -  
112 // 即将到期 108 // 即将到期
113 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); 109 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
114 LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); 110 LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());
  111 + // TODO: @芋艿 需要配置 提前提醒天数
115 int REMIND_DAYS = 20; 112 int REMIND_DAYS = 20;
116 query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) 113 query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus())
117 .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); 114 .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS));
118 -  
119 return selectCount(query); 115 return selectCount(query);
120 } 116 }
  117 +
121 } 118 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
@@ -99,8 +99,7 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; { @@ -99,8 +99,7 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
99 99
100 // backlog 查询 100 // backlog 查询
101 if (ObjUtil.isNotNull(pageReqVO.getContactStatus())) { 101 if (ObjUtil.isNotNull(pageReqVO.getContactStatus())) {
102 - Assert.isNull(pageReqVO.getPool(), "[是否为公海数据]必须是null");  
103 - 102 + Assert.isNull(pageReqVO.getPool(), "pool 必须是 null");
104 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); 103 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
105 LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); 104 LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());
106 if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_TODAY)) { // 今天需联系 105 if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_TODAY)) { // 今天需联系
@@ -113,7 +112,6 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; { @@ -113,7 +112,6 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
113 throw new IllegalArgumentException("未知联系状态:" + pageReqVO.getContactStatus()); 112 throw new IllegalArgumentException("未知联系状态:" + pageReqVO.getContactStatus());
114 } 113 }
115 } 114 }
116 -  
117 return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); 115 return selectJoinPage(pageReqVO, CrmCustomerDO.class, query);
118 } 116 }
119 117
@@ -150,31 +148,28 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; { @@ -150,31 +148,28 @@ public interface CrmCustomerMapper extends BaseMapperX&lt;CrmCustomerDO&gt; {
150 return selectCount(query); 148 return selectCount(query);
151 } 149 }
152 150
  151 + // TODO @dhb52:db 统一都是 select 关键字;
153 default Long getTodayCustomerCount(Long userId) { 152 default Long getTodayCustomerCount(Long userId) {
154 MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); 153 MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
155 -  
156 - // 我负责的, 非公海 154 + // 我负责的 + 非公海
157 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), 155 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
158 CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); 156 CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
159 -  
160 // 今天需联系 157 // 今天需联系
161 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); 158 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
162 LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); 159 LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());
163 query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); 160 query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday);
164 -  
165 return selectCount(query); 161 return selectCount(query);
166 } 162 }
167 163
  164 + // TODO @dhb52:db 统一都是 select 关键字;
168 default Long getFollowCustomerCount(Long userId) { 165 default Long getFollowCustomerCount(Long userId) {
169 MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>(); 166 MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
170 -  
171 - // 我负责的, 非公海 167 + // 我负责的 + 非公海
172 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), 168 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
173 CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); 169 CrmCustomerDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
174 -  
175 - // 未跟进 170 + // 未跟进 TODO @dhb52:是不是 eq 会更好哈;mysql 不等于,对索引不友好
176 query.ne(CrmClueDO::getFollowUpStatus, true); 171 query.ne(CrmClueDO::getFollowUpStatus, true);
177 -  
178 return selectCount(query); 172 return selectCount(query);
179 } 173 }
  174 +
180 } 175 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
@@ -62,16 +62,14 @@ public interface CrmReceivableMapper extends BaseMapperX&lt;CrmReceivableDO&gt; { @@ -62,16 +62,14 @@ public interface CrmReceivableMapper extends BaseMapperX&lt;CrmReceivableDO&gt; {
62 return selectJoinList(CrmReceivableDO.class, query); 62 return selectJoinList(CrmReceivableDO.class, query);
63 } 63 }
64 64
  65 + // TODO @dhb52:db 统一都是 select 关键字;
65 default Long getCheckReceivablesCount(Long userId) { 66 default Long getCheckReceivablesCount(Long userId) {
66 MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>(); 67 MPJLambdaWrapperX<CrmReceivableDO> query = new MPJLambdaWrapperX<>();
67 -  
68 - // 我负责的, 非公海 68 + // 我负责的 + 非公海
69 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), 69 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(),
70 CrmReceivableDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); 70 CrmReceivableDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
71 -  
72 // 未提交 or 审核不通过 71 // 未提交 or 审核不通过
73 query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus()); 72 query.in(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.REJECT.getStatus());
74 -  
75 return selectCount(query); 73 return selectCount(query);
76 } 74 }
77 75
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java
@@ -79,19 +79,18 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO @@ -79,19 +79,18 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO
79 return selectJoinList(CrmReceivablePlanDO.class, query); 79 return selectJoinList(CrmReceivablePlanDO.class, query);
80 } 80 }
81 81
  82 + // TODO @dhb52:db 统一都是 select 关键字;
82 default Long getRemindReceivablePlanCount(Long userId) { 83 default Long getRemindReceivablePlanCount(Long userId) {
83 MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>(); 84 MPJLambdaWrapperX<CrmReceivablePlanDO> query = new MPJLambdaWrapperX<>();
84 -  
85 - // 我负责的, 非公海 85 + // 我负责的 + 非公海
86 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), 86 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(),
87 CrmReceivablePlanDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE); 87 CrmReceivablePlanDO::getId, userId, CrmSceneTypeEnum.OWNER.getType(), Boolean.FALSE);
88 -  
89 - // 待回款 88 + // 待回款 TODO @dhb52:to_days(return_time) <= to_days(now())+ remind_days 看看怎么改成,不用数据库自己去计算这样的时间;
90 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); 89 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
91 query.isNull(CrmReceivablePlanDO::getReceivableId) 90 query.isNull(CrmReceivablePlanDO::getReceivableId)
92 .gt(CrmReceivablePlanDO::getReturnTime, beginOfToday) 91 .gt(CrmReceivablePlanDO::getReturnTime, beginOfToday)
93 .apply("to_days(return_time) <= to_days(now())+ remind_days"); 92 .apply("to_days(return_time) <= to_days(now())+ remind_days");
94 -  
95 return selectCount(query); 93 return selectCount(query);
96 } 94 }
  95 +
97 } 96 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
@@ -179,4 +179,5 @@ public interface CrmCustomerService { @@ -179,4 +179,5 @@ public interface CrmCustomerService {
179 * @return 提醒数量 179 * @return 提醒数量
180 */ 180 */
181 Long getFollowCustomerCount(Long userId); 181 Long getFollowCustomerCount(Long userId);
  182 +
182 } 183 }