Commit 30fce2911f307fc1ef66b40a740cc49df9157c1b
Merge remote-tracking branch 'origin/develop' into develop
# Conflicts: # yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java
Showing
112 changed files
with
1631 additions
and
1003 deletions
Too many changes.
To preserve performance only 100 of 112 files are displayed.
sql/mysql/optinal/product_statistics.sql deleted
| 1 | -CREATE TABLE product_statistics | |
| 2 | -( | |
| 3 | - id bigint AUTO_INCREMENT COMMENT '编号,主键自增' PRIMARY KEY, | |
| 4 | - time date NOT NULL COMMENT '统计日期', | |
| 5 | - spu_id bigint NOT NULL COMMENT '商品SPU编号', | |
| 6 | - browse_count int DEFAULT 0 NOT NULL COMMENT '浏览量', | |
| 7 | - browse_user_count int DEFAULT 0 NOT NULL COMMENT '访客量', | |
| 8 | - favorite_count int DEFAULT 0 NOT NULL COMMENT '收藏数量', | |
| 9 | - cart_count int DEFAULT 0 NOT NULL COMMENT '加购数量', | |
| 10 | - order_count int DEFAULT 0 NOT NULL COMMENT '下单件数', | |
| 11 | - order_pay_count int DEFAULT 0 NOT NULL COMMENT '支付件数', | |
| 12 | - order_pay_price int DEFAULT 0 NOT NULL COMMENT '支付金额,单位:分', | |
| 13 | - after_sale_count int DEFAULT 0 NOT NULL COMMENT '退款件数', | |
| 14 | - after_sale_refund_price int DEFAULT 0 NOT NULL COMMENT '退款金额,单位:分', | |
| 15 | - browse_convert_percent int DEFAULT 0 NOT NULL COMMENT '访客支付转化率(百分比)', | |
| 16 | - creator varchar(64) DEFAULT '' NULL COMMENT '创建者', | |
| 17 | - create_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '创建时间', | |
| 18 | - updater varchar(64) DEFAULT '' NULL COMMENT '更新者', | |
| 19 | - update_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', | |
| 20 | - deleted bit DEFAULT b'0' NOT NULL COMMENT '是否删除', | |
| 21 | - tenant_id bigint DEFAULT 0 NOT NULL COMMENT '租户编号' | |
| 22 | -) | |
| 23 | - COMMENT '商品统计表'; | |
| 24 | - | |
| 25 | -CREATE INDEX idx_time | |
| 26 | - ON product_statistics (time); | |
| 27 | - | |
| 28 | -CREATE INDEX idx_spu_id | |
| 29 | - ON product_statistics (spu_id); | |
| 30 | - | |
| 31 | -INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES ('商品统计', '', 2, 6, 2358, 'product', 'fa:product-hunt', 'statistics/product/index', 'ProductStatistics', 0, true, true, true, '', '2023-12-15 18:54:28', '', '2023-12-15 18:54:33', false); | |
| 32 | -SELECT @parentId1 := LAST_INSERT_ID(); | |
| 33 | -INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES ('商品统计查询', 'statistics:product:query', 3, 1, @parentId, '', '', '', null, 0, true, true, true, '', '2023-09-30 03:22:40', '', '2023-09-30 03:22:40', false); | |
| 34 | -INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES ('商品统计导出', 'statistics:product:export', 3, 2, @parentId, '', '', '', null, 0, true, true, true, '', '2023-09-30 03:22:40', '', '2023-09-30 03:22:40', false); |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
| ... | ... | @@ -6,6 +6,7 @@ import java.time.Duration; |
| 6 | 6 | import java.time.LocalDate; |
| 7 | 7 | import java.time.LocalDateTime; |
| 8 | 8 | import java.time.LocalTime; |
| 9 | +import java.time.temporal.ChronoUnit; | |
| 9 | 10 | import java.time.temporal.TemporalAdjusters; |
| 10 | 11 | |
| 11 | 12 | /** |
| ... | ... | @@ -121,4 +122,9 @@ public class LocalDateTimeUtils { |
| 121 | 122 | return date.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX); |
| 122 | 123 | } |
| 123 | 124 | |
| 125 | + // TODO @puhui999:加下注释哈; | |
| 126 | + public static Long between(LocalDateTime dateTime) { | |
| 127 | + return LocalDateTimeUtil.between(dateTime, LocalDateTime.now(), ChronoUnit.DAYS); | |
| 128 | + } | |
| 129 | + | |
| 124 | 130 | } | ... | ... |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/PageUtils.java
| 1 | 1 | package cn.iocoder.yudao.framework.common.util.object; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.hutool.core.lang.func.Func1; | |
| 5 | +import cn.hutool.core.lang.func.LambdaUtil; | |
| 6 | +import cn.hutool.core.util.ArrayUtil; | |
| 3 | 7 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; | |
| 9 | +import cn.iocoder.yudao.framework.common.pojo.SortingField; | |
| 10 | +import org.springframework.util.Assert; | |
| 11 | + | |
| 12 | +import java.util.List; | |
| 4 | 13 | |
| 5 | 14 | /** |
| 6 | 15 | * {@link cn.iocoder.yudao.framework.common.pojo.PageParam} 工具类 |
| ... | ... | @@ -9,8 +18,50 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 9 | 18 | */ |
| 10 | 19 | public class PageUtils { |
| 11 | 20 | |
| 21 | + private static final Object[] ORDER_TYPES = new String[]{SortingField.ORDER_ASC, SortingField.ORDER_DESC}; | |
| 22 | + | |
| 12 | 23 | public static int getStart(PageParam pageParam) { |
| 13 | 24 | return (pageParam.getPageNo() - 1) * pageParam.getPageSize(); |
| 14 | 25 | } |
| 15 | 26 | |
| 27 | + /** | |
| 28 | + * 构建排序字段(默认倒序) | |
| 29 | + * | |
| 30 | + * @param func 排序字段的 Lambda 表达式 | |
| 31 | + * @param <T> 排序字段所属的类型 | |
| 32 | + * @return 排序字段 | |
| 33 | + */ | |
| 34 | + public static <T> SortingField buildSortingField(Func1<T, ?> func) { | |
| 35 | + return buildSortingField(func, SortingField.ORDER_DESC); | |
| 36 | + } | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * 构建排序字段 | |
| 40 | + * | |
| 41 | + * @param func 排序字段的 Lambda 表达式 | |
| 42 | + * @param order 排序类型 {@link SortingField#ORDER_ASC} {@link SortingField#ORDER_DESC} | |
| 43 | + * @param <T> 排序字段所属的类型 | |
| 44 | + * @return 排序字段 | |
| 45 | + */ | |
| 46 | + public static <T> SortingField buildSortingField(Func1<T, ?> func, String order) { | |
| 47 | + Assert.isTrue(ArrayUtil.contains(ORDER_TYPES, order), String.format("字段的排序类型只能是 %s/%s", ORDER_TYPES)); | |
| 48 | + | |
| 49 | + String fieldName = LambdaUtil.getFieldName(func); | |
| 50 | + return new SortingField(fieldName, order); | |
| 51 | + } | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 构建默认的排序字段 | |
| 55 | + * 如果排序字段为空,则设置排序字段;否则忽略 | |
| 56 | + * | |
| 57 | + * @param sortablePageParam 排序分页查询参数 | |
| 58 | + * @param func 排序字段的 Lambda 表达式 | |
| 59 | + * @param <T> 排序字段所属的类型 | |
| 60 | + */ | |
| 61 | + public static <T> void buildDefaultSortingField(SortablePageParam sortablePageParam, Func1<T, ?> func) { | |
| 62 | + if (sortablePageParam != null && CollUtil.isEmpty(sortablePageParam.getSortingFields())) { | |
| 63 | + sortablePageParam.setSortingFields(List.of(buildSortingField(func))); | |
| 64 | + } | |
| 65 | + } | |
| 66 | + | |
| 16 | 67 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java
| 1 | 1 | package cn.iocoder.yudao.framework.mybatis.core.util; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.collection.CollUtil; | |
| 4 | 3 | import cn.hutool.core.collection.CollectionUtil; |
| 5 | -import cn.hutool.core.lang.func.Func1; | |
| 6 | -import cn.hutool.core.lang.func.LambdaUtil; | |
| 7 | -import cn.hutool.core.util.ArrayUtil; | |
| 8 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 9 | -import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; | |
| 10 | 5 | import cn.iocoder.yudao.framework.common.pojo.SortingField; |
| 11 | 6 | import com.baomidou.mybatisplus.core.metadata.OrderItem; |
| 12 | 7 | import com.baomidou.mybatisplus.core.toolkit.StringPool; |
| ... | ... | @@ -16,7 +11,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| 16 | 11 | import net.sf.jsqlparser.expression.Alias; |
| 17 | 12 | import net.sf.jsqlparser.schema.Column; |
| 18 | 13 | import net.sf.jsqlparser.schema.Table; |
| 19 | -import org.springframework.util.Assert; | |
| 20 | 14 | |
| 21 | 15 | import java.util.ArrayList; |
| 22 | 16 | import java.util.Collection; |
| ... | ... | @@ -91,46 +85,4 @@ public class MyBatisUtils { |
| 91 | 85 | return new Column(tableName + StringPool.DOT + column); |
| 92 | 86 | } |
| 93 | 87 | |
| 94 | - | |
| 95 | - /** | |
| 96 | - * 构建排序字段(默认倒序) | |
| 97 | - * | |
| 98 | - * @param func 排序字段的 Lambda 表达式 | |
| 99 | - * @param <T> 排序字段所属的类型 | |
| 100 | - * @return 排序字段 | |
| 101 | - */ | |
| 102 | - public static <T> SortingField buildSortingField(Func1<T, ?> func) { | |
| 103 | - return buildSortingField(func, SortingField.ORDER_DESC); | |
| 104 | - } | |
| 105 | - | |
| 106 | - /** | |
| 107 | - * 构建排序字段 | |
| 108 | - * | |
| 109 | - * @param func 排序字段的 Lambda 表达式 | |
| 110 | - * @param order 排序类型 {@link SortingField#ORDER_ASC} {@link SortingField#ORDER_DESC} | |
| 111 | - * @param <T> 排序字段所属的类型 | |
| 112 | - * @return 排序字段 | |
| 113 | - */ | |
| 114 | - public static <T> SortingField buildSortingField(Func1<T, ?> func, String order) { | |
| 115 | - Object[] orderTypes = {SortingField.ORDER_ASC, SortingField.ORDER_DESC}; | |
| 116 | - Assert.isTrue(ArrayUtil.contains(orderTypes, order), String.format("字段的排序类型只能是%s/%s", orderTypes)); | |
| 117 | - | |
| 118 | - String fieldName = LambdaUtil.getFieldName(func); | |
| 119 | - return new SortingField(fieldName, order); | |
| 120 | - } | |
| 121 | - | |
| 122 | - /** | |
| 123 | - * 构建默认的排序字段 | |
| 124 | - * 如果排序字段为空,则设置排序字段;否则忽略 | |
| 125 | - * | |
| 126 | - * @param sortablePageParam 排序分页查询参数 | |
| 127 | - * @param func 排序字段的 Lambda 表达式 | |
| 128 | - * @param <T> 排序字段所属的类型 | |
| 129 | - */ | |
| 130 | - public static <T> void buildDefaultSortingField(SortablePageParam sortablePageParam, Func1<T, ?> func) { | |
| 131 | - if (sortablePageParam != null && CollUtil.isEmpty(sortablePageParam.getSortingFields())) { | |
| 132 | - sortablePageParam.setSortingFields(List.of(buildSortingField(func))); | |
| 133 | - } | |
| 134 | - } | |
| 135 | - | |
| 136 | 88 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogV2Configuration.java
| 1 | 1 | package cn.iocoder.yudao.framework.operatelog.config; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.framework.operatelog.core.service.ILogRecordServiceImpl; | |
| 3 | +import cn.iocoder.yudao.framework.operatelog.core.service.LogRecordServiceImpl; | |
| 4 | 4 | import com.mzt.logapi.service.ILogRecordService; |
| 5 | 5 | import com.mzt.logapi.starter.annotation.EnableLogRecord; |
| 6 | 6 | import lombok.extern.slf4j.Slf4j; |
| ... | ... | @@ -21,7 +21,7 @@ public class YudaoOperateLogV2Configuration { |
| 21 | 21 | @Bean |
| 22 | 22 | @Primary |
| 23 | 23 | public ILogRecordService iLogRecordServiceImpl() { |
| 24 | - return new ILogRecordServiceImpl(); | |
| 24 | + return new LogRecordServiceImpl(); | |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | 27 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/ILogRecordServiceImpl.java renamed to yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java
| ... | ... | @@ -2,7 +2,8 @@ package cn.iocoder.yudao.framework.operatelog.core.service; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; |
| 5 | -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; | |
| 5 | +import cn.iocoder.yudao.framework.security.core.LoginUser; | |
| 6 | +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | |
| 6 | 7 | import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; |
| 7 | 8 | import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; |
| 8 | 9 | import com.mzt.logapi.beans.LogRecord; |
| ... | ... | @@ -13,7 +14,6 @@ import lombok.extern.slf4j.Slf4j; |
| 13 | 14 | |
| 14 | 15 | import java.util.List; |
| 15 | 16 | |
| 16 | -// TODO @puhui999:LogRecordServiceImpl 改成这个名字哈 | |
| 17 | 17 | /** |
| 18 | 18 | * 操作日志 ILogRecordService 实现类 |
| 19 | 19 | * |
| ... | ... | @@ -22,7 +22,7 @@ import java.util.List; |
| 22 | 22 | * @author HUIHUI |
| 23 | 23 | */ |
| 24 | 24 | @Slf4j |
| 25 | -public class ILogRecordServiceImpl implements ILogRecordService { | |
| 25 | +public class LogRecordServiceImpl implements ILogRecordService { | |
| 26 | 26 | |
| 27 | 27 | @Resource |
| 28 | 28 | private OperateLogApi operateLogApi; |
| ... | ... | @@ -46,9 +46,13 @@ public class ILogRecordServiceImpl implements ILogRecordService { |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | 48 | private static void fillUserFields(OperateLogV2CreateReqDTO reqDTO) { |
| 49 | - // TODO @puhui999:使用 SecurityFrameworkUtils。因为要考虑,rpc、mq、job,它其实不是 web; | |
| 50 | - reqDTO.setUserId(WebFrameworkUtils.getLoginUserId()); | |
| 51 | - reqDTO.setUserType(WebFrameworkUtils.getLoginUserType()); | |
| 49 | + // 使用 SecurityFrameworkUtils。因为要考虑,rpc、mq、job,它其实不是 web; | |
| 50 | + LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); | |
| 51 | + if (loginUser == null) { | |
| 52 | + return; | |
| 53 | + } | |
| 54 | + reqDTO.setUserId(loginUser.getId()); | |
| 55 | + reqDTO.setUserType(loginUser.getUserType()); | |
| 52 | 56 | } |
| 53 | 57 | |
| 54 | 58 | public static void fillModuleFields(OperateLogV2CreateReqDTO reqDTO, LogRecord logRecord) { | ... | ... |
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
| ... | ... | @@ -24,6 +24,7 @@ public interface ErrorCodeConstants { |
| 24 | 24 | // ========== 联系人管理 1-020-003-000 ========== |
| 25 | 25 | ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); |
| 26 | 26 | ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode( 1_020_003_001, "联系人商机关联不存在"); |
| 27 | + ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode( 1_020_003_002, "联系人已关联合同,不能删除"); | |
| 27 | 28 | |
| 28 | 29 | // ========== 回款 1-020-004-000 ========== |
| 29 | 30 | ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); |
| ... | ... | @@ -40,7 +41,7 @@ public interface ErrorCodeConstants { |
| 40 | 41 | ErrorCode CUSTOMER_LOCKED_PUT_POOL_FAIL = new ErrorCode(1_020_006_005, "客户【{}】放入公海失败,原因:客户已锁定"); |
| 41 | 42 | ErrorCode CUSTOMER_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_006_006, "更新客户【{}】负责人失败, 原因:系统异常"); |
| 42 | 43 | ErrorCode CUSTOMER_LOCK_FAIL_IS_LOCK = new ErrorCode(1_020_006_007, "锁定客户失败,它已经处于锁定状态"); |
| 43 | - ErrorCode CUSTOMER_UNLOCK_FAIL_IS_UNLOCK = new ErrorCode(1_020_006_008, "锁定客户失败,它已经处于未锁定状态"); | |
| 44 | + ErrorCode CUSTOMER_UNLOCK_FAIL_IS_UNLOCK = new ErrorCode(1_020_006_008, "解锁客户失败,它已经处于未锁定状态"); | |
| 44 | 45 | ErrorCode CUSTOMER_LOCK_EXCEED_LIMIT = new ErrorCode(1_020_006_009, "锁定客户失败,超出锁定规则上限"); |
| 45 | 46 | ErrorCode CUSTOMER_OWNER_EXCEED_LIMIT = new ErrorCode(1_020_006_010, "操作失败,超出客户数拥有上限"); |
| 46 | 47 | ... | ... |
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java
| ... | ... | @@ -2,32 +2,86 @@ package cn.iocoder.yudao.module.crm.enums; |
| 2 | 2 | |
| 3 | 3 | /** |
| 4 | 4 | * CRM 操作日志枚举 |
| 5 | + * 目的:统一管理,也减少 Service 里各种“复杂”字符串 | |
| 5 | 6 | * |
| 6 | 7 | * @author HUIHUI |
| 7 | 8 | */ |
| 8 | 9 | public interface LogRecordConstants { |
| 9 | 10 | |
| 10 | - //======================= 客户模块类型 ======================= | |
| 11 | - // TODO puhui999: 确保模块命名方式为 module + 子模块名称的方式。统一定义模块名称是为了方便查询各自记录的操作日志,列如说:查询客户【张三的操作日志】就可以 module + bizId | |
| 12 | - String CRM_LEADS = "CRM 线索"; | |
| 13 | - String CRM_CUSTOMER = "CRM 客户"; | |
| 14 | - String CRM_CONTACT = "CRM 联系人"; | |
| 15 | - String CRM_BUSINESS = "CRM 商机"; | |
| 16 | - String CRM_CONTRACT = "CRM 合同"; | |
| 17 | - String CRM_PRODUCT = "CRM 产品"; | |
| 18 | - String CRM_RECEIVABLE = "CRM 回款"; | |
| 19 | - String CRM_RECEIVABLE_PLAN = "CRM 回款计划"; | |
| 11 | + // ======================= CRM_LEADS 线索 ======================= | |
| 20 | 12 | |
| 21 | - //======================= 客户转移操作日志 ======================= | |
| 13 | + String CRM_LEADS_TYPE = "CRM 线索"; | |
| 22 | 14 | |
| 23 | - String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; | |
| 15 | + // ======================= CRM_CUSTOMER 客户 ======================= | |
| 24 | 16 | |
| 25 | - // TODO @puhui999:这里格式是不是可以这样;目的是:统一管理,也减少 Service 里各种“复杂”字符串 | |
| 26 | - // ======================= Customer 客户 ======================= | |
| 27 | - String CUSTOMER_TYPE = "CRM 客户"; | |
| 28 | - String CUSTOMER_CREATE_SUB_TYPE = "创建客户"; | |
| 29 | - String CUSTOMER_CREATE_SUCCESS = "更新了客户{_DIFF{#updateReqVO}}"; | |
| 17 | + String CRM_CUSTOMER_TYPE = "CRM 客户"; | |
| 18 | + String CRM_CUSTOMER_CREATE_SUB_TYPE = "创建客户"; | |
| 19 | + String CRM_CUSTOMER_CREATE_SUCCESS = "创建了客户{{#customer.name}}"; | |
| 20 | + String CRM_CUSTOMER_UPDATE_SUB_TYPE = "更新客户"; | |
| 21 | + String CRM_CUSTOMER_UPDATE_SUCCESS = "更新了客户【{{#customerName}}】: {_DIFF{#updateReqVO}}"; | |
| 22 | + String CRM_CUSTOMER_DELETE_SUB_TYPE = "删除客户"; | |
| 23 | + String CRM_CUSTOMER_DELETE_SUCCESS = "删除了客户【{{#customerName}}】"; | |
| 24 | + String CRM_CUSTOMER_TRANSFER_SUB_TYPE = "转移客户"; | |
| 25 | + String CRM_CUSTOMER_TRANSFER_SUCCESS = "将客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; | |
| 26 | + String CRM_CUSTOMER_LOCK_SUB_TYPE = "{{#crmCustomer.lockStatus ? '解锁客户' : '锁定客户'}}"; | |
| 27 | + String CRM_CUSTOMER_LOCK_SUCCESS = "{{#crmCustomer.lockStatus ? '将客户【' + #crmCustomer.name + '】解锁' : '将客户【' + #crmCustomer.name + '】锁定'}}"; | |
| 28 | + String CRM_CUSTOMER_POOL_SUB_TYPE = "客户放入公海"; | |
| 29 | + String CRM_CUSTOMER_POOL_SUCCESS = "将客户【{{#customerName}}】放入了公海"; | |
| 30 | + String CRM_CUSTOMER_RECEIVE_SUB_TYPE = "{{#ownerUserName != null ? '分配客户' : '领取客户'}}"; | |
| 31 | + String CRM_CUSTOMER_RECEIVE_SUCCESS = "{{#ownerUserName != null ? '将客户【' + #customer.name + '】分配给【' + #ownerUserName + '】' : '领取客户【' + #customer.name + '】'}}"; | |
| 30 | 32 | |
| 31 | - String CUSTOMER_UPDATE_SUB_TYPE = "更新客户"; | |
| 33 | + // ======================= CRM_CUSTOMER_LIMIT_CONFIG 客户限制配置 ======================= | |
| 34 | + | |
| 35 | + String CRM_CUSTOMER_LIMIT_CONFIG_TYPE = "CRM 客户限制配置"; | |
| 36 | + String CRM_CUSTOMER_LIMIT_CONFIG_CREATE_SUB_TYPE = "创建客户限制配置"; | |
| 37 | + String CRM_CUSTOMER_LIMIT_CONFIG_CREATE_SUCCESS = "创建了【{{#limitType}}】类型的客户限制配置"; | |
| 38 | + String CRM_CUSTOMER_LIMIT_CONFIG_UPDATE_SUB_TYPE = "更新客户限制配置"; | |
| 39 | + String CRM_CUSTOMER_LIMIT_CONFIG_UPDATE_SUCCESS = "更新了客户限制配置: {_DIFF{#updateReqVO}}"; | |
| 40 | + String CRM_CUSTOMER_LIMIT_CONFIG_DELETE_SUB_TYPE = "删除客户限制配置"; | |
| 41 | + String CRM_CUSTOMER_LIMIT_CONFIG_DELETE_SUCCESS = "删除了【{{#limitType}}】类型的客户限制配置"; | |
| 42 | + | |
| 43 | + // ======================= CRM_CUSTOMER_POOL_CONFIG 客户公海规则 ======================= | |
| 44 | + | |
| 45 | + String CRM_CUSTOMER_POOL_CONFIG_TYPE = "CRM 客户公海规则"; | |
| 46 | + String CRM_CUSTOMER_POOL_CONFIG_SUB_TYPE = "{{#isPoolConfigUpdate ? '更新客户公海规则' : '创建客户公海规则'}}"; | |
| 47 | + String CRM_CUSTOMER_POOL_CONFIG_SUCCESS = "{{#isPoolConfigUpdate ? '更新了客户公海规则' : '创建了客户公海规则'}}"; | |
| 48 | + | |
| 49 | + // ======================= CRM_CONTACT 联系人 ======================= | |
| 50 | + | |
| 51 | + String CRM_CONTACT_TYPE = "CRM 联系人"; | |
| 52 | + | |
| 53 | + // ======================= CRM_BUSINESS 商机 ======================= | |
| 54 | + | |
| 55 | + String CRM_BUSINESS_TYPE = "CRM 商机"; | |
| 56 | + | |
| 57 | + // ======================= CRM_CONTRACT 合同 ======================= | |
| 58 | + | |
| 59 | + String CRM_CONTRACT_TYPE = "CRM 合同"; | |
| 60 | + | |
| 61 | + // ======================= CRM_PRODUCT 产品 ======================= | |
| 62 | + | |
| 63 | + // TODO @hao:可以把 CRM 产品、和 CRM 产品分类分开哈,量程两个 type; | |
| 64 | + String CRM_PRODUCT_TYPE = "CRM 产品"; | |
| 65 | + String CRM_PRODUCT_CREATE_SUB_TYPE = "创建产品"; | |
| 66 | + String CRM_PRODUCT_CREATE_SUCCESS = "创建了产品【{{#createReqVO.name}}】"; | |
| 67 | + String CRM_PRODUCT_UPDATE_SUB_TYPE = "更新产品"; | |
| 68 | + String CRM_PRODUCT_UPDATE_SUCCESS = "更新了产品【{{#updateReqVO.name}}】: {_DIFF{#updateReqVO}}"; | |
| 69 | + String CRM_PRODUCT_DELETE_SUB_TYPE = "删除产品"; | |
| 70 | + String CRM_PRODUCT_DELETE_SUCCESS = "删除了产品【{{#product.name}}】"; | |
| 71 | + String CRM_PRODUCT_CATEGORY_TYPE = "CRM 产品分类"; | |
| 72 | + String CRM_PRODUCT_CATEGORY_CREATE_SUB_TYPE = "创建产品分类"; | |
| 73 | + String CRM_PRODUCT_CATEGORY_CREATE_SUCCESS = "创建了产品分类【{{#createReqVO.name}}】"; | |
| 74 | + String CRM_PRODUCT_CATEGORY_UPDATE_SUB_TYPE = "更新产品分类"; | |
| 75 | + String CRM_PRODUCT_CATEGORY_UPDATE_SUCCESS = "更新了产品分类【{{#updateReqVO.name}}】: {_DIFF{#updateReqVO}}"; | |
| 76 | + String CRM_PRODUCT_CATEGORY_DELETE_SUB_TYPE = "删除产品分类"; | |
| 77 | + String CRM_PRODUCT_CATEGORY_DELETE_SUCCESS = "删除了产品分类【{{#productCategory.name}}】"; | |
| 78 | + | |
| 79 | + // ======================= CRM_RECEIVABLE 回款 ======================= | |
| 80 | + | |
| 81 | + String CRM_RECEIVABLE_TYPE = "CRM 回款"; | |
| 82 | + | |
| 83 | + // ======================= CRM_RECEIVABLE_PLAN 回款计划 ======================= | |
| 84 | + | |
| 85 | + String CRM_RECEIVABLE_PLAN_TYPE = "CRM 回款计划"; | |
| 32 | 86 | |
| 33 | 87 | } | ... | ... |
yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.enums.customer; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.hutool.core.util.ObjUtil; | |
| 3 | 5 | import cn.iocoder.yudao.framework.common.core.IntArrayValuable; |
| 4 | 6 | import lombok.AllArgsConstructor; |
| 5 | 7 | import lombok.Getter; |
| ... | ... | @@ -36,6 +38,12 @@ public enum CrmCustomerLimitConfigTypeEnum implements IntArrayValuable { |
| 36 | 38 | */ |
| 37 | 39 | private final String name; |
| 38 | 40 | |
| 41 | + public static String getNameByType(Integer type) { | |
| 42 | + CrmCustomerLimitConfigTypeEnum typeEnum = CollUtil.findOne(CollUtil.newArrayList(CrmCustomerLimitConfigTypeEnum.values()), | |
| 43 | + item -> ObjUtil.equal(item.type, type)); | |
| 44 | + return typeEnum == null ? null : typeEnum.getName(); | |
| 45 | + } | |
| 46 | + | |
| 39 | 47 | @Override |
| 40 | 48 | public int[] array() { |
| 41 | 49 | return ARRAYS; | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.controller.admin.business; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | -import cn.hutool.core.lang.Assert; | |
| 5 | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 6 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | 6 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| ... | ... | @@ -29,11 +28,13 @@ import org.springframework.web.bind.annotation.*; |
| 29 | 28 | import java.io.IOException; |
| 30 | 29 | import java.util.List; |
| 31 | 30 | |
| 31 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 32 | 32 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 33 | 33 | import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; |
| 34 | 34 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 35 | 35 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 36 | 36 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 37 | +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; | |
| 37 | 38 | |
| 38 | 39 | @Tag(name = "管理后台 - 商机") |
| 39 | 40 | @RestController |
| ... | ... | @@ -95,7 +96,9 @@ public class CrmBusinessController { |
| 95 | 96 | @GetMapping("/page-by-customer") |
| 96 | 97 | @Operation(summary = "获得商机分页,基于指定客户") |
| 97 | 98 | public CommonResult<PageResult<CrmBusinessRespVO>> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) { |
| 98 | - Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); | |
| 99 | + if (pageReqVO.getCustomerId() == null) { | |
| 100 | + throw exception(CUSTOMER_NOT_EXISTS); | |
| 101 | + } | |
| 99 | 102 | PageResult<CrmBusinessDO> pageResult = businessService.getBusinessPageByCustomerId(pageReqVO); |
| 100 | 103 | return success(buildBusinessDetailPageResult(pageResult)); |
| 101 | 104 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java
| ... | ... | @@ -38,14 +38,14 @@ public class CrmClueController { |
| 38 | 38 | @PostMapping("/create") |
| 39 | 39 | @Operation(summary = "创建线索") |
| 40 | 40 | @PreAuthorize("@ss.hasPermission('crm:clue:create')") |
| 41 | - public CommonResult<Long> createClue(@Valid @RequestBody CrmClueCreateReqVO createReqVO) { | |
| 41 | + public CommonResult<Long> createClue(@Valid @RequestBody CrmClueSaveReqVO createReqVO) { | |
| 42 | 42 | return success(clueService.createClue(createReqVO)); |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | 45 | @PutMapping("/update") |
| 46 | 46 | @Operation(summary = "更新线索") |
| 47 | 47 | @PreAuthorize("@ss.hasPermission('crm:clue:update')") |
| 48 | - public CommonResult<Boolean> updateClue(@Valid @RequestBody CrmClueUpdateReqVO updateReqVO) { | |
| 48 | + public CommonResult<Boolean> updateClue(@Valid @RequestBody CrmClueSaveReqVO updateReqVO) { | |
| 49 | 49 | clueService.updateClue(updateReqVO); |
| 50 | 50 | return success(true); |
| 51 | 51 | } |
| ... | ... | @@ -96,4 +96,13 @@ public class CrmClueController { |
| 96 | 96 | return success(true); |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | + @PostMapping("/transform") | |
| 100 | + @Operation(summary = "线索转化为客户") | |
| 101 | + @PreAuthorize("@ss.hasPermission('crm:clue:update')") | |
| 102 | + // TODO @min:方法改成 translateCustomer | |
| 103 | + public CommonResult<Boolean> translate(@Valid @RequestBody CrmClueTransformReqVO reqVO) { | |
| 104 | + clueService.translate(reqVO, getLoginUserId()); | |
| 105 | + return success(Boolean.TRUE); | |
| 106 | + } | |
| 107 | + | |
| 99 | 108 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueBaseVO.java
| ... | ... | @@ -3,11 +3,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.validation.Mobile; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.validation.Telephone; |
| 5 | 5 | import io.swagger.v3.oas.annotations.media.Schema; |
| 6 | +import jakarta.validation.constraints.NotEmpty; | |
| 6 | 7 | import lombok.Data; |
| 7 | 8 | import org.springframework.format.annotation.DateTimeFormat; |
| 8 | 9 | |
| 9 | -import jakarta.validation.constraints.NotEmpty; | |
| 10 | -import jakarta.validation.constraints.NotNull; | |
| 11 | 10 | import java.time.LocalDateTime; |
| 12 | 11 | |
| 13 | 12 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| ... | ... | @@ -24,7 +23,6 @@ public class CrmClueBaseVO { |
| 24 | 23 | private String name; |
| 25 | 24 | |
| 26 | 25 | @Schema(description = "客户 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "520") |
| 27 | - @NotNull(message = "客户不能为空") | |
| 28 | 26 | private Long customerId; |
| 29 | 27 | |
| 30 | 28 | @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") |
| ... | ... | @@ -46,6 +44,9 @@ public class CrmClueBaseVO { |
| 46 | 44 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 47 | 45 | private LocalDateTime contactLastTime; |
| 48 | 46 | |
| 47 | + @Schema(description = "负责人编号") | |
| 48 | + private Long ownerUserId; | |
| 49 | + | |
| 49 | 50 | @Schema(description = "备注", example = "随便") |
| 50 | 51 | private String remark; |
| 51 | 52 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueCreateReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; | |
| 2 | - | |
| 3 | -import lombok.*; | |
| 4 | -import java.util.*; | |
| 5 | -import io.swagger.v3.oas.annotations.media.Schema; | |
| 6 | -import jakarta.validation.constraints.*; | |
| 7 | - | |
| 8 | -@Schema(description = "管理后台 - 线索创建 Request VO") | |
| 9 | -@Data | |
| 10 | -@EqualsAndHashCode(callSuper = true) | |
| 11 | -@ToString(callSuper = true) | |
| 12 | -public class CrmClueCreateReqVO extends CrmClueBaseVO { | |
| 13 | - | |
| 14 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.validation.Mobile; | |
| 4 | +import cn.iocoder.yudao.framework.common.validation.Telephone; | |
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 6 | +import jakarta.validation.constraints.NotEmpty; | |
| 7 | +import lombok.Data; | |
| 8 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 9 | + | |
| 10 | +import java.time.LocalDateTime; | |
| 11 | + | |
| 12 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 13 | + | |
| 14 | +@Schema(description = "管理后台 - CRM 线索 创建/更新 Request VO") | |
| 15 | +@Data | |
| 16 | +public class CrmClueSaveReqVO { | |
| 17 | + | |
| 18 | + @Schema(description = "编号", example = "10969") | |
| 19 | + private Long id; | |
| 20 | + | |
| 21 | + @Schema(description = "线索名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "线索xxx") | |
| 22 | + @NotEmpty(message = "线索名称不能为空") | |
| 23 | + private String name; | |
| 24 | + | |
| 25 | + // TODO @min:是不是不传递 customerId? | |
| 26 | + @Schema(description = "客户 id", example = "520") | |
| 27 | + private Long customerId; | |
| 28 | + | |
| 29 | + @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") | |
| 30 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 31 | + private LocalDateTime contactNextTime; | |
| 32 | + | |
| 33 | + @Schema(description = "电话", example = "18000000000") | |
| 34 | + @Telephone | |
| 35 | + private String telephone; | |
| 36 | + | |
| 37 | + @Schema(description = "手机号", example = "18000000000") | |
| 38 | + @Mobile | |
| 39 | + private String mobile; | |
| 40 | + | |
| 41 | + @Schema(description = "地址", example = "北京市海淀区") | |
| 42 | + private String address; | |
| 43 | + | |
| 44 | + @Schema(description = "最后跟进时间") | |
| 45 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 46 | + private LocalDateTime contactLastTime; | |
| 47 | + | |
| 48 | + @Schema(description = "负责人编号", example = "2048") | |
| 49 | + private Long ownerUserId; | |
| 50 | + | |
| 51 | + @Schema(description = "备注", example = "随便") | |
| 52 | + private String remark; | |
| 53 | + | |
| 54 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransformReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import jakarta.validation.constraints.NotEmpty; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import java.util.Set; | |
| 8 | + | |
| 9 | +@Schema(description = "管理后台 - 线索转化为客户 Request VO") | |
| 10 | +@Data | |
| 11 | +public class CrmClueTransformReqVO { | |
| 12 | + | |
| 13 | + @Schema(description = "线索编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1024, 1025]") | |
| 14 | + @NotEmpty(message = "线索编号不能为空") Set<Long> ids; // TODO @min:应该空行噢 | |
| 15 | + | |
| 16 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueUpdateReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.clue.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 = "管理后台 - 线索更新 Request VO") | |
| 11 | -@Data | |
| 12 | -@EqualsAndHashCode(callSuper = true) | |
| 13 | -@ToString(callSuper = true) | |
| 14 | -public class CrmClueUpdateReqVO extends CrmClueBaseVO { | |
| 15 | - | |
| 16 | - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10969") | |
| 17 | - @NotNull(message = "编号不能为空") | |
| 18 | - private Long id; | |
| 19 | - | |
| 20 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java
| ... | ... | @@ -17,6 +17,9 @@ import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; |
| 17 | 17 | import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; |
| 18 | 18 | import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; |
| 19 | 19 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 20 | +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; | |
| 21 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; | |
| 22 | +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; | |
| 20 | 23 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 21 | 24 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 22 | 25 | import com.google.common.collect.Lists; |
| ... | ... | @@ -40,10 +43,10 @@ import java.util.stream.Stream; |
| 40 | 43 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 41 | 44 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 42 | 45 | import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; |
| 43 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; | |
| 44 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 46 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | |
| 45 | 47 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 46 | 48 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 49 | +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT_TYPE; | |
| 47 | 50 | |
| 48 | 51 | @Tag(name = "管理后台 - CRM 联系人") |
| 49 | 52 | @RestController |
| ... | ... | @@ -57,23 +60,25 @@ public class CrmContactController { |
| 57 | 60 | @Resource |
| 58 | 61 | private CrmCustomerService customerService; |
| 59 | 62 | @Resource |
| 60 | - private AdminUserApi adminUserApi; | |
| 63 | + private CrmContactBusinessService contactBusinessLinkService; | |
| 61 | 64 | |
| 62 | 65 | @Resource |
| 63 | - private CrmContactBusinessService contactBusinessLinkService; | |
| 66 | + private AdminUserApi adminUserApi; | |
| 67 | + @Resource | |
| 68 | + private OperateLogApi operateLogApi; | |
| 64 | 69 | |
| 65 | - // TODO @zyna:CrmContactCreateReqVO、CrmContactUpdateReqVO、CrmContactRespVO 按照新的 VO 规范搞哈;可以参考 dept 模块 | |
| 66 | 70 | @PostMapping("/create") |
| 67 | 71 | @Operation(summary = "创建联系人") |
| 68 | 72 | @PreAuthorize("@ss.hasPermission('crm:contact:create')") |
| 69 | - public CommonResult<Long> createContact(@Valid @RequestBody CrmContactCreateReqVO createReqVO) { | |
| 73 | + public CommonResult<Long> createContact(@Valid @RequestBody CrmContactSaveReqVO createReqVO) { | |
| 70 | 74 | return success(contactService.createContact(createReqVO, getLoginUserId())); |
| 71 | 75 | } |
| 72 | 76 | |
| 73 | 77 | @PutMapping("/update") |
| 74 | 78 | @Operation(summary = "更新联系人") |
| 79 | + @OperateLog(enable = false) | |
| 75 | 80 | @PreAuthorize("@ss.hasPermission('crm:contact:update')") |
| 76 | - public CommonResult<Boolean> updateContact(@Valid @RequestBody CrmContactUpdateReqVO updateReqVO) { | |
| 81 | + public CommonResult<Boolean> updateContact(@Valid @RequestBody CrmContactSaveReqVO updateReqVO) { | |
| 77 | 82 | contactService.updateContact(updateReqVO); |
| 78 | 83 | return success(true); |
| 79 | 84 | } |
| ... | ... | @@ -109,14 +114,12 @@ public class CrmContactController { |
| 109 | 114 | } |
| 110 | 115 | |
| 111 | 116 | @GetMapping("/simple-all-list") |
| 112 | - @Operation(summary = "获得联系人列表") | |
| 117 | + @Operation(summary = "获得联系人的精简列表") | |
| 113 | 118 | @PreAuthorize("@ss.hasPermission('crm:contact:query')") |
| 114 | - 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)); | |
| 119 | + public CommonResult<List<CrmContactRespVO>> getSimpleContactList() { | |
| 120 | + List<CrmContactDO> list = contactService.getContactList(); | |
| 121 | + return success(convertList(list, contact -> // 只返回 id、name 字段 | |
| 122 | + new CrmContactRespVO().setId(contact.getId()).setName(contact.getName()))); | |
| 120 | 123 | } |
| 121 | 124 | |
| 122 | 125 | @GetMapping("/page") |
| ... | ... | @@ -147,6 +150,17 @@ public class CrmContactController { |
| 147 | 150 | buildContactDetailPage(pageResult).getList()); |
| 148 | 151 | } |
| 149 | 152 | |
| 153 | + @GetMapping("/operate-log-page") | |
| 154 | + @Operation(summary = "获得客户操作日志") | |
| 155 | + @PreAuthorize("@ss.hasPermission('crm:customer:query')") | |
| 156 | + public CommonResult<PageResult<OperateLogV2RespDTO>> getCustomerOperateLog(@RequestParam("bizId")Long bizId) { | |
| 157 | + OperateLogV2PageReqDTO reqVO = new OperateLogV2PageReqDTO(); | |
| 158 | + reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 | |
| 159 | + reqVO.setBizType(CRM_CONTACT_TYPE); | |
| 160 | + reqVO.setBizId(bizId); | |
| 161 | + return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); | |
| 162 | + } | |
| 163 | + | |
| 150 | 164 | /** |
| 151 | 165 | * 构建详细的联系人分页结果 |
| 152 | 166 | * |
| ... | ... | @@ -181,7 +195,7 @@ public class CrmContactController { |
| 181 | 195 | // ================== 关联/取关联系人 =================== |
| 182 | 196 | |
| 183 | 197 | @PostMapping("/create-business-list") |
| 184 | - @Operation(summary = "创建联系人与联系人的关联") | |
| 198 | + @Operation(summary = "创建联系人与商机的关联") | |
| 185 | 199 | @PreAuthorize("@ss.hasPermission('crm:contact:create-business')") |
| 186 | 200 | public CommonResult<Boolean> createContactBusinessList(@Valid @RequestBody CrmContactBusinessReqVO createReqVO) { |
| 187 | 201 | contactBusinessLinkService.createContactBusinessList(createReqVO); | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactCreateReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; | |
| 2 | - | |
| 3 | -import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | -import lombok.Data; | |
| 5 | -import lombok.EqualsAndHashCode; | |
| 6 | -import lombok.ToString; | |
| 7 | - | |
| 8 | -@Schema(description = "管理后台 - CRM 联系人创建 Request VO") | |
| 9 | -@Data | |
| 10 | -@EqualsAndHashCode(callSuper = true) | |
| 11 | -@ToString(callSuper = true) | |
| 12 | -public class CrmContactCreateReqVO extends CrmContactBaseVO { | |
| 13 | - | |
| 14 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 4 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 5 | +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; | |
| 3 | 6 | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| 4 | 7 | import com.alibaba.excel.annotation.ExcelProperty; |
| 5 | 8 | import io.swagger.v3.oas.annotations.media.Schema; |
| 6 | -import lombok.*; | |
| 9 | +import lombok.Data; | |
| 10 | +import lombok.ToString; | |
| 11 | + | |
| 7 | 12 | import java.time.LocalDateTime; |
| 8 | 13 | |
| 9 | 14 | @Schema(description = "管理后台 - CRM 联系人 Response VO") |
| 10 | 15 | @Data |
| 11 | -@EqualsAndHashCode(callSuper = true) | |
| 12 | 16 | @ToString(callSuper = true) |
| 13 | 17 | @ExcelIgnoreUnannotated |
| 14 | -public class CrmContactRespVO extends CrmContactBaseVO { | |
| 18 | +public class CrmContactRespVO { | |
| 15 | 19 | |
| 16 | 20 | @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167") |
| 17 | 21 | private Long id; |
| 18 | 22 | |
| 19 | - @Schema(description = "创建时间") | |
| 20 | - @ExcelProperty(value = "创建时间", order = 8) | |
| 21 | - private LocalDateTime createTime; | |
| 23 | + @Schema(description = "姓名", example = "芋艿") | |
| 24 | + @ExcelProperty(value = "姓名", order = 1) | |
| 25 | + private String name; | |
| 26 | + | |
| 27 | + @Schema(description = "客户编号", example = "10795") | |
| 28 | + private Long customerId; | |
| 29 | + | |
| 30 | + @Schema(description = "性别") | |
| 31 | + @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3) | |
| 32 | + @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX) | |
| 33 | + private Integer sex; | |
| 34 | + | |
| 35 | + @Schema(description = "职位") | |
| 36 | + @ExcelProperty(value = "职位", order = 3) | |
| 37 | + private String post; | |
| 38 | + | |
| 39 | + @Schema(description = "是否关键决策人") | |
| 40 | + @ExcelProperty(value = "是否关键决策人", converter = DictConvert.class, order = 3) | |
| 41 | + @DictFormat(DictTypeConstants.BOOLEAN_STRING) | |
| 42 | + private Boolean master; | |
| 43 | + | |
| 44 | + @Schema(description = "直属上级", example = "23457") | |
| 45 | + private Long parentId; | |
| 46 | + | |
| 47 | + @Schema(description = "手机号", example = "1387171766") | |
| 48 | + @ExcelProperty(value = "手机号", order = 4) | |
| 49 | + private String mobile; | |
| 50 | + | |
| 51 | + @Schema(description = "电话", example = "021-0029922") | |
| 52 | + @ExcelProperty(value = "电话", order = 4) | |
| 53 | + private String telephone; | |
| 54 | + | |
| 55 | + @Schema(description = "QQ", example = "197272662") | |
| 56 | + @ExcelProperty(value = "QQ", order = 4) | |
| 57 | + private Long qq; | |
| 58 | + | |
| 59 | + @Schema(description = "微信", example = "zzz3883") | |
| 60 | + @ExcelProperty(value = "微信", order = 4) | |
| 61 | + private String wechat; | |
| 62 | + | |
| 63 | + @Schema(description = "电子邮箱", example = "1111@22.com") | |
| 64 | + @ExcelProperty(value = "邮箱", order = 4) | |
| 65 | + private String email; | |
| 66 | + | |
| 67 | + @Schema(description = "地区编号", example = "20158") | |
| 68 | + private Integer areaId; | |
| 69 | + | |
| 70 | + @Schema(description = "地址") | |
| 71 | + @ExcelProperty(value = "地址", order = 5) | |
| 72 | + private String detailAddress; | |
| 73 | + | |
| 74 | + @Schema(description = "备注", example = "你说的对") | |
| 75 | + @ExcelProperty(value = "备注", order = 6) | |
| 76 | + private String remark; | |
| 77 | + | |
| 78 | + @Schema(description = "负责人用户编号", example = "14334") | |
| 79 | + private Long ownerUserId; | |
| 80 | + | |
| 81 | + @Schema(description = "最后跟进时间") | |
| 82 | + @ExcelProperty(value = "最后跟进时间", order = 6) | |
| 83 | + private LocalDateTime contactLastTime; | |
| 22 | 84 | |
| 23 | - @Schema(description = "更新时间") | |
| 24 | - @ExcelProperty(value = "更新时间", order = 8) | |
| 25 | - private LocalDateTime updateTime; | |
| 85 | + @Schema(description = "下次联系时间") | |
| 86 | + @ExcelProperty(value = "下次联系时间", order = 6) | |
| 87 | + private LocalDateTime contactNextTime; | |
| 26 | 88 | |
| 27 | 89 | @Schema(description = "创建人", example = "25682") |
| 28 | 90 | private String creator; |
| ... | ... | @@ -31,7 +93,7 @@ public class CrmContactRespVO extends CrmContactBaseVO { |
| 31 | 93 | @ExcelProperty(value = "创建人", order = 8) |
| 32 | 94 | private String creatorName; |
| 33 | 95 | |
| 34 | - @ExcelProperty(value = "客户名称",order = 2) | |
| 96 | + @ExcelProperty(value = "客户名称", order = 2) | |
| 35 | 97 | @Schema(description = "客户名字", example = "test") |
| 36 | 98 | private String customerName; |
| 37 | 99 | ... | ... |
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
| ... | ... | @@ -2,11 +2,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.validation.Mobile; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.validation.Telephone; |
| 5 | -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 6 | -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 7 | -import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; | |
| 8 | -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; | |
| 9 | -import com.alibaba.excel.annotation.ExcelProperty; | |
| 5 | +import cn.iocoder.yudao.module.crm.framework.operatelog.core.*; | |
| 6 | +import com.mzt.logapi.starter.annotation.DiffLogField; | |
| 10 | 7 | import io.swagger.v3.oas.annotations.media.Schema; |
| 11 | 8 | import jakarta.validation.constraints.Email; |
| 12 | 9 | import jakarta.validation.constraints.NotNull; |
| ... | ... | @@ -18,86 +15,89 @@ import java.time.LocalDateTime; |
| 18 | 15 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; |
| 19 | 16 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| 20 | 17 | |
| 21 | -// TODO zyna:要不按照新的,干掉这个 basevo,都放子类里 | |
| 22 | -/** | |
| 23 | - * CRM 联系人 Base VO,提供给添加、修改、详细的子 VO 使用 | |
| 24 | - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | |
| 25 | - */ | |
| 18 | +@Schema(description = "管理后台 - CRM 联系人创建/更新 Request VO") | |
| 26 | 19 | @Data |
| 27 | -@ExcelIgnoreUnannotated | |
| 28 | -public class CrmContactBaseVO { | |
| 20 | +public class CrmContactSaveReqVO { | |
| 21 | + | |
| 22 | + @Schema(description = "主键", example = "3167") | |
| 23 | + private Long id; | |
| 29 | 24 | |
| 30 | - @ExcelProperty(value = "姓名",order = 1) | |
| 31 | 25 | @Schema(description = "姓名", example = "芋艿") |
| 32 | 26 | @NotNull(message = "姓名不能为空") |
| 27 | + @DiffLogField(name = "姓名") | |
| 33 | 28 | private String name; |
| 34 | 29 | |
| 35 | 30 | @Schema(description = "客户编号", example = "10795") |
| 31 | + @DiffLogField(name = "姓名", function = CrmCustomerParseFunction.NAME) | |
| 36 | 32 | private Long customerId; |
| 37 | 33 | |
| 38 | - @ExcelProperty(value = "性别", converter = DictConvert.class, order = 3) | |
| 39 | - @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.USER_SEX) | |
| 40 | 34 | @Schema(description = "性别") |
| 35 | + @DiffLogField(name = "性别", function = CrmSexParseFunction.NAME) | |
| 41 | 36 | private Integer sex; |
| 42 | 37 | |
| 43 | 38 | @Schema(description = "职位") |
| 44 | - @ExcelProperty(value = "职位", order = 3) | |
| 39 | + @DiffLogField(name = "职位") | |
| 45 | 40 | private String post; |
| 46 | 41 | |
| 47 | 42 | @Schema(description = "是否关键决策人") |
| 48 | - @ExcelProperty(value = "是否关键决策人", converter = DictConvert.class, order = 3) | |
| 49 | - @DictFormat(DictTypeConstants.BOOLEAN_STRING) | |
| 43 | + @DiffLogField(name = "关键决策人", function = CrmBooleanParseFunction.NAME) | |
| 50 | 44 | private Boolean master; |
| 51 | 45 | |
| 52 | 46 | @Schema(description = "直属上级", example = "23457") |
| 47 | + @DiffLogField(name = "直属上级", function = CrmContactParseFunction.NAME) | |
| 53 | 48 | private Long parentId; |
| 54 | 49 | |
| 55 | - @Schema(description = "手机号",example = "1387171766") | |
| 50 | + @Schema(description = "手机号", example = "1387171766") | |
| 56 | 51 | @Mobile |
| 57 | - @ExcelProperty(value = "手机号",order = 4) | |
| 52 | + @DiffLogField(name = "手机号") | |
| 58 | 53 | private String mobile; |
| 59 | 54 | |
| 60 | - @Schema(description = "座机",example = "021-0029922") | |
| 55 | + @Schema(description = "电话", example = "021-0029922") | |
| 61 | 56 | @Telephone |
| 62 | - @ExcelProperty(value = "座机",order = 4) | |
| 57 | + @DiffLogField(name = "电话") | |
| 63 | 58 | private String telephone; |
| 64 | 59 | |
| 65 | - @ExcelProperty(value = "QQ",order = 4) | |
| 66 | - @Schema(description = "QQ",example = "197272662") | |
| 60 | + @Schema(description = "QQ", example = "197272662") | |
| 61 | + @DiffLogField(name = "QQ") | |
| 67 | 62 | private Long qq; |
| 68 | 63 | |
| 69 | - @ExcelProperty(value = "微信",order = 4) | |
| 70 | - @Schema(description = "微信",example = "zzz3883") | |
| 64 | + @Schema(description = "微信", example = "zzz3883") | |
| 65 | + @DiffLogField(name = "微信") | |
| 71 | 66 | private String wechat; |
| 72 | 67 | |
| 73 | - @Schema(description = "电子邮箱",example = "1111@22.com") | |
| 68 | + @Schema(description = "电子邮箱", example = "1111@22.com") | |
| 69 | + @DiffLogField(name = "邮箱") | |
| 74 | 70 | |
| 75 | - @ExcelProperty(value = "邮箱",order = 4) | |
| 76 | 71 | private String email; |
| 77 | 72 | |
| 78 | 73 | @Schema(description = "地区编号", example = "20158") |
| 74 | + @DiffLogField(name = "所在地", function = "getAreaById") | |
| 79 | 75 | private Integer areaId; |
| 80 | 76 | |
| 81 | - @ExcelProperty(value = "地址",order = 5) | |
| 82 | 77 | @Schema(description = "地址") |
| 78 | + @DiffLogField(name = "地址") | |
| 83 | 79 | private String detailAddress; |
| 84 | 80 | |
| 85 | 81 | @Schema(description = "备注", example = "你说的对") |
| 86 | - @ExcelProperty(value = "备注",order = 6) | |
| 82 | + @DiffLogField(name = "备注") | |
| 87 | 83 | private String remark; |
| 88 | 84 | |
| 89 | 85 | @Schema(description = "负责人用户编号", example = "14334") |
| 90 | 86 | @NotNull(message = "负责人不能为空") |
| 87 | + @DiffLogField(name = "负责人", function = CrmSysUserParseFunction.NAME) | |
| 91 | 88 | private Long ownerUserId; |
| 92 | 89 | |
| 93 | 90 | @Schema(description = "最后跟进时间") |
| 94 | 91 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 95 | - @ExcelProperty(value = "最后跟进时间",order = 6) | |
| 92 | + @DiffLogField(name = "最后跟进时间") | |
| 96 | 93 | private LocalDateTime contactLastTime; |
| 97 | 94 | |
| 98 | 95 | @Schema(description = "下次联系时间") |
| 99 | 96 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) |
| 100 | - @ExcelProperty(value = "下次联系时间",order = 6) | |
| 97 | + @DiffLogField(name = "下次联系时间") | |
| 101 | 98 | private LocalDateTime contactNextTime; |
| 102 | 99 | |
| 100 | + @Schema(description = "关联商机 ID", example = "122233") | |
| 101 | + private Long businessId; // 注意:该字段用于在【商机】详情界面「新建联系人」时,自动进行关联 | |
| 102 | + | |
| 103 | 103 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactSimpleRespVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; | |
| 2 | - | |
| 3 | -import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | -import lombok.Data; | |
| 5 | -import lombok.ToString; | |
| 6 | - | |
| 7 | -@Schema(description = "管理后台 - CRM 联系人的精简 Response VO") | |
| 8 | -@Data | |
| 9 | -@ToString(callSuper = true) | |
| 10 | -public class CrmContactSimpleRespVO { | |
| 11 | - | |
| 12 | - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "3167") | |
| 13 | - private Long id; | |
| 14 | - | |
| 15 | - @Schema(description = "姓名", example = "芋艿") | |
| 16 | - private String name; | |
| 17 | - | |
| 18 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/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/controller/admin/customer/CrmCustomerController.java
| ... | ... | @@ -3,12 +3,15 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer; |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | |
| 6 | 7 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | 8 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| 8 | 9 | import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 9 | 10 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; |
| 10 | 11 | import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; |
| 11 | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 13 | +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; | |
| 14 | +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerPoolConfigService; | |
| 12 | 15 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 13 | 16 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| 14 | 17 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| ... | ... | @@ -19,7 +22,6 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 19 | 22 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 20 | 23 | import io.swagger.v3.oas.annotations.Operation; |
| 21 | 24 | import io.swagger.v3.oas.annotations.Parameter; |
| 22 | -import io.swagger.v3.oas.annotations.Parameters; | |
| 23 | 25 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 24 | 26 | import jakarta.annotation.Resource; |
| 25 | 27 | import jakarta.servlet.http.HttpServletResponse; |
| ... | ... | @@ -36,11 +38,10 @@ import java.util.stream.Stream; |
| 36 | 38 | |
| 37 | 39 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 38 | 40 | import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; |
| 39 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 40 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; | |
| 41 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | |
| 41 | 42 | import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; |
| 42 | 43 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 43 | -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; | |
| 44 | +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER_TYPE; | |
| 44 | 45 | |
| 45 | 46 | @Tag(name = "管理后台 - CRM 客户") |
| 46 | 47 | @RestController |
| ... | ... | @@ -50,7 +51,8 @@ public class CrmCustomerController { |
| 50 | 51 | |
| 51 | 52 | @Resource |
| 52 | 53 | private CrmCustomerService customerService; |
| 53 | - | |
| 54 | + @Resource | |
| 55 | + private CrmCustomerPoolConfigService customerPoolConfigService; | |
| 54 | 56 | @Resource |
| 55 | 57 | private DeptApi deptApi; |
| 56 | 58 | @Resource |
| ... | ... | @@ -58,28 +60,24 @@ public class CrmCustomerController { |
| 58 | 60 | @Resource |
| 59 | 61 | private OperateLogApi operateLogApi; |
| 60 | 62 | |
| 61 | - // TODO @puhui999:把 CrmCustomerCreateReqVO、CrmCustomerUpdateReqVO、CrmCustomerRespVO 按照新的规范,搞一下哈; | |
| 62 | 63 | @PostMapping("/create") |
| 63 | 64 | @Operation(summary = "创建客户") |
| 64 | - @OperateLog(enable = false) // TODO 关闭原有日志记录;@puhui999:注解都先删除。先记录,没关系。我们下个迭代,就都删除掉操作日志了; | |
| 65 | 65 | @PreAuthorize("@ss.hasPermission('crm:customer:create')") |
| 66 | - public CommonResult<Long> createCustomer(@Valid @RequestBody CrmCustomerCreateReqVO createReqVO) { | |
| 66 | + public CommonResult<Long> createCustomer(@Valid @RequestBody CrmCustomerSaveReqVO createReqVO) { | |
| 67 | 67 | return success(customerService.createCustomer(createReqVO, getLoginUserId())); |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | 70 | @PutMapping("/update") |
| 71 | 71 | @Operation(summary = "更新客户") |
| 72 | - @OperateLog(enable = false) // TODO 关闭原有日志记录 | |
| 73 | 72 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") |
| 74 | - public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { | |
| 73 | + public CommonResult<Boolean> updateCustomer(@Valid @RequestBody CrmCustomerSaveReqVO updateReqVO) { | |
| 75 | 74 | customerService.updateCustomer(updateReqVO); |
| 76 | 75 | return success(true); |
| 77 | 76 | } |
| 78 | 77 | |
| 79 | 78 | @DeleteMapping("/delete") |
| 80 | 79 | @Operation(summary = "删除客户") |
| 81 | - @OperateLog(enable = false) // TODO 关闭原有日志记录 | |
| 82 | - @Parameter(name = "id", description = "编号", required = true) | |
| 80 | + @Parameter(name = "id", description = "客户编号", required = true) | |
| 83 | 81 | @PreAuthorize("@ss.hasPermission('crm:customer:delete')") |
| 84 | 82 | public CommonResult<Boolean> deleteCustomer(@RequestParam("id") Long id) { |
| 85 | 83 | customerService.deleteCustomer(id); |
| ... | ... | @@ -103,7 +101,6 @@ public class CrmCustomerController { |
| 103 | 101 | return success(CrmCustomerConvert.INSTANCE.convert(customer, userMap, deptMap)); |
| 104 | 102 | } |
| 105 | 103 | |
| 106 | - // TODO @puhui999:这个查询会查出多个;微信发你图了 | |
| 107 | 104 | @GetMapping("/page") |
| 108 | 105 | @Operation(summary = "获得客户分页") |
| 109 | 106 | @PreAuthorize("@ss.hasPermission('crm:customer:query')") |
| ... | ... | @@ -115,11 +112,42 @@ public class CrmCustomerController { |
| 115 | 112 | } |
| 116 | 113 | |
| 117 | 114 | // 2. 拼接数据 |
| 118 | - // TODO @puhui999:距离进入公海的时间 | |
| 115 | + Map<Long, Long> poolDayMap = getPoolDayMap(pageResult); // 距离进入公海的时间 | |
| 119 | 116 | Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( |
| 120 | 117 | convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId()))); |
| 121 | 118 | Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); |
| 122 | - return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap)); | |
| 119 | + return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap)); | |
| 120 | + } | |
| 121 | + | |
| 122 | + // TODO @puhui999:加下注释哈; | |
| 123 | + private Map<Long, Long> getPoolDayMap(PageResult<CrmCustomerDO> pageResult) { | |
| 124 | + Map<Long, Long> poolDayMap = null; | |
| 125 | + CrmCustomerPoolConfigDO customerPoolConfig = customerPoolConfigService.getCustomerPoolConfig(); | |
| 126 | + // TODO @puhui999:if return 减少括号 | |
| 127 | + if (customerPoolConfig != null && customerPoolConfig.getEnabled()) { // 有公海配置的情况 | |
| 128 | + // TODO @puhui999:item 改成 customer 更好,容易理解; | |
| 129 | + poolDayMap = convertMap(pageResult.getList(), CrmCustomerDO::getId, item -> { | |
| 130 | + long dealExpireDay = 0; | |
| 131 | + if (!item.getDealStatus()) { // 检查是否成交 | |
| 132 | + dealExpireDay = customerPoolConfig.getDealExpireDays() - LocalDateTimeUtils.between(item.getCreateTime()); | |
| 133 | + } | |
| 134 | + // TODO @puhui999:需要考虑 contactLastTime 为空的情况哈; | |
| 135 | + long contactExpireDay = customerPoolConfig.getContactExpireDays() - LocalDateTimeUtils.between(item.getContactLastTime()); | |
| 136 | + return dealExpireDay == 0 ? contactExpireDay : Math.min(dealExpireDay, contactExpireDay); | |
| 137 | + }); | |
| 138 | + // TODO @puhui999:需要考虑 lock 的情况么? | |
| 139 | + } | |
| 140 | + return poolDayMap; | |
| 141 | + } | |
| 142 | + | |
| 143 | + @GetMapping(value = "/list-all-simple") | |
| 144 | + @Operation(summary = "获取客户精简信息列表", description = "只包含有读权限的客户,主要用于前端的下拉选项") | |
| 145 | + public CommonResult<List<CrmCustomerRespVO>> getSimpleDeptList() { | |
| 146 | + CrmCustomerPageReqVO reqVO = new CrmCustomerPageReqVO(); | |
| 147 | + reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 | |
| 148 | + List<CrmCustomerDO> list = customerService.getCustomerPage(reqVO, getLoginUserId()).getList(); | |
| 149 | + return success(convertList(list, customer -> // 只返回 id、name 精简字段 | |
| 150 | + new CrmCustomerRespVO().setId(customer.getId()).setName(customer.getName()))); | |
| 123 | 151 | } |
| 124 | 152 | |
| 125 | 153 | @GetMapping("/export-excel") |
| ... | ... | @@ -131,32 +159,32 @@ public class CrmCustomerController { |
| 131 | 159 | pageVO.setPageSize(PAGE_SIZE_NONE); // 不分页 |
| 132 | 160 | List<CrmCustomerDO> list = customerService.getCustomerPage(pageVO, getLoginUserId()).getList(); |
| 133 | 161 | // 导出 Excel |
| 134 | - List<CrmCustomerExcelVO> datas = CrmCustomerConvert.INSTANCE.convertList02(list); | |
| 135 | - ExcelUtils.write(response, "客户.xls", "数据", CrmCustomerExcelVO.class, datas); | |
| 162 | + ExcelUtils.write(response, "客户.xls", "数据", CrmCustomerRespVO.class, | |
| 163 | + BeanUtils.toBean(list, CrmCustomerRespVO.class)); | |
| 136 | 164 | } |
| 137 | 165 | |
| 138 | 166 | @PutMapping("/transfer") |
| 139 | 167 | @Operation(summary = "转移客户") |
| 140 | - @OperateLog(enable = false) // TODO 关闭原有日志记录 | |
| 141 | 168 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") |
| 142 | 169 | public CommonResult<Boolean> transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { |
| 143 | 170 | customerService.transferCustomer(reqVO, getLoginUserId()); |
| 144 | 171 | return success(true); |
| 145 | 172 | } |
| 146 | 173 | |
| 147 | - // TODO @puhui999:是不是接口只要传递 bizId,由 Controller 自己组装出 OperateLogV2PageReqDTO | |
| 148 | 174 | @GetMapping("/operate-log-page") |
| 149 | 175 | @Operation(summary = "获得客户操作日志") |
| 176 | + @Parameter(name = "id", description = "客户编号", required = true) | |
| 150 | 177 | @PreAuthorize("@ss.hasPermission('crm:customer:query')") |
| 151 | - public CommonResult<PageResult<OperateLogV2RespDTO>> getCustomerOperateLog(CrmCustomerOperateLogPageReqVO reqVO) { | |
| 152 | - reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 | |
| 153 | - reqVO.setBizType(CRM_CUSTOMER); | |
| 154 | - return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); | |
| 178 | + public CommonResult<PageResult<OperateLogV2RespDTO>> getCustomerOperateLog(@RequestParam("id") Long id) { | |
| 179 | + OperateLogV2PageReqDTO reqDTO = new OperateLogV2PageReqDTO(); | |
| 180 | + reqDTO.setPageSize(PAGE_SIZE_NONE); // 不分页 | |
| 181 | + reqDTO.setBizType(CRM_CUSTOMER_TYPE); | |
| 182 | + reqDTO.setBizId(id); | |
| 183 | + return success(operateLogApi.getOperateLogPage(reqDTO)); | |
| 155 | 184 | } |
| 156 | 185 | |
| 157 | 186 | @PutMapping("/lock") |
| 158 | 187 | @Operation(summary = "锁定/解锁客户") |
| 159 | - @OperateLog(enable = false) // TODO 关闭原有日志记录 | |
| 160 | 188 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") |
| 161 | 189 | public CommonResult<Boolean> lockCustomer(@Valid @RequestBody CrmCustomerLockReqVO lockReqVO) { |
| 162 | 190 | customerService.lockCustomer(lockReqVO, getLoginUserId()); |
| ... | ... | @@ -167,7 +195,6 @@ public class CrmCustomerController { |
| 167 | 195 | |
| 168 | 196 | @PutMapping("/put-pool") |
| 169 | 197 | @Operation(summary = "数据放入公海") |
| 170 | - @OperateLog(enable = false) // TODO 关闭原有日志记录 | |
| 171 | 198 | @Parameter(name = "id", description = "客户编号", required = true, example = "1024") |
| 172 | 199 | @PreAuthorize("@ss.hasPermission('crm:customer:update')") |
| 173 | 200 | public CommonResult<Boolean> putCustomerPool(@RequestParam("id") Long id) { |
| ... | ... | @@ -180,32 +207,16 @@ public class CrmCustomerController { |
| 180 | 207 | @Parameter(name = "ids", description = "编号数组", required = true, example = "1,2,3") |
| 181 | 208 | @PreAuthorize("@ss.hasPermission('crm:customer:receive')") |
| 182 | 209 | public CommonResult<Boolean> receiveCustomer(@RequestParam(value = "ids") List<Long> ids) { |
| 183 | - customerService.receiveCustomer(ids, getLoginUserId()); | |
| 210 | + customerService.receiveCustomer(ids, getLoginUserId(), Boolean.TRUE); | |
| 184 | 211 | return success(true); |
| 185 | 212 | } |
| 186 | 213 | |
| 187 | - // TODO @puhui999:需要搞个 VO 类 | |
| 188 | 214 | @PutMapping("/distribute") |
| 189 | 215 | @Operation(summary = "分配公海给对应负责人") |
| 190 | - @Parameters({ | |
| 191 | - @Parameter(name = "ids", description = "客户编号数组", required = true, example = "1,2,3"), | |
| 192 | - @Parameter(name = "ownerUserId", description = "分配的负责人编号", required = true, example = "12345") | |
| 193 | - }) | |
| 194 | 216 | @PreAuthorize("@ss.hasPermission('crm:customer:distribute')") |
| 195 | - public CommonResult<Boolean> distributeCustomer(@RequestParam(value = "ids") List<Long> ids, | |
| 196 | - @RequestParam(value = "ownerUserId") Long ownerUserId) { | |
| 197 | - customerService.receiveCustomer(ids, ownerUserId); | |
| 217 | + public CommonResult<Boolean> distributeCustomer(@Valid @RequestBody CrmCustomerDistributeReqVO distributeReqVO) { | |
| 218 | + customerService.receiveCustomer(distributeReqVO.getIds(), distributeReqVO.getOwnerUserId(), Boolean.FALSE); | |
| 198 | 219 | return success(true); |
| 199 | 220 | } |
| 200 | 221 | |
| 201 | - // TODO 芋艿:这个接口要调整下 | |
| 202 | - @GetMapping("/query-all-list") | |
| 203 | - @Operation(summary = "查询客户列表") | |
| 204 | - @PreAuthorize("@ss.hasPermission('crm:customer:all')") | |
| 205 | - public CommonResult<List<CrmCustomerQueryAllRespVO>> queryAll() { | |
| 206 | - List<CrmCustomerDO> crmCustomerDOList = customerService.getCustomerList(); | |
| 207 | - List<CrmCustomerQueryAllRespVO> data = CrmCustomerConvert.INSTANCE.convertQueryAll(crmCustomerDOList); | |
| 208 | - return success(data); | |
| 209 | - } | |
| 210 | - | |
| 211 | 222 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerLimitConfigController.java
| ... | ... | @@ -3,10 +3,9 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer; |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; | |
| 7 | 6 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; |
| 8 | 7 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigRespVO; |
| 9 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO; | |
| 8 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigSaveReqVO; | |
| 10 | 9 | import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerLimitConfigConvert; |
| 11 | 10 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; |
| 12 | 11 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerLimitConfigService; |
| ... | ... | @@ -17,12 +16,12 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 17 | 16 | import io.swagger.v3.oas.annotations.Operation; |
| 18 | 17 | import io.swagger.v3.oas.annotations.Parameter; |
| 19 | 18 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 19 | +import jakarta.annotation.Resource; | |
| 20 | +import jakarta.validation.Valid; | |
| 20 | 21 | import org.springframework.security.access.prepost.PreAuthorize; |
| 21 | 22 | import org.springframework.validation.annotation.Validated; |
| 22 | 23 | import org.springframework.web.bind.annotation.*; |
| 23 | 24 | |
| 24 | -import jakarta.annotation.Resource; | |
| 25 | -import jakarta.validation.Valid; | |
| 26 | 25 | import java.util.Collection; |
| 27 | 26 | import java.util.Map; |
| 28 | 27 | |
| ... | ... | @@ -43,18 +42,17 @@ public class CrmCustomerLimitConfigController { |
| 43 | 42 | @Resource |
| 44 | 43 | private AdminUserApi adminUserApi; |
| 45 | 44 | |
| 46 | - // TODO @puhui999:可以把 vo 改下哈 | |
| 47 | 45 | @PostMapping("/create") |
| 48 | 46 | @Operation(summary = "创建客户限制配置") |
| 49 | 47 | @PreAuthorize("@ss.hasPermission('crm:customer-limit-config:create')") |
| 50 | - public CommonResult<Long> createCustomerLimitConfig(@Valid @RequestBody CrmCustomerLimitConfigCreateReqVO createReqVO) { | |
| 48 | + public CommonResult<Long> createCustomerLimitConfig(@Valid @RequestBody CrmCustomerLimitConfigSaveReqVO createReqVO) { | |
| 51 | 49 | return success(customerLimitConfigService.createCustomerLimitConfig(createReqVO)); |
| 52 | 50 | } |
| 53 | 51 | |
| 54 | 52 | @PutMapping("/update") |
| 55 | 53 | @Operation(summary = "更新客户限制配置") |
| 56 | 54 | @PreAuthorize("@ss.hasPermission('crm:customer-limit-config:update')") |
| 57 | - public CommonResult<Boolean> updateCustomerLimitConfig(@Valid @RequestBody CrmCustomerLimitConfigUpdateReqVO updateReqVO) { | |
| 55 | + public CommonResult<Boolean> updateCustomerLimitConfig(@Valid @RequestBody CrmCustomerLimitConfigSaveReqVO updateReqVO) { | |
| 58 | 56 | customerLimitConfigService.updateCustomerLimitConfig(updateReqVO); |
| 59 | 57 | return success(true); |
| 60 | 58 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerPoolConfigController.java
| ... | ... | @@ -8,13 +8,12 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfig |
| 8 | 8 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerPoolConfigService; |
| 9 | 9 | import io.swagger.v3.oas.annotations.Operation; |
| 10 | 10 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 11 | +import jakarta.annotation.Resource; | |
| 12 | +import jakarta.validation.Valid; | |
| 11 | 13 | import org.springframework.security.access.prepost.PreAuthorize; |
| 12 | 14 | import org.springframework.validation.annotation.Validated; |
| 13 | 15 | import org.springframework.web.bind.annotation.*; |
| 14 | 16 | |
| 15 | -import jakarta.annotation.Resource; | |
| 16 | -import jakarta.validation.Valid; | |
| 17 | - | |
| 18 | 17 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 19 | 18 | |
| 20 | 19 | @Tag(name = "管理后台 - CRM 客户公海配置") |
| ... | ... | @@ -26,7 +25,6 @@ public class CrmCustomerPoolConfigController { |
| 26 | 25 | @Resource |
| 27 | 26 | private CrmCustomerPoolConfigService customerPoolConfigService; |
| 28 | 27 | |
| 29 | - // TODO @puhui999:可以把 vo 改下哈 | |
| 30 | 28 | @GetMapping("/get") |
| 31 | 29 | @Operation(summary = "获取客户公海规则设置") |
| 32 | 30 | @PreAuthorize("@ss.hasPermission('crm:customer-pool-config:query')") | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerCreateReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.customer.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 CrmCustomerCreateReqVO extends CrmCustomerBaseVO { | |
| 15 | - | |
| 16 | - @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 17 | - @NotNull(message = "负责人不能为空") | |
| 18 | - private Long ownerUserId; | |
| 19 | - | |
| 20 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerDistributeReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import jakarta.validation.constraints.NotNull; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import java.util.List; | |
| 8 | + | |
| 9 | +@Schema(description = "管理后台 - CRM 客户分配公海给对应负责人 Request VO") | |
| 10 | +@Data | |
| 11 | +public class CrmCustomerDistributeReqVO { | |
| 12 | + | |
| 13 | + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1024]") | |
| 14 | + @NotNull(message = "客户编号不能为空") // TODO @puhui999:list 是 @NotEmpty | |
| 15 | + private List<Long> ids; | |
| 16 | + | |
| 17 | + @Schema(description = "负责人", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 18 | + @NotNull(message = "负责人不能为空") | |
| 19 | + private Long ownerUserId; | |
| 20 | + | |
| 21 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerExcelVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 4 | -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 5 | -import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; | |
| 6 | -import com.alibaba.excel.annotation.ExcelProperty; | |
| 7 | -import io.swagger.v3.oas.annotations.media.Schema; | |
| 8 | -import lombok.Data; | |
| 9 | - | |
| 10 | -import java.time.LocalDateTime; | |
| 11 | - | |
| 12 | -// TODO 芋艿:导出最后做,等基本确认的差不多之后; | |
| 13 | -/** | |
| 14 | - * CRM 客户 Excel VO | |
| 15 | - * | |
| 16 | - * @author Wanwan | |
| 17 | - */ | |
| 18 | -@Data | |
| 19 | -public class CrmCustomerExcelVO { | |
| 20 | - | |
| 21 | - @ExcelProperty("编号") | |
| 22 | - private Long id; | |
| 23 | - | |
| 24 | - @ExcelProperty("客户名称") | |
| 25 | - private String name; | |
| 26 | - | |
| 27 | - @ExcelProperty(value = "跟进状态", converter = DictConvert.class) | |
| 28 | - @DictFormat(DictTypeConstants.BOOLEAN_STRING) | |
| 29 | - private Boolean followUpStatus; | |
| 30 | - | |
| 31 | - @ExcelProperty(value = "锁定状态", converter = DictConvert.class) | |
| 32 | - @DictFormat(DictTypeConstants.BOOLEAN_STRING) | |
| 33 | - private Boolean lockStatus; | |
| 34 | - | |
| 35 | - @ExcelProperty(value = "成交状态", converter = DictConvert.class) | |
| 36 | - @DictFormat(DictTypeConstants.BOOLEAN_STRING) | |
| 37 | - private Boolean dealStatus; | |
| 38 | - | |
| 39 | - @ExcelProperty(value = "所属行业", converter = DictConvert.class) | |
| 40 | - @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY) | |
| 41 | - private Integer industryId; | |
| 42 | - | |
| 43 | - @ExcelProperty(value = "客户等级", converter = DictConvert.class) | |
| 44 | - @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL) | |
| 45 | - private Integer level; | |
| 46 | - | |
| 47 | - @ExcelProperty(value = "客户来源", converter = DictConvert.class) | |
| 48 | - @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE) | |
| 49 | - private Integer source; | |
| 50 | - | |
| 51 | - @ExcelProperty("手机") | |
| 52 | - private String mobile; | |
| 53 | - | |
| 54 | - @ExcelProperty("电话") | |
| 55 | - private String telephone; | |
| 56 | - | |
| 57 | - @ExcelProperty("网址") | |
| 58 | - private String website; | |
| 59 | - | |
| 60 | - @ExcelProperty("QQ") | |
| 61 | - private String qq; | |
| 62 | - | |
| 63 | - @ExcelProperty("wechat") | |
| 64 | - private String wechat; | |
| 65 | - | |
| 66 | - @ExcelProperty("email") | |
| 67 | - private String email; | |
| 68 | - | |
| 69 | - @ExcelProperty("客户描述") | |
| 70 | - private String description; | |
| 71 | - | |
| 72 | - @ExcelProperty("备注") | |
| 73 | - private String remark; | |
| 74 | - | |
| 75 | - @ExcelProperty("负责人的用户编号") | |
| 76 | - private Long ownerUserId; | |
| 77 | - | |
| 78 | - @ExcelProperty("地区编号") | |
| 79 | - private Integer areaId; | |
| 80 | - | |
| 81 | - @ExcelProperty("详细地址") | |
| 82 | - private String detailAddress; | |
| 83 | - | |
| 84 | - @ExcelProperty("最后跟进时间") | |
| 85 | - private LocalDateTime contactLastTime; | |
| 86 | - | |
| 87 | - @ExcelProperty("下次联系时间") | |
| 88 | - private LocalDateTime contactNextTime; | |
| 89 | - | |
| 90 | - @ExcelProperty("创建时间") | |
| 91 | - private LocalDateTime createTime; | |
| 92 | - | |
| 93 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerOperateLogPageReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 4 | -import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | -import lombok.Data; | |
| 6 | - | |
| 7 | -@Schema(description = "管理后台 - crm 客户操作日志分页 Request VO") | |
| 8 | -@Data | |
| 9 | -public class CrmCustomerOperateLogPageReqVO extends PageParam { | |
| 10 | - | |
| 11 | - @Schema(description = "模块数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 12 | - private Long bizId; | |
| 13 | - | |
| 14 | - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 15 | - private Long userId; | |
| 16 | - | |
| 17 | - @Schema(description = "模块类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 18 | - private String bizType; | |
| 19 | - | |
| 20 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerQueryAllRespVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; | |
| 2 | - | |
| 3 | -import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | -import lombok.Data; | |
| 5 | - | |
| 6 | -// TODO 芋艿:这块要统一下; | |
| 7 | -@Schema(description = "管理后台 - CRM 全部客户 Response VO") | |
| 8 | -@Data | |
| 9 | -public class CrmCustomerQueryAllRespVO{ | |
| 10 | - | |
| 11 | - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 12 | - private Long id; | |
| 13 | - | |
| 14 | - @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") | |
| 15 | - private String name; | |
| 16 | - | |
| 17 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerRespVO.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; |
| 2 | 2 | |
| 3 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 4 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 5 | +import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; | |
| 6 | +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; | |
| 7 | +import com.alibaba.excel.annotation.ExcelProperty; | |
| 3 | 8 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 9 | import lombok.Data; |
| 5 | -import lombok.EqualsAndHashCode; | |
| 6 | -import lombok.ToString; | |
| 7 | 10 | import org.springframework.format.annotation.DateTimeFormat; |
| 8 | 11 | |
| 9 | 12 | import java.time.LocalDateTime; |
| ... | ... | @@ -12,45 +15,124 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ |
| 12 | 15 | |
| 13 | 16 | @Schema(description = "管理后台 - CRM 客户 Response VO") |
| 14 | 17 | @Data |
| 15 | -@EqualsAndHashCode(callSuper = true) | |
| 16 | -@ToString(callSuper = true) | |
| 17 | -public class CrmCustomerRespVO extends CrmCustomerBaseVO { | |
| 18 | +@ExcelIgnoreUnannotated | |
| 19 | +public class CrmCustomerRespVO { | |
| 18 | 20 | |
| 19 | 21 | @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") |
| 22 | + @ExcelProperty("编号") | |
| 20 | 23 | private Long id; |
| 21 | 24 | |
| 22 | - @Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 25 | + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 26 | + @ExcelProperty("客户名称") | |
| 27 | + private String name; | |
| 28 | + | |
| 29 | + @Schema(description = "跟进状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 30 | + @ExcelProperty(value = "跟进状态", converter = DictConvert.class) | |
| 31 | + @DictFormat(DictTypeConstants.BOOLEAN_STRING) | |
| 23 | 32 | private Boolean followUpStatus; |
| 24 | 33 | |
| 25 | - @Schema(description = "锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 34 | + @Schema(description = "锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 35 | + @ExcelProperty(value = "锁定状态", converter = DictConvert.class) | |
| 36 | + @DictFormat(DictTypeConstants.BOOLEAN_STRING) | |
| 26 | 37 | private Boolean lockStatus; |
| 27 | 38 | |
| 28 | - @Schema(description = "成交状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 39 | + @Schema(description = "成交状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 40 | + @ExcelProperty(value = "成交状态", converter = DictConvert.class) | |
| 41 | + @DictFormat(DictTypeConstants.BOOLEAN_STRING) | |
| 29 | 42 | private Boolean dealStatus; |
| 30 | 43 | |
| 44 | + @Schema(description = "所属行业", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 45 | + @ExcelProperty(value = "所属行业", converter = DictConvert.class) | |
| 46 | + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY) | |
| 47 | + private Integer industryId; | |
| 48 | + | |
| 49 | + @Schema(description = "客户等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 50 | + @ExcelProperty(value = "客户等级", converter = DictConvert.class) | |
| 51 | + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL) | |
| 52 | + private Integer level; | |
| 53 | + | |
| 54 | + @Schema(description = "客户来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 55 | + @ExcelProperty(value = "客户来源", converter = DictConvert.class) | |
| 56 | + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE) | |
| 57 | + private Integer source; | |
| 58 | + | |
| 59 | + @Schema(description = "负责人的用户编号", example = "25682") | |
| 60 | + @ExcelProperty("手机") | |
| 61 | + private String mobile; | |
| 62 | + | |
| 63 | + @Schema(description = "负责人的用户编号", example = "25682") | |
| 64 | + @ExcelProperty("电话") | |
| 65 | + private String telephone; | |
| 66 | + | |
| 67 | + @Schema(description = "负责人的用户编号", example = "25682") | |
| 68 | + @ExcelProperty("网址") | |
| 69 | + private String website; | |
| 70 | + | |
| 71 | + @Schema(description = "负责人的用户编号", example = "25682") | |
| 72 | + @ExcelProperty("QQ") | |
| 73 | + private String qq; | |
| 74 | + | |
| 75 | + @Schema(description = "负责人的用户编号", example = "25682") | |
| 76 | + @ExcelProperty("wechat") | |
| 77 | + private String wechat; | |
| 78 | + | |
| 31 | 79 | @Schema(description = "负责人的用户编号", example = "25682") |
| 80 | + @ExcelProperty("email") | |
| 81 | + private String email; | |
| 82 | + | |
| 83 | + @Schema(description = "负责人的用户编号", example = "25682") | |
| 84 | + @ExcelProperty("客户描述") | |
| 85 | + private String description; | |
| 86 | + | |
| 87 | + @Schema(description = "负责人的用户编号", example = "25682") | |
| 88 | + @ExcelProperty("备注") | |
| 89 | + private String remark; | |
| 90 | + | |
| 91 | + @Schema(description = "负责人的用户编号", example = "25682") | |
| 92 | + @ExcelProperty("负责人的用户编号") | |
| 32 | 93 | private Long ownerUserId; |
| 33 | 94 | @Schema(description = "负责人名字", example = "25682") |
| 95 | + @ExcelProperty("负责人名字") | |
| 34 | 96 | private String ownerUserName; |
| 35 | 97 | @Schema(description = "负责人部门") |
| 98 | + @ExcelProperty("负责人部门") | |
| 36 | 99 | private String ownerUserDeptName; |
| 37 | 100 | |
| 101 | + @Schema(description = "地区编号", example = "1024") | |
| 102 | + @ExcelProperty("地区编号") | |
| 103 | + private Integer areaId; | |
| 38 | 104 | @Schema(description = "地区名称", example = "北京市") |
| 105 | + @ExcelProperty("地区名称") | |
| 39 | 106 | private String areaName; |
| 107 | + @Schema(description = "详细地址", example = "北京市成华大道") | |
| 108 | + @ExcelProperty("详细地址") | |
| 109 | + private String detailAddress; | |
| 40 | 110 | |
| 41 | 111 | @Schema(description = "最后跟进时间") |
| 112 | + @ExcelProperty("最后跟进时间") | |
| 42 | 113 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 43 | 114 | private LocalDateTime contactLastTime; |
| 44 | 115 | |
| 116 | + @Schema(description = "下次联系时间") | |
| 117 | + @ExcelProperty("下次联系时间") | |
| 118 | + private LocalDateTime contactNextTime; | |
| 119 | + | |
| 45 | 120 | @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 121 | + @ExcelProperty("创建时间") | |
| 46 | 122 | private LocalDateTime createTime; |
| 47 | 123 | |
| 48 | 124 | @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) |
| 125 | + @ExcelProperty("更新时间") | |
| 49 | 126 | private LocalDateTime updateTime; |
| 50 | 127 | |
| 51 | - @Schema(description = "创建人") | |
| 128 | + @Schema(description = "创建人", example = "1024") | |
| 129 | + @ExcelProperty("创建人") | |
| 52 | 130 | private String creator; |
| 53 | - @Schema(description = "创建人名字") | |
| 131 | + @Schema(description = "创建人名字", example = "芋道源码") | |
| 132 | + @ExcelProperty("创建人名字") | |
| 54 | 133 | private String creatorName; |
| 55 | 134 | |
| 135 | + @Schema(description = "距离加入公海时间", example = "1") | |
| 136 | + private Long poolDay; | |
| 137 | + | |
| 56 | 138 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerSaveReqVO.java
| ... | ... | @@ -5,6 +5,9 @@ import cn.iocoder.yudao.framework.common.validation.Mobile; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.validation.Telephone; |
| 6 | 6 | import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; |
| 7 | 7 | import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum; |
| 8 | +import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmIndustryParseFunction; | |
| 9 | +import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmLevelParseFunction; | |
| 10 | +import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmSourceParseFunction; | |
| 8 | 11 | import com.mzt.logapi.starter.annotation.DiffLogField; |
| 9 | 12 | import io.swagger.v3.oas.annotations.media.Schema; |
| 10 | 13 | import jakarta.validation.constraints.Email; |
| ... | ... | @@ -18,12 +21,12 @@ import java.time.LocalDateTime; |
| 18 | 21 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| 19 | 22 | import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; |
| 20 | 23 | |
| 21 | -/** | |
| 22 | - * 客户 Base VO,提供给添加、修改、详细的子 VO 使用 | |
| 23 | - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | |
| 24 | - */ | |
| 24 | +@Schema(description = "管理后台 - CRM 客户新增/修改 Request VO") | |
| 25 | 25 | @Data |
| 26 | -public class CrmCustomerBaseVO { | |
| 26 | +public class CrmCustomerSaveReqVO { | |
| 27 | + | |
| 28 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 29 | + private Long id; | |
| 27 | 30 | |
| 28 | 31 | @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") |
| 29 | 32 | @DiffLogField(name = "客户名称") |
| ... | ... | @@ -31,17 +34,17 @@ public class CrmCustomerBaseVO { |
| 31 | 34 | private String name; |
| 32 | 35 | |
| 33 | 36 | @Schema(description = "所属行业", example = "1") |
| 34 | - @DiffLogField(name = "所属行业", function = "getIndustryById") | |
| 37 | + @DiffLogField(name = "所属行业", function = CrmIndustryParseFunction.NAME) | |
| 35 | 38 | @DictFormat(CRM_CUSTOMER_INDUSTRY) |
| 36 | 39 | private Integer industryId; |
| 37 | 40 | |
| 38 | 41 | @Schema(description = "客户等级", example = "2") |
| 39 | - @DiffLogField(name = "客户等级", function = "getLevel") | |
| 42 | + @DiffLogField(name = "客户等级", function = CrmLevelParseFunction.NAME) | |
| 40 | 43 | @InEnum(CrmCustomerLevelEnum.class) |
| 41 | 44 | private Integer level; |
| 42 | 45 | |
| 43 | 46 | @Schema(description = "客户来源", example = "3") |
| 44 | - @DiffLogField(name = "客户来源", function = "getSource") | |
| 47 | + @DiffLogField(name = "客户来源", function = CrmSourceParseFunction.NAME) | |
| 45 | 48 | private Integer source; |
| 46 | 49 | |
| 47 | 50 | @Schema(description = "手机", example = "18000000000") |
| ... | ... | @@ -96,4 +99,7 @@ public class CrmCustomerBaseVO { |
| 96 | 99 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 97 | 100 | private LocalDateTime contactNextTime; |
| 98 | 101 | |
| 102 | + @Schema(description = "负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 103 | + private Long ownerUserId; | |
| 104 | + | |
| 99 | 105 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerUpdateReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.customer.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 CrmCustomerUpdateReqVO extends CrmCustomerBaseVO { | |
| 15 | - | |
| 16 | - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") | |
| 17 | - @NotNull(message = "编号不能为空") | |
| 18 | - private Long id; | |
| 19 | - | |
| 20 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig; | |
| 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 = "管理后台 - 客户限制配置创建 Request VO") | |
| 9 | -@Data | |
| 10 | -@EqualsAndHashCode(callSuper = true) | |
| 11 | -@ToString(callSuper = true) | |
| 12 | -public class CrmCustomerLimitConfigCreateReqVO extends CrmCustomerLimitConfigBaseVO { | |
| 13 | - | |
| 14 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigRespVO.java
| ... | ... | @@ -4,21 +4,32 @@ import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| 4 | 4 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 5 | 5 | import io.swagger.v3.oas.annotations.media.Schema; |
| 6 | 6 | import lombok.Data; |
| 7 | -import lombok.EqualsAndHashCode; | |
| 8 | -import lombok.ToString; | |
| 9 | 7 | |
| 10 | 8 | import java.time.LocalDateTime; |
| 11 | 9 | import java.util.List; |
| 12 | 10 | |
| 13 | 11 | @Schema(description = "管理后台 - 客户限制配置 Response VO") |
| 14 | 12 | @Data |
| 15 | -@EqualsAndHashCode(callSuper = true) | |
| 16 | -@ToString(callSuper = true) | |
| 17 | -public class CrmCustomerLimitConfigRespVO extends CrmCustomerLimitConfigBaseVO { | |
| 13 | +public class CrmCustomerLimitConfigRespVO { | |
| 18 | 14 | |
| 19 | 15 | @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27930") |
| 20 | 16 | private Long id; |
| 21 | 17 | |
| 18 | + @Schema(description = "规则类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | |
| 19 | + private Integer type; | |
| 20 | + | |
| 21 | + @Schema(description = "规则适用人群") | |
| 22 | + private List<Long> userIds; | |
| 23 | + | |
| 24 | + @Schema(description = "规则适用部门") | |
| 25 | + private List<Long> deptIds; | |
| 26 | + | |
| 27 | + @Schema(description = "数量上限", requiredMode = Schema.RequiredMode.REQUIRED, example = "28384") | |
| 28 | + private Integer maxCount; | |
| 29 | + | |
| 30 | + @Schema(description = "成交客户是否占有拥有客户数") | |
| 31 | + private Boolean dealCountEnabled; | |
| 32 | + | |
| 22 | 33 | @Schema(description = "规则适用人群名称") |
| 23 | 34 | private List<AdminUserRespDTO> users; |
| 24 | 35 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigBaseVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigSaveReqVO.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig; |
| 2 | 2 | |
| 3 | +import com.mzt.logapi.starter.annotation.DiffLogField; | |
| 3 | 4 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | +import jakarta.validation.constraints.NotNull; | |
| 4 | 6 | import lombok.Data; |
| 5 | 7 | |
| 6 | -import jakarta.validation.constraints.NotNull; | |
| 7 | 8 | import java.util.List; |
| 8 | 9 | |
| 9 | -/** | |
| 10 | - * 客户限制配置 Base VO,提供给添加、修改、详细的子 VO 使用 | |
| 11 | - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | |
| 12 | - */ | |
| 10 | +@Schema(description = "管理后台 - 客户限制配置创建/更新 Request VO") | |
| 13 | 11 | @Data |
| 14 | -public class CrmCustomerLimitConfigBaseVO { | |
| 12 | +public class CrmCustomerLimitConfigSaveReqVO { | |
| 13 | + | |
| 14 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27930") | |
| 15 | + private Long id; | |
| 15 | 16 | |
| 16 | 17 | @Schema(description = "规则类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 17 | 18 | @NotNull(message = "规则类型不能为空") |
| 19 | + @DiffLogField(name = "规则类型") | |
| 18 | 20 | private Integer type; |
| 19 | 21 | |
| 22 | + // TODO @puhui999:可以把 Function 那的 functionName 搞成 NAME 枚举,这里直接引用。这样后续改动更方便哈。 | |
| 20 | 23 | @Schema(description = "规则适用人群") |
| 24 | + @DiffLogField(name = "规则适用人群", function = "getAdminUserById") | |
| 21 | 25 | private List<Long> userIds; |
| 22 | 26 | |
| 23 | 27 | @Schema(description = "规则适用部门") |
| 28 | + @DiffLogField(name = "规则适用部门", function = "getDeptById") | |
| 24 | 29 | private List<Long> deptIds; |
| 25 | 30 | |
| 26 | 31 | @Schema(description = "数量上限", requiredMode = Schema.RequiredMode.REQUIRED, example = "28384") |
| 27 | 32 | @NotNull(message = "数量上限不能为空") |
| 33 | + @DiffLogField(name = "数量上限") | |
| 28 | 34 | private Integer maxCount; |
| 29 | 35 | |
| 30 | 36 | @Schema(description = "成交客户是否占有拥有客户数(当 type = 1 时)") |
| 37 | + @DiffLogField(name = "成交客户是否占有拥有客户数") | |
| 31 | 38 | private Boolean dealCountEnabled; |
| 32 | 39 | |
| 33 | 40 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigUpdateReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig; | |
| 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 = "管理后台 - 客户限制配置更新 Request VO") | |
| 11 | -@Data | |
| 12 | -@EqualsAndHashCode(callSuper = true) | |
| 13 | -@ToString(callSuper = true) | |
| 14 | -public class CrmCustomerLimitConfigUpdateReqVO extends CrmCustomerLimitConfigBaseVO { | |
| 15 | - | |
| 16 | - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27930") | |
| 17 | - @NotNull(message = "编号不能为空") | |
| 18 | - private Long id; | |
| 19 | - | |
| 20 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigBaseVO.java deleted
| 1 | -package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig; | |
| 2 | - | |
| 3 | -import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | -import lombok.Data; | |
| 5 | - | |
| 6 | -import jakarta.validation.constraints.NotNull; | |
| 7 | - | |
| 8 | -/** | |
| 9 | - * 客户公海配置 Base VO,提供给添加、修改、详细的子 VO 使用 | |
| 10 | - * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 | |
| 11 | - */ | |
| 12 | -@Data | |
| 13 | -public class CrmCustomerPoolConfigBaseVO { | |
| 14 | - | |
| 15 | - @Schema(description = "是否启用客户公海", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 16 | - @NotNull(message = "是否启用客户公海不能为空") | |
| 17 | - private Boolean enabled; | |
| 18 | - | |
| 19 | - @Schema(description = "未跟进放入公海天数", example = "2") | |
| 20 | - private Integer contactExpireDays; | |
| 21 | - | |
| 22 | - @Schema(description = "未成交放入公海天数", example = "2") | |
| 23 | - private Integer dealExpireDays; | |
| 24 | - | |
| 25 | - @Schema(description = "是否开启提前提醒", example = "true") | |
| 26 | - private Boolean notifyEnabled; | |
| 27 | - | |
| 28 | - @Schema(description = "提前提醒天数", example = "2") | |
| 29 | - private Integer notifyDays; | |
| 30 | - | |
| 31 | -} |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigRespVO.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig; |
| 2 | 2 | |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | +import jakarta.validation.constraints.NotNull; | |
| 4 | 5 | import lombok.Data; |
| 5 | -import lombok.EqualsAndHashCode; | |
| 6 | -import lombok.ToString; | |
| 7 | 6 | |
| 8 | 7 | @Schema(description = "管理后台 - CRM 客户公海规则 Response VO") |
| 9 | 8 | @Data |
| 10 | -@EqualsAndHashCode(callSuper = true) | |
| 11 | -@ToString(callSuper = true) | |
| 12 | -public class CrmCustomerPoolConfigRespVO extends CrmCustomerPoolConfigBaseVO { | |
| 9 | +public class CrmCustomerPoolConfigRespVO { | |
| 10 | + | |
| 11 | + @Schema(description = "是否启用客户公海", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 12 | + @NotNull(message = "是否启用客户公海不能为空") | |
| 13 | + private Boolean enabled; | |
| 14 | + | |
| 15 | + @Schema(description = "未跟进放入公海天数", example = "2") | |
| 16 | + private Integer contactExpireDays; | |
| 17 | + | |
| 18 | + @Schema(description = "未成交放入公海天数", example = "2") | |
| 19 | + private Integer dealExpireDays; | |
| 20 | + | |
| 21 | + @Schema(description = "是否开启提前提醒", example = "true") | |
| 22 | + private Boolean notifyEnabled; | |
| 23 | + | |
| 24 | + @Schema(description = "提前提醒天数", example = "2") | |
| 25 | + private Integer notifyDays; | |
| 13 | 26 | |
| 14 | 27 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigSaveReqVO.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.BooleanUtil; |
| 4 | -import cn.hutool.core.util.ObjectUtil; | |
| 4 | +import com.fasterxml.jackson.annotation.JsonIgnore; | |
| 5 | +import com.mzt.logapi.starter.annotation.DiffLogField; | |
| 5 | 6 | import io.swagger.v3.oas.annotations.media.Schema; |
| 7 | +import jakarta.validation.constraints.AssertTrue; | |
| 8 | +import jakarta.validation.constraints.NotNull; | |
| 6 | 9 | import lombok.Data; |
| 7 | -import lombok.EqualsAndHashCode; | |
| 8 | -import lombok.ToString; | |
| 9 | 10 | |
| 10 | -import jakarta.validation.constraints.AssertTrue; | |
| 11 | 11 | import java.util.Objects; |
| 12 | 12 | |
| 13 | -@Schema(description = "管理后台 - CRM 客户公海配置的保存 Request VO") | |
| 13 | +@Schema(description = "管理后台 - CRM 客户公海配置的创建/更新 Request VO") | |
| 14 | 14 | @Data |
| 15 | -@EqualsAndHashCode(callSuper = true) | |
| 16 | -@ToString(callSuper = true) | |
| 17 | -public class CrmCustomerPoolConfigSaveReqVO extends CrmCustomerPoolConfigBaseVO { | |
| 18 | - | |
| 19 | - // TODO @puhui999:AssertTrue 必须 is 开头哈;注意需要 json 忽略下,避免被序列化; | |
| 20 | - @AssertTrue(message = "客户公海规则设置不正确") | |
| 21 | - // TODO @puhui999:这个方法,是不是拆成 2 个,一个校验 contactExpireDays、一个校验 dealExpireDays; | |
| 22 | - public boolean poolEnableValid() { | |
| 15 | +public class CrmCustomerPoolConfigSaveReqVO { | |
| 16 | + | |
| 17 | + @Schema(description = "是否启用客户公海", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | |
| 18 | + @DiffLogField(name = "是否启用客户公海") | |
| 19 | + @NotNull(message = "是否启用客户公海不能为空") | |
| 20 | + private Boolean enabled; | |
| 21 | + | |
| 22 | + @Schema(description = "未跟进放入公海天数", example = "2") | |
| 23 | + @DiffLogField(name = "未跟进放入公海天数") | |
| 24 | + private Integer contactExpireDays; | |
| 25 | + | |
| 26 | + @Schema(description = "未成交放入公海天数", example = "2") | |
| 27 | + @DiffLogField(name = "未成交放入公海天数") | |
| 28 | + private Integer dealExpireDays; | |
| 29 | + | |
| 30 | + @Schema(description = "是否开启提前提醒", example = "true") | |
| 31 | + @DiffLogField(name = "是否开启提前提醒") | |
| 32 | + private Boolean notifyEnabled; | |
| 33 | + | |
| 34 | + @Schema(description = "提前提醒天数", example = "2") | |
| 35 | + @DiffLogField(name = "提前提醒天数") | |
| 36 | + private Integer notifyDays; | |
| 37 | + | |
| 38 | + @AssertTrue(message = "未成交放入公海天数不能为空") | |
| 39 | + @JsonIgnore | |
| 40 | + public boolean isDealExpireDaysValid() { | |
| 41 | + if (!BooleanUtil.isTrue(getEnabled())) { | |
| 42 | + return true; | |
| 43 | + } | |
| 44 | + return Objects.nonNull(getDealExpireDays()); | |
| 45 | + } | |
| 46 | + | |
| 47 | + @AssertTrue(message = "未跟进放入公海天数不能为空") | |
| 48 | + @JsonIgnore | |
| 49 | + public boolean isContactExpireDaysValid() { | |
| 23 | 50 | if (!BooleanUtil.isTrue(getEnabled())) { |
| 24 | 51 | return true; |
| 25 | 52 | } |
| 26 | - return ObjectUtil.isAllNotEmpty(getContactExpireDays(), getDealExpireDays()); | |
| 53 | + return Objects.nonNull(getContactExpireDays()); | |
| 27 | 54 | } |
| 28 | 55 | |
| 29 | - @AssertTrue(message = "客户公海规则设置不正确") | |
| 30 | - // TODO @puhui999:这个方法,是不是改成 isNotifyDaysValid() 更好点?本质校验的是 notifyDays 是否为空 | |
| 31 | - public boolean notifyEnableValid() { | |
| 56 | + @AssertTrue(message = "提前提醒天数不能为空") | |
| 57 | + @JsonIgnore | |
| 58 | + public boolean isNotifyDaysValid() { | |
| 32 | 59 | if (!BooleanUtil.isTrue(getNotifyEnabled())) { |
| 33 | 60 | return true; |
| 34 | 61 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java
| ... | ... | @@ -103,7 +103,6 @@ public class CrmPermissionController { |
| 103 | 103 | // 拼接数据 |
| 104 | 104 | List<AdminUserRespDTO> userList = adminUserApi.getUserList(convertSet(permission, CrmPermissionDO::getUserId)); |
| 105 | 105 | Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId)); |
| 106 | - // TODO @puhui999:可能 postIds 为空的时候,会导致报错,看看怎么 fix 下 | |
| 107 | 106 | Set<Long> postIds = CollectionUtils.convertSetByFlatMap(userList, AdminUserRespDTO::getPostIds, Collection::stream); |
| 108 | 107 | Map<Long, PostRespDTO> postMap = postApi.getPostMap(postIds); |
| 109 | 108 | return success(CrmPermissionConvert.INSTANCE.convert(permission, userList, deptMap, postMap)); | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.convert.clue; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; | |
| 4 | +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueExcelVO; | |
| 5 | +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueRespVO; | |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; | |
| 7 | +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; | |
| 5 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; |
| 6 | 9 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; |
| 7 | 10 | import org.mapstruct.Mapper; |
| ... | ... | @@ -20,9 +23,8 @@ public interface CrmClueConvert { |
| 20 | 23 | |
| 21 | 24 | CrmClueConvert INSTANCE = Mappers.getMapper(CrmClueConvert.class); |
| 22 | 25 | |
| 23 | - CrmClueDO convert(CrmClueCreateReqVO bean); | |
| 24 | - | |
| 25 | - CrmClueDO convert(CrmClueUpdateReqVO bean); | |
| 26 | + // TODO @min:这几个 convert,都使用 BeanUtils 替代哈 | |
| 27 | + CrmClueDO convert(CrmClueSaveReqVO bean); | |
| 26 | 28 | |
| 27 | 29 | CrmClueRespVO convert(CrmClueDO bean); |
| 28 | 30 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java
| ... | ... | @@ -29,10 +29,6 @@ public interface CrmContactConvert { |
| 29 | 29 | |
| 30 | 30 | CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class); |
| 31 | 31 | |
| 32 | - CrmContactDO convert(CrmContactCreateReqVO bean); | |
| 33 | - | |
| 34 | - CrmContactDO convert(CrmContactUpdateReqVO bean); | |
| 35 | - | |
| 36 | 32 | CrmContactRespVO convert(CrmContactDO bean); |
| 37 | 33 | |
| 38 | 34 | List<CrmContactRespVO> convertList(List<CrmContactDO> list); | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java
| ... | ... | @@ -2,9 +2,12 @@ package cn.iocoder.yudao.module.crm.convert.customer; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; |
| 5 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; | |
| 5 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerRespVO; | |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; | |
| 7 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; | |
| 6 | 8 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig.CrmCustomerPoolConfigRespVO; |
| 7 | 9 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig.CrmCustomerPoolConfigSaveReqVO; |
| 10 | +import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; | |
| 8 | 11 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 9 | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; |
| 10 | 13 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; |
| ... | ... | @@ -14,7 +17,6 @@ import org.mapstruct.Mapper; |
| 14 | 17 | import org.mapstruct.Mapping; |
| 15 | 18 | import org.mapstruct.factory.Mappers; |
| 16 | 19 | |
| 17 | -import java.util.List; | |
| 18 | 20 | import java.util.Map; |
| 19 | 21 | |
| 20 | 22 | import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; |
| ... | ... | @@ -29,18 +31,17 @@ public interface CrmCustomerConvert { |
| 29 | 31 | |
| 30 | 32 | CrmCustomerConvert INSTANCE = Mappers.getMapper(CrmCustomerConvert.class); |
| 31 | 33 | |
| 32 | - CrmCustomerDO convert(CrmCustomerCreateReqVO bean); | |
| 33 | - | |
| 34 | - CrmCustomerDO convert(CrmCustomerUpdateReqVO bean); | |
| 34 | + // TODO @puhui999:可以清理掉可以用 BeanUtil 替代的方法哈 | |
| 35 | + CrmCustomerDO convert(CrmCustomerSaveReqVO bean); | |
| 35 | 36 | |
| 36 | 37 | CrmCustomerRespVO convert(CrmCustomerDO bean); |
| 37 | 38 | |
| 38 | 39 | /** |
| 39 | 40 | * 设置用户信息 |
| 40 | 41 | * |
| 41 | - * @param customer CRM 客户 Response VO | |
| 42 | - * @param userMap 用户信息 map | |
| 43 | - * @param deptMap 用户部门信息 map | |
| 42 | + * @param customer CRM 客户 Response VO | |
| 43 | + * @param userMap 用户信息 map | |
| 44 | + * @param deptMap 用户部门信息 map | |
| 44 | 45 | */ |
| 45 | 46 | static void setUserInfo(CrmCustomerRespVO customer, Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) { |
| 46 | 47 | customer.setAreaName(AreaUtils.format(customer.getAreaId())); |
| ... | ... | @@ -51,8 +52,6 @@ public interface CrmCustomerConvert { |
| 51 | 52 | findAndThen(userMap, Long.parseLong(customer.getCreator()), user -> customer.setCreatorName(user.getNickname())); |
| 52 | 53 | } |
| 53 | 54 | |
| 54 | - List<CrmCustomerExcelVO> convertList02(List<CrmCustomerDO> list); | |
| 55 | - | |
| 56 | 55 | @Mapping(target = "bizId", source = "reqVO.id") |
| 57 | 56 | CrmPermissionTransferReqBO convert(CrmCustomerTransferReqVO reqVO, Long userId); |
| 58 | 57 | |
| ... | ... | @@ -66,9 +65,12 @@ public interface CrmCustomerConvert { |
| 66 | 65 | } |
| 67 | 66 | |
| 68 | 67 | default PageResult<CrmCustomerRespVO> convertPage(PageResult<CrmCustomerDO> pageResult, Map<Long, AdminUserRespDTO> userMap, |
| 69 | - Map<Long, DeptRespDTO> deptMap) { | |
| 68 | + Map<Long, DeptRespDTO> deptMap, Map<Long, Long> poolDayMap) { | |
| 70 | 69 | PageResult<CrmCustomerRespVO> result = convertPage(pageResult); |
| 71 | - result.getList().forEach(item -> setUserInfo(item, userMap, deptMap)); | |
| 70 | + result.getList().forEach(item -> { | |
| 71 | + setUserInfo(item, userMap, deptMap); | |
| 72 | + findAndThen(poolDayMap, item.getId(), item::setPoolDay); | |
| 73 | + }); | |
| 72 | 74 | return result; |
| 73 | 75 | } |
| 74 | 76 | |
| ... | ... | @@ -76,6 +78,8 @@ public interface CrmCustomerConvert { |
| 76 | 78 | |
| 77 | 79 | CrmCustomerPoolConfigDO convert(CrmCustomerPoolConfigSaveReqVO updateReqVO); |
| 78 | 80 | |
| 79 | - List<CrmCustomerQueryAllRespVO> convertQueryAll(List<CrmCustomerDO> crmCustomerDO); | |
| 81 | + // TODO @min:使用 BeanUtils 拷贝哈。我们慢慢简单的对象,不再直接基于 convert 做啦。 | |
| 82 | + @Mapping(ignore = true, target = "id") | |
| 83 | + CrmCustomerSaveReqVO convert(CrmClueDO bean); | |
| 80 | 84 | |
| 81 | 85 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerLimitConfigConvert.java
| ... | ... | @@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.crm.convert.customer; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 5 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; | |
| 6 | 5 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigRespVO; |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO; | |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigSaveReqVO; | |
| 8 | 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; |
| 9 | 8 | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| 10 | 9 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| ... | ... | @@ -24,9 +23,8 @@ public interface CrmCustomerLimitConfigConvert { |
| 24 | 23 | |
| 25 | 24 | CrmCustomerLimitConfigConvert INSTANCE = Mappers.getMapper(CrmCustomerLimitConfigConvert.class); |
| 26 | 25 | |
| 27 | - CrmCustomerLimitConfigDO convert(CrmCustomerLimitConfigCreateReqVO bean); | |
| 28 | - | |
| 29 | - CrmCustomerLimitConfigDO convert(CrmCustomerLimitConfigUpdateReqVO bean); | |
| 26 | + // TODO @puhui999:可以把 convert 改成 BeanUtils | |
| 27 | + CrmCustomerLimitConfigDO convert(CrmCustomerLimitConfigSaveReqVO bean); | |
| 30 | 28 | |
| 31 | 29 | CrmCustomerLimitConfigRespVO convert(CrmCustomerLimitConfigDO bean); |
| 32 | 30 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.convert.permission; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 3 | 4 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 4 | 5 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| 5 | 6 | import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionCreateReqVO; |
| ... | ... | @@ -15,6 +16,7 @@ import com.google.common.collect.Multimaps; |
| 15 | 16 | import org.mapstruct.Mapper; |
| 16 | 17 | import org.mapstruct.factory.Mappers; |
| 17 | 18 | |
| 19 | +import java.util.Collections; | |
| 18 | 20 | import java.util.List; |
| 19 | 21 | import java.util.Map; |
| 20 | 22 | |
| ... | ... | @@ -46,10 +48,12 @@ public interface CrmPermissionConvert { |
| 46 | 48 | return CollectionUtils.convertList(convert(permission), item -> { |
| 47 | 49 | findAndThen(userMap, item.getUserId(), user -> { |
| 48 | 50 | item.setNickname(user.getNickname()); |
| 49 | - findAndThen(deptMap, user.getDeptId(), deptRespDTO -> { | |
| 50 | - item.setDeptName(deptRespDTO.getName()); | |
| 51 | - }); | |
| 51 | + findAndThen(deptMap, user.getDeptId(), deptRespDTO -> item.setDeptName(deptRespDTO.getName())); | |
| 52 | 52 | List<PostRespDTO> postRespList = MapUtils.getList(Multimaps.forMap(postMap), user.getPostIds()); |
| 53 | + if (CollUtil.isEmpty(postRespList)) { | |
| 54 | + item.setPostNames(Collections.emptySet()); | |
| 55 | + return; | |
| 56 | + } | |
| 53 | 57 | item.setPostNames(CollectionUtils.convertSet(postRespList, PostRespDTO::getName)); |
| 54 | 58 | }); |
| 55 | 59 | return item; | ... | ... |
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> { |
| 60 | 60 | return selectJoinList(CrmContractDO.class, mpjLambdaWrapperX); |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | + default Long selectCountByContactId(Long contactId) { | |
| 64 | + return selectCount(CrmContractDO::getContactId, contactId); | |
| 65 | + } | |
| 66 | + | |
| 63 | 67 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java
| ... | ... | @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 5 | 5 | import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; |
| 6 | 6 | import org.apache.ibatis.annotations.Mapper; |
| 7 | 7 | |
| 8 | +import java.util.Collection; | |
| 8 | 9 | import java.util.List; |
| 9 | 10 | |
| 10 | 11 | /** |
| ... | ... | @@ -28,6 +29,12 @@ public interface CrmPermissionMapper extends BaseMapperX<CrmPermissionDO> { |
| 28 | 29 | .eq(CrmPermissionDO::getBizId, bizId)); |
| 29 | 30 | } |
| 30 | 31 | |
| 32 | + default List<CrmPermissionDO> selectByBizTypeAndBizIds(Integer bizType, Collection<Long> bizIds) { | |
| 33 | + return selectList(new LambdaQueryWrapperX<CrmPermissionDO>() | |
| 34 | + .eq(CrmPermissionDO::getBizType, bizType) | |
| 35 | + .in(CrmPermissionDO::getBizId, bizIds)); | |
| 36 | + } | |
| 37 | + | |
| 31 | 38 | default List<CrmPermissionDO> selectListByBizTypeAndUserId(Integer bizType, Long userId) { |
| 32 | 39 | return selectList(new LambdaQueryWrapperX<CrmPermissionDO>() |
| 33 | 40 | .eq(CrmPermissionDO::getBizType, bizType) | ... | ... |
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 | +@Component | |
| 16 | +@Slf4j | |
| 17 | +public class CrmBooleanParseFunction implements IParseFunction { | |
| 18 | + | |
| 19 | + public static final String NAME = "getBooleanById"; | |
| 20 | + | |
| 21 | + @Override | |
| 22 | + public boolean executeBefore() { | |
| 23 | + return true; // 先转换值后对比 | |
| 24 | + } | |
| 25 | + | |
| 26 | + @Override | |
| 27 | + public String functionName() { | |
| 28 | + return NAME; | |
| 29 | + } | |
| 30 | + | |
| 31 | + @Override | |
| 32 | + public String apply(Object value) { | |
| 33 | + if (StrUtil.isEmptyIfStr(value)) { | |
| 34 | + return ""; | |
| 35 | + } | |
| 36 | + return DictFrameworkUtils.getDictDataLabel(DictTypeConstants.BOOLEAN_STRING, value.toString()); | |
| 37 | + } | |
| 38 | + | |
| 39 | +} | ... | ... |
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 com.mzt.logapi.service.IParseFunction; | |
| 7 | +import jakarta.annotation.Resource; | |
| 8 | +import lombok.extern.slf4j.Slf4j; | |
| 9 | +import org.springframework.stereotype.Component; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 行业的 {@link IParseFunction} 实现类 | |
| 13 | + * | |
| 14 | + * @author HUIHUI | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +@Slf4j | |
| 18 | +public class CrmContactParseFunction implements IParseFunction { | |
| 19 | + | |
| 20 | + public static final String NAME = "getContactById"; | |
| 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 NAME; | |
| 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.module.crm.dal.dataobject.customer.CrmCustomerDO; | |
| 5 | +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; | |
| 6 | +import com.mzt.logapi.service.IParseFunction; | |
| 7 | +import jakarta.annotation.Resource; | |
| 8 | +import lombok.extern.slf4j.Slf4j; | |
| 9 | +import org.springframework.stereotype.Component; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 行业的 {@link IParseFunction} 实现类 | |
| 13 | + * | |
| 14 | + * @author HUIHUI | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +@Slf4j | |
| 18 | +public class CrmCustomerParseFunction implements IParseFunction { | |
| 19 | + | |
| 20 | + public static final String NAME = "getCustomerById"; | |
| 21 | + | |
| 22 | + @Resource | |
| 23 | + private CrmCustomerService customerService; | |
| 24 | + | |
| 25 | + @Override | |
| 26 | + public boolean executeBefore() { | |
| 27 | + return true; // 先转换值后对比 | |
| 28 | + } | |
| 29 | + | |
| 30 | + @Override | |
| 31 | + public String functionName() { | |
| 32 | + return NAME; | |
| 33 | + } | |
| 34 | + | |
| 35 | + @Override | |
| 36 | + public String apply(Object value) { | |
| 37 | + if (StrUtil.isEmptyIfStr(value)) { | |
| 38 | + return ""; | |
| 39 | + } | |
| 40 | + CrmCustomerDO crmCustomerDO = customerService.getCustomer(Long.parseLong(value.toString())); | |
| 41 | + return crmCustomerDO == null ? "" : crmCustomerDO.getName(); | |
| 42 | + } | |
| 43 | + | |
| 44 | +} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmIndustryParseFunction.java
| ... | ... | @@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_I |
| 13 | 13 | * |
| 14 | 14 | * @author HUIHUI |
| 15 | 15 | */ |
| 16 | -@Slf4j | |
| 17 | 16 | @Component |
| 17 | +@Slf4j | |
| 18 | 18 | public class CrmIndustryParseFunction implements IParseFunction { |
| 19 | 19 | |
| 20 | + public static final String NAME = "getIndustryById"; | |
| 21 | + | |
| 20 | 22 | @Override |
| 21 | 23 | public boolean executeBefore() { |
| 22 | 24 | return true; // 先转换值后对比 |
| ... | ... | @@ -24,7 +26,7 @@ public class CrmIndustryParseFunction implements IParseFunction { |
| 24 | 26 | |
| 25 | 27 | @Override |
| 26 | 28 | public String functionName() { |
| 27 | - return "getIndustryById"; | |
| 29 | + return NAME; | |
| 28 | 30 | } |
| 29 | 31 | |
| 30 | 32 | @Override | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmLevelParseFunction.java
| ... | ... | @@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_L |
| 13 | 13 | * |
| 14 | 14 | * @author HUIHUI |
| 15 | 15 | */ |
| 16 | -@Slf4j | |
| 17 | 16 | @Component |
| 17 | +@Slf4j | |
| 18 | 18 | public class CrmLevelParseFunction implements IParseFunction { |
| 19 | 19 | |
| 20 | + public static final String NAME = "getLevel"; | |
| 21 | + | |
| 20 | 22 | @Override |
| 21 | 23 | public boolean executeBefore() { |
| 22 | 24 | return true; // 先转换值后对比 |
| ... | ... | @@ -24,7 +26,7 @@ public class CrmLevelParseFunction implements IParseFunction { |
| 24 | 26 | |
| 25 | 27 | @Override |
| 26 | 28 | public String functionName() { |
| 27 | - return "getLevel"; | |
| 29 | + return NAME; | |
| 28 | 30 | } |
| 29 | 31 | |
| 30 | 32 | @Override | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSexParseFunction.java
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 | +/** | |
| 11 | + * 行业的 {@link IParseFunction} 实现类 | |
| 12 | + * | |
| 13 | + * @author HUIHUI | |
| 14 | + */ | |
| 15 | +@Component | |
| 16 | +@Slf4j | |
| 17 | +public class CrmSexParseFunction implements IParseFunction { | |
| 18 | + | |
| 19 | + public static final String NAME = "getSexById"; | |
| 20 | + | |
| 21 | + @Override | |
| 22 | + public boolean executeBefore() { | |
| 23 | + return true; // 先转换值后对比 | |
| 24 | + } | |
| 25 | + | |
| 26 | + @Override | |
| 27 | + public String functionName() { | |
| 28 | + return NAME; | |
| 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/CrmSourceParseFunction.java
| ... | ... | @@ -13,10 +13,12 @@ import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_S |
| 13 | 13 | * |
| 14 | 14 | * @author HUIHUI |
| 15 | 15 | */ |
| 16 | -@Slf4j | |
| 17 | 16 | @Component |
| 17 | +@Slf4j | |
| 18 | 18 | public class CrmSourceParseFunction implements IParseFunction { |
| 19 | 19 | |
| 20 | + public static final String NAME = "getSource"; | |
| 21 | + | |
| 20 | 22 | @Override |
| 21 | 23 | public boolean executeBefore() { |
| 22 | 24 | return true; // 先转换值后对比 |
| ... | ... | @@ -24,7 +26,7 @@ public class CrmSourceParseFunction implements IParseFunction { |
| 24 | 26 | |
| 25 | 27 | @Override |
| 26 | 28 | public String functionName() { |
| 27 | - return "getSource"; | |
| 29 | + return NAME; | |
| 28 | 30 | } |
| 29 | 31 | |
| 30 | 32 | @Override | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSysUserParseFunction.java
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.system.api.user.AdminUserApi; | |
| 5 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | |
| 6 | +import com.mzt.logapi.service.IParseFunction; | |
| 7 | +import jakarta.annotation.Resource; | |
| 8 | +import lombok.extern.slf4j.Slf4j; | |
| 9 | +import org.springframework.stereotype.Component; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * 行业的 {@link IParseFunction} 实现类 | |
| 13 | + * | |
| 14 | + * @author HUIHUI | |
| 15 | + */ | |
| 16 | +@Component | |
| 17 | +@Slf4j | |
| 18 | +public class CrmSysUserParseFunction implements IParseFunction { | |
| 19 | + | |
| 20 | + public static final String NAME = "getUserById"; | |
| 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 NAME; | |
| 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/framework/permission/core/aop/CrmPermissionAspect.java
| ... | ... | @@ -18,12 +18,10 @@ import org.aspectj.lang.annotation.Aspect; |
| 18 | 18 | import org.aspectj.lang.annotation.Before; |
| 19 | 19 | import org.springframework.stereotype.Component; |
| 20 | 20 | |
| 21 | -import java.util.ArrayList; | |
| 22 | -import java.util.List; | |
| 23 | -import java.util.Map; | |
| 21 | +import java.util.*; | |
| 24 | 22 | |
| 25 | 23 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 26 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; | |
| 24 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | |
| 27 | 25 | import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; |
| 28 | 26 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED; |
| 29 | 27 | |
| ... | ... | @@ -42,28 +40,40 @@ public class CrmPermissionAspect { |
| 42 | 40 | |
| 43 | 41 | @Before("@annotation(crmPermission)") |
| 44 | 42 | public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) { |
| 45 | - // 获取相关属性值 | |
| 43 | + // 1.1 获取相关属性值 | |
| 46 | 44 | Map<String, Object> expressionValues = parseExpressions(joinPoint, crmPermission); |
| 47 | 45 | Integer bizType = StrUtil.isEmpty(crmPermission.bizTypeValue()) ? |
| 48 | 46 | crmPermission.bizType()[0].getType() : (Integer) expressionValues.get(crmPermission.bizTypeValue()); // 模块类型 |
| 49 | - Long bizId = (Long) expressionValues.get(crmPermission.bizId()); // 模块数据编号 | |
| 47 | + // 1.2 处理兼容多个 bizId 的情况 | |
| 48 | + Object object = expressionValues.get(crmPermission.bizId()); // 模块数据编号 | |
| 49 | + Set<Long> bizIds = new HashSet<>(); | |
| 50 | + if (object instanceof Collection<?>) { | |
| 51 | + bizIds.addAll(convertSet((Collection<?>) object, item -> Long.parseLong(item.toString()))); | |
| 52 | + } else { | |
| 53 | + bizIds.add(Long.parseLong(object.toString())); | |
| 54 | + } | |
| 50 | 55 | Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别 |
| 51 | 56 | |
| 52 | - // 1.1 如果是超级管理员则直接通过 | |
| 57 | + // 2. 逐个校验权限 | |
| 58 | + List<CrmPermissionDO> permissionList = crmPermissionService.getPermissionListByBiz(bizType, bizIds); | |
| 59 | + Map<Long, List<CrmPermissionDO>> multiMap = convertMultiMap(permissionList, CrmPermissionDO::getBizId); | |
| 60 | + bizIds.forEach(bizId -> validatePermission(bizType, multiMap.get(bizId), permissionLevel)); | |
| 61 | + } | |
| 62 | + | |
| 63 | + private void validatePermission(Integer bizType, List<CrmPermissionDO> bizPermissions, Integer permissionLevel) { | |
| 64 | + // 1. 如果是超级管理员则直接通过 | |
| 53 | 65 | if (CrmPermissionUtils.isCrmAdmin()) { |
| 54 | 66 | return; |
| 55 | 67 | } |
| 56 | - // 1.2 获取数据权限 | |
| 57 | - List<CrmPermissionDO> bizPermissions = crmPermissionService.getPermissionListByBiz(bizType, bizId); | |
| 58 | - if (CollUtil.isEmpty(bizPermissions)) { // 没有数据权限的情况 | |
| 68 | + // 1.1 没有数据权限的情况 | |
| 69 | + if (CollUtil.isEmpty(bizPermissions)) { | |
| 59 | 70 | // 公海数据如果没有团队成员大家也因该有读权限才对 |
| 60 | 71 | if (CrmPermissionLevelEnum.isRead(permissionLevel)) { |
| 61 | 72 | return; |
| 62 | 73 | } |
| 63 | - | |
| 64 | 74 | // 没有数据权限的情况下超出了读权限直接报错,避免后面校验空指针 |
| 65 | 75 | throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.getNameByType(bizType)); |
| 66 | - } else { // 有数据权限但是没有负责人的情况 | |
| 76 | + } else { // 1.2 有数据权限但是没有负责人的情况 | |
| 67 | 77 | if (!anyMatch(bizPermissions, item -> CrmPermissionLevelEnum.isOwner(item.getLevel()))) { |
| 68 | 78 | if (CrmPermissionLevelEnum.isRead(permissionLevel)) { |
| 69 | 79 | return; |
| ... | ... | @@ -91,9 +101,8 @@ public class CrmPermissionAspect { |
| 91 | 101 | } |
| 92 | 102 | } |
| 93 | 103 | } |
| 94 | - // 2.4 没有权限! | |
| 95 | - // 打个 info 日志,方便后续排查问题、审计 | |
| 96 | - log.info("[doBefore][userId({}) 要求权限({}) 实际权限({}) 数据校验错误]", | |
| 104 | + // 2.4 没有权限,抛出异常 | |
| 105 | + log.info("[doBefore][userId({}) 要求权限({}) 实际权限({}) 数据校验错误]", // 打个 info 日志,方便后续排查问题、审计 | |
| 97 | 106 | getUserId(), permissionLevel, toJsonString(userPermission)); |
| 98 | 107 | throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.getNameByType(bizType)); |
| 99 | 108 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.service.clue; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; | |
| 5 | 4 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; |
| 5 | +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; | |
| 6 | 6 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; | |
| 7 | +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransformReqVO; | |
| 8 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; |
| 9 | 9 | import jakarta.validation.Valid; |
| 10 | 10 | |
| ... | ... | @@ -24,14 +24,14 @@ public interface CrmClueService { |
| 24 | 24 | * @param createReqVO 创建信息 |
| 25 | 25 | * @return 编号 |
| 26 | 26 | */ |
| 27 | - Long createClue(@Valid CrmClueCreateReqVO createReqVO); | |
| 27 | + Long createClue(@Valid CrmClueSaveReqVO createReqVO); | |
| 28 | 28 | |
| 29 | 29 | /** |
| 30 | 30 | * 更新线索 |
| 31 | 31 | * |
| 32 | 32 | * @param updateReqVO 更新信息 |
| 33 | 33 | */ |
| 34 | - void updateClue(@Valid CrmClueUpdateReqVO updateReqVO); | |
| 34 | + void updateClue(@Valid CrmClueSaveReqVO updateReqVO); | |
| 35 | 35 | |
| 36 | 36 | /** |
| 37 | 37 | * 删除线索 |
| ... | ... | @@ -73,4 +73,12 @@ public interface CrmClueService { |
| 73 | 73 | */ |
| 74 | 74 | void transferClue(CrmClueTransferReqVO reqVO, Long userId); |
| 75 | 75 | |
| 76 | + /** | |
| 77 | + * 线索转化为客户 | |
| 78 | + * | |
| 79 | + * @param reqVO 线索编号 | |
| 80 | + * @param userId 用户编号 | |
| 81 | + */ | |
| 82 | + void translate(CrmClueTransformReqVO reqVO, Long userId); | |
| 83 | + | |
| 76 | 84 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java
| ... | ... | @@ -3,11 +3,12 @@ package cn.iocoder.yudao.module.crm.service.clue; |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.collection.ListUtil; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; | |
| 7 | 6 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; |
| 7 | +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; | |
| 8 | 8 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; |
| 9 | -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; | |
| 9 | +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransformReqVO; | |
| 10 | 10 | import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; |
| 11 | +import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; | |
| 11 | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; |
| 12 | 13 | import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; |
| 13 | 14 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| ... | ... | @@ -15,15 +16,20 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 15 | 16 | import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 16 | 17 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 17 | 18 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 19 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 18 | 20 | import jakarta.annotation.Resource; |
| 19 | 21 | import org.springframework.stereotype.Service; |
| 22 | +import org.springframework.transaction.annotation.Transactional; | |
| 20 | 23 | import org.springframework.validation.annotation.Validated; |
| 21 | 24 | |
| 22 | 25 | import java.util.Collection; |
| 23 | 26 | import java.util.List; |
| 27 | +import java.util.Objects; | |
| 24 | 28 | |
| 25 | 29 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 26 | 30 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CLUE_NOT_EXISTS; |
| 31 | +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; | |
| 32 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; | |
| 27 | 33 | |
| 28 | 34 | /** |
| 29 | 35 | * 线索 Service 实现类 |
| ... | ... | @@ -39,13 +45,19 @@ public class CrmClueServiceImpl implements CrmClueService { |
| 39 | 45 | |
| 40 | 46 | @Resource |
| 41 | 47 | private CrmCustomerService customerService; |
| 48 | + | |
| 42 | 49 | @Resource |
| 43 | 50 | private CrmPermissionService crmPermissionService; |
| 44 | 51 | |
| 52 | + @Resource | |
| 53 | + private AdminUserApi adminUserApi; | |
| 54 | + | |
| 45 | 55 | @Override |
| 46 | - public Long createClue(CrmClueCreateReqVO createReqVO) { | |
| 47 | - // 校验客户是否存在 | |
| 48 | - customerService.validateCustomer(createReqVO.getCustomerId()); | |
| 56 | + // TODO @min:补充相关几个方法的操作日志; | |
| 57 | + public Long createClue(CrmClueSaveReqVO createReqVO) { | |
| 58 | + // 校验关联数据 | |
| 59 | + validateRelationDataExists(createReqVO); | |
| 60 | + | |
| 49 | 61 | // 插入 |
| 50 | 62 | CrmClueDO clue = CrmClueConvert.INSTANCE.convert(createReqVO); |
| 51 | 63 | clueMapper.insert(clue); |
| ... | ... | @@ -55,11 +67,11 @@ public class CrmClueServiceImpl implements CrmClueService { |
| 55 | 67 | |
| 56 | 68 | @Override |
| 57 | 69 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) |
| 58 | - public void updateClue(CrmClueUpdateReqVO updateReqVO) { | |
| 59 | - // 校验存在 | |
| 70 | + public void updateClue(CrmClueSaveReqVO updateReqVO) { | |
| 71 | + // 校验线索是否存在 | |
| 60 | 72 | validateClueExists(updateReqVO.getId()); |
| 61 | - // 校验客户是否存在 | |
| 62 | - customerService.validateCustomer(updateReqVO.getCustomerId()); | |
| 73 | + // 校验关联数据 | |
| 74 | + validateRelationDataExists(updateReqVO); | |
| 63 | 75 | |
| 64 | 76 | // 更新 |
| 65 | 77 | CrmClueDO updateObj = CrmClueConvert.INSTANCE.convert(updateReqVO); |
| ... | ... | @@ -108,12 +120,47 @@ public class CrmClueServiceImpl implements CrmClueService { |
| 108 | 120 | validateClueExists(reqVO.getId()); |
| 109 | 121 | |
| 110 | 122 | // 2.1 数据权限转移 |
| 111 | - crmPermissionService.transferPermission( | |
| 112 | - CrmClueConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_LEADS.getType())); | |
| 123 | + crmPermissionService.transferPermission(CrmClueConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_LEADS.getType())); | |
| 113 | 124 | // 2.2 设置新的负责人 |
| 114 | 125 | clueMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); |
| 115 | 126 | |
| 116 | 127 | // 3. TODO 记录转移日志 |
| 117 | 128 | } |
| 118 | 129 | |
| 130 | + @Override | |
| 131 | + @Transactional(rollbackFor = Exception.class) | |
| 132 | + public void translate(CrmClueTransformReqVO reqVO, Long userId) { | |
| 133 | + // 校验线索都存在 | |
| 134 | + List<CrmClueDO> clues = getClueList(reqVO.getIds(), userId); | |
| 135 | + if (CollUtil.isEmpty(clues)) { | |
| 136 | + throw exception(CLUE_NOT_EXISTS); | |
| 137 | + } | |
| 138 | + // TODO @min:如果已经转化,则不能重复转化 | |
| 139 | + | |
| 140 | + // 遍历线索,创建对应的客户 | |
| 141 | + clues.forEach(clue -> { | |
| 142 | + // 创建客户 | |
| 143 | + customerService.createCustomer(CrmCustomerConvert.INSTANCE.convert(clue), userId); | |
| 144 | + // 更新线索状态 | |
| 145 | + // TODO @min:新建一个 CrmClueDO 去更新。尽量规避直接用原本的对象去更新。因为这样万一并发更新,会存在覆盖的问题。 | |
| 146 | + // TODO @puhui999:如果有跟进记录,需要一起转过去; | |
| 147 | + clue.setTransformStatus(Boolean.TRUE); | |
| 148 | + clueMapper.updateById(clue); | |
| 149 | + }); | |
| 150 | + } | |
| 151 | + | |
| 152 | + private void validateRelationDataExists(CrmClueSaveReqVO reqVO) { | |
| 153 | + // 校验客户 | |
| 154 | + if (Objects.nonNull(reqVO.getCustomerId()) && | |
| 155 | + Objects.isNull(customerService.getCustomer(reqVO.getCustomerId()))) { | |
| 156 | + throw exception(CUSTOMER_NOT_EXISTS); | |
| 157 | + } | |
| 158 | + // 校验负责人 | |
| 159 | + // 2. 校验负责人 | |
| 160 | + if (Objects.nonNull(reqVO.getOwnerUserId()) && | |
| 161 | + Objects.isNull(adminUserApi.getUser(reqVO.getOwnerUserId()))) { | |
| 162 | + throw exception(USER_NOT_EXISTS); | |
| 163 | + } | |
| 164 | + } | |
| 165 | + | |
| 119 | 166 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java
| ... | ... | @@ -28,6 +28,13 @@ public interface CrmContactBusinessService { |
| 28 | 28 | void deleteContactBusinessList(@Valid CrmContactBusinessReqVO deleteReqVO); |
| 29 | 29 | |
| 30 | 30 | /** |
| 31 | + * 删除联系人与商机的关联,基于联系人编号 | |
| 32 | + * | |
| 33 | + * @param contactId 联系人编号 | |
| 34 | + */ | |
| 35 | + void deleteContactBusinessByContactId(Long contactId); | |
| 36 | + | |
| 37 | + /** | |
| 31 | 38 | * 获得联系人与商机的关联列表,基于联系人编号 |
| 32 | 39 | * |
| 33 | 40 | * @param contactId 联系人编号 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java
| ... | ... | @@ -76,6 +76,11 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService |
| 76 | 76 | } |
| 77 | 77 | |
| 78 | 78 | @Override |
| 79 | + public void deleteContactBusinessByContactId(Long contactId) { | |
| 80 | + contactBusinessMapper.delete(CrmContactBusinessDO::getContactId,contactId); | |
| 81 | + } | |
| 82 | + | |
| 83 | + @Override | |
| 79 | 84 | public List<CrmContactBusinessDO> getContactBusinessListByContactId(Long contactId) { |
| 80 | 85 | return contactBusinessMapper.selectListByContactId(contactId); |
| 81 | 86 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.service.contact; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO; | |
| 5 | -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; | |
| 6 | -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; | |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO; | |
| 4 | +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; | |
| 8 | 5 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; |
| 9 | 6 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 10 | 7 | import jakarta.validation.Valid; |
| ... | ... | @@ -26,14 +23,14 @@ public interface CrmContactService { |
| 26 | 23 | * @param userId 用户编号 |
| 27 | 24 | * @return 编号 |
| 28 | 25 | */ |
| 29 | - Long createContact(@Valid CrmContactCreateReqVO createReqVO, Long userId); | |
| 26 | + Long createContact(@Valid CrmContactSaveReqVO createReqVO, Long userId); | |
| 30 | 27 | |
| 31 | 28 | /** |
| 32 | 29 | * 更新联系人 |
| 33 | 30 | * |
| 34 | 31 | * @param updateReqVO 更新信息 |
| 35 | 32 | */ |
| 36 | - void updateContact(@Valid CrmContactUpdateReqVO updateReqVO); | |
| 33 | + void updateContact(@Valid CrmContactSaveReqVO updateReqVO); | |
| 37 | 34 | |
| 38 | 35 | /** |
| 39 | 36 | * 删除联系人 |
| ... | ... | @@ -60,6 +57,13 @@ public interface CrmContactService { |
| 60 | 57 | List<CrmContactDO> getContactList(Collection<Long> ids, Long userId); |
| 61 | 58 | |
| 62 | 59 | /** |
| 60 | + * 获得联系人列表 | |
| 61 | + * | |
| 62 | + * @return 联系人列表 | |
| 63 | + */ | |
| 64 | + List<CrmContactDO> getContactList(); | |
| 65 | + | |
| 66 | + /** | |
| 63 | 67 | * 获得联系人分页 |
| 64 | 68 | * |
| 65 | 69 | * 数据权限:基于 {@link CrmContactDO} | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
| ... | ... | @@ -3,17 +3,26 @@ package cn.iocoder.yudao.module.crm.service.contact; |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.collection.ListUtil; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; | |
| 6 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 7 | +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO; | |
| 8 | +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; | |
| 9 | +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReqVO; | |
| 10 | +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; | |
| 7 | 11 | import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert; |
| 8 | 12 | import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; |
| 9 | 13 | import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; |
| 10 | 14 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 11 | 15 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 12 | 16 | import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 17 | +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; | |
| 18 | +import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; | |
| 13 | 19 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; |
| 14 | 20 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 15 | 21 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 16 | 22 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 23 | +import com.mzt.logapi.context.LogRecordContext; | |
| 24 | +import com.mzt.logapi.service.impl.DiffParseFunction; | |
| 25 | +import com.mzt.logapi.starter.annotation.LogRecord; | |
| 17 | 26 | import jakarta.annotation.Resource; |
| 18 | 27 | import org.springframework.stereotype.Service; |
| 19 | 28 | import org.springframework.transaction.annotation.Transactional; |
| ... | ... | @@ -23,9 +32,10 @@ import java.util.Collection; |
| 23 | 32 | import java.util.List; |
| 24 | 33 | |
| 25 | 34 | 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; | |
| 35 | +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; | |
| 36 | +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT_TYPE; | |
| 28 | 37 | import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; |
| 38 | +import static java.util.Collections.singletonList; | |
| 29 | 39 | |
| 30 | 40 | /** |
| 31 | 41 | * CRM 联系人 Service 实现类 |
| ... | ... | @@ -42,41 +52,60 @@ public class CrmContactServiceImpl implements CrmContactService { |
| 42 | 52 | @Resource |
| 43 | 53 | private CrmCustomerService customerService; |
| 44 | 54 | @Resource |
| 45 | - private CrmPermissionService crmPermissionService; | |
| 55 | + private CrmPermissionService permissionService; | |
| 56 | + @Resource | |
| 57 | + private CrmContractService contractService; | |
| 58 | + @Resource | |
| 59 | + private CrmContactBusinessService contactBusinessService; | |
| 60 | + @Resource | |
| 61 | + private CrmBusinessService businessService; | |
| 62 | + | |
| 46 | 63 | @Resource |
| 47 | 64 | private AdminUserApi adminUserApi; |
| 48 | 65 | |
| 49 | 66 | @Override |
| 50 | 67 | @Transactional(rollbackFor = Exception.class) |
| 51 | - // TODO @zyna:增加操作日志,可以参考 CustomerService;内容是 新建了联系人【名字】 | |
| 52 | - public Long createContact(CrmContactCreateReqVO createReqVO, Long userId) { | |
| 68 | + @LogRecord(type = CRM_CONTACT_TYPE, subType = "创建联系人", bizNo = "{{#contactId}}", success = "创建了联系人[{{#contactName}}]") | |
| 69 | + public Long createContact(CrmContactSaveReqVO createReqVO, Long userId) { | |
| 53 | 70 | // 1. 校验 |
| 54 | 71 | validateRelationDataExists(createReqVO); |
| 55 | 72 | |
| 56 | 73 | // 2. 插入联系人 |
| 57 | - CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO); | |
| 74 | + CrmContactDO contact = BeanUtils.toBean(createReqVO, CrmContactDO.class); | |
| 58 | 75 | contactMapper.insert(contact); |
| 59 | 76 | |
| 60 | 77 | // 3. 创建数据权限 |
| 61 | - crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) | |
| 78 | + permissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) | |
| 62 | 79 | .setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()).setBizId(contact.getId()) |
| 63 | 80 | .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); |
| 64 | 81 | |
| 65 | - // TODO @zyna:特殊逻辑:如果在【商机】详情那,点击【新增联系人】时,可以自动绑定商机 | |
| 82 | + // 4. 如果有关联商机,则需要创建关联 | |
| 83 | + if (createReqVO.getBusinessId() != null) { | |
| 84 | + contactBusinessService.createContactBusinessList(new CrmContactBusinessReqVO() | |
| 85 | + .setContactId(contact.getId()).setBusinessIds(singletonList(createReqVO.getBusinessId()))); | |
| 86 | + } | |
| 87 | + | |
| 88 | + // 5. 记录操作日志 | |
| 89 | + LogRecordContext.putVariable("contactId", contact.getId()); | |
| 90 | + LogRecordContext.putVariable("contactName", contact.getName()); | |
| 66 | 91 | return contact.getId(); |
| 67 | 92 | } |
| 68 | 93 | |
| 69 | 94 | @Override |
| 95 | + @Transactional(rollbackFor = Exception.class) | |
| 96 | + @LogRecord(type = CRM_CONTACT_TYPE, subType = "更新联系人", bizNo = "{{#updateReqVO.id}}", success = "更新了联系人{_DIFF{#updateReqVO}}") | |
| 70 | 97 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) |
| 71 | - // TODO @zyna:增加操作日志,可以参考 CustomerService;需要 diff 出字段 | |
| 72 | - public void updateContact(CrmContactUpdateReqVO updateReqVO) { | |
| 98 | + public void updateContact(CrmContactSaveReqVO updateReqVO) { | |
| 73 | 99 | // 1. 校验存在 |
| 74 | - validateContactExists(updateReqVO.getId()); | |
| 100 | + CrmContactDO contactDO = validateContactExists(updateReqVO.getId()); | |
| 75 | 101 | validateRelationDataExists(updateReqVO); |
| 76 | 102 | |
| 77 | 103 | // 2. 更新联系人 |
| 78 | - CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO); | |
| 104 | + CrmContactDO updateObj = BeanUtils.toBean(updateReqVO, CrmContactDO.class); | |
| 79 | 105 | contactMapper.updateById(updateObj); |
| 106 | + | |
| 107 | + // 3. 记录操作日志 | |
| 108 | + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(contactDO, CrmContactSaveReqVO.class)); | |
| 80 | 109 | } |
| 81 | 110 | |
| 82 | 111 | /** |
| ... | ... | @@ -84,7 +113,7 @@ public class CrmContactServiceImpl implements CrmContactService { |
| 84 | 113 | * |
| 85 | 114 | * @param saveReqVO 新增/修改请求 VO |
| 86 | 115 | */ |
| 87 | - private void validateRelationDataExists(CrmContactBaseVO saveReqVO) { | |
| 116 | + private void validateRelationDataExists(CrmContactSaveReqVO saveReqVO) { | |
| 88 | 117 | // 1. 校验客户 |
| 89 | 118 | if (saveReqVO.getCustomerId() != null && customerService.getCustomer(saveReqVO.getCustomerId()) == null) { |
| 90 | 119 | throw exception(CUSTOMER_NOT_EXISTS); |
| ... | ... | @@ -97,28 +126,39 @@ public class CrmContactServiceImpl implements CrmContactService { |
| 97 | 126 | if (saveReqVO.getParentId() != null && contactMapper.selectById(saveReqVO.getParentId()) == null) { |
| 98 | 127 | throw exception(CONTACT_NOT_EXISTS); |
| 99 | 128 | } |
| 129 | + // 4. 如果有关联商机,则需要校验存在 | |
| 130 | + if (saveReqVO.getBusinessId() != null && businessService.getBusiness(saveReqVO.getBusinessId()) == null) { | |
| 131 | + throw exception(BUSINESS_NOT_EXISTS); | |
| 132 | + } | |
| 100 | 133 | } |
| 101 | 134 | |
| 102 | 135 | @Override |
| 103 | 136 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) |
| 137 | + @Transactional(rollbackFor = Exception.class) | |
| 104 | 138 | public void deleteContact(Long id) { |
| 105 | - // 校验存在 | |
| 139 | + // 1.1 校验存在 | |
| 106 | 140 | validateContactExists(id); |
| 107 | - // TODO @zyna:如果有关联的合同,不允许删除;Contract.contactId | |
| 141 | + // 1.2 校验是否关联合同 | |
| 142 | + if (contractService.getContractCountByContactId(id) > 0) { | |
| 143 | + throw exception(CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS); | |
| 144 | + } | |
| 108 | 145 | |
| 109 | - // 删除 | |
| 146 | + // 2. 删除联系人 | |
| 110 | 147 | contactMapper.deleteById(id); |
| 111 | - // 删除数据权限 | |
| 112 | - crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id); | |
| 113 | - // TODO @zyna:删除商机联系人关联 | |
| 114 | 148 | |
| 149 | + // 4.1 删除数据权限 | |
| 150 | + permissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id); | |
| 151 | + // 4.2 删除商机关联 | |
| 152 | + contactBusinessService.deleteContactBusinessByContactId(id); | |
| 115 | 153 | // TODO @puhui999:删除跟进记录 |
| 116 | 154 | } |
| 117 | 155 | |
| 118 | - private void validateContactExists(Long id) { | |
| 119 | - if (contactMapper.selectById(id) == null) { | |
| 156 | + private CrmContactDO validateContactExists(Long id) { | |
| 157 | + CrmContactDO contactDO = contactMapper.selectById(id); | |
| 158 | + if (contactDO == null) { | |
| 120 | 159 | throw exception(CONTACT_NOT_EXISTS); |
| 121 | 160 | } |
| 161 | + return contactDO; | |
| 122 | 162 | } |
| 123 | 163 | |
| 124 | 164 | @Override |
| ... | ... | @@ -136,6 +176,11 @@ public class CrmContactServiceImpl implements CrmContactService { |
| 136 | 176 | } |
| 137 | 177 | |
| 138 | 178 | @Override |
| 179 | + public List<CrmContactDO> getContactList() { | |
| 180 | + return contactMapper.selectList(); | |
| 181 | + } | |
| 182 | + | |
| 183 | + @Override | |
| 139 | 184 | public PageResult<CrmContactDO> getContactPage(CrmContactPageReqVO pageReqVO, Long userId) { |
| 140 | 185 | return contactMapper.selectPage(pageReqVO, userId); |
| 141 | 186 | } |
| ... | ... | @@ -154,7 +199,7 @@ public class CrmContactServiceImpl implements CrmContactService { |
| 154 | 199 | validateContactExists(reqVO.getId()); |
| 155 | 200 | |
| 156 | 201 | // 2.1 数据权限转移 |
| 157 | - crmPermissionService.transferPermission( | |
| 202 | + permissionService.transferPermission( | |
| 158 | 203 | CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType())); |
| 159 | 204 | // 2.2 设置新的负责人 |
| 160 | 205 | contactMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java
| ... | ... | @@ -87,4 +87,12 @@ public interface CrmContractService { |
| 87 | 87 | */ |
| 88 | 88 | void transferContract(CrmContractTransferReqVO reqVO, Long userId); |
| 89 | 89 | |
| 90 | + /** | |
| 91 | + * 查询属于某个联系人的合同数量 | |
| 92 | + * | |
| 93 | + * @param contactId 联系人ID | |
| 94 | + * @return 合同 | |
| 95 | + */ | |
| 96 | + Long getContractCountByContactId(Long contactId); | |
| 97 | + | |
| 90 | 98 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
| ... | ... | @@ -135,5 +135,10 @@ public class CrmContractServiceImpl implements CrmContractService { |
| 135 | 135 | contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); |
| 136 | 136 | } |
| 137 | 137 | |
| 138 | + @Override | |
| 139 | + public Long getContractCountByContactId(Long contactId) { | |
| 140 | + return contractMapper.selectCountByContactId(contactId); | |
| 141 | + } | |
| 142 | + | |
| 138 | 143 | // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒; |
| 139 | 144 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.service.customer; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; | |
| 5 | 4 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; |
| 6 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO; | |
| 5 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigSaveReqVO; | |
| 7 | 6 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; |
| 8 | 7 | import jakarta.validation.Valid; |
| 9 | 8 | |
| ... | ... | @@ -22,14 +21,14 @@ public interface CrmCustomerLimitConfigService { |
| 22 | 21 | * @param createReqVO 创建信息 |
| 23 | 22 | * @return 编号 |
| 24 | 23 | */ |
| 25 | - Long createCustomerLimitConfig(@Valid CrmCustomerLimitConfigCreateReqVO createReqVO); | |
| 24 | + Long createCustomerLimitConfig(@Valid CrmCustomerLimitConfigSaveReqVO createReqVO); | |
| 26 | 25 | |
| 27 | 26 | /** |
| 28 | 27 | * 更新客户限制配置 |
| 29 | 28 | * |
| 30 | 29 | * @param updateReqVO 更新信息 |
| 31 | 30 | */ |
| 32 | - void updateCustomerLimitConfig(@Valid CrmCustomerLimitConfigUpdateReqVO updateReqVO); | |
| 31 | + void updateCustomerLimitConfig(@Valid CrmCustomerLimitConfigSaveReqVO updateReqVO); | |
| 33 | 32 | |
| 34 | 33 | /** |
| 35 | 34 | * 删除客户限制配置 |
| ... | ... | @@ -57,7 +56,7 @@ public interface CrmCustomerLimitConfigService { |
| 57 | 56 | /** |
| 58 | 57 | * 查询用户对应的配置列表 |
| 59 | 58 | * |
| 60 | - * @param type 类型 | |
| 59 | + * @param type 类型 | |
| 61 | 60 | * @param userId 用户类型 |
| 62 | 61 | */ |
| 63 | 62 | List<CrmCustomerLimitConfigDO> getCustomerLimitConfigListByUserId(Integer type, Long userId); | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java
| ... | ... | @@ -2,25 +2,29 @@ package cn.iocoder.yudao.module.crm.service.customer; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.lang.Assert; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; | |
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 6 | 6 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO; | |
| 7 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigSaveReqVO; | |
| 8 | 8 | import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerLimitConfigConvert; |
| 9 | 9 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; |
| 10 | 10 | import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerLimitConfigMapper; |
| 11 | +import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum; | |
| 11 | 12 | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| 12 | 13 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 13 | 14 | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| 15 | +import com.mzt.logapi.context.LogRecordContext; | |
| 16 | +import com.mzt.logapi.service.impl.DiffParseFunction; | |
| 17 | +import com.mzt.logapi.starter.annotation.LogRecord; | |
| 18 | +import jakarta.annotation.Resource; | |
| 14 | 19 | import org.springframework.stereotype.Service; |
| 15 | 20 | import org.springframework.validation.annotation.Validated; |
| 16 | 21 | |
| 17 | -import jakarta.annotation.Resource; | |
| 18 | - | |
| 19 | 22 | import java.util.Collection; |
| 20 | 23 | import java.util.List; |
| 21 | 24 | |
| 22 | 25 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 23 | 26 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_LIMIT_CONFIG_NOT_EXISTS; |
| 27 | +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; | |
| 24 | 28 | |
| 25 | 29 | /** |
| 26 | 30 | * 客户限制配置 Service 实现类 |
| ... | ... | @@ -40,34 +44,46 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig |
| 40 | 44 | private AdminUserApi adminUserApi; |
| 41 | 45 | |
| 42 | 46 | @Override |
| 43 | - // TODO @puhui999:操作日志 | |
| 44 | - public Long createCustomerLimitConfig(CrmCustomerLimitConfigCreateReqVO createReqVO) { | |
| 47 | + @LogRecord(type = CRM_CUSTOMER_LIMIT_CONFIG_TYPE, subType = CRM_CUSTOMER_LIMIT_CONFIG_CREATE_SUB_TYPE, bizNo = "{{#limitId}}", | |
| 48 | + success = CRM_CUSTOMER_LIMIT_CONFIG_CREATE_SUCCESS) | |
| 49 | + public Long createCustomerLimitConfig(CrmCustomerLimitConfigSaveReqVO createReqVO) { | |
| 45 | 50 | validateUserAndDept(createReqVO.getUserIds(), createReqVO.getDeptIds()); |
| 46 | 51 | // 插入 |
| 47 | 52 | CrmCustomerLimitConfigDO customerLimitConfig = CrmCustomerLimitConfigConvert.INSTANCE.convert(createReqVO); |
| 48 | 53 | customerLimitConfigMapper.insert(customerLimitConfig); |
| 49 | - // 返回 | |
| 54 | + | |
| 55 | + // 记录操作日志上下文 | |
| 56 | + LogRecordContext.putVariable("limitType", CrmCustomerLimitConfigTypeEnum.getNameByType(customerLimitConfig.getType())); | |
| 57 | + LogRecordContext.putVariable("limitId", customerLimitConfig.getId()); | |
| 50 | 58 | return customerLimitConfig.getId(); |
| 51 | 59 | } |
| 52 | 60 | |
| 53 | 61 | @Override |
| 54 | - // TODO @puhui999:操作日志 | |
| 55 | - public void updateCustomerLimitConfig(CrmCustomerLimitConfigUpdateReqVO updateReqVO) { | |
| 62 | + @LogRecord(type = CRM_CUSTOMER_LIMIT_CONFIG_TYPE, subType = CRM_CUSTOMER_LIMIT_CONFIG_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", | |
| 63 | + success = CRM_CUSTOMER_LIMIT_CONFIG_UPDATE_SUCCESS) | |
| 64 | + public void updateCustomerLimitConfig(CrmCustomerLimitConfigSaveReqVO updateReqVO) { | |
| 56 | 65 | // 校验存在 |
| 57 | - validateCustomerLimitConfigExists(updateReqVO.getId()); | |
| 66 | + CrmCustomerLimitConfigDO oldLimitConfig = validateCustomerLimitConfigExists(updateReqVO.getId()); | |
| 58 | 67 | validateUserAndDept(updateReqVO.getUserIds(), updateReqVO.getDeptIds()); |
| 59 | 68 | // 更新 |
| 60 | 69 | CrmCustomerLimitConfigDO updateObj = CrmCustomerLimitConfigConvert.INSTANCE.convert(updateReqVO); |
| 61 | 70 | customerLimitConfigMapper.updateById(updateObj); |
| 71 | + | |
| 72 | + // 记录操作日志上下文 | |
| 73 | + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldLimitConfig, CrmCustomerLimitConfigSaveReqVO.class)); | |
| 62 | 74 | } |
| 63 | 75 | |
| 64 | 76 | @Override |
| 65 | - // TODO @puhui999:操作日志 | |
| 77 | + @LogRecord(type = CRM_CUSTOMER_LIMIT_CONFIG_TYPE, subType = CRM_CUSTOMER_LIMIT_CONFIG_DELETE_SUB_TYPE, bizNo = "{{#id}}", | |
| 78 | + success = CRM_CUSTOMER_LIMIT_CONFIG_DELETE_SUCCESS) | |
| 66 | 79 | public void deleteCustomerLimitConfig(Long id) { |
| 67 | 80 | // 校验存在 |
| 68 | - validateCustomerLimitConfigExists(id); | |
| 81 | + CrmCustomerLimitConfigDO limitConfigDO = validateCustomerLimitConfigExists(id); | |
| 69 | 82 | // 删除 |
| 70 | 83 | customerLimitConfigMapper.deleteById(id); |
| 84 | + | |
| 85 | + // 记录操作日志上下文 | |
| 86 | + LogRecordContext.putVariable("limitType", CrmCustomerLimitConfigTypeEnum.getNameByType(limitConfigDO.getType())); | |
| 71 | 87 | } |
| 72 | 88 | |
| 73 | 89 | @Override |
| ... | ... | @@ -80,10 +96,12 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig |
| 80 | 96 | return customerLimitConfigMapper.selectPage(pageReqVO); |
| 81 | 97 | } |
| 82 | 98 | |
| 83 | - private void validateCustomerLimitConfigExists(Long id) { | |
| 84 | - if (customerLimitConfigMapper.selectById(id) == null) { | |
| 99 | + private CrmCustomerLimitConfigDO validateCustomerLimitConfigExists(Long id) { | |
| 100 | + CrmCustomerLimitConfigDO limitConfigDO = customerLimitConfigMapper.selectById(id); | |
| 101 | + if (limitConfigDO == null) { | |
| 85 | 102 | throw exception(CUSTOMER_LIMIT_CONFIG_NOT_EXISTS); |
| 86 | 103 | } |
| 104 | + return limitConfigDO; | |
| 87 | 105 | } |
| 88 | 106 | |
| 89 | 107 | /** | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java
| ... | ... | @@ -5,12 +5,16 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.poolconfig.CrmCu |
| 5 | 5 | import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; |
| 6 | 6 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; |
| 7 | 7 | import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerPoolConfigMapper; |
| 8 | +import com.mzt.logapi.context.LogRecordContext; | |
| 9 | +import com.mzt.logapi.starter.annotation.LogRecord; | |
| 10 | +import jakarta.annotation.Resource; | |
| 8 | 11 | import org.springframework.stereotype.Service; |
| 9 | 12 | import org.springframework.validation.annotation.Validated; |
| 10 | 13 | |
| 11 | -import jakarta.annotation.Resource; | |
| 12 | 14 | import java.util.Objects; |
| 13 | 15 | |
| 16 | +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; | |
| 17 | + | |
| 14 | 18 | /** |
| 15 | 19 | * 客户公海配置 Service 实现类 |
| 16 | 20 | * |
| ... | ... | @@ -19,6 +23,7 @@ import java.util.Objects; |
| 19 | 23 | @Service |
| 20 | 24 | @Validated |
| 21 | 25 | public class CrmCustomerPoolConfigServiceImpl implements CrmCustomerPoolConfigService { |
| 26 | + | |
| 22 | 27 | @Resource |
| 23 | 28 | private CrmCustomerPoolConfigMapper customerPoolConfigMapper; |
| 24 | 29 | |
| ... | ... | @@ -29,6 +34,7 @@ public class CrmCustomerPoolConfigServiceImpl implements CrmCustomerPoolConfigSe |
| 29 | 34 | */ |
| 30 | 35 | @Override |
| 31 | 36 | public CrmCustomerPoolConfigDO getCustomerPoolConfig() { |
| 37 | + // TODO @puhui999:这个要搞到 mapper 里噢。 | |
| 32 | 38 | return customerPoolConfigMapper.selectOne(new LambdaQueryWrapperX<CrmCustomerPoolConfigDO>().last("LIMIT 1")); |
| 33 | 39 | } |
| 34 | 40 | |
| ... | ... | @@ -38,16 +44,24 @@ public class CrmCustomerPoolConfigServiceImpl implements CrmCustomerPoolConfigSe |
| 38 | 44 | * @param saveReqVO 更新信息 |
| 39 | 45 | */ |
| 40 | 46 | @Override |
| 41 | - // TODO @puhui999:操作日志 | |
| 47 | + @LogRecord(type = CRM_CUSTOMER_POOL_CONFIG_TYPE, subType = CRM_CUSTOMER_POOL_CONFIG_SUB_TYPE, bizNo = "{{#poolConfigId}}", | |
| 48 | + success = CRM_CUSTOMER_POOL_CONFIG_SUCCESS) | |
| 42 | 49 | public void saveCustomerPoolConfig(CrmCustomerPoolConfigSaveReqVO saveReqVO) { |
| 43 | 50 | // 存在,则进行更新 |
| 44 | 51 | CrmCustomerPoolConfigDO dbConfig = getCustomerPoolConfig(); |
| 52 | + CrmCustomerPoolConfigDO poolConfig = CrmCustomerConvert.INSTANCE.convert(saveReqVO); | |
| 45 | 53 | if (Objects.nonNull(dbConfig)) { |
| 46 | - customerPoolConfigMapper.updateById(CrmCustomerConvert.INSTANCE.convert(saveReqVO).setId(dbConfig.getId())); | |
| 54 | + customerPoolConfigMapper.updateById(poolConfig.setId(dbConfig.getId())); | |
| 55 | + // 记录操作日志上下文 | |
| 56 | + LogRecordContext.putVariable("isPoolConfigUpdate", Boolean.TRUE); | |
| 57 | + LogRecordContext.putVariable("poolConfigId", poolConfig.getId()); | |
| 47 | 58 | return; |
| 48 | 59 | } |
| 49 | 60 | // 不存在,则进行插入 |
| 50 | - customerPoolConfigMapper.insert(CrmCustomerConvert.INSTANCE.convert(saveReqVO)); | |
| 61 | + customerPoolConfigMapper.insert(poolConfig); | |
| 62 | + // 记录操作日志上下文 | |
| 63 | + LogRecordContext.putVariable("isPoolConfigUpdate", Boolean.FALSE); | |
| 64 | + LogRecordContext.putVariable("poolConfigId", poolConfig.getId()); | |
| 51 | 65 | } |
| 52 | 66 | |
| 53 | 67 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.service.customer; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; | |
| 4 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLockReqVO; | |
| 5 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; | |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; | |
| 7 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; | |
| 5 | 8 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 6 | 9 | import jakarta.validation.Valid; |
| 7 | 10 | |
| ... | ... | @@ -22,14 +25,14 @@ public interface CrmCustomerService { |
| 22 | 25 | * @param userId 用户编号 |
| 23 | 26 | * @return 编号 |
| 24 | 27 | */ |
| 25 | - Long createCustomer(@Valid CrmCustomerCreateReqVO createReqVO, Long userId); | |
| 28 | + Long createCustomer(@Valid CrmCustomerSaveReqVO createReqVO, Long userId); | |
| 26 | 29 | |
| 27 | 30 | /** |
| 28 | 31 | * 更新客户 |
| 29 | 32 | * |
| 30 | 33 | * @param updateReqVO 更新信息 |
| 31 | 34 | */ |
| 32 | - void updateCustomer(@Valid CrmCustomerUpdateReqVO updateReqVO); | |
| 35 | + void updateCustomer(@Valid CrmCustomerSaveReqVO updateReqVO); | |
| 33 | 36 | |
| 34 | 37 | /** |
| 35 | 38 | * 删除客户 |
| ... | ... | @@ -83,7 +86,7 @@ public interface CrmCustomerService { |
| 83 | 86 | * 锁定/解锁客户 |
| 84 | 87 | * |
| 85 | 88 | * @param lockReqVO 更新信息 |
| 86 | - * @param userId 用户编号 | |
| 89 | + * @param userId 用户编号 | |
| 87 | 90 | */ |
| 88 | 91 | void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO, Long userId); |
| 89 | 92 | |
| ... | ... | @@ -101,15 +104,8 @@ public interface CrmCustomerService { |
| 101 | 104 | * |
| 102 | 105 | * @param ids 要领取的客户编号数组 |
| 103 | 106 | * @param ownerUserId 负责人 |
| 107 | + * @param isReceive 是/否领取 | |
| 104 | 108 | */ |
| 105 | - void receiveCustomer(List<Long> ids, Long ownerUserId); | |
| 106 | - | |
| 107 | - /** | |
| 108 | - * 获取客户列表 | |
| 109 | - * | |
| 110 | - * @return 客户列表 | |
| 111 | - * @author zyna | |
| 112 | - */ | |
| 113 | - List<CrmCustomerDO> getCustomerList(); | |
| 109 | + void receiveCustomer(List<Long> ids, Long ownerUserId, Boolean isReceive); | |
| 114 | 110 | |
| 115 | 111 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.crm.service.customer; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.lang.Assert; | |
| 5 | +import cn.hutool.extra.spring.SpringUtil; | |
| 4 | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | 7 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 6 | 8 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; | |
| 9 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLockReqVO; | |
| 10 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; | |
| 11 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; | |
| 12 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; | |
| 8 | 13 | import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; |
| 9 | 14 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 10 | 15 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; |
| ... | ... | @@ -12,9 +17,11 @@ import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; |
| 12 | 17 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 13 | 18 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 14 | 19 | import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; |
| 20 | +import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; | |
| 15 | 21 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 16 | 22 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 17 | 23 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 24 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | |
| 18 | 25 | import com.mzt.logapi.context.LogRecordContext; |
| 19 | 26 | import com.mzt.logapi.service.impl.DiffParseFunction; |
| 20 | 27 | import com.mzt.logapi.starter.annotation.LogRecord; |
| ... | ... | @@ -24,12 +31,14 @@ import org.springframework.transaction.annotation.Transactional; |
| 24 | 31 | import org.springframework.validation.annotation.Validated; |
| 25 | 32 | |
| 26 | 33 | import java.time.LocalDateTime; |
| 27 | -import java.util.*; | |
| 34 | +import java.util.ArrayList; | |
| 35 | +import java.util.Collection; | |
| 36 | +import java.util.Collections; | |
| 37 | +import java.util.List; | |
| 28 | 38 | |
| 29 | 39 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 30 | 40 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; |
| 31 | -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; | |
| 32 | -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.TRANSFER_CUSTOMER_LOG_SUCCESS; | |
| 41 | +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; | |
| 33 | 42 | import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; |
| 34 | 43 | import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_OWNER_LIMIT; |
| 35 | 44 | import static java.util.Collections.singletonList; |
| ... | ... | @@ -56,8 +65,10 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 56 | 65 | |
| 57 | 66 | @Override |
| 58 | 67 | @Transactional(rollbackFor = Exception.class) |
| 59 | - @LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户") // TODO @puhui999:创建了客户【客户名】,要记录进去;不然在展示操作日志的全列表,看不清楚是哪个客户哈; | |
| 60 | - public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { | |
| 68 | + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_CREATE_SUB_TYPE, bizNo = "{{#customer.id}}", | |
| 69 | + success = CRM_CUSTOMER_CREATE_SUCCESS) | |
| 70 | + public Long createCustomer(CrmCustomerSaveReqVO createReqVO, Long userId) { | |
| 71 | + createReqVO.setId(null); | |
| 61 | 72 | // 1. 校验拥有客户是否到达上限 |
| 62 | 73 | validateCustomerExceedOwnerLimit(createReqVO.getOwnerUserId(), 1); |
| 63 | 74 | |
| ... | ... | @@ -72,17 +83,19 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 72 | 83 | permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) |
| 73 | 84 | .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 |
| 74 | 85 | |
| 75 | - // 4. 记录操作日志 | |
| 76 | - LogRecordContext.putVariable("customerId", customer.getId()); | |
| 86 | + // 4. 记录操作日志上下文 | |
| 87 | + LogRecordContext.putVariable("customer", customer); | |
| 77 | 88 | return customer.getId(); |
| 78 | 89 | } |
| 79 | 90 | |
| 80 | 91 | @Override |
| 81 | 92 | @Transactional(rollbackFor = Exception.class) |
| 82 | - @LogRecord(type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}", success = "更新了客户{_DIFF{#updateReqVO}}", extra = "{{#extra}}") | |
| 93 | + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", | |
| 94 | + success = CRM_CUSTOMER_UPDATE_SUCCESS) | |
| 83 | 95 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) |
| 84 | - public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { | |
| 85 | - // TODO @puhui999:更新的时候,要把 updateReqVO 负责人设置为空,避免修改。 | |
| 96 | + public void updateCustomer(CrmCustomerSaveReqVO updateReqVO) { | |
| 97 | + Assert.notNull(updateReqVO.getId(), "客户编号不能为空"); | |
| 98 | + updateReqVO.setOwnerUserId(null); // 更新的时候,要把 updateReqVO 负责人设置为空,避免修改 | |
| 86 | 99 | // 1. 校验存在 |
| 87 | 100 | CrmCustomerDO oldCustomer = validateCustomerExists(updateReqVO.getId()); |
| 88 | 101 | |
| ... | ... | @@ -90,21 +103,19 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 90 | 103 | CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); |
| 91 | 104 | customerMapper.updateById(updateObj); |
| 92 | 105 | |
| 93 | - // 3. 记录操作日志 | |
| 94 | - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerUpdateReqVO.class)); | |
| 95 | - // TODO 扩展信息测试 @puhui999:看着没啥问题,可以删除啦; | |
| 96 | - HashMap<String, Object> extra = new HashMap<>(); | |
| 97 | - extra.put("tips", "随便记录一点啦"); | |
| 98 | - LogRecordContext.putVariable("extra", extra); | |
| 106 | + // 3. 记录操作日志上下文 | |
| 107 | + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerSaveReqVO.class)); | |
| 108 | + LogRecordContext.putVariable("customerName", oldCustomer.getName()); | |
| 99 | 109 | } |
| 100 | 110 | |
| 101 | 111 | @Override |
| 102 | 112 | @Transactional(rollbackFor = Exception.class) |
| 103 | - @LogRecord(type = CRM_CUSTOMER, subType = "删除客户", bizNo = "{{#id}}", success = "删除了客户") | |
| 113 | + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_DELETE_SUB_TYPE, bizNo = "{{#id}}", | |
| 114 | + success = CRM_CUSTOMER_DELETE_SUCCESS) | |
| 104 | 115 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) |
| 105 | 116 | public void deleteCustomer(Long id) { |
| 106 | 117 | // 校验存在 |
| 107 | - validateCustomerExists(id); | |
| 118 | + CrmCustomerDO customer = validateCustomerExists(id); | |
| 108 | 119 | // TODO @puhui999:如果有联系人、商机,则不允许删除; |
| 109 | 120 | |
| 110 | 121 | // 删除 |
| ... | ... | @@ -112,48 +123,15 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 112 | 123 | // 删除数据权限 |
| 113 | 124 | permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); |
| 114 | 125 | // TODO @puhui999:删除跟进记录 |
| 115 | - } | |
| 116 | - | |
| 117 | - private CrmCustomerDO validateCustomerExists(Long id) { | |
| 118 | - CrmCustomerDO customerDO = customerMapper.selectById(id); | |
| 119 | - if (customerDO == null) { | |
| 120 | - throw exception(CUSTOMER_NOT_EXISTS); | |
| 121 | - } | |
| 122 | - return customerDO; | |
| 123 | - } | |
| 124 | - | |
| 125 | - @Override | |
| 126 | - @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.READ) | |
| 127 | - public CrmCustomerDO getCustomer(Long id) { | |
| 128 | - return customerMapper.selectById(id); | |
| 129 | - } | |
| 130 | 126 | |
| 131 | - @Override | |
| 132 | - public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) { | |
| 133 | - if (CollUtil.isEmpty(ids)) { | |
| 134 | - return Collections.emptyList(); | |
| 135 | - } | |
| 136 | - return customerMapper.selectBatchIds(ids); | |
| 137 | - } | |
| 138 | - | |
| 139 | - @Override | |
| 140 | - public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId) { | |
| 141 | - return customerMapper.selectPage(pageReqVO, userId); | |
| 142 | - } | |
| 143 | - | |
| 144 | - /** | |
| 145 | - * 校验客户是否存在 | |
| 146 | - * | |
| 147 | - * @param customerId 客户 id | |
| 148 | - */ | |
| 149 | - @Override | |
| 150 | - public void validateCustomer(Long customerId) { | |
| 151 | - validateCustomerExists(customerId); | |
| 127 | + // 记录操作日志上下文 | |
| 128 | + LogRecordContext.putVariable("customerName", customer.getName()); | |
| 152 | 129 | } |
| 153 | 130 | |
| 154 | 131 | @Override |
| 155 | 132 | @Transactional(rollbackFor = Exception.class) |
| 156 | - @LogRecord(type = CRM_CUSTOMER, subType = "转移客户", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) | |
| 133 | + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}", | |
| 134 | + success = CRM_CUSTOMER_TRANSFER_SUCCESS) | |
| 157 | 135 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) |
| 158 | 136 | public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { |
| 159 | 137 | // 1.1 校验客户是否存在 |
| ... | ... | @@ -168,20 +146,19 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 168 | 146 | customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); |
| 169 | 147 | |
| 170 | 148 | // 3. TODO 记录转移日志 |
| 149 | + // 记录操作日志上下文 | |
| 150 | + // TODO @puhui999:crmCustomer=》customer,也看看其他有没类似的情况哈 | |
| 171 | 151 | LogRecordContext.putVariable("crmCustomer", customer); |
| 172 | 152 | } |
| 173 | 153 | |
| 174 | 154 | @Override |
| 175 | - // TODO @puhui999:看看这个能不能根据条件,写操作日志; | |
| 176 | - // TODO 如果是 锁定,则 subType 为 锁定客户;success 为 将客户【】锁定 | |
| 177 | - // TODO 如果是 解锁,则 subType 为 解锁客户;success 为 将客户【】解锁 | |
| 178 | - @LogRecord(type = CRM_CUSTOMER, subType = "锁定/解锁客户", bizNo = "{{#updateReqVO.id}}", success = "锁定了客户") | |
| 179 | - // TODO @puhui999:数据权限 | |
| 155 | + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_LOCK_SUB_TYPE, bizNo = "{{#lockReqVO.id}}", | |
| 156 | + success = CRM_CUSTOMER_LOCK_SUCCESS) | |
| 157 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#lockReqVO.id", level = CrmPermissionLevelEnum.OWNER) | |
| 180 | 158 | public void lockCustomer(CrmCustomerLockReqVO lockReqVO, Long userId) { |
| 181 | 159 | // 1.1 校验当前客户是否存在 |
| 182 | - validateCustomerExists(lockReqVO.getId()); | |
| 160 | + CrmCustomerDO customer = validateCustomerExists(lockReqVO.getId()); | |
| 183 | 161 | // 1.2 校验当前是否重复操作锁定/解锁状态 |
| 184 | - CrmCustomerDO customer = customerMapper.selectById(lockReqVO.getId()); | |
| 185 | 162 | if (customer.getLockStatus().equals(lockReqVO.getLockStatus())) { |
| 186 | 163 | throw exception(customer.getLockStatus() ? CUSTOMER_LOCK_FAIL_IS_LOCK : CUSTOMER_UNLOCK_FAIL_IS_UNLOCK); |
| 187 | 164 | } |
| ... | ... | @@ -192,52 +169,18 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 192 | 169 | |
| 193 | 170 | // 2. 更新锁定状态 |
| 194 | 171 | customerMapper.updateById(BeanUtils.toBean(lockReqVO, CrmCustomerDO.class)); |
| 195 | - } | |
| 196 | 172 | |
| 197 | - /** | |
| 198 | - * 校验用户拥有的客户数量,是否到达上限 | |
| 199 | - * | |
| 200 | - * @param userId 用户编号 | |
| 201 | - * @param newCount 附加数量 | |
| 202 | - */ | |
| 203 | - private void validateCustomerExceedOwnerLimit(Long userId, int newCount) { | |
| 204 | - List<CrmCustomerLimitConfigDO> limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId( | |
| 205 | - CUSTOMER_OWNER_LIMIT.getType(), userId); | |
| 206 | - if (CollUtil.isEmpty(limitConfigs)) { | |
| 207 | - return; | |
| 208 | - } | |
| 209 | - Long ownerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(null, userId); | |
| 210 | - Long dealOwnerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(true, userId); | |
| 211 | - limitConfigs.forEach(limitConfig -> { | |
| 212 | - long nowCount = limitConfig.getDealCountEnabled() ? ownerCount : ownerCount - dealOwnerCount; | |
| 213 | - if (nowCount + newCount > limitConfig.getMaxCount()) { | |
| 214 | - throw exception(CUSTOMER_OWNER_EXCEED_LIMIT); | |
| 215 | - } | |
| 216 | - }); | |
| 173 | + // 3. 记录操作日志上下文 | |
| 174 | + // tips: 因为这里使用的是老的状态所以记录时反着记录,也就是 lockStatus 为 true 那么就是解锁反之为锁定 | |
| 175 | + LogRecordContext.putVariable("crmCustomer", customer); | |
| 217 | 176 | } |
| 218 | 177 | |
| 219 | - /** | |
| 220 | - * 校验用户锁定的客户数量,是否到达上限 | |
| 221 | - * | |
| 222 | - * @param userId 用户编号 | |
| 223 | - */ | |
| 224 | - private void validateCustomerExceedLockLimit(Long userId) { | |
| 225 | - List<CrmCustomerLimitConfigDO> limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId( | |
| 226 | - CUSTOMER_LOCK_LIMIT.getType(), userId); | |
| 227 | - if (CollUtil.isEmpty(limitConfigs)) { | |
| 228 | - return; | |
| 229 | - } | |
| 230 | - Long lockCount = customerMapper.selectCountByLockStatusAndOwnerUserId(true, userId); | |
| 231 | - Integer maxCount = CollectionUtils.getMaxValue(limitConfigs, CrmCustomerLimitConfigDO::getMaxCount); | |
| 232 | - assert maxCount != null; | |
| 233 | - if (lockCount >= maxCount) { | |
| 234 | - throw exception(CUSTOMER_LOCK_EXCEED_LIMIT); | |
| 235 | - } | |
| 236 | - } | |
| 178 | + // ==================== 公海相关操作 ==================== | |
| 237 | 179 | |
| 238 | 180 | @Override |
| 239 | 181 | @Transactional(rollbackFor = Exception.class) |
| 240 | - @LogRecord(type = CRM_CUSTOMER, subType = "客户放入公海", bizNo = "{{#id}}", success = "将客户放入了公海") // TODO @puhui999:将客户【】放入了公海 | |
| 182 | + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_POOL_SUB_TYPE, bizNo = "{{#id}}", | |
| 183 | + success = CRM_CUSTOMER_POOL_SUCCESS) | |
| 241 | 184 | @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) |
| 242 | 185 | public void putCustomerPool(Long id) { |
| 243 | 186 | // 1. 校验存在 |
| ... | ... | @@ -259,16 +202,18 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 259 | 202 | permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(), |
| 260 | 203 | CrmPermissionLevelEnum.OWNER.getLevel()); |
| 261 | 204 | // TODO @puhui999:联系人的负责人,也要设置为 null;这块和领取是对应的;因为领取后,负责人也要关联过来; |
| 205 | + | |
| 206 | + // 记录操作日志上下文 | |
| 207 | + LogRecordContext.putVariable("customerName", customer.getName()); | |
| 262 | 208 | } |
| 263 | 209 | |
| 264 | 210 | @Override |
| 265 | 211 | @Transactional(rollbackFor = Exception.class) |
| 266 | - // TODO @puhui999:权限校验 | |
| 212 | + public void receiveCustomer(List<Long> ids, Long ownerUserId, Boolean isReceive) { | |
| 213 | + if (!isReceive && !CrmPermissionUtils.isCrmAdmin()) { // 只有管理员可以分配 | |
| 214 | + throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.CRM_CUSTOMER.getName()); | |
| 215 | + } | |
| 267 | 216 | |
| 268 | - // TODO @puhui999:如果是分配,操作日志是 “将客户【】分配给【】” | |
| 269 | - // TODO @puhui999:如果是领取,操作日志是“领取客户【】”; | |
| 270 | - // TODO @puhui999:如果是多条,则需要记录多条操作日志;不然 bizId 不好关联 | |
| 271 | - public void receiveCustomer(List<Long> ids, Long ownerUserId) { | |
| 272 | 217 | // 1.1 校验存在 |
| 273 | 218 | List<CrmCustomerDO> customers = customerMapper.selectBatchIds(ids); |
| 274 | 219 | if (customers.size() != ids.size()) { |
| ... | ... | @@ -303,6 +248,56 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 303 | 248 | // 2.3 创建负责人数据权限 |
| 304 | 249 | permissionService.createPermissionBatch(createPermissions); |
| 305 | 250 | // TODO @芋艿:要不要处理关联的联系人??? |
| 251 | + | |
| 252 | + // 3. 记录操作日志 | |
| 253 | + AdminUserRespDTO user = null; | |
| 254 | + if (!isReceive) { | |
| 255 | + user = adminUserApi.getUser(ownerUserId); | |
| 256 | + } | |
| 257 | + for (CrmCustomerDO customer : customers) { | |
| 258 | + getSelf().receiveCustomerLog(customer, user == null ? null : user.getNickname()); | |
| 259 | + } | |
| 260 | + } | |
| 261 | + | |
| 262 | + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_RECEIVE_SUB_TYPE, bizNo = "{{#customer.id}}", | |
| 263 | + success = CRM_CUSTOMER_RECEIVE_SUCCESS) | |
| 264 | + public void receiveCustomerLog(CrmCustomerDO customer, String ownerUserName) { | |
| 265 | + // 记录操作日志上下文 | |
| 266 | + LogRecordContext.putVariable("customer", customer); | |
| 267 | + LogRecordContext.putVariable("ownerUserName", ownerUserName); | |
| 268 | + } | |
| 269 | + | |
| 270 | + //======================= 查询相关 ======================= | |
| 271 | + | |
| 272 | + @Override | |
| 273 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.READ) | |
| 274 | + public CrmCustomerDO getCustomer(Long id) { | |
| 275 | + return customerMapper.selectById(id); | |
| 276 | + } | |
| 277 | + | |
| 278 | + @Override | |
| 279 | + public List<CrmCustomerDO> getCustomerList(Collection<Long> ids) { | |
| 280 | + if (CollUtil.isEmpty(ids)) { | |
| 281 | + return Collections.emptyList(); | |
| 282 | + } | |
| 283 | + return customerMapper.selectBatchIds(ids); | |
| 284 | + } | |
| 285 | + | |
| 286 | + @Override | |
| 287 | + public PageResult<CrmCustomerDO> getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId) { | |
| 288 | + return customerMapper.selectPage(pageReqVO, userId); | |
| 289 | + } | |
| 290 | + | |
| 291 | + // ======================= 校验相关 ======================= | |
| 292 | + | |
| 293 | + /** | |
| 294 | + * 校验客户是否存在 | |
| 295 | + * | |
| 296 | + * @param customerId 客户 id | |
| 297 | + */ | |
| 298 | + @Override | |
| 299 | + public void validateCustomer(Long customerId) { | |
| 300 | + validateCustomerExists(customerId); | |
| 306 | 301 | } |
| 307 | 302 | |
| 308 | 303 | private void validateCustomerOwnerExists(CrmCustomerDO customer, Boolean pool) { |
| ... | ... | @@ -314,11 +309,19 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 314 | 309 | throw exception(CUSTOMER_IN_POOL, customer.getName()); |
| 315 | 310 | } |
| 316 | 311 | // 负责人已存在 |
| 317 | - if (customer.getOwnerUserId() != null) { | |
| 312 | + if (!pool && customer.getOwnerUserId() != null) { | |
| 318 | 313 | throw exception(CUSTOMER_OWNER_EXISTS, customer.getName()); |
| 319 | 314 | } |
| 320 | 315 | } |
| 321 | 316 | |
| 317 | + private CrmCustomerDO validateCustomerExists(Long id) { | |
| 318 | + CrmCustomerDO customerDO = customerMapper.selectById(id); | |
| 319 | + if (customerDO == null) { | |
| 320 | + throw exception(CUSTOMER_NOT_EXISTS); | |
| 321 | + } | |
| 322 | + return customerDO; | |
| 323 | + } | |
| 324 | + | |
| 322 | 325 | private void validateCustomerIsLocked(CrmCustomerDO customer, Boolean pool) { |
| 323 | 326 | if (customer.getLockStatus()) { |
| 324 | 327 | throw exception(pool ? CUSTOMER_LOCKED_PUT_POOL_FAIL : CUSTOMER_LOCKED, customer.getName()); |
| ... | ... | @@ -331,9 +334,55 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { |
| 331 | 334 | } |
| 332 | 335 | } |
| 333 | 336 | |
| 334 | - @Override | |
| 335 | - public List<CrmCustomerDO> getCustomerList() { | |
| 336 | - return customerMapper.selectList(); | |
| 337 | + /** | |
| 338 | + * 校验用户拥有的客户数量,是否到达上限 | |
| 339 | + * | |
| 340 | + * @param userId 用户编号 | |
| 341 | + * @param newCount 附加数量 | |
| 342 | + */ | |
| 343 | + private void validateCustomerExceedOwnerLimit(Long userId, int newCount) { | |
| 344 | + List<CrmCustomerLimitConfigDO> limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId( | |
| 345 | + CUSTOMER_OWNER_LIMIT.getType(), userId); | |
| 346 | + if (CollUtil.isEmpty(limitConfigs)) { | |
| 347 | + return; | |
| 348 | + } | |
| 349 | + Long ownerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(null, userId); | |
| 350 | + Long dealOwnerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(true, userId); | |
| 351 | + limitConfigs.forEach(limitConfig -> { | |
| 352 | + long nowCount = limitConfig.getDealCountEnabled() ? ownerCount : ownerCount - dealOwnerCount; | |
| 353 | + if (nowCount + newCount > limitConfig.getMaxCount()) { | |
| 354 | + throw exception(CUSTOMER_OWNER_EXCEED_LIMIT); | |
| 355 | + } | |
| 356 | + }); | |
| 357 | + } | |
| 358 | + | |
| 359 | + /** | |
| 360 | + * 校验用户锁定的客户数量,是否到达上限 | |
| 361 | + * | |
| 362 | + * @param userId 用户编号 | |
| 363 | + */ | |
| 364 | + private void validateCustomerExceedLockLimit(Long userId) { | |
| 365 | + List<CrmCustomerLimitConfigDO> limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId( | |
| 366 | + CUSTOMER_LOCK_LIMIT.getType(), userId); | |
| 367 | + if (CollUtil.isEmpty(limitConfigs)) { | |
| 368 | + return; | |
| 369 | + } | |
| 370 | + Long lockCount = customerMapper.selectCountByLockStatusAndOwnerUserId(true, userId); | |
| 371 | + Integer maxCount = CollectionUtils.getMaxValue(limitConfigs, CrmCustomerLimitConfigDO::getMaxCount); | |
| 372 | + assert maxCount != null; | |
| 373 | + if (lockCount >= maxCount) { | |
| 374 | + throw exception(CUSTOMER_LOCK_EXCEED_LIMIT); | |
| 375 | + } | |
| 376 | + } | |
| 377 | + | |
| 378 | + | |
| 379 | + /** | |
| 380 | + * 获得自身的代理对象,解决 AOP 生效问题 | |
| 381 | + * | |
| 382 | + * @return 自己 | |
| 383 | + */ | |
| 384 | + private CrmCustomerServiceImpl getSelf() { | |
| 385 | + return SpringUtil.getBean(getClass()); | |
| 337 | 386 | } |
| 338 | 387 | |
| 339 | 388 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java
| ... | ... | @@ -91,6 +91,15 @@ public interface CrmPermissionService { |
| 91 | 91 | List<CrmPermissionDO> getPermissionListByBiz(Integer bizType, Long bizId); |
| 92 | 92 | |
| 93 | 93 | /** |
| 94 | + * 获取数据权限列表,通过 数据类型 x 某个数据 | |
| 95 | + * | |
| 96 | + * @param bizType 数据类型,关联 {@link CrmBizTypeEnum} | |
| 97 | + * @param bizIds 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId() | |
| 98 | + * @return Crm 数据权限列表 | |
| 99 | + */ | |
| 100 | + List<CrmPermissionDO> getPermissionListByBiz(Integer bizType, Collection<Long> bizIds); | |
| 101 | + | |
| 102 | + /** | |
| 94 | 103 | * 获取用户参与的模块数据列表 |
| 95 | 104 | * |
| 96 | 105 | * @param bizType 模块类型 | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java
| ... | ... | @@ -188,6 +188,11 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | 190 | @Override |
| 191 | + public List<CrmPermissionDO> getPermissionListByBiz(Integer bizType, Collection<Long> bizIds) { | |
| 192 | + return crmPermissionMapper.selectByBizTypeAndBizIds(bizType, bizIds); | |
| 193 | + } | |
| 194 | + | |
| 195 | + @Override | |
| 191 | 196 | public List<CrmPermissionDO> getPermissionListByBizTypeAndUserId(Integer bizType, Long userId) { |
| 192 | 197 | return crmPermissionMapper.selectListByBizTypeAndUserId(bizType, userId); |
| 193 | 198 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java
| ... | ... | @@ -5,6 +5,10 @@ import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProdu |
| 5 | 5 | import cn.iocoder.yudao.module.crm.controller.admin.product.vo.category.CrmProductCategoryListReqVO; |
| 6 | 6 | import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; |
| 7 | 7 | import cn.iocoder.yudao.module.crm.dal.mysql.product.CrmProductCategoryMapper; |
| 8 | +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; | |
| 9 | +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; | |
| 10 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; | |
| 11 | +import com.mzt.logapi.starter.annotation.LogRecord; | |
| 8 | 12 | import org.springframework.context.annotation.Lazy; |
| 9 | 13 | import org.springframework.stereotype.Service; |
| 10 | 14 | import org.springframework.validation.annotation.Validated; |
| ... | ... | @@ -17,6 +21,7 @@ import java.util.Objects; |
| 17 | 21 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 18 | 22 | import static cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO.PARENT_ID_NULL; |
| 19 | 23 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; |
| 24 | +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; | |
| 20 | 25 | |
| 21 | 26 | /** |
| 22 | 27 | * CRM 产品分类 Service 实现类 |
| ... | ... | @@ -35,12 +40,16 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService |
| 35 | 40 | private CrmProductService crmProductService; |
| 36 | 41 | |
| 37 | 42 | @Override |
| 38 | - // TODO @puhui999:操作日志 | |
| 43 | + @LogRecord(type = CRM_PRODUCT_CATEGORY_TYPE, subType = CRM_PRODUCT_CATEGORY_CREATE_SUB_TYPE, bizNo = "{{#createReqVO.id}}", | |
| 44 | + success = CRM_PRODUCT_CATEGORY_CREATE_SUCCESS) | |
| 45 | + // TODO @hao:产品分类,应该没数据权限。可以删除下哈; | |
| 46 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#createReqVO.id", level = CrmPermissionLevelEnum.WRITE) | |
| 39 | 47 | public Long createProductCategory(CrmProductCategoryCreateReqVO createReqVO) { |
| 40 | 48 | // 1.1 校验父分类存在 |
| 41 | 49 | validateParentProductCategory(createReqVO.getParentId()); |
| 42 | 50 | // 1.2 分类名称是否存在 |
| 43 | 51 | validateProductNameExists(null, createReqVO.getParentId(), createReqVO.getName()); |
| 52 | + | |
| 44 | 53 | // 2. 插入分类 |
| 45 | 54 | CrmProductCategoryDO category = BeanUtils.toBean(createReqVO, CrmProductCategoryDO.class); |
| 46 | 55 | productCategoryMapper.insert(category); |
| ... | ... | @@ -48,7 +57,9 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService |
| 48 | 57 | } |
| 49 | 58 | |
| 50 | 59 | @Override |
| 51 | - // TODO @puhui999:操作日志 | |
| 60 | + @LogRecord(type = CRM_PRODUCT_CATEGORY_TYPE, subType = CRM_PRODUCT_CATEGORY_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", | |
| 61 | + success = CRM_PRODUCT_CATEGORY_UPDATE_SUCCESS) | |
| 62 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) | |
| 52 | 63 | public void updateProductCategory(CrmProductCategoryCreateReqVO updateReqVO) { |
| 53 | 64 | // 1.1 校验存在 |
| 54 | 65 | validateProductCategoryExists(updateReqVO.getId()); |
| ... | ... | @@ -56,6 +67,7 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService |
| 56 | 67 | validateParentProductCategory(updateReqVO.getParentId()); |
| 57 | 68 | // 1.3 分类名称是否存在 |
| 58 | 69 | validateProductNameExists(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); |
| 70 | + | |
| 59 | 71 | // 2. 更新分类 |
| 60 | 72 | CrmProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, CrmProductCategoryDO.class); |
| 61 | 73 | productCategoryMapper.updateById(updateObj); |
| ... | ... | @@ -93,7 +105,9 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService |
| 93 | 105 | } |
| 94 | 106 | |
| 95 | 107 | @Override |
| 96 | - // TODO @puhui999:操作日志 | |
| 108 | + @LogRecord(type = CRM_PRODUCT_CATEGORY_TYPE, subType = CRM_PRODUCT_CATEGORY_DELETE_SUB_TYPE, bizNo = "{{#id}}", | |
| 109 | + success = CRM_PRODUCT_CATEGORY_DELETE_SUCCESS) | |
| 110 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) | |
| 97 | 111 | public void deleteProductCategory(Long id) { |
| 98 | 112 | // 1.1 校验存在 |
| 99 | 113 | validateProductCategoryExists(id); |
| ... | ... | @@ -110,16 +124,19 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService |
| 110 | 124 | } |
| 111 | 125 | |
| 112 | 126 | @Override |
| 127 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#id", level = CrmPermissionLevelEnum.READ) | |
| 113 | 128 | public CrmProductCategoryDO getProductCategory(Long id) { |
| 114 | 129 | return productCategoryMapper.selectById(id); |
| 115 | 130 | } |
| 116 | 131 | |
| 117 | 132 | @Override |
| 133 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#listReqVO.id", level = CrmPermissionLevelEnum.READ) | |
| 118 | 134 | public List<CrmProductCategoryDO> getProductCategoryList(CrmProductCategoryListReqVO listReqVO) { |
| 119 | 135 | return productCategoryMapper.selectList(listReqVO); |
| 120 | 136 | } |
| 121 | 137 | |
| 122 | 138 | @Override |
| 139 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#listReqVO.id", level = CrmPermissionLevelEnum.READ) | |
| 123 | 140 | public List<CrmProductCategoryDO> getProductCategoryList(Collection<Long> ids) { |
| 124 | 141 | return productCategoryMapper.selectBatchIds(ids); |
| 125 | 142 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java
| ... | ... | @@ -11,22 +11,26 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; |
| 11 | 11 | import cn.iocoder.yudao.module.crm.dal.mysql.product.CrmProductMapper; |
| 12 | 12 | import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; |
| 13 | 13 | import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; |
| 14 | +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; | |
| 14 | 15 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 15 | 16 | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| 16 | 17 | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| 17 | 18 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 19 | +import com.mzt.logapi.starter.annotation.LogRecord; | |
| 20 | +import jakarta.annotation.Resource; | |
| 18 | 21 | import org.springframework.stereotype.Service; |
| 22 | +import org.springframework.transaction.annotation.Transactional; | |
| 19 | 23 | import org.springframework.validation.annotation.Validated; |
| 20 | 24 | |
| 21 | -import jakarta.annotation.Resource; | |
| 22 | 25 | import java.util.Collection; |
| 23 | 26 | import java.util.Collections; |
| 24 | 27 | import java.util.List; |
| 25 | 28 | |
| 26 | 29 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 27 | 30 | import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; |
| 31 | +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; | |
| 32 | + | |
| 28 | 33 | |
| 29 | -// TODO 芋艿:数据权限 | |
| 30 | 34 | /** |
| 31 | 35 | * CRM 产品 Service 实现类 |
| 32 | 36 | * |
| ... | ... | @@ -48,7 +52,10 @@ public class CrmProductServiceImpl implements CrmProductService { |
| 48 | 52 | private AdminUserApi adminUserApi; |
| 49 | 53 | |
| 50 | 54 | @Override |
| 51 | - // TODO @puhui999:操作日志 | |
| 55 | + @Transactional(rollbackFor = Exception.class) | |
| 56 | + @LogRecord(type = CRM_PRODUCT_TYPE, subType = CRM_PRODUCT_CREATE_SUB_TYPE, bizNo = "{{#createReqVO.id}}", | |
| 57 | + success = CRM_PRODUCT_CREATE_SUCCESS) | |
| 58 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#createReqVO.id", level = CrmPermissionLevelEnum.WRITE) | |
| 52 | 59 | public Long createProduct(CrmProductSaveReqVO createReqVO) { |
| 53 | 60 | // 校验产品 |
| 54 | 61 | adminUserApi.validateUserList(Collections.singleton(createReqVO.getOwnerUserId())); |
| ... | ... | @@ -67,7 +74,9 @@ public class CrmProductServiceImpl implements CrmProductService { |
| 67 | 74 | } |
| 68 | 75 | |
| 69 | 76 | @Override |
| 70 | - // TODO @puhui999:操作日志 | |
| 77 | + @LogRecord(type = CRM_PRODUCT_TYPE, subType = CRM_PRODUCT_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", | |
| 78 | + success = CRM_PRODUCT_UPDATE_SUCCESS) | |
| 79 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) | |
| 71 | 80 | public void updateProduct(CrmProductSaveReqVO updateReqVO) { |
| 72 | 81 | // 校验产品 |
| 73 | 82 | updateReqVO.setOwnerUserId(null); // 不修改负责人 |
| ... | ... | @@ -90,7 +99,7 @@ public class CrmProductServiceImpl implements CrmProductService { |
| 90 | 99 | private void validateProductNoDuplicate(Long id, String no) { |
| 91 | 100 | CrmProductDO product = productMapper.selectByNo(no); |
| 92 | 101 | if (product == null |
| 93 | - || product.getId().equals(id)) { | |
| 102 | + || product.getId().equals(id)) { | |
| 94 | 103 | return; |
| 95 | 104 | } |
| 96 | 105 | throw exception(PRODUCT_NO_EXISTS); |
| ... | ... | @@ -104,7 +113,9 @@ public class CrmProductServiceImpl implements CrmProductService { |
| 104 | 113 | } |
| 105 | 114 | |
| 106 | 115 | @Override |
| 107 | - // TODO @puhui999:操作日志 | |
| 116 | + @LogRecord(type = CRM_PRODUCT_TYPE, subType = CRM_PRODUCT_DELETE_SUB_TYPE, bizNo = "{{#id}}", | |
| 117 | + success = CRM_PRODUCT_DELETE_SUCCESS) | |
| 118 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) | |
| 108 | 119 | public void deleteProduct(Long id) { |
| 109 | 120 | // 校验存在 |
| 110 | 121 | validateProductExists(id); |
| ... | ... | @@ -113,6 +124,7 @@ public class CrmProductServiceImpl implements CrmProductService { |
| 113 | 124 | } |
| 114 | 125 | |
| 115 | 126 | @Override |
| 127 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#id", level = CrmPermissionLevelEnum.READ) | |
| 116 | 128 | public CrmProductDO getProduct(Long id) { |
| 117 | 129 | return productMapper.selectById(id); |
| 118 | 130 | } |
| ... | ... | @@ -126,6 +138,7 @@ public class CrmProductServiceImpl implements CrmProductService { |
| 126 | 138 | } |
| 127 | 139 | |
| 128 | 140 | @Override |
| 141 | + @CrmPermission(bizType = CrmBizTypeEnum.CRM_PRODUCT, bizId = "#pageReqVO.id", level = CrmPermissionLevelEnum.READ) | |
| 129 | 142 | public PageResult<CrmProductDO> getProductPage(CrmProductPageReqVO pageReqVO) { |
| 130 | 143 | return productMapper.selectPage(pageReqVO); |
| 131 | 144 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java
| ... | ... | @@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.crm.service.clue; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 5 | -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; | |
| 6 | 5 | import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; | |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; | |
| 8 | 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; |
| 9 | 8 | import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; |
| 10 | 9 | import jakarta.annotation.Resource; |
| ... | ... | @@ -43,7 +42,7 @@ public class CrmClueServiceImplTest extends BaseDbUnitTest { |
| 43 | 42 | @Test |
| 44 | 43 | public void testCreateClue_success() { |
| 45 | 44 | // 准备参数 |
| 46 | - CrmClueCreateReqVO reqVO = randomPojo(CrmClueCreateReqVO.class); | |
| 45 | + CrmClueSaveReqVO reqVO = randomPojo(CrmClueSaveReqVO.class); | |
| 47 | 46 | |
| 48 | 47 | // 调用 |
| 49 | 48 | Long clueId = clueService.createClue(reqVO); |
| ... | ... | @@ -60,7 +59,7 @@ public class CrmClueServiceImplTest extends BaseDbUnitTest { |
| 60 | 59 | CrmClueDO dbClue = randomPojo(CrmClueDO.class); |
| 61 | 60 | clueMapper.insert(dbClue);// @Sql: 先插入出一条存在的数据 |
| 62 | 61 | // 准备参数 |
| 63 | - CrmClueUpdateReqVO reqVO = randomPojo(CrmClueUpdateReqVO.class, o -> { | |
| 62 | + CrmClueSaveReqVO reqVO = randomPojo(CrmClueSaveReqVO.class, o -> { | |
| 64 | 63 | o.setId(dbClue.getId()); // 设置更新的 ID |
| 65 | 64 | }); |
| 66 | 65 | |
| ... | ... | @@ -74,7 +73,7 @@ public class CrmClueServiceImplTest extends BaseDbUnitTest { |
| 74 | 73 | @Test |
| 75 | 74 | public void testUpdateClue_notExists() { |
| 76 | 75 | // 准备参数 |
| 77 | - CrmClueUpdateReqVO reqVO = randomPojo(CrmClueUpdateReqVO.class); | |
| 76 | + CrmClueSaveReqVO reqVO = randomPojo(CrmClueSaveReqVO.class); | |
| 78 | 77 | |
| 79 | 78 | // 调用, 并断言异常 |
| 80 | 79 | assertServiceException(() -> clueService.updateClue(reqVO), CLUE_NOT_EXISTS); | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImplTest.java
| ... | ... | @@ -2,19 +2,17 @@ package cn.iocoder.yudao.module.crm.service.customer; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 5 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; | |
| 6 | 5 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO; | |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; | |
| 8 | 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; |
| 9 | 8 | import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; |
| 10 | 9 | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| 10 | +import jakarta.annotation.Resource; | |
| 11 | 11 | import org.junit.jupiter.api.Disabled; |
| 12 | 12 | import org.junit.jupiter.api.Test; |
| 13 | 13 | import org.springframework.boot.test.mock.mockito.MockBean; |
| 14 | 14 | import org.springframework.context.annotation.Import; |
| 15 | 15 | |
| 16 | -import jakarta.annotation.Resource; | |
| 17 | - | |
| 18 | 16 | import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; |
| 19 | 17 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| 20 | 18 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| ... | ... | @@ -47,7 +45,7 @@ public class CrmCustomerServiceImplTest extends BaseDbUnitTest { |
| 47 | 45 | @Test |
| 48 | 46 | public void testCreateCustomer_success() { |
| 49 | 47 | // 准备参数 |
| 50 | - CrmCustomerCreateReqVO reqVO = randomPojo(CrmCustomerCreateReqVO.class); | |
| 48 | + CrmCustomerSaveReqVO reqVO = randomPojo(CrmCustomerSaveReqVO.class); | |
| 51 | 49 | |
| 52 | 50 | // 调用 |
| 53 | 51 | Long customerId = customerService.createCustomer(reqVO, getLoginUserId()); |
| ... | ... | @@ -64,7 +62,7 @@ public class CrmCustomerServiceImplTest extends BaseDbUnitTest { |
| 64 | 62 | CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class); |
| 65 | 63 | customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据 |
| 66 | 64 | // 准备参数 |
| 67 | - CrmCustomerUpdateReqVO reqVO = randomPojo(CrmCustomerUpdateReqVO.class, o -> { | |
| 65 | + CrmCustomerSaveReqVO reqVO = randomPojo(CrmCustomerSaveReqVO.class, o -> { | |
| 68 | 66 | o.setId(dbCustomer.getId()); // 设置更新的 ID |
| 69 | 67 | }); |
| 70 | 68 | |
| ... | ... | @@ -78,7 +76,7 @@ public class CrmCustomerServiceImplTest extends BaseDbUnitTest { |
| 78 | 76 | @Test |
| 79 | 77 | public void testUpdateCustomer_notExists() { |
| 80 | 78 | // 准备参数 |
| 81 | - CrmCustomerUpdateReqVO reqVO = randomPojo(CrmCustomerUpdateReqVO.class); | |
| 79 | + CrmCustomerSaveReqVO reqVO = randomPojo(CrmCustomerSaveReqVO.class); | |
| 82 | 80 | |
| 83 | 81 | // 调用, 并断言异常 |
| 84 | 82 | assertServiceException(() -> customerService.updateCustomer(reqVO), CUSTOMER_NOT_EXISTS); |
| ... | ... | @@ -140,38 +138,4 @@ public class CrmCustomerServiceImplTest extends BaseDbUnitTest { |
| 140 | 138 | //assertPojoEquals(dbCustomer, pageResult.getList().get(0)); |
| 141 | 139 | } |
| 142 | 140 | |
| 143 | - @Test | |
| 144 | - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 | |
| 145 | - public void testGetCustomerList() { | |
| 146 | - // mock 数据 | |
| 147 | - CrmCustomerDO dbCustomer = randomPojo(CrmCustomerDO.class, o -> { // 等会查询到 | |
| 148 | - o.setName(null); | |
| 149 | - o.setMobile(null); | |
| 150 | - o.setTelephone(null); | |
| 151 | - o.setWebsite(null); | |
| 152 | - }); | |
| 153 | - customerMapper.insert(dbCustomer); | |
| 154 | - // 测试 name 不匹配 | |
| 155 | - customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setName(null))); | |
| 156 | - // 测试 mobile 不匹配 | |
| 157 | - customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setMobile(null))); | |
| 158 | - // 测试 telephone 不匹配 | |
| 159 | - customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setTelephone(null))); | |
| 160 | - // 测试 website 不匹配 | |
| 161 | - customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setWebsite(null))); | |
| 162 | - // 准备参数 | |
| 163 | - CrmCustomerPageReqVO reqVO = new CrmCustomerPageReqVO(); | |
| 164 | - reqVO.setName("张三"); | |
| 165 | - reqVO.setMobile("13888888888"); | |
| 166 | - reqVO.setPageSize(PAGE_SIZE_NONE); | |
| 167 | - //reqVO.setTelephone(null); | |
| 168 | - //reqVO.setWebsite(null); | |
| 169 | - | |
| 170 | - // 调用 | |
| 171 | - PageResult<CrmCustomerDO> pageResult = customerService.getCustomerPage(reqVO, 1L); | |
| 172 | - // 断言 | |
| 173 | - assertEquals(1, pageResult.getList().size()); | |
| 174 | - assertPojoEquals(dbCustomer, pageResult.getList().get(0)); | |
| 175 | - } | |
| 176 | - | |
| 177 | 141 | } | ... | ... |
yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/customerlimitconfig/CrmCustomerLimitConfigServiceImplTest.java
| ... | ... | @@ -2,18 +2,16 @@ package cn.iocoder.yudao.module.crm.service.customerlimitconfig; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; |
| 5 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; | |
| 6 | 5 | import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; |
| 7 | -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO; | |
| 6 | +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigSaveReqVO; | |
| 8 | 7 | import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; |
| 9 | 8 | import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerLimitConfigMapper; |
| 10 | 9 | import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerLimitConfigServiceImpl; |
| 10 | +import jakarta.annotation.Resource; | |
| 11 | 11 | import org.junit.jupiter.api.Disabled; |
| 12 | 12 | import org.junit.jupiter.api.Test; |
| 13 | 13 | import org.springframework.context.annotation.Import; |
| 14 | 14 | |
| 15 | -import jakarta.annotation.Resource; | |
| 16 | - | |
| 17 | 15 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 18 | 16 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| 19 | 17 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; |
| ... | ... | @@ -40,7 +38,7 @@ public class CrmCustomerLimitConfigServiceImplTest extends BaseDbUnitTest { |
| 40 | 38 | @Test |
| 41 | 39 | public void testCreateCustomerLimitConfig_success() { |
| 42 | 40 | // 准备参数 |
| 43 | - CrmCustomerLimitConfigCreateReqVO reqVO = randomPojo(CrmCustomerLimitConfigCreateReqVO.class); | |
| 41 | + CrmCustomerLimitConfigSaveReqVO reqVO = randomPojo(CrmCustomerLimitConfigSaveReqVO.class); | |
| 44 | 42 | |
| 45 | 43 | // 调用 |
| 46 | 44 | Long customerLimitConfigId = customerLimitConfigService.createCustomerLimitConfig(reqVO); |
| ... | ... | @@ -57,7 +55,7 @@ public class CrmCustomerLimitConfigServiceImplTest extends BaseDbUnitTest { |
| 57 | 55 | CrmCustomerLimitConfigDO dbCustomerLimitConfig = randomPojo(CrmCustomerLimitConfigDO.class); |
| 58 | 56 | customerLimitConfigMapper.insert(dbCustomerLimitConfig);// @Sql: 先插入出一条存在的数据 |
| 59 | 57 | // 准备参数 |
| 60 | - CrmCustomerLimitConfigUpdateReqVO reqVO = randomPojo(CrmCustomerLimitConfigUpdateReqVO.class, o -> { | |
| 58 | + CrmCustomerLimitConfigSaveReqVO reqVO = randomPojo(CrmCustomerLimitConfigSaveReqVO.class, o -> { | |
| 61 | 59 | o.setId(dbCustomerLimitConfig.getId()); // 设置更新的 ID |
| 62 | 60 | }); |
| 63 | 61 | |
| ... | ... | @@ -71,7 +69,7 @@ public class CrmCustomerLimitConfigServiceImplTest extends BaseDbUnitTest { |
| 71 | 69 | @Test |
| 72 | 70 | public void testUpdateCustomerLimitConfig_notExists() { |
| 73 | 71 | // 准备参数 |
| 74 | - CrmCustomerLimitConfigUpdateReqVO reqVO = randomPojo(CrmCustomerLimitConfigUpdateReqVO.class); | |
| 72 | + CrmCustomerLimitConfigSaveReqVO reqVO = randomPojo(CrmCustomerLimitConfigSaveReqVO.class); | |
| 75 | 73 | |
| 76 | 74 | // 调用, 并断言异常 |
| 77 | 75 | assertServiceException(() -> customerLimitConfigService.updateCustomerLimitConfig(reqVO), CUSTOMER_LIMIT_CONFIG_NOT_EXISTS); | ... | ... |
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
| ... | ... | @@ -252,15 +252,11 @@ import ${subSimpleClassName}List from './components/${subSimpleClassName}List.vu |
| 252 | 252 | /** ${table.classComment} 列表 */ |
| 253 | 253 | defineOptions({ name: '${table.className}' }) |
| 254 | 254 | |
| 255 | -// 消息弹窗 | |
| 256 | -const message = useMessage() | |
| 257 | -// 国际化 | |
| 258 | -const { t } = useI18n() | |
| 255 | +const message = useMessage() // 消息弹窗 | |
| 256 | +const { t } = useI18n() // 国际化 | |
| 259 | 257 | |
| 260 | -// 列表的加载中 | |
| 261 | -const loading = ref(true) | |
| 262 | -// 列表的数据 | |
| 263 | -const list = ref<${simpleClassName}VO[]>([]) | |
| 258 | +const loading = ref(true) // 列表的加载中 | |
| 259 | +const list = ref<${simpleClassName}VO[]>([]) // 列表的数据 | |
| 264 | 260 | ## 特殊:树表专属逻辑(树不需要分页接口) |
| 265 | 261 | #if ( $table.templateType != 2 ) |
| 266 | 262 | // 列表的总页数 |
| ... | ... | @@ -283,10 +279,8 @@ const queryParams = reactive({ |
| 283 | 279 | #end |
| 284 | 280 | #end |
| 285 | 281 | }) |
| 286 | -// 搜索的表单 | |
| 287 | -const queryFormRef = ref() | |
| 288 | -// 导出的加载中 | |
| 289 | -const exportLoading = ref(false) | |
| 282 | +const queryFormRef = ref() // 搜索的表单 | |
| 283 | +const exportLoading = ref(false) // 导出的加载中 | |
| 290 | 284 | |
| 291 | 285 | /** 查询列表 */ |
| 292 | 286 | const getList = async () => { | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/ProductCategoryController.java
| ... | ... | @@ -67,8 +67,8 @@ public class ProductCategoryController { |
| 67 | 67 | @GetMapping("/list") |
| 68 | 68 | @Operation(summary = "获得商品分类列表") |
| 69 | 69 | @PreAuthorize("@ss.hasPermission('product:category:query')") |
| 70 | - public CommonResult<List<ProductCategoryRespVO>> getCategoryList(@Valid ProductCategoryListReqVO treeListReqVO) { | |
| 71 | - List<ProductCategoryDO> list = categoryService.getEnableCategoryList(treeListReqVO); | |
| 70 | + public CommonResult<List<ProductCategoryRespVO>> getCategoryList(@Valid ProductCategoryListReqVO listReqVO) { | |
| 71 | + List<ProductCategoryDO> list = categoryService.getCategoryList(listReqVO); | |
| 72 | 72 | list.sort(Comparator.comparing(ProductCategoryDO::getSort)); |
| 73 | 73 | return success(ProductCategoryConvert.INSTANCE.convertList(list)); |
| 74 | 74 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/category/vo/ProductCategoryListReqVO.java
| ... | ... | @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.product.controller.admin.category.vo; |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | +import java.util.Collection; | |
| 7 | + | |
| 6 | 8 | @Schema(description = "管理后台 - 商品分类列表查询 Request VO") |
| 7 | 9 | @Data |
| 8 | 10 | public class ProductCategoryListReqVO { |
| ... | ... | @@ -16,4 +18,7 @@ public class ProductCategoryListReqVO { |
| 16 | 18 | @Schema(description = "父分类编号", example = "1") |
| 17 | 19 | private Long parentId; |
| 18 | 20 | |
| 21 | + @Schema(description = "父分类编号数组", example = "1,2,3") | |
| 22 | + private Collection<Long> parentIds; | |
| 23 | + | |
| 19 | 24 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/AppProductBrowseHistoryController.java
| ... | ... | @@ -28,6 +28,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. |
| 28 | 28 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 29 | 29 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 30 | 30 | |
| 31 | +// TODO 芋艿:后面再看 | |
| 31 | 32 | @Tag(name = "用户 APP - 商品浏览记录") |
| 32 | 33 | @RestController |
| 33 | 34 | @RequestMapping("/product/browse-history") |
| ... | ... | @@ -65,10 +66,9 @@ public class AppProductBrowseHistoryController { |
| 65 | 66 | @Operation(summary = "获得商品浏览记录分页") |
| 66 | 67 | @PreAuthenticated |
| 67 | 68 | public CommonResult<PageResult<AppProductBrowseHistoryRespVO>> getBrowseHistoryPage(AppProductBrowseHistoryPageReqVO reqVO) { |
| 68 | - ProductBrowseHistoryPageReqVO pageReqVO = BeanUtils.toBean(reqVO, ProductBrowseHistoryPageReqVO.class); | |
| 69 | - pageReqVO.setUserId(getLoginUserId()); | |
| 70 | - // 排除用户已删除的(隐藏的) | |
| 71 | - pageReqVO.setUserDeleted(false); | |
| 69 | + ProductBrowseHistoryPageReqVO pageReqVO = BeanUtils.toBean(reqVO, ProductBrowseHistoryPageReqVO.class) | |
| 70 | + .setUserId(getLoginUserId()) | |
| 71 | + .setUserDeleted(false); // 排除用户已删除的(隐藏的) | |
| 72 | 72 | PageResult<ProductBrowseHistoryDO> pageResult = productBrowseHistoryService.getBrowseHistoryPage(pageReqVO); |
| 73 | 73 | if (CollUtil.isEmpty(pageResult.getList())) { |
| 74 | 74 | return success(PageResult.empty()); |
| ... | ... | @@ -77,15 +77,9 @@ public class AppProductBrowseHistoryController { |
| 77 | 77 | // 得到商品 spu 信息 |
| 78 | 78 | Set<Long> spuIds = convertSet(pageResult.getList(), ProductBrowseHistoryDO::getSpuId); |
| 79 | 79 | Map<Long, ProductSpuDO> spuMap = convertMap(productSpuService.getSpuList(spuIds), ProductSpuDO::getId); |
| 80 | - | |
| 81 | - // 转换 VO 结果 | |
| 82 | - PageResult<AppProductBrowseHistoryRespVO> result = BeanUtils.toBean(pageResult, AppProductBrowseHistoryRespVO.class, | |
| 83 | - vo -> Optional.ofNullable(spuMap.get(vo.getSpuId())).ifPresent(spu -> { | |
| 84 | - vo.setSpuName(spu.getName()) | |
| 85 | - .setPicUrl(spu.getPicUrl()) | |
| 86 | - .setPrice(spu.getPrice()); | |
| 87 | - })); | |
| 88 | - return success(result); | |
| 80 | + return success(BeanUtils.toBean(pageResult, AppProductBrowseHistoryRespVO.class, | |
| 81 | + vo -> Optional.ofNullable(spuMap.get(vo.getSpuId())) | |
| 82 | + .ifPresent(spu -> vo.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setPrice(spu.getPrice())))); | |
| 89 | 83 | } |
| 90 | 84 | |
| 91 | 85 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryPageReqVO.java
| ... | ... | @@ -16,6 +16,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ |
| 16 | 16 | @EqualsAndHashCode(callSuper = true) |
| 17 | 17 | @ToString(callSuper = true) |
| 18 | 18 | public class AppProductBrowseHistoryPageReqVO extends PageParam { |
| 19 | + | |
| 19 | 20 | @Schema(description = "创建时间") |
| 20 | 21 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 21 | 22 | private LocalDateTime[] createTime; | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java
| ... | ... | @@ -4,11 +4,12 @@ import cn.hutool.core.util.StrUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 5 | 5 | import com.fasterxml.jackson.annotation.JsonIgnore; |
| 6 | 6 | import io.swagger.v3.oas.annotations.media.Schema; |
| 7 | +import jakarta.validation.constraints.AssertTrue; | |
| 7 | 8 | import lombok.Data; |
| 8 | 9 | import lombok.EqualsAndHashCode; |
| 9 | 10 | import lombok.ToString; |
| 10 | 11 | |
| 11 | -import jakarta.validation.constraints.AssertTrue; | |
| 12 | +import java.util.List; | |
| 12 | 13 | |
| 13 | 14 | @Schema(description = "用户 App - 商品 SPU 分页 Request VO") |
| 14 | 15 | @Data |
| ... | ... | @@ -26,9 +27,15 @@ public class AppProductSpuPageReqVO extends PageParam { |
| 26 | 27 | public static final String RECOMMEND_TYPE_NEW = "new"; |
| 27 | 28 | public static final String RECOMMEND_TYPE_GOOD = "good"; |
| 28 | 29 | |
| 30 | + @Schema(description = "商品 SPU 编号数组", example = "1,3,5") | |
| 31 | + private List<Long> ids; | |
| 32 | + | |
| 29 | 33 | @Schema(description = "分类编号", example = "1") |
| 30 | 34 | private Long categoryId; |
| 31 | 35 | |
| 36 | + @Schema(description = "分类编号数组", example = "1,2,3") | |
| 37 | + private List<Long> categoryIds; | |
| 38 | + | |
| 32 | 39 | @Schema(description = "关键字", example = "好看") |
| 33 | 40 | private String keyword; |
| 34 | 41 | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java
| ... | ... | @@ -21,6 +21,7 @@ public interface ProductCategoryMapper extends BaseMapperX<ProductCategoryDO> { |
| 21 | 21 | return selectList(new LambdaQueryWrapperX<ProductCategoryDO>() |
| 22 | 22 | .likeIfPresent(ProductCategoryDO::getName, listReqVO.getName()) |
| 23 | 23 | .eqIfPresent(ProductCategoryDO::getParentId, listReqVO.getParentId()) |
| 24 | + .inIfPresent(ProductCategoryDO::getId, listReqVO.getParentIds()) | |
| 24 | 25 | .eqIfPresent(ProductCategoryDO::getStatus, listReqVO.getStatus()) |
| 25 | 26 | .orderByDesc(ProductCategoryDO::getId)); |
| 26 | 27 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java
| ... | ... | @@ -67,7 +67,7 @@ public interface ProductCategoryService { |
| 67 | 67 | * @param listReqVO 查询条件 |
| 68 | 68 | * @return 商品分类列表 |
| 69 | 69 | */ |
| 70 | - List<ProductCategoryDO> getEnableCategoryList(ProductCategoryListReqVO listReqVO); | |
| 70 | + List<ProductCategoryDO> getCategoryList(ProductCategoryListReqVO listReqVO); | |
| 71 | 71 | |
| 72 | 72 | /** |
| 73 | 73 | * 获得开启状态的商品分类列表 | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
| ... | ... | @@ -161,7 +161,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | 163 | @Override |
| 164 | - public List<ProductCategoryDO> getEnableCategoryList(ProductCategoryListReqVO listReqVO) { | |
| 164 | + public List<ProductCategoryDO> getCategoryList(ProductCategoryListReqVO listReqVO) { | |
| 165 | 165 | return productCategoryMapper.selectList(listReqVO); |
| 166 | 166 | } |
| 167 | 167 | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryService.java
| ... | ... | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.product.service.history; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.module.product.controller.admin.history.vo.ProductBrowseHistoryPageReqVO; |
| 5 | 5 | import cn.iocoder.yudao.module.product.dal.dataobject.history.ProductBrowseHistoryDO; |
| 6 | +import org.springframework.scheduling.annotation.Async; | |
| 6 | 7 | |
| 7 | 8 | import java.util.Collection; |
| 8 | 9 | |
| ... | ... | @@ -20,6 +21,7 @@ public interface ProductBrowseHistoryService { |
| 20 | 21 | * @param spuId SPU 编号 |
| 21 | 22 | * @return 编号 |
| 22 | 23 | */ |
| 24 | + @Async | |
| 23 | 25 | Long createBrowseHistory(Long userId, Long spuId); |
| 24 | 26 | |
| 25 | 27 | /** |
| ... | ... | @@ -31,14 +33,6 @@ public interface ProductBrowseHistoryService { |
| 31 | 33 | void hideUserBrowseHistory(Long userId, Collection<Long> spuId); |
| 32 | 34 | |
| 33 | 35 | /** |
| 34 | - * 获得商品浏览记录 | |
| 35 | - * | |
| 36 | - * @param id 编号 | |
| 37 | - * @return 商品浏览记录 | |
| 38 | - */ | |
| 39 | - ProductBrowseHistoryDO getBrowseHistory(Long id); | |
| 40 | - | |
| 41 | - /** | |
| 42 | 36 | * 获取用户记录数量 |
| 43 | 37 | * |
| 44 | 38 | * @param userId 用户编号 | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/history/ProductBrowseHistoryServiceImpl.java
| ... | ... | @@ -50,7 +50,6 @@ public class ProductBrowseHistoryServiceImpl implements ProductBrowseHistoryServ |
| 50 | 50 | .setUserId(userId) |
| 51 | 51 | .setSpuId(spuId); |
| 52 | 52 | browseHistoryMapper.insert(browseHistory); |
| 53 | - // 返回 | |
| 54 | 53 | return browseHistory.getId(); |
| 55 | 54 | } |
| 56 | 55 | |
| ... | ... | @@ -60,11 +59,6 @@ public class ProductBrowseHistoryServiceImpl implements ProductBrowseHistoryServ |
| 60 | 59 | } |
| 61 | 60 | |
| 62 | 61 | @Override |
| 63 | - public ProductBrowseHistoryDO getBrowseHistory(Long id) { | |
| 64 | - return browseHistoryMapper.selectById(id); | |
| 65 | - } | |
| 66 | - | |
| 67 | - @Override | |
| 68 | 62 | public Long getBrowseHistoryCount(Long userId, Boolean userDeleted) { |
| 69 | 63 | return browseHistoryMapper.selectCountByUserIdAndUserDeleted(userId, userDeleted); |
| 70 | 64 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
| ... | ... | @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageRe |
| 6 | 6 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; |
| 7 | 7 | |
| 8 | 8 | import jakarta.validation.Valid; |
| 9 | +import org.springframework.scheduling.annotation.Async; | |
| 10 | + | |
| 9 | 11 | import java.util.Collection; |
| 10 | 12 | import java.util.List; |
| 11 | 13 | import java.util.Map; |
| ... | ... | @@ -154,6 +156,7 @@ public interface ProductSpuService { |
| 154 | 156 | * @param id 商品 SPU 编号 |
| 155 | 157 | * @param incrCount 增加的数量 |
| 156 | 158 | */ |
| 159 | + @Async | |
| 157 | 160 | void updateBrowseCount(Long id, int incrCount); |
| 158 | 161 | |
| 159 | 162 | } | ... | ... |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
| ... | ... | @@ -18,17 +18,16 @@ import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; |
| 18 | 18 | import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; |
| 19 | 19 | import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; |
| 20 | 20 | import com.google.common.collect.Maps; |
| 21 | +import jakarta.annotation.Resource; | |
| 21 | 22 | import org.springframework.context.annotation.Lazy; |
| 22 | 23 | import org.springframework.stereotype.Service; |
| 23 | 24 | import org.springframework.transaction.annotation.Transactional; |
| 24 | 25 | import org.springframework.validation.annotation.Validated; |
| 25 | 26 | |
| 26 | -import jakarta.annotation.Resource; | |
| 27 | 27 | import java.util.*; |
| 28 | 28 | |
| 29 | 29 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 30 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMinValue; | |
| 31 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; | |
| 30 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | |
| 32 | 31 | import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.CATEGORY_LEVEL; |
| 33 | 32 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; |
| 34 | 33 | |
| ... | ... | @@ -220,9 +219,15 @@ public class ProductSpuServiceImpl implements ProductSpuService { |
| 220 | 219 | Set<Long> categoryIds = new HashSet<>(); |
| 221 | 220 | if (pageReqVO.getCategoryId() != null && pageReqVO.getCategoryId() > 0) { |
| 222 | 221 | categoryIds.add(pageReqVO.getCategoryId()); |
| 223 | - List<ProductCategoryDO> categoryChildren = categoryService.getEnableCategoryList(new ProductCategoryListReqVO() | |
| 224 | - .setParentId(pageReqVO.getCategoryId()).setStatus(CommonStatusEnum.ENABLE.getStatus())); | |
| 225 | - categoryIds.addAll(CollectionUtils.convertList(categoryChildren, ProductCategoryDO::getId)); | |
| 222 | + List<ProductCategoryDO> categoryChildren = categoryService.getCategoryList(new ProductCategoryListReqVO() | |
| 223 | + .setStatus(CommonStatusEnum.ENABLE.getStatus()).setParentId(pageReqVO.getCategoryId())); | |
| 224 | + categoryIds.addAll(convertList(categoryChildren, ProductCategoryDO::getId)); | |
| 225 | + } | |
| 226 | + if (CollUtil.isNotEmpty(pageReqVO.getCategoryIds())) { | |
| 227 | + categoryIds.addAll(pageReqVO.getCategoryIds()); | |
| 228 | + List<ProductCategoryDO> categoryChildren = categoryService.getCategoryList(new ProductCategoryListReqVO() | |
| 229 | + .setStatus(CommonStatusEnum.ENABLE.getStatus()).setParentIds(pageReqVO.getCategoryIds())); | |
| 230 | + categoryIds.addAll(convertList(categoryChildren, ProductCategoryDO::getId)); | |
| 226 | 231 | } |
| 227 | 232 | // 分页查询 |
| 228 | 233 | return productSpuMapper.selectPage(pageReqVO, categoryIds); | ... | ... |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionActivityStatusEnum.java
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/reward/vo/RewardActivityBaseVO.java
| ... | ... | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.reward.vo; |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.validation.InEnum; |
| 5 | 5 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; |
| 6 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | |
| 6 | 7 | import com.fasterxml.jackson.annotation.JsonIgnore; |
| 7 | 8 | import io.swagger.v3.oas.annotations.media.Schema; |
| 8 | 9 | import lombok.Data; |
| ... | ... | @@ -50,7 +51,7 @@ public class RewardActivityBaseVO { |
| 50 | 51 | |
| 51 | 52 | @Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| 52 | 53 | @NotNull(message = "商品范围不能为空") |
| 53 | - @InEnum(value = PromotionConditionTypeEnum.class, message = "商品范围必须是 {value}") | |
| 54 | + @InEnum(value = PromotionProductScopeEnum.class, message = "商品范围必须是 {value}") | |
| 54 | 55 | private Integer productScope; |
| 55 | 56 | |
| 56 | 57 | @Schema(description = "商品 SPU 编号的数组", example = "1,2,3") | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java
| ... | ... | @@ -145,6 +145,7 @@ public class AppActivityController { |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | 147 | private void getRewardActivities(Collection<Long> spuIds, LocalDateTime now, List<AppActivityRespVO> activityList) { |
| 148 | + // TODO @puhui999:有 3 范围,不只 spuId,还有 categoryId,全部 | |
| 148 | 149 | List<RewardActivityDO> rewardActivityList = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt( |
| 149 | 150 | spuIds, PromotionActivityStatusEnum.RUN.getStatus(), now); |
| 150 | 151 | if (CollUtil.isEmpty(rewardActivityList)) { | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/reward/AppRewardActivityController.java
0 → 100755
| 1 | +package cn.iocoder.yudao.module.promotion.controller.app.reward; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 4 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 5 | +import cn.iocoder.yudao.module.promotion.controller.app.reward.vo.AppRewardActivityRespVO; | |
| 6 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; | |
| 7 | +import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; | |
| 8 | +import io.swagger.v3.oas.annotations.Operation; | |
| 9 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 10 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 11 | +import jakarta.annotation.Resource; | |
| 12 | +import org.springframework.validation.annotation.Validated; | |
| 13 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 14 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 15 | +import org.springframework.web.bind.annotation.RequestParam; | |
| 16 | +import org.springframework.web.bind.annotation.RestController; | |
| 17 | + | |
| 18 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 19 | + | |
| 20 | +@Tag(name = "用户 App - 满减送活动") | |
| 21 | +@RestController | |
| 22 | +@RequestMapping("/promotion/reward-activity") | |
| 23 | +@Validated | |
| 24 | +public class AppRewardActivityController { | |
| 25 | + | |
| 26 | + @Resource | |
| 27 | + private RewardActivityService rewardActivityService; | |
| 28 | + | |
| 29 | + @GetMapping("/get") | |
| 30 | + @Operation(summary = "获得满减送活动") | |
| 31 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | |
| 32 | + public CommonResult<AppRewardActivityRespVO> getRewardActivity(@RequestParam("id") Long id) { | |
| 33 | + RewardActivityDO rewardActivity = rewardActivityService.getRewardActivity(id); | |
| 34 | + return success(BeanUtils.toBean(rewardActivity, AppRewardActivityRespVO.class)); | |
| 35 | + } | |
| 36 | + | |
| 37 | +} | ... | ... |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/reward/vo/AppRewardActivityRespVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.module.promotion.controller.app.reward.vo; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityBaseVO; | |
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 5 | +import lombok.Data; | |
| 6 | + | |
| 7 | +import java.util.List; | |
| 8 | + | |
| 9 | +@Schema(description = "用户 App - 满减送活动 Response VO") | |
| 10 | +@Data | |
| 11 | +public class AppRewardActivityRespVO { | |
| 12 | + | |
| 13 | + @Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 14 | + private Integer id; | |
| 15 | + | |
| 16 | + @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 17 | + private Integer status; | |
| 18 | + | |
| 19 | + @Schema(description = "活动标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "满啦满啦") | |
| 20 | + private String name; | |
| 21 | + | |
| 22 | + @Schema(description = "条件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 23 | + private Integer conditionType; | |
| 24 | + | |
| 25 | + @Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | |
| 26 | + private Integer productScope; | |
| 27 | + | |
| 28 | + @Schema(description = "商品 SPU 编号的数组", example = "1,2,3") | |
| 29 | + private List<Long> productSpuIds; | |
| 30 | + | |
| 31 | + @Schema(description = "优惠规则的数组") | |
| 32 | + private List<RewardActivityBaseVO.Rule> rules; | |
| 33 | + | |
| 34 | +} | ... | ... |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/ProductStatisticsController.java
| ... | ... | @@ -79,13 +79,9 @@ public class ProductStatisticsController { |
| 79 | 79 | // 处理商品信息 |
| 80 | 80 | Set<Long> spuIds = convertSet(pageResult.getList(), ProductStatisticsDO::getSpuId); |
| 81 | 81 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(productSpuApi.getSpuList(spuIds), ProductSpuRespDTO::getId); |
| 82 | - // 拼接返回 | |
| 83 | 82 | return success(BeanUtils.toBean(pageResult, ProductStatisticsRespVO.class, |
| 84 | - // 拼接商品信息 | |
| 85 | - item -> Optional.ofNullable(spuMap.get(item.getSpuId())).ifPresent(spu -> { | |
| 86 | - item.setName(spu.getName()); | |
| 87 | - item.setPicUrl(spu.getPicUrl()); | |
| 88 | - }))); | |
| 83 | + item -> Optional.ofNullable(spuMap.get(item.getSpuId())) | |
| 84 | + .ifPresent(spu -> item.setName(spu.getName()).setPicUrl(spu.getPicUrl())))); | |
| 89 | 85 | } |
| 90 | 86 | |
| 91 | 87 | } |
| 92 | 88 | \ No newline at end of file | ... | ... |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java
| ... | ... | @@ -27,7 +27,7 @@ public class ProductStatisticsRespVO { |
| 27 | 27 | @ExcelProperty("商品SPU编号") |
| 28 | 28 | private Long spuId; |
| 29 | 29 | |
| 30 | - //region 商品信息 | |
| 30 | + // region 商品信息 | |
| 31 | 31 | |
| 32 | 32 | @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "商品名称") |
| 33 | 33 | @ExcelProperty("商品名称") |
| ... | ... | @@ -37,7 +37,7 @@ public class ProductStatisticsRespVO { |
| 37 | 37 | @ExcelProperty("商品封面图") |
| 38 | 38 | private String picUrl; |
| 39 | 39 | |
| 40 | - //endregion | |
| 40 | + // endregion | |
| 41 | 41 | |
| 42 | 42 | @Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "17505") |
| 43 | 43 | @ExcelProperty("浏览量") | ... | ... |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/TradeStatisticsController.java
| ... | ... | @@ -49,7 +49,6 @@ public class TradeStatisticsController { |
| 49 | 49 | @Resource |
| 50 | 50 | private BrokerageStatisticsService brokerageStatisticsService; |
| 51 | 51 | |
| 52 | - // TODO 芋艿:已经 review | |
| 53 | 52 | @GetMapping("/summary") |
| 54 | 53 | @Operation(summary = "获得交易统计") |
| 55 | 54 | @PreAuthorize("@ss.hasPermission('statistics:trade:query')") |
| ... | ... | @@ -75,7 +74,6 @@ public class TradeStatisticsController { |
| 75 | 74 | ArrayUtil.get(reqVO.getTimes(), 1))); |
| 76 | 75 | } |
| 77 | 76 | |
| 78 | - // TODO 芋艿:已经 review | |
| 79 | 77 | @GetMapping("/list") |
| 80 | 78 | @Operation(summary = "获得交易状况明细") |
| 81 | 79 | @PreAuthorize("@ss.hasPermission('statistics:trade:query')") |
| ... | ... | @@ -85,7 +83,6 @@ public class TradeStatisticsController { |
| 85 | 83 | return success(TradeStatisticsConvert.INSTANCE.convertList(list)); |
| 86 | 84 | } |
| 87 | 85 | |
| 88 | - // TODO 芋艿:已经 review | |
| 89 | 86 | @GetMapping("/export-excel") |
| 90 | 87 | @Operation(summary = "导出获得交易状况明细 Excel") |
| 91 | 88 | @PreAuthorize("@ss.hasPermission('statistics:trade:export')") |
| ... | ... | @@ -98,7 +95,6 @@ public class TradeStatisticsController { |
| 98 | 95 | ExcelUtils.write(response, "交易状况.xls", "数据", TradeTrendSummaryExcelVO.class, data); |
| 99 | 96 | } |
| 100 | 97 | |
| 101 | - // TODO 芋艿:已经 review | |
| 102 | 98 | @GetMapping("/order-count") |
| 103 | 99 | @Operation(summary = "获得交易订单数量") |
| 104 | 100 | @PreAuthorize("@ss.hasPermission('statistics:trade:query')") |
| ... | ... | @@ -116,7 +112,6 @@ public class TradeStatisticsController { |
| 116 | 112 | return success(TradeStatisticsConvert.INSTANCE.convert(undeliveredCount, pickUpCount, afterSaleApplyCount, auditingWithdrawCount)); |
| 117 | 113 | } |
| 118 | 114 | |
| 119 | - // TODO 芋艿:已经 review | |
| 120 | 115 | @GetMapping("/order-comparison") |
| 121 | 116 | @Operation(summary = "获得交易订单数量") |
| 122 | 117 | @PreAuthorize("@ss.hasPermission('statistics:trade:query')") |
| ... | ... | @@ -124,7 +119,6 @@ public class TradeStatisticsController { |
| 124 | 119 | return success(tradeOrderStatisticsService.getOrderComparison()); |
| 125 | 120 | } |
| 126 | 121 | |
| 127 | - // TODO 芋艿:已经 review | |
| 128 | 122 | @GetMapping("/order-count-trend") |
| 129 | 123 | @Operation(summary = "获得订单量趋势统计") |
| 130 | 124 | @PreAuthorize("@ss.hasPermission('statistics:trade:query')") | ... | ... |
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/product/ProductStatisticsDO.java
yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/job/product/ProductStatisticsJob.java