From 10d245afc3dbc4236d0f36186213919fc4df7413 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 8 Dec 2023 22:17:13 +0800 Subject: [PATCH 01/55] =?UTF-8?q?=F0=9F=90=9B=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E5=A4=9A=E4=BD=99=E7=9A=84=20yudao-spring-boot-starter-securit?= =?UTF-8?q?y=20=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-spring-boot-starter-websocket/pom.xml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml b/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml index b18ee4783..b534f10d3 100644 --- a/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml @@ -38,17 +38,6 @@ spring-boot-starter-websocket - - - - cn.iocoder.boot - yudao-spring-boot-starter-security - provided - - cn.iocoder.boot From 8c67d1d0ba3259b27dbde8568d4db79d4967ef45 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 9 Dec 2023 01:05:25 +0800 Subject: [PATCH 02/55] =?UTF-8?q?=E2=9C=A8=20=E5=A2=9E=E5=8A=A0=E3=80=8A?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=E5=8A=9F=E8=83=BD=E5=88=B0=E7=B2=BE=E7=AE=80?= =?UTF-8?q?=E7=89=88=E3=80=8B=E7=9A=84=E8=AF=B4=E6=98=8E=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 23fa09d6f..f59f99b2c 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,8 @@ * JDK 21 + Spring Boot 3.2.0 版本: 的 `master` 分支 * JDK 8 + Spring Boot 2.7.18 版本: 的 `master-jdk8` 分支 +如果你想把【完整版】的功能,迁移到【精简版】,可以参考 [《迁移功能到精简版》](https://doc.iocoder.cn/migrate-module/) 文档。 + ## 😎 开源协议 **为什么推荐使用本项目?** From 5c60202c1471f9238cdd1cd4c0ef65d05ca7b604 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 8 Dec 2023 22:17:13 +0800 Subject: [PATCH 03/55] =?UTF-8?q?=F0=9F=90=9B=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E5=A4=9A=E4=BD=99=E7=9A=84=20yudao-spring-boot-starter-securit?= =?UTF-8?q?y=20=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-spring-boot-starter-websocket/pom.xml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml b/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml index b18ee4783..b534f10d3 100644 --- a/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-websocket/pom.xml @@ -38,17 +38,6 @@ spring-boot-starter-websocket - - - - cn.iocoder.boot - yudao-spring-boot-starter-security - provided - - cn.iocoder.boot From a8c14614abb277d68668c119e06a36b9ae4378e7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 9 Dec 2023 01:05:25 +0800 Subject: [PATCH 04/55] =?UTF-8?q?=E2=9C=A8=20=E5=A2=9E=E5=8A=A0=E3=80=8A?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=E5=8A=9F=E8=83=BD=E5=88=B0=E7=B2=BE=E7=AE=80?= =?UTF-8?q?=E7=89=88=E3=80=8B=E7=9A=84=E8=AF=B4=E6=98=8E=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 23fa09d6f..f59f99b2c 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,8 @@ * JDK 21 + Spring Boot 3.2.0 版本: 的 `master` 分支 * JDK 8 + Spring Boot 2.7.18 版本: 的 `master-jdk8` 分支 +如果你想把【完整版】的功能,迁移到【精简版】,可以参考 [《迁移功能到精简版》](https://doc.iocoder.cn/migrate-module/) 文档。 + ## 😎 开源协议 **为什么推荐使用本项目?** From 9bac10c6f77455e532995bb8f44ddbbc97321780 Mon Sep 17 00:00:00 2001 From: Joey Date: Sat, 9 Dec 2023 17:25:47 +0800 Subject: [PATCH 05/55] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E9=94=81=E5=AE=9A/=E8=A7=A3=E9=94=81=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=8C=E6=A0=A1=E9=AA=8C=E9=94=81=E5=AE=9A=E4=B8=8A=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 6 ++ .../admin/customer/CrmCustomerController.java | 4 +- .../customer/vo/CrmCustomerLockReqVO.java | 18 ++++++ .../CrmCustomerLimitConfigCreateReqVO.java | 6 ++ .../convert/customer/CrmCustomerConvert.java | 2 + .../CrmCustomerLimitConfigMapper.java | 16 +++++ .../CrmCustomerLimitConfigService.java | 5 ++ .../CrmCustomerLimitConfigServiceImpl.java | 5 ++ .../service/customer/CrmCustomerService.java | 9 +-- .../customer/CrmCustomerServiceImpl.java | 58 +++++++++++++++---- 10 files changed, 111 insertions(+), 18 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index a7494dc8d..d99e5b23a 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -40,6 +40,12 @@ public interface ErrorCodeConstants { ErrorCode CUSTOMER_LOCKED_PUT_POOL_FAIL = new ErrorCode(1_020_006_005, "客户【{}】放入公海失败,原因:客户已锁定"); ErrorCode CUSTOMER_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_006_006, "更新客户【{}】负责人失败, 原因:系统异常"); + ErrorCode CUSTOMER_UNLOCK_STATUS_NO_REPETITION = new ErrorCode(1_020_006_001, "无需重复操作锁定/解锁状态"); + + ErrorCode CUSTOMER_NO_DEPARTMENT_FOUND = new ErrorCode(1_020_006_002, "操作失败,请先绑定部门再进行操作"); + + ErrorCode CUSTOMER_EXCEED_LOCK_LIMIT = new ErrorCode(1_020_006_003, "操作失败,超出锁定规则上限"); + // ========== 权限管理 1_020_007_000 ========== ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在"); ErrorCode CRM_PERMISSION_DENIED = new ErrorCode(1_020_007_001, "{}操作失败,原因:没有权限"); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index f06e26e4a..5ec7012a1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -134,8 +134,8 @@ public class CrmCustomerController { @PutMapping("/lock") @Operation(summary = "锁定/解锁客户") @PreAuthorize("@ss.hasPermission('crm:customer:update')") - public CommonResult lockCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { - customerService.lockCustomer(updateReqVO); + public CommonResult lockCustomer(@Valid @RequestBody CrmCustomerLockReqVO lockReqVO) { + customerService.lockCustomer(lockReqVO); return success(true); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java new file mode 100644 index 000000000..50608049f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - CRM 客户锁定/解锁 Request VO") +@Data +public class CrmCustomerLockReqVO { + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private Long id; + + @Schema(description = "客户锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Boolean lockStatus; + + + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java index 7aa372901..2cc707c43 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java @@ -5,10 +5,16 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +import java.util.List; + @Schema(description = "管理后台 - 客户限制配置创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class CrmCustomerLimitConfigCreateReqVO extends CrmCustomerLimitConfigBaseVO { + + @Schema(description = "规则适用人群") + private Long userId; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java index 55e2a3518..b300c6416 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java @@ -79,4 +79,6 @@ public interface CrmCustomerConvert { List convertQueryAll(List crmCustomerDO); + CrmCustomerDO convert(CrmCustomerLockReqVO lockReqVO); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java index f5fb31b61..ea8f7d8bf 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java @@ -3,10 +3,14 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; import org.apache.ibatis.annotations.Mapper; +import java.util.Arrays; +import java.util.stream.Collectors; + /** * 客户限制配置 Mapper * @@ -21,4 +25,16 @@ public interface CrmCustomerLimitConfigMapper extends BaseMapperX queryWrapper = new LambdaQueryWrapperX<>(); + queryWrapper.apply("FIND_IN_SET({0}, user_ids) > 0", reqVO.getUserId()); + queryWrapper.eq(CrmCustomerLimitConfigDO::getType, reqVO.getType()); + // 将部门ID列表转换成逗号分隔的字符串 + String deptIdsString = reqVO.getDeptIds().stream() + .map(String::valueOf) + .collect(Collectors.joining(",")); + queryWrapper.apply("FIND_IN_SET({0}, dept_ids) > 0", deptIdsString); + return selectOne(queryWrapper); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java index 96090cdfc..a181032f5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java @@ -53,4 +53,9 @@ public interface CrmCustomerLimitConfigService { */ PageResult getCustomerLimitConfigPage(CrmCustomerLimitConfigPageReqVO pageReqVO); + /** + * 查询当前登录人客户限制配置 + */ + CrmCustomerLimitConfigDO selectByLimitConfig(CrmCustomerLimitConfigCreateReqVO configReqVO); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java index 4528eafad..24cd84d36 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java @@ -90,4 +90,9 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig adminUserApi.validateUserList(userIds); } + @Override + public CrmCustomerLimitConfigDO selectByLimitConfig(CrmCustomerLimitConfigCreateReqVO configReqVO) { + return customerLimitConfigMapper.selectByLimitConfig(configReqVO); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 73be18951..2ecfd9ca5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -1,10 +1,7 @@ package cn.iocoder.yudao.module.crm.service.customer; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import jakarta.validation.Valid; @@ -85,9 +82,9 @@ public interface CrmCustomerService { /** * 锁定/解锁客户 * - * @param updateReqVO 更新信息 + * @param lockReqVO 更新信息 */ - void lockCustomer(@Valid CrmCustomerUpdateReqVO updateReqVO); + void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO); // ==================== 公海相关操作 ==================== diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 93589a5b0..b1a0e1dc8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -2,12 +2,11 @@ package cn.iocoder.yudao.module.crm.service.customer; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; @@ -15,6 +14,7 @@ import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -23,7 +23,10 @@ import org.springframework.validation.annotation.Validated; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_EXCEED_LOCK_LIMIT; +import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; import static java.util.Collections.singletonList; /** @@ -43,6 +46,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Resource private AdminUserApi adminUserApi; + @Resource + private CrmCustomerLimitConfigService crmCustomerLimitConfigService; @Override @Transactional(rollbackFor = Exception.class) @@ -142,14 +147,47 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override - public void lockCustomer(CrmCustomerUpdateReqVO updateReqVO) { - // 校验存在 - validateCustomerExists(updateReqVO.getId()); - // TODO @Joey:可以校验下,如果已经对应的锁定状态,报个业务异常;原因是:后续这个业务会记录操作日志,会记录多了; - // TODO @芋艿:业务完善,增加锁定上限; + public void lockCustomer(CrmCustomerLockReqVO lockReqVO) { + // 校验当前客户是否存在 + validateCustomerExists(lockReqVO.getId()); + + CrmCustomerDO customerDO = customerMapper.selectById(lockReqVO.getId()); + + // 校验当前是否重复操作锁定/解锁状态 + if (customerDO.getLockStatus().equals(lockReqVO.getLockStatus())) { + throw exception(CUSTOMER_UNLOCK_STATUS_NO_REPETITION); + } + + // 获取当前登录信息,开始校验锁定上限 + AdminUserRespDTO userRespDTO = adminUserApi.getUser(getLoginUserId()); + + if (userRespDTO.getDeptId() == null || userRespDTO.getId() == null) { + // 如有入参为空,提示业务异常 + throw exception(CUSTOMER_NO_DEPARTMENT_FOUND); + } + + // 开始校验规则限制 + List userDeptIds = Collections.singletonList(userRespDTO.getDeptId()); + + CrmCustomerLimitConfigCreateReqVO configReqVO = new CrmCustomerLimitConfigCreateReqVO(); + configReqVO.setUserId(userRespDTO.getId()); + configReqVO.setDeptIds(userDeptIds); + configReqVO.setType(CUSTOMER_LOCK_LIMIT.getCode()); + + CrmCustomerLimitConfigDO crmCustomerLimitConfigDO = crmCustomerLimitConfigService.selectByLimitConfig(configReqVO); + + // 统计当前用户已锁定客户数量 + List crmCustomerDOS = customerMapper.selectList("owner_user_id", getLoginUserId()); + long customerLockCount = crmCustomerDOS.stream().filter(CrmCustomerDO::getLockStatus).count(); + + // 锁定操作的时候校验当前用户可锁定客户的上限 + if (crmCustomerLimitConfigDO != null && lockReqVO.getLockStatus() && customerLockCount >= crmCustomerLimitConfigDO.getMaxCount()) { + // 超出锁定数量上限,提示业务异常 + throw exception(CUSTOMER_EXCEED_LOCK_LIMIT); + } // 更新 - CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); + CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(lockReqVO); customerMapper.updateById(updateObj); } From 6a8baff080b1592aa73d9caa1dd4815e8d5c7c9f Mon Sep 17 00:00:00 2001 From: kyle <573984425@qq.com> Date: Mon, 11 Dec 2023 09:28:43 +0800 Subject: [PATCH 06/55] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dvm=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E4=B8=AD=EF=BC=8Cimport=E4=BE=9D=E8=B5=96=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/codegen/java/controller/controller.vm | 8 ++++---- .../resources/codegen/java/controller/vo/saveReqVO.vm | 2 +- .../src/main/resources/codegen/java/service/service.vm | 2 +- .../main/resources/codegen/java/service/serviceImpl.vm | 2 +- .../src/main/resources/codegen/java/test/serviceTest.vm | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/controller.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/controller.vm index 4c047c948..f58ce0cb2 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/controller.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/controller.vm @@ -1,7 +1,7 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}; import org.springframework.web.bind.annotation.*; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.springframework.validation.annotation.Validated; #if ($sceneEnum.scene == 1)import org.springframework.security.access.prepost.PreAuthorize;#end @@ -9,9 +9,9 @@ import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; -import javax.validation.constraints.*; -import javax.validation.*; -import javax.servlet.http.*; +import jakarta.validation.constraints.*; +import jakarta.validation.*; +import jakarta.servlet.http.*; import java.util.*; import java.io.IOException; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/saveReqVO.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/saveReqVO.vm index 89829cc99..5e03326c8 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/saveReqVO.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/saveReqVO.vm @@ -3,7 +3,7 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePac import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import javax.validation.constraints.*; +import jakarta.validation.constraints.*; ## 处理 BigDecimal 字段的引入 import java.util.*; #foreach ($column in $columns) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm index 4085889d9..828cabdf1 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm @@ -1,7 +1,7 @@ package ${basePackage}.module.${table.moduleName}.service.${table.businessName}; import java.util.*; -import javax.validation.*; +import jakarta.validation.*; import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; ## 特殊:主子表专属逻辑 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm index 6aa2fb2e9..4d7070926 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm @@ -1,7 +1,7 @@ package ${basePackage}.module.${table.moduleName}.service.${table.businessName}; import org.springframework.stereotype.Service; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.springframework.validation.annotation.Validated; import org.springframework.transaction.annotation.Transactional; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm index eeac3ce66..f72945064 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import ${baseFrameworkPackage}.test.core.ut.BaseDbUnitTest; @@ -13,7 +13,7 @@ import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.business import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper; import ${PageResultClassName}; -import javax.annotation.Resource; +import jakarta.annotation.Resource; import org.springframework.context.annotation.Import; import java.util.*; import java.time.LocalDateTime; From a6a9f4e3a660d8e6ccfeb66e1bdd4ea6a43ae299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A3=8E=E7=8B=97?= <909275705@qq.com> Date: Mon, 11 Dec 2023 02:47:22 +0000 Subject: [PATCH 07/55] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E4=B8=9C=E8=8E=9E?= =?UTF-8?q?=E5=B8=82=E4=B8=8B=E9=9D=A2=E7=9A=84=E8=A1=8C=E6=94=BF=E5=8C=BA?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 风狗 <909275705@qq.com> --- .../src/main/resources/area.csv | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/area.csv b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/area.csv index 27e753c90..c9a3a0e74 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/area.csv +++ b/yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/area.csv @@ -490,6 +490,37 @@ id,name,type,parentId 441700,阳江市,3,440000 441800,清远市,3,440000 441900,东莞市,3,440000 +441901,莞城区,4,441900 +441902,南城区,4,441900 +441904,万江区,4,441900 +441905,石碣镇,4,441900 +441906,石龙镇,4,441900 +441907,茶山镇,4,441900 +441908,石排镇,4,441900 +441909,企石镇,4,441900 +441910,横沥镇,4,441900 +441911,桥头镇,4,441900 +441912,谢岗镇,4,441900 +441913,东坑镇,4,441900 +441914,常平镇,4,441900 +441915,寮步镇,4,441900 +441916,大朗镇,4,441900 +441917,麻涌镇,4,441900 +441918,中堂镇,4,441900 +441919,高埗镇,4,441900 +441920,樟木头镇,4,441900 +441921,大岭山镇,4,441900 +441922,望牛墩镇,4,441900 +441923,黄江镇,4,441900 +441924,洪梅镇,4,441900 +441925,清溪镇,4,441900 +441926,沙田镇,4,441900 +441927,道滘镇,4,441900 +441928,塘厦镇,4,441900 +441929,虎门镇,4,441900 +441930,厚街镇,4,441900 +441931,凤岗镇,4,441900 +441932,长安镇,4,441900 442000,中山市,3,440000 445100,潮州市,3,440000 445200,揭阳市,3,440000 @@ -3605,4 +3636,4 @@ id,name,type,parentId 659008,可克达拉市,4,659000 659009,昆玉市,4,659000 659010,胡杨河市,4,659000 -659011,新星市,4,659000 +659011,新星市,4,659000 \ No newline at end of file From d2c071bbb676bec834f60c81cd46863898a0ab45 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 12 Dec 2023 12:17:50 +0800 Subject: [PATCH 08/55] =?UTF-8?q?=E2=9C=A8=20=E8=80=83=E8=99=91=E5=88=B0?= =?UTF-8?q?=E5=A4=A7=E5=AE=B6=E7=9A=84=E6=8E=A5=E5=8F=97=E5=BA=A6=EF=BC=8C?= =?UTF-8?q?master=20=E8=BF=98=E6=98=AF=E4=BF=9D=E6=8C=81=20jdk8=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC=EF=BC=88=E7=A8=B3=E5=AE=9A=EF=BC=89=EF=BC=8C?= =?UTF-8?q?master-jdk21=20=E4=BD=BF=E7=94=A8=20jdk21=20=E7=89=88=E6=9C=AC?= =?UTF-8?q?=EF=BC=88=E5=88=9B=E6=96=B0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f59f99b2c..35a1e89b5 100644 --- a/README.md +++ b/README.md @@ -78,15 +78,17 @@ 【完整版】包括系统功能、基础设施、会员中心、数据报表、工作流程、商城系统、微信公众号、CRM 等功能 -* JDK 21 + Spring Boot 3.2.0 版本: 的 `master` 分支 -* JDK 8 + Spring Boot 2.7.18 版本: 的 `master-jdk8` 分支 +* JDK 8 + Spring Boot 2.7.18 版本: 的 `master` 分支 +* JDK 21 + Spring Boot 3.2.0 版本: 的 `master-jdk21` 分支 + +两个分支的功能是一致的,可以放心使用! ### ➡️️ 精简版 【精简版】只包括系统功能、基础设施功能,不包括会员中心、数据报表、工作流程、商城系统、微信公众号、CRM 等功能 -* JDK 21 + Spring Boot 3.2.0 版本: 的 `master` 分支 -* JDK 8 + Spring Boot 2.7.18 版本: 的 `master-jdk8` 分支 +* JDK 8 + Spring Boot 2.7.18 版本: 的 `master` 分支 +* JDK 21 + Spring Boot 3.2.0 版本: 的 `master-jdk21` 分支 如果你想把【完整版】的功能,迁移到【精简版】,可以参考 [《迁移功能到精简版》](https://doc.iocoder.cn/migrate-module/) 文档。 From a7189e74257ee12b9920eab91674e79fc1434d6e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 12 Dec 2023 12:21:38 +0800 Subject: [PATCH 09/55] =?UTF-8?q?=E2=9C=A8=20=E8=80=83=E8=99=91=E5=88=B0?= =?UTF-8?q?=E5=A4=A7=E5=AE=B6=E7=9A=84=E6=8E=A5=E5=8F=97=E5=BA=A6=EF=BC=8C?= =?UTF-8?q?master=20=E8=BF=98=E6=98=AF=E4=BF=9D=E6=8C=81=20jdk8=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC=EF=BC=88=E7=A8=B3=E5=AE=9A=EF=BC=89=EF=BC=8C?= =?UTF-8?q?master-jdk21=20=E4=BD=BF=E7=94=A8=20jdk21=20=E7=89=88=E6=9C=AC?= =?UTF-8?q?=EF=BC=88=E5=88=9B=E6=96=B0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 35a1e89b5..2ae3cf9ce 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ ![架构图](/.image/common/ruoyi-vue-pro-architecture.png) -* Java 后端:`master` 分支为 JDK 21 + Spring Boot 3.2.0,`master-jdk8` 分支为 JDK8 + Spring Boot 2.7.18 +* Java 后端:`master` 分支为 JDK 8 + Spring Boot 2.7.18,`master-jdk21` 分支为 JDK21 + Spring Boot 3.2.0 * 管理后台的电脑端:Vue3 提供 `element-plus`、`vben(ant-design-vue)` 两个版本,Vue2 提供 `element-ui` 版本 * 管理后台的移动端:采用 `uni-app` 方案,一份代码多终端适配,同时支持 APP、小程序、H5! * 后端采用 Spring Boot 多模块架构、MySQL + MyBatis Plus、Redis + Redisson From 35f796875df3713319cca7c6723b34777e83754a Mon Sep 17 00:00:00 2001 From: Qiksy Date: Fri, 15 Dec 2023 09:40:29 +0800 Subject: [PATCH 10/55] =?UTF-8?q?fix=20=E5=AE=A1=E6=89=B9=E6=B5=81-?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E8=8E=B7=E5=8F=96=E5=88=B0=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=8F=98=E9=87=8F=EF=BC=88Process=20Variables=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/bpm/service/task/BpmProcessInstanceServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 603c5bb07..1a4b437e1 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -1 +1 @@ -package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.flowable.core.context.FlowableContextHolder; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; import jakarta.validation.Valid; import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 *

* ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. *

* HistoricProcessInstance & ProcessInstance 的关系: * 1. *

* 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null, createReqVO.getAssignee()); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(), createReqDTO.getAssignee()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String) event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey, Map> assignee) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 设置上下文信息 // TODO @hai:要不往 variables 存到一个全局固定 key 里,减少对上下文的依赖 FlowableContextHolder.setAssignee(assignee); // 创建流程实例 ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables).setAssignee(assignee)); return instance.getId(); } @Override public List getAssigneeByProcessInstanceIdAndTaskDefinitionKey(String processInstanceId, String taskDefinitionKey) { // 1. 先从上下文获取,首次提交数据库中查询不到 List result = FlowableContextHolder.getAssigneeByTaskDefinitionKey(taskDefinitionKey); if (CollUtil.isNotEmpty(result)) { return result; } // 2. 从数据库中获取 BpmProcessInstanceExtDO instance = processInstanceExtMapper.selectByProcessInstanceId(processInstanceId); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } if (CollUtil.isNotEmpty(instance.getAssignee())) { return instance.getAssignee().get(taskDefinitionKey); } return Collections.emptyList(); } } \ No newline at end of file +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.flowable.core.context.FlowableContextHolder; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; import jakarta.validation.Valid; import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 *

* ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. *

* HistoricProcessInstance & ProcessInstance 的关系: * 1. *

* 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery() .includeProcessVariables() .processInstanceId(id) .singleResult(); } @Override public List getProcessInstances(Set ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null, createReqVO.getAssignee()); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(), createReqDTO.getAssignee()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List getHistoricProcessInstances(Set ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String) event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map variables, String businessKey, Map> assignee) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 设置上下文信息 // TODO @hai:要不往 variables 存到一个全局固定 key 里,减少对上下文的依赖 FlowableContextHolder.setAssignee(assignee); // 创建流程实例 ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables).setAssignee(assignee)); return instance.getId(); } @Override public List getAssigneeByProcessInstanceIdAndTaskDefinitionKey(String processInstanceId, String taskDefinitionKey) { // 1. 先从上下文获取,首次提交数据库中查询不到 List result = FlowableContextHolder.getAssigneeByTaskDefinitionKey(taskDefinitionKey); if (CollUtil.isNotEmpty(result)) { return result; } // 2. 从数据库中获取 BpmProcessInstanceExtDO instance = processInstanceExtMapper.selectByProcessInstanceId(processInstanceId); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } if (CollUtil.isNotEmpty(instance.getAssignee())) { return instance.getAssignee().get(taskDefinitionKey); } return Collections.emptyList(); } } \ No newline at end of file From 8434a8cd6864fa31b7e6cfa292adb564ce12c2bf Mon Sep 17 00:00:00 2001 From: zyna Date: Sun, 17 Dec 2023 17:33:52 +0800 Subject: [PATCH 11/55] =?UTF-8?q?crm=E8=81=94=E7=B3=BB=E4=BA=BA=E5=95=86?= =?UTF-8?q?=E6=9C=BA=E5=8A=9F=E8=83=BD=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/optinal/crm.sql | 5 +- .../module/crm/enums/ErrorCodeConstants.java | 2 +- .../admin/business/CrmBusinessController.java | 34 +++++- .../vo/business/CrmBusinessRespVO.java | 2 + .../admin/contact/CrmContactController.java | 23 +++- .../vo/CrmContactBusinessLinkPageReqVO.java | 2 +- .../vo/CrmContactBusinessLinkRespVO.java | 2 +- .../vo/CrmContactBusinessLinkSaveReqVO.java | 2 +- .../CrmContactBusinessLinkController.java | 115 ------------------ .../crm/convert/contact/ContactConvert.java | 12 +- .../CrmContactBusinessLinkConvert.java | 16 --- .../CrmContactBusinessLinkDO.java | 7 +- .../CrmContactBusinessLinkMapper.java | 6 +- .../service/business/CrmBusinessService.java | 12 +- .../business/CrmBusinessServiceImpl.java | 33 +++++ .../CrmContactBusinessLinkService.java | 12 +- .../CrmContactBusinessLinkServiceImpl.java | 47 ++++--- .../service/contact/CrmContactService.java | 10 ++ .../contact/CrmContactServiceImpl.java | 22 +++- 19 files changed, 181 insertions(+), 183 deletions(-) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/{contactbusinesslink => contact}/vo/CrmContactBusinessLinkPageReqVO.java (92%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/{contactbusinesslink => contact}/vo/CrmContactBusinessLinkRespVO.java (91%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/{contactbusinesslink => contact}/vo/CrmContactBusinessLinkSaveReqVO.java (90%) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/CrmContactBusinessLinkController.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contactbusinessslink/CrmContactBusinessLinkConvert.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/{contactbusinesslink => contact}/CrmContactBusinessLinkDO.java (74%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/{contactbusinesslink => contact}/CrmContactBusinessLinkService.java (76%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/{contactbusinesslink => contact}/CrmContactBusinessLinkServiceImpl.java (68%) diff --git a/sql/mysql/optinal/crm.sql b/sql/mysql/optinal/crm.sql index 1cb1371ae..77ec46d97 100644 --- a/sql/mysql/optinal/crm.sql +++ b/sql/mysql/optinal/crm.sql @@ -1,6 +1,6 @@ -- `ruoyi-vue-pro`.crm_contact_business_link definition -CREATE TABLE `crm_contact_business_link` ( +CREATE TABLE `crm_contact_business` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `contact_id` int(11) DEFAULT NULL COMMENT '联系人id', `business_id` int(11) DEFAULT NULL COMMENT '商机id', @@ -10,6 +10,5 @@ CREATE TABLE `crm_contact_business_link` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '租户编号', - PRIMARY KEY (`id`), - UNIQUE KEY `crm_contact_business_link_un` (`contact_id`,`business_id`,`deleted`,`tenant_id`) + PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='联系人商机关联表'; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 222253f9f..567846e46 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -24,7 +24,7 @@ public interface ErrorCodeConstants { // ========== 联系人管理 1-020-003-000 ========== ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode( 1_020_003_001, "联系人商机关联不存在"); - + ErrorCode CONTACT_BUSINESS_LINK_CREATE_EMPTY = new ErrorCode( 1_020_003_002, "联系人商机关联参数为空"); // ========== 回款 1-020-004-000 ========== ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java index 7b924c88a..7f6d9481a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java @@ -4,11 +4,13 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; @@ -31,6 +33,7 @@ import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -170,5 +173,34 @@ public class CrmBusinessController { businessService.transferBusiness(reqVO, getLoginUserId()); return success(true); } - + @GetMapping("/page-by-contact") + @Operation(summary = "获得联系人的商机分页") + @PreAuthorize("@ss.hasPermission('crm:business:query')") + public CommonResult> getBusinessContactPage(@Valid CrmContactBusinessLinkPageReqVO pageVO) { + PageResult pageResult = businessService.getBusinessPageByContact(pageVO); + // 处理商机状态类型名称回显 + Set statusTypeIds = pageResult.getList().stream() + .map(CrmBusinessRespVO::getStatusTypeId).filter(Objects::nonNull).collect(Collectors.toSet()); + CrmBusinessStatusTypeQueryVO queryStatusTypeVO = new CrmBusinessStatusTypeQueryVO(); + queryStatusTypeVO.setIdList(statusTypeIds); + List statusTypeList = businessStatusTypeService.selectList(queryStatusTypeVO); + Map statusTypeMap = CollectionUtils.convertMap(statusTypeList,CrmBusinessStatusTypeDO::getId,CrmBusinessStatusTypeDO::getName); + // 处理商机状态名称回显 + Set statusIds = pageResult.getList().stream() + .map(CrmBusinessRespVO::getStatusId).filter(Objects::nonNull).collect(Collectors.toSet()); + CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO(); + queryVO.setIdList(statusIds); + List statusList = businessStatusService.selectList(queryVO); + Map statusMap = CollectionUtils.convertMap(statusList,CrmBusinessStatusDO::getId,CrmBusinessStatusDO::getName); + // 处理客户名称回显 + Set customerIds = CollectionUtils.convertSet(pageResult.getList(),CrmBusinessRespVO::getCustomerId); + List customerList = customerService.getCustomerList(customerIds); + Map customerMap = CollectionUtils.convertMap(customerList,CrmCustomerDO::getId,CrmCustomerDO::getName); + pageResult.getList().forEach(item -> { + item.setStatusTypeName(statusTypeMap.get(item.getStatusTypeId())); + item.setStatusName(statusMap.get(item.getStatusId())); + item.setCustomerName(customerMap.get(item.getCustomerId())); + }); + return success(pageResult); + } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java index 53c8f45da..c0d61fa93 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java @@ -25,4 +25,6 @@ public class CrmBusinessRespVO extends CrmBusinessBaseVO { @Schema(description = "状态名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "跟进中") private String statusName; + @Schema(description = "联系人商机关联ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") + private Long businessContactId; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java index f39f67ac4..b984f14a0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessLinkService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -30,6 +31,7 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; import java.io.IOException; import java.util.Collections; import java.util.List; @@ -54,10 +56,12 @@ public class CrmContactController { private CrmContactService contactService; @Resource private CrmCustomerService customerService; - @Resource private AdminUserApi adminUserApi; + @Resource + private CrmContactBusinessLinkService contactBusinessLinkService; + @PostMapping("/create") @Operation(summary = "创建联系人") @PreAuthorize("@ss.hasPermission('crm:contact:create')") @@ -137,6 +141,23 @@ public class CrmContactController { convertDetailContactPage(pageResult).getList()); } + @DeleteMapping("/delete-batch-business") + @Operation(summary = "批量删除联系人商机关联") + @PreAuthorize("@ss.hasPermission('crm:contact-business-link:delete')") + public CommonResult deleteContactBusinessLinkBatch(@Valid @RequestBody List businessContactIds) { + contactBusinessLinkService.deleteContactBusinessLink(businessContactIds); + return success(true); + } + + @PostMapping("/create-batch-business") + @Operation(summary = "创建联系人商机关联") + @PreAuthorize("@ss.hasPermission('crm:contact-business-link:create')") + public CommonResult createContactBusinessLinkBatch( + @Valid @NotEmpty @RequestBody List createReqVO) { + contactBusinessLinkService.createContactBusinessLinkBatch(createReqVO); + return success(true); + } + /** * 转换成详细的联系人分页,即读取关联信息 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/vo/CrmContactBusinessLinkPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkPageReqVO.java similarity index 92% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/vo/CrmContactBusinessLinkPageReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkPageReqVO.java index c8e98c15a..0755b6715 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/vo/CrmContactBusinessLinkPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo; +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/vo/CrmContactBusinessLinkRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkRespVO.java similarity index 91% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/vo/CrmContactBusinessLinkRespVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkRespVO.java index 17aadf667..7dd061b48 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/vo/CrmContactBusinessLinkRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo; +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/vo/CrmContactBusinessLinkSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkSaveReqVO.java similarity index 90% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/vo/CrmContactBusinessLinkSaveReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkSaveReqVO.java index 1db4d2717..3613124c3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/vo/CrmContactBusinessLinkSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkSaveReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo; +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/CrmContactBusinessLinkController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/CrmContactBusinessLinkController.java deleted file mode 100644 index 52234369c..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/CrmContactBusinessLinkController.java +++ /dev/null @@ -1,115 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink; - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContactBusinessLinkDO; -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; -import cn.iocoder.yudao.module.crm.service.contactbusinesslink.CrmContactBusinessLinkService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.validation.Valid; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; - -@Tag(name = "管理后台 - CRM 联系人商机关联") -@RestController -@RequestMapping("/crm/contact-business-link") -@Validated -public class CrmContactBusinessLinkController { - - @Resource - private CrmContactBusinessLinkService contactBusinessLinkService; - @Resource - private CrmBusinessService crmBusinessService; - - // TODO @zyna:createContactBusinessLink 和 createContactBusinessLinkBatch 是不是合并成一个接口?contactId、List - @PostMapping("/create") - @Operation(summary = "创建联系人商机关联") - @PreAuthorize("@ss.hasPermission('crm:contact-business-link:create')") - public CommonResult createContactBusinessLink(@Valid @RequestBody CrmContactBusinessLinkSaveReqVO createReqVO) { - return success(contactBusinessLinkService.createContactBusinessLink(createReqVO)); - } - - @PostMapping("/create-batch") - @Operation(summary = "创建联系人商机关联") - @PreAuthorize("@ss.hasPermission('crm:contact-business-link:create')") - @Transactional(rollbackFor = Exception.class) - public CommonResult createContactBusinessLinkBatch( - @Valid @RequestBody List createReqVO) { - createReqVO.stream().forEach(item -> { - CrmBusinessDO crmBusinessDO = crmBusinessService.getBusiness(item.getBusinessId()); - if(crmBusinessDO == null){ - throw exception(BUSINESS_NOT_EXISTS); - } - }); - contactBusinessLinkService.createContactBusinessLinkBatch(createReqVO); - return success(true); - } - - // TODO @zyna:这个接口是不是可以删除掉了哈?应该不存在更新。 - @PutMapping("/update") - @Operation(summary = "更新联系人商机关联") - @PreAuthorize("@ss.hasPermission('crm:contact-business-link:update')") - public CommonResult updateContactBusinessLink(@Valid @RequestBody CrmContactBusinessLinkSaveReqVO updateReqVO) { - contactBusinessLinkService.updateContactBusinessLink(updateReqVO); - return success(true); - } - - // TODO @zyna:删除,是不是传递 ids? - @DeleteMapping("/delete-batch") - @Operation(summary = "批量删除联系人商机关联") - @PreAuthorize("@ss.hasPermission('crm:contact-business-link:delete')") - public CommonResult deleteContactBusinessLinkBatch(@Valid @RequestBody List deleteList) { - contactBusinessLinkService.deleteContactBusinessLink(deleteList); - return success(true); - } - - // TODO @zyna:这个接口是不是可以删除掉了哈?应该不存在单个读取; - @GetMapping("/get") - @Operation(summary = "获得联系人商机关联") - @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('crm:contact-business-link:query')") - public CommonResult getContactBusinessLink(@RequestParam("id") Long id) { - CrmContactBusinessLinkDO contactBusinessLink = contactBusinessLinkService.getContactBusinessLink(id); - return success(BeanUtils.toBean(contactBusinessLink, CrmContactBusinessLinkRespVO.class)); - } - - // TODO @zyna:这个可以转化下,使用客户编号去查询,就是使用 CrmBusinessController 的 getBusinessPageByCustomer 接口;目的是:复用 - @GetMapping("/page-by-contact") - @Operation(summary = "获得联系人商机关联") - @PreAuthorize("@ss.hasPermission('crm:contact-business-link:query')") - public CommonResult> getContactBusinessLinkByContact( - @Valid CrmContactBusinessLinkPageReqVO pageReqVO) { - PageResult contactBusinessLink = contactBusinessLinkService.getContactBusinessLinkPageByContact(pageReqVO); - return success(contactBusinessLink); - } - - // TODO @zyna:这个优化下,搞到 CrmBusinessController 里去,加一个 CrmBusinessController 的 getBusinessPageByContact 接口;目的是: - @GetMapping("/page") - @Operation(summary = "获得联系人商机关联分页") - @PreAuthorize("@ss.hasPermission('crm:contact-business-link:query')") - public CommonResult> getContactBusinessLinkPage( - @Valid CrmContactBusinessLinkPageReqVO pageReqVO) { - PageResult pageResult = contactBusinessLinkService.getContactBusinessLinkPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, CrmContactBusinessLinkRespVO.class)); - } - - // TODO @zyna:最终梳理完后,应该就 2 个接口,要不直接合并到 CrmContactController 中,不作为独立模块,就关联、接触关联。其实和 user 设置它有哪些岗位、部门是类似的。 - -} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java index 636835be7..48e18b5b8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java @@ -80,12 +80,12 @@ public interface ContactConvert { Map customerMap = convertMap(customerList, CrmCustomerDO::getId); result.forEach(item -> { setUserInfo(item, userMap); - findAndThen(customerMap, item.getCustomerId(), customer -> { // TODO @zyna:这里的 { 可以去掉 - item.setCustomerName(customer.getName()); - }); - findAndThen(parentContactMap, item.getParentId(), contactDO -> { // TODO @zyna:这里的 { 可以去掉 - item.setParentName(contactDO.getName()); - }); + findAndThen(customerMap, item.getCustomerId(), customer -> + item.setCustomerName(customer.getName()) + ); + findAndThen(parentContactMap, item.getParentId(), contactDO -> + item.setParentName(contactDO.getName()) + ); }); return result; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contactbusinessslink/CrmContactBusinessLinkConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contactbusinessslink/CrmContactBusinessLinkConvert.java deleted file mode 100644 index dfb71bad5..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contactbusinessslink/CrmContactBusinessLinkConvert.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.contactbusinessslink; - -import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContactBusinessLinkDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -// TODO @zyna:使用 BeanUtils 慢慢替代现有的 mapstruct 哈 -@Mapper -public interface CrmContactBusinessLinkConvert { - CrmContactBusinessLinkConvert INSTANCE = Mappers.getMapper(CrmContactBusinessLinkConvert.class); - CrmContactBusinessLinkDO convert(CrmContactBusinessLinkSaveReqVO bean); - List convert(List bean); -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contactbusinesslink/CrmContactBusinessLinkDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessLinkDO.java similarity index 74% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contactbusinesslink/CrmContactBusinessLinkDO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessLinkDO.java index ad6c898d7..7e7c50c89 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contactbusinesslink/CrmContactBusinessLinkDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessLinkDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink; +package cn.iocoder.yudao.module.crm.dal.dataobject.contact; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; @@ -8,14 +8,13 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; -// TODO @zyna:可以放到 contact 包下 /** * CRM 联系人商机关联 DO * * @author 芋道源码 */ -@TableName("crm_contact_business_link") -@KeySequence("crm_contact_business_link_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@TableName("crm_contact_business") +@KeySequence("crm_contact_business_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessLinkMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessLinkMapper.java index 1692def86..df67bf6e5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessLinkMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessLinkMapper.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkPageReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContactBusinessLinkDO; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; import org.apache.ibatis.annotations.Mapper; /** @@ -21,7 +21,7 @@ public interface CrmContactBusinessLinkMapper extends BaseMapperX selectPageByContact(CrmContactBusinessLinkPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .eqIfPresent(CrmContactBusinessLinkDO::getContactId, reqVO.getContactId()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java index 2e62db48d..cdde95422 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java @@ -1,10 +1,8 @@ package cn.iocoder.yudao.module.crm.service.business; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessCreateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -88,4 +86,10 @@ public interface CrmBusinessService { */ void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId); + /** + * 获取联系人商机列表 + * @param pageReqVO 分页参数 + * @return 联系人商机 + */ + PageResult getBusinessPageByContact(CrmContactBusinessLinkPageReqVO pageReqVO); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index d96124799..a496f0eb4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -3,15 +3,20 @@ package cn.iocoder.yudao.module.crm.service.business; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import org.springframework.stereotype.Service; @@ -21,6 +26,7 @@ import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -42,6 +48,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Resource private CrmPermissionService crmPermissionService; + @Resource + private CrmContactService crmContactService; + @Override @Transactional(rollbackFor = Exception.class) public Long createBusiness(CrmBusinessCreateReqVO createReqVO, Long userId) { @@ -134,5 +143,29 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { // 3. TODO 记录转移日志 } + @Override + public PageResult getBusinessPageByContact(CrmContactBusinessLinkPageReqVO pageReqVO) { + CrmContactBusinessLinkPageReqVO crmContactBusinessLinkPageReqVO = new CrmContactBusinessLinkPageReqVO(); + crmContactBusinessLinkPageReqVO.setContactId(pageReqVO.getContactId()); + PageResult businessLinkDOS = crmContactService.selectBusinessPageByContact(crmContactBusinessLinkPageReqVO); + if (CollUtil.isEmpty(businessLinkDOS.getList())){ + return PageResult.empty(); + } + List businessList = this.getBusinessList(CollectionUtils.convertList(businessLinkDOS.getList(), + CrmContactBusinessLinkDO::getBusinessId)); + if (CollUtil.isEmpty(businessList)){ + return PageResult.empty(); + } + PageResult pageResult = new PageResult(); + List respVOList = BeanUtils.toBean(businessList,CrmBusinessRespVO.class); + Map businessContactMap = CollectionUtils.convertMap(businessLinkDOS.getList(), + CrmContactBusinessLinkDO::getBusinessId,CrmContactBusinessLinkDO::getId); + respVOList.forEach(item -> { + item.setBusinessContactId(businessContactMap.get(item.getId())); + }); + pageResult.setList(respVOList); + pageResult.setTotal(businessLinkDOS.getTotal()); + return pageResult; + } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkService.java similarity index 76% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkService.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkService.java index 34a62b341..b06ddbf18 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkService.java @@ -1,10 +1,10 @@ -package cn.iocoder.yudao.module.crm.service.contactbusinesslink; +package cn.iocoder.yudao.module.crm.service.contact; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContactBusinessLinkDO; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkSaveReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; import javax.validation.Valid; import java.util.List; @@ -41,9 +41,9 @@ public interface CrmContactBusinessLinkService { /** * 删除联系人商机关联 * - * @param createReqVO 删除列表 + * @param businessContactIds 删除列表 */ - void deleteContactBusinessLink(@Valid List createReqVO); + void deleteContactBusinessLink(@Valid List businessContactIds); /** * 获得联系人商机关联 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkServiceImpl.java similarity index 68% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkServiceImpl.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkServiceImpl.java index 1ad91e6ec..4400a09f0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkServiceImpl.java @@ -1,25 +1,31 @@ -package cn.iocoder.yudao.module.crm.service.contactbusinesslink; +package cn.iocoder.yudao.module.crm.service.contact; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contactbusinesslink.vo.CrmContactBusinessLinkSaveReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkSaveReqVO; import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; -import cn.iocoder.yudao.module.crm.convert.contactbusinessslink.CrmContactBusinessLinkConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContactBusinessLinkDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessLinkMapper; +import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; +import java.util.ArrayList; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTACT_BUSINESS_LINK_NOT_EXISTS; // TODO @puhui999:数据权限的校验;每个操作; @@ -37,6 +43,9 @@ public class CrmContactBusinessLinkServiceImpl implements CrmContactBusinessLink @Resource private CrmBusinessService crmBusinessService; + @Resource + private CrmContactService crmContactService; + @Override public Long createContactBusinessLink(CrmContactBusinessLinkSaveReqVO createReqVO) { CrmContactBusinessLinkDO contactBusinessLink = BeanUtils.toBean(createReqVO, CrmContactBusinessLinkDO.class); @@ -47,9 +56,22 @@ public class CrmContactBusinessLinkServiceImpl implements CrmContactBusinessLink @Override public void createContactBusinessLinkBatch(List createReqVOList) { // 插入 - // TODO @zyna:如果已经关联过,不用重复插入; - // TODO @zyna:contact 和 business 存在校验,挪到这里,Controller 不用 @Transactional 注解,添加到这里哈。尽量业务都在 Service; - List saveDoList = CrmContactBusinessLinkConvert.INSTANCE.convert(createReqVOList); + CrmContactDO contactDO = crmContactService.getContact(createReqVOList.stream().findFirst().get().getContactId()); + Assert.notNull(contactDO,ErrorCodeConstants.CONTACT_NOT_EXISTS.getMsg()); + List saveDoList = new ArrayList(); + createReqVOList.forEach(item -> { + CrmBusinessDO crmBusinessDO = crmBusinessService.getBusiness(item.getBusinessId()); + if(crmBusinessDO == null){ + throw exception(BUSINESS_NOT_EXISTS); + } + // 判重 + CrmContactBusinessLinkDO crmContactBusinessLinkDO = contactBusinessLinkMapper.selectOne(new LambdaQueryWrapper() + .eq(CrmContactBusinessLinkDO::getBusinessId,item.getBusinessId()) + .eq(CrmContactBusinessLinkDO::getContactId,item.getContactId())); + if(crmContactBusinessLinkDO == null){ + saveDoList.add(BeanUtils.toBean(item,CrmContactBusinessLinkDO.class)); + } + }); contactBusinessLinkMapper.insertBatch(saveDoList); } @@ -63,14 +85,9 @@ public class CrmContactBusinessLinkServiceImpl implements CrmContactBusinessLink } @Override - public void deleteContactBusinessLink(List createReqVO) { + public void deleteContactBusinessLink(List businessContactIds) { // 删除 - createReqVO.forEach(item -> { - contactBusinessLinkMapper.delete(new LambdaQueryWrapperX() - .eq(CrmContactBusinessLinkDO::getBusinessId,item.getBusinessId()) - .eq(CrmContactBusinessLinkDO::getContactId,item.getContactId()) - .eq(CrmContactBusinessLinkDO::getDeleted,0)); - }); + contactBusinessLinkMapper.deleteBatchIds(businessContactIds); } private void validateContactBusinessLinkExists(Long id) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java index 6f49f7661..17797561d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java @@ -1,9 +1,11 @@ package cn.iocoder.yudao.module.crm.service.contact; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -84,4 +86,12 @@ public interface CrmContactService { */ List getContactList(); + + /** + * 获取联系人商机关联分页列表 + * @param reqVO 联系人 + * @return 商机联系人关联列表 + */ + PageResult selectBusinessPageByContact(CrmContactBusinessLinkPageReqVO reqVO); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 57ebdf4e1..db91399f3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -3,13 +3,16 @@ package cn.iocoder.yudao.module.crm.service.contact; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBaseVO; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; +import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; +import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessLinkMapper; import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; @@ -46,10 +49,12 @@ public class CrmContactServiceImpl implements CrmContactService { private CrmCustomerService customerService; @Resource private CrmPermissionService crmPermissionService; - @Resource private AdminUserApi adminUserApi; + @Resource + private CrmContactBusinessLinkMapper contactBusinessLinkMapper; + @Override @Transactional(rollbackFor = Exception.class) public Long createContact(CrmContactCreateReqVO createReqVO, Long userId) { @@ -144,4 +149,11 @@ public class CrmContactServiceImpl implements CrmContactService { return contactMapper.selectList(); } + @Override + public PageResult selectBusinessPageByContact(CrmContactBusinessLinkPageReqVO pageReqVO) { + CrmContactBusinessLinkPageReqVO crmContactBusinessLinkPageReqVO = new CrmContactBusinessLinkPageReqVO(); + crmContactBusinessLinkPageReqVO.setContactId(pageReqVO.getContactId()); + return contactBusinessLinkMapper.selectPageByContact(crmContactBusinessLinkPageReqVO); + + } } From 3bab9748db4d7e0661afaf365b3789966223145d Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 19 Dec 2023 09:20:47 +0800 Subject: [PATCH 12/55] =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=A5=E5=BF=97=EF=BC=9A=E4=BD=BF=E7=94=A8=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=20starter=20=E7=9A=84=E6=96=B9=E5=BC=8F=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E9=9B=86=E6=88=90=20mzt-biz-log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 2 +- .../pom.xml | 7 ++++ .../YudaoOperateLogV2Configuration.java | 28 +++++++++++++++ .../operatelogv2/core/package-info.java | 1 + .../core}/service/ILogRecordServiceImpl.java | 31 ++++++++--------- .../core/vo/OperateLogV2PageReqVO.java | 20 +++++++++++ .../framework/operatelogv2/package-info.java | 1 + ...ot.autoconfigure.AutoConfiguration.imports | 3 +- .../module/crm/enums/LogRecordConstants.java | 1 - .../yudao-module-system-api/pom.xml | 20 ----------- .../system/api/logger/OperateLogApi.java | 21 ++++++++---- .../logger/dto/OperateLogV2CreateReqDTO.java} | 19 ++++++----- .../logger/dto/OperateLogV2PageReqDTO.java | 28 +++++++++++++++ .../api/logger/dto/OperateLogV2RespDTO.java | 27 ++++----------- .../system/api/logger/OperateLogApiImpl.java | 34 +++++++++++++------ .../convert/logger/OperateLogConvert.java | 8 +++++ .../dal/dataobject/logger/OperateLogV2DO.java | 7 ++-- .../dal/mysql/logger/OperateLogV2Mapper.java | 13 +++---- .../YudaoOperateLogV2Configuration.java | 16 --------- .../service/logger/OperateLogService.java | 17 ++++------ .../service/logger/OperateLogServiceImpl.java | 11 +++--- 21 files changed, 187 insertions(+), 128 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java rename {yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog => yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core}/service/ILogRecordServiceImpl.java (68%) create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java rename yudao-module-system/{yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java => yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java} (80%) create mode 100644 yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2PageReqDTO.java delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index da0c4e735..4c1e671a3 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -26,7 +26,7 @@ 3.5.4.1 3.5.4.1 4.2.0 - 1.4.7.2 + 1.4.8.1 3.25.0 8.1.3.62 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml index 5792b4cb4..51ea2e04f 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml @@ -46,6 +46,13 @@ com.google.guava guava + + + + io.github.mouzt + bizlog-sdk + + diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java new file mode 100644 index 000000000..fa907c8f6 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.operatelogv2.config; + +import cn.iocoder.yudao.framework.operatelogv2.core.service.ILogRecordServiceImpl; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import com.mzt.logapi.service.ILogRecordService; +import com.mzt.logapi.starter.annotation.EnableLogRecord; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +/** + * mzt-biz-log 配置类 + * + * @author HUIHUI + */ +@EnableLogRecord(tenant = "") // 貌似用不上 tenant 这玩意给个空好啦 +@AutoConfiguration +@Slf4j +public class YudaoOperateLogV2Configuration { + + @Bean + @Primary + public ILogRecordService iLogRecordServiceImpl(OperateLogApi operateLogApi) { + return new ILogRecordServiceImpl(operateLogApi); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java new file mode 100644 index 000000000..2cc0c2835 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.framework.operatelogv2.core; \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java similarity index 68% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java rename to yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java index 07b25343e..903f5de72 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java @@ -1,38 +1,35 @@ -package cn.iocoder.yudao.module.system.framework.bizlog.service; +package cn.iocoder.yudao.framework.operatelogv2.core.service; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import cn.iocoder.yudao.module.system.service.logger.OperateLogService; -import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; import com.mzt.logapi.beans.LogRecord; import com.mzt.logapi.service.ILogRecordService; -import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; -// TODO @puhui999:这个应该搞到 operatelog 组件里哈; /** * 操作日志 ILogRecordService 实现类 * - * 基于 {@link OperateLogService} 实现,记录操作日志 + * 基于 {@link OperateLogApi} 实现,记录操作日志 * * @author HUIHUI */ @Slf4j -@Service +@RequiredArgsConstructor public class ILogRecordServiceImpl implements ILogRecordService { - @Resource - private OperateLogService operateLogService; + private final OperateLogApi operateLogApi; @Override public void record(LogRecord logRecord) { - OperateLogV2CreateReqBO reqBO = new OperateLogV2CreateReqBO(); + OperateLogV2CreateReqDTO reqBO = new OperateLogV2CreateReqDTO(); // 补全通用字段 reqBO.setTraceId(TracerUtils.getTraceId()); // 补充用户信息 @@ -42,24 +39,24 @@ public class ILogRecordServiceImpl implements ILogRecordService { // 补全请求信息 fillRequestFields(reqBO); // 异步记录日志 - operateLogService.createOperateLogV2(reqBO); + operateLogApi.createOperateLogV2(reqBO); log.info("操作日志 ===> {}", reqBO); } - private static void fillUserFields(OperateLogV2CreateReqBO reqBO) { + private static void fillUserFields(OperateLogV2CreateReqDTO reqBO) { reqBO.setUserId(WebFrameworkUtils.getLoginUserId()); reqBO.setUserType(WebFrameworkUtils.getLoginUserType()); } - public static void fillModuleFields(OperateLogV2CreateReqBO reqBO, LogRecord logRecord) { - reqBO.setModule(logRecord.getType()); // 大模块类型如 crm-客户 - reqBO.setName(logRecord.getSubType());// 操作名称如 转移客户 + public static void fillModuleFields(OperateLogV2CreateReqDTO reqBO, LogRecord logRecord) { + reqBO.setType(logRecord.getType()); // 大模块类型如 crm-客户 + reqBO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 reqBO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 reqBO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 reqBO.setExtra(logRecord.getExtra()); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} } - private static void fillRequestFields(OperateLogV2CreateReqBO reqBO) { + private static void fillRequestFields(OperateLogV2CreateReqDTO reqBO) { // 获得 Request 对象 HttpServletRequest request = ServletUtils.getRequest(); if (request == null) { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java new file mode 100644 index 000000000..8d7a535ad --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.framework.operatelogv2.core.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - 操作日志分页 Request VO") +@Data +public class OperateLogV2PageReqVO extends PageParam { + + @Schema(description = "模块数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long bizId; + + @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long userId; + + @Schema(description = "模块类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String bizType; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java new file mode 100644 index 000000000..439ddc3de --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.framework.operatelogv2; \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 04ccab1cd..3fb6d2cc9 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1 +1,2 @@ -cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration \ No newline at end of file +cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration +cn.iocoder.yudao.framework.operatelogv2.config.YudaoOperateLogV2Configuration \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java index ae8c795ab..9435ec27d 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java @@ -22,6 +22,5 @@ public interface LogRecordConstants { //======================= 客户转移操作日志 ======================= String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; - String TRANSFER_CUSTOMER_LOG_FAIL = ""; // TODO @puhui999:这个可以删除哈,一般不搞失败的日志 } diff --git a/yudao-module-system/yudao-module-system-api/pom.xml b/yudao-module-system/yudao-module-system-api/pom.xml index 2a60b20b8..c98baf3dd 100644 --- a/yudao-module-system/yudao-module-system-api/pom.xml +++ b/yudao-module-system/yudao-module-system-api/pom.xml @@ -22,32 +22,12 @@ yudao-common - - - - - io.github.mouzt - bizlog-sdk - - - - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-core - - org.springframework.boot spring-boot-starter-validation true - diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java index ad42c87f7..509d3f0a1 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java @@ -1,11 +1,12 @@ package cn.iocoder.yudao.module.system.api.logger; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import jakarta.validation.Valid; -import java.util.List; - /** * 操作日志 API 接口 * @@ -21,12 +22,18 @@ public interface OperateLogApi { void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO); /** - * 获取指定模块的指定数据的操作日志 + * 创建操作日志 * - * @param module 操作模块 - * @param bizId 操作模块编号 - * @return 操作日志 + * @param createReqDTO 请求 */ - List getOperateLogByModuleAndBizId(String module, Long bizId); + void createOperateLogV2(@Valid OperateLogV2CreateReqDTO createReqDTO); + + /** + * 获取指定模块的指定数据的操作日志分页 + * + * @param pageReqVO 请求 + * @return 操作日志分页 + */ + PageResult getOperateLogPage(OperateLogV2PageReqDTO pageReqVO); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java similarity index 80% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java index d6c44604c..8904bf072 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java @@ -1,7 +1,8 @@ -package cn.iocoder.yudao.module.system.service.logger.bo; +package cn.iocoder.yudao.module.system.api.logger.dto; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import lombok.Data; /** @@ -10,7 +11,7 @@ import lombok.Data; * @author HUIHUI */ @Data -public class OperateLogV2CreateReqBO { +public class OperateLogV2CreateReqDTO { /** * 链路追踪编号 @@ -23,29 +24,29 @@ public class OperateLogV2CreateReqBO { * * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 */ - @NotEmpty(message = "用户编号不能为空") + @NotNull(message = "用户编号不能为空") private Long userId; /** * 用户类型 * * 关联 {@link UserTypeEnum} */ - @NotEmpty(message = "用户类型不能为空") + @NotNull(message = "用户类型不能为空") private Integer userType; /** - * 操作模块 + * 操作模块类型 */ - @NotEmpty(message = "操作模块不能为空") - private String module; + @NotEmpty(message = "操作模块类型不能为空") + private String type; /** * 操作名 */ @NotEmpty(message = "操作名不能为空") - private String name; + private String subType; /** * 操作模块业务编号 */ - @NotEmpty(message = "操作模块业务编号不能为空") + @NotNull(message = "操作模块业务编号不能为空") private Long bizId; /** * 操作内容,记录整个操作的明细 diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2PageReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2PageReqDTO.java new file mode 100644 index 000000000..aa54c3f5c --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2PageReqDTO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.system.api.logger.dto; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import lombok.Data; + +/** + * 操作日志分页 Request DTO + * + * @author HUIHUI + */ +@Data +public class OperateLogV2PageReqDTO extends PageParam { + + /** + * 模块类型 + */ + private String bizType; + /** + * 模块数据编号 + */ + private Long bizId; + + /** + * 用户编号 + */ + private Long userId; + +} diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java index a7670541d..2a3ca002c 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java @@ -1,14 +1,7 @@ package cn.iocoder.yudao.module.system.api.logger.dto; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; - /** * 系统操作日志 Resp DTO * @@ -25,6 +18,10 @@ public class OperateLogV2RespDTO { * 用户编号 */ private Long userId; + /** + * 用户名称 + */ + private String userName; /** * 用户类型 */ @@ -68,20 +65,8 @@ public class OperateLogV2RespDTO { private String userAgent; /** - * 创建时间 + * 创建时间, 直接返回字符串 */ - // TODO puhui999: 木得效果怎么肥事 - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private LocalDateTime createTime; - - // TODO @puhui999:下面 2 个字段不用返回;用 userId 哈;返回一个 userName - /** - * 创建者 - */ - private String creator; - /** - * 创建者名称 - */ - private String creatorName; + private String createTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java index d748bcc23..4e0ff0397 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java @@ -1,18 +1,22 @@ package cn.iocoder.yudao.module.system.api.logger; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; +import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.logger.OperateLogService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import jakarta.annotation.Resource; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -39,21 +43,31 @@ public class OperateLogApiImpl implements OperateLogApi { } @Override - public List getOperateLogByModuleAndBizId(String module, Long bizId) { - List logList = operateLogService.getOperateLogByModuleAndBizId(module, bizId); - if (CollUtil.isEmpty(logList)) { - return Collections.emptyList(); + @Async + public void createOperateLogV2(OperateLogV2CreateReqDTO createReqDTO) { + operateLogService.createOperateLogV2(createReqDTO); + } + + @Override + public PageResult getOperateLogPage(OperateLogV2PageReqDTO pageReqVO) { + PageResult operateLogPage = operateLogService.getOperateLogPage(pageReqVO); + if (CollUtil.isEmpty(operateLogPage.getList())) { + return PageResult.empty(); } // 获取用户 - List userList = adminUserService.getUserList(convertSet(logList, item -> Long.parseLong(item.getCreator()))); + List userList = adminUserService.getUserList(convertSet(operateLogPage.getList(), OperateLogV2DO::getUserId)); + return BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class).setList(setUserInfo(operateLogPage.getList(), userList)); + } + + private static List setUserInfo(List logList, List userList) { Map userMap = convertMap(userList, AdminUserDO::getId); return convertList(logList, item -> { - OperateLogV2RespDTO bean = BeanUtils.toBean(item, OperateLogV2RespDTO.class); - findAndThen(userMap, Long.parseLong(item.getCreator()), user -> { - bean.setCreatorName(user.getNickname()); + OperateLogV2RespDTO respDTO = OperateLogConvert.INSTANCE.convert(item); + findAndThen(userMap, item.getUserId(), user -> { + respDTO.setUserName(user.getNickname()); }); - return bean; + return respDTO; }); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java index 7b3aff8c0..eebbedc7d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java @@ -3,15 +3,20 @@ package cn.iocoder.yudao.module.system.convert.logger; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; import java.util.Map; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + @Mapper public interface OperateLogConvert { @@ -25,4 +30,7 @@ public interface OperateLogConvert { }); } + @Mapping(target = "createTime", source = "logV2DO.createTime", dateFormat = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + OperateLogV2RespDTO convert(OperateLogV2DO logV2DO); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java index 10035c8e9..56845b131 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java @@ -42,15 +42,14 @@ public class OperateLogV2DO extends BaseDO { * 关联 {@link UserTypeEnum} */ private Integer userType; - // TODO @puhui999:module 改成 type,name 改成 subType; /** - * 操作模块 + * 操作模块类型 */ - private String module; + private String type; /** * 操作名 */ - private String name; + private String subType; /** * 操作模块业务编号 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java index 362f0d2c4..0b2458106 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java @@ -3,28 +3,29 @@ package cn.iocoder.yudao.module.system.dal.mysql.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; -import java.util.List; @Mapper public interface OperateLogV2Mapper extends BaseMapperX { default PageResult selectPage(OperateLogPageReqVO reqVO, Collection userIds) { LambdaQueryWrapperX query = new LambdaQueryWrapperX() - .likeIfPresent(OperateLogV2DO::getModule, reqVO.getModule()) + .likeIfPresent(OperateLogV2DO::getType, reqVO.getModule()) .inIfPresent(OperateLogV2DO::getUserId, userIds); query.orderByDesc(OperateLogV2DO::getId); // 降序 return selectPage(reqVO, query); } - default List selectListByModuleAndBizId(String module, Long bizId) { - return selectList(new LambdaQueryWrapperX() - .eq(OperateLogV2DO::getModule, module) - .eq(OperateLogV2DO::getBizId, bizId) + default PageResult selectPage(OperateLogV2PageReqDTO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eqIfPresent(OperateLogV2DO::getType, pageReqVO.getBizType()) + .eqIfPresent(OperateLogV2DO::getBizId, pageReqVO.getBizId()) + .eqIfPresent(OperateLogV2DO::getUserId, pageReqVO.getUserId()) .orderByDesc(OperateLogV2DO::getCreateTime)); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java deleted file mode 100644 index a5f3a9eaa..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.system.framework.bizlog.config; - -import com.mzt.logapi.starter.annotation.EnableLogRecord; -import org.springframework.context.annotation.Configuration; - -// TODO @puhui999:挪到 yudao-spring-boot-starter-biz-operatelog 下,搞个 cn.iocoder.yudao.framework.operatelogv2;跑通后,我们直接就删除老的实现了; -/** - * mzt-biz-log 配置类 - * - * @author HUIHUI - */ -@Configuration(proxyBeanMethods = false) -@EnableLogRecord(tenant = "") // 貌似用不上 tenant 这玩意给个空好啦 -public class YudaoOperateLogV2Configuration { - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java index 971685857..27ced45a0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java @@ -2,12 +2,11 @@ package cn.iocoder.yudao.module.system.service.logger; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; -import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; - -import java.util.List; /** * 操作日志 Service 接口 @@ -38,16 +37,14 @@ public interface OperateLogService { * * @param createReqBO 创建请求 */ - void createOperateLogV2(OperateLogV2CreateReqBO createReqBO); + void createOperateLogV2(OperateLogV2CreateReqDTO createReqBO); - // TODO @puhui999:module 改成 type /** - * 获取指定模块的指定数据的操作日志 + * 获得操作日志分页列表 * - * @param module 操作模块 - * @param bizId 操作模块编号 - * @return 操作日志 + * @param pageReqVO 分页条件 + * @return 操作日志分页列表 */ - List getOperateLogByModuleAndBizId(String module, Long bizId); + PageResult getOperateLogPage(OperateLogV2PageReqDTO pageReqVO); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java index 39c84ed33..f66e9a0ae 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java @@ -6,13 +6,14 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogMapper; import cn.iocoder.yudao.module.system.dal.mysql.logger.OperateLogV2Mapper; -import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -20,7 +21,6 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.util.Collection; -import java.util.List; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH; @@ -69,14 +69,15 @@ public class OperateLogServiceImpl implements OperateLogService { // ======================= LOG V2 ======================= @Override - public void createOperateLogV2(OperateLogV2CreateReqBO createReqBO) { + public void createOperateLogV2(OperateLogV2CreateReqDTO createReqBO) { OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class); operateLogV2Mapper.insert(log); } + @Override - public List getOperateLogByModuleAndBizId(String module, Long bizId) { - return operateLogV2Mapper.selectListByModuleAndBizId(module, bizId); + public PageResult getOperateLogPage(OperateLogV2PageReqDTO pageReqVO) { + return operateLogV2Mapper.selectPage(pageReqVO); } } From 3e91ac73c4fd1bcebe2c608675324d6cf2df5c5a Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 19 Dec 2023 10:29:41 +0800 Subject: [PATCH 13/55] =?UTF-8?q?CRM=EF=BC=9A=E5=AE=8C=E5=96=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=88=86=E9=A1=B5=E6=9F=A5=E8=AF=A2=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?=E6=9E=84=E9=80=A0=20CrmQueryWrapperUtils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../permission/CrmPermissionRoleCodeEnum.java | 27 +++++++ .../admin/customer/CrmCustomerController.http | 4 +- .../admin/customer/CrmCustomerController.java | 22 +++--- .../dal/mysql/business/CrmBusinessMapper.java | 5 +- .../crm/dal/mysql/clue/CrmClueMapper.java | 5 +- .../dal/mysql/contact/CrmContactMapper.java | 5 +- .../dal/mysql/contract/CrmContractMapper.java | 5 +- .../dal/mysql/customer/CrmCustomerMapper.java | 5 +- .../mysql/receivable/CrmReceivableMapper.java | 5 +- .../receivable/CrmReceivablePlanMapper.java | 5 +- .../module/crm/util/CrmQueryWrapperUtils.java | 72 +++++++++---------- .../src/main/resources/application-local.yaml | 1 + .../src/main/resources/application.yaml | 12 +++- 13 files changed, 91 insertions(+), 82 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java new file mode 100644 index 000000000..c9a51057b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/permission/CrmPermissionRoleCodeEnum.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.crm.enums.permission; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Crm 数据权限角色枚举 + * + * @author HUIHUI + */ +@Getter +@AllArgsConstructor +public enum CrmPermissionRoleCodeEnum { + + CRM_ADMIN("crm_admin", "CRM 管理员"); + + /** + * 角色标识 + */ + private String code; + /** + * 角色名称 + */ + private String name; + +} + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http index 6a5c6774c..9a6cb93a8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.http @@ -1,8 +1,8 @@ ### 请求 /transfer PUT {{baseUrl}}/crm/customer/transfer -Content-Type: application/json +Content-Type: application/-id: {{adminTenentId}}json Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} +tenant { "id": 10, diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 0882ea72c..1a9b75ad2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -3,8 +3,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.framework.operatelogv2.core.vo.OperateLogV2PageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -12,6 +14,7 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; @@ -135,23 +138,14 @@ public class CrmCustomerController { return success(true); } - // TODO @puhui999:operate-log-list 或者 operate-log-page 如果分页 - @GetMapping("/operate-log") + @GetMapping("/operate-log-page") @Operation(summary = "获得客户操作日志") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('crm:customer:query')") - // TODO @puhui999:最好有读权限;方法名改成 getCustomerOperateLog - public CommonResult> getOperateLog(@RequestParam("id") Long id) { - // 1. 获取客户 - // TODO @puhui999:这个校验可以去掉哈; - CrmCustomerDO customer = customerService.getCustomer(id); - if (customer == null) { - return success(null); - } - - // 2. 获取操作日志 - // TODO @puhui999:操作日志,返回可能要分页哈; - return success(operateLogApi.getOperateLogByModuleAndBizId(CRM_CUSTOMER, id)); + public CommonResult> getCustomerOperateLog(OperateLogV2PageReqVO reqVO) { + reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 + reqVO.setBizType(CRM_CUSTOMER); + return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); } // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java index 6dfdf8fad..eb9d50a64 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java @@ -38,11 +38,8 @@ public interface CrmBusinessMapper extends BaseMapperX { default PageResult selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmBusinessDO.class) .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index cd558dce4..2253e69f6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -30,11 +30,8 @@ public interface CrmClueMapper extends BaseMapperX { default PageResult selectPage(CrmCluePageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmClueDO.class) .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java index adc4ced87..1d387149c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java @@ -43,11 +43,8 @@ public interface CrmContactMapper extends BaseMapperX { default PageResult selectPage(CrmContactPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmContactDO.class) .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java index 60a5ab785..dfb3e6236 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java @@ -41,11 +41,8 @@ public interface CrmContractMapper extends BaseMapperX { default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 mpjLambdaWrapperX.selectAll(CrmContractDO.class) .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index b399ca7df..77304575c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -30,11 +30,8 @@ public interface CrmCustomerMapper extends BaseMapperX { default PageResult selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmCustomerDO.class) .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java index fca4e30e2..a20da86a6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java @@ -39,11 +39,8 @@ public interface CrmReceivableMapper extends BaseMapperX { default PageResult selectPage(CrmReceivablePageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), CrmReceivableDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmReceivableDO.class) .eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java index e22c920b9..ed578f1fd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java @@ -38,11 +38,8 @@ public interface CrmReceivablePlanMapper extends BaseMapperX selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - boolean condition = CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CrmReceivablePlanDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); - if (!condition) { - return PageResult.empty(); - } // 拼接自身的查询条件 query.selectAll(CrmReceivablePlanDO.class) .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java index 161bff845..cbe43e683 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java @@ -7,9 +7,12 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.github.yulichang.autoconfigure.MybatisPlusJoinProperties; import com.github.yulichang.wrapper.MPJLambdaWrapper; import java.util.Collection; @@ -33,46 +36,41 @@ public class CrmQueryWrapperUtils { * @param userId 用户编号 * @param sceneType 场景类型 * @param pool 公海 - * @return 是否 (是:需要执行查询,否:不需要查询调用方法直接返回空) */ - // TODO @puhui999:bizId 直接传递会不会简单点 回复:还是需要 SFunction 因为分页连表时不知道 bizId 是多少;是不是把 bizId 传入就好啦? - public static , S> boolean appendPermissionCondition(T query, Integer bizType, SFunction bizId, - Long userId, Integer sceneType, Boolean pool) { + public static , S> void appendPermissionCondition(T query, Integer bizType, SFunction bizId, + Long userId, Integer sceneType, Boolean pool) { + final String ownerUserIdField = SingletonManager.getMybatisPlusJoinProperties().getTableAlias() + ".owner_user_id"; // 1. 构建数据权限连表条件 - if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 + if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) - .eq(CrmPermissionDO::getBizId, bizId) + .eq(CrmPermissionDO::getBizId, bizId) // 只能使用 SFunction 如果传 id 解析出来的 sql 不对 .eq(CrmPermissionDO::getUserId, userId)); } // 2.1 场景一:我负责的数据 if (CrmSceneTypeEnum.isOwner(sceneType)) { - query.eq("owner_user_id", userId); + query.eq(ownerUserIdField, userId); } // 2.2 场景二:我参与的数据 if (CrmSceneTypeEnum.isInvolved(sceneType)) { - query.ne("owner_user_id", userId) - // TODO @puhui999:IN 是不是更合适哈; - .and(q -> q.eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel()) - .or() - .eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.WRITE.getLevel())); + query.ne(ownerUserIdField, userId) + .in(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel(), CrmPermissionLevelEnum.WRITE.getLevel()); } // 2.3 场景三:下属负责的数据 if (CrmSceneTypeEnum.isSubordinate(sceneType)) { - // TODO @puhui999:要不如果没有下属,拼一个 owner_user_id in null,不返回结果就好啦; - List subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId); + List subordinateUsers = SingletonManager.getAdminUserApi().getUserListBySubordinate(userId); if (CollUtil.isEmpty(subordinateUsers)) { - return false; + query.eq(ownerUserIdField, -1); // 不返回任何结果 + } else { + query.in(ownerUserIdField, convertSet(subordinateUsers, AdminUserRespDTO::getId)); } - query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId)); } // 3. 拼接公海的查询条件 if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海 - query.isNull("owner_user_id"); + query.isNull(ownerUserIdField); } else { // 情况二:不是公海 - query.isNotNull("owner_user_id"); + query.isNotNull(ownerUserIdField); } - return true; } /** @@ -93,38 +91,38 @@ public class CrmQueryWrapperUtils { .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); } - private static AdminUserApi getAdminUserApi() { - return AdminUserApiHolder.ADMIN_USER_API; - } - /** - * 校验用户是否是管理员 + * 校验用户是否是 CRM 管理员 * * @param userId 用户编号 * @return 是/否 */ private static boolean validateAdminUser(Long userId) { - // TODO 查询权限配置表用户的角色信息 - // TODO @puhui999:查询用户的角色;CRM_ADMIN("crm_admin", "CRM 管理员"), - //CrmPermissionConfig permissionConfig = crmPermissionConfigService.getPermissionConfigByUserId(userId); - //if (permissionConfig == null) { - // return false; - //} - //// 校验是否为管理员 - //if (permissionConfig.getIsAdmin()){ - // return true; - //} - return false; + return SingletonManager.getPermissionApi().hasAnyRoles(userId, CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); } /** - * 静态内部类实现 AdminUserApi 单例获取 + * 静态内部类实现单例获取 * * @author HUIHUI */ - private static class AdminUserApiHolder { + private static class SingletonManager { private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); + private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); + private static final MybatisPlusJoinProperties MYBATIS_PLUS_JOIN_PROPERTIES = SpringUtil.getBean(MybatisPlusJoinProperties.class); + + public static AdminUserApi getAdminUserApi() { + return ADMIN_USER_API; + } + + public static PermissionApi getPermissionApi() { + return PERMISSION_API; + } + + public static MybatisPlusJoinProperties getMybatisPlusJoinProperties() { + return MYBATIS_PLUS_JOIN_PROPERTIES; + } } diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 900656ecf..3e2a7ed6a 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -188,6 +188,7 @@ logging: cn.iocoder.yudao.module.trade.dal.mysql: debug cn.iocoder.yudao.module.promotion.dal.mysql: debug cn.iocoder.yudao.module.statistics.dal.mysql: debug + cn.iocoder.yudao.module.crm.dal.mysql: debug debug: false diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 627028bdd..21b2d48c3 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -79,7 +79,17 @@ mybatis-plus: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 mybatis-plus-join: - banner: false # 关闭控制台的 Banner 打印 + #是否打印 mybatis plus join banner 默认true + banner: false + #全局启用副表逻辑删除(默认true) 关闭后关联查询不会加副表逻辑删除 + sub-table-logic: true + #拦截器MappedStatement缓存(默认true) + ms-cache: true + #表别名(默认 t) + table-alias: t + #副表逻辑删除条件的位置,支持where、on + #默认ON (1.4.7.2及之前版本默认为where) + logic-del-type: on # Spring Data Redis 配置 spring: From 55a215da44481a9116bdae824d018dda45afaacd Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 19 Dec 2023 10:43:45 +0800 Subject: [PATCH 14/55] =?UTF-8?q?CRM-=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90?= =?UTF-8?q?=EF=BC=9A=E5=AE=8C=E5=96=84=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90?= =?UTF-8?q?=E8=A1=A5=E5=85=A8=E7=AE=A1=E7=90=86=E5=91=98=E5=92=8C=E5=85=AC?= =?UTF-8?q?=E6=B5=B7=E7=9B=B8=E5=85=B3=E6=83=85=E5=86=B5=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../permission/CrmPermissionController.java | 6 +- .../crm/framework/core/package-info.java | 1 - .../core/annotations/CrmPermission.java | 2 +- .../core/aop/CrmPermissionAspect.java | 71 ++++++++++++++----- .../permission/core/package-info.java | 1 + .../framework/permission/package-info.java | 1 + .../business/CrmBusinessServiceImpl.java | 2 +- .../crm/service/clue/CrmClueServiceImpl.java | 2 +- .../contact/CrmContactServiceImpl.java | 2 +- .../CrmContactBusinessLinkServiceImpl.java | 2 +- .../contract/CrmContractServiceImpl.java | 2 +- .../customer/CrmCustomerServiceImpl.java | 2 +- .../CrmReceivablePlanServiceImpl.java | 2 +- .../receivable/CrmReceivableServiceImpl.java | 2 +- 14 files changed, 67 insertions(+), 31 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/{ => permission}/core/annotations/CrmPermission.java (93%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/{ => permission}/core/aop/CrmPermissionAspect.java (68%) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java index 32d4a1ab7..5dc3807f5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java @@ -8,8 +8,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionR import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.PostApi; @@ -21,12 +21,12 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import java.util.*; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java deleted file mode 100644 index 4a3e65722..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.crm.framework.core; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/annotations/CrmPermission.java similarity index 93% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/annotations/CrmPermission.java index f92371f2b..9ef6d4d02 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/annotations/CrmPermission.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/annotations/CrmPermission.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.core.annotations; +package cn.iocoder.yudao.module.crm.framework.permission.core.annotations; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java similarity index 68% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java index 3e1cf87b2..ddd44edff 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/core/aop/CrmPermissionAspect.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java @@ -1,32 +1,34 @@ -package cn.iocoder.yudao.module.crm.framework.core.aop; +package cn.iocoder.yudao.module.crm.framework.permission.core.aop; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; -import jakarta.annotation.Resource; import java.util.ArrayList; import java.util.List; import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_DENIED; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CRM_PERMISSION_MODEL_NOT_EXISTS; -// TODO 这个包,改成 permission,然后搞 config 和 core 包,这个类在 core 包里;目的是:framework 最好分类下 /** * Crm 数据权限校验 AOP 切面 * @@ -42,10 +44,6 @@ public class CrmPermissionAspect { @Before("@annotation(crmPermission)") public void doBefore(JoinPoint joinPoint, CrmPermission crmPermission) { - // TODO 芋艿:临时,方便大家调试 - //if (true) { - // return; - //} // 获取相关属性值 Map expressionValues = parseExpressions(joinPoint, crmPermission); Integer bizType = StrUtil.isEmpty(crmPermission.bizTypeValue()) ? @@ -53,16 +51,28 @@ public class CrmPermissionAspect { Long bizId = (Long) expressionValues.get(crmPermission.bizId()); // 模块数据编号 Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别 - // TODO 如果是超级管理员则直接通过 - //if (superAdmin){ - // return; - //} - - // 1. 获取数据权限 - List bizPermissions = crmPermissionService.getPermissionListByBiz(bizType, bizId); - if (CollUtil.isEmpty(bizPermissions)) { // 数据权限不存存那么数据也不存在 - throw exception(CRM_PERMISSION_MODEL_NOT_EXISTS, CrmBizTypeEnum.getNameByType(bizType)); + // 1.1 如果是超级管理员则直接通过 + if (validateAdminUser(getUserId())) { + return; } + // 1.2 获取数据权限 + List bizPermissions = crmPermissionService.getPermissionListByBiz(bizType, bizId); + if (CollUtil.isEmpty(bizPermissions)) { // 没有数据权限的情况 + // 公海数据如果没有团队成员大家也因该有读权限才对 + if (CrmPermissionLevelEnum.isRead(permissionLevel)) { + return; + } + + // 没有数据权限的情况下超出了读权限直接报错,避免后面校验空指针 + throw exception(CRM_PERMISSION_DENIED, CrmBizTypeEnum.getNameByType(bizType)); + } else { // 有数据权限但是没有负责人的情况 + if (!anyMatch(bizPermissions, item -> CrmPermissionLevelEnum.isOwner(item.getLevel()))) { + if (CrmPermissionLevelEnum.isRead(permissionLevel)) { + return; + } + } + } + // 2.1 情况一:如果自己是负责人,则默认有所有权限 CrmPermissionDO userPermission = CollUtil.findOne(bizPermissions, permission -> ObjUtil.equal(permission.getUserId(), getUserId())); if (userPermission != null) { @@ -110,4 +120,29 @@ public class CrmPermissionAspect { return SpringExpressionUtils.parseExpressions(joinPoint, expressionStrings); } + /** + * 校验用户是否是 CRM 管理员 + * + * @param userId 用户编号 + * @return 是/否 + */ + private static boolean validateAdminUser(Long userId) { + return SingletonManager.getPermissionApi().hasAnyRoles(userId, CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); + } + + /** + * 静态内部类实现单例获取 + * + * @author HUIHUI + */ + private static class SingletonManager { + + private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); + + public static PermissionApi getPermissionApi() { + return PERMISSION_API; + } + + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java new file mode 100644 index 000000000..d895fe969 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.crm.framework.permission.core; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java new file mode 100644 index 000000000..44f408016 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.crm.framework.permission; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index f2db01b83..5281084b9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 414a52d17..c3af9e414 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import jakarta.annotation.Resource; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 50b1bd4be..5edf22a2e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkServiceImpl.java index 0a9512ffb..94de4d7be 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contactbusinesslink/CrmContactBusinessLinkServiceImpl.java @@ -14,7 +14,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.contactbusinesslink.CrmContact import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessLinkMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 6f2fc16ab..00d6c5e4c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import jakarta.annotation.Resource; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index e53dc1a46..a4ea82323 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -12,7 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index edfb6c70a..e6940e793 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -15,7 +15,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index 38bf5266e..6071c2615 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -18,7 +18,7 @@ import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivableMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; From 1fae341cae3ab3667757c2c766b3606fc78bf9e6 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 19 Dec 2023 16:29:13 +0800 Subject: [PATCH 15/55] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../YudaoOperateLogAutoConfiguration.java | 23 +- .../YudaoOperateLogV2Configuration.java | 11 +- .../core/aop/OperateLogV2Aspect.java | 325 ++++++++++++++++++ .../core/enums/OperateLogV2Constants.java | 34 ++ .../core/service/ILogRecordServiceImpl.java | 54 +-- .../admin/customer/CrmCustomerController.java | 4 +- .../crm/framework/bizlog/package-info.java | 1 - .../function/CrmIndustryParseFunction.java | 3 +- .../function/CrmLevelParseFunction.java | 2 +- .../function/CrmSourceParseFunction.java | 2 +- .../framework/operatelog/package-info.java | 1 + .../logger/dto/OperateLogV2CreateReqDTO.java | 39 ++- .../api/logger/dto/OperateLogV2RespDTO.java | 6 +- .../system/api/logger/OperateLogApiImpl.java | 3 +- .../convert/logger/OperateLogConvert.java | 8 - .../dal/dataobject/logger/OperateLogV2DO.java | 62 +++- .../dal/mysql/logger/OperateLogV2Mapper.java | 11 - .../system/framework/bizlog/package-info.java | 1 - .../function/AdminUserParseFunction.java | 2 +- .../function/AreaParseFunction.java | 2 +- .../framework/operatelog/package-info.java | 1 + .../service/logger/OperateLogServiceImpl.java | 2 + 22 files changed, 491 insertions(+), 106 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java create mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/{bizlog => operatelog}/function/CrmIndustryParseFunction.java (89%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/{bizlog => operatelog}/function/CrmLevelParseFunction.java (94%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/{bizlog => operatelog}/function/CrmSourceParseFunction.java (94%) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/{bizlog => operatelog}/function/AdminUserParseFunction.java (95%) rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/{bizlog => operatelog}/function/AreaParseFunction.java (92%) create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java index 441ec6bbd..0f4f48eeb 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java @@ -1,23 +1,18 @@ package cn.iocoder.yudao.framework.operatelog.config; -import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; -import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; -import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkServiceImpl; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.context.annotation.Bean; @AutoConfiguration public class YudaoOperateLogAutoConfiguration { - @Bean - public OperateLogAspect operateLogAspect() { - return new OperateLogAspect(); - } - - @Bean - public OperateLogFrameworkService operateLogFrameworkService(OperateLogApi operateLogApi) { - return new OperateLogFrameworkServiceImpl(operateLogApi); - } + //@Bean + //public OperateLogAspect operateLogAspect() { + // return new OperateLogAspect(); + //} + // + //@Bean + //public OperateLogFrameworkService operateLogFrameworkService(OperateLogApi operateLogApi) { + // return new OperateLogFrameworkServiceImpl(operateLogApi); + //} } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java index fa907c8f6..a7aa3a379 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.operatelogv2.config; +import cn.iocoder.yudao.framework.operatelogv2.core.aop.OperateLogV2Aspect; import cn.iocoder.yudao.framework.operatelogv2.core.service.ILogRecordServiceImpl; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; import com.mzt.logapi.service.ILogRecordService; import com.mzt.logapi.starter.annotation.EnableLogRecord; import lombok.extern.slf4j.Slf4j; @@ -21,8 +21,13 @@ public class YudaoOperateLogV2Configuration { @Bean @Primary - public ILogRecordService iLogRecordServiceImpl(OperateLogApi operateLogApi) { - return new ILogRecordServiceImpl(operateLogApi); + public ILogRecordService iLogRecordServiceImpl() { + return new ILogRecordServiceImpl(); + } + + @Bean + public OperateLogV2Aspect operateLogV2Aspect() { + return new OperateLogV2Aspect(); } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java new file mode 100644 index 000000000..2f11d96b5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java @@ -0,0 +1,325 @@ +package cn.iocoder.yudao.framework.operatelogv2.core.aop; + +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import com.google.common.collect.Maps; +import com.mzt.logapi.beans.LogRecord; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.multipart.MultipartFile; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Array; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.IntStream; + +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; +import static cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants.*; + +/** + * 拦截使用 @Operation 注解 + * + * @author HUIHUI + */ +@Aspect +@Slf4j +public class OperateLogV2Aspect { + + /** + * 用于记录操作内容的上下文 + * + * @see OperateLogV2CreateReqDTO#getContent() + */ + private static final ThreadLocal CONTENT = new ThreadLocal<>(); + /** + * 用于记录拓展字段的上下文 + * + * @see OperateLogV2CreateReqDTO#getExtra() + */ + private static final ThreadLocal> EXTRA = new ThreadLocal<>(); + + @Resource + private OperateLogApi operateLogApi; + + @Around("@annotation(operation)") + public Object around(ProceedingJoinPoint joinPoint, Operation operation) throws Throwable { + RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint)); + if (requestMethod == RequestMethod.GET) { // 跳过 get 方法 + return joinPoint.proceed(); + } + + // 目前,只有管理员,才记录操作日志!所以非管理员,直接调用,不进行记录 + Integer userType = WebFrameworkUtils.getLoginUserType(); + if (ObjUtil.notEqual(userType, UserTypeEnum.ADMIN.getValue())) { + return joinPoint.proceed(); + } + + // 记录开始时间 + LocalDateTime startTime = LocalDateTime.now(); + try { + // 执行原有方法 + Object result = joinPoint.proceed(); + // 记录正常执行时的操作日志 + this.log(joinPoint, operation, startTime, result, null); + return result; + } catch (Throwable exception) { + this.log(joinPoint, operation, startTime, null, exception); + throw exception; + } finally { + clearThreadLocal(); + } + } + + public static void setContent(LogRecord content) { + CONTENT.set(content); + } + + public static void addExtra(String key, Object value) { + if (EXTRA.get() == null) { + EXTRA.set(new HashMap<>()); + } + EXTRA.get().put(key, value); + } + + public static void addExtra(Map extra) { + if (EXTRA.get() == null) { + EXTRA.set(new HashMap<>()); + } + EXTRA.get().putAll(extra); + } + + private static void clearThreadLocal() { + CONTENT.remove(); + EXTRA.remove(); + } + + private void log(ProceedingJoinPoint joinPoint, Operation operation, + LocalDateTime startTime, Object result, Throwable exception) { + try { + // 判断不记录的情况(默认没有值就是记录) + if (EXTRA.get() != null && EXTRA.get().get(ENABLE) != null) { + return; + } + // 真正记录操作日志 + this.log0(joinPoint, operation, startTime, result, exception); + } catch (Throwable ex) { + log.error("[log][记录操作日志时,发生异常,其中参数是 joinPoint({}) apiOperation({}) result({}) exception({}) ]", + joinPoint, operation, result, exception, ex); + } + } + + private void log0(ProceedingJoinPoint joinPoint, Operation operation, + LocalDateTime startTime, Object result, Throwable exception) { + OperateLogV2CreateReqDTO reqDTO = new OperateLogV2CreateReqDTO(); + // 补全通用字段 + reqDTO.setTraceId(TracerUtils.getTraceId()); + reqDTO.setStartTime(startTime); + // 补充用户信息 + fillUserFields(reqDTO); + // 补全模块信息 + fillModuleFields(reqDTO, joinPoint, operation); + // 补全请求信息 + fillRequestFields(reqDTO); + // 补全方法信息 + fillMethodFields(reqDTO, joinPoint, startTime, result, exception); + + // 异步记录日志 + operateLogApi.createOperateLogV2(reqDTO); + } + + private static void fillUserFields(OperateLogV2CreateReqDTO reqDTO) { + reqDTO.setUserId(WebFrameworkUtils.getLoginUserId()); + reqDTO.setUserType(WebFrameworkUtils.getLoginUserType()); + } + + private static void fillModuleFields(OperateLogV2CreateReqDTO reqDTO, ProceedingJoinPoint joinPoint, Operation operation) { + LogRecord logRecord = CONTENT.get(); + reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 + reqDTO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 + if (EXTRA.get() != null) { + reqDTO.setExtra((Map) EXTRA.get().get(EXTRA_KEY)); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} + } + + // type 属性 + if (logRecord.getType() != null) { + reqDTO.setType(logRecord.getType()); // 大模块类型如 crm 客户 + } + if (StrUtil.isEmpty(reqDTO.getType())) { + Tag tag = getClassAnnotation(joinPoint, Tag.class); + if (tag != null) { + // 优先读取 @Tag 的 name 属性 + if (StrUtil.isNotEmpty(tag.name())) { + reqDTO.setType(tag.name()); + } + // 没有的话,读取 @API 的 description 属性 + if (StrUtil.isEmpty(reqDTO.getType()) && ArrayUtil.isNotEmpty(tag.description())) { + reqDTO.setType(tag.description()); + } + } + } + // subType 属性 + if (logRecord.getSubType() != null) { + reqDTO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 + } + if (StrUtil.isEmpty(reqDTO.getSubType()) && operation != null) { + reqDTO.setSubType(operation.summary()); + } + + } + + private static void fillRequestFields(OperateLogV2CreateReqDTO reqDTO) { + // 获得 Request 对象 + HttpServletRequest request = ServletUtils.getRequest(); + if (request == null) { + return; + } + // 补全请求信息 + reqDTO.setRequestMethod(request.getMethod()); + reqDTO.setRequestUrl(request.getRequestURI()); + reqDTO.setUserIp(ServletUtils.getClientIP(request)); + reqDTO.setUserAgent(ServletUtils.getUserAgent(request)); + } + + private static void fillMethodFields(OperateLogV2CreateReqDTO reqDTO, ProceedingJoinPoint joinPoint, LocalDateTime startTime, + Object result, Throwable exception) { + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + reqDTO.setJavaMethod(methodSignature.toString()); + if (EXTRA.get().get(IS_LOG_ARGS) == null) { + reqDTO.setJavaMethodArgs(obtainMethodArgs(joinPoint)); + } + if (EXTRA.get().get(IS_LOG_RESULT_DATA) == null) { + reqDTO.setResultData(obtainResultData(result)); + } + reqDTO.setDuration((int) (LocalDateTimeUtil.between(startTime, LocalDateTime.now()).toMillis())); + // (正常)处理 resultCode 和 resultMsg 字段 + if (result instanceof CommonResult) { + CommonResult commonResult = (CommonResult) result; + reqDTO.setResultCode(commonResult.getCode()); + reqDTO.setResultMsg(commonResult.getMsg()); + } else { + reqDTO.setResultCode(SUCCESS.getCode()); + } + // (异常)处理 resultCode 和 resultMsg 字段 + if (exception != null) { + reqDTO.setResultCode(INTERNAL_SERVER_ERROR.getCode()); + reqDTO.setResultMsg(ExceptionUtil.getRootCauseMessage(exception)); + } + } + + @SuppressWarnings("SameParameterValue") + private static T getClassAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass) { + return ((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaringClass().getAnnotation(annotationClass); + } + + private static String obtainMethodArgs(ProceedingJoinPoint joinPoint) { + // TODO 提升:参数脱敏和忽略 + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + String[] argNames = methodSignature.getParameterNames(); + Object[] argValues = joinPoint.getArgs(); + // 拼接参数 + Map args = Maps.newHashMapWithExpectedSize(argValues.length); + for (int i = 0; i < argNames.length; i++) { + String argName = argNames[i]; + Object argValue = argValues[i]; + // 被忽略时,标记为 ignore 字符串,避免和 null 混在一起 + args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]"); + } + return JsonUtils.toJsonString(args); + } + + private static String obtainResultData(Object result) { + // TODO 提升:结果脱敏和忽略 + if (result instanceof CommonResult) { + result = ((CommonResult) result).getData(); + } + return JsonUtils.toJsonString(result); + } + + private static boolean isIgnoreArgs(Object object) { + Class clazz = object.getClass(); + // 处理数组的情况 + if (clazz.isArray()) { + return IntStream.range(0, Array.getLength(object)) + .anyMatch(index -> isIgnoreArgs(Array.get(object, index))); + } + // 递归,处理数组、Collection、Map 的情况 + if (Collection.class.isAssignableFrom(clazz)) { + return ((Collection) object).stream() + .anyMatch((Predicate) OperateLogV2Aspect::isIgnoreArgs); + } + if (Map.class.isAssignableFrom(clazz)) { + return isIgnoreArgs(((Map) object).values()); + } + // obj + return object instanceof MultipartFile + || object instanceof HttpServletRequest + || object instanceof HttpServletResponse + || object instanceof BindingResult; + } + + private static RequestMethod obtainFirstMatchRequestMethod(RequestMethod[] requestMethods) { + if (ArrayUtil.isEmpty(requestMethods)) { + return null; + } + // 优先,匹配最优的 POST、PUT、DELETE + RequestMethod result = obtainFirstLogRequestMethod(requestMethods); + if (result != null) { + return result; + } + // 然后,匹配次优的 GET + result = Arrays.stream(requestMethods).filter(requestMethod -> requestMethod == RequestMethod.GET) + .findFirst().orElse(null); + if (result != null) { + return result; + } + // 兜底,获得第一个 + return requestMethods[0]; + } + + private static RequestMethod[] obtainRequestMethod(ProceedingJoinPoint joinPoint) { + RequestMapping requestMapping = AnnotationUtils.getAnnotation( // 使用 Spring 的工具类,可以处理 @RequestMapping 别名注解 + ((MethodSignature) joinPoint.getSignature()).getMethod(), RequestMapping.class); + return requestMapping != null ? requestMapping.method() : new RequestMethod[]{}; + } + + private static RequestMethod obtainFirstLogRequestMethod(RequestMethod[] requestMethods) { + if (ArrayUtil.isEmpty(requestMethods)) { + return null; + } + return Arrays.stream(requestMethods).filter(requestMethod -> + requestMethod == RequestMethod.POST + || requestMethod == RequestMethod.PUT + || requestMethod == RequestMethod.DELETE) + .findFirst().orElse(null); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java new file mode 100644 index 000000000..b0cfe43b3 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.framework.operatelogv2.core.enums; + +/** + * 操作日志常量接口 + * + * @author HUIHUI + */ +public interface OperateLogV2Constants { + + // ========== 开关字段-如果没有值默认就是记录 ========== + + /** + * 是否记录日志 + */ + String ENABLE = "enable"; + + /** + * 是否记录方法参数 + */ + String IS_LOG_ARGS = "isLogArgs"; + + /** + * 是否记录方法结果的数据 + */ + String IS_LOG_RESULT_DATA = "isLogResultData"; + + // ========== 扩展 ========== + + /** + * 扩展信息 + */ + String EXTRA_KEY = "extra"; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java index 903f5de72..b54e0b4f1 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java @@ -1,14 +1,9 @@ package cn.iocoder.yudao.framework.operatelogv2.core.service; -import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; -import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import cn.iocoder.yudao.framework.operatelogv2.core.aop.OperateLogV2Aspect; import com.mzt.logapi.beans.LogRecord; +import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.ILogRecordService; -import jakarta.servlet.http.HttpServletRequest; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import java.util.Collections; @@ -17,56 +12,17 @@ import java.util.List; /** * 操作日志 ILogRecordService 实现类 * - * 基于 {@link OperateLogApi} 实现,记录操作日志 + * 基于 {@link OperateLogV2Aspect} 实现,记录操作日志 * * @author HUIHUI */ @Slf4j -@RequiredArgsConstructor public class ILogRecordServiceImpl implements ILogRecordService { - private final OperateLogApi operateLogApi; - @Override public void record(LogRecord logRecord) { - OperateLogV2CreateReqDTO reqBO = new OperateLogV2CreateReqDTO(); - // 补全通用字段 - reqBO.setTraceId(TracerUtils.getTraceId()); - // 补充用户信息 - fillUserFields(reqBO); - // 补全模块信息 - fillModuleFields(reqBO, logRecord); - // 补全请求信息 - fillRequestFields(reqBO); - // 异步记录日志 - operateLogApi.createOperateLogV2(reqBO); - log.info("操作日志 ===> {}", reqBO); - } - - private static void fillUserFields(OperateLogV2CreateReqDTO reqBO) { - reqBO.setUserId(WebFrameworkUtils.getLoginUserId()); - reqBO.setUserType(WebFrameworkUtils.getLoginUserType()); - } - - public static void fillModuleFields(OperateLogV2CreateReqDTO reqBO, LogRecord logRecord) { - reqBO.setType(logRecord.getType()); // 大模块类型如 crm-客户 - reqBO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 - reqBO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 - reqBO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 - reqBO.setExtra(logRecord.getExtra()); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} - } - - private static void fillRequestFields(OperateLogV2CreateReqDTO reqBO) { - // 获得 Request 对象 - HttpServletRequest request = ServletUtils.getRequest(); - if (request == null) { - return; - } - // 补全请求信息 - reqBO.setRequestMethod(request.getMethod()); - reqBO.setRequestUrl(request.getRequestURI()); - reqBO.setUserIp(ServletUtils.getClientIP(request)); - reqBO.setUserAgent(ServletUtils.getUserAgent(request)); + OperateLogV2Aspect.setContent(logRecord); // 操作日志 + OperateLogV2Aspect.addExtra(LogRecordContext.getVariables()); // 扩展信息 } @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 1a9b75ad2..2580f9584 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -67,7 +67,7 @@ public class CrmCustomerController { } @PutMapping("/update") - //@Operation(summary = "更新客户") + @Operation(summary = "更新客户") @PreAuthorize("@ss.hasPermission('crm:customer:update')") public CommonResult updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { customerService.updateCustomer(updateReqVO); @@ -131,7 +131,7 @@ public class CrmCustomerController { } @PutMapping("/transfer") - //@Operation(summary = "客户转移") + @Operation(summary = "客户转移") @PreAuthorize("@ss.hasPermission('crm:customer:update')") public CommonResult transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { customerService.transferCustomer(reqVO, getLoginUserId()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java deleted file mode 100644 index b756f540d..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.crm.framework.bizlog; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java similarity index 89% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java index f963b533a..c2972a4b1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.bizlog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.function; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; @@ -8,7 +8,6 @@ import org.springframework.stereotype.Component; import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; -// TODO @puhui999:包名使用 operatelog 更合适哈; /** * 自定义函数-通过行业编号获取行业信息 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java similarity index 94% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java index 15af42d5e..25865d9b1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.bizlog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.function; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java similarity index 94% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java index 0a630dfe6..9c1a62f5d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.bizlog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.function; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java new file mode 100644 index 000000000..975a2eb51 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.crm.framework.operatelog; \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java index 8904bf072..bab21a0dc 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java @@ -5,6 +5,9 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; +import java.time.LocalDateTime; +import java.util.Map; + /** * 系统操作日志 Create Req BO * @@ -58,7 +61,7 @@ public class OperateLogV2CreateReqDTO { * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) * 例如说,记录订单编号,{ orderId: "1"} */ - private String extra; + private Map extra; /** * 请求方法名 @@ -81,4 +84,38 @@ public class OperateLogV2CreateReqDTO { @NotEmpty(message = "浏览器 UA 不能为空") private String userAgent; + /** + * Java 方法名 + */ + private String javaMethod; + /** + * Java 方法的参数 + */ + private String javaMethodArgs; + + /** + * 开始时间 + */ + private LocalDateTime startTime; + + /** + * 执行时长,单位:毫秒 + */ + private Integer duration; + + /** + * 结果码 + */ + private Integer resultCode; + + /** + * 结果提示 + */ + private String resultMsg; + + /** + * 结果数据 + */ + private String resultData; + } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java index 2a3ca002c..cdeab0456 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.system.api.logger.dto; import lombok.Data; +import java.time.LocalDateTime; + /** * 系统操作日志 Resp DTO * @@ -65,8 +67,8 @@ public class OperateLogV2RespDTO { private String userAgent; /** - * 创建时间, 直接返回字符串 + * 创建时间 */ - private String createTime; + private LocalDateTime createTime; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java index 4e0ff0397..ffe10b9c8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; -import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.logger.OperateLogService; @@ -63,7 +62,7 @@ public class OperateLogApiImpl implements OperateLogApi { private static List setUserInfo(List logList, List userList) { Map userMap = convertMap(userList, AdminUserDO::getId); return convertList(logList, item -> { - OperateLogV2RespDTO respDTO = OperateLogConvert.INSTANCE.convert(item); + OperateLogV2RespDTO respDTO = BeanUtils.toBean(item, OperateLogV2RespDTO.class); findAndThen(userMap, item.getUserId(), user -> { respDTO.setUserName(user.getNickname()); }); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java index eebbedc7d..7b3aff8c0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java @@ -3,20 +3,15 @@ package cn.iocoder.yudao.module.system.convert.logger; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; -import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import org.mapstruct.Mapper; -import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; import java.util.Map; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - @Mapper public interface OperateLogConvert { @@ -30,7 +25,4 @@ public interface OperateLogConvert { }); } - @Mapping(target = "createTime", source = "logV2DO.createTime", dateFormat = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - OperateLogV2RespDTO convert(OperateLogV2DO logV2DO); - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java index 56845b131..656331c52 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java @@ -1,13 +1,19 @@ package cn.iocoder.yudao.module.system.dal.dataobject.logger; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.Data; import lombok.EqualsAndHashCode; +import java.time.LocalDateTime; +import java.util.Map; + /** * 操作日志表 V2 * @@ -19,6 +25,16 @@ import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) public class OperateLogV2DO extends BaseDO { + /** + * {@link #javaMethodArgs} 的最大长度 + */ + public static final Integer JAVA_METHOD_ARGS_MAX_LENGTH = 8000; + + /** + * {@link #resultData} 的最大长度 + */ + public static final Integer RESULT_MAX_LENGTH = 4000; + /** * 日志主键 */ @@ -65,8 +81,8 @@ public class OperateLogV2DO extends BaseDO { * * 例如说,记录订单编号,{ orderId: "1"} */ - // TODO @puhui999:看看能不能类似 exts 搞 json 格式; - private String extra; + @TableField(typeHandler = JacksonTypeHandler.class) + private Map extra; /** * 请求方法名 */ @@ -84,9 +100,43 @@ public class OperateLogV2DO extends BaseDO { */ private String userAgent; - // TODO @芋艿:requestUrl、requestMethod - // TODO @芋艿:javaMethod、javaMethodArgs - // TODO @芋艿:startTime、duration - // TODO @芋艿:resultMsg、resultData + /** + * Java 方法名 + */ + private String javaMethod; + /** + * Java 方法的参数 + * + * 实际格式为 Map + * 不使用 @TableField(typeHandler = FastjsonTypeHandler.class) 注解的原因是,数据库存储有长度限制,会进行裁剪,会导致 JSON 反序列化失败 + * 其中,key 为参数名,value 为参数值 + */ + private String javaMethodArgs; + /** + * 开始时间 + */ + private LocalDateTime startTime; + /** + * 执行时长,单位:毫秒 + */ + private Integer duration; + /** + * 结果码 + * + * 目前使用的 {@link CommonResult#getCode()} 属性 + */ + private Integer resultCode; + /** + * 结果提示 + * + * 目前使用的 {@link CommonResult#getMsg()} 属性 + */ + private String resultMsg; + /** + * 结果数据 + * + * 如果是对象,则使用 JSON 格式化 + */ + private String resultData; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java index 0b2458106..acf14478f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java @@ -4,23 +4,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; -import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import org.apache.ibatis.annotations.Mapper; -import java.util.Collection; - @Mapper public interface OperateLogV2Mapper extends BaseMapperX { - default PageResult selectPage(OperateLogPageReqVO reqVO, Collection userIds) { - LambdaQueryWrapperX query = new LambdaQueryWrapperX() - .likeIfPresent(OperateLogV2DO::getType, reqVO.getModule()) - .inIfPresent(OperateLogV2DO::getUserId, userIds); - query.orderByDesc(OperateLogV2DO::getId); // 降序 - return selectPage(reqVO, query); - } - default PageResult selectPage(OperateLogV2PageReqDTO pageReqVO) { return selectPage(pageReqVO, new LambdaQueryWrapperX() .eqIfPresent(OperateLogV2DO::getType, pageReqVO.getBizType()) diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java deleted file mode 100644 index c96f3a0c1..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.system.framework.bizlog; \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java similarity index 95% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java index a88073d4e..2e7d6498a 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.framework.bizlog.function; +package cn.iocoder.yudao.module.system.framework.operatelog.function; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java similarity index 92% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java index f486a49fa..e6815a742 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.framework.bizlog.function; +package cn.iocoder.yudao.module.system.framework.operatelog.function; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java new file mode 100644 index 000000000..978444e17 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.system.framework.operatelog; \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java index f66e9a0ae..76532af87 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java @@ -71,6 +71,8 @@ public class OperateLogServiceImpl implements OperateLogService { @Override public void createOperateLogV2(OperateLogV2CreateReqDTO createReqBO) { OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class); + log.setJavaMethodArgs(StrUtils.maxLength(log.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH)); + log.setResultData(StrUtils.maxLength(log.getResultData(), RESULT_MAX_LENGTH)); operateLogV2Mapper.insert(log); } From f56d8a2751e61c2436f774083962f53c05b0363b Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 19 Dec 2023 18:34:51 +0800 Subject: [PATCH 16/55] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/aop/OperateLogV2Aspect.java | 42 +++++++++--------- .../CrmIndustryParseFunction.java | 2 +- .../CrmLevelParseFunction.java | 2 +- .../CrmSourceParseFunction.java | 2 +- .../customer/CrmCustomerServiceImpl.java | 30 ++++++------- .../permission/CrmPermissionServiceImpl.java | 1 - .../api/logger/dto/OperateLogV2RespDTO.java | 43 +++++++++++++++++-- .../AdminUserParseFunction.java | 2 +- .../AreaParseFunction.java | 2 +- 9 files changed, 78 insertions(+), 48 deletions(-) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/{function => parse}/CrmIndustryParseFunction.java (94%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/{function => parse}/CrmLevelParseFunction.java (94%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/{function => parse}/CrmSourceParseFunction.java (94%) rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/{function => parse}/AdminUserParseFunction.java (95%) rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/{function => parse}/AreaParseFunction.java (92%) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java index 2f11d96b5..99d33dc71 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java @@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; import com.google.common.collect.Maps; import com.mzt.logapi.beans.LogRecord; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -46,7 +45,8 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC import static cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants.*; /** - * 拦截使用 @Operation 注解 + * 拦截使用 @Operation 注解, 获取操作类型、开始时间、持续时间、方法相关信息、执行结果等信息 + * 对 mzt-biz-log 日志信息进行增强 * * @author HUIHUI */ @@ -165,27 +165,9 @@ public class OperateLogV2Aspect { LogRecord logRecord = CONTENT.get(); reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 reqDTO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 - if (EXTRA.get() != null) { - reqDTO.setExtra((Map) EXTRA.get().get(EXTRA_KEY)); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} - } // type 属性 - if (logRecord.getType() != null) { - reqDTO.setType(logRecord.getType()); // 大模块类型如 crm 客户 - } - if (StrUtil.isEmpty(reqDTO.getType())) { - Tag tag = getClassAnnotation(joinPoint, Tag.class); - if (tag != null) { - // 优先读取 @Tag 的 name 属性 - if (StrUtil.isNotEmpty(tag.name())) { - reqDTO.setType(tag.name()); - } - // 没有的话,读取 @API 的 description 属性 - if (StrUtil.isEmpty(reqDTO.getType()) && ArrayUtil.isNotEmpty(tag.description())) { - reqDTO.setType(tag.description()); - } - } - } + reqDTO.setType(logRecord.getType()); // 大模块类型如 crm 客户 // subType 属性 if (logRecord.getSubType() != null) { reqDTO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 @@ -194,6 +176,24 @@ public class OperateLogV2Aspect { reqDTO.setSubType(operation.summary()); } + // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} + Map objectMap = EXTRA.get(); + if (objectMap != null) { + Object object = objectMap.get(EXTRA_KEY); + if (object instanceof Map extraMap) { + if (extraMap.keySet().stream().allMatch(String.class::isInstance)) { + @SuppressWarnings("unchecked") + Map extra = (Map) extraMap; + reqDTO.setExtra(extra); + return; + } + } + // 激进一点不是 map 直接当 value 处理 + Map extra = Maps.newHashMapWithExpectedSize(1); + extra.put(EXTRA_KEY, object); + reqDTO.setExtra(extra); + } + } private static void fillRequestFields(OperateLogV2CreateReqDTO reqDTO) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java similarity index 94% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java index c2972a4b1..45c98918b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmIndustryParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.operatelog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.parse; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmLevelParseFunction.java similarity index 94% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmLevelParseFunction.java index 25865d9b1..bb0e23205 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmLevelParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmLevelParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.operatelog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.parse; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmSourceParseFunction.java similarity index 94% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmSourceParseFunction.java index 9c1a62f5d..eeb5a5674 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/function/CrmSourceParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmSourceParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.framework.operatelog.function; +package cn.iocoder.yudao.module.crm.framework.operatelog.parse; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index a4ea82323..d20512917 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.service.customer; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; @@ -65,17 +66,21 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(success = "更新了客户{_DIFF{#updateReqVO}}", type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}") + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#updateReqVO.id}}", success = "更新了客户{_DIFF{#updateReqVO}}") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { // 校验存在 CrmCustomerDO oldCustomerDO = validateCustomerExists(updateReqVO.getId()); - // __DIFF 函数传递了一个参数,传递的参数是修改之后的对象,这种方式需要在方法内部向 LogRecordContext 中 put 一个变量,代表是之前的对象,这个对象可以是null - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomerDO, CrmCustomerUpdateReqVO.class)); // 更新 CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); customerMapper.updateById(updateObj); + + // __DIFF 函数传递了一个参数,传递的参数是修改之后的对象,这种方式需要在方法内部向 LogRecordContext 中 put 一个变量,代表是之前的对象,这个对象可以是null + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomerDO, CrmCustomerUpdateReqVO.class)); + HashMap extra = new HashMap<>(); + extra.put("tips", "随便记录一点啦"); + LogRecordContext.putVariable(OperateLogV2Constants.EXTRA_KEY, extra); } @Override @@ -125,27 +130,17 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { */ @Override public void validateCustomer(Long customerId) { - // 校验客户是否存在 - if (customerId == null) { - throw exception(CUSTOMER_NOT_EXISTS); - } - CrmCustomerDO customer = customerMapper.selectById(customerId); - if (Objects.isNull(customer)) { - throw exception(CUSTOMER_NOT_EXISTS); - } + validateCustomerExists(customerId); } @Override @Transactional(rollbackFor = Exception.class) - // TODO @puhui999:@LogRecord(type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) - @LogRecord(success = TRANSFER_CUSTOMER_LOG_SUCCESS, type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}") + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { // 1. 校验客户是否存在 - validateCustomer(reqVO.getId()); - // 添加 crmCustomer 到日志上下文 TODO 日志记录放在 service 里是因为已经过了权限校验查询时不用走两次校验 - // TODO @puhui999:customer 不用查询,从 1. 拿到哈;然后 put这个动作,可以放到 3.;这样逻辑结构就是,校验、逻辑、日志,更加清晰 - LogRecordContext.putVariable("crmCustomer", customerMapper.selectById(reqVO.getId())); + CrmCustomerDO customerDO = validateCustomerExists(reqVO.getId()); + // 2.1 数据权限转移 crmPermissionService.transferPermission( CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); @@ -153,6 +148,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); // 3. TODO 记录转移日志 + LogRecordContext.putVariable("crmCustomer", customerDO); } @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index 14fb966c5..a686ffc6a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -138,7 +138,6 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { } @Override - @Transactional(rollbackFor = Exception.class) // TODO @puhui999:这里不用加的,就一个操作哈; public void deletePermission(Integer bizType, Long bizId) { int deletedCount = crmPermissionMapper.deletePermission(bizType, bizId); if (deletedCount == 0) { diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java index cdeab0456..17dfeb491 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.api.logger.dto; import lombok.Data; import java.time.LocalDateTime; +import java.util.Map; /** * 系统操作日志 Resp DTO @@ -29,13 +30,13 @@ public class OperateLogV2RespDTO { */ private Integer userType; /** - * 操作模块 + * 操作模块类型 */ - private String module; + private String type; /** * 操作名 */ - private String name; + private String subType; /** * 操作模块业务编号 */ @@ -47,7 +48,7 @@ public class OperateLogV2RespDTO { /** * 拓展字段 */ - private String extra; + private Map extra; /** * 请求方法名 @@ -66,6 +67,40 @@ public class OperateLogV2RespDTO { */ private String userAgent; + /** + * Java 方法名 + */ + private String javaMethod; + /** + * Java 方法的参数 + */ + private String javaMethodArgs; + + /** + * 开始时间 + */ + private LocalDateTime startTime; + + /** + * 执行时长,单位:毫秒 + */ + private Integer duration; + + /** + * 结果码 + */ + private Integer resultCode; + + /** + * 结果提示 + */ + private String resultMsg; + + /** + * 结果数据 + */ + private String resultData; + /** * 创建时间 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java similarity index 95% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java index 2e7d6498a..5685dda75 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AdminUserParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.framework.operatelog.function; +package cn.iocoder.yudao.module.system.framework.operatelog.parse; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java similarity index 92% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java index e6815a742..b63083a38 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/function/AreaParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.framework.operatelog.function; +package cn.iocoder.yudao.module.system.framework.operatelog.parse; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; From 106c1ecf4c08c9f8b2e52d3e2f60408586a55be2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 19 Dec 2023 23:11:09 +0800 Subject: [PATCH 17/55] =?UTF-8?q?=F0=9F=93=96=20code=20review=EF=BC=9A?= =?UTF-8?q?=E5=BA=97=E9=93=BA=E8=A3=85=E4=BF=AE=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/controller/admin/diy/DiyTemplateController.java | 2 ++ .../controller/app/decorate/AppDecorateController.java | 1 + .../promotion/controller/app/diy/AppDiyTemplateController.java | 2 ++ .../yudao/module/promotion/dal/dataobject/diy/DiyPageDO.java | 1 + .../module/promotion/dal/dataobject/diy/DiyTemplateDO.java | 3 ++- .../module/pay/dal/mysql/wallet/PayWalletRechargeMapper.java | 3 ++- 6 files changed, 10 insertions(+), 2 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/diy/DiyTemplateController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/diy/DiyTemplateController.java index f8aa3b180..7a3c85b9e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/diy/DiyTemplateController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/diy/DiyTemplateController.java @@ -82,6 +82,7 @@ public class DiyTemplateController { return success(DiyTemplateConvert.INSTANCE.convertPage(pageResult)); } + // TODO @疯狂:这个要不和 getDiyTemplate 合并,然后 DiyTemplateRespVO 里面直接把 DiyPagePropertyRespVO 也加上。减少 VO 好了,管理后台 get 多返回点数据,也问题不大的。目的,还是想尽可能降低大家的理解成本哈; @GetMapping("/get-property") @Operation(summary = "获得装修模板属性") @Parameter(name = "id", description = "编号", required = true, example = "1024") @@ -92,6 +93,7 @@ public class DiyTemplateController { return success(DiyTemplateConvert.INSTANCE.convertPropertyVo(diyTemplate, pages)); } + // TODO @疯狂:这个接口,要不和 useDiyTemplate 合并成一个,然后 VO 改成我们新的 VO 规范。不改的字段,就不传递。 @PutMapping("/update-property") @Operation(summary = "更新装修模板属性") @PreAuthorize("@ss.hasPermission('promotion:diy-template:update')") diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/decorate/AppDecorateController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/decorate/AppDecorateController.java index 36ae25b55..6f5b1ec68 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/decorate/AppDecorateController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/decorate/AppDecorateController.java @@ -25,6 +25,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @RestController @RequestMapping("/promotion/decorate") @Validated +@Deprecated // 废弃 public class AppDecorateController { @Resource diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/diy/AppDiyTemplateController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/diy/AppDiyTemplateController.java index fa1ea2d5b..90ecbcac4 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/diy/AppDiyTemplateController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/diy/AppDiyTemplateController.java @@ -33,6 +33,7 @@ public class AppDiyTemplateController { @Resource private DiyPageService diyPageService; + // TODO @疯狂:要不要把 used 和 get 接口合并哈;不传递 id,直接拿默认; @GetMapping("/used") @Operation(summary = "使用中的装修模板") public CommonResult getUsedDiyTemplate() { @@ -54,6 +55,7 @@ public class AppDiyTemplateController { } // 查询模板下的页面 List pages = diyPageService.getDiyPageByTemplateId(diyTemplate.getId()); + // TODO @疯狂:首页、我的,要不枚举到 DiyPageDO 例如说 NAME_USER,NAME_HOME 类似这种哈; String home = findFirst(pages, page -> "首页".equals(page.getName()), DiyPageDO::getProperty); String user = findFirst(pages, page -> "我的".equals(page.getName()), DiyPageDO::getProperty); // 拼接返回 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/diy/DiyPageDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/diy/DiyPageDO.java index 7e1044104..4a9324dfc 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/diy/DiyPageDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/diy/DiyPageDO.java @@ -44,6 +44,7 @@ public class DiyPageDO extends BaseDO { * 备注 */ private String remark; + // TODO @疯狂:这个字段要不改成 previewPicUrls,和别的模块一样用 pic 作为图片哇? /** * 预览图,多个逗号分隔 */ diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/diy/DiyTemplateDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/diy/DiyTemplateDO.java index 684a6f9cb..daf1f786d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/diy/DiyTemplateDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/diy/DiyTemplateDO.java @@ -50,13 +50,14 @@ public class DiyTemplateDO extends BaseDO { * 备注 */ private String remark; + // TODO @疯狂:这个字段要不改成 previewPicUrls,和别的模块一样用 pic 作为图片哇? /** * 预览图 */ @TableField(typeHandler = StringListTypeHandler.class) private List previewImageUrls; /** - * 底部导航属性,JSON 格式 + * uni-app 底部导航属性,JSON 格式 */ private String property; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletRechargeMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletRechargeMapper.java index e10d23d74..f82b88582 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletRechargeMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/wallet/PayWalletRechargeMapper.java @@ -24,7 +24,8 @@ public interface PayWalletRechargeMapper extends BaseMapperX selectPage(PageParam pageReqVO, Long walletId, Boolean payStatus) { return selectPage(pageReqVO, new LambdaQueryWrapperX() .eq(PayWalletRechargeDO::getWalletId, walletId) - .eq(PayWalletRechargeDO::getPayStatus, payStatus)); + .eq(PayWalletRechargeDO::getPayStatus, payStatus) + .orderByDesc(PayWalletRechargeDO::getId)); } } \ No newline at end of file From d65c28d7f7e7db4a8c14538ba3cd30d3111bf6d3 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 23 Dec 2023 09:59:58 +0800 Subject: [PATCH 18/55] =?UTF-8?q?=E2=9C=A8=20Member=EF=BC=9A=E7=A4=BE?= =?UTF-8?q?=E4=BA=A4=E7=99=BB=E5=BD=95=E9=80=BB=E8=BE=91=E8=B0=83=E6=95=B4?= =?UTF-8?q?=EF=BC=8C=E5=A6=82=E6=9E=9C=E7=99=BB=E5=BD=95=E6=97=B6=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E6=88=B7=EF=BC=8C=E5=88=99=E8=87=AA=E5=8A=A8=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E7=94=A8=E6=88=B7=EF=BC=8C=E4=BF=9D=E6=8C=81=E5=92=8C?= =?UTF-8?q?=E5=90=84=20App=20=E7=BB=9F=E4=B8=80=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/enums/TerminalEnum.java | 1 + .../common/util/servlet/ServletUtils.java | 2 -- .../web/core/util/WebFrameworkUtils.java | 19 +++++++++++++++++++ .../app/order/AppTradeOrderController.java | 5 ++--- .../convert/order/TradeOrderConvert.java | 3 +-- .../order/TradeOrderUpdateService.java | 4 +--- .../order/TradeOrderUpdateServiceImpl.java | 14 ++++++++------ .../app/auth/AppAuthController.java | 5 ++--- .../service/auth/MemberAuthService.java | 4 +--- .../service/auth/MemberAuthServiceImpl.java | 10 +++++++--- .../service/user/MemberUserService.java | 12 ++++++++++++ .../service/user/MemberUserServiceImpl.java | 15 +++++++++++---- .../api/logger/dto/LoginLogCreateReqDTO.java | 4 ++-- .../api/social/dto/SocialUserRespDTO.java | 10 +++++++++- .../service/auth/AdminAuthServiceImpl.java | 2 +- .../service/social/SocialUserServiceImpl.java | 8 +++----- 16 files changed, 80 insertions(+), 38 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java index 632675203..f256712b3 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/TerminalEnum.java @@ -15,6 +15,7 @@ import java.util.Arrays; @Getter public enum TerminalEnum implements IntArrayValuable { + UNKNOWN(0, "未知"), // 目的:在无法解析到 terminal 时,使用它 WECHAT_MINI_PROGRAM(10, "微信小程序"), WECHAT_WAP(11, "微信公众号"), H5(20, "H5 网页"), diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java index 672c1fa19..bc592d890 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/servlet/ServletUtils.java @@ -88,8 +88,6 @@ public class ServletUtils { return JakartaServletUtil.getClientIP(request); } - // TODO @疯狂:terminal 还是从 ServletUtils 里拿,更容易全局治理; - public static boolean isJsonRequest(ServletRequest request) { return StrUtil.startWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java index 70c59cb4e..ae18634c2 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java @@ -1,8 +1,11 @@ package cn.iocoder.yudao.framework.web.core.util; import cn.hutool.core.util.NumberUtil; +import cn.hutool.extra.servlet.ServletUtil; +import cn.iocoder.yudao.framework.common.enums.TerminalEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.config.WebProperties; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; @@ -25,6 +28,13 @@ public class WebFrameworkUtils { public static final String HEADER_TENANT_ID = "tenant-id"; + /** + * 终端的 Header + * + * @see cn.iocoder.yudao.framework.common.enums.TerminalEnum + */ + public static final String HEADER_TERMINAL = "terminal"; + private static WebProperties properties; public WebFrameworkUtils(WebProperties webProperties) { @@ -107,6 +117,15 @@ public class WebFrameworkUtils { return getLoginUserId(request); } + public static Integer getTerminal() { + HttpServletRequest request = getRequest(); + if (request == null) { + return TerminalEnum.UNKNOWN.getTerminal(); + } + String terminalValue = request.getHeader(HEADER_TERMINAL); + return NumberUtil.parseInt(terminalValue, TerminalEnum.UNKNOWN.getTerminal()); + } + public static void setCommonResult(ServletRequest request, CommonResult result) { request.setAttribute(REQUEST_ATTRIBUTE_COMMON_RESULT, result); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java index 545f0adde..8bae3e35d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -61,9 +61,8 @@ public class AppTradeOrderController { @PostMapping("/create") @Operation(summary = "创建订单") @PreAuthenticated - public CommonResult createOrder(@Valid @RequestBody AppTradeOrderCreateReqVO createReqVO, - @RequestHeader Integer terminal) { - TradeOrderDO order = tradeOrderUpdateService.createOrder(getLoginUserId(), getClientIP(), createReqVO, terminal); + public CommonResult createOrder(@Valid @RequestBody AppTradeOrderCreateReqVO createReqVO) { + TradeOrderDO order = tradeOrderUpdateService.createOrder(getLoginUserId(), createReqVO); return success(new AppTradeOrderCreateRespVO().setId(order.getId()).setPayOrderId(order.getPayOrderId())); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index 773bb9e91..e368d0355 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -69,8 +69,7 @@ public interface TradeOrderConvert { @Mapping(source = "calculateRespBO.price.vipPrice", target = "vipPrice"), @Mapping(source = "calculateRespBO.price.payPrice", target = "payPrice") }) - TradeOrderDO convert(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO, - TradePriceCalculateRespBO calculateRespBO); + TradeOrderDO convert(Long userId, AppTradeOrderCreateReqVO createReqVO, TradePriceCalculateRespBO calculateRespBO); TradeOrderRespDTO convert(TradeOrderDO orderDO); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java index b26d84c65..e16a08bd7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java @@ -36,12 +36,10 @@ public interface TradeOrderUpdateService { * 【会员】创建交易订单 * * @param userId 登录用户 - * @param userIp 用户 IP 地址 * @param createReqVO 创建交易订单请求模型 - * @param terminal 终端 {@link TerminalEnum} * @return 交易订单的 */ - TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO, Integer terminal); + TradeOrderDO createOrder(Long userId, AppTradeOrderCreateReqVO createReqVO); /** * 更新交易订单已支付 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 40e26a2b7..e0b57d923 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -64,6 +64,8 @@ import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.minusTime; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getTerminal; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; /** @@ -158,11 +160,11 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { @Override @Transactional(rollbackFor = Exception.class) @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_CREATE) - public TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO, Integer terminal) { + public TradeOrderDO createOrder(Long userId, AppTradeOrderCreateReqVO createReqVO) { // 1.1 价格计算 TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO); // 1.2 构建订单 - TradeOrderDO order = buildTradeOrder(userId, userIp, createReqVO, calculateRespBO, terminal); + TradeOrderDO order = buildTradeOrder(userId, createReqVO, calculateRespBO); List orderItems = buildTradeOrderItems(order, calculateRespBO); // 2. 订单创建前的逻辑 @@ -178,15 +180,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { return order; } - private TradeOrderDO buildTradeOrder(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO, - TradePriceCalculateRespBO calculateRespBO, Integer terminal) { - TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, calculateRespBO); + private TradeOrderDO buildTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, + TradePriceCalculateRespBO calculateRespBO) { + TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, createReqVO, calculateRespBO); order.setType(calculateRespBO.getType()); order.setNo(tradeNoRedisDAO.generate(TradeNoRedisDAO.TRADE_ORDER_NO_PREFIX)); order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum)); - order.setTerminal(terminal); + order.setUserIp(getClientIP()).setTerminal(getTerminal()); // 支付 + 退款信息 order.setAdjustPrice(0).setPayStatus(false); order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java index 503ff13bd..16c7db207 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java @@ -73,9 +73,8 @@ public class AppAuthController { @PostMapping("/sms-login") @Operation(summary = "使用手机 + 验证码登录") - public CommonResult smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO, - @RequestHeader Integer terminal) { - return success(authService.smsLogin(reqVO, terminal)); + public CommonResult smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO) { + return success(authService.smsLogin(reqVO)); } @PostMapping("/send-sms-code") diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java index 46bc048dc..3fad6e232 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthService.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.member.service.auth; -import cn.iocoder.yudao.framework.common.enums.TerminalEnum; import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; import jakarta.validation.Valid; @@ -33,10 +32,9 @@ public interface MemberAuthService { * 手机 + 验证码登陆 * * @param reqVO 登陆信息 - * @param terminal 终端 {@link TerminalEnum} * @return 登录结果 */ - AppAuthLoginRespVO smsLogin(@Valid AppAuthSmsLoginReqVO reqVO, Integer terminal); + AppAuthLoginRespVO smsLogin(@Valid AppAuthSmsLoginReqVO reqVO); /** * 社交登录,使用 code 授权码 diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java index cb246bd0f..3111034d5 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java @@ -36,6 +36,7 @@ import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getTerminal; import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*; /** @@ -78,13 +79,13 @@ public class MemberAuthServiceImpl implements MemberAuthService { @Override @Transactional - public AppAuthLoginRespVO smsLogin(AppAuthSmsLoginReqVO reqVO, Integer terminal) { + public AppAuthLoginRespVO smsLogin(AppAuthSmsLoginReqVO reqVO) { // 校验验证码 String userIp = getClientIP(); smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_LOGIN.getScene(), userIp)); // 获得获得注册用户 - MemberUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp, terminal); + MemberUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp, getTerminal()); Assert.notNull(user, "获取用户失败,结果为空"); // 如果 socialType 非空,说明需要绑定社交用户 @@ -107,10 +108,13 @@ public class MemberAuthServiceImpl implements MemberAuthService { throw exception(AUTH_THIRD_LOGIN_NOT_BIND); } - // 自动登录 + // 情况一:已绑定,自动登录 MemberUserDO user = userService.getUser(socialUser.getUserId()); if (user == null) { throw exception(USER_NOT_EXISTS); + // 情况二:未绑定,注册登录 + } else { + user = userService.createUser(user.getNickname(), user.getAvatar(), getClientIP(), getTerminal()); } // 创建 Token 令牌,记录登录日志 diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java index 1305c5ae3..dcd71ea21 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java @@ -49,6 +49,18 @@ public interface MemberUserService { */ MemberUserDO createUserIfAbsent(@Mobile String mobile, String registerIp, Integer terminal); + /** + * 创建用户 + * 目的:三方登录时,如果未绑定用户时,自动创建对应用户 + * + * @param nickname 昵称 + * @param avtar 头像 + * @param registerIp 注册 IP + * @param terminal 终端 {@link TerminalEnum} + * @return 用户对象 + */ + MemberUserDO createUser(String nickname, String avtar, String registerIp, Integer terminal); + /** * 更新用户的最后登陆信息 * diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java index 37b56f001..b704166b4 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -81,10 +81,17 @@ public class MemberUserServiceImpl implements MemberUserService { return user; } // 用户不存在,则进行创建 - return createUser(mobile, registerIp, terminal); + return createUser(mobile, null, null, registerIp, terminal); } - private MemberUserDO createUser(String mobile, String registerIp, Integer terminal) { + @Override + @Transactional(rollbackFor = Exception.class) + public MemberUserDO createUser(String nickname, String avtar, String registerIp, Integer terminal) { + return createUser(null, nickname, avtar, registerIp, terminal); + } + + private MemberUserDO createUser(String mobile, String nickname, String avtar, + String registerIp, Integer terminal) { // 生成密码 String password = IdUtil.fastSimpleUUID(); // 插入用户 @@ -92,8 +99,8 @@ public class MemberUserServiceImpl implements MemberUserService { user.setMobile(mobile); user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 user.setPassword(encodePassword(password)); // 加密密码 - user.setRegisterIp(registerIp); - user.setRegisterTerminal(terminal); + user.setRegisterIp(registerIp).setRegisterTerminal(terminal); + user.setNickname(nickname).setAvatar(avtar); // 基础信息 memberUserMapper.insert(user); // 发送 MQ 消息:用户创建 diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/LoginLogCreateReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/LoginLogCreateReqDTO.java index 2e7a14210..539c8ee27 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/LoginLogCreateReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/LoginLogCreateReqDTO.java @@ -36,9 +36,9 @@ public class LoginLogCreateReqDTO { private Integer userType; /** * 用户账号 + * + * 不再强制校验 username 非空,因为 Member 社交登录时,此时暂时没有 username(mobile)! */ - @NotBlank(message = "用户账号不能为空") - @Size(max = 30, message = "用户账号长度不能超过30个字符") private String username; /** diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserRespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserRespDTO.java index ac25b148e..29fef0107 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserRespDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserRespDTO.java @@ -15,9 +15,17 @@ import lombok.NoArgsConstructor; public class SocialUserRespDTO { /** - * 社交用户 openid + * 社交用户的 openid */ private String openid; + /** + * 社交用户的昵称 + */ + private String nickname; + /** + * 社交用户的头像 + */ + private String avatar; /** * 关联的用户编号 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java index aae67de0d..6ff184544 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java @@ -158,7 +158,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 SocialUserRespDTO socialUser = socialUserService.getSocialUser(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), reqVO.getCode(), reqVO.getState()); - if (socialUser == null) { + if (socialUser == null || socialUser.getUserId() == null) { throw exception(AUTH_THIRD_LOGIN_NOT_BIND); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java index 1deecba78..5b7dd5f72 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java @@ -99,13 +99,11 @@ public class SocialUserServiceImpl implements SocialUserService { SocialUserDO socialUser = authSocialUser(socialType, userType, code, state); Assert.notNull(socialUser, "社交用户不能为空"); - // 如果未绑定的社交用户,则无法自动登录,进行报错 + // 获得绑定用户 SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserTypeAndSocialUserId(userType, socialUser.getId()); - if (socialUserBind == null) { - throw exception(AUTH_THIRD_LOGIN_NOT_BIND); - } - return new SocialUserRespDTO(socialUser.getOpenid(), socialUserBind.getUserId()); + return new SocialUserRespDTO(socialUser.getOpenid(), socialUser.getNickname(), socialUser.getAvatar(), + socialUserBind != null ? socialUserBind.getUserId() : null); } /** From 59752d43b7dcd2f1cc3e767187640f31c2753e3c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 23 Dec 2023 17:54:13 +0800 Subject: [PATCH 19/55] =?UTF-8?q?=E2=9C=A8=20Member=EF=BC=9A=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E7=A4=BE=E4=BA=A4=E7=99=BB=E5=BD=95=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=88=9B=E5=BB=BA=20user=20=E5=90=8E?= =?UTF-8?q?=EF=BC=8C=E6=9C=AA=E8=BF=9B=E8=A1=8C=E7=BB=91=E5=AE=9A=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/enums/ErrorCodeConstants.java | 2 +- .../service/auth/MemberAuthServiceImpl.java | 18 ++++++++++++------ .../service/user/MemberUserServiceImpl.java | 8 +++++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java index c7dc8b749..ee970a54c 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java +++ b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java @@ -18,7 +18,7 @@ public interface ErrorCodeConstants { // ========== AUTH 模块 1-004-003-000 ========== ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1_004_003_000, "登录失败,账号密码不正确"); ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1_004_003_001, "登录失败,账号被禁用"); - ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_004_003_005, "未绑定账号,需要进行绑定"); + ErrorCode AUTH_SOCIAL_USER_NOT_FOUND = new ErrorCode(1_004_003_005, "登录失败,解析不到三方登录信息"); ErrorCode AUTH_MOBILE_USED = new ErrorCode(1_004_003_007, "手机号已经被使用"); // ========== 用户收件地址 1-004-004-000 ========== diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java index 3111034d5..78d534610 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java @@ -100,21 +100,27 @@ public class MemberAuthServiceImpl implements MemberAuthService { } @Override + @Transactional public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) { // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 SocialUserRespDTO socialUser = socialUserApi.getSocialUser(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), reqVO.getCode(), reqVO.getState()); if (socialUser == null) { - throw exception(AUTH_THIRD_LOGIN_NOT_BIND); + throw exception(AUTH_SOCIAL_USER_NOT_FOUND); } - // 情况一:已绑定,自动登录 - MemberUserDO user = userService.getUser(socialUser.getUserId()); + // 情况一:已绑定,直接读取用户信息 + MemberUserDO user; + if (socialUser.getUserId() != null) { + user = userService.getUser(socialUser.getUserId()); + // 情况二:未绑定,注册用户 + 绑定用户 + } else { + user = userService.createUser(socialUser.getNickname(), socialUser.getAvatar(), getClientIP(), getTerminal()); + socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), + reqVO.getType(), reqVO.getCode(), reqVO.getState())); + } if (user == null) { throw exception(USER_NOT_EXISTS); - // 情况二:未绑定,注册登录 - } else { - user = userService.createUser(user.getNickname(), user.getAvatar(), getClientIP(), getTerminal()); } // 创建 Token 令牌,记录登录日志 diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java index b704166b4..9fb385475 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -2,9 +2,7 @@ package cn.iocoder.yudao.module.member.service.user; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.*; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -101,6 +99,10 @@ public class MemberUserServiceImpl implements MemberUserService { user.setPassword(encodePassword(password)); // 加密密码 user.setRegisterIp(registerIp).setRegisterTerminal(terminal); user.setNickname(nickname).setAvatar(avtar); // 基础信息 + if (StrUtil.isEmpty(nickname)) { + // 昵称为空时,随机一个名字,避免一些依赖 nickname 的逻辑报错,或者有点丑。例如说,短信发送有昵称时~ + user.setNickname("用户" + RandomUtil.randomNumbers(6)); + } memberUserMapper.insert(user); // 发送 MQ 消息:用户创建 From e8ade5f1fe36f1a7102822b5ed3e7b2444711174 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 23 Dec 2023 20:10:40 +0800 Subject: [PATCH 20/55] =?UTF-8?q?crm=EF=BC=9A=E5=AE=8C=E5=96=84=E4=B8=80?= =?UTF-8?q?=E4=BA=9B=E9=81=97=E7=95=99=E7=9A=84=20TODO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/aop/OperateLogV2Aspect.java | 8 +++- .../core/aop/CrmPermissionAspect.java | 31 +----------- .../core/util/CrmPermissionUtils.java | 48 +++++++++++++++++++ .../customer/CrmCustomerServiceImpl.java | 7 +++ .../permission/CrmPermissionServiceImpl.java | 4 +- .../module/crm/util/CrmQueryWrapperUtils.java | 22 ++------- 6 files changed, 68 insertions(+), 52 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java index 99d33dc71..a4129c37c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java @@ -129,6 +129,10 @@ public class OperateLogV2Aspect { if (EXTRA.get() != null && EXTRA.get().get(ENABLE) != null) { return; } + if (CONTENT.get() == null) { // 没有值说明没有日志需要记录 + return; + } + // 真正记录操作日志 this.log0(joinPoint, operation, startTime, result, exception); } catch (Throwable ex) { @@ -146,7 +150,7 @@ public class OperateLogV2Aspect { // 补充用户信息 fillUserFields(reqDTO); // 补全模块信息 - fillModuleFields(reqDTO, joinPoint, operation); + fillModuleFields(reqDTO, operation); // 补全请求信息 fillRequestFields(reqDTO); // 补全方法信息 @@ -161,7 +165,7 @@ public class OperateLogV2Aspect { reqDTO.setUserType(WebFrameworkUtils.getLoginUserType()); } - private static void fillModuleFields(OperateLogV2CreateReqDTO reqDTO, ProceedingJoinPoint joinPoint, Operation operation) { + private static void fillModuleFields(OperateLogV2CreateReqDTO reqDTO, Operation operation) { LogRecord logRecord = CONTENT.get(); reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 reqDTO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java index ddd44edff..40bae7b98 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java @@ -3,16 +3,14 @@ package cn.iocoder.yudao.module.crm.framework.permission.core.aop; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; -import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; @@ -52,7 +50,7 @@ public class CrmPermissionAspect { Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别 // 1.1 如果是超级管理员则直接通过 - if (validateAdminUser(getUserId())) { + if (CrmPermissionUtils.validateAdminUser()) { return; } // 1.2 获取数据权限 @@ -120,29 +118,4 @@ public class CrmPermissionAspect { return SpringExpressionUtils.parseExpressions(joinPoint, expressionStrings); } - /** - * 校验用户是否是 CRM 管理员 - * - * @param userId 用户编号 - * @return 是/否 - */ - private static boolean validateAdminUser(Long userId) { - return SingletonManager.getPermissionApi().hasAnyRoles(userId, CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); - } - - /** - * 静态内部类实现单例获取 - * - * @author HUIHUI - */ - private static class SingletonManager { - - private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); - - public static PermissionApi getPermissionApi() { - return PERMISSION_API; - } - - } - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java new file mode 100644 index 000000000..80a1654a8 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.crm.framework.permission.core.util; + +import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; + +/** + * 数据权限工具类 + * + * @author HUIHUI + */ +public class CrmPermissionUtils { + + /** + * 校验用户是否是 CRM 管理员 + * + * @return 是/否 + */ + public static boolean validateAdminUser() { + return SingletonManager.getPermissionApi().hasAnyRoles(getUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); + } + + /** + * 获得用户编号 + * + * @return 用户编号 + */ + private static Long getUserId() { + return WebFrameworkUtils.getLoginUserId(); + } + + /** + * 静态内部类实现单例获取 + * + * @author HUIHUI + */ + private static class SingletonManager { + + private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); + + public static PermissionApi getPermissionApi() { + return PERMISSION_API; + } + + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index d20512917..5d8dd36b2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -53,6 +53,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#customerId}}", success = "创建了客户") public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { // 插入 CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO); @@ -61,6 +62,9 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 创建数据权限 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 + + // 添加日志上下文所需 + LogRecordContext.putVariable("customerId", customer.getId()); return customer.getId(); } @@ -85,6 +89,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#id}}", success = "删除了客户") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteCustomer(Long id) { // 校验存在 @@ -152,6 +157,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#updateReqVO.id}}", success = "锁定了客户") public void lockCustomer(CrmCustomerUpdateReqVO updateReqVO) { // 校验存在 validateCustomerExists(updateReqVO.getId()); @@ -165,6 +171,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#id}}", success = "将客户放入了公海") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void putCustomerPool(Long id) { // 1. 校验存在 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index a686ffc6a..e3cc4a24b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.dal.mysql.permission.CrmPermissionMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -89,8 +90,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId( transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId()); String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType()); - // TODO 校验是否为超级管理员 || 1 - if (oldPermission == null || !isOwner(oldPermission.getLevel())) { + if (oldPermission == null || !isOwner(oldPermission.getLevel()) || !CrmPermissionUtils.validateAdminUser()) { throw exception(CRM_PERMISSION_DENIED, bizTypeName); } // 1.1 校验转移对象是否已经是该负责人 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java index cbe43e683..0e1ba5471 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java @@ -7,8 +7,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; -import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; @@ -41,7 +40,7 @@ public class CrmQueryWrapperUtils { Long userId, Integer sceneType, Boolean pool) { final String ownerUserIdField = SingletonManager.getMybatisPlusJoinProperties().getTableAlias() + ".owner_user_id"; // 1. 构建数据权限连表条件 - if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 + if (ObjUtil.notEqual(CrmPermissionUtils.validateAdminUser(), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) .eq(CrmPermissionDO::getBizId, bizId) // 只能使用 SFunction 如果传 id 解析出来的 sql 不对 .eq(CrmPermissionDO::getUserId, userId)); @@ -82,7 +81,7 @@ public class CrmQueryWrapperUtils { * @param userId 用户编号 */ public static > void appendPermissionCondition(T query, Integer bizType, Collection bizIds, Long userId) { - if (ObjUtil.equal(validateAdminUser(userId), Boolean.TRUE)) {// 管理员不需要数据权限 + if (ObjUtil.equal(CrmPermissionUtils.validateAdminUser(), Boolean.TRUE)) {// 管理员不需要数据权限 return; } @@ -91,16 +90,6 @@ public class CrmQueryWrapperUtils { .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); } - /** - * 校验用户是否是 CRM 管理员 - * - * @param userId 用户编号 - * @return 是/否 - */ - private static boolean validateAdminUser(Long userId) { - return SingletonManager.getPermissionApi().hasAnyRoles(userId, CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); - } - /** * 静态内部类实现单例获取 * @@ -109,17 +98,12 @@ public class CrmQueryWrapperUtils { private static class SingletonManager { private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); - private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); private static final MybatisPlusJoinProperties MYBATIS_PLUS_JOIN_PROPERTIES = SpringUtil.getBean(MybatisPlusJoinProperties.class); public static AdminUserApi getAdminUserApi() { return ADMIN_USER_API; } - public static PermissionApi getPermissionApi() { - return PERMISSION_API; - } - public static MybatisPlusJoinProperties getMybatisPlusJoinProperties() { return MYBATIS_PLUS_JOIN_PROPERTIES; } From 7b482f572986bda8f3f8e6cbe4b646f2497a0c7e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 23 Dec 2023 21:48:33 +0800 Subject: [PATCH 21/55] =?UTF-8?q?=E2=9C=A8=20Member=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=8E=B7=E5=8F=96=E5=8D=95=E4=B8=AA=E7=A4=BE=E4=BA=A4?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=9A=84=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/social/AppSocialUserController.java | 31 +++++++++++++++---- .../app/social/vo/AppSocialUserBindReqVO.java | 3 -- .../app/social/vo/AppSocialUserRespVO.java | 19 ++++++++++++ .../social/vo/AppSocialUserUnbindReqVO.java | 3 -- .../convert/social/SocialUserConvert.java | 19 ------------ .../service/auth/MemberAuthServiceImpl.java | 2 +- .../system/api/social/SocialUserApi.java | 13 ++++++-- .../social/dto/SocialUserUnbindReqDTO.java | 4 +++ .../system/api/social/SocialUserApiImpl.java | 9 ++++-- .../mysql/social/SocialUserBindMapper.java | 7 +++++ .../service/auth/AdminAuthServiceImpl.java | 2 +- .../service/social/SocialUserService.java | 12 ++++++- .../service/social/SocialUserServiceImpl.java | 17 ++++++++-- .../auth/AdminAuthServiceImplTest.java | 2 +- .../social/SocialUserServiceImplTest.java | 2 +- 15 files changed, 103 insertions(+), 42 deletions(-) create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserRespVO.java delete mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/social/SocialUserConvert.java diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index 00a27610b..d93e1eaa3 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -2,11 +2,16 @@ package cn.iocoder.yudao.module.member.controller.app.social; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserBindReqVO; +import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserRespVO; import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO; -import cn.iocoder.yudao.module.member.convert.social.SocialUserConvert; import cn.iocoder.yudao.module.system.api.social.SocialUserApi; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO; +import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; import org.springframework.validation.annotation.Validated; @@ -15,11 +20,12 @@ import org.springframework.web.bind.annotation.*; import jakarta.annotation.Resource; import jakarta.validation.Valid; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "用户 App - 社交用户") @RestController -@RequestMapping("/system/social-user") +@RequestMapping("/member/social-user") @Validated public class AppSocialUserController { @@ -29,16 +35,29 @@ public class AppSocialUserController { @PostMapping("/bind") @Operation(summary = "社交绑定,使用 code 授权码") public CommonResult socialBind(@RequestBody @Valid AppSocialUserBindReqVO reqVO) { - socialUserApi.bindSocialUser(SocialUserConvert.INSTANCE.convert(getLoginUserId(), UserTypeEnum.MEMBER.getValue(), reqVO)); - return CommonResult.success(true); + SocialUserBindReqDTO reqDTO = new SocialUserBindReqDTO(getLoginUserId(), UserTypeEnum.MEMBER.getValue(), + reqVO.getType(), reqVO.getCode(), reqVO.getState()); + socialUserApi.bindSocialUser(reqDTO); + return success(true); } @DeleteMapping("/unbind") @Operation(summary = "取消社交绑定") @PreAuthenticated public CommonResult socialUnbind(@RequestBody AppSocialUserUnbindReqVO reqVO) { - socialUserApi.unbindSocialUser(SocialUserConvert.INSTANCE.convert(getLoginUserId(), UserTypeEnum.MEMBER.getValue(), reqVO)); - return CommonResult.success(true); + SocialUserUnbindReqDTO reqDTO = new SocialUserUnbindReqDTO(getLoginUserId(), UserTypeEnum.MEMBER.getValue(), + reqVO.getType(), reqVO.getOpenid()); + socialUserApi.unbindSocialUser(reqDTO); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得社交用户") + @Parameter(name = "type", description = "社交平台的类型,参见 SocialTypeEnum 枚举值", required = true, example = "10") + @PreAuthenticated + public CommonResult getSocialUser(@RequestParam("type") Integer type) { + SocialUserRespDTO socialUser = socialUserApi.getSocialUserByUserId(UserTypeEnum.MEMBER.getValue(), getLoginUserId(), type); + return success(BeanUtils.toBean(socialUser, AppSocialUserRespVO.class)); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java index 3c0080c21..0b455965a 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserBindReqVO.java @@ -13,9 +13,6 @@ import jakarta.validation.constraints.NotNull; @Schema(description = "用户 APP - 社交绑定 Request VO,使用 code 授权码") @Data -@NoArgsConstructor -@AllArgsConstructor -@Builder public class AppSocialUserBindReqVO { @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserRespVO.java new file mode 100644 index 000000000..f37ced800 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserRespVO.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.member.controller.app.social.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "用户 APP - 社交用户 Response VO") +@Data +public class AppSocialUserRespVO { + + @Schema(description = "社交用户的 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE") + private String openid; + + @Schema(description = "社交用户的昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") + private String nickname; + + @Schema(description = "社交用户的头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/1.png") + private String avatar; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java index 43bf067b4..5b3cd8866 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/vo/AppSocialUserUnbindReqVO.java @@ -13,9 +13,6 @@ import jakarta.validation.constraints.NotNull; @Schema(description = "用户 APP - 取消社交绑定 Request VO") @Data -@NoArgsConstructor -@AllArgsConstructor -@Builder public class AppSocialUserUnbindReqVO { @Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/social/SocialUserConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/social/SocialUserConvert.java deleted file mode 100644 index 3c9288ba8..000000000 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/social/SocialUserConvert.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.member.convert.social; - -import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserBindReqVO; -import cn.iocoder.yudao.module.member.controller.app.social.vo.AppSocialUserUnbindReqVO; -import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; -import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface SocialUserConvert { - - SocialUserConvert INSTANCE = Mappers.getMapper(SocialUserConvert.class); - - SocialUserBindReqDTO convert(Long userId, Integer userType, AppSocialUserBindReqVO reqVO); - - SocialUserUnbindReqDTO convert(Long userId, Integer userType, AppSocialUserUnbindReqVO reqVO); - -} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java index 78d534610..7fb1926ce 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java @@ -103,7 +103,7 @@ public class MemberAuthServiceImpl implements MemberAuthService { @Transactional public AppAuthLoginRespVO socialLogin(AppAuthSocialLoginReqVO reqVO) { // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 - SocialUserRespDTO socialUser = socialUserApi.getSocialUser(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), + SocialUserRespDTO socialUser = socialUserApi.getSocialUserByCode(UserTypeEnum.MEMBER.getValue(), reqVO.getType(), reqVO.getCode(), reqVO.getState()); if (socialUser == null) { throw exception(AUTH_SOCIAL_USER_NOT_FOUND); diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java index 5038e94bd..e24f8356d 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java @@ -29,6 +29,16 @@ public interface SocialUserApi { */ void unbindSocialUser(@Valid SocialUserUnbindReqDTO reqDTO); + /** + * 获得社交用户,基于 userId + * + * @param userType 用户类型 + * @param userId 用户编号 + * @param socialType 社交平台的类型 + * @return 社交用户 + */ + SocialUserRespDTO getSocialUserByUserId(Integer userType, Long userId, Integer socialType); + /** * 获得社交用户 * @@ -40,7 +50,6 @@ public interface SocialUserApi { * @param state state * @return 社交用户 */ - SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, - String code, String state); + SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state); } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java index 55ff5b165..7e559d8ee 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java @@ -3,10 +3,12 @@ package cn.iocoder.yudao.module.system.api.social.dto; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; +import lombok.AllArgsConstructor; import lombok.Data; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import lombok.NoArgsConstructor; /** * 社交绑定 Request DTO,使用 code 授权码 @@ -14,6 +16,8 @@ import jakarta.validation.constraints.NotNull; * @author 芋道源码 */ @Data +@AllArgsConstructor +@NoArgsConstructor public class SocialUserUnbindReqDTO { /** diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java index dc92dfce6..eb8331618 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java @@ -33,8 +33,13 @@ public class SocialUserApiImpl implements SocialUserApi { } @Override - public SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, String code, String state) { - return socialUserService.getSocialUser(userType, socialType, code, state); + public SocialUserRespDTO getSocialUserByUserId(Integer userType, Long userId, Integer socialType) { + return socialUserService.getSocialUserByUserId(userType, userId, socialType); + } + + @Override + public SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state) { + return socialUserService.getSocialUserByCode(userType, socialType, code, state); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserBindMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserBindMapper.java index 28619ca51..d9957f76c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserBindMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserBindMapper.java @@ -34,4 +34,11 @@ public interface SocialUserBindMapper extends BaseMapperX { .eq(SocialUserBindDO::getUserType, userType)); } + default SocialUserBindDO selectByUserIdAndUserTypeAndSocialType(Long userId, Integer userType, Integer socialType) { + return selectOne(new LambdaQueryWrapperX() + .eq(SocialUserBindDO::getUserId, userId) + .eq(SocialUserBindDO::getUserType, userType) + .eq(SocialUserBindDO::getSocialType, socialType)); + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java index 6ff184544..bd4c93e11 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java @@ -156,7 +156,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { @Override public AuthLoginRespVO socialLogin(AuthSocialLoginReqVO reqVO) { // 使用 code 授权码,进行登录。然后,获得到绑定的用户编号 - SocialUserRespDTO socialUser = socialUserService.getSocialUser(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), + SocialUserRespDTO socialUser = socialUserService.getSocialUserByCode(UserTypeEnum.ADMIN.getValue(), reqVO.getType(), reqVO.getCode(), reqVO.getState()); if (socialUser == null || socialUser.getUserId() == null) { throw exception(AUTH_THIRD_LOGIN_NOT_BIND); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java index c840f19d1..739ff2d94 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java @@ -45,6 +45,16 @@ public interface SocialUserService { */ void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid); + /** + * 获得社交用户,基于 userId + * + * @param userType 用户类型 + * @param userId 用户编号 + * @param socialType 社交平台的类型 + * @return 社交用户 + */ + SocialUserRespDTO getSocialUserByUserId(Integer userType, Long userId, Integer socialType); + /** * 获得社交用户 * @@ -56,7 +66,7 @@ public interface SocialUserService { * @param state state * @return 社交用户 */ - SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, String code, String state); + SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state); // ==================== 社交用户 CRUD ==================== diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java index 5b7dd5f72..7f1b271ad 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java @@ -26,7 +26,6 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_THIRD_LOGIN_NOT_BIND; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND; /** @@ -94,7 +93,21 @@ public class SocialUserServiceImpl implements SocialUserService { } @Override - public SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, String code, String state) { + public SocialUserRespDTO getSocialUserByUserId(Integer userType, Long userId, Integer socialType) { + // 获得绑定用户 + SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserIdAndUserTypeAndSocialType(userId, userType, socialType); + if (socialUserBind == null) { + return null; + } + // 获得社交用户 + SocialUserDO socialUser = socialUserMapper.selectById(socialUserBind.getSocialUserId()); + Assert.notNull(socialUser, "社交用户不能为空"); + return new SocialUserRespDTO(socialUser.getOpenid(), socialUser.getNickname(), socialUser.getAvatar(), + socialUserBind.getUserId()); + } + + @Override + public SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state) { // 获得社交用户 SocialUserDO socialUser = authSocialUser(socialType, userType, code, state); Assert.notNull(socialUser, "社交用户不能为空"); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java index cd6c81f9f..a731d9ab5 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java @@ -236,7 +236,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { AuthSocialLoginReqVO reqVO = randomPojo(AuthSocialLoginReqVO.class); // mock 方法(绑定的用户编号) Long userId = 1L; - when(socialUserService.getSocialUser(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()), + when(socialUserService.getSocialUserByCode(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()), eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(new SocialUserRespDTO(randomString(), userId)); // mock(用户) AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId)); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java index 3685ed266..32393dd51 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java @@ -147,7 +147,7 @@ public class SocialUserServiceImplTest extends BaseDbUnitTest { socialUserBindMapper.insert(socialUserBind); // 调用 - SocialUserRespDTO socialUser = socialUserService.getSocialUser(userType, type, code, state); + SocialUserRespDTO socialUser = socialUserService.getSocialUserByCode(userType, type, code, state); // 断言 assertEquals(userId, socialUser.getUserId()); assertEquals(socialUserDO.getOpenid(), socialUser.getOpenid()); From bd5c7d57dc962297b05c82da19ef388c80c0f5a3 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 23 Dec 2023 22:54:20 +0800 Subject: [PATCH 22/55] =?UTF-8?q?=E2=9C=A8=20Member=EF=BC=9A=E7=A4=BE?= =?UTF-8?q?=E4=BA=A4=EF=BC=88=E4=B8=89=E6=96=B9=EF=BC=89=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=EF=BC=8C=E5=A2=9E=E5=8A=A0=20openid=20?= =?UTF-8?q?=E8=BF=94=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/app/social/AppSocialUserController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java index d93e1eaa3..fcdd2132d 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/social/AppSocialUserController.java @@ -34,11 +34,11 @@ public class AppSocialUserController { @PostMapping("/bind") @Operation(summary = "社交绑定,使用 code 授权码") - public CommonResult socialBind(@RequestBody @Valid AppSocialUserBindReqVO reqVO) { + public CommonResult socialBind(@RequestBody @Valid AppSocialUserBindReqVO reqVO) { SocialUserBindReqDTO reqDTO = new SocialUserBindReqDTO(getLoginUserId(), UserTypeEnum.MEMBER.getValue(), reqVO.getType(), reqVO.getCode(), reqVO.getState()); - socialUserApi.bindSocialUser(reqDTO); - return success(true); + String openid = socialUserApi.bindSocialUser(reqDTO); + return success(openid); } @DeleteMapping("/unbind") From 60e684c4556c7796032d14845d6db8b5971fcd34 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sun, 24 Dec 2023 00:32:17 +0800 Subject: [PATCH 23/55] =?UTF-8?q?=E8=90=A5=E9=94=80=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=EF=BC=9A=E8=8E=B7=E5=8F=96=E5=95=86=E5=93=81=E8=BF=91=E6=9C=9F?= =?UTF-8?q?=E5=8F=82=E4=B8=8E=E7=9A=84=E6=AF=8F=E4=B8=AA=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=BB=A1=E5=87=8F=E9=80=81=E5=92=8C=E9=99=90?= =?UTF-8?q?=E6=97=B6=E6=8A=98=E6=89=A3=E6=B4=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/activity/AppActivityController.java | 147 +++++++++++++----- .../discount/DiscountActivityMapper.java | 18 ++- .../mysql/discount/DiscountProductMapper.java | 18 +++ .../mysql/reward/RewardActivityMapper.java | 31 ++++ .../discount/DiscountActivityService.java | 13 +- .../discount/DiscountActivityServiceImpl.java | 22 ++- .../service/reward/RewardActivityService.java | 13 +- .../reward/RewardActivityServiceImpl.java | 22 ++- 8 files changed, 238 insertions(+), 46 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java index 16233bef3..6c5cec14a 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java @@ -7,26 +7,33 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.module.promotion.controller.app.activity.vo.AppActivityRespVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.bargain.BargainActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; +import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService; import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; +import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService; +import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService; import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import jakarta.annotation.Resource; import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; @Tag(name = "用户 APP - 营销活动") // 用于提供跨多个活动的 HTTP 接口 @RestController @@ -40,6 +47,10 @@ public class AppActivityController { private SeckillActivityService seckillActivityService; @Resource private BargainActivityService bargainActivityService; + @Resource + private DiscountActivityService discountActivityService; + @Resource + private RewardActivityService rewardActivityService; @GetMapping("/list-by-spu-id") @Operation(summary = "获得单个商品,近期参与的每个活动") @@ -64,45 +75,105 @@ public class AppActivityController { if (CollUtil.isEmpty(spuIds)) { return new ArrayList<>(); } + LocalDateTime now = LocalDateTime.now(); + // 获取开启的且开始的且没有结束的活动 List activityList = new ArrayList<>(); - - // 1. 拼团活动 - 获取开启的且开始的且没有结束的活动 - List combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatusAndDateTimeLt( - spuIds, CommonStatusEnum.ENABLE.getStatus(), now); - if (CollUtil.isNotEmpty(combinationActivities)) { - combinationActivities.forEach(item -> { - activityList.add(new AppActivityRespVO().setId(item.getId()) - .setType(PromotionTypeEnum.COMBINATION_ACTIVITY.getType()).setName(item.getName()) - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); - }); - } - - // 2. 秒杀活动 - 获取开启的且开始的且没有结束的活动 - List seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatusAndDateTimeLt( - spuIds, CommonStatusEnum.ENABLE.getStatus(), now); - if (CollUtil.isNotEmpty(seckillActivities)) { - seckillActivities.forEach(item -> { - activityList.add(new AppActivityRespVO().setId(item.getId()) - .setType(PromotionTypeEnum.SECKILL_ACTIVITY.getType()).setName(item.getName()) - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); - }); - } - - // 3. 砍价活动 - 获取开启的且开始的且没有结束的活动 - List bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatusAndDateTimeLt( - spuIds, CommonStatusEnum.ENABLE.getStatus(), now); - if (CollUtil.isNotEmpty(bargainActivities)) { - bargainActivities.forEach(item -> { - activityList.add(new AppActivityRespVO().setId(item.getId()) - .setType(PromotionTypeEnum.BARGAIN_ACTIVITY.getType()).setName(item.getName()) - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); - }); - } - - // TODO 芋艿:满减送活动 - // TODO 芋艿:限时折扣活动 + // 1. 拼团活动 + getCombinationActivities(spuIds, now, activityList); + // 2. 秒杀活动 + getSeckillActivities(spuIds, now, activityList); + // 3. 砍价活动 + getBargainActivities(spuIds, now, activityList); + // 4. 限时折扣活动 + getDiscountActivities(spuIds, now, activityList); + // 5. 满减送活动 + getRewardActivities(spuIds, now, activityList); return activityList; } + private void getCombinationActivities(Collection spuIds, LocalDateTime now, List activityList) { + List combinationActivities = combinationActivityService.getCombinationActivityBySpuIdsAndStatusAndDateTimeLt( + spuIds, CommonStatusEnum.ENABLE.getStatus(), now); + if (CollUtil.isEmpty(combinationActivities)) { + return; + } + + combinationActivities.forEach(item -> { + activityList.add(new AppActivityRespVO().setId(item.getId()) + .setType(PromotionTypeEnum.COMBINATION_ACTIVITY.getType()).setName(item.getName()) + .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); + }); + } + + private void getSeckillActivities(Collection spuIds, LocalDateTime now, List activityList) { + List seckillActivities = seckillActivityService.getSeckillActivityBySpuIdsAndStatusAndDateTimeLt( + spuIds, CommonStatusEnum.ENABLE.getStatus(), now); + if (CollUtil.isEmpty(seckillActivities)) { + return; + } + + seckillActivities.forEach(item -> { + activityList.add(new AppActivityRespVO().setId(item.getId()) + .setType(PromotionTypeEnum.SECKILL_ACTIVITY.getType()).setName(item.getName()) + .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); + }); + } + + private void getBargainActivities(Collection spuIds, LocalDateTime now, List activityList) { + List bargainActivities = bargainActivityService.getBargainActivityBySpuIdsAndStatusAndDateTimeLt( + spuIds, CommonStatusEnum.ENABLE.getStatus(), now); + if (CollUtil.isNotEmpty(bargainActivities)) { + return; + } + + bargainActivities.forEach(item -> { + activityList.add(new AppActivityRespVO().setId(item.getId()) + .setType(PromotionTypeEnum.BARGAIN_ACTIVITY.getType()).setName(item.getName()) + .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); + }); + } + + private void getDiscountActivities(Collection spuIds, LocalDateTime now, List activityList) { + List discountActivities = discountActivityService.getDiscountActivityBySpuIdsAndStatusAndDateTimeLt( + spuIds, CommonStatusEnum.ENABLE.getStatus(), now); + if (CollUtil.isEmpty(discountActivities)) { + return; + } + + List products = discountActivityService.getDiscountProductsByActivityId( + convertSet(discountActivities, DiscountActivityDO::getId)); + Map productMap = convertMap(products, DiscountProductDO::getActivityId, DiscountProductDO::getSpuId); + discountActivities.forEach(item -> { + activityList.add(new AppActivityRespVO().setId(item.getId()) + .setType(PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()).setName(item.getName()) + .setSpuId(productMap.get(item.getId())).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); + }); + } + + private void getRewardActivities(Collection spuIds, LocalDateTime now, List activityList) { + List rewardActivityList = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt( + spuIds, PromotionActivityStatusEnum.RUN.getStatus(), now); + if (CollUtil.isEmpty(rewardActivityList)) { + return; + } + + Map> spuIdAndActivityMap = spuIds.stream() + .collect(Collectors.toMap( + spuId -> spuId, + spuId -> rewardActivityList.stream() + .filter(activity -> activity.getProductSpuIds().contains(spuId)) + .max(Comparator.comparing(RewardActivityDO::getCreateTime)))); + for (Long supId : spuIdAndActivityMap.keySet()) { + if (spuIdAndActivityMap.get(supId).isEmpty()) { + continue; + } + + RewardActivityDO rewardActivityDO = spuIdAndActivityMap.get(supId).get(); + activityList.add(new AppActivityRespVO().setId(rewardActivityDO.getId()) + .setType(PromotionTypeEnum.REWARD_ACTIVITY.getType()).setName(rewardActivityDO.getName()) + .setSpuId(supId).setStartTime(rewardActivityDO.getStartTime()).setEndTime(rewardActivityDO.getEndTime())); + } + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountActivityMapper.java index 534ce627a..efd4e4d25 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountActivityMapper.java @@ -7,9 +7,9 @@ import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountAc import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; import org.apache.ibatis.annotations.Mapper; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; -import java.util.Set; /** * 限时折扣活动 Mapper @@ -27,4 +27,20 @@ public interface DiscountActivityMapper extends BaseMapperX .orderByDesc(DiscountActivityDO::getId)); } + /** + * 获取指定活动编号的活动列表且 + * 开始时间和结束时间小于给定时间 dateTime 的活动列表 + * + * @param ids 活动编号 + * @param dateTime 指定日期 + * @return 活动列表 + */ + default List selectListByIdsAndDateTimeLt(Collection ids, LocalDateTime dateTime) { + return selectList(new LambdaQueryWrapperX() + .in(DiscountActivityDO::getId, ids) + .lt(DiscountActivityDO::getStartTime, dateTime) + .gt(DiscountActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动 + .orderByDesc(DiscountActivityDO::getCreateTime)); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java index 10df2ce3a..5257b836d 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java @@ -2,11 +2,13 @@ package cn.iocoder.yudao.module.promotion.dal.mysql.discount; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import java.util.Collection; import java.util.List; +import java.util.Map; /** * 限时折扣商城 Mapper @@ -30,4 +32,20 @@ public interface DiscountProductMapper extends BaseMapperX { // TODO @zhangshuai:逻辑里,尽量避免写 join 语句哈,你可以看看这个查询,有什么办法优化?目前的一个思路,是分 2 次查询,性能也是 ok 的 List getMatchDiscountProductList(@Param("skuIds") Collection skuIds); + + /** + * 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 + * + * @param spuIds spu 编号 + * @param status 状态 + * @return 包含 spuId 和 activityId 的 map 对象列表 + */ + default List> selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(Collection spuIds, Integer status) { + return selectMaps(new QueryWrapper() + .select("spu_id AS spuId, MAX(DISTINCT(activity_id)) AS activityId") + .in("spu_id", spuIds) + .eq("activity_status", status) + .groupBy("spu_id")); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java index 2ee879823..ca9e9668f 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java @@ -1,14 +1,19 @@ package cn.iocoder.yudao.module.promotion.dal.mysql.reward; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.ibatis.annotations.Mapper; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; /** * 满减送活动 Mapper @@ -35,4 +40,30 @@ public interface RewardActivityMapper extends BaseMapperX { .eq(RewardActivityDO::getStatus, status)); } + default List selectListBySpuIdsAndStatus(Collection spuIds, Integer status) { + Function, String> productScopeValuesFindInSetFunc = ids -> ids.stream() + .map(id -> StrUtil.format("FIND_IN_SET({}, product_spu_ids) ", id)) + .collect(Collectors.joining(" OR ")); + return selectList(new QueryWrapper() + .eq("status", status) + .apply(productScopeValuesFindInSetFunc.apply(spuIds))); + } + + /** + * 获取指定活动编号的活动列表且 + * 开始时间和结束时间小于给定时间 dateTime 的活动列表 + * + * @param ids 活动编号 + * @param dateTime 指定日期 + * @return 活动列表 + */ + default List selectListByIdsAndDateTimeLt(Collection ids, LocalDateTime dateTime) { + return selectList(new LambdaQueryWrapperX() + .in(RewardActivityDO::getId, ids) + .lt(RewardActivityDO::getStartTime, dateTime) + .gt(RewardActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动 + .orderByDesc(RewardActivityDO::getCreateTime) + ); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java index 05ad13eed..d754d0d9f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java @@ -6,8 +6,9 @@ import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountAc import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO; - import jakarta.validation.Valid; + +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -89,4 +90,14 @@ public interface DiscountActivityService { */ List getDiscountProductsByActivityId(Collection activityIds); + /** + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 + * + * @param spuIds spu 编号 + * @param status 状态 + * @param dateTime 当前日期时间 + * @return 折扣活动列表 + */ + List getDiscountActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java index b8b496fdb..f103cf553 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.service.discount; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO; @@ -15,16 +16,20 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountActivityMapp import cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper; import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; import cn.iocoder.yudao.module.promotion.util.PromotionUtils; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; +import java.time.LocalDateTime; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; /** @@ -109,7 +114,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { /** * 校验商品是否冲突 * - * @param id 编号 + * @param id 编号 * @param products 商品列表 */ private void validateDiscountActivityProductConflicts(Long id, List products) { @@ -184,4 +189,17 @@ public class DiscountActivityServiceImpl implements DiscountActivityService { return discountProductMapper.selectList("activity_id", activityIds); } + @Override + public List getDiscountActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime) { + // 1. 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号 + List> spuIdAndActivityIdMaps = discountProductMapper.selectSpuIdAndActivityIdMapsBySpuIdsAndStatus(spuIds, status); + if (CollUtil.isEmpty(spuIdAndActivityIdMaps)) { + return Collections.emptyList(); + } + + // 2. 查询活动详情 + return discountActivityMapper.selectListByIdsAndDateTimeLt( + convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java index 7176e980b..e2e225608 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java @@ -6,8 +6,9 @@ import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivi import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; - import jakarta.validation.Valid; + +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -71,4 +72,14 @@ public interface RewardActivityService { */ List getMatchRewardActivityList(Collection spuIds); + /** + * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录 + * + * @param spuIds spu 编号 + * @param status 状态 + * @param dateTime 当前日期时间 + * @return 满减送活动列表 + */ + List getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java index 723dda933..e896eab92 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java @@ -11,14 +11,17 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO; import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper; import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum; import cn.iocoder.yudao.module.promotion.util.PromotionUtils; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; +import java.time.LocalDateTime; import java.util.Collection; +import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; import static java.util.Arrays.asList; @@ -100,10 +103,11 @@ public class RewardActivityServiceImpl implements RewardActivityService { } // TODO @芋艿:逻辑有问题,需要优化;要分成全场、和指定来校验; + /** * 校验商品参加的活动是否冲突 * - * @param id 活动编号 + * @param id 活动编号 * @param spuIds 商品 SPU 编号数组 */ private void validateRewardActivitySpuConflicts(Long id, Collection spuIds) { @@ -125,7 +129,7 @@ public class RewardActivityServiceImpl implements RewardActivityService { /** * 获得商品参加的满减送活动的数组 * - * @param spuIds 商品 SPU 编号数组 + * @param spuIds 商品 SPU 编号数组 * @param statuses 活动状态数组 * @return 商品参加的满减送活动的数组 */ @@ -163,4 +167,16 @@ public class RewardActivityServiceImpl implements RewardActivityService { return null; } + @Override + public List getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime) { + // 1. 查询出指定 spuId 的 spu 参加的活动 + List rewardActivityList = rewardActivityMapper.selectListBySpuIdsAndStatus(spuIds, status); + if (CollUtil.isEmpty(rewardActivityList)) { + return Collections.emptyList(); + } + + // 2. 查询活动详情 + return rewardActivityMapper.selectListByIdsAndDateTimeLt(convertSet(rewardActivityList, RewardActivityDO::getId), dateTime); + } + } From 7542b6a78d5c932c9a416d2392c4825d3822e187 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 25 Dec 2023 08:43:32 +0800 Subject: [PATCH 24/55] =?UTF-8?q?=E2=9C=A8=20Member=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E5=BE=AE=E4=BF=A1=E7=9B=B8=E5=85=B3=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/impl/weixin/AbstractWxPayClient.java | 1 + .../service/social/SocialClientServiceImpl.java | 2 +- .../src/main/resources/application-local.yaml | 13 ++++++++----- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java index ada1f42e6..a8c50cf1c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java @@ -71,6 +71,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient Date: Mon, 25 Dec 2023 21:40:16 +0800 Subject: [PATCH 25/55] =?UTF-8?q?=F0=9F=93=96=20code=20review=EF=BC=9A?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pom.xml | 5 +++-- .../config/YudaoOperateLogAutoConfiguration.java | 1 + .../config/YudaoOperateLogV2Configuration.java | 1 + .../core/aop/OperateLogV2Aspect.java | 1 + .../core/enums/OperateLogV2Constants.java | 1 + .../operatelogv2/core/package-info.java | 1 - .../core/service/ILogRecordServiceImpl.java | 5 +++-- .../core/vo/OperateLogV2PageReqVO.java | 1 + .../parse/CrmIndustryParseFunction.java | 4 ++++ .../permission/core/util/CrmPermissionUtils.java | 2 ++ .../service/customer/CrmCustomerServiceImpl.java | 1 + .../permission/CrmPermissionServiceImpl.java | 1 + .../module/crm/util/CrmQueryWrapperUtils.java | 1 + .../app/activity/AppActivityController.java | 12 +++++------- .../discount/DiscountActivityService.java | 3 ++- .../system/api/logger/OperateLogApiImpl.java | 5 ++--- .../dal/dataobject/logger/OperateLogV2DO.java | 3 +++ .../operatelog/parse/AdminUserParseFunction.java | 1 + .../operatelog/parse/AreaParseFunction.java | 2 ++ yudao-server/src/main/resources/application.yaml | 16 +++++----------- 20 files changed, 40 insertions(+), 27 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml index 51ea2e04f..bb07a6bc7 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml @@ -46,9 +46,10 @@ com.google.guava guava - - + + + io.github.mouzt bizlog-sdk diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java index 0f4f48eeb..7ce824645 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java @@ -5,6 +5,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; @AutoConfiguration public class YudaoOperateLogAutoConfiguration { + // TODO @puhui999:这个是不是留着哈?因为老版本还是会留着一段时间的 //@Bean //public OperateLogAspect operateLogAspect() { // return new OperateLogAspect(); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java index a7aa3a379..195d7b9ec 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java @@ -9,6 +9,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; +// TODO @puhui999:思考了下,为了减少 starter 数量,在 security 组件里,增加一个 core/operatelog 包,然后 YudaoOperateLogV2Configuration 搞一个过去; /** * mzt-biz-log 配置类 * diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java index a4129c37c..e92178ed5 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java @@ -44,6 +44,7 @@ import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeC import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; import static cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants.*; +// TODO @puhui999:这个类,是不是可以删除哈;简化简化 /** * 拦截使用 @Operation 注解, 获取操作类型、开始时间、持续时间、方法相关信息、执行结果等信息 * 对 mzt-biz-log 日志信息进行增强 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java index b0cfe43b3..a141e50c8 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.operatelogv2.core.enums; +// TODO @puhui999:这个类,是不是可以删除哈; /** * 操作日志常量接口 * diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java deleted file mode 100644 index 2cc0c2835..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.framework.operatelogv2.core; \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java index b54e0b4f1..f801f2713 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java @@ -23,16 +23,17 @@ public class ILogRecordServiceImpl implements ILogRecordService { public void record(LogRecord logRecord) { OperateLogV2Aspect.setContent(logRecord); // 操作日志 OperateLogV2Aspect.addExtra(LogRecordContext.getVariables()); // 扩展信息 + // TODO @puhui999:这里是不是调用 operateLogApi 进行记录哈 } @Override public List queryLog(String bizNo, String type) { - return Collections.emptyList(); + throw new UnsupportedOperationException("不支持该操作,请使用 OperateLogApi 查询!"); } @Override public List queryLogByBizNo(String bizNo, String type, String subType) { - return Collections.emptyList(); + throw new UnsupportedOperationException("不支持该操作,请使用 OperateLogApi 查询!"); } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java index 8d7a535ad..a0da2e94b 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +// TODO @puhui999:这个最好每个模块自己弄哈,放这里有点怪可能 @Schema(description = "管理后台 - 操作日志分页 Request VO") @Data public class OperateLogV2PageReqVO extends PageParam { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java index 45c98918b..e515be8e0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java @@ -8,6 +8,7 @@ import org.springframework.stereotype.Component; import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; +// TODO @puhui999:还是放在 core 包下哈; /** * 自定义函数-通过行业编号获取行业信息 * @@ -29,6 +30,7 @@ public class CrmIndustryParseFunction implements IParseFunction { @Override public String apply(Object value) { +// if (ObjUtil.isEmpty(value)) TODO @puhui999 可以直接替代哈; if (value == null) { return ""; } @@ -37,10 +39,12 @@ public class CrmIndustryParseFunction implements IParseFunction { } // 获取行业信息 + // TODO @puhui999:这里可以不用 try catch 哇? try { return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, value.toString()); } catch (Exception ignored) { } return ""; } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java index 80a1654a8..50da5c584 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.system.api.permission.PermissionApi; */ public class CrmPermissionUtils { + // TODO @puhui999:isCrmAdmin。换成这个名字;因为 validate 一般是参数校验,不符合抛出异常;一般是 isXXXValid 才会返回 true false /** * 校验用户是否是 CRM 管理员 * @@ -21,6 +22,7 @@ public class CrmPermissionUtils { return SingletonManager.getPermissionApi().hasAnyRoles(getUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); } + // TODO @puhui999:这个不需要哈,直接用原本的 SecuriyUtils 去拿更方便一些; /** * 获得用户编号 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 5d8dd36b2..400e276be 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -68,6 +68,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { return customer.getId(); } + // TODO @puhui999:测试下,能不能打出用户数据的变更。啊哈,可以打完微信发我下; @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#updateReqVO.id}}", success = "更新了客户{_DIFF{#updateReqVO}}") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index e3cc4a24b..bb6136c36 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -90,6 +90,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId( transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId()); String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType()); + // TODO @puhui999:是不是并且? 不是拥有者,并且不是超管 if (oldPermission == null || !isOwner(oldPermission.getLevel()) || !CrmPermissionUtils.validateAdminUser()) { throw exception(CRM_PERMISSION_DENIED, bizTypeName); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java index 0e1ba5471..2c9353daf 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java @@ -98,6 +98,7 @@ public class CrmQueryWrapperUtils { private static class SingletonManager { private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); + private static final MybatisPlusJoinProperties MYBATIS_PLUS_JOIN_PROPERTIES = SpringUtil.getBean(MybatisPlusJoinProperties.class); public static AdminUserApi getAdminUserApi() { diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java index 6c5cec14a..ce6480bd4 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java @@ -75,10 +75,9 @@ public class AppActivityController { if (CollUtil.isEmpty(spuIds)) { return new ArrayList<>(); } - - LocalDateTime now = LocalDateTime.now(); // 获取开启的且开始的且没有结束的活动 List activityList = new ArrayList<>(); + LocalDateTime now = LocalDateTime.now(); // 1. 拼团活动 getCombinationActivities(spuIds, now, activityList); // 2. 秒杀活动 @@ -99,6 +98,7 @@ public class AppActivityController { return; } + // TODO @puhui999:AppActivityRespVO 搞个构造方法,写起来更方便一些;这样后续万一加个属性,也可以处理下哈; combinationActivities.forEach(item -> { activityList.add(new AppActivityRespVO().setId(item.getId()) .setType(PromotionTypeEnum.COMBINATION_ACTIVITY.getType()).setName(item.getName()) @@ -144,11 +144,9 @@ public class AppActivityController { List products = discountActivityService.getDiscountProductsByActivityId( convertSet(discountActivities, DiscountActivityDO::getId)); Map productMap = convertMap(products, DiscountProductDO::getActivityId, DiscountProductDO::getSpuId); - discountActivities.forEach(item -> { - activityList.add(new AppActivityRespVO().setId(item.getId()) - .setType(PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()).setName(item.getName()) - .setSpuId(productMap.get(item.getId())).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); - }); + discountActivities.forEach(item -> activityList.add(new AppActivityRespVO().setId(item.getId()) + .setType(PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()).setName(item.getName()) + .setSpuId(productMap.get(item.getId())).setStartTime(item.getStartTime()).setEndTime(item.getEndTime()))); } private void getRewardActivities(Collection spuIds, LocalDateTime now, List activityList) { diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java index d754d0d9f..e08c7e2b5 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java @@ -98,6 +98,7 @@ public interface DiscountActivityService { * @param dateTime 当前日期时间 * @return 折扣活动列表 */ - List getDiscountActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime); + List getDiscountActivityBySpuIdsAndStatusAndDateTimeLt( + Collection spuIds, Integer status, LocalDateTime dateTime); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java index ffe10b9c8..9bd502869 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java @@ -59,13 +59,12 @@ public class OperateLogApiImpl implements OperateLogApi { return BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class).setList(setUserInfo(operateLogPage.getList(), userList)); } + // TODO @puhui999:这种 convert 还是放到 convert 类里, private static List setUserInfo(List logList, List userList) { Map userMap = convertMap(userList, AdminUserDO::getId); return convertList(logList, item -> { OperateLogV2RespDTO respDTO = BeanUtils.toBean(item, OperateLogV2RespDTO.class); - findAndThen(userMap, item.getUserId(), user -> { - respDTO.setUserName(user.getNickname()); - }); + findAndThen(userMap, item.getUserId(), user -> respDTO.setUserName(user.getNickname())); return respDTO; }); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java index 656331c52..73cd20864 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java @@ -70,6 +70,7 @@ public class OperateLogV2DO extends BaseDO { * 操作模块业务编号 */ private Long bizId; + // TODO @puhui999:content 改成 action,extra 换成 String。注释就直接用 mzt,和它完全对应好了。 /** * 操作内容,记录整个操作的明细 * @@ -83,6 +84,7 @@ public class OperateLogV2DO extends BaseDO { */ @TableField(typeHandler = JacksonTypeHandler.class) private Map extra; + /** * 请求方法名 */ @@ -100,6 +102,7 @@ public class OperateLogV2DO extends BaseDO { */ private String userAgent; + // TODO @puhui999:微信已经讨论,下面的字段都不要哈; /** * Java 方法名 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java index 5685dda75..476e235c4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java @@ -27,6 +27,7 @@ public class AdminUserParseFunction implements IParseFunction { return "getAdminUserById"; } + // TODO @puhui999:这个方法的实现优化下哈; @Override public String apply(Object value) { if (value == null) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java index b63083a38..a14637c58 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java @@ -6,6 +6,7 @@ import com.mzt.logapi.service.IParseFunction; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +// TODO @puhui999:还是放在 core 包下哈; /** * 自定义函数-通过区域编号获取区域信息 * @@ -36,4 +37,5 @@ public class AreaParseFunction implements IParseFunction { return AreaUtils.format(Integer.parseInt(value.toString())); } + } diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 21b2d48c3..7462b2310 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -79,17 +79,11 @@ mybatis-plus: password: XDV71a+xqStEA3WH # 加解密的秘钥,可使用 https://www.imaegoo.com/2020/aes-key-generator/ 网站生成 mybatis-plus-join: - #是否打印 mybatis plus join banner 默认true - banner: false - #全局启用副表逻辑删除(默认true) 关闭后关联查询不会加副表逻辑删除 - sub-table-logic: true - #拦截器MappedStatement缓存(默认true) - ms-cache: true - #表别名(默认 t) - table-alias: t - #副表逻辑删除条件的位置,支持where、on - #默认ON (1.4.7.2及之前版本默认为where) - logic-del-type: on + banner: false # 是否打印 mybatis plus join banner,默认true + sub-table-logic: true # 全局启用副表逻辑删除,默认true。关闭后关联查询不会加副表逻辑删除 + ms-cache: true # 拦截器MappedStatement缓存,默认 true + table-alias: t # 表别名(默认 t) + logic-del-type: on # 副表逻辑删除条件的位置,支持 WHERE、ON,默认 ON # Spring Data Redis 配置 spring: From 2f5afdb5c946bae3a489b1cb5772f495b07b8971 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 25 Dec 2023 23:33:50 +0800 Subject: [PATCH 26/55] =?UTF-8?q?=E2=9C=A8=20Member=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BD=BF=E7=94=A8=E5=BE=AE=E4=BF=A1=E5=B0=8F=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=20code=20=E7=BB=91=E5=AE=9A=E6=89=8B=E6=9C=BA?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/AppAuthWeixinMiniAppLoginReqVO.java | 4 +- .../app/user/AppMemberUserController.java | 8 ++++ ...ppMemberUserUpdateMobileByWeixinReqVO.java | 16 +++++++ .../vo/AppMemberUserUpdateMobileReqVO.java | 8 +--- .../service/user/MemberUserService.java | 16 ++++--- .../service/user/MemberUserServiceImpl.java | 42 ++++++++++++++----- 6 files changed, 70 insertions(+), 24 deletions(-) create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileByWeixinReqVO.java diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java index fa8724cd0..15adaa8d6 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthWeixinMiniAppLoginReqVO.java @@ -15,11 +15,11 @@ import jakarta.validation.constraints.NotEmpty; @Builder public class AppAuthWeixinMiniAppLoginReqVO { - @Schema(description = "手机 code,小程序通过 wx.getPhoneNumber 方法获得", requiredMode = Schema.RequiredMode.REQUIRED, example = "hello") + @Schema(description = "手机 code,小程序通过 wx.getPhoneNumber 方法获得", requiredMode = Schema.RequiredMode.REQUIRED, example = "hello") @NotEmpty(message = "手机 code 不能为空") private String phoneCode; - @Schema(description = "登录 code,小程序通过 wx.login 方法获得", requiredMode = Schema.RequiredMode.REQUIRED, example = "word") + @Schema(description = "登录 code,小程序通过 wx.login 方法获得", requiredMode = Schema.RequiredMode.REQUIRED, example = "word") @NotEmpty(message = "登录 code 不能为空") private String loginCode; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java index 2c04a6908..91d549fa6 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppMemberUserController.java @@ -57,6 +57,14 @@ public class AppMemberUserController { return success(true); } + @PutMapping("/update-mobile-by-weixin") + @Operation(summary = "基于微信小程序的授权码,修改用户手机") + @PreAuthenticated + public CommonResult updateUserMobileByWeixin(@RequestBody @Valid AppMemberUserUpdateMobileByWeixinReqVO reqVO) { + userService.updateUserMobileByWeixin(getLoginUserId(), reqVO); + return success(true); + } + @PutMapping("/update-password") @Operation(summary = "修改用户密码", description = "用户修改密码时使用") @PreAuthenticated diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileByWeixinReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileByWeixinReqVO.java new file mode 100644 index 000000000..88d546a66 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileByWeixinReqVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.member.controller.app.user.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +@Schema(description = "用户 APP - 基于微信小程序的授权码,修改手机 Request VO") +@Data +public class AppMemberUserUpdateMobileByWeixinReqVO { + + @Schema(description = "手机 code,小程序通过 wx.getPhoneNumber 方法获得", + requiredMode = Schema.RequiredMode.REQUIRED, example = "hello") + @NotEmpty(message = "手机 code 不能为空") + private String code; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileReqVO.java index 06d27cbfd..8f4d8b64f 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateMobileReqVO.java @@ -14,9 +14,6 @@ import jakarta.validation.constraints.Pattern; @Schema(description = "用户 APP - 修改手机 Request VO") @Data -@NoArgsConstructor -@AllArgsConstructor -@Builder public class AppMemberUserUpdateMobileReqVO { @Schema(description = "手机验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @@ -25,14 +22,13 @@ public class AppMemberUserUpdateMobileReqVO { @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字") private String code; - @Schema(description = "手机号",requiredMode = Schema.RequiredMode.REQUIRED,example = "15823654487") + @Schema(description = "手机号",requiredMode = Schema.RequiredMode.REQUIRED, example = "15823654487") @NotBlank(message = "手机号不能为空") @Length(min = 8, max = 11, message = "手机号码长度为 8-11 位") @Mobile private String mobile; - @Schema(description = "原手机验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotEmpty(message = "原手机验证码不能为空") + @Schema(description = "原手机验证码", example = "1024") @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位") @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字") private String oldCode; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java index dcd71ea21..2c07d4b6e 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java @@ -5,10 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.validation.Mobile; import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO; import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO; -import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserResetPasswordReqVO; -import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateMobileReqVO; -import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdatePasswordReqVO; -import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.*; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import jakarta.validation.Valid; @@ -94,13 +91,21 @@ public interface MemberUserService { void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO); /** - * 【会员】修改手机 + * 【会员】修改手机,基于手机验证码 * * @param userId 用户编号 * @param reqVO 请求信息 */ void updateUserMobile(Long userId, AppMemberUserUpdateMobileReqVO reqVO); + /** + * 【会员】修改手机,基于微信小程序的授权码 + * + * @param userId 用户编号 + * @param reqVO 请求信息 + */ + void updateUserMobileByWeixin(Long userId, AppMemberUserUpdateMobileByWeixinReqVO reqVO); + /** * 【会员】修改密码 * @@ -181,4 +186,5 @@ public interface MemberUserService { * @return 更新结果 */ boolean updateUserPoint(Long userId, Integer point); + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java index 9fb385475..e44e8b2df 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java @@ -2,16 +2,15 @@ package cn.iocoder.yudao.module.member.service.user; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.*; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO; import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserUpdateReqVO; -import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserResetPasswordReqVO; -import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateMobileReqVO; -import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdatePasswordReqVO; -import cn.iocoder.yudao.module.member.controller.app.user.vo.AppMemberUserUpdateReqVO; +import cn.iocoder.yudao.module.member.controller.app.user.vo.*; import cn.iocoder.yudao.module.member.convert.auth.AuthConvert; import cn.iocoder.yudao.module.member.convert.user.MemberUserConvert; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; @@ -19,6 +18,8 @@ import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper; import cn.iocoder.yudao.module.member.mq.producer.user.MemberUserProducer; import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.iocoder.yudao.module.system.api.social.SocialClientApi; +import cn.iocoder.yudao.module.system.api.social.dto.SocialWxPhoneNumberInfoRespDTO; import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; @@ -54,6 +55,9 @@ public class MemberUserServiceImpl implements MemberUserService { @Resource private SmsCodeApi smsCodeApi; + @Resource + private SocialClientApi socialClientApi; + @Resource private PasswordEncoder passwordEncoder; @@ -145,22 +149,38 @@ public class MemberUserServiceImpl implements MemberUserService { @Override @Transactional(rollbackFor = Exception.class) public void updateUserMobile(Long userId, AppMemberUserUpdateMobileReqVO reqVO) { - // 检测用户是否存在 + // 1.1 检测用户是否存在 MemberUserDO user = validateUserExists(userId); - // 校验新手机是否已经被绑定 + // 1.2 校验新手机是否已经被绑定 validateMobileUnique(null, reqVO.getMobile()); - // 校验旧手机和旧验证码 - smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode()) - .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); - // 使用新验证码 + // 2.1 校验旧手机和旧验证码 + // 补充说明:从安全性来说,老手机也校验 oldCode 验证码会更安全。但是由于 uni-app 商城界面暂时没做,所以这里不强制校验 + if (StrUtil.isNotEmpty(reqVO.getOldCode())) { + smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode()) + .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); + } + // 2.2 使用新验证码 smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode()) .setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())); - // 更新用户手机 + // 3. 更新用户手机 memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build()); } + @Override + public void updateUserMobileByWeixin(Long userId, AppMemberUserUpdateMobileByWeixinReqVO reqVO) { + // 1.1 获得对应的手机号信息 + SocialWxPhoneNumberInfoRespDTO phoneNumberInfo = socialClientApi.getWxMaPhoneNumberInfo( + UserTypeEnum.MEMBER.getValue(), reqVO.getCode()); + Assert.notNull(phoneNumberInfo, "获得手机信息失败,结果为空"); + // 1.2 校验新手机是否已经被绑定 + validateMobileUnique(userId, phoneNumberInfo.getPhoneNumber()); + + // 2. 更新用户手机 + memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(phoneNumberInfo.getPhoneNumber()).build()); + } + @Override public void updateUserPassword(Long userId, AppMemberUserUpdatePasswordReqVO reqVO) { // 检测用户是否存在 From 69503689912abe6e565fd71895bc0245bd72fc2c Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 26 Dec 2023 00:04:20 +0800 Subject: [PATCH 27/55] =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97?= =?UTF-8?q?=EF=BC=9A=E5=AE=8C=E5=96=84=20code=20review=20=E6=8F=90?= =?UTF-8?q?=E5=88=B0=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pom.xml | 7 - .../YudaoOperateLogAutoConfiguration.java | 24 +- .../core/aop/OperateLogV2Aspect.java | 330 ------------------ .../core/enums/OperateLogV2Constants.java | 35 -- .../core/service/ILogRecordServiceImpl.java | 39 --- .../framework/operatelogv2/package-info.java | 1 - ...ot.autoconfigure.AutoConfiguration.imports | 3 +- .../pom.xml | 7 + .../YudaoOperateLogV2Configuration.java | 12 +- .../operatelog/core/package-info.java | 1 + .../core/service/ILogRecordServiceImpl.java | 83 +++++ ...ot.autoconfigure.AutoConfiguration.imports | 3 +- .../admin/customer/CrmCustomerController.java | 10 +- .../vo/CrmCustomerOperateLogPageReqVO.java | 7 +- .../CrmIndustryParseFunction.java | 14 +- .../CrmLevelParseFunction.java | 12 +- .../CrmSourceParseFunction.java | 12 +- .../customer/CrmCustomerServiceImpl.java | 16 +- .../logger/dto/OperateLogV2CreateReqDTO.java | 41 +-- .../api/logger/dto/OperateLogV2RespDTO.java | 46 +-- .../system/api/logger/OperateLogApiImpl.java | 18 +- .../convert/logger/OperateLogConvert.java | 19 + .../dal/dataobject/logger/OperateLogV2DO.java | 64 +--- .../AdminUserParseFunction.java | 9 +- .../{parse => core}/AreaParseFunction.java | 6 +- .../service/logger/OperateLogServiceImpl.java | 2 - .../auth/AdminAuthServiceImplTest.java | 11 +- 27 files changed, 183 insertions(+), 649 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java rename yudao-framework/{yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2 => yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog}/config/YudaoOperateLogV2Configuration.java (56%) create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/ILogRecordServiceImpl.java rename yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java => yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerOperateLogPageReqVO.java (66%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/{parse => core}/CrmIndustryParseFunction.java (65%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/{parse => core}/CrmLevelParseFunction.java (77%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/{parse => core}/CrmSourceParseFunction.java (77%) rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/{parse => core}/AdminUserParseFunction.java (79%) rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/{parse => core}/AreaParseFunction.java (84%) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml index bb07a6bc7..c52d8fc10 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/pom.xml @@ -47,13 +47,6 @@ guava - - - - io.github.mouzt - bizlog-sdk - - diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java index 7ce824645..441ec6bbd 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogAutoConfiguration.java @@ -1,19 +1,23 @@ package cn.iocoder.yudao.framework.operatelog.config; +import cn.iocoder.yudao.framework.operatelog.core.aop.OperateLogAspect; +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkService; +import cn.iocoder.yudao.framework.operatelog.core.service.OperateLogFrameworkServiceImpl; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.context.annotation.Bean; @AutoConfiguration public class YudaoOperateLogAutoConfiguration { - // TODO @puhui999:这个是不是留着哈?因为老版本还是会留着一段时间的 - //@Bean - //public OperateLogAspect operateLogAspect() { - // return new OperateLogAspect(); - //} - // - //@Bean - //public OperateLogFrameworkService operateLogFrameworkService(OperateLogApi operateLogApi) { - // return new OperateLogFrameworkServiceImpl(operateLogApi); - //} + @Bean + public OperateLogAspect operateLogAspect() { + return new OperateLogAspect(); + } + + @Bean + public OperateLogFrameworkService operateLogFrameworkService(OperateLogApi operateLogApi) { + return new OperateLogFrameworkServiceImpl(operateLogApi); + } } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java deleted file mode 100644 index e92178ed5..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/aop/OperateLogV2Aspect.java +++ /dev/null @@ -1,330 +0,0 @@ -package cn.iocoder.yudao.framework.operatelogv2.core.aop; - -import cn.hutool.core.date.LocalDateTimeUtil; -import cn.hutool.core.exceptions.ExceptionUtil; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.ObjUtil; -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; -import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; -import com.google.common.collect.Maps; -import com.mzt.logapi.beans.LogRecord; -import io.swagger.v3.oas.annotations.Operation; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.multipart.MultipartFile; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Predicate; -import java.util.stream.IntStream; - -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.SUCCESS; -import static cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants.*; - -// TODO @puhui999:这个类,是不是可以删除哈;简化简化 -/** - * 拦截使用 @Operation 注解, 获取操作类型、开始时间、持续时间、方法相关信息、执行结果等信息 - * 对 mzt-biz-log 日志信息进行增强 - * - * @author HUIHUI - */ -@Aspect -@Slf4j -public class OperateLogV2Aspect { - - /** - * 用于记录操作内容的上下文 - * - * @see OperateLogV2CreateReqDTO#getContent() - */ - private static final ThreadLocal CONTENT = new ThreadLocal<>(); - /** - * 用于记录拓展字段的上下文 - * - * @see OperateLogV2CreateReqDTO#getExtra() - */ - private static final ThreadLocal> EXTRA = new ThreadLocal<>(); - - @Resource - private OperateLogApi operateLogApi; - - @Around("@annotation(operation)") - public Object around(ProceedingJoinPoint joinPoint, Operation operation) throws Throwable { - RequestMethod requestMethod = obtainFirstMatchRequestMethod(obtainRequestMethod(joinPoint)); - if (requestMethod == RequestMethod.GET) { // 跳过 get 方法 - return joinPoint.proceed(); - } - - // 目前,只有管理员,才记录操作日志!所以非管理员,直接调用,不进行记录 - Integer userType = WebFrameworkUtils.getLoginUserType(); - if (ObjUtil.notEqual(userType, UserTypeEnum.ADMIN.getValue())) { - return joinPoint.proceed(); - } - - // 记录开始时间 - LocalDateTime startTime = LocalDateTime.now(); - try { - // 执行原有方法 - Object result = joinPoint.proceed(); - // 记录正常执行时的操作日志 - this.log(joinPoint, operation, startTime, result, null); - return result; - } catch (Throwable exception) { - this.log(joinPoint, operation, startTime, null, exception); - throw exception; - } finally { - clearThreadLocal(); - } - } - - public static void setContent(LogRecord content) { - CONTENT.set(content); - } - - public static void addExtra(String key, Object value) { - if (EXTRA.get() == null) { - EXTRA.set(new HashMap<>()); - } - EXTRA.get().put(key, value); - } - - public static void addExtra(Map extra) { - if (EXTRA.get() == null) { - EXTRA.set(new HashMap<>()); - } - EXTRA.get().putAll(extra); - } - - private static void clearThreadLocal() { - CONTENT.remove(); - EXTRA.remove(); - } - - private void log(ProceedingJoinPoint joinPoint, Operation operation, - LocalDateTime startTime, Object result, Throwable exception) { - try { - // 判断不记录的情况(默认没有值就是记录) - if (EXTRA.get() != null && EXTRA.get().get(ENABLE) != null) { - return; - } - if (CONTENT.get() == null) { // 没有值说明没有日志需要记录 - return; - } - - // 真正记录操作日志 - this.log0(joinPoint, operation, startTime, result, exception); - } catch (Throwable ex) { - log.error("[log][记录操作日志时,发生异常,其中参数是 joinPoint({}) apiOperation({}) result({}) exception({}) ]", - joinPoint, operation, result, exception, ex); - } - } - - private void log0(ProceedingJoinPoint joinPoint, Operation operation, - LocalDateTime startTime, Object result, Throwable exception) { - OperateLogV2CreateReqDTO reqDTO = new OperateLogV2CreateReqDTO(); - // 补全通用字段 - reqDTO.setTraceId(TracerUtils.getTraceId()); - reqDTO.setStartTime(startTime); - // 补充用户信息 - fillUserFields(reqDTO); - // 补全模块信息 - fillModuleFields(reqDTO, operation); - // 补全请求信息 - fillRequestFields(reqDTO); - // 补全方法信息 - fillMethodFields(reqDTO, joinPoint, startTime, result, exception); - - // 异步记录日志 - operateLogApi.createOperateLogV2(reqDTO); - } - - private static void fillUserFields(OperateLogV2CreateReqDTO reqDTO) { - reqDTO.setUserId(WebFrameworkUtils.getLoginUserId()); - reqDTO.setUserType(WebFrameworkUtils.getLoginUserType()); - } - - private static void fillModuleFields(OperateLogV2CreateReqDTO reqDTO, Operation operation) { - LogRecord logRecord = CONTENT.get(); - reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 - reqDTO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 - - // type 属性 - reqDTO.setType(logRecord.getType()); // 大模块类型如 crm 客户 - // subType 属性 - if (logRecord.getSubType() != null) { - reqDTO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 - } - if (StrUtil.isEmpty(reqDTO.getSubType()) && operation != null) { - reqDTO.setSubType(operation.summary()); - } - - // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} - Map objectMap = EXTRA.get(); - if (objectMap != null) { - Object object = objectMap.get(EXTRA_KEY); - if (object instanceof Map extraMap) { - if (extraMap.keySet().stream().allMatch(String.class::isInstance)) { - @SuppressWarnings("unchecked") - Map extra = (Map) extraMap; - reqDTO.setExtra(extra); - return; - } - } - // 激进一点不是 map 直接当 value 处理 - Map extra = Maps.newHashMapWithExpectedSize(1); - extra.put(EXTRA_KEY, object); - reqDTO.setExtra(extra); - } - - } - - private static void fillRequestFields(OperateLogV2CreateReqDTO reqDTO) { - // 获得 Request 对象 - HttpServletRequest request = ServletUtils.getRequest(); - if (request == null) { - return; - } - // 补全请求信息 - reqDTO.setRequestMethod(request.getMethod()); - reqDTO.setRequestUrl(request.getRequestURI()); - reqDTO.setUserIp(ServletUtils.getClientIP(request)); - reqDTO.setUserAgent(ServletUtils.getUserAgent(request)); - } - - private static void fillMethodFields(OperateLogV2CreateReqDTO reqDTO, ProceedingJoinPoint joinPoint, LocalDateTime startTime, - Object result, Throwable exception) { - MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); - reqDTO.setJavaMethod(methodSignature.toString()); - if (EXTRA.get().get(IS_LOG_ARGS) == null) { - reqDTO.setJavaMethodArgs(obtainMethodArgs(joinPoint)); - } - if (EXTRA.get().get(IS_LOG_RESULT_DATA) == null) { - reqDTO.setResultData(obtainResultData(result)); - } - reqDTO.setDuration((int) (LocalDateTimeUtil.between(startTime, LocalDateTime.now()).toMillis())); - // (正常)处理 resultCode 和 resultMsg 字段 - if (result instanceof CommonResult) { - CommonResult commonResult = (CommonResult) result; - reqDTO.setResultCode(commonResult.getCode()); - reqDTO.setResultMsg(commonResult.getMsg()); - } else { - reqDTO.setResultCode(SUCCESS.getCode()); - } - // (异常)处理 resultCode 和 resultMsg 字段 - if (exception != null) { - reqDTO.setResultCode(INTERNAL_SERVER_ERROR.getCode()); - reqDTO.setResultMsg(ExceptionUtil.getRootCauseMessage(exception)); - } - } - - @SuppressWarnings("SameParameterValue") - private static T getClassAnnotation(ProceedingJoinPoint joinPoint, Class annotationClass) { - return ((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaringClass().getAnnotation(annotationClass); - } - - private static String obtainMethodArgs(ProceedingJoinPoint joinPoint) { - // TODO 提升:参数脱敏和忽略 - MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); - String[] argNames = methodSignature.getParameterNames(); - Object[] argValues = joinPoint.getArgs(); - // 拼接参数 - Map args = Maps.newHashMapWithExpectedSize(argValues.length); - for (int i = 0; i < argNames.length; i++) { - String argName = argNames[i]; - Object argValue = argValues[i]; - // 被忽略时,标记为 ignore 字符串,避免和 null 混在一起 - args.put(argName, !isIgnoreArgs(argValue) ? argValue : "[ignore]"); - } - return JsonUtils.toJsonString(args); - } - - private static String obtainResultData(Object result) { - // TODO 提升:结果脱敏和忽略 - if (result instanceof CommonResult) { - result = ((CommonResult) result).getData(); - } - return JsonUtils.toJsonString(result); - } - - private static boolean isIgnoreArgs(Object object) { - Class clazz = object.getClass(); - // 处理数组的情况 - if (clazz.isArray()) { - return IntStream.range(0, Array.getLength(object)) - .anyMatch(index -> isIgnoreArgs(Array.get(object, index))); - } - // 递归,处理数组、Collection、Map 的情况 - if (Collection.class.isAssignableFrom(clazz)) { - return ((Collection) object).stream() - .anyMatch((Predicate) OperateLogV2Aspect::isIgnoreArgs); - } - if (Map.class.isAssignableFrom(clazz)) { - return isIgnoreArgs(((Map) object).values()); - } - // obj - return object instanceof MultipartFile - || object instanceof HttpServletRequest - || object instanceof HttpServletResponse - || object instanceof BindingResult; - } - - private static RequestMethod obtainFirstMatchRequestMethod(RequestMethod[] requestMethods) { - if (ArrayUtil.isEmpty(requestMethods)) { - return null; - } - // 优先,匹配最优的 POST、PUT、DELETE - RequestMethod result = obtainFirstLogRequestMethod(requestMethods); - if (result != null) { - return result; - } - // 然后,匹配次优的 GET - result = Arrays.stream(requestMethods).filter(requestMethod -> requestMethod == RequestMethod.GET) - .findFirst().orElse(null); - if (result != null) { - return result; - } - // 兜底,获得第一个 - return requestMethods[0]; - } - - private static RequestMethod[] obtainRequestMethod(ProceedingJoinPoint joinPoint) { - RequestMapping requestMapping = AnnotationUtils.getAnnotation( // 使用 Spring 的工具类,可以处理 @RequestMapping 别名注解 - ((MethodSignature) joinPoint.getSignature()).getMethod(), RequestMapping.class); - return requestMapping != null ? requestMapping.method() : new RequestMethod[]{}; - } - - private static RequestMethod obtainFirstLogRequestMethod(RequestMethod[] requestMethods) { - if (ArrayUtil.isEmpty(requestMethods)) { - return null; - } - return Arrays.stream(requestMethods).filter(requestMethod -> - requestMethod == RequestMethod.POST - || requestMethod == RequestMethod.PUT - || requestMethod == RequestMethod.DELETE) - .findFirst().orElse(null); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java deleted file mode 100644 index a141e50c8..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/enums/OperateLogV2Constants.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.framework.operatelogv2.core.enums; - -// TODO @puhui999:这个类,是不是可以删除哈; -/** - * 操作日志常量接口 - * - * @author HUIHUI - */ -public interface OperateLogV2Constants { - - // ========== 开关字段-如果没有值默认就是记录 ========== - - /** - * 是否记录日志 - */ - String ENABLE = "enable"; - - /** - * 是否记录方法参数 - */ - String IS_LOG_ARGS = "isLogArgs"; - - /** - * 是否记录方法结果的数据 - */ - String IS_LOG_RESULT_DATA = "isLogResultData"; - - // ========== 扩展 ========== - - /** - * 扩展信息 - */ - String EXTRA_KEY = "extra"; - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java deleted file mode 100644 index f801f2713..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/service/ILogRecordServiceImpl.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.framework.operatelogv2.core.service; - -import cn.iocoder.yudao.framework.operatelogv2.core.aop.OperateLogV2Aspect; -import com.mzt.logapi.beans.LogRecord; -import com.mzt.logapi.context.LogRecordContext; -import com.mzt.logapi.service.ILogRecordService; -import lombok.extern.slf4j.Slf4j; - -import java.util.Collections; -import java.util.List; - -/** - * 操作日志 ILogRecordService 实现类 - * - * 基于 {@link OperateLogV2Aspect} 实现,记录操作日志 - * - * @author HUIHUI - */ -@Slf4j -public class ILogRecordServiceImpl implements ILogRecordService { - - @Override - public void record(LogRecord logRecord) { - OperateLogV2Aspect.setContent(logRecord); // 操作日志 - OperateLogV2Aspect.addExtra(LogRecordContext.getVariables()); // 扩展信息 - // TODO @puhui999:这里是不是调用 operateLogApi 进行记录哈 - } - - @Override - public List queryLog(String bizNo, String type) { - throw new UnsupportedOperationException("不支持该操作,请使用 OperateLogApi 查询!"); - } - - @Override - public List queryLogByBizNo(String bizNo, String type, String subType) { - throw new UnsupportedOperationException("不支持该操作,请使用 OperateLogApi 查询!"); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java deleted file mode 100644 index 439ddc3de..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.framework.operatelogv2; \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 3fb6d2cc9..04ccab1cd 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1 @@ -cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration -cn.iocoder.yudao.framework.operatelogv2.config.YudaoOperateLogV2Configuration \ No newline at end of file +cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-security/pom.xml b/yudao-framework/yudao-spring-boot-starter-security/pom.xml index 864f1f101..4457227ae 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-security/pom.xml @@ -50,6 +50,13 @@ guava + + + + io.github.mouzt + bizlog-sdk + + cn.iocoder.boot diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogV2Configuration.java similarity index 56% rename from yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java rename to yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogV2Configuration.java index 195d7b9ec..f5610bd28 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/config/YudaoOperateLogV2Configuration.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogV2Configuration.java @@ -1,7 +1,6 @@ -package cn.iocoder.yudao.framework.operatelogv2.config; +package cn.iocoder.yudao.framework.operatelog.config; -import cn.iocoder.yudao.framework.operatelogv2.core.aop.OperateLogV2Aspect; -import cn.iocoder.yudao.framework.operatelogv2.core.service.ILogRecordServiceImpl; +import cn.iocoder.yudao.framework.operatelog.core.service.ILogRecordServiceImpl; import com.mzt.logapi.service.ILogRecordService; import com.mzt.logapi.starter.annotation.EnableLogRecord; import lombok.extern.slf4j.Slf4j; @@ -9,7 +8,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; -// TODO @puhui999:思考了下,为了减少 starter 数量,在 security 组件里,增加一个 core/operatelog 包,然后 YudaoOperateLogV2Configuration 搞一个过去; + /** * mzt-biz-log 配置类 * @@ -26,9 +25,4 @@ public class YudaoOperateLogV2Configuration { return new ILogRecordServiceImpl(); } - @Bean - public OperateLogV2Aspect operateLogV2Aspect() { - return new OperateLogV2Aspect(); - } - } diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java new file mode 100644 index 000000000..1a87fb84d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.framework.operatelog.core; \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/ILogRecordServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/ILogRecordServiceImpl.java new file mode 100644 index 000000000..4b4702c45 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/ILogRecordServiceImpl.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.framework.operatelog.core.service; + +import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; +import com.mzt.logapi.beans.LogRecord; +import com.mzt.logapi.service.ILogRecordService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; + +import java.util.Collections; +import java.util.List; + +/** + * 操作日志 ILogRecordService 实现类 + * + * 基于 {@link OperateLogApi} 实现,记录操作日志 + * + * @author HUIHUI + */ +@Slf4j +public class ILogRecordServiceImpl implements ILogRecordService { + + @Resource + private OperateLogApi operateLogApi; + + @Override + public void record(LogRecord logRecord) { + OperateLogV2CreateReqDTO reqDTO = new OperateLogV2CreateReqDTO(); + // 补全通用字段 + reqDTO.setTraceId(TracerUtils.getTraceId()); + // 补充用户信息 + fillUserFields(reqDTO); + // 补全模块信息 + fillModuleFields(reqDTO, logRecord); + // 补全请求信息 + fillRequestFields(reqDTO); + // 异步记录日志 + operateLogApi.createOperateLogV2(reqDTO); + // TODO 测试结束删除或搞个开关 + log.info("操作日志 ===> {}", reqDTO); + } + + private static void fillUserFields(OperateLogV2CreateReqDTO reqDTO) { + reqDTO.setUserId(WebFrameworkUtils.getLoginUserId()); + reqDTO.setUserType(WebFrameworkUtils.getLoginUserType()); + } + + public static void fillModuleFields(OperateLogV2CreateReqDTO reqDTO, LogRecord logRecord) { + reqDTO.setType(logRecord.getType()); // 大模块类型如 crm 客户 + reqDTO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 + reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 + reqDTO.setAction(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 + reqDTO.setExtra(logRecord.getExtra()); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} + } + + private static void fillRequestFields(OperateLogV2CreateReqDTO reqDTO) { + // 获得 Request 对象 + HttpServletRequest request = ServletUtils.getRequest(); + if (request == null) { + return; + } + // 补全请求信息 + reqDTO.setRequestMethod(request.getMethod()); + reqDTO.setRequestUrl(request.getRequestURI()); + reqDTO.setUserIp(ServletUtils.getClientIP(request)); + reqDTO.setUserAgent(ServletUtils.getUserAgent(request)); + } + + @Override + public List queryLog(String bizNo, String type) { + return Collections.emptyList(); + } + + @Override + public List queryLogByBizNo(String bizNo, String type, String subType) { + return Collections.emptyList(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index f64277f01..c66f41985 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,2 +1,3 @@ cn.iocoder.yudao.framework.security.config.YudaoSecurityAutoConfiguration -cn.iocoder.yudao.framework.security.config.YudaoWebSecurityConfigurerAdapter \ No newline at end of file +cn.iocoder.yudao.framework.security.config.YudaoWebSecurityConfigurerAdapter +cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogV2Configuration \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 2580f9584..87d836595 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.framework.operatelogv2.core.vo.OperateLogV2PageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -61,6 +60,7 @@ public class CrmCustomerController { @PostMapping("/create") @Operation(summary = "创建客户") + @OperateLog(enable = false) // TODO 关闭原有日志记录 @PreAuthorize("@ss.hasPermission('crm:customer:create')") public CommonResult createCustomer(@Valid @RequestBody CrmCustomerCreateReqVO createReqVO) { return success(customerService.createCustomer(createReqVO, getLoginUserId())); @@ -68,6 +68,7 @@ public class CrmCustomerController { @PutMapping("/update") @Operation(summary = "更新客户") + @OperateLog(enable = false) // TODO 关闭原有日志记录 @PreAuthorize("@ss.hasPermission('crm:customer:update')") public CommonResult updateCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { customerService.updateCustomer(updateReqVO); @@ -76,6 +77,7 @@ public class CrmCustomerController { @DeleteMapping("/delete") @Operation(summary = "删除客户") + @OperateLog(enable = false) // TODO 关闭原有日志记录 @Parameter(name = "id", description = "编号", required = true) @PreAuthorize("@ss.hasPermission('crm:customer:delete')") public CommonResult deleteCustomer(@RequestParam("id") Long id) { @@ -132,6 +134,7 @@ public class CrmCustomerController { @PutMapping("/transfer") @Operation(summary = "客户转移") + @OperateLog(enable = false) // TODO 关闭原有日志记录 @PreAuthorize("@ss.hasPermission('crm:customer:update')") public CommonResult transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { customerService.transferCustomer(reqVO, getLoginUserId()); @@ -140,9 +143,8 @@ public class CrmCustomerController { @GetMapping("/operate-log-page") @Operation(summary = "获得客户操作日志") - @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('crm:customer:query')") - public CommonResult> getCustomerOperateLog(OperateLogV2PageReqVO reqVO) { + public CommonResult> getCustomerOperateLog(CrmCustomerOperateLogPageReqVO reqVO) { reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 reqVO.setBizType(CRM_CUSTOMER); return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); @@ -151,6 +153,7 @@ public class CrmCustomerController { // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; @PutMapping("/lock") @Operation(summary = "锁定/解锁客户") + @OperateLog(enable = false) // TODO 关闭原有日志记录 @PreAuthorize("@ss.hasPermission('crm:customer:update')") public CommonResult lockCustomer(@Valid @RequestBody CrmCustomerUpdateReqVO updateReqVO) { customerService.lockCustomer(updateReqVO); @@ -161,6 +164,7 @@ public class CrmCustomerController { @PutMapping("/put-pool") @Operation(summary = "数据放入公海") + @OperateLog(enable = false) // TODO 关闭原有日志记录 @Parameter(name = "id", description = "客户编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('crm:customer:update')") public CommonResult putCustomerPool(@RequestParam("id") Long id) { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerOperateLogPageReqVO.java similarity index 66% rename from yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerOperateLogPageReqVO.java index a0da2e94b..c23c8d01a 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelogv2/core/vo/OperateLogV2PageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerOperateLogPageReqVO.java @@ -1,13 +1,12 @@ -package cn.iocoder.yudao.framework.operatelogv2.core.vo; +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -// TODO @puhui999:这个最好每个模块自己弄哈,放这里有点怪可能 -@Schema(description = "管理后台 - 操作日志分页 Request VO") +@Schema(description = "管理后台 - crm 客户操作日志分页 Request VO") @Data -public class OperateLogV2PageReqVO extends PageParam { +public class CrmCustomerOperateLogPageReqVO extends PageParam { @Schema(description = "模块数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long bizId; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmIndustryParseFunction.java similarity index 65% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmIndustryParseFunction.java index e515be8e0..67abc71b6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmIndustryParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmIndustryParseFunction.java @@ -1,5 +1,6 @@ -package cn.iocoder.yudao.module.crm.framework.operatelog.parse; +package cn.iocoder.yudao.module.crm.framework.operatelog.core; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import com.mzt.logapi.service.IParseFunction; @@ -8,7 +9,6 @@ import org.springframework.stereotype.Component; import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; -// TODO @puhui999:还是放在 core 包下哈; /** * 自定义函数-通过行业编号获取行业信息 * @@ -30,8 +30,7 @@ public class CrmIndustryParseFunction implements IParseFunction { @Override public String apply(Object value) { -// if (ObjUtil.isEmpty(value)) TODO @puhui999 可以直接替代哈; - if (value == null) { + if (ObjUtil.isEmpty(value)) { return ""; } if (StrUtil.isEmpty(value.toString())) { @@ -39,12 +38,7 @@ public class CrmIndustryParseFunction implements IParseFunction { } // 获取行业信息 - // TODO @puhui999:这里可以不用 try catch 哇? - try { - return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, value.toString()); - } catch (Exception ignored) { - } - return ""; + return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, value.toString()); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmLevelParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmLevelParseFunction.java similarity index 77% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmLevelParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmLevelParseFunction.java index bb0e23205..22e6b9423 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmLevelParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmLevelParseFunction.java @@ -1,5 +1,6 @@ -package cn.iocoder.yudao.module.crm.framework.operatelog.parse; +package cn.iocoder.yudao.module.crm.framework.operatelog.core; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import com.mzt.logapi.service.IParseFunction; @@ -29,7 +30,7 @@ public class CrmLevelParseFunction implements IParseFunction { @Override public String apply(Object value) { - if (value == null) { + if (ObjUtil.isEmpty(value)) { return ""; } if (StrUtil.isEmpty(value.toString())) { @@ -37,10 +38,7 @@ public class CrmLevelParseFunction implements IParseFunction { } // 获取客户等级信息 - try { - return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_LEVEL, value.toString()); - } catch (Exception ignored) { - } - return ""; + return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_LEVEL, value.toString()); } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmSourceParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSourceParseFunction.java similarity index 77% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmSourceParseFunction.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSourceParseFunction.java index eeb5a5674..46696cfd8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/parse/CrmSourceParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSourceParseFunction.java @@ -1,5 +1,6 @@ -package cn.iocoder.yudao.module.crm.framework.operatelog.parse; +package cn.iocoder.yudao.module.crm.framework.operatelog.core; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import com.mzt.logapi.service.IParseFunction; @@ -29,7 +30,7 @@ public class CrmSourceParseFunction implements IParseFunction { @Override public String apply(Object value) { - if (value == null) { + if (ObjUtil.isEmpty(value)) { return ""; } if (StrUtil.isEmpty(value.toString())) { @@ -37,10 +38,7 @@ public class CrmSourceParseFunction implements IParseFunction { } // 获取客户来源信息 - try { - return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_SOURCE, value.toString()); - } catch (Exception ignored) { - } - return ""; + return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_SOURCE, value.toString()); } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 400e276be..c9d19ceaf 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.crm.service.customer; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.operatelogv2.core.enums.OperateLogV2Constants; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; @@ -53,7 +52,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#customerId}}", success = "创建了客户") + @LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户") public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { // 插入 CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO); @@ -71,7 +70,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // TODO @puhui999:测试下,能不能打出用户数据的变更。啊哈,可以打完微信发我下; @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#updateReqVO.id}}", success = "更新了客户{_DIFF{#updateReqVO}}") + @LogRecord(type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}", success = "更新了客户{_DIFF{#updateReqVO}}", extra = "{{#extra}}") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { // 校验存在 @@ -83,14 +82,15 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // __DIFF 函数传递了一个参数,传递的参数是修改之后的对象,这种方式需要在方法内部向 LogRecordContext 中 put 一个变量,代表是之前的对象,这个对象可以是null LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomerDO, CrmCustomerUpdateReqVO.class)); + // TODO 扩展信息测试 HashMap extra = new HashMap<>(); extra.put("tips", "随便记录一点啦"); - LogRecordContext.putVariable(OperateLogV2Constants.EXTRA_KEY, extra); + LogRecordContext.putVariable("extra", extra); } @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#id}}", success = "删除了客户") + @LogRecord(type = CRM_CUSTOMER, subType = "删除客户", bizNo = "{{#id}}", success = "删除了客户") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteCustomer(Long id) { // 校验存在 @@ -141,7 +141,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) + @LogRecord(type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { // 1. 校验客户是否存在 @@ -158,7 +158,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override - @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#updateReqVO.id}}", success = "锁定了客户") + @LogRecord(type = CRM_CUSTOMER, subType = "锁定/解锁客户", bizNo = "{{#updateReqVO.id}}", success = "锁定了客户") public void lockCustomer(CrmCustomerUpdateReqVO updateReqVO) { // 校验存在 validateCustomerExists(updateReqVO.getId()); @@ -172,7 +172,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_CUSTOMER, bizNo = "{{#id}}", success = "将客户放入了公海") + @LogRecord(type = CRM_CUSTOMER, subType = "客户放入公海", bizNo = "{{#id}}", success = "将客户放入了公海") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void putCustomerPool(Long id) { // 1. 校验存在 diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java index bab21a0dc..e8c7616a4 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2CreateReqDTO.java @@ -5,9 +5,6 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; -import java.time.LocalDateTime; -import java.util.Map; - /** * 系统操作日志 Create Req BO * @@ -56,12 +53,12 @@ public class OperateLogV2CreateReqDTO { * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 */ @NotEmpty(message = "操作内容不能为空") - private String content; + private String action; /** * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) * 例如说,记录订单编号,{ orderId: "1"} */ - private Map extra; + private String extra; /** * 请求方法名 @@ -84,38 +81,4 @@ public class OperateLogV2CreateReqDTO { @NotEmpty(message = "浏览器 UA 不能为空") private String userAgent; - /** - * Java 方法名 - */ - private String javaMethod; - /** - * Java 方法的参数 - */ - private String javaMethodArgs; - - /** - * 开始时间 - */ - private LocalDateTime startTime; - - /** - * 执行时长,单位:毫秒 - */ - private Integer duration; - - /** - * 结果码 - */ - private Integer resultCode; - - /** - * 结果提示 - */ - private String resultMsg; - - /** - * 结果数据 - */ - private String resultData; - } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java index 17dfeb491..6345965a3 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java @@ -2,9 +2,6 @@ package cn.iocoder.yudao.module.system.api.logger.dto; import lombok.Data; -import java.time.LocalDateTime; -import java.util.Map; - /** * 系统操作日志 Resp DTO * @@ -44,11 +41,11 @@ public class OperateLogV2RespDTO { /** * 操作内容 */ - private String content; + private String action; /** * 拓展字段 */ - private Map extra; + private String extra; /** * 请求方法名 @@ -67,43 +64,4 @@ public class OperateLogV2RespDTO { */ private String userAgent; - /** - * Java 方法名 - */ - private String javaMethod; - /** - * Java 方法的参数 - */ - private String javaMethodArgs; - - /** - * 开始时间 - */ - private LocalDateTime startTime; - - /** - * 执行时长,单位:毫秒 - */ - private Integer duration; - - /** - * 结果码 - */ - private Integer resultCode; - - /** - * 结果提示 - */ - private String resultMsg; - - /** - * 结果数据 - */ - private String resultData; - - /** - * 创建时间 - */ - private LocalDateTime createTime; - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java index 9bd502869..5d8a0dc16 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.system.api.logger; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2CreateReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; +import cn.iocoder.yudao.module.system.convert.logger.OperateLogConvert; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.logger.OperateLogService; @@ -17,10 +17,8 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.util.List; -import java.util.Map; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; /** * 操作日志 API 实现类 @@ -56,17 +54,7 @@ public class OperateLogApiImpl implements OperateLogApi { // 获取用户 List userList = adminUserService.getUserList(convertSet(operateLogPage.getList(), OperateLogV2DO::getUserId)); - return BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class).setList(setUserInfo(operateLogPage.getList(), userList)); - } - - // TODO @puhui999:这种 convert 还是放到 convert 类里, - private static List setUserInfo(List logList, List userList) { - Map userMap = convertMap(userList, AdminUserDO::getId); - return convertList(logList, item -> { - OperateLogV2RespDTO respDTO = BeanUtils.toBean(item, OperateLogV2RespDTO.class); - findAndThen(userMap, item.getUserId(), user -> respDTO.setUserName(user.getNickname())); - return respDTO; - }); + return OperateLogConvert.INSTANCE.convertPage(operateLogPage, userList); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java index 7b3aff8c0..93fc1c638 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/logger/OperateLogConvert.java @@ -1,10 +1,13 @@ package cn.iocoder.yudao.module.system.convert.logger; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; +import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogV2DO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -12,6 +15,9 @@ import org.mapstruct.factory.Mappers; import java.util.List; import java.util.Map; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; + @Mapper public interface OperateLogConvert { @@ -25,4 +31,17 @@ public interface OperateLogConvert { }); } + default PageResult convertPage(PageResult operateLogPage, List userList) { + return BeanUtils.toBean(operateLogPage, OperateLogV2RespDTO.class).setList(setUserInfo(operateLogPage.getList(), userList)); + } + + private static List setUserInfo(List logList, List userList) { + Map userMap = convertMap(userList, AdminUserDO::getId); + return CollectionUtils.convertList(logList, item -> { + OperateLogV2RespDTO respDTO = BeanUtils.toBean(item, OperateLogV2RespDTO.class); + findAndThen(userMap, item.getUserId(), user -> respDTO.setUserName(user.getNickname())); + return respDTO; + }); + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java index 73cd20864..2b3741660 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java @@ -1,19 +1,13 @@ package cn.iocoder.yudao.module.system.dal.dataobject.logger; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import lombok.Data; import lombok.EqualsAndHashCode; -import java.time.LocalDateTime; -import java.util.Map; - /** * 操作日志表 V2 * @@ -25,16 +19,6 @@ import java.util.Map; @EqualsAndHashCode(callSuper = true) public class OperateLogV2DO extends BaseDO { - /** - * {@link #javaMethodArgs} 的最大长度 - */ - public static final Integer JAVA_METHOD_ARGS_MAX_LENGTH = 8000; - - /** - * {@link #resultData} 的最大长度 - */ - public static final Integer RESULT_MAX_LENGTH = 4000; - /** * 日志主键 */ @@ -70,20 +54,18 @@ public class OperateLogV2DO extends BaseDO { * 操作模块业务编号 */ private Long bizId; - // TODO @puhui999:content 改成 action,extra 换成 String。注释就直接用 mzt,和它完全对应好了。 /** - * 操作内容,记录整个操作的明细 + * 日志内容,记录整个操作的明细 * * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 */ - private String content; + private String action; /** * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) * * 例如说,记录订单编号,{ orderId: "1"} */ - @TableField(typeHandler = JacksonTypeHandler.class) - private Map extra; + private String extra; /** * 请求方法名 @@ -102,44 +84,4 @@ public class OperateLogV2DO extends BaseDO { */ private String userAgent; - // TODO @puhui999:微信已经讨论,下面的字段都不要哈; - /** - * Java 方法名 - */ - private String javaMethod; - /** - * Java 方法的参数 - * - * 实际格式为 Map - * 不使用 @TableField(typeHandler = FastjsonTypeHandler.class) 注解的原因是,数据库存储有长度限制,会进行裁剪,会导致 JSON 反序列化失败 - * 其中,key 为参数名,value 为参数值 - */ - private String javaMethodArgs; - /** - * 开始时间 - */ - private LocalDateTime startTime; - /** - * 执行时长,单位:毫秒 - */ - private Integer duration; - /** - * 结果码 - * - * 目前使用的 {@link CommonResult#getCode()} 属性 - */ - private Integer resultCode; - /** - * 结果提示 - * - * 目前使用的 {@link CommonResult#getMsg()} 属性 - */ - private String resultMsg; - /** - * 结果数据 - * - * 如果是对象,则使用 JSON 格式化 - */ - private String resultData; - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AdminUserParseFunction.java similarity index 79% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AdminUserParseFunction.java index 476e235c4..858cc96b9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AdminUserParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AdminUserParseFunction.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.framework.operatelog.parse; +package cn.iocoder.yudao.module.system.framework.operatelog.core; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; @@ -9,7 +9,6 @@ import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -// TODO @puhui999:这个微信讨论下,function 叫啥好哈; /** * 自定义函数-通过用户编号获取用户信息 * @@ -27,15 +26,12 @@ public class AdminUserParseFunction implements IParseFunction { return "getAdminUserById"; } - // TODO @puhui999:这个方法的实现优化下哈; @Override public String apply(Object value) { - if (value == null) { - //log.warn("(getAdminUserById) 解析异常参数为 null"); + if (ObjUtil.isEmpty(value)) { return ""; } if (StrUtil.isEmpty(value.toString())) { - //log.warn("(getAdminUserById) 解析异常参数为空"); return ""; } @@ -52,4 +48,5 @@ public class AdminUserParseFunction implements IParseFunction { } return nickname; } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AreaParseFunction.java similarity index 84% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AreaParseFunction.java index a14637c58..71051bfe2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/parse/AreaParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AreaParseFunction.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.module.system.framework.operatelog.parse; +package cn.iocoder.yudao.module.system.framework.operatelog.core; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import com.mzt.logapi.service.IParseFunction; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -// TODO @puhui999:还是放在 core 包下哈; /** * 自定义函数-通过区域编号获取区域信息 * @@ -28,7 +28,7 @@ public class AreaParseFunction implements IParseFunction { @Override public String apply(Object value) { - if (value == null) { + if (ObjUtil.isEmpty(value)) { return ""; } if (StrUtil.isEmpty(value.toString())) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java index 76532af87..f66e9a0ae 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java @@ -71,8 +71,6 @@ public class OperateLogServiceImpl implements OperateLogService { @Override public void createOperateLogV2(OperateLogV2CreateReqDTO createReqBO) { OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class); - log.setJavaMethodArgs(StrUtils.maxLength(log.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH)); - log.setResultData(StrUtils.maxLength(log.getResultData(), RESULT_MAX_LENGTH)); operateLogV2Mapper.insert(log); } diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java index a731d9ab5..344ae13af 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java @@ -21,15 +21,14 @@ import cn.iocoder.yudao.module.system.service.social.SocialUserService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; import com.xingyuv.captcha.model.common.ResponseModel; import com.xingyuv.captcha.service.CaptchaService; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; - import jakarta.annotation.Resource; import jakarta.validation.ConstraintViolationException; import jakarta.validation.Validation; import jakarta.validation.Validator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; @@ -237,7 +236,7 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest { // mock 方法(绑定的用户编号) Long userId = 1L; when(socialUserService.getSocialUserByCode(eq(UserTypeEnum.ADMIN.getValue()), eq(reqVO.getType()), - eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(new SocialUserRespDTO(randomString(), userId)); + eq(reqVO.getCode()), eq(reqVO.getState()))).thenReturn(new SocialUserRespDTO(randomString(), randomString(), randomString(), userId)); // mock(用户) AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(userId)); when(userService.getUser(eq(userId))).thenReturn(user); From e5377074d5c51fd0f2242b6ad234f12b1085d372 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 26 Dec 2023 00:21:04 +0800 Subject: [PATCH 28/55] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90?= =?UTF-8?q?=EF=BC=9A=E5=AE=8C=E5=96=84=20code=20review=20=E6=8F=90?= =?UTF-8?q?=E5=88=B0=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/aop/CrmPermissionAspect.java | 2 +- .../core/util/CrmPermissionUtils.java | 19 ++++---------- .../customer/CrmCustomerServiceImpl.java | 1 - .../permission/CrmPermissionServiceImpl.java | 3 +-- .../module/crm/util/CrmQueryWrapperUtils.java | 4 +-- .../app/activity/AppActivityController.java | 26 +++++++------------ .../app/activity/vo/AppActivityRespVO.java | 4 +++ 7 files changed, 23 insertions(+), 36 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java index 40bae7b98..b6fef8c62 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/aop/CrmPermissionAspect.java @@ -50,7 +50,7 @@ public class CrmPermissionAspect { Integer permissionLevel = crmPermission.level().getLevel(); // 需要的权限级别 // 1.1 如果是超级管理员则直接通过 - if (CrmPermissionUtils.validateAdminUser()) { + if (CrmPermissionUtils.isCrmAdmin()) { return; } // 1.2 获取数据权限 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java index 50da5c584..ec482be66 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java @@ -1,10 +1,11 @@ package cn.iocoder.yudao.module.crm.framework.permission.core.util; import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + /** * 数据权限工具类 * @@ -12,24 +13,14 @@ import cn.iocoder.yudao.module.system.api.permission.PermissionApi; */ public class CrmPermissionUtils { - // TODO @puhui999:isCrmAdmin。换成这个名字;因为 validate 一般是参数校验,不符合抛出异常;一般是 isXXXValid 才会返回 true false + /** * 校验用户是否是 CRM 管理员 * * @return 是/否 */ - public static boolean validateAdminUser() { - return SingletonManager.getPermissionApi().hasAnyRoles(getUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); - } - - // TODO @puhui999:这个不需要哈,直接用原本的 SecuriyUtils 去拿更方便一些; - /** - * 获得用户编号 - * - * @return 用户编号 - */ - private static Long getUserId() { - return WebFrameworkUtils.getLoginUserId(); + public static boolean isCrmAdmin() { + return SingletonManager.getPermissionApi().hasAnyRoles(getLoginUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); } /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index c9d19ceaf..aa717839b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -67,7 +67,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { return customer.getId(); } - // TODO @puhui999:测试下,能不能打出用户数据的变更。啊哈,可以打完微信发我下; @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}", success = "更新了客户{_DIFF{#updateReqVO}}", extra = "{{#extra}}") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index bb6136c36..60af10123 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -90,8 +90,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId( transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId()); String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType()); - // TODO @puhui999:是不是并且? 不是拥有者,并且不是超管 - if (oldPermission == null || !isOwner(oldPermission.getLevel()) || !CrmPermissionUtils.validateAdminUser()) { + if (oldPermission == null || (!isOwner(oldPermission.getLevel()) && !CrmPermissionUtils.isCrmAdmin())) { // 不是拥有者,并且不是超管 throw exception(CRM_PERMISSION_DENIED, bizTypeName); } // 1.1 校验转移对象是否已经是该负责人 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java index 2c9353daf..9824c674c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java @@ -40,7 +40,7 @@ public class CrmQueryWrapperUtils { Long userId, Integer sceneType, Boolean pool) { final String ownerUserIdField = SingletonManager.getMybatisPlusJoinProperties().getTableAlias() + ".owner_user_id"; // 1. 构建数据权限连表条件 - if (ObjUtil.notEqual(CrmPermissionUtils.validateAdminUser(), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 + if (ObjUtil.notEqual(CrmPermissionUtils.isCrmAdmin(), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) .eq(CrmPermissionDO::getBizId, bizId) // 只能使用 SFunction 如果传 id 解析出来的 sql 不对 .eq(CrmPermissionDO::getUserId, userId)); @@ -81,7 +81,7 @@ public class CrmQueryWrapperUtils { * @param userId 用户编号 */ public static > void appendPermissionCondition(T query, Integer bizType, Collection bizIds, Long userId) { - if (ObjUtil.equal(CrmPermissionUtils.validateAdminUser(), Boolean.TRUE)) {// 管理员不需要数据权限 + if (ObjUtil.equal(CrmPermissionUtils.isCrmAdmin(), Boolean.TRUE)) {// 管理员不需要数据权限 return; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java index ce6480bd4..f95945627 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java @@ -98,11 +98,9 @@ public class AppActivityController { return; } - // TODO @puhui999:AppActivityRespVO 搞个构造方法,写起来更方便一些;这样后续万一加个属性,也可以处理下哈; combinationActivities.forEach(item -> { - activityList.add(new AppActivityRespVO().setId(item.getId()) - .setType(PromotionTypeEnum.COMBINATION_ACTIVITY.getType()).setName(item.getName()) - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); + activityList.add(new AppActivityRespVO(item.getId(), PromotionTypeEnum.COMBINATION_ACTIVITY.getType(), + item.getName(), item.getSpuId(), item.getStartTime(), item.getEndTime())); }); } @@ -114,9 +112,8 @@ public class AppActivityController { } seckillActivities.forEach(item -> { - activityList.add(new AppActivityRespVO().setId(item.getId()) - .setType(PromotionTypeEnum.SECKILL_ACTIVITY.getType()).setName(item.getName()) - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); + activityList.add(new AppActivityRespVO(item.getId(), PromotionTypeEnum.SECKILL_ACTIVITY.getType(), + item.getName(), item.getSpuId(), item.getStartTime(), item.getEndTime())); }); } @@ -128,9 +125,8 @@ public class AppActivityController { } bargainActivities.forEach(item -> { - activityList.add(new AppActivityRespVO().setId(item.getId()) - .setType(PromotionTypeEnum.BARGAIN_ACTIVITY.getType()).setName(item.getName()) - .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); + activityList.add(new AppActivityRespVO(item.getId(), PromotionTypeEnum.BARGAIN_ACTIVITY.getType(), + item.getName(), item.getSpuId(), item.getStartTime(), item.getEndTime())); }); } @@ -144,9 +140,8 @@ public class AppActivityController { List products = discountActivityService.getDiscountProductsByActivityId( convertSet(discountActivities, DiscountActivityDO::getId)); Map productMap = convertMap(products, DiscountProductDO::getActivityId, DiscountProductDO::getSpuId); - discountActivities.forEach(item -> activityList.add(new AppActivityRespVO().setId(item.getId()) - .setType(PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()).setName(item.getName()) - .setSpuId(productMap.get(item.getId())).setStartTime(item.getStartTime()).setEndTime(item.getEndTime()))); + discountActivities.forEach(item -> activityList.add(new AppActivityRespVO(item.getId(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(), + item.getName(), productMap.get(item.getId()), item.getStartTime(), item.getEndTime()))); } private void getRewardActivities(Collection spuIds, LocalDateTime now, List activityList) { @@ -168,9 +163,8 @@ public class AppActivityController { } RewardActivityDO rewardActivityDO = spuIdAndActivityMap.get(supId).get(); - activityList.add(new AppActivityRespVO().setId(rewardActivityDO.getId()) - .setType(PromotionTypeEnum.REWARD_ACTIVITY.getType()).setName(rewardActivityDO.getName()) - .setSpuId(supId).setStartTime(rewardActivityDO.getStartTime()).setEndTime(rewardActivityDO.getEndTime())); + activityList.add(new AppActivityRespVO(rewardActivityDO.getId(), PromotionTypeEnum.REWARD_ACTIVITY.getType(), + rewardActivityDO.getName(), supId, rewardActivityDO.getStartTime(), rewardActivityDO.getEndTime())); } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/vo/AppActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/vo/AppActivityRespVO.java index 8cb3b281b..6a67a669d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/vo/AppActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/vo/AppActivityRespVO.java @@ -1,11 +1,15 @@ package cn.iocoder.yudao.module.promotion.controller.app.activity.vo; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import java.time.LocalDateTime; @Schema(description = "用户 App - 营销活动 Response VO") +@AllArgsConstructor +@NoArgsConstructor @Data public class AppActivityRespVO { From c019136f07e4f3aacc1cdbeb62f2475e48c45890 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 27 Dec 2023 20:39:14 +0800 Subject: [PATCH 29/55] =?UTF-8?q?=E2=9C=A8=20Member=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=A7=AF=E5=88=86=E8=AE=B0=E5=BD=95=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E7=AD=9B=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppBrokerageRecordController.java | 3 ++- .../record/AppBrokerageRecordPageReqVO.java | 9 ++++++++ .../vo/record/AppBrokerageRecordRespVO.java | 6 +++++ .../brokerage/BrokerageRecordConvert.java | 2 -- .../point/AppMemberPointRecordController.java | 9 +++++--- .../vo/AppMemberPointRecordPageReqVO.java | 23 +++++++++++++++++++ .../point/MemberPointRecordConvert.java | 2 -- .../mysql/point/MemberPointRecordMapper.java | 10 ++++++-- .../point/MemberPointRecordService.java | 5 ++-- .../point/MemberPointRecordServiceImpl.java | 5 ++-- 10 files changed, 60 insertions(+), 14 deletions(-) create mode 100644 yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/vo/AppMemberPointRecordPageReqVO.java diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java index dd0fe6b20..28666cb43 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO; import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO; @@ -39,7 +40,7 @@ public class AppBrokerageRecordController { public CommonResult> getBrokerageRecordPage(@Valid AppBrokerageRecordPageReqVO pageReqVO) { PageResult pageResult = brokerageRecordService.getBrokerageRecordPage( BrokerageRecordConvert.INSTANCE.convert(pageReqVO, getLoginUserId())); - return success(BrokerageRecordConvert.INSTANCE.convertPage02(pageResult)); + return success(BeanUtils.toBean(pageResult, AppBrokerageRecordRespVO.class)); } @GetMapping("/get-product-brokerage-price") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java index e2df6dae6..2100c2324 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java @@ -6,11 +6,20 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordBizTypeEnum; import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageRecordStatusEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @Schema(description = "应用 App - 分销记录分页 Request VO") @Data public class AppBrokerageRecordPageReqVO extends PageParam { + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @InEnum(value = BrokerageRecordBizTypeEnum.class, message = "业务类型必须是 {value}") private Integer bizType; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java index 221d19758..993006e34 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java @@ -12,12 +12,18 @@ public class AppBrokerageRecordRespVO { @Schema(description = "记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Long id; + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + private String bizId; + @Schema(description = "分销标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "用户下单") private String title; @Schema(description = "分销金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") private Integer price; + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageRecordConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageRecordConvert.java index e6c0e4f8c..0f1fe6178 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageRecordConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageRecordConvert.java @@ -70,8 +70,6 @@ public interface BrokerageRecordConvert { BrokerageRecordPageReqVO convert(AppBrokerageRecordPageReqVO pageReqVO, Long userId); - PageResult convertPage02(PageResult pageResult); - default PageResult convertPage03(PageResult pageResult, Map userMap) { for (AppBrokerageUserRankByPriceRespVO vo : pageResult.getList()) { copyTo(userMap.get(vo.getId()), vo); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java index d57d195c0..f6d183d5c 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/AppMemberPointRecordController.java @@ -3,7 +3,9 @@ package cn.iocoder.yudao.module.member.controller.app.point; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; +import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordPageReqVO; import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordRespVO; import cn.iocoder.yudao.module.member.convert.point.MemberPointRecordConvert; import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; @@ -33,9 +35,10 @@ public class AppMemberPointRecordController { @GetMapping("/page") @Operation(summary = "获得用户积分记录分页") @PreAuthenticated - public CommonResult> getPointRecordPage(@Valid PageParam pageVO) { - PageResult pageResult = pointRecordService.getPointRecordPage(getLoginUserId(), pageVO); - return success(MemberPointRecordConvert.INSTANCE.convertPage02(pageResult)); + public CommonResult> getPointRecordPage( + @Valid AppMemberPointRecordPageReqVO pageReqVO) { + PageResult pageResult = pointRecordService.getPointRecordPage(getLoginUserId(), pageReqVO); + return success(BeanUtils.toBean(pageResult, AppMemberPointRecordRespVO.class)); } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/vo/AppMemberPointRecordPageReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/vo/AppMemberPointRecordPageReqVO.java new file mode 100644 index 000000000..5e51ce658 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/point/vo/AppMemberPointRecordPageReqVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.member.controller.app.point.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "用户 App - 用户积分记录分页 Request VO") +@Data +public class AppMemberPointRecordPageReqVO extends PageParam { + + @Schema(description = "是否增加积分", example = "true") + private Boolean addStatus; // true - 增加;false - 减少;null - 不筛选 + + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @Schema(description = "创建时间") + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/point/MemberPointRecordConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/point/MemberPointRecordConvert.java index 018670c51..896ae350a 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/point/MemberPointRecordConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/point/MemberPointRecordConvert.java @@ -34,6 +34,4 @@ public interface MemberPointRecordConvert { } PageResult convertPage(PageResult pageResult); - PageResult convertPage02(PageResult pageResult); - } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/point/MemberPointRecordMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/point/MemberPointRecordMapper.java index 5c3370929..d0e2452c7 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/point/MemberPointRecordMapper.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/point/MemberPointRecordMapper.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; import org.apache.ibatis.annotations.Mapper; @@ -27,9 +28,14 @@ public interface MemberPointRecordMapper extends BaseMapperX selectPage(Long userId, PageParam pageVO) { - return selectPage(pageVO, new LambdaQueryWrapperX() + default PageResult selectPage(Long userId, AppMemberPointRecordPageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() .eq(MemberPointRecordDO::getUserId, userId) + .betweenIfPresent(MemberPointRecordDO::getCreateTime, pageReqVO.getCreateTime()) + .gt(Boolean.TRUE.equals(pageReqVO.getAddStatus()), + MemberPointRecordDO::getPoint, 0) + .lt(Boolean.FALSE.equals(pageReqVO.getAddStatus()), + MemberPointRecordDO::getPoint, 0) .orderByDesc(MemberPointRecordDO::getId)); } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordService.java index 74e91880f..26d18a852 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordService.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordService.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.member.service.point; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; @@ -25,10 +26,10 @@ public interface MemberPointRecordService { * 【会员】获得积分记录分页 * * @param userId 用户编号 - * @param pageVO 分页查询 + * @param pageReqVO 分页查询 * @return 签到记录分页 */ - PageResult getPointRecordPage(Long userId, PageParam pageVO); + PageResult getPointRecordPage(Long userId, AppMemberPointRecordPageReqVO pageReqVO); /** * 创建用户积分记录 diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordServiceImpl.java index 8a5491431..d4ce47c67 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/point/MemberPointRecordServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO; +import cn.iocoder.yudao.module.member.controller.app.point.vo.AppMemberPointRecordPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import cn.iocoder.yudao.module.member.dal.mysql.point.MemberPointRecordMapper; @@ -59,8 +60,8 @@ public class MemberPointRecordServiceImpl implements MemberPointRecordService { } @Override - public PageResult getPointRecordPage(Long userId, PageParam pageVO) { - return memberPointRecordMapper.selectPage(userId, pageVO); + public PageResult getPointRecordPage(Long userId, AppMemberPointRecordPageReqVO pageReqVO) { + return memberPointRecordMapper.selectPage(userId, pageReqVO); } @Override From 1f3f3d789b751a3f585b61f2bd9ed7299c5e2134 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 27 Dec 2023 22:07:54 +0800 Subject: [PATCH 30/55] =?UTF-8?q?=E2=9C=A8=20MALL=EF=BC=9A=E8=90=A5?= =?UTF-8?q?=E9=94=80=E6=96=87=E7=AB=A0=E5=A2=9E=E5=8A=A0=20title=20?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=EF=BC=8C=E7=AE=80=E6=98=93=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E5=B8=B8=E8=A7=81=E9=97=AE=E9=A2=98=E3=80=81=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE=E7=9A=84=E7=BC=96=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/article/AppArticleController.java | 16 +++++-- .../article/vo/article/AppArticleRespVO.java | 2 +- .../dal/mysql/article/ArticleMapper.java | 4 ++ .../service/article/ArticleService.java | 42 ++++++++++--------- .../service/article/ArticleServiceImpl.java | 12 +++--- 5 files changed, 46 insertions(+), 30 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/AppArticleController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/AppArticleController.java index ee3a13357..bf33a2be2 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/AppArticleController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/AppArticleController.java @@ -2,9 +2,11 @@ package cn.iocoder.yudao.module.promotion.controller.app.article; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.promotion.controller.app.article.vo.article.AppArticlePageReqVO; import cn.iocoder.yudao.module.promotion.controller.app.article.vo.article.AppArticleRespVO; import cn.iocoder.yudao.module.promotion.convert.article.ArticleConvert; +import cn.iocoder.yudao.module.promotion.dal.dataobject.article.ArticleDO; import cn.iocoder.yudao.module.promotion.service.article.ArticleService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -51,9 +53,15 @@ public class AppArticleController { @RequestMapping("/get") @Operation(summary = "获得文章详情") - @Parameter(name = "id", description = "文章编号", example = "1024") - public CommonResult getArticlePage(@RequestParam("id") Long id) { - return success(ArticleConvert.INSTANCE.convert01(articleService.getArticle(id))); + @Parameters({ + @Parameter(name = "id", description = "文章编号", example = "1024"), + @Parameter(name = "title", description = "文章标题", example = "1024"), + }) + public CommonResult getArticle(@RequestParam(value = "id", required = false) Long id, + @RequestParam(value = "title", required = false) String title) { + ArticleDO article = id != null ? articleService.getArticle(id) + : articleService.getLastArticleByTitle(title); + return success(BeanUtils.toBean(article, AppArticleRespVO.class)); } @PutMapping("/add-browse-count") @@ -64,4 +72,4 @@ public class AppArticleController { return success(true); } -} +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/vo/article/AppArticleRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/vo/article/AppArticleRespVO.java index 8f74776c4..2c77fdc34 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/vo/article/AppArticleRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/article/vo/article/AppArticleRespVO.java @@ -28,7 +28,7 @@ public class AppArticleRespVO { private String introduction; @Schema(description = "文章内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是详细") - private String description; + private String content; @Schema(description = "发布时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/article/ArticleMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/article/ArticleMapper.java index 6f05b9a9b..4ee82471e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/article/ArticleMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/article/ArticleMapper.java @@ -38,6 +38,10 @@ public interface ArticleMapper extends BaseMapperX { .eqIfPresent(ArticleDO::getRecommendBanner, recommendBanner)); } + default List selectListByTitle(String title) { + return selectList(ArticleDO::getTitle, title); + } + default PageResult selectPage(AppArticlePageReqVO pageReqVO) { return selectPage(pageReqVO, new LambdaQueryWrapperX() .eqIfPresent(ArticleDO::getCategoryId, pageReqVO.getCategoryId())); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/article/ArticleService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/article/ArticleService.java index 7af9153f4..79b09c353 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/article/ArticleService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/article/ArticleService.java @@ -11,14 +11,14 @@ import jakarta.validation.Valid; import java.util.List; /** - * 文章详情 Service 接口 + * 文章 Service 接口 * * @author HUIHUI */ public interface ArticleService { /** - * 创建文章详情 + * 创建文章 * * @param createReqVO 创建信息 * @return 编号 @@ -26,60 +26,62 @@ public interface ArticleService { Long createArticle(@Valid ArticleCreateReqVO createReqVO); /** - * 更新文章详情 + * 更新文章 * * @param updateReqVO 更新信息 */ void updateArticle(@Valid ArticleUpdateReqVO updateReqVO); /** - * 删除文章详情 + * 删除文章 * * @param id 编号 */ void deleteArticle(Long id); /** - * 获得文章详情 + * 获得文章 * * @param id 编号 - * @return 文章详情 + * @return 文章 */ ArticleDO getArticle(Long id); /** - * 获得文章详情分页 + * 基于标题,获得文章 + * + * 如果有重名的文章,获取最后发布的 + * + * @param title 标题 + * @return 文章 + */ + ArticleDO getLastArticleByTitle(String title); + + /** + * 获得文章分页 * * @param pageReqVO 分页查询 - * @return 文章详情分页 + * @return 文章分页 */ PageResult getArticlePage(ArticlePageReqVO pageReqVO); /** - * 获得文章详情列表 + * 获得文章列表 * * @param recommendHot 是否热门 * @param recommendBanner 是否轮播图 - * @return 文章详情列表 + * @return 文章列表 */ List getArticleCategoryListByRecommend(Boolean recommendHot, Boolean recommendBanner); /** - * 获得文章详情分页 + * 获得文章分页 * * @param pageReqVO 分页查询 - * @return 文章详情分页 + * @return 文章分页 */ PageResult getArticlePage(AppArticlePageReqVO pageReqVO); - /** - * 获得指定分类的文章列表 - * - * @param categoryId 文章分类编号 - * @return 文章列表 - */ - List getArticleByCategoryId(Long categoryId); - /** * 获得指定分类的文章数量 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/article/ArticleServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/article/ArticleServiceImpl.java index 76e05f906..3c3dc8ccb 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/article/ArticleServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/article/ArticleServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.promotion.service.article; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticleCreateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.article.vo.article.ArticlePageReqVO; @@ -85,6 +86,12 @@ public class ArticleServiceImpl implements ArticleService { return articleMapper.selectById(id); } + @Override + public ArticleDO getLastArticleByTitle(String title) { + List articles = articleMapper.selectListByTitle(title); + return CollUtil.getLast(articles); + } + @Override public PageResult getArticlePage(ArticlePageReqVO pageReqVO) { return articleMapper.selectPage(pageReqVO); @@ -100,11 +107,6 @@ public class ArticleServiceImpl implements ArticleService { return articleMapper.selectPage(pageReqVO); } - @Override - public List getArticleByCategoryId(Long categoryId) { - return articleMapper.selectList(ArticleDO::getCategoryId, categoryId); - } - @Override public Long getArticleCountByCategoryId(Long categoryId) { return articleMapper.selectCount(ArticleDO::getCategoryId, categoryId); From 33c3686bef7d97afef33e5263bbe5a2af135fff4 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 28 Dec 2023 23:15:25 +0800 Subject: [PATCH 31/55] =?UTF-8?q?=E2=9C=A8=20MALL=EF=BC=9A=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E8=AE=A2=E5=8D=95=E5=92=8C=E5=94=AE=E5=90=8E=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E7=9A=84=E6=95=B0=E9=87=8F=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trade/controller/admin/order/TradeOrderController.java | 1 + .../controller/app/aftersale/AppAfterSaleController.java | 6 ------ .../trade/controller/app/order/AppTradeOrderController.java | 6 ++++++ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java index 5a572d6f6..934739bb1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderLogDO; +import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderLogService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java index 997d3427d..9b60d8c24 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java @@ -47,12 +47,6 @@ public class AppAfterSaleController { return success(AfterSaleConvert.INSTANCE.convert(afterSaleService.getAfterSale(getLoginUserId(), id))); } - @GetMapping(value = "/get-applying-count") - @Operation(summary = "获得进行中的售后订单数量") - public CommonResult getApplyingAfterSaleCount() { - return success(afterSaleService.getApplyingAfterSaleCount(getLoginUserId())); - } - @PostMapping(value = "/create") @Operation(summary = "申请售后") public CommonResult createAfterSale(@RequestBody AppAfterSaleCreateReqVO createReqVO) { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java index 8bae3e35d..c29be0d65 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; @@ -48,6 +49,9 @@ public class AppTradeOrderController { @Resource private DeliveryExpressService deliveryExpressService; + @Resource + private AfterSaleService afterSaleService; + @Resource private TradeOrderProperties tradeOrderProperties; @@ -131,6 +135,8 @@ public class AppTradeOrderController { // 待评价 orderCount.put("uncommentedCount", tradeOrderQueryService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.COMPLETED.getStatus(), false)); + // 售后数量 + orderCount.put("afterSaleCount", afterSaleService.getApplyingAfterSaleCount(getLoginUserId())); return success(orderCount); } From 08ff391f78b9dc83c862e3c7e4334e41860f4c87 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 29 Dec 2023 12:48:36 +0800 Subject: [PATCH 32/55] =?UTF-8?q?=F0=9F=90=9B=20Websocket=20=E6=96=AD?= =?UTF-8?q?=E5=BC=80=E6=97=B6=EF=BC=8C=E6=9C=AA=E5=88=A0=E9=99=A4=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D=E7=BC=93=E5=AD=98=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/core/mapper/BaseMapperX.java | 28 +++++++++---------- .../session/WebSocketSessionManagerImpl.java | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java index 023611bbc..0d970c9d6 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java @@ -121,8 +121,8 @@ public interface BaseMapperX extends MPJBaseMapper { * * @param entities 实体们 */ - default void insertBatch(Collection entities) { - Db.saveBatch(entities); + default Boolean insertBatch(Collection entities) { + return Db.saveBatch(entities); } /** @@ -131,28 +131,28 @@ public interface BaseMapperX extends MPJBaseMapper { * @param entities 实体们 * @param size 插入数量 Db.saveBatch 默认为 1000 */ - default void insertBatch(Collection entities, int size) { - Db.saveBatch(entities, size); + default Boolean insertBatch(Collection entities, int size) { + return Db.saveBatch(entities, size); } - default void updateBatch(T update) { - update(update, new QueryWrapper<>()); + default int updateBatch(T update) { + return update(update, new QueryWrapper<>()); } - default void updateBatch(Collection entities) { - Db.updateBatchById(entities); + default Boolean updateBatch(Collection entities) { + return Db.updateBatchById(entities); } - default void updateBatch(Collection entities, int size) { - Db.updateBatchById(entities, size); + default Boolean updateBatch(Collection entities, int size) { + return Db.updateBatchById(entities, size); } - default void insertOrUpdate(T entity) { - Db.saveOrUpdate(entity); + default Boolean insertOrUpdate(T entity) { + return Db.saveOrUpdate(entity); } - default void insertOrUpdateBatch(Collection collection) { - Db.saveOrUpdateBatch(collection); + default Boolean insertOrUpdateBatch(Collection collection) { + return Db.saveOrUpdateBatch(collection); } default int delete(String field, String value) { diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java index aca572f90..6dba89851 100644 --- a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java @@ -66,7 +66,7 @@ public class WebSocketSessionManagerImpl implements WebSocketSessionManager { @Override public void removeSession(WebSocketSession session) { // 移除从 idSessions 中 - idSessions.remove(session.getId(), session); + idSessions.remove(session.getId()); // 移除从 idSessions 中 LoginUser user = WebSocketFrameworkUtils.getLoginUser(session); if (user == null) { From 829965e50a27d85c5e687c2fc9e3c4caa6a75b0f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 29 Dec 2023 12:54:52 +0800 Subject: [PATCH 33/55] =?UTF-8?q?=F0=9F=90=9B=20fix(websocket):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20websocket=20=E5=A4=B1=E6=95=88=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml index c6e8f1881..f7f4adcbb 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml @@ -65,6 +65,12 @@ com.baomidou dynamic-datasource-spring-boot3-starter + + + org.springframework.boot + spring-boot-starter-undertow + + From 086137275572426a2caadc9e7946c37397e87b40 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 29 Dec 2023 12:59:20 +0800 Subject: [PATCH 34/55] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=9F=AD=E4=BF=A1=E6=B8=A0=E9=81=93=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E6=B2=A1=E6=9C=89=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/sms/core/client/impl/AbstractSmsClient.java | 1 + 1 file changed, 1 insertion(+) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java index 42f00f968..a3b92d5c3 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java @@ -41,6 +41,7 @@ public abstract class AbstractSmsClient implements SmsClient { return; } log.info("[refresh][配置({})发生变化,重新初始化]", properties); + this.properties = properties; // 初始化 this.init(); } From 475e932aecd335154614016ce0637f04d3f81994 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 29 Dec 2023 21:45:43 +0800 Subject: [PATCH 35/55] =?UTF-8?q?=F0=9F=90=9B=20=E5=AF=BC=E5=87=BA=20Excel?= =?UTF-8?q?:Long=20=E7=B1=BB=E5=9E=8B=20ID=20=E4=BC=9A=E4=B8=A2=E5=A4=B1?= =?UTF-8?q?=E7=B2=BE=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/framework/excel/core/util/ExcelUtils.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index 1bdeabc50..c2104693e 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -1,12 +1,14 @@ package cn.iocoder.yudao.framework.excel.core.util; import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.converters.longconverter.LongStringConverter; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import org.springframework.web.multipart.MultipartFile; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; /** @@ -33,9 +35,10 @@ public class ExcelUtils { EasyExcel.write(response.getOutputStream(), head) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 + .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 .sheet(sheetName).doWrite(data); // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 - response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8)); response.setContentType("application/vnd.ms-excel;charset=UTF-8"); } From 0f6f204320ca4f7699636d71dfede3de038d543d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 29 Dec 2023 21:52:49 +0800 Subject: [PATCH 36/55] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E6=94=B9=20`pay`?= =?UTF-8?q?=20=E6=A8=A1=E5=9D=97>=E6=94=AF=E4=BB=98=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E7=9A=84=E5=90=8C=E6=AD=A5=20Job=EF=BC=8C=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E5=88=9B=E5=BB=BA=E6=97=B6=E9=97=B4=E5=89=8D?= =?UTF-8?q?=E7=9A=84=E5=BE=85=E6=94=AF=E4=BB=98=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/pay/dal/mysql/order/PayOrderExtensionMapper.java | 4 ++-- .../yudao/module/pay/service/order/PayOrderServiceImpl.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderExtensionMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderExtensionMapper.java index 8513c4b31..9cc0cc4d2 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderExtensionMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderExtensionMapper.java @@ -24,10 +24,10 @@ public interface PayOrderExtensionMapper extends BaseMapperX selectListByStatusAndCreateTimeGe(Integer status, LocalDateTime minCreateTime) { + default List selectListByStatusAndCreateTimeLe(Integer status, LocalDateTime minCreateTime) { return selectList(new LambdaQueryWrapper() .eq(PayOrderExtensionDO::getStatus, status) - .ge(PayOrderExtensionDO::getCreateTime, minCreateTime)); + .le(PayOrderExtensionDO::getCreateTime, minCreateTime)); } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index 4a2550c77..1b5b5f1e3 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -438,8 +438,8 @@ public class PayOrderServiceImpl implements PayOrderService { @Override public int syncOrder(LocalDateTime minCreateTime) { - // 1. 查询指定创建时间内的待支付订单 - List orderExtensions = orderExtensionMapper.selectListByStatusAndCreateTimeGe( + // 1. 查询指定创建时间前的待支付订单 + List orderExtensions = orderExtensionMapper.selectListByStatusAndCreateTimeLe( PayOrderStatusEnum.WAITING.getStatus(), minCreateTime); if (CollUtil.isEmpty(orderExtensions)) { return 0; From ed1b55fed7ca4dc1e12bfb1b60d961af55e99bbb Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 29 Dec 2023 22:20:59 +0800 Subject: [PATCH 37/55] =?UTF-8?q?=F0=9F=90=9B=20=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=20url=20=E4=B8=AD=E6=96=87=E8=A7=A3=E7=A0=81?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/infra/controller/admin/file/FileController.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index 72120e513..3d3cd7ed6 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.file; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.URLUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -70,6 +71,8 @@ public class FileController { if (StrUtil.isEmpty(path)) { throw new IllegalArgumentException("结尾的 path 路径必须传递"); } + // 解码,解决中文路径的问题 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/807/ + path = URLUtil.decode(path); // 读取内容 byte[] content = fileService.getFileContent(configId, path); From d31a12aff7b8da53e46b4514527882b9bcfada75 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 29 Dec 2023 22:33:26 +0800 Subject: [PATCH 38/55] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=BA=86=E6=94=AF=E4=BB=98=20demo=20=E9=80=80=E6=AC=BE?= =?UTF-8?q?=E5=8D=95=E5=8C=B9=E9=85=8D=E9=94=99=E8=AF=AF=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java index b86342841..817390537 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java @@ -232,7 +232,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { throw exception(DEMO_ORDER_NOT_FOUND); } // 1.2 校验退款订单匹配 - if (Objects.equals(order.getPayOrderId(), payRefundId)) { + if (Objects.equals(order.getPayRefundId(), payRefundId)) { log.error("[validateDemoOrderCanRefunded][order({}) 退款单不匹配({}),请进行处理!order 数据是:{}]", id, payRefundId, toJsonString(order)); throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR); From 9a03f1a7966abac5828583986ce3849068be938a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 30 Dec 2023 09:38:01 +0800 Subject: [PATCH 39/55] =?UTF-8?q?=F0=9F=90=9B=20BPM=EF=BC=9A=E5=A4=9A?= =?UTF-8?q?=E7=A7=9F=E6=88=B7=E7=9A=84=E5=B7=A5=E4=BD=9C=E6=B5=81=E9=9A=94?= =?UTF-8?q?=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tenant/core/context/TenantContextHolder.java | 13 ++++++++++++- .../flowable/config/YudaoFlowableConfiguration.java | 3 +++ .../bpm/service/definition/BpmModelServiceImpl.java | 5 ++++- .../definition/BpmProcessDefinitionServiceImpl.java | 4 ++++ .../yudao/module/bpm/service/task/package-info.java | 1 - 5 files changed, 23 insertions(+), 3 deletions(-) delete mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java index 93a17b376..e78a8b859 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.tenant.core.context; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.DocumentEnum; import com.alibaba.ttl.TransmittableThreadLocal; @@ -21,7 +22,7 @@ public class TenantContextHolder { private static final ThreadLocal IGNORE = new TransmittableThreadLocal<>(); /** - * 获得租户编号。 + * 获得租户编号 * * @return 租户编号 */ @@ -29,6 +30,16 @@ public class TenantContextHolder { return TENANT_ID.get(); } + /** + * 获得租户编号 String + * + * @return 租户编号 + */ + public static String getTenantIdStr() { + Long tenantId = getTenantId(); + return StrUtil.toStringOrNull(tenantId); + } + /** * 获得租户编号。如果不存在,则抛出 NullPointerException 异常 * diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java index 7c29a6462..6d657a1b4 100644 --- a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.flowable.config; import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import cn.iocoder.yudao.framework.flowable.core.web.FlowableWebFilter; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.core.task.AsyncListenableTaskExecutor; @@ -17,6 +18,7 @@ public class YudaoFlowableConfiguration { * 如果不创建,会导致项目启动时,Flowable 报错的问题 */ @Bean + @ConditionalOnMissingBean public AsyncListenableTaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(8); @@ -40,4 +42,5 @@ public class YudaoFlowableConfiguration { registrationBean.setOrder(WebFilterOrderEnum.FLOWABLE_FILTER); return registrationBean; } + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java index 6be51bd8c..fecf2e1ff 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; @@ -71,7 +72,8 @@ public class BpmModelServiceImpl implements BpmModelService { modelQuery.modelCategory(pageVO.getCategory()); } // 执行查询 - List models = modelQuery.orderByCreateTime().desc() + List models = modelQuery.modelTenantId(TenantContextHolder.getTenantIdStr()) + .orderByCreateTime().desc() .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); // 获得 Form Map @@ -107,6 +109,7 @@ public class BpmModelServiceImpl implements BpmModelService { // 创建流程定义 Model model = repositoryService.newModel(); BpmModelConvert.INSTANCE.copy(model, createReqVO); + model.setTenantId(TenantContextHolder.getTenantIdStr()); // 保存流程定义 repositoryService.saveModel(model); // 保存 BPMN XML diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java index 78c6a1e0b..28487b562 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java @@ -6,6 +6,8 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.PageUtils; import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; +import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO; @@ -124,6 +126,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ Deployment deploy = repositoryService.createDeployment() .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory()) .addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes()) + .tenantId(TenantContextHolder.getTenantIdStr()) .deploy(); // 设置 ProcessDefinition 的 category 分类 @@ -234,6 +237,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ definitionQuery.active(); } // 执行查询 + definitionQuery.processDefinitionTenantId(TenantContextHolder.getTenantIdStr()); List processDefinitions = definitionQuery.list(); if (CollUtil.isEmpty(processDefinitions)) { return Collections.emptyList(); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java deleted file mode 100644 index eaa615302..000000000 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package cn.iocoder.yudao.module.bpm.service.task; From 078ead536bef09b0ef78690ca12c3ac5bc3a46e9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 30 Dec 2023 10:30:47 +0800 Subject: [PATCH 40/55] =?UTF-8?q?=F0=9F=90=9B=20REPORT=EF=BC=9A=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20SaaS=20=E7=A7=9F=E6=88=B7=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 4 ++-- .../yudao-module-report-biz/pom.xml | 2 +- .../core/service/JmReportTokenServiceImpl.java | 17 +++++++++++++++++ .../ureport/config/UReportConfiguration.java | 16 ++++++---------- .../ureport/core/UReportDataSource.java | 2 +- .../ureport/core/UReportDatabaseProvider.java | 2 +- .../src/main/resources/application-dev.yaml | 3 --- .../src/main/resources/application-local.yaml | 2 +- .../src/main/resources/application.yaml | 6 +++--- 9 files changed, 32 insertions(+), 22 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 00ac14356..e58ba4254 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -71,7 +71,7 @@ 2.2.1 3.1.880 2.0.5 - 1.6.1 + 1.6.6-beta2 2.12.2 4.5.7.B 2.2.9 @@ -639,7 +639,7 @@ org.jeecgframework.jimureport - jimureport-spring-boot-starter + jimureport-spring-boot3-starter ${jimureport.version} diff --git a/yudao-module-report/yudao-module-report-biz/pom.xml b/yudao-module-report/yudao-module-report-biz/pom.xml index 83461f5fe..62aeb3ee0 100644 --- a/yudao-module-report/yudao-module-report-biz/pom.xml +++ b/yudao-module-report/yudao-module-report-biz/pom.xml @@ -66,7 +66,7 @@ org.jeecgframework.jimureport - jimureport-spring-boot-starter + jimureport-spring-boot3-starter diff --git a/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/jmreport/core/service/JmReportTokenServiceImpl.java b/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/jmreport/core/service/JmReportTokenServiceImpl.java index ad4240f2f..f4685432f 100644 --- a/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/jmreport/core/service/JmReportTokenServiceImpl.java +++ b/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/jmreport/core/service/JmReportTokenServiceImpl.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi; import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO; +import cn.iocoder.yudao.module.system.api.permission.RoleApi; import lombok.RequiredArgsConstructor; import org.jeecg.modules.jmreport.api.JmReportTokenServiceI; import org.springframework.http.HttpHeaders; @@ -128,4 +129,20 @@ public class JmReportTokenServiceImpl implements JmReportTokenServiceI { return user; } + @Override + public String[] getRoles(String s) { + // 暂时不用实现,因为不用 JmReport 的角色 + return null; + } + + @Override + public String getTenantId() { + // 补充说明:不能直接通过 TenantContext 获取,因为 jimu 报表前端请求时,没有带上 tenant-id Header + LoginUser loginUser = SecurityFrameworkUtils.getLoginUser(); + if (loginUser == null) { + return null; + } + return StrUtil.toStringOrNull(loginUser.getTenantId()); + } + } diff --git a/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/config/UReportConfiguration.java b/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/config/UReportConfiguration.java index 3cf09c6aa..313ec4e66 100644 --- a/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/config/UReportConfiguration.java +++ b/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/config/UReportConfiguration.java @@ -1,29 +1,25 @@ package cn.iocoder.yudao.module.report.framework.ureport.config; -import com.bstek.ureport.console.UReportServlet; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.servlet.ServletRegistrationBean; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; import org.springframework.context.annotation.PropertySource; -import jakarta.servlet.Servlet; - /** * UReport2 配置类 * * @author 赤焰 */ -@Configuration +// @Configuration TODO 芋艿:JDK21 暂时不支持 UReport2,原因是 Spring Boot 3 的 javax 替换成 jakarta 了 @ImportResource({"classpath:ureport-console-context.xml"}) @PropertySource(value = {"classpath:ureport.properties"}) // TODO @赤焰:这个可以搞到 application.yaml 里么? @EnableConfigurationProperties({UReportProperties.class}) public class UReportConfiguration { - @Bean - public ServletRegistrationBean uReportRegistrationBean() { - return new ServletRegistrationBean<>(new UReportServlet(), "/ureport/*"); - } +// TODO 芋艿:JDK21 暂时不支持 UReport2,原因是 Spring Boot 3 的 javax 替换成 jakarta 了 +// @Bean +// public ServletRegistrationBean uReportRegistrationBean() { +// return new ServletRegistrationBean<>(new UReportServlet(), "/ureport/*"); +// } } diff --git a/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/core/UReportDataSource.java b/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/core/UReportDataSource.java index eb5d5e48c..69bee4476 100644 --- a/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/core/UReportDataSource.java +++ b/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/core/UReportDataSource.java @@ -18,7 +18,7 @@ import static cn.iocoder.yudao.module.report.enums.ErrorCodeConstants.UREPORT_DA * @author 赤焰 */ @Slf4j -@Component +//@Component public class UReportDataSource implements BuildinDatasource { private static final String NAME = "UReportDataSource"; diff --git a/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/core/UReportDatabaseProvider.java b/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/core/UReportDatabaseProvider.java index d04c088bc..077c55a91 100644 --- a/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/core/UReportDatabaseProvider.java +++ b/yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/core/UReportDatabaseProvider.java @@ -29,7 +29,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. * @author 赤焰 */ // TODO @赤焰:这个 bean 的注解,交给 UReportConfiguration 搞 -@Component +//@Component @Slf4j @Setter public class UReportDatabaseProvider implements ReportProvider { diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 6263a4278..3358e678e 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -5,9 +5,6 @@ server: spring: # 数据源配置项 - autoconfigure: - exclude: - - org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置 datasource: druid: # Druid 【监控】相关的全局配置 web-stat-filter: diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 900656ecf..93b2a69e9 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -7,7 +7,6 @@ spring: # 数据源配置项 autoconfigure: exclude: - - org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置 - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置 - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 @@ -188,6 +187,7 @@ logging: cn.iocoder.yudao.module.trade.dal.mysql: debug cn.iocoder.yudao.module.promotion.dal.mysql: debug cn.iocoder.yudao.module.statistics.dal.mysql: debug + org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示 debug: false diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 627028bdd..bb952d26e 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -260,9 +260,9 @@ yudao: debug: false # 积木报表配置 -minidao : - base-package: org.jeecg.modules.jmreport.desreport.dao* - db-type: mysql +jeecg: + jmreport: + saas-mode: tenant # UReport 配置 ureport: From 51968c4c198870c880c126406cba00fcc438c4c3 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 30 Dec 2023 11:23:59 +0800 Subject: [PATCH 41/55] =?UTF-8?q?=F0=9F=90=9B=20=E8=85=BE=E8=AE=AF?= =?UTF-8?q?=E4=BA=91=E4=B8=8A=E4=BC=A0=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/file/core/client/s3/S3FileClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java index f554e0b52..49238f8f9 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java @@ -81,7 +81,7 @@ public class S3FileClient extends AbstractFileClient { } // 腾讯云必须有 region,否则会报错 if (config.getEndpoint().contains(ENDPOINT_TENCENT)) { - return StrUtil.subAfter(config.getEndpoint(), ".cos.", false) + return StrUtil.subAfter(config.getEndpoint(), "cos.", false) .replaceAll("." + ENDPOINT_TENCENT, ""); // 去除 Endpoint } return null; From 2fb36563ec1a659497e65cb55c32a33c0224ff4e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 30 Dec 2023 12:01:12 +0800 Subject: [PATCH 42/55] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E5=A4=8D=20Cache?= =?UTF-8?q?Utils=20=E5=BC=82=E6=AD=A5=E7=BC=93=E5=AD=98=E7=9A=84=20ThreadL?= =?UTF-8?q?ocal=20=E5=8F=98=E9=87=8F=E4=BC=A0=E9=80=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/common/util/cache/CacheUtils.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/cache/CacheUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/cache/CacheUtils.java index 7f7318487..41f75405e 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/cache/CacheUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/cache/CacheUtils.java @@ -1,10 +1,12 @@ package cn.iocoder.yudao.framework.common.util.cache; +import com.alibaba.ttl.threadpool.TtlExecutors; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import java.time.Duration; +import java.util.concurrent.Executor; import java.util.concurrent.Executors; /** @@ -15,11 +17,13 @@ import java.util.concurrent.Executors; public class CacheUtils { public static LoadingCache buildAsyncReloadingCache(Duration duration, CacheLoader loader) { + Executor executor = Executors.newCachedThreadPool( // TODO 芋艿:可能要思考下,未来要不要做成可配置 + TtlExecutors.getDefaultDisableInheritableThreadFactory()); // TTL 保证 ThreadLocal 可以透传 return CacheBuilder.newBuilder() // 只阻塞当前数据加载线程,其他线程返回旧值 .refreshAfterWrite(duration) // 通过 asyncReloading 实现全异步加载,包括 refreshAfterWrite 被阻塞的加载线程 - .build(CacheLoader.asyncReloading(loader, Executors.newCachedThreadPool())); // TODO 芋艿:可能要思考下,未来要不要做成可配置 + .build(CacheLoader.asyncReloading(loader, executor)); } } From 8a947990f43d3b98576351341654eda043cc6d7f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 30 Dec 2023 19:22:58 +0800 Subject: [PATCH 43/55] =?UTF-8?q?=F0=9F=90=9B=20=E5=8D=87=E7=BA=A7=20easye?= =?UTF-8?q?xcel=20=E4=BE=9D=E8=B5=96=EF=BC=8C=E8=A7=A3=E5=86=B3=20JDK21=20?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index e58ba4254..76da6b6c4 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -51,7 +51,7 @@ 1.5.5.Final 5.8.23 6.0.0-M8 - 3.3.2 + 3.3.3 2.3 1.0.5 1.2.83 From 8c9b483ac596e1fcadcb2f02a15c7fca5b8a9b14 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 30 Dec 2023 21:36:46 +0800 Subject: [PATCH 44/55] =?UTF-8?q?=F0=9F=93=96=20code=20review=20=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=97=A5=E5=BF=97=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pom.xml | 5 +++- .../YudaoOperateLogV2Configuration.java | 3 +-- .../operatelog/core/package-info.java | 3 +++ .../core/service/ILogRecordServiceImpl.java | 24 ++++++++++--------- .../framework/operatelog/package-info.java | 7 ++++++ .../module/crm/enums/LogRecordConstants.java | 9 ++++++- .../admin/customer/CrmCustomerController.java | 4 +++- .../core/CrmIndustryParseFunction.java | 10 ++------ .../core/CrmLevelParseFunction.java | 10 ++------ .../core/CrmSourceParseFunction.java | 10 ++------ .../core/util/CrmPermissionUtils.java | 1 - .../customer/CrmCustomerServiceImpl.java | 10 ++++---- .../permission/CrmPermissionServiceImpl.java | 3 ++- .../module/crm/util/CrmQueryWrapperUtils.java | 4 ++-- .../system/api/logger/OperateLogApiImpl.java | 3 ++- .../dal/mysql/logger/OperateLogV2Mapper.java | 12 +++++----- .../core/AdminUserParseFunction.java | 16 +++++-------- .../operatelog/core/AreaParseFunction.java | 9 ++----- .../service/logger/OperateLogService.java | 4 ++-- .../service/logger/OperateLogServiceImpl.java | 9 ++++--- 20 files changed, 76 insertions(+), 80 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java diff --git a/yudao-framework/yudao-spring-boot-starter-security/pom.xml b/yudao-framework/yudao-spring-boot-starter-security/pom.xml index 4457227ae..e76e57ef9 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-security/pom.xml @@ -12,7 +12,10 @@ jar ${project.artifactId} - 用户的认证、权限的校验 + + 1. security:用户的认证、权限的校验,实现「谁」可以做「什么事」 + 2. operatelog:操作日志,实现「谁」在「什么时间」对「什么」做了「什么事」 + https://github.com/YunaiV/ruoyi-vue-pro diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogV2Configuration.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogV2Configuration.java index f5610bd28..db793c9b4 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogV2Configuration.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/config/YudaoOperateLogV2Configuration.java @@ -8,9 +8,8 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; - /** - * mzt-biz-log 配置类 + * 操作日志配置类 * * @author HUIHUI */ diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java index 1a87fb84d..97ce4eaa7 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/package-info.java @@ -1 +1,4 @@ +/** + * 占位,无特殊作用 + */ package cn.iocoder.yudao.framework.operatelog.core; \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/ILogRecordServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/ILogRecordServiceImpl.java index 4b4702c45..7efef017d 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/ILogRecordServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/ILogRecordServiceImpl.java @@ -11,9 +11,9 @@ import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; -import java.util.Collections; import java.util.List; +// TODO @puhui999:LogRecordServiceImpl 改成这个名字哈 /** * 操作日志 ILogRecordService 实现类 * @@ -26,11 +26,11 @@ public class ILogRecordServiceImpl implements ILogRecordService { @Resource private OperateLogApi operateLogApi; - + @Override public void record(LogRecord logRecord) { + // 1. 补全通用字段 OperateLogV2CreateReqDTO reqDTO = new OperateLogV2CreateReqDTO(); - // 补全通用字段 reqDTO.setTraceId(TracerUtils.getTraceId()); // 补充用户信息 fillUserFields(reqDTO); @@ -38,22 +38,24 @@ public class ILogRecordServiceImpl implements ILogRecordService { fillModuleFields(reqDTO, logRecord); // 补全请求信息 fillRequestFields(reqDTO); - // 异步记录日志 + + // 2. 异步记录日志 operateLogApi.createOperateLogV2(reqDTO); // TODO 测试结束删除或搞个开关 log.info("操作日志 ===> {}", reqDTO); } private static void fillUserFields(OperateLogV2CreateReqDTO reqDTO) { + // TODO @puhui999:使用 SecurityFrameworkUtils。因为要考虑,rpc、mq、job,它其实不是 web; reqDTO.setUserId(WebFrameworkUtils.getLoginUserId()); reqDTO.setUserType(WebFrameworkUtils.getLoginUserType()); } public static void fillModuleFields(OperateLogV2CreateReqDTO reqDTO, LogRecord logRecord) { - reqDTO.setType(logRecord.getType()); // 大模块类型如 crm 客户 - reqDTO.setSubType(logRecord.getSubType());// 操作名称如 转移客户 - reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 - reqDTO.setAction(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 + reqDTO.setType(logRecord.getType()); // 大模块类型,例如:CRM 客户 + reqDTO.setSubType(logRecord.getSubType());// 操作名称,例如:转移客户 + reqDTO.setBizId(Long.parseLong(logRecord.getBizNo())); // 业务编号,例如:客户编号 + reqDTO.setAction(logRecord.getAction());// 操作内容,例如:修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 reqDTO.setExtra(logRecord.getExtra()); // 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ),例如说,记录订单编号,{ orderId: "1"} } @@ -72,12 +74,12 @@ public class ILogRecordServiceImpl implements ILogRecordService { @Override public List queryLog(String bizNo, String type) { - return Collections.emptyList(); + throw new UnsupportedOperationException("使用 OperateLogApi 进行操作日志的查询"); } @Override public List queryLogByBizNo(String bizNo, String type, String subType) { - return Collections.emptyList(); + throw new UnsupportedOperationException("使用 OperateLogApi 进行操作日志的查询"); } -} +} \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java new file mode 100644 index 000000000..c90139b89 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/package-info.java @@ -0,0 +1,7 @@ +/** + * 基于 mzt-log 框架 + * 实现操作日志功能 + * + * @author HUIHUI + */ +package cn.iocoder.yudao.framework.operatelog; diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java index 9435ec27d..b522993eb 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.crm.enums; -// TODO 芋艿:操作日志;看看这个类怎么搞个好点的规范; /** * CRM 操作日志枚举 * @@ -23,4 +22,12 @@ public interface LogRecordConstants { String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; + // TODO @puhui999:这里格式是不是可以这样;目的是:统一管理,也减少 Service 里各种“复杂”字符串 + // ======================= Customer 客户 ======================= + String CUSTOMER_TYPE = "CRM 客户"; + String CUSTOMER_CREATE_SUB_TYPE = "创建客户"; + String CUSTOMER_CREATE_SUCCESS = "更新了客户{_DIFF{#updateReqVO}}"; + + String CUSTOMER_UPDATE_SUB_TYPE = "更新客户"; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 87d836595..cc40ae257 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -60,7 +60,7 @@ public class CrmCustomerController { @PostMapping("/create") @Operation(summary = "创建客户") - @OperateLog(enable = false) // TODO 关闭原有日志记录 + @OperateLog(enable = false) // TODO 关闭原有日志记录;@puhui999:注解都先删除。先记录,没关系。我们下个迭代,就都删除掉操作日志了; @PreAuthorize("@ss.hasPermission('crm:customer:create')") public CommonResult createCustomer(@Valid @RequestBody CrmCustomerCreateReqVO createReqVO) { return success(customerService.createCustomer(createReqVO, getLoginUserId())); @@ -102,6 +102,7 @@ public class CrmCustomerController { return success(CrmCustomerConvert.INSTANCE.convert(customer, userMap, deptMap)); } + // TODO @puhui999:这个查询会查出多个;微信发你图了 @GetMapping("/page") @Operation(summary = "获得客户分页") @PreAuthorize("@ss.hasPermission('crm:customer:query')") @@ -141,6 +142,7 @@ public class CrmCustomerController { return success(true); } + // TODO @puhui999:是不是接口只要传递 bizId,由 Controller 自己组装出 OperateLogV2PageReqDTO @GetMapping("/operate-log-page") @Operation(summary = "获得客户操作日志") @PreAuthorize("@ss.hasPermission('crm:customer:query')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmIndustryParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmIndustryParseFunction.java index 67abc71b6..60ca46a23 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmIndustryParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmIndustryParseFunction.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.crm.framework.operatelog.core; -import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import com.mzt.logapi.service.IParseFunction; @@ -10,7 +9,7 @@ import org.springframework.stereotype.Component; import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; /** - * 自定义函数-通过行业编号获取行业信息 + * 行业的 {@link IParseFunction} 实现类 * * @author HUIHUI */ @@ -30,14 +29,9 @@ public class CrmIndustryParseFunction implements IParseFunction { @Override public String apply(Object value) { - if (ObjUtil.isEmpty(value)) { + if (StrUtil.isEmptyIfStr(value)) { return ""; } - if (StrUtil.isEmpty(value.toString())) { - return ""; - } - - // 获取行业信息 return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_INDUSTRY, value.toString()); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmLevelParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmLevelParseFunction.java index 22e6b9423..28b1b8b66 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmLevelParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmLevelParseFunction.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.crm.framework.operatelog.core; -import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import com.mzt.logapi.service.IParseFunction; @@ -10,7 +9,7 @@ import org.springframework.stereotype.Component; import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL; /** - * 自定义函数-通过客户等级编号获取客户等级信息 + * 客户等级的 {@link IParseFunction} 实现类 * * @author HUIHUI */ @@ -30,14 +29,9 @@ public class CrmLevelParseFunction implements IParseFunction { @Override public String apply(Object value) { - if (ObjUtil.isEmpty(value)) { + if (StrUtil.isEmptyIfStr(value)) { return ""; } - if (StrUtil.isEmpty(value.toString())) { - return ""; - } - - // 获取客户等级信息 return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_LEVEL, value.toString()); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSourceParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSourceParseFunction.java index 46696cfd8..1fbec3af8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSourceParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmSourceParseFunction.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.crm.framework.operatelog.core; -import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import com.mzt.logapi.service.IParseFunction; @@ -10,7 +9,7 @@ import org.springframework.stereotype.Component; import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE; /** - * 自定义函数-通过客户来源编号获取客户来源信息 + * 客户来源的 {@link IParseFunction} 实现类 * * @author HUIHUI */ @@ -30,14 +29,9 @@ public class CrmSourceParseFunction implements IParseFunction { @Override public String apply(Object value) { - if (ObjUtil.isEmpty(value)) { + if (StrUtil.isEmptyIfStr(value)) { return ""; } - if (StrUtil.isEmpty(value.toString())) { - return ""; - } - - // 获取客户来源信息 return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_SOURCE, value.toString()); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java index ec482be66..43bb729b6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java @@ -13,7 +13,6 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti */ public class CrmPermissionUtils { - /** * 校验用户是否是 CRM 管理员 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index aa717839b..0ab626b8f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -62,7 +62,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 - // 添加日志上下文所需 + // 记录操作日志 LogRecordContext.putVariable("customerId", customer.getId()); return customer.getId(); } @@ -73,15 +73,15 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { // 校验存在 - CrmCustomerDO oldCustomerDO = validateCustomerExists(updateReqVO.getId()); + CrmCustomerDO oldCustomer = validateCustomerExists(updateReqVO.getId()); // 更新 CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); customerMapper.updateById(updateObj); - // __DIFF 函数传递了一个参数,传递的参数是修改之后的对象,这种方式需要在方法内部向 LogRecordContext 中 put 一个变量,代表是之前的对象,这个对象可以是null - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomerDO, CrmCustomerUpdateReqVO.class)); - // TODO 扩展信息测试 + // 记录操作日志 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerUpdateReqVO.class)); + // TODO 扩展信息测试 @puhui999:看着没啥问题,可以删除啦; HashMap extra = new HashMap<>(); extra.put("tips", "随便记录一点啦"); LogRecordContext.putVariable("extra", extra); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index 60af10123..aaf319844 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -90,7 +90,8 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { CrmPermissionDO oldPermission = crmPermissionMapper.selectByBizTypeAndBizIdByUserId( transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId()); String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType()); - if (oldPermission == null || (!isOwner(oldPermission.getLevel()) && !CrmPermissionUtils.isCrmAdmin())) { // 不是拥有者,并且不是超管 + if (oldPermission == null // 不是拥有者,并且不是超管 + || (!isOwner(oldPermission.getLevel()) && !CrmPermissionUtils.isCrmAdmin())) { throw exception(CRM_PERMISSION_DENIED, bizTypeName); } // 1.1 校验转移对象是否已经是该负责人 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java index 9824c674c..dc849622e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java @@ -40,7 +40,7 @@ public class CrmQueryWrapperUtils { Long userId, Integer sceneType, Boolean pool) { final String ownerUserIdField = SingletonManager.getMybatisPlusJoinProperties().getTableAlias() + ".owner_user_id"; // 1. 构建数据权限连表条件 - if (ObjUtil.notEqual(CrmPermissionUtils.isCrmAdmin(), Boolean.TRUE) && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 + if (!CrmPermissionUtils.isCrmAdmin() && ObjUtil.notEqual(pool, Boolean.TRUE)) { // 管理员,公海不需要数据权限 query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) .eq(CrmPermissionDO::getBizId, bizId) // 只能使用 SFunction 如果传 id 解析出来的 sql 不对 .eq(CrmPermissionDO::getUserId, userId)); @@ -81,7 +81,7 @@ public class CrmQueryWrapperUtils { * @param userId 用户编号 */ public static > void appendPermissionCondition(T query, Integer bizType, Collection bizIds, Long userId) { - if (ObjUtil.equal(CrmPermissionUtils.isCrmAdmin(), Boolean.TRUE)) {// 管理员不需要数据权限 + if (CrmPermissionUtils.isCrmAdmin()) {// 管理员不需要数据权限 return; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java index 5d8a0dc16..7bf6f5bc1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java @@ -53,7 +53,8 @@ public class OperateLogApiImpl implements OperateLogApi { } // 获取用户 - List userList = adminUserService.getUserList(convertSet(operateLogPage.getList(), OperateLogV2DO::getUserId)); + List userList = adminUserService.getUserList( + convertSet(operateLogPage.getList(), OperateLogV2DO::getUserId)); return OperateLogConvert.INSTANCE.convertPage(operateLogPage, userList); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java index acf14478f..117c368e4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java @@ -10,12 +10,12 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface OperateLogV2Mapper extends BaseMapperX { - default PageResult selectPage(OperateLogV2PageReqDTO pageReqVO) { - return selectPage(pageReqVO, new LambdaQueryWrapperX() - .eqIfPresent(OperateLogV2DO::getType, pageReqVO.getBizType()) - .eqIfPresent(OperateLogV2DO::getBizId, pageReqVO.getBizId()) - .eqIfPresent(OperateLogV2DO::getUserId, pageReqVO.getUserId()) - .orderByDesc(OperateLogV2DO::getCreateTime)); + default PageResult selectPage(OperateLogV2PageReqDTO pageReqDTO) { + return selectPage(pageReqDTO, new LambdaQueryWrapperX() + .eqIfPresent(OperateLogV2DO::getType, pageReqDTO.getBizType()) + .eqIfPresent(OperateLogV2DO::getBizId, pageReqDTO.getBizId()) + .eqIfPresent(OperateLogV2DO::getUserId, pageReqDTO.getUserId()) + .orderByDesc(OperateLogV2DO::getId)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AdminUserParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AdminUserParseFunction.java index 858cc96b9..a75ac309b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AdminUserParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AdminUserParseFunction.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.framework.operatelog.core; -import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; @@ -10,7 +9,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; /** - * 自定义函数-通过用户编号获取用户信息 + * 管理员名字的 {@link IParseFunction} 实现类 * * @author HUIHUI */ @@ -28,25 +27,22 @@ public class AdminUserParseFunction implements IParseFunction { @Override public String apply(Object value) { - if (ObjUtil.isEmpty(value)) { - return ""; - } - if (StrUtil.isEmpty(value.toString())) { + if (StrUtil.isEmptyIfStr(value)) { return ""; } // 获取用户信息 AdminUserRespDTO user = adminUserApi.getUser(Long.parseLong(value.toString())); if (user == null) { - log.warn("(getAdminUserById) 获取用户信息失败,参数为:{}", value); + log.warn("[apply][获取用户{{}}为空", value); return ""; } // 返回格式 芋道源码(13888888888) String nickname = user.getNickname(); - if (ObjUtil.isNotEmpty(user.getMobile())) { - return nickname.concat("(").concat(user.getMobile()).concat(")"); + if (StrUtil.isEmpty(user.getMobile())) { + return nickname; } - return nickname; + return StrUtil.format("{}({})", nickname, user.getMobile()); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AreaParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AreaParseFunction.java index 71051bfe2..a114beb2d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AreaParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/operatelog/core/AreaParseFunction.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.framework.operatelog.core; -import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import com.mzt.logapi.service.IParseFunction; @@ -8,7 +7,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; /** - * 自定义函数-通过区域编号获取区域信息 + * 地名的 {@link IParseFunction} 实现类 * * @author HUIHUI */ @@ -28,13 +27,9 @@ public class AreaParseFunction implements IParseFunction { @Override public String apply(Object value) { - if (ObjUtil.isEmpty(value)) { + if (StrUtil.isEmptyIfStr(value)) { return ""; } - if (StrUtil.isEmpty(value.toString())) { - return ""; - } - return AreaUtils.format(Integer.parseInt(value.toString())); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java index 27ced45a0..6843f2fb1 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogService.java @@ -35,9 +35,9 @@ public interface OperateLogService { /** * 记录操作日志 V2 * - * @param createReqBO 创建请求 + * @param createReqDTO 创建请求 */ - void createOperateLogV2(OperateLogV2CreateReqDTO createReqBO); + void createOperateLogV2(OperateLogV2CreateReqDTO createReqDTO); /** * 获得操作日志分页列表 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java index f66e9a0ae..0f31665fd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/OperateLogServiceImpl.java @@ -69,15 +69,14 @@ public class OperateLogServiceImpl implements OperateLogService { // ======================= LOG V2 ======================= @Override - public void createOperateLogV2(OperateLogV2CreateReqDTO createReqBO) { - OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class); + public void createOperateLogV2(OperateLogV2CreateReqDTO createReqDTO) { + OperateLogV2DO log = BeanUtils.toBean(createReqDTO, OperateLogV2DO.class); operateLogV2Mapper.insert(log); } - @Override - public PageResult getOperateLogPage(OperateLogV2PageReqDTO pageReqVO) { - return operateLogV2Mapper.selectPage(pageReqVO); + public PageResult getOperateLogPage(OperateLogV2PageReqDTO pageReqDTO) { + return operateLogV2Mapper.selectPage(pageReqDTO); } } From 9e3055ee1ee2ef043bbb24314a87df11002c09d6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 2 Jan 2024 18:49:14 +0800 Subject: [PATCH 45/55] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20review?= =?UTF-8?q?=20=E5=95=86=E6=9C=BA=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 2 +- .../admin/business/CrmBusinessController.java | 111 ++++----------- .../vo/business/CrmBusinessPageReqVO.java | 3 + .../vo/business/CrmBusinessRespVO.java | 2 - .../admin/contact/CrmContactController.java | 47 +++---- .../vo/CrmContactBusinessLinkPageReqVO.java | 30 ---- .../vo/CrmContactBusinessLinkRespVO.java | 26 ---- .../vo/CrmContactBusinessLinkSaveReqVO.java | 23 ---- .../contact/vo/CrmContactBusinessReqVO.java | 22 +++ .../CrmContactBusinessLinkController.java | 0 .../admin/contract/CrmContractController.java | 2 +- .../receivable/CrmReceivableController.java | 2 +- .../CrmReceivablePlanController.java | 2 +- .../convert/contact/CrmContactConvert.java | 14 +- ...sLinkDO.java => CrmContactBusinessDO.java} | 5 +- .../dal/mysql/business/CrmBusinessMapper.java | 9 +- .../CrmContactBusinessLinkMapper.java | 30 ---- .../CrmContactBusinessMapper.java | 34 +++++ .../service/business/CrmBusinessService.java | 22 +-- .../business/CrmBusinessServiceImpl.java | 66 ++++----- .../business/CrmBusinessStatusService.java | 10 ++ .../CrmBusinessStatusServiceImpl.java | 6 + .../CrmBusinessStatusTypeService.java | 11 +- .../CrmBusinessStatusTypeServiceImpl.java | 7 + .../CrmContactBusinessLinkService.java | 72 ---------- .../CrmContactBusinessLinkServiceImpl.java | 129 ------------------ .../contact/CrmContactBusinessService.java | 38 ++++++ .../CrmContactBusinessServiceImpl.java | 83 +++++++++++ .../service/contact/CrmContactService.java | 10 -- .../contact/CrmContactServiceImpl.java | 21 +-- .../service/customer/CrmCustomerService.java | 2 +- .../customer/CrmCustomerServiceImpl.java | 4 +- 32 files changed, 326 insertions(+), 519 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkPageReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkRespVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkSaveReqVO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/CrmContactBusinessLinkController.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/{CrmContactBusinessLinkDO.java => CrmContactBusinessDO.java} (86%) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessLinkMapper.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessMapper.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkService.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkServiceImpl.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index f3e3d2523..a7494dc8d 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -24,7 +24,7 @@ public interface ErrorCodeConstants { // ========== 联系人管理 1-020-003-000 ========== ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode( 1_020_003_001, "联系人商机关联不存在"); - ErrorCode CONTACT_BUSINESS_LINK_CREATE_EMPTY = new ErrorCode( 1_020_003_002, "联系人商机关联参数为空"); + // ========== 回款 1-020-004-000 ========== ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java index fed2da2af..20355610b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java @@ -4,14 +4,9 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusQueryVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; @@ -33,13 +28,10 @@ import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -51,13 +43,10 @@ public class CrmBusinessController { @Resource private CrmBusinessService businessService; - @Resource private CrmCustomerService customerService; - @Resource private CrmBusinessStatusTypeService businessStatusTypeService; - @Resource private CrmBusinessStatusService businessStatusService; @@ -99,27 +88,7 @@ public class CrmBusinessController { @PreAuthorize("@ss.hasPermission('crm:business:query')") public CommonResult> getBusinessPage(@Valid CrmBusinessPageReqVO pageVO) { PageResult pageResult = businessService.getBusinessPage(pageVO, getLoginUserId()); - if (CollUtil.isEmpty(pageResult.getList())) { - return success(PageResult.empty(pageResult.getTotal())); - } - // 处理客户名称回显 - // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈; - Set customerIds = pageResult.getList().stream() - .map(CrmBusinessDO::getCustomerId).filter(Objects::nonNull).collect(Collectors.toSet()); - List customerList = customerService.getCustomerList(customerIds, getLoginUserId()); - // 处理商机状态类型名称回显 - Set statusTypeIds = pageResult.getList().stream() - .map(CrmBusinessDO::getStatusTypeId).filter(Objects::nonNull).collect(Collectors.toSet()); - CrmBusinessStatusTypeQueryVO queryStatusTypeVO = new CrmBusinessStatusTypeQueryVO(); - queryStatusTypeVO.setIdList(statusTypeIds); - List statusTypeList = businessStatusTypeService.selectList(queryStatusTypeVO); - // 处理商机状态名称回显 - Set statusIds = pageResult.getList().stream() - .map(CrmBusinessDO::getStatusId).filter(Objects::nonNull).collect(Collectors.toSet()); - CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO(); - queryVO.setIdList(statusIds); - List statusList = businessStatusService.selectList(queryVO); - return success(CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList)); + return success(buildBusinessDetailPageResult(pageResult)); } @GetMapping("/page-by-customer") @@ -127,24 +96,16 @@ public class CrmBusinessController { public CommonResult> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) { Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); PageResult pageResult = businessService.getBusinessPageByCustomerId(pageReqVO); - // 处理客户名称回显 - // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈; - Set customerIds = pageResult.getList().stream() - .map(CrmBusinessDO::getCustomerId).filter(Objects::nonNull).collect(Collectors.toSet()); - List customerList = customerService.getCustomerList(customerIds, getLoginUserId()); - // 处理商机状态类型名称回显 - Set statusTypeIds = pageResult.getList().stream() - .map(CrmBusinessDO::getStatusTypeId).filter(Objects::nonNull).collect(Collectors.toSet()); - CrmBusinessStatusTypeQueryVO queryStatusTypeVO = new CrmBusinessStatusTypeQueryVO(); - queryStatusTypeVO.setIdList(statusTypeIds); - List statusTypeList = businessStatusTypeService.selectList(queryStatusTypeVO); - // 处理商机状态名称回显 - Set statusIds = pageResult.getList().stream() - .map(CrmBusinessDO::getStatusId).filter(Objects::nonNull).collect(Collectors.toSet()); - CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO(); - queryVO.setIdList(statusIds); - List statusList = businessStatusService.selectList(queryVO); - return success(CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList)); + return success(buildBusinessDetailPageResult(pageResult)); + } + + + @GetMapping("/page-by-contact") + @Operation(summary = "获得联系人的商机分页") + @PreAuthorize("@ss.hasPermission('crm:business:query')") + public CommonResult> getBusinessContactPage(@Valid CrmBusinessPageReqVO pageReqVO) { + PageResult pageResult = businessService.getBusinessPageByContact(pageReqVO); + return success(buildBusinessDetailPageResult(pageResult)); } @GetMapping("/export-excel") @@ -156,8 +117,21 @@ public class CrmBusinessController { exportReqVO.setPageSize(PAGE_SIZE_NONE); PageResult pageResult = businessService.getBusinessPage(exportReqVO, getLoginUserId()); // 导出 Excel - ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessExcelVO.class, - CrmBusinessConvert.INSTANCE.convertList02(pageResult.getList())); + ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessRespVO.class, + buildBusinessDetailPageResult(pageResult).getList()); + } + + private PageResult buildBusinessDetailPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + List statusTypeList = businessStatusTypeService.getBusinessStatusTypeList( + convertSet(pageResult.getList(), CrmBusinessDO::getStatusTypeId)); + List statusList = businessStatusService.getBusinessStatusList( + convertSet(pageResult.getList(), CrmBusinessDO::getStatusId)); + List customerList = customerService.getCustomerList( + convertSet(pageResult.getList(), CrmBusinessDO::getCustomerId)); + return CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList); } @PutMapping("/transfer") @@ -167,34 +141,5 @@ public class CrmBusinessController { businessService.transferBusiness(reqVO, getLoginUserId()); return success(true); } - @GetMapping("/page-by-contact") - @Operation(summary = "获得联系人的商机分页") - @PreAuthorize("@ss.hasPermission('crm:business:query')") - public CommonResult> getBusinessContactPage(@Valid CrmContactBusinessLinkPageReqVO pageVO) { - PageResult pageResult = businessService.getBusinessPageByContact(pageVO); - // 处理商机状态类型名称回显 - Set statusTypeIds = pageResult.getList().stream() - .map(CrmBusinessRespVO::getStatusTypeId).filter(Objects::nonNull).collect(Collectors.toSet()); - CrmBusinessStatusTypeQueryVO queryStatusTypeVO = new CrmBusinessStatusTypeQueryVO(); - queryStatusTypeVO.setIdList(statusTypeIds); - List statusTypeList = businessStatusTypeService.selectList(queryStatusTypeVO); - Map statusTypeMap = CollectionUtils.convertMap(statusTypeList,CrmBusinessStatusTypeDO::getId,CrmBusinessStatusTypeDO::getName); - // 处理商机状态名称回显 - Set statusIds = pageResult.getList().stream() - .map(CrmBusinessRespVO::getStatusId).filter(Objects::nonNull).collect(Collectors.toSet()); - CrmBusinessStatusQueryVO queryVO = new CrmBusinessStatusQueryVO(); - queryVO.setIdList(statusIds); - List statusList = businessStatusService.selectList(queryVO); - Map statusMap = CollectionUtils.convertMap(statusList,CrmBusinessStatusDO::getId,CrmBusinessStatusDO::getName); - // 处理客户名称回显 - Set customerIds = CollectionUtils.convertSet(pageResult.getList(),CrmBusinessRespVO::getCustomerId); - List customerList = customerService.getCustomerList(customerIds); - Map customerMap = CollectionUtils.convertMap(customerList,CrmCustomerDO::getId,CrmCustomerDO::getName); - pageResult.getList().forEach(item -> { - item.setStatusTypeName(statusTypeMap.get(item.getStatusTypeId())); - item.setStatusName(statusMap.get(item.getStatusId())); - item.setCustomerName(customerMap.get(item.getCustomerId())); - }); - return success(pageResult); - } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessPageReqVO.java index 3c9520607..0e47bf5be 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessPageReqVO.java @@ -20,6 +20,9 @@ public class CrmBusinessPageReqVO extends PageParam { @Schema(description = "客户编号", example = "10795") private Long customerId; + @Schema(description = "联系人编号", example = "10795") + private Long contactId; + @Schema(description = "场景类型", example = "1") @InEnum(CrmSceneTypeEnum.class) private Integer sceneType; // 场景类型,为 null 时则表示全部 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java index c0d61fa93..53c8f45da 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java @@ -25,6 +25,4 @@ public class CrmBusinessRespVO extends CrmBusinessBaseVO { @Schema(description = "状态名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "跟进中") private String statusName; - @Schema(description = "联系人商机关联ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") - private Long businessContactId; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java index ed640d503..6974b4902 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java @@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; -import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessLinkService; +import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -30,10 +30,6 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; import java.io.IOException; import java.util.Collections; import java.util.List; @@ -63,7 +59,7 @@ public class CrmContactController { private AdminUserApi adminUserApi; @Resource - private CrmContactBusinessLinkService contactBusinessLinkService; + private CrmContactBusinessService contactBusinessLinkService; @PostMapping("/create") @Operation(summary = "创建联系人") @@ -103,7 +99,7 @@ public class CrmContactController { NumberUtil.parseLong(contact.getCreator()), contact.getOwnerUserId()))); // 2. 获取客户信息 List customerList = customerService.getCustomerList( - Collections.singletonList(contact.getCustomerId()), getLoginUserId()); + Collections.singletonList(contact.getCustomerId())); // 3. 直属上级 List parentContactList = contactService.getContactList( Collections.singletonList(contact.getParentId()), getLoginUserId()); @@ -148,23 +144,6 @@ public class CrmContactController { convertDetailContactPage(pageResult).getList()); } - @DeleteMapping("/delete-batch-business") - @Operation(summary = "批量删除联系人商机关联") - @PreAuthorize("@ss.hasPermission('crm:contact-business-link:delete')") - public CommonResult deleteContactBusinessLinkBatch(@Valid @RequestBody List businessContactIds) { - contactBusinessLinkService.deleteContactBusinessLink(businessContactIds); - return success(true); - } - - @PostMapping("/create-batch-business") - @Operation(summary = "创建联系人商机关联") - @PreAuthorize("@ss.hasPermission('crm:contact-business-link:create')") - public CommonResult createContactBusinessLinkBatch( - @Valid @NotEmpty @RequestBody List createReqVO) { - contactBusinessLinkService.createContactBusinessLinkBatch(createReqVO); - return success(true); - } - /** * 转换成详细的联系人分页,即读取关联信息 * @@ -178,7 +157,7 @@ public class CrmContactController { } // 1. 获取客户列表 List crmCustomerDOList = customerService.getCustomerList( - convertSet(contactList, CrmContactDO::getCustomerId), getLoginUserId()); + convertSet(contactList, CrmContactDO::getCustomerId)); // 2. 获取创建人、负责人列表 Map userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList, contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); @@ -196,4 +175,22 @@ public class CrmContactController { return success(true); } + // ================== 关联/取关商机 =================== + + @PostMapping("/create-business-list") + @Operation(summary = "创建联系人与商机的关联") + @PreAuthorize("@ss.hasPermission('crm:contact:create-business')") + public CommonResult createContactBusinessList(@Valid @RequestBody CrmContactBusinessReqVO createReqVO) { + contactBusinessLinkService.createContactBusinessList(createReqVO); + return success(true); + } + + @DeleteMapping("/delete-business-list") + @Operation(summary = "删除联系人与商机的关联") + @PreAuthorize("@ss.hasPermission('crm:contact:delete-business')") + public CommonResult deleteContactBusinessList(@Valid @RequestBody CrmContactBusinessReqVO deleteReqVO) { + contactBusinessLinkService.deleteContactBusinessList(deleteReqVO); + return success(true); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkPageReqVO.java deleted file mode 100644 index 0755b6715..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkPageReqVO.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - CRM 联系人商机关联分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class CrmContactBusinessLinkPageReqVO extends PageParam { - - @Schema(description = "联系人编号", example = "20878") - private Long contactId; - - @Schema(description = "商机编号", example = "7638") - private Long businessId; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkRespVO.java deleted file mode 100644 index 7dd061b48..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkRespVO.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; - -import com.alibaba.excel.annotation.ExcelProperty; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -@Schema(description = "管理后台 - CRM 联系人商机关联 Response VO") -@Data -public class CrmContactBusinessLinkRespVO { - - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "17220") - @ExcelProperty("主键") - private Long id; - - @Schema(description = "联系人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20878") - private Long contactId; - - @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7638") - private Long businessId; - - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - private LocalDateTime createTime; - -} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkSaveReqVO.java deleted file mode 100644 index 9d59b48f6..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessLinkSaveReqVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotNull; - -@Schema(description = "管理后台 - CRM 联系人商机关联新增/修改 Request VO") -@Data -public class CrmContactBusinessLinkSaveReqVO { - - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "17220") - private Long id; - - @Schema(description = "联系人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20878") - @NotNull(message="联系人不能为空") - private Long contactId; - - @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7638") - @NotNull(message="商机不能为空") - private Long businessId; - -} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessReqVO.java new file mode 100644 index 000000000..9b360f84b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBusinessReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +@Schema(description = "管理后台 - CRM 联系人商机 Request VO") // 用于关联,取消关联的操作 +@Data +public class CrmContactBusinessReqVO { + + @Schema(description = "联系人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20878") + @NotNull(message="联系人不能为空") + private Long contactId; + + @Schema(description = "商机编号数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "7638") + @NotEmpty(message="商机不能为空") + private List businessIds; + +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/CrmContactBusinessLinkController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contactbusinesslink/CrmContactBusinessLinkController.java deleted file mode 100644 index e69de29bb..000000000 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index f0442c4d3..849e424a2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -124,7 +124,7 @@ public class CrmContractController { } // 1. 获取客户列表 List customerList = customerService.getCustomerList( - convertSet(contactList, CrmContractDO::getCustomerId), getLoginUserId()); + convertSet(contactList, CrmContractDO::getCustomerId)); // 2. 获取创建人、负责人列表 Map userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList, contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java index a353491e7..98355077e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java @@ -131,7 +131,7 @@ public class CrmReceivableController { } // 1. 获取客户列表 List customerList = customerService.getCustomerList( - convertSet(receivableList, CrmReceivableDO::getCustomerId), getLoginUserId()); + convertSet(receivableList, CrmReceivableDO::getCustomerId)); // 2. 获取创建人、负责人列表 Map userMap = adminUserApi.getUserMap(convertListByFlatMap(receivableList, contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java index 9f3c23895..6dc540e42 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java @@ -135,7 +135,7 @@ public class CrmReceivablePlanController { } // 1. 获取客户列表 List customerList = customerService.getCustomerList( - convertSet(receivablePlanList, CrmReceivablePlanDO::getCustomerId), getLoginUserId()); + convertSet(receivablePlanList, CrmReceivablePlanDO::getCustomerId)); // 2. 获取创建人、负责人列表 Map userMap = adminUserApi.getUserMap(convertListByFlatMap(receivablePlanList, contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java index ca84f4736..d41a4f6b3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.convert.contact; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; @@ -13,7 +14,6 @@ import org.mapstruct.factory.Mappers; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; @@ -55,16 +55,16 @@ public interface CrmContactConvert { * * @param contactDO 联系人 * @param userMap 用户列表 - * @param crmCustomerDOList 客户 + * @param customerDOList 客户 * @return ContactRespVO */ - default CrmContactRespVO convert(CrmContactDO contactDO, Map userMap, List crmCustomerDOList, - List contactList) { + default CrmContactRespVO convert(CrmContactDO contactDO, Map userMap, + List customerDOList, List contactList) { CrmContactRespVO contactVO = convert(contactDO); setUserInfo(contactVO, userMap); - Map ustomerMap = crmCustomerDOList.stream().collect(Collectors.toMap(CrmCustomerDO::getId, v -> v)); - Map contactMap = contactList.stream().collect(Collectors.toMap(CrmContactDO::getId, v -> v)); - findAndThen(ustomerMap, contactDO.getCustomerId(), customer -> contactVO.setCustomerName(customer.getName())); + Map customerMap = CollectionUtils.convertMap(customerDOList, CrmCustomerDO::getId); + Map contactMap = CollectionUtils.convertMap(contactList, CrmContactDO::getId); + findAndThen(customerMap, contactDO.getCustomerId(), customer -> contactVO.setCustomerName(customer.getName())); findAndThen(contactMap, contactDO.getParentId(), contact -> contactVO.setParentName(contact.getName())); return contactVO; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessLinkDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessDO.java similarity index 86% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessLinkDO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessDO.java index 7e7c50c89..46185a5ac 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessLinkDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactBusinessDO.java @@ -2,14 +2,13 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.contact; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; /** - * CRM 联系人商机关联 DO + * CRM 联系人与商机的关联 DO * * @author 芋道源码 */ @@ -21,7 +20,7 @@ import lombok.*; @Builder @NoArgsConstructor @AllArgsConstructor -public class CrmContactBusinessLinkDO extends BaseDO { +public class CrmContactBusinessDO extends BaseDO { /** * 主键 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java index eb9d50a64..d01352007 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java @@ -30,7 +30,14 @@ public interface CrmBusinessMapper extends BaseMapperX { default PageResult selectPageByCustomerId(CrmBusinessPageReqVO pageReqVO) { return selectPage(pageReqVO, new LambdaQueryWrapperX() - .eq(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 + .eq(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 + .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) + .orderByDesc(CrmBusinessDO::getId)); + } + + default PageResult selectPageByContactId(CrmBusinessPageReqVO pageReqVO, Collection businessIds) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .in(CrmBusinessDO::getId, businessIds) // 指定商机编号 .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) .orderByDesc(CrmBusinessDO::getId)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessLinkMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessLinkMapper.java deleted file mode 100644 index df67bf6e5..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessLinkMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; -import org.apache.ibatis.annotations.Mapper; - -/** - * CRM 联系人商机关联 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface CrmContactBusinessLinkMapper extends BaseMapperX { - - default PageResult selectPage(CrmContactBusinessLinkPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(CrmContactBusinessLinkDO::getContactId, reqVO.getContactId()) - .eqIfPresent(CrmContactBusinessLinkDO::getBusinessId, reqVO.getBusinessId()) - .betweenIfPresent(CrmContactBusinessLinkDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(CrmContactBusinessLinkDO::getId)); - } - default PageResult selectPageByContact(CrmContactBusinessLinkPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(CrmContactBusinessLinkDO::getContactId, reqVO.getContactId()) - .orderByDesc(CrmContactBusinessLinkDO::getId)); - } -} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessMapper.java new file mode 100644 index 000000000..3eae483bc --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contactbusinesslink/CrmContactBusinessMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * CRM 联系人与商机的关联 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface CrmContactBusinessMapper extends BaseMapperX { + + default CrmContactBusinessDO selectByContactIdAndBusinessId(Long contactId, Long businessId) { + return selectOne(CrmContactBusinessDO::getContactId, contactId, + CrmContactBusinessDO::getBusinessId, businessId); + } + + default void deleteByContactIdAndBusinessId(Long contactId, Collection businessIds) { + delete(new LambdaQueryWrapper() + .eq(CrmContactBusinessDO::getContactId, contactId) + .in(CrmContactBusinessDO::getBusinessId, businessIds)); + } + + default List selectListByContactId(Long contactId) { + return selectList(CrmContactBusinessDO::getContactId, contactId); + } + +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java index a7f07896a..fad8930e4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java @@ -5,10 +5,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import jakarta.validation.Valid; @@ -78,10 +76,20 @@ public interface CrmBusinessService { * 数据权限:基于 {@link CrmCustomerDO} 读取 * * @param pageReqVO 分页查询 - * @return 联系人分页 + * @return 商机分页 */ PageResult getBusinessPageByCustomerId(CrmBusinessPageReqVO pageReqVO); + /** + * 获得商机分页,基于指定联系人 + * + * 数据权限:基于 {@link CrmContactDO} 读取 + * + * @param pageReqVO 分页参数 + * @return 商机分页 + */ + PageResult getBusinessPageByContact(CrmBusinessPageReqVO pageReqVO); + /** * 商机转移 * @@ -90,10 +98,4 @@ public interface CrmBusinessService { */ void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId); - /** - * 获取联系人商机列表 - * @param pageReqVO 分页参数 - * @return 联系人商机 - */ - PageResult getBusinessPageByContact(CrmContactBusinessLinkPageReqVO pageReqVO); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 4c39ba22d..d2d45ba99 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -7,20 +7,14 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessUpdateReqVO; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; -import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; @@ -31,10 +25,9 @@ import org.springframework.validation.annotation.Validated; import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; /** @@ -48,14 +41,13 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Resource private CrmBusinessMapper businessMapper; - @Resource - private CrmCustomerService customerService; @Resource - private CrmPermissionService crmPermissionService; - + private CrmPermissionService permissionService; @Resource - private CrmContactService crmContactService; + private CrmContactService contactService; + @Resource + private CrmContactBusinessService contactBusinessService; @Override @Transactional(rollbackFor = Exception.class) @@ -65,7 +57,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { businessMapper.insert(business); // 创建数据权限 - crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) + permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 // 返回 @@ -93,7 +85,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { // 删除 businessMapper.deleteById(id); // 删除数据权限 - crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_BUSINESS.getType(), id); + permissionService.deletePermission(CrmBizTypeEnum.CRM_BUSINESS.getType(), id); } private CrmBusinessDO validateBusinessExists(Long id) { @@ -129,6 +121,20 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { return businessMapper.selectPageByCustomerId(pageReqVO); } + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#pageReqVO.contactId", level = CrmPermissionLevelEnum.READ) + public PageResult getBusinessPageByContact(CrmBusinessPageReqVO pageReqVO) { + // 1. 查询关联的商机编号 + List contactBusinessList = contactBusinessService.getContactBusinessListByContactId( + pageReqVO.getContactId()); + if (CollUtil.isEmpty(contactBusinessList)) { + return PageResult.empty(); + } + // 2. 查询商机分页 + return businessMapper.selectPageByContactId(pageReqVO, + convertSet(contactBusinessList, CrmContactBusinessDO::getBusinessId)); + } + @Override @Transactional(rollbackFor = Exception.class) public void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId) { @@ -136,36 +142,12 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { validateBusinessExists(reqVO.getId()); // 2.1 数据权限转移 - crmPermissionService.transferPermission( + permissionService.transferPermission( CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())); // 2.2 设置新的负责人 businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); // 3. TODO 记录转移日志 } - @Override - public PageResult getBusinessPageByContact(CrmContactBusinessLinkPageReqVO pageReqVO) { - CrmContactBusinessLinkPageReqVO crmContactBusinessLinkPageReqVO = new CrmContactBusinessLinkPageReqVO(); - crmContactBusinessLinkPageReqVO.setContactId(pageReqVO.getContactId()); - PageResult businessLinkDOS = crmContactService.selectBusinessPageByContact(crmContactBusinessLinkPageReqVO); - if (CollUtil.isEmpty(businessLinkDOS.getList())){ - return PageResult.empty(); - } - List businessList = this.getBusinessList(CollectionUtils.convertList(businessLinkDOS.getList(), - CrmContactBusinessLinkDO::getBusinessId)); - if (CollUtil.isEmpty(businessList)){ - return PageResult.empty(); - } - PageResult pageResult = new PageResult(); - List respVOList = BeanUtils.toBean(businessList,CrmBusinessRespVO.class); - Map businessContactMap = CollectionUtils.convertMap(businessLinkDOS.getList(), - CrmContactBusinessLinkDO::getBusinessId,CrmContactBusinessLinkDO::getId); - respVOList.forEach(item -> { - item.setBusinessContactId(businessContactMap.get(item.getId())); - }); - pageResult.setList(respVOList); - pageResult.setTotal(businessLinkDOS.getTotal()); - return pageResult; - } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java index ffad53556..a2fc2d18d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusService.java @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusine import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; import jakarta.validation.Valid; + +import java.util.Collection; import java.util.List; /** @@ -64,4 +66,12 @@ public interface CrmBusinessStatusService { */ List selectList(CrmBusinessStatusQueryVO queryVO); + /** + * 获得商机状态列表 + * + * @param ids 编号数组 + * @return 商机状态列表 + */ + List getBusinessStatusList(Collection ids); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java index fa6ad3d03..2e49e99d7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusServiceImpl.java @@ -12,6 +12,7 @@ import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; +import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -77,4 +78,9 @@ public class CrmBusinessStatusServiceImpl implements CrmBusinessStatusService { return businessStatusMapper.selectList(queryVO); } + @Override + public List getBusinessStatusList(Collection ids) { + return businessStatusMapper.selectBatchIds(ids); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java index 39dc3128c..20509994e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeService.java @@ -5,8 +5,9 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusiness import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; - import jakarta.validation.Valid; + +import java.util.Collection; import java.util.List; /** @@ -63,4 +64,12 @@ public interface CrmBusinessStatusTypeService { */ List selectList(CrmBusinessStatusTypeQueryVO queryVO); + /** + * 获得商机状态类型列表 + * + * @param ids 编号数组 + * @return 商机状态类型列表 + */ + List getBusinessStatusTypeList(Collection ids); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java index 501780abd..0ebcda87c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessStatusTypeServiceImpl.java @@ -17,6 +17,8 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; + +import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -118,4 +120,9 @@ public class CrmBusinessStatusTypeServiceImpl implements CrmBusinessStatusTypeSe return businessStatusTypeMapper.selectList(queryVO); } + @Override + public List getBusinessStatusTypeList(Collection ids) { + return businessStatusTypeMapper.selectBatchIds(ids); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkService.java deleted file mode 100644 index 7eab5cff3..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkService.java +++ /dev/null @@ -1,72 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.contact; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; - -import jakarta.validation.Valid; -import java.util.List; - -/** - * CRM 联系人商机关联 Service 接口 - * - * @author 芋道源码 - */ -public interface CrmContactBusinessLinkService { - - /** - * 创建联系人商机关联 - * - * @param createReqVO 创建信息 - * @return 编号 - */ - Long createContactBusinessLink(@Valid CrmContactBusinessLinkSaveReqVO createReqVO); - - /** - * 创建联系人商机关联 - * - * @param createReqVO 创建信息 - */ - void createContactBusinessLinkBatch(@Valid List createReqVO); - - /** - * 更新联系人商机关联 - * - * @param updateReqVO 更新信息 - */ - void updateContactBusinessLink(@Valid CrmContactBusinessLinkSaveReqVO updateReqVO); - - /** - * 删除联系人商机关联 - * - * @param businessContactIds 删除列表 - */ - void deleteContactBusinessLink(@Valid List businessContactIds); - - /** - * 获得联系人商机关联 - * - * @param id 编号 - * @return 联系人商机关联 - */ - CrmContactBusinessLinkDO getContactBusinessLink(Long id); - - /** - * 获得联系人商机关联分页 - * - * @param pageReqVO 编号 - * @return 联系人商机关联 - */ - PageResult getContactBusinessLinkPageByContact(CrmContactBusinessLinkPageReqVO pageReqVO); - - /** - * 获得联系人商机关联分页 - * - * @param pageReqVO 分页查询 - * @return 联系人商机关联分页 - */ - PageResult getContactBusinessLinkPage(CrmContactBusinessLinkPageReqVO pageReqVO); - -} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkServiceImpl.java deleted file mode 100644 index d2387179e..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessLinkServiceImpl.java +++ /dev/null @@ -1,129 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.contact; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Assert; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkSaveReqVO; -import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; -import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessLinkMapper; -import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; -import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; -import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTACT_BUSINESS_LINK_NOT_EXISTS; - -// TODO @puhui999:数据权限的校验;每个操作; -/** - * 联系人商机关联 Service 实现类 - * - * @author 芋道源码 - */ -@Service -@Validated -public class CrmContactBusinessLinkServiceImpl implements CrmContactBusinessLinkService { - - @Resource - private CrmContactBusinessLinkMapper contactBusinessLinkMapper; - @Resource - private CrmBusinessService crmBusinessService; - - @Resource - private CrmContactService crmContactService; - - @Override - public Long createContactBusinessLink(CrmContactBusinessLinkSaveReqVO createReqVO) { - CrmContactBusinessLinkDO contactBusinessLink = BeanUtils.toBean(createReqVO, CrmContactBusinessLinkDO.class); - contactBusinessLinkMapper.insert(contactBusinessLink); - return contactBusinessLink.getId(); - } - - @Override - public void createContactBusinessLinkBatch(List createReqVOList) { - // 插入 - CrmContactDO contactDO = crmContactService.getContact(createReqVOList.stream().findFirst().get().getContactId()); - Assert.notNull(contactDO,ErrorCodeConstants.CONTACT_NOT_EXISTS.getMsg()); - List saveDoList = new ArrayList(); - createReqVOList.forEach(item -> { - CrmBusinessDO crmBusinessDO = crmBusinessService.getBusiness(item.getBusinessId()); - if(crmBusinessDO == null){ - throw exception(BUSINESS_NOT_EXISTS); - } - // 判重 - CrmContactBusinessLinkDO crmContactBusinessLinkDO = contactBusinessLinkMapper.selectOne(new LambdaQueryWrapper() - .eq(CrmContactBusinessLinkDO::getBusinessId,item.getBusinessId()) - .eq(CrmContactBusinessLinkDO::getContactId,item.getContactId())); - if(crmContactBusinessLinkDO == null){ - saveDoList.add(BeanUtils.toBean(item,CrmContactBusinessLinkDO.class)); - } - }); - contactBusinessLinkMapper.insertBatch(saveDoList); - } - - @Override - public void updateContactBusinessLink(CrmContactBusinessLinkSaveReqVO updateReqVO) { - // 校验存在 - validateContactBusinessLinkExists(updateReqVO.getId()); - // 更新 - CrmContactBusinessLinkDO updateObj = BeanUtils.toBean(updateReqVO, CrmContactBusinessLinkDO.class); - contactBusinessLinkMapper.updateById(updateObj); - } - - @Override - public void deleteContactBusinessLink(List businessContactIds) { - // 删除 - contactBusinessLinkMapper.deleteBatchIds(businessContactIds); - } - - private void validateContactBusinessLinkExists(Long id) { - if (contactBusinessLinkMapper.selectById(id) == null) { - throw exception(CONTACT_BUSINESS_LINK_NOT_EXISTS); - } - } - - @Override - @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.READ) - public CrmContactBusinessLinkDO getContactBusinessLink(Long id) { - return contactBusinessLinkMapper.selectById(id); - } - - @Override - public PageResult getContactBusinessLinkPageByContact(CrmContactBusinessLinkPageReqVO pageReqVO) { - CrmContactBusinessLinkPageReqVO crmContactBusinessLinkPageReqVO = new CrmContactBusinessLinkPageReqVO(); - crmContactBusinessLinkPageReqVO.setContactId(pageReqVO.getContactId()); - PageResult businessLinkDOS = contactBusinessLinkMapper.selectPageByContact(crmContactBusinessLinkPageReqVO); - List businessDOS = crmBusinessService.getBusinessList(CollectionUtils.convertList(businessLinkDOS.getList(), - CrmContactBusinessLinkDO::getBusinessId), getLoginUserId()); - PageResult pageResult = new PageResult(); - pageResult.setList(CrmBusinessConvert.INSTANCE.convert(businessDOS)); - pageResult.setTotal(businessLinkDOS.getTotal()); - return pageResult; - - } - - @Override - public PageResult getContactBusinessLinkPage(CrmContactBusinessLinkPageReqVO pageReqVO) { - return contactBusinessLinkMapper.selectPage(pageReqVO); - } - -} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java new file mode 100644 index 000000000..4a4d7a42d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.crm.service.contact; + +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * CRM 联系人与商机的关联 Service 接口 + * + * @author 芋道源码 + */ +public interface CrmContactBusinessService { + + /** + * 创建联系人与商机的关联 + * + * @param createReqVO 创建信息 + */ + void createContactBusinessList(@Valid CrmContactBusinessReqVO createReqVO); + + /** + * 删除联系人与商机的关联 + * + * @param deleteReqVO 删除信息 + */ + void deleteContactBusinessList(@Valid CrmContactBusinessReqVO deleteReqVO); + + /** + * 获得联系人与商机的关联列表,基于联系人编号 + * + * @param contactId 联系人编号 + * @return 联系人商机关联 + */ + List getContactBusinessListByContactId(Long contactId); + +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java new file mode 100644 index 000000000..d0c92b548 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.crm.service.contact; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; +import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessMapper; +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTACT_NOT_EXISTS; + +// TODO @puhui999:数据权限的校验;每个操作; +/** + * 联系人与商机的关联 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class CrmContactBusinessServiceImpl implements CrmContactBusinessService { + + @Resource + private CrmContactBusinessMapper contactBusinessMapper; + + @Resource + @Lazy // 延迟加载,为了解决延迟加载 + private CrmBusinessService businessService; + @Resource + @Lazy // 延迟加载,为了解决延迟加载 + private CrmContactService contactService; + + @Override + public void createContactBusinessList(CrmContactBusinessReqVO createReqVO) { + CrmContactDO contact = contactService.getContact(createReqVO.getContactId()); + if (contact == null) { + throw exception(CONTACT_NOT_EXISTS); + } + // 遍历处理,考虑到一般数量不会太多,代码处理简单 + List saveDOList = new ArrayList<>(); + createReqVO.getBusinessIds().forEach(businessId -> { + CrmBusinessDO business = businessService.getBusiness(businessId); + if (business == null) { + throw exception(BUSINESS_NOT_EXISTS); + } + // 关联判重 + if (contactBusinessMapper.selectByContactIdAndBusinessId(createReqVO.getContactId(), businessId) != null) { + return; + } + saveDOList.add(new CrmContactBusinessDO(null, createReqVO.getContactId(), businessId)); + }); + // 批量插入 + if (CollUtil.isNotEmpty(saveDOList)) { + contactBusinessMapper.insertBatch(saveDOList); + } + } + + @Override + public void deleteContactBusinessList(CrmContactBusinessReqVO deleteReqVO) { + CrmContactDO contact = contactService.getContact(deleteReqVO.getContactId()); + if (contact == null) { + throw exception(CONTACT_NOT_EXISTS); + } + // 直接删除 + contactBusinessMapper.deleteByContactIdAndBusinessId( + deleteReqVO.getContactId(), deleteReqVO.getBusinessIds()); + } + + @Override + public List getContactBusinessListByContactId(Long contactId) { + return contactBusinessMapper.selectListByContactId(contactId); + } + +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java index 17ae00f44..7d0c1dc0c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java @@ -1,12 +1,10 @@ package cn.iocoder.yudao.module.crm.service.contact; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactBusinessLinkPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import jakarta.validation.Valid; @@ -90,12 +88,4 @@ public interface CrmContactService { */ void transferContact(CrmContactTransferReqVO reqVO, Long userId); - - /** - * 获取联系人商机关联分页列表 - * @param reqVO 联系人 - * @return 商机联系人关联列表 - */ - PageResult selectBusinessPageByContact(CrmContactBusinessLinkPageReqVO reqVO); - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index b1bf83d46..520038008 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -5,17 +5,9 @@ import cn.hutool.core.collection.ListUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; -import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; -import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessLinkDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; -import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessLinkMapper; -import cn.iocoder.yudao.module.crm.framework.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; @@ -56,7 +48,7 @@ public class CrmContactServiceImpl implements CrmContactService { private AdminUserApi adminUserApi; @Resource - private CrmContactBusinessLinkMapper contactBusinessLinkMapper; + private CrmContactBusinessMapper contactBusinessLinkMapper; @Override @Transactional(rollbackFor = Exception.class) @@ -161,11 +153,4 @@ public class CrmContactServiceImpl implements CrmContactService { // 3. TODO 记录转移日志 } - @Override - public PageResult selectBusinessPageByContact(CrmContactBusinessLinkPageReqVO pageReqVO) { - CrmContactBusinessLinkPageReqVO crmContactBusinessLinkPageReqVO = new CrmContactBusinessLinkPageReqVO(); - crmContactBusinessLinkPageReqVO.setContactId(pageReqVO.getContactId()); - return contactBusinessLinkMapper.selectPageByContact(crmContactBusinessLinkPageReqVO); - - } -} +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 73be18951..917196335 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -56,7 +56,7 @@ public interface CrmCustomerService { * @return 客户列表 * @author ljlleo */ - List getCustomerList(Collection ids, Long userId); + List getCustomerList(Collection ids); /** * 获得客户分页 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 0ab626b8f..c6fcae0e2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -116,11 +116,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override - public List getCustomerList(Collection ids, Long userId) { + public List getCustomerList(Collection ids) { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } - return customerMapper.selectBatchIds(ids, userId); + return customerMapper.selectBatchIds(ids); } @Override From 1da8006af35f2ab6a7aeb3636260df21e650b7f5 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 2 Jan 2024 21:45:02 +0800 Subject: [PATCH 46/55] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9A=E3=80=90?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E3=80=91=E5=AE=8C=E5=96=84=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E3=80=81=E6=96=B0=E5=A2=9E=E3=80=81=E4=BF=AE=E6=94=B9=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E7=9A=84=20todo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/customer/CrmCustomerController.java | 2 ++ .../crm/service/customer/CrmCustomerServiceImpl.java | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index cc40ae257..5c766c5b3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -58,6 +58,7 @@ public class CrmCustomerController { @Resource private OperateLogApi operateLogApi; + // TODO @puhui999:把 CrmCustomerCreateReqVO、CrmCustomerUpdateReqVO、CrmCustomerRespVO 按照新的规范,搞一下哈; @PostMapping("/create") @Operation(summary = "创建客户") @OperateLog(enable = false) // TODO 关闭原有日志记录;@puhui999:注解都先删除。先记录,没关系。我们下个迭代,就都删除掉操作日志了; @@ -114,6 +115,7 @@ public class CrmCustomerController { } // 2. 拼接数据 + // TODO @puhui999:距离进入公海的时间 Map userMap = adminUserApi.getUserMap( convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId()))); Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index c6fcae0e2..2ab693c59 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -24,6 +24,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -52,10 +53,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户") + @LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户") // TODO @puhui999:客户名字,要记录进去;不然在展示操作日志的全列表,看不清楚是哪个客户哈; public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { - // 插入 - CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO); + // 插入客户 + CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO) + .setLockStatus(false).setDealStatus(false) + .setContactLastTime(LocalDateTime.now()); + // TODO @puhui999:可能要加个 receiveTime 字段,记录最后接收时间 customerMapper.insert(customer); // 创建数据权限 @@ -72,6 +76,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @LogRecord(type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}", success = "更新了客户{_DIFF{#updateReqVO}}", extra = "{{#extra}}") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { + // TODO @puhui999:更新的时候,要把 updateReqVO 负责人设置为空,避免修改。 // 校验存在 CrmCustomerDO oldCustomer = validateCustomerExists(updateReqVO.getId()); From d0df0e8e161ec9df00db23916181465daca83a25 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 3 Jan 2024 13:06:49 +0800 Subject: [PATCH 47/55] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9A=E3=80=90?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E3=80=91=E4=BC=98=E5=8C=96=E9=94=81=E5=AE=9A?= =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=9A=84=E9=80=BB=E8=BE=91=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 10 +- .../CrmCustomerLimitConfigTypeEnum.java | 6 +- .../admin/customer/CrmCustomerController.java | 3 +- .../customer/vo/CrmCustomerLockReqVO.java | 2 - .../CrmCustomerLimitConfigCreateReqVO.java | 6 - .../convert/customer/CrmCustomerConvert.java | 3 - .../CrmCustomerLimitConfigMapper.java | 23 ++- .../dal/mysql/customer/CrmCustomerMapper.java | 14 ++ .../CrmCustomerLimitConfigService.java | 10 +- .../CrmCustomerLimitConfigServiceImpl.java | 10 +- .../service/customer/CrmCustomerService.java | 3 +- .../customer/CrmCustomerServiceImpl.java | 141 ++++++++++-------- 12 files changed, 128 insertions(+), 103 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index d99e5b23a..137acee10 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -39,12 +39,10 @@ public interface ErrorCodeConstants { ErrorCode CUSTOMER_IN_POOL = new ErrorCode(1_020_006_004, "客户【{}】放入公海失败,原因:已经是公海客户"); ErrorCode CUSTOMER_LOCKED_PUT_POOL_FAIL = new ErrorCode(1_020_006_005, "客户【{}】放入公海失败,原因:客户已锁定"); ErrorCode CUSTOMER_UPDATE_OWNER_USER_FAIL = new ErrorCode(1_020_006_006, "更新客户【{}】负责人失败, 原因:系统异常"); - - ErrorCode CUSTOMER_UNLOCK_STATUS_NO_REPETITION = new ErrorCode(1_020_006_001, "无需重复操作锁定/解锁状态"); - - ErrorCode CUSTOMER_NO_DEPARTMENT_FOUND = new ErrorCode(1_020_006_002, "操作失败,请先绑定部门再进行操作"); - - ErrorCode CUSTOMER_EXCEED_LOCK_LIMIT = new ErrorCode(1_020_006_003, "操作失败,超出锁定规则上限"); + ErrorCode CUSTOMER_LOCK_FAIL_IS_LOCK = new ErrorCode(1_020_006_007, "锁定客户失败,它已经处于锁定状态"); + ErrorCode CUSTOMER_UNLOCK_FAIL_IS_UNLOCK = new ErrorCode(1_020_006_008, "锁定客户失败,它已经处于未锁定状态"); + ErrorCode CUSTOMER_LOCK_EXCEED_LIMIT = new ErrorCode(1_020_006_009, "锁定客户失败,超出锁定规则上限"); + ErrorCode CUSTOMER_OWNER_EXCEED_LIMIT = new ErrorCode(1_020_006_010, "操作失败,超出客户数拥有上限"); // ========== 权限管理 1_020_007_000 ========== ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在"); diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java index 6300dee0e..ec362d484 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/customer/CrmCustomerLimitConfigTypeEnum.java @@ -18,19 +18,19 @@ public enum CrmCustomerLimitConfigTypeEnum implements IntArrayValuable { /** * 拥有客户数限制 */ - CUSTOMER_QUANTITY_LIMIT(1, "拥有客户数限制"), + CUSTOMER_OWNER_LIMIT(1, "拥有客户数限制"), /** * 锁定客户数限制 */ CUSTOMER_LOCK_LIMIT(2, "锁定客户数限制"), ; - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLimitConfigTypeEnum::getCode).toArray(); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmCustomerLimitConfigTypeEnum::getType).toArray(); /** * 状态 */ - private final Integer code; + private final Integer type; /** * 状态名 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 1ad8f7d5a..dfa02c0b2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -154,13 +154,12 @@ public class CrmCustomerController { return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); } - // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; @PutMapping("/lock") @Operation(summary = "锁定/解锁客户") @OperateLog(enable = false) // TODO 关闭原有日志记录 @PreAuthorize("@ss.hasPermission('crm:customer:update')") public CommonResult lockCustomer(@Valid @RequestBody CrmCustomerLockReqVO lockReqVO) { - customerService.lockCustomer(lockReqVO); + customerService.lockCustomer(lockReqVO, getLoginUserId()); return success(true); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java index 50608049f..1cf9ff382 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerLockReqVO.java @@ -13,6 +13,4 @@ public class CrmCustomerLockReqVO { @Schema(description = "客户锁定状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") private Boolean lockStatus; - - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java index 2cc707c43..7aa372901 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/limitconfig/CrmCustomerLimitConfigCreateReqVO.java @@ -5,16 +5,10 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import java.util.List; - @Schema(description = "管理后台 - 客户限制配置创建 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class CrmCustomerLimitConfigCreateReqVO extends CrmCustomerLimitConfigBaseVO { - - @Schema(description = "规则适用人群") - private Long userId; - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java index b300c6416..6c8fdcbef 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/customer/CrmCustomerConvert.java @@ -12,7 +12,6 @@ import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; -import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; import java.util.List; @@ -79,6 +78,4 @@ public interface CrmCustomerConvert { List convertQueryAll(List crmCustomerDO); - CrmCustomerDO convert(CrmCustomerLockReqVO lockReqVO); - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java index ea8f7d8bf..08beaf808 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerLimitConfigMapper.java @@ -3,13 +3,11 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; import org.apache.ibatis.annotations.Mapper; -import java.util.Arrays; -import java.util.stream.Collectors; +import java.util.List; /** * 客户限制配置 Mapper @@ -25,16 +23,15 @@ public interface CrmCustomerLimitConfigMapper extends BaseMapperX queryWrapper = new LambdaQueryWrapperX<>(); - queryWrapper.apply("FIND_IN_SET({0}, user_ids) > 0", reqVO.getUserId()); - queryWrapper.eq(CrmCustomerLimitConfigDO::getType, reqVO.getType()); - // 将部门ID列表转换成逗号分隔的字符串 - String deptIdsString = reqVO.getDeptIds().stream() - .map(String::valueOf) - .collect(Collectors.joining(",")); - queryWrapper.apply("FIND_IN_SET({0}, dept_ids) > 0", deptIdsString); - return selectOne(queryWrapper); + default List selectListByTypeAndUserIdAndDeptId( + Integer type, Long userId, Long deptId) { + LambdaQueryWrapperX query = new LambdaQueryWrapperX() + .eq(CrmCustomerLimitConfigDO::getType, type); + query.apply("FIND_IN_SET({0}, user_ids) > 0", userId); + if (deptId != null) { + query.apply("FIND_IN_SET({0}, dept_ids) > 0", deptId); + } + return selectList(query); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 77304575c..8acd92b3e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -9,6 +10,7 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; +import org.springframework.lang.Nullable; import java.util.Collection; import java.util.List; @@ -21,6 +23,18 @@ import java.util.List; @Mapper public interface CrmCustomerMapper extends BaseMapperX { + default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) { + return selectCount(new LambdaUpdateWrapper() + .eq(CrmCustomerDO::getLockStatus, lockStatus) + .eq(CrmCustomerDO::getOwnerUserId, ownerUserId)); + } + + default Long selectCountByDealStatusAndOwnerUserId(@Nullable Boolean dealStatus, Long ownerUserId) { + return selectCount(new LambdaQueryWrapperX() + .eqIfPresent(CrmCustomerDO::getDealStatus, dealStatus) + .eq(CrmCustomerDO::getOwnerUserId, ownerUserId)); + } + default int updateOwnerUserIdById(Long id, Long ownerUserId) { return update(new LambdaUpdateWrapper() .eq(CrmCustomerDO::getId, id) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java index a181032f5..585d49f0a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigService.java @@ -5,9 +5,10 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmC import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; - import jakarta.validation.Valid; +import java.util.List; + /** * 客户限制配置 Service 接口 * @@ -54,8 +55,11 @@ public interface CrmCustomerLimitConfigService { PageResult getCustomerLimitConfigPage(CrmCustomerLimitConfigPageReqVO pageReqVO); /** - * 查询当前登录人客户限制配置 + * 查询用户对应的配置列表 + * + * @param type 类型 + * @param userId 用户类型 */ - CrmCustomerLimitConfigDO selectByLimitConfig(CrmCustomerLimitConfigCreateReqVO configReqVO); + List getCustomerLimitConfigListByUserId(Integer type, Long userId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java index 24cd84d36..be8ddd968 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.crm.service.customer; +import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigPageReqVO; @@ -9,12 +10,14 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfi import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerLimitConfigMapper; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; import java.util.Collection; +import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_LIMIT_CONFIG_NOT_EXISTS; @@ -30,6 +33,7 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig @Resource private CrmCustomerLimitConfigMapper customerLimitConfigMapper; + @Resource private DeptApi deptApi; @Resource @@ -91,8 +95,10 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig } @Override - public CrmCustomerLimitConfigDO selectByLimitConfig(CrmCustomerLimitConfigCreateReqVO configReqVO) { - return customerLimitConfigMapper.selectByLimitConfig(configReqVO); + public List getCustomerLimitConfigListByUserId(Integer type, Long userId) { + AdminUserRespDTO user = adminUserApi.getUser(userId); + Assert.notNull(user, "用户({})不存在", userId); + return customerLimitConfigMapper.selectListByTypeAndUserIdAndDeptId(type, userId, user.getDeptId()); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index e1a1b938a..c7eeaaf4a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -83,8 +83,9 @@ public interface CrmCustomerService { * 锁定/解锁客户 * * @param lockReqVO 更新信息 + * @param userId 用户编号 */ - void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO); + void lockCustomer(@Valid CrmCustomerLockReqVO lockReqVO, Long userId); // ==================== 公海相关操作 ==================== diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 246663477..bb900b784 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -2,13 +2,9 @@ package cn.iocoder.yudao.module.crm.service.customer; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerCreateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.limitconfig.CrmCustomerLimitConfigCreateReqVO; import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; @@ -19,11 +15,9 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; -import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -33,13 +27,11 @@ import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.TRANSFER_CUSTOMER_LOG_SUCCESS; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_EXCEED_LOCK_LIMIT; import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; +import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_OWNER_LIMIT; import static java.util.Collections.singletonList; /** @@ -55,29 +47,32 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { private CrmCustomerMapper customerMapper; @Resource - private CrmPermissionService crmPermissionService; + private CrmPermissionService permissionService; @Resource - private CrmCustomerLimitConfigService crmCustomerLimitConfigService; + private CrmCustomerLimitConfigService customerLimitConfigService; @Resource private AdminUserApi adminUserApi; @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户") // TODO @puhui999:客户名字,要记录进去;不然在展示操作日志的全列表,看不清楚是哪个客户哈; + @LogRecord(type = CRM_CUSTOMER, subType = "创建客户", bizNo = "{{#customerId}}", success = "创建了客户") // TODO @puhui999:创建了客户【客户名】,要记录进去;不然在展示操作日志的全列表,看不清楚是哪个客户哈; public Long createCustomer(CrmCustomerCreateReqVO createReqVO, Long userId) { - // 插入客户 + // 1. 校验拥有客户是否到达上限 + validateCustomerExceedOwnerLimit(createReqVO.getOwnerUserId(), 1); + + // 2. 插入客户 CrmCustomerDO customer = CrmCustomerConvert.INSTANCE.convert(createReqVO) .setLockStatus(false).setDealStatus(false) .setContactLastTime(LocalDateTime.now()); // TODO @puhui999:可能要加个 receiveTime 字段,记录最后接收时间 customerMapper.insert(customer); - // 创建数据权限 - crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) + // 3. 创建数据权限 + permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 - // 记录操作日志 + // 4. 记录操作日志 LogRecordContext.putVariable("customerId", customer.getId()); return customer.getId(); } @@ -88,14 +83,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { // TODO @puhui999:更新的时候,要把 updateReqVO 负责人设置为空,避免修改。 - // 校验存在 + // 1. 校验存在 CrmCustomerDO oldCustomer = validateCustomerExists(updateReqVO.getId()); - // 更新 + // 2. 更新客户 CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(updateReqVO); customerMapper.updateById(updateObj); - // 记录操作日志 + // 3. 记录操作日志 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerUpdateReqVO.class)); // TODO 扩展信息测试 @puhui999:看着没啥问题,可以删除啦; HashMap extra = new HashMap<>(); @@ -114,7 +109,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 删除 customerMapper.deleteById(id); // 删除数据权限 - crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); + permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); } private CrmCustomerDO validateCustomerExists(Long id) { @@ -159,63 +154,83 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @LogRecord(type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { - // 1. 校验客户是否存在 - CrmCustomerDO customerDO = validateCustomerExists(reqVO.getId()); + // 1.1 校验客户是否存在 + CrmCustomerDO customer = validateCustomerExists(reqVO.getId()); + // 1.2 校验拥有客户是否到达上限 + validateCustomerExceedOwnerLimit(reqVO.getNewOwnerUserId(), 1); // 2.1 数据权限转移 - crmPermissionService.transferPermission( + permissionService.transferPermission( CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); // 2.2 转移后重新设置负责人 customerMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); // 3. TODO 记录转移日志 - LogRecordContext.putVariable("crmCustomer", customerDO); + LogRecordContext.putVariable("crmCustomer", customer); } @Override + // TODO @puhui999:看看这个能不能根据条件,写操作日志; + // TODO 如果是 锁定,则 subType 为 锁定客户;success 为 将客户【】锁定 + // TODO 如果是 解锁,则 subType 为 解锁客户;success 为 将客户【】解锁 @LogRecord(type = CRM_CUSTOMER, subType = "锁定/解锁客户", bizNo = "{{#updateReqVO.id}}", success = "锁定了客户") - public void lockCustomer(CrmCustomerLockReqVO lockReqVO) { - // 校验当前客户是否存在 + // TODO @puhui999:数据权限 + public void lockCustomer(CrmCustomerLockReqVO lockReqVO, Long userId) { + // 1.1 校验当前客户是否存在 validateCustomerExists(lockReqVO.getId()); - - CrmCustomerDO customerDO = customerMapper.selectById(lockReqVO.getId()); - - // 校验当前是否重复操作锁定/解锁状态 - if (customerDO.getLockStatus().equals(lockReqVO.getLockStatus())) { - throw exception(CUSTOMER_UNLOCK_STATUS_NO_REPETITION); + // 1.2 校验当前是否重复操作锁定/解锁状态 + CrmCustomerDO customer = customerMapper.selectById(lockReqVO.getId()); + if (customer.getLockStatus().equals(lockReqVO.getLockStatus())) { + throw exception(customer.getLockStatus() ? CUSTOMER_LOCK_FAIL_IS_LOCK : CUSTOMER_UNLOCK_FAIL_IS_UNLOCK); + } + // 1.3 校验锁定上限。 + if (lockReqVO.getLockStatus()) { + validateCustomerExceedLockLimit(userId); } - // 获取当前登录信息,开始校验锁定上限 - AdminUserRespDTO userRespDTO = adminUserApi.getUser(getLoginUserId()); + // 2. 更新锁定状态 + customerMapper.updateById(BeanUtils.toBean(lockReqVO, CrmCustomerDO.class)); + } - if (userRespDTO.getDeptId() == null || userRespDTO.getId() == null) { - // 如有入参为空,提示业务异常 - throw exception(CUSTOMER_NO_DEPARTMENT_FOUND); + /** + * 校验用户拥有的客户数量,是否到达上限 + * + * @param userId 用户编号 + * @param newCount 附加数量 + */ + private void validateCustomerExceedOwnerLimit(Long userId, int newCount) { + List limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId( + CUSTOMER_OWNER_LIMIT.getType(), userId); + if (CollUtil.isEmpty(limitConfigs)) { + return; } + Long ownerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(null, userId); + Long dealOwnerCount = customerMapper.selectCountByDealStatusAndOwnerUserId(true, userId); + limitConfigs.forEach(limitConfig -> { + long nowCount = limitConfig.getDealCountEnabled() ? ownerCount : ownerCount - dealOwnerCount; + if (nowCount + newCount > limitConfig.getMaxCount()) { + throw exception(CUSTOMER_OWNER_EXCEED_LIMIT); + } + }); + } - // 开始校验规则限制 - List userDeptIds = Collections.singletonList(userRespDTO.getDeptId()); - - CrmCustomerLimitConfigCreateReqVO configReqVO = new CrmCustomerLimitConfigCreateReqVO(); - configReqVO.setUserId(userRespDTO.getId()); - configReqVO.setDeptIds(userDeptIds); - configReqVO.setType(CUSTOMER_LOCK_LIMIT.getCode()); - - CrmCustomerLimitConfigDO crmCustomerLimitConfigDO = crmCustomerLimitConfigService.selectByLimitConfig(configReqVO); - - // 统计当前用户已锁定客户数量 - List crmCustomerDOS = customerMapper.selectList("owner_user_id", getLoginUserId()); - long customerLockCount = crmCustomerDOS.stream().filter(CrmCustomerDO::getLockStatus).count(); - - // 锁定操作的时候校验当前用户可锁定客户的上限 - if (crmCustomerLimitConfigDO != null && lockReqVO.getLockStatus() && customerLockCount >= crmCustomerLimitConfigDO.getMaxCount()) { - // 超出锁定数量上限,提示业务异常 - throw exception(CUSTOMER_EXCEED_LOCK_LIMIT); + /** + * 校验用户锁定的客户数量,是否到达上限 + * + * @param userId 用户编号 + */ + private void validateCustomerExceedLockLimit(Long userId) { + List limitConfigs = customerLimitConfigService.getCustomerLimitConfigListByUserId( + CUSTOMER_LOCK_LIMIT.getType(), userId); + if (CollUtil.isEmpty(limitConfigs)) { + return; + } + Long lockCount = customerMapper.selectCountByLockStatusAndOwnerUserId(true, userId); + Integer maxCount = CollectionUtils.getMaxValue(limitConfigs, CrmCustomerLimitConfigDO::getMaxCount); + assert maxCount != null; + if (lockCount >= maxCount) { + throw exception(CUSTOMER_LOCK_EXCEED_LIMIT); } - - // 更新 - CrmCustomerDO updateObj = CrmCustomerConvert.INSTANCE.convert(lockReqVO); - customerMapper.updateById(updateObj); } @Override @@ -239,7 +254,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { throw exception(CUSTOMER_UPDATE_OWNER_USER_FAIL); } // 3. 删除负责人数据权限 - crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(), + permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(), CrmPermissionLevelEnum.OWNER.getLevel()); } @@ -262,6 +277,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 校验成交状态 validateCustomerDeal(customer); }); + // 1.4 校验负责人是否到达上限 + validateCustomerExceedOwnerLimit(ownerUserId, customers.size()); // 2. 领取公海数据 List updateCustomers = new ArrayList<>(); @@ -277,7 +294,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 3.1 更新客户负责人 customerMapper.updateBatch(updateCustomers); // 3.2 创建负责人数据权限 - crmPermissionService.createPermissionBatch(createPermissions); + permissionService.createPermissionBatch(createPermissions); } private void validateCustomerOwnerExists(CrmCustomerDO customer, Boolean pool) { From 2e7c3e09a9b1d8deba1b2dffe24e3187b3efb905 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 3 Jan 2024 19:38:13 +0800 Subject: [PATCH 48/55] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20review?= =?UTF-8?q?=20=E6=89=80=E6=9C=89=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E5=AF=B9=E5=BA=94=20todo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/business/CrmBusinessController.java | 7 ++- .../admin/contact/CrmContactController.java | 20 +++--- .../admin/contract/CrmContractController.java | 12 ++-- .../admin/customer/CrmCustomerController.java | 4 +- .../customer/vo/CrmCustomerTransferReqVO.java | 2 + .../permission/CrmPermissionController.java | 1 + .../receivable/CrmReceivableController.java | 14 ++--- .../CrmReceivablePlanController.java | 6 +- .../convert/business/CrmBusinessConvert.java | 12 ++-- .../convert/contact/CrmContactConvert.java | 63 ++++++------------- .../convert/contract/CrmContractConvert.java | 23 +++---- .../receivable/CrmReceivableConvert.java | 27 +++----- .../receivable/CrmReceivablePlanConvert.java | 30 +++------ .../customer/CrmCustomerServiceImpl.java | 20 ++++-- 14 files changed, 102 insertions(+), 139 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java index 20355610b..e7bc01e18 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java @@ -99,7 +99,6 @@ public class CrmBusinessController { return success(buildBusinessDetailPageResult(pageResult)); } - @GetMapping("/page-by-contact") @Operation(summary = "获得联系人的商机分页") @PreAuthorize("@ss.hasPermission('crm:business:query')") @@ -121,6 +120,12 @@ public class CrmBusinessController { buildBusinessDetailPageResult(pageResult).getList()); } + /** + * 构建详细的商机分页结果 + * + * @param pageResult 简单的商机分页结果 + * @return 详细的商机分页结果 + */ private PageResult buildBusinessDetailPageResult(PageResult pageResult) { if (CollUtil.isEmpty(pageResult.getList())) { return PageResult.empty(pageResult.getTotal()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java index 6974b4902..80e8b623b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java @@ -121,7 +121,7 @@ public class CrmContactController { @PreAuthorize("@ss.hasPermission('crm:contact:query')") public CommonResult> getContactPage(@Valid CrmContactPageReqVO pageVO) { PageResult pageResult = contactService.getContactPage(pageVO, getLoginUserId()); - return success(convertDetailContactPage(pageResult)); + return success(buildContactDetailPage(pageResult)); } @GetMapping("/page-by-customer") @@ -129,7 +129,7 @@ public class CrmContactController { public CommonResult> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) { Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); PageResult pageResult = contactService.getContactPageByCustomerId(pageVO); - return success(convertDetailContactPage(pageResult)); + return success(buildContactDetailPage(pageResult)); } @GetMapping("/export-excel") @@ -141,16 +141,16 @@ public class CrmContactController { exportReqVO.setPageNo(PAGE_SIZE_NONE); PageResult pageResult = contactService.getContactPage(exportReqVO, getLoginUserId()); ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class, - convertDetailContactPage(pageResult).getList()); + buildContactDetailPage(pageResult).getList()); } /** - * 转换成详细的联系人分页,即读取关联信息 + * 构建详细的联系人分页结果 * - * @param pageResult 联系人分页 - * @return 详细的联系人分页 + * @param pageResult 简单的联系人分页结果 + * @return 详细的联系人分页结果 */ - private PageResult convertDetailContactPage(PageResult pageResult) { + private PageResult buildContactDetailPage(PageResult pageResult) { List contactList = pageResult.getList(); if (CollUtil.isEmpty(contactList)) { return PageResult.empty(pageResult.getTotal()); @@ -175,10 +175,10 @@ public class CrmContactController { return success(true); } - // ================== 关联/取关商机 =================== + // ================== 关联/取关联系人 =================== @PostMapping("/create-business-list") - @Operation(summary = "创建联系人与商机的关联") + @Operation(summary = "创建联系人与联系人的关联") @PreAuthorize("@ss.hasPermission('crm:contact:create-business')") public CommonResult createContactBusinessList(@Valid @RequestBody CrmContactBusinessReqVO createReqVO) { contactBusinessLinkService.createContactBusinessList(createReqVO); @@ -186,7 +186,7 @@ public class CrmContactController { } @DeleteMapping("/delete-business-list") - @Operation(summary = "删除联系人与商机的关联") + @Operation(summary = "删除联系人与联系人的关联") @PreAuthorize("@ss.hasPermission('crm:contact:delete-business')") public CommonResult deleteContactBusinessList(@Valid @RequestBody CrmContactBusinessReqVO deleteReqVO) { contactBusinessLinkService.deleteContactBusinessList(deleteReqVO); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index 849e424a2..0a4043772 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -88,7 +88,7 @@ public class CrmContractController { @PreAuthorize("@ss.hasPermission('crm:contract:query')") public CommonResult> getContractPage(@Valid CrmContractPageReqVO pageVO) { PageResult pageResult = contractService.getContractPage(pageVO, getLoginUserId()); - return success(convertDetailContractPage(pageResult)); + return success(buildContractDetailPage(pageResult)); } @GetMapping("/page-by-customer") @@ -96,7 +96,7 @@ public class CrmContractController { public CommonResult> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) { Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); PageResult pageResult = contractService.getContractPageByCustomerId(pageVO); - return success(convertDetailContractPage(pageResult)); + return success(buildContractDetailPage(pageResult)); } @GetMapping("/export-excel") @@ -112,12 +112,12 @@ public class CrmContractController { } /** - * 转换成详细的合同分页,即读取关联信息 + * 构建详细的合同分页结果 * - * @param pageResult 合同分页 - * @return 详细的合同分页 + * @param pageResult 简单的合同分页结果 + * @return 详细的合同分页结果 */ - private PageResult convertDetailContractPage(PageResult pageResult) { + private PageResult buildContractDetailPage(PageResult pageResult) { List contactList = pageResult.getList(); if (CollUtil.isEmpty(contactList)) { return PageResult.empty(pageResult.getTotal()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index dfa02c0b2..1ba9cc010 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -136,7 +136,7 @@ public class CrmCustomerController { } @PutMapping("/transfer") - @Operation(summary = "客户转移") + @Operation(summary = "转移客户") @OperateLog(enable = false) // TODO 关闭原有日志记录 @PreAuthorize("@ss.hasPermission('crm:customer:update')") public CommonResult transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { @@ -184,6 +184,7 @@ public class CrmCustomerController { return success(true); } + // TODO @puhui999:需要搞个 VO 类 @PutMapping("/distribute") @Operation(summary = "分配公海给对应负责人") @Parameters({ @@ -193,7 +194,6 @@ public class CrmCustomerController { @PreAuthorize("@ss.hasPermission('crm:customer:distribute')") public CommonResult distributeCustomer(@RequestParam(value = "ids") List ids, @RequestParam(value = "ownerUserId") Long ownerUserId) { - // 领取公海数据 customerService.receiveCustomer(ids, ownerUserId); return success(true); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java index 9bdc43532..09eca73ea 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerTransferReqVO.java @@ -28,4 +28,6 @@ public class CrmCustomerTransferReqVO { @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") private Integer oldOwnerPermissionLevel; + // TODO @puhui999:联系人、商机、合同的转移 + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java index 5dc3807f5..7350e6915 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java @@ -103,6 +103,7 @@ public class CrmPermissionController { // 拼接数据 List userList = adminUserApi.getUserList(convertSet(permission, CrmPermissionDO::getUserId)); Map deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId)); + // TODO @puhui999:可能 postIds 为空的时候,会导致报错,看看怎么 fix 下 Set postIds = CollectionUtils.convertSetByFlatMap(userList, AdminUserRespDTO::getPostIds, Collection::stream); Map postMap = postApi.getPostMap(postIds); return success(CrmPermissionConvert.INSTANCE.convert(permission, userList, deptMap, postMap)); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java index 98355077e..e5ae4fd9b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java @@ -93,7 +93,7 @@ public class CrmReceivableController { @PreAuthorize("@ss.hasPermission('crm:receivable:query')") public CommonResult> getReceivablePage(@Valid CrmReceivablePageReqVO pageReqVO) { PageResult pageResult = receivableService.getReceivablePage(pageReqVO, getLoginUserId()); - return success(convertDetailReceivablePage(pageResult)); + return success(buildReceivableDetailPage(pageResult)); } @GetMapping("/page-by-customer") @@ -101,7 +101,7 @@ public class CrmReceivableController { public CommonResult> getReceivablePageByCustomer(@Valid CrmReceivablePageReqVO pageReqVO) { Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); PageResult pageResult = receivableService.getReceivablePageByCustomerId(pageReqVO); - return success(convertDetailReceivablePage(pageResult)); + return success(buildReceivableDetailPage(pageResult)); } // TODO 芋艿:后面在优化导出 @@ -115,16 +115,16 @@ public class CrmReceivableController { PageResult pageResult = receivableService.getReceivablePage(exportReqVO, getLoginUserId()); // 导出 Excel ExcelUtils.write(response, "回款.xls", "数据", CrmReceivableRespVO.class, - convertDetailReceivablePage(pageResult).getList()); + buildReceivableDetailPage(pageResult).getList()); } /** - * 转换成详细的回款分页,即读取关联信息 + * 构建详细的回款分页结果 * - * @param pageResult 回款分页 - * @return 详细的回款分页 + * @param pageResult 简单的回款分页结果 + * @return 详细的回款分页结果 */ - private PageResult convertDetailReceivablePage(PageResult pageResult) { + private PageResult buildReceivableDetailPage(PageResult pageResult) { List receivableList = pageResult.getList(); if (CollUtil.isEmpty(receivableList)) { return PageResult.empty(pageResult.getTotal()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java index 6dc540e42..7ff0a9385 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java @@ -123,10 +123,10 @@ public class CrmReceivablePlanController { } /** - * 转换成详细的回款计划分页,即读取关联信息 + * 构建详细的回款计划分页结果 * - * @param pageResult 回款计划分页 - * @return 详细的回款计划分页 + * @param pageResult 简单的回款计划分页结果 + * @return 详细的回款计划分页结果 */ private PageResult convertDetailReceivablePlanPage(PageResult pageResult) { List receivablePlanList = pageResult.getList(); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java index 3effb21e0..a67812f8b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.convert.business; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.*; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; @@ -9,7 +10,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; -import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; import java.util.List; @@ -34,25 +34,23 @@ public interface CrmBusinessConvert { CrmBusinessRespVO convert(CrmBusinessDO bean); List convert(List bean); - PageResult convertPage(PageResult page); - List convertList02(List list); @Mapping(target = "bizId", source = "reqVO.id") CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId); - default PageResult convertPage(PageResult page, List customerList, + default PageResult convertPage(PageResult pageResult, List customerList, List statusTypeList, List statusList) { - PageResult result = convertPage(page); + PageResult voPageResult = BeanUtils.toBean(pageResult, CrmBusinessRespVO.class); // 拼接关联字段 Map customerMap = convertMap(customerList, CrmCustomerDO::getId, CrmCustomerDO::getName); Map statusTypeMap = convertMap(statusTypeList, CrmBusinessStatusTypeDO::getId, CrmBusinessStatusTypeDO::getName); Map statusMap = convertMap(statusList, CrmBusinessStatusDO::getId, CrmBusinessStatusDO::getName); - result.getList().forEach(type -> type + voPageResult.getList().forEach(type -> type .setCustomerName(customerMap.get(type.getCustomerId())) .setStatusTypeName(statusTypeMap.get(type.getStatusTypeId())) .setStatusName(statusMap.get(type.getStatusId()))); - return result; + return voPageResult; } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java index d41a4f6b3..8d023618f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.convert.contact; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; @@ -18,7 +19,6 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; -// TODO 芋艿:convert 后面在梳理下,略微有点乱 /** * CRM 联系人 Convert * @@ -39,64 +39,39 @@ public interface CrmContactConvert { PageResult convertPage(PageResult page); - default PageResult convertPage(PageResult pageResult, Map userMap, - List customerList, List parentContactList) { - List list = converList(pageResult.getList(), userMap, customerList, parentContactList); - return convertPage(pageResult).setList(list); - } - List convertAllList(List list); @Mapping(target = "bizId", source = "reqVO.id") CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId); - /** - * 转换详情信息 - * - * @param contactDO 联系人 - * @param userMap 用户列表 - * @param customerDOList 客户 - * @return ContactRespVO - */ + default PageResult convertPage(PageResult pageResult, Map userMap, + List customerList, List parentContactList) { + PageResult voPageResult = BeanUtils.toBean(pageResult, CrmContactRespVO.class); + // 拼接关联字段 + Map parentContactMap = convertMap(parentContactList, CrmContactDO::getId); + Map customerMap = convertMap(customerList, CrmCustomerDO::getId); + voPageResult.getList().forEach(item -> { + setUserInfo(item, userMap); + findAndThen(customerMap, item.getCustomerId(), customer -> item.setCustomerName(customer.getName())); + findAndThen(parentContactMap, item.getParentId(), contactDO -> item.setParentName(contactDO.getName())); + }); + return voPageResult; + } + default CrmContactRespVO convert(CrmContactDO contactDO, Map userMap, - List customerDOList, List contactList) { + List customerList, List parentContactList) { CrmContactRespVO contactVO = convert(contactDO); setUserInfo(contactVO, userMap); - Map customerMap = CollectionUtils.convertMap(customerDOList, CrmCustomerDO::getId); - Map contactMap = CollectionUtils.convertMap(contactList, CrmContactDO::getId); + Map customerMap = CollectionUtils.convertMap(customerList, CrmCustomerDO::getId); + Map contactMap = CollectionUtils.convertMap(parentContactList, CrmContactDO::getId); findAndThen(customerMap, contactDO.getCustomerId(), customer -> contactVO.setCustomerName(customer.getName())); findAndThen(contactMap, contactDO.getParentId(), contact -> contactVO.setParentName(contact.getName())); return contactVO; } - default List converList(List contactList, Map userMap, - List customerList, List parentContactList) { - List result = convertList(contactList); - Map parentContactMap = convertMap(parentContactList, CrmContactDO::getId); - Map customerMap = convertMap(customerList, CrmCustomerDO::getId); - result.forEach(item -> { - setUserInfo(item, userMap); - findAndThen(customerMap, item.getCustomerId(), customer -> - item.setCustomerName(customer.getName()) - ); - findAndThen(parentContactMap, item.getParentId(), contactDO -> - item.setParentName(contactDO.getName()) - ); - }); - return result; - } - - /** - * 设置用户信息 - * - * @param contactRespVO 联系人Response VO - * @param userMap 用户信息 map - */ static void setUserInfo(CrmContactRespVO contactRespVO, Map userMap) { contactRespVO.setAreaName(AreaUtils.format(contactRespVO.getAreaId())); - findAndThen(userMap, contactRespVO.getOwnerUserId(), user -> { - contactRespVO.setOwnerUserName(user == null ? "" : user.getNickname()); - }); + findAndThen(userMap, contactRespVO.getOwnerUserId(), user -> contactRespVO.setOwnerUserName(user.getNickname())); findAndThen(userMap, Long.parseLong(contactRespVO.getCreator()), user -> contactRespVO.setCreatorName(user.getNickname())); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java index 74b7a4663..b898ef4e3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.convert.contract; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -43,23 +44,15 @@ public interface CrmContractConvert { default PageResult convertPage(PageResult pageResult, Map userMap, List customerList) { - return new PageResult<>(converList(pageResult.getList(), userMap, customerList), pageResult.getTotal()); - } - - default List converList(List contractList, Map userMap, - List customerList) { - List result = convertList(contractList); + PageResult voPageResult = BeanUtils.toBean(pageResult, ContractRespVO.class); + // 拼接关联字段 Map customerMap = convertMap(customerList, CrmCustomerDO::getId); - result.forEach(item -> { - setUserInfo(item, userMap); - findAndThen(customerMap, item.getCustomerId(), customer -> item.setCustomerName(customer.getName())); + voPageResult.getList().forEach(contract -> { + findAndThen(userMap, contract.getOwnerUserId(), user -> contract.setOwnerUserName(user.getNickname())); + findAndThen(userMap, Long.parseLong(contract.getCreator()), user -> contract.setCreatorName(user.getNickname())); + findAndThen(customerMap, contract.getCustomerId(), customer -> contract.setCustomerName(customer.getName())); }); - return result; - } - - static void setUserInfo(ContractRespVO contract, Map userMap) { - findAndThen(userMap, contract.getOwnerUserId(), user -> contract.setOwnerUserName(user.getNickname())); - findAndThen(userMap, Long.parseLong(contract.getCreator()), user -> contract.setCreatorName(user.getNickname())); + return voPageResult; } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivableConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivableConvert.java index e7340fc86..9f343238a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivableConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivableConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.convert.receivable; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableTransferReqVO; @@ -36,29 +37,19 @@ public interface CrmReceivableConvert { CrmReceivableRespVO convert(CrmReceivableDO bean); - List convertList(List list); - default PageResult convertPage(PageResult pageResult, Map userMap, List customerList, List contractList) { - return new PageResult<>(converList(pageResult.getList(), userMap, customerList, contractList), pageResult.getTotal()); - } - - default List converList(List receivableList, Map userMap, - List customerList, List contractList) { - List result = convertList(receivableList); + PageResult voPageResult = BeanUtils.toBean(pageResult, CrmReceivableRespVO.class); + // 拼接关联字段 Map customerMap = convertMap(customerList, CrmCustomerDO::getId); Map contractMap = convertMap(contractList, CrmContractDO::getId); - result.forEach(item -> { - setUserInfo(item, userMap); - findAndThen(customerMap, item.getCustomerId(), customer -> item.setCustomerName(customer.getName())); - findAndThen(contractMap, item.getContractId(), contract -> item.setContractNo(contract.getNo())); + voPageResult.getList().forEach(receivable -> { + findAndThen(userMap, receivable.getOwnerUserId(), user -> receivable.setOwnerUserName(user.getNickname())); + findAndThen(userMap, Long.parseLong(receivable.getCreator()), user -> receivable.setCreatorName(user.getNickname())); + findAndThen(customerMap, receivable.getCustomerId(), customer -> receivable.setCustomerName(customer.getName())); + findAndThen(contractMap, receivable.getContractId(), contract -> receivable.setContractNo(contract.getNo())); }); - return result; - } - - static void setUserInfo(CrmReceivableRespVO receivable, Map userMap) { - findAndThen(userMap, receivable.getOwnerUserId(), user -> receivable.setOwnerUserName(user.getNickname())); - findAndThen(userMap, Long.parseLong(receivable.getCreator()), user -> receivable.setCreatorName(user.getNickname())); + return voPageResult; } @Mapping(target = "bizId", source = "reqVO.id") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivablePlanConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivablePlanConvert.java index 70e930880..eb459e071 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivablePlanConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/receivable/CrmReceivablePlanConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.convert.receivable; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanTransferReqVO; @@ -37,33 +38,22 @@ public interface CrmReceivablePlanConvert { CrmReceivablePlanRespVO convert(CrmReceivablePlanDO bean); - List convertList(List list); - default PageResult convertPage(PageResult pageResult, Map userMap, List customerList, List contractList, List receivableList) { - return new PageResult<>(converList(pageResult.getList(), userMap, customerList, contractList, receivableList), pageResult.getTotal()); - } - - default List converList(List receivablePlanList, Map userMap, - List customerList, List contractList, - List receivableList) { - List result = convertList(receivablePlanList); + PageResult voPageResult = BeanUtils.toBean(pageResult, CrmReceivablePlanRespVO.class); + // 拼接关联字段 Map customerMap = convertMap(customerList, CrmCustomerDO::getId); Map contractMap = convertMap(contractList, CrmContractDO::getId); Map receivableMap = convertMap(receivableList, CrmReceivableDO::getId); - result.forEach(item -> { - setUserInfo(item, userMap); - findAndThen(customerMap, item.getCustomerId(), customer -> item.setCustomerName(customer.getName())); - findAndThen(contractMap, item.getContractId(), contract -> item.setContractNo(contract.getNo())); - findAndThen(receivableMap, item.getReceivableId(), receivable -> item.setReturnType(receivable.getReturnType())); + voPageResult.getList().forEach(receivablePlan -> { + findAndThen(userMap, receivablePlan.getOwnerUserId(), user -> receivablePlan.setOwnerUserName(user.getNickname())); + findAndThen(userMap, Long.parseLong(receivablePlan.getCreator()), user -> receivablePlan.setCreatorName(user.getNickname())); + findAndThen(customerMap, receivablePlan.getCustomerId(), customer -> receivablePlan.setCustomerName(customer.getName())); + findAndThen(contractMap, receivablePlan.getContractId(), contract -> receivablePlan.setContractNo(contract.getNo())); + findAndThen(receivableMap, receivablePlan.getReceivableId(), receivable -> receivablePlan.setReturnType(receivable.getReturnType())); }); - return result; - } - - static void setUserInfo(CrmReceivablePlanRespVO receivablePlan, Map userMap) { - findAndThen(userMap, receivablePlan.getOwnerUserId(), user -> receivablePlan.setOwnerUserName(user.getNickname())); - findAndThen(userMap, Long.parseLong(receivablePlan.getCreator()), user -> receivablePlan.setCreatorName(user.getNickname())); + return voPageResult; } @Mapping(target = "bizId", source = "reqVO.id") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index bb900b784..ad0ee9a76 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -105,11 +105,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { public void deleteCustomer(Long id) { // 校验存在 validateCustomerExists(id); + // TODO @puhui999:如果有联系人、商机,则不允许删除; // 删除 customerMapper.deleteById(id); // 删除数据权限 permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); + // TODO @puhui999:删除跟进记录 } private CrmCustomerDO validateCustomerExists(Long id) { @@ -151,7 +153,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) + @LogRecord(type = CRM_CUSTOMER, subType = "转移客户", bizNo = "{{#reqVO.id}}", success = TRANSFER_CUSTOMER_LOG_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { // 1.1 校验客户是否存在 @@ -235,7 +237,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(type = CRM_CUSTOMER, subType = "客户放入公海", bizNo = "{{#id}}", success = "将客户放入了公海") + @LogRecord(type = CRM_CUSTOMER, subType = "客户放入公海", bizNo = "{{#id}}", success = "将客户放入了公海") // TODO @puhui999:将客户【】放入了公海 @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void putCustomerPool(Long id) { // 1. 校验存在 @@ -256,10 +258,16 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 3. 删除负责人数据权限 permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(), CrmPermissionLevelEnum.OWNER.getLevel()); + // TODO @puhui999:联系人的负责人,也要设置为 null;这块和领取是对应的;因为领取后,负责人也要关联过来; } @Override @Transactional(rollbackFor = Exception.class) + // TODO @puhui999:权限校验 + + // TODO @puhui999:如果是分配,操作日志是 “将客户【】分配给【】” + // TODO @puhui999:如果是领取,操作日志是“领取客户【】”; + // TODO @puhui999:如果是多条,则需要记录多条操作日志;不然 bizId 不好关联 public void receiveCustomer(List ids, Long ownerUserId) { // 1.1 校验存在 List customers = customerMapper.selectBatchIds(ids); @@ -280,7 +288,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 1.4 校验负责人是否到达上限 validateCustomerExceedOwnerLimit(ownerUserId, customers.size()); - // 2. 领取公海数据 + // 2.1 领取公海数据 List updateCustomers = new ArrayList<>(); List createPermissions = new ArrayList<>(); customers.forEach(customer -> { @@ -290,11 +298,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { createPermissions.add(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) .setBizId(customer.getId()).setUserId(ownerUserId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); }); - - // 3.1 更新客户负责人 + // 2.2 更新客户负责人 customerMapper.updateBatch(updateCustomers); - // 3.2 创建负责人数据权限 + // 2.3 创建负责人数据权限 permissionService.createPermissionBatch(createPermissions); + // TODO @芋艿:要不要处理关联的联系人??? } private void validateCustomerOwnerExists(CrmCustomerDO customer, Boolean pool) { From f8f5e525be05a2476ab3e59084541a4cefd6bcfa Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 3 Jan 2024 20:56:28 +0800 Subject: [PATCH 49/55] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E8=B7=9F=E8=BF=9B=E8=AE=B0=E5=BD=95=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CrmCustomerLimitConfigController.java | 1 + .../CrmCustomerPoolConfigController.java | 1 + .../CrmCustomerPoolConfigSaveReqVO.java | 6 +- .../dataobject/customer/CrmCustomerDO.java | 1 + .../followup/CrmFollowUpRecordDO.java | 81 +++++++++++++++++++ 5 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerLimitConfigController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerLimitConfigController.java index ec86c99d5..7636bc200 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerLimitConfigController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerLimitConfigController.java @@ -43,6 +43,7 @@ public class CrmCustomerLimitConfigController { @Resource private AdminUserApi adminUserApi; + // TODO @puhui999:可以把 vo 改下哈 @PostMapping("/create") @Operation(summary = "创建客户限制配置") @PreAuthorize("@ss.hasPermission('crm:customer-limit-config:create')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerPoolConfigController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerPoolConfigController.java index a6da45b7d..8ae809337 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerPoolConfigController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerPoolConfigController.java @@ -26,6 +26,7 @@ public class CrmCustomerPoolConfigController { @Resource private CrmCustomerPoolConfigService customerPoolConfigService; + // TODO @puhui999:可以把 vo 改下哈 @GetMapping("/get") @Operation(summary = "获取客户公海规则设置") @PreAuthorize("@ss.hasPermission('crm:customer-pool-config:query')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigSaveReqVO.java index fa72f5f74..93b6557a4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/poolconfig/CrmCustomerPoolConfigSaveReqVO.java @@ -16,9 +16,9 @@ import java.util.Objects; @ToString(callSuper = true) public class CrmCustomerPoolConfigSaveReqVO extends CrmCustomerPoolConfigBaseVO { - // TODO @wanwan:AssertTrue 必须 is 开头哈;注意需要 json 忽略下,避免被序列化; + // TODO @puhui999:AssertTrue 必须 is 开头哈;注意需要 json 忽略下,避免被序列化; @AssertTrue(message = "客户公海规则设置不正确") - // TODO @wanwan:这个方法,是不是拆成 2 个,一个校验 contactExpireDays、一个校验 dealExpireDays; + // TODO @puhui999:这个方法,是不是拆成 2 个,一个校验 contactExpireDays、一个校验 dealExpireDays; public boolean poolEnableValid() { if (!BooleanUtil.isTrue(getEnabled())) { return true; @@ -27,7 +27,7 @@ public class CrmCustomerPoolConfigSaveReqVO extends CrmCustomerPoolConfigBaseVO } @AssertTrue(message = "客户公海规则设置不正确") - // TODO @wanwan:这个方法,是不是改成 isNotifyDaysValid() 更好点?本质校验的是 notifyDays 是否为空 + // TODO @puhui999:这个方法,是不是改成 isNotifyDaysValid() 更好点?本质校验的是 notifyDays 是否为空 public boolean notifyEnableValid() { if (!BooleanUtil.isTrue(getNotifyEnabled())) { return true; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java index c5826b7c3..3cc42a5d2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java @@ -115,6 +115,7 @@ public class CrmCustomerDO extends BaseDO { * 最后跟进时间 */ private LocalDateTime contactLastTime; + // TODO @puhui999:增加一个字段 contactLastContent;最后跟进内容 /** * 下次联系时间 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java new file mode 100644 index 000000000..b9138da92 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.followup; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDateTime; +import java.util.List; + +// TODO @puhui999:界面:做成一个 list 列表,字段是 id、跟进人、跟进方式、跟进时间、跟进内容、下次联系时间、关联联系人、关联商机 +// TODO @puhui999:界面:记录时,弹窗,表单字段是跟进方式、跟进内容、下次联系时间、关联联系人、关联商机;其中关联联系人、关联商机,要做成对应的组件列。 +/** + * 跟进记录 DO + * + * 用于记录客户、联系人的每一次跟进 + * + * @author 芋道源码 + */ +@TableName(value = "crm_follow_up_record") +@KeySequence("crm_follow_up_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CrmFollowUpRecordDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + + /** + * 数据类型 + * + * 枚举 {@link CrmBizTypeEnum} + */ + private Integer bizType; + /** + * 数据编号 + * + * 关联 {@link CrmBizTypeEnum} 对应模块 DO 的 id 字段 + */ + private Long bizId; + + /** + * 跟进类型 + * + * TODO @puhui999:可以搞个数据字典,打电话、发短信、上门拜访、微信、邮箱、QQ + */ + private Integer type; + /** + * 跟进内容 + */ + private String content; + /** + * 下次联系时间 + */ + private LocalDateTime nextTime; + + /** + * 关联的商机编号数组 + * + * 关联 {@link CrmBusinessDO#getId()} + */ + private List businessIds; + /** + * 关联的联系人编号数组 + * + * 关联 {@link CrmContactDO#getId()} + */ + private List contactIds; + +} From cff6e520ee99c519e497423fc5b75fb9f5bc4321 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 3 Jan 2024 22:07:20 +0800 Subject: [PATCH 50/55] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9A=E3=80=90?= =?UTF-8?q?=E8=81=94=E7=B3=BB=E4=BA=BA=E3=80=91code=20review=20=E8=81=94?= =?UTF-8?q?=E7=B3=BB=E4=BA=BA=E7=9A=84=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=A1=A5?= =?UTF-8?q?=E5=85=A8=E5=AF=B9=E5=BA=94=E7=9A=84=20todo=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/contact/CrmContactController.java | 5 +++- .../convert/contact/CrmContactConvert.java | 2 -- .../contact/CrmContactServiceImpl.java | 25 +++++++++++++------ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java index 80e8b623b..dfb269c8f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.NumberUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; @@ -61,6 +62,7 @@ public class CrmContactController { @Resource private CrmContactBusinessService contactBusinessLinkService; + // TODO @zyna:CrmContactCreateReqVO、CrmContactUpdateReqVO、CrmContactRespVO 按照新的 VO 规范搞哈;可以参考 dept 模块 @PostMapping("/create") @Operation(summary = "创建联系人") @PreAuthorize("@ss.hasPermission('crm:contact:create')") @@ -110,10 +112,11 @@ public class CrmContactController { @Operation(summary = "获得联系人列表") @PreAuthorize("@ss.hasPermission('crm:contact:query')") public CommonResult> getSimpleContactList() { + // TODO @zyna:建议 contactService 单独搞个 list 接口哈 CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO(); pageReqVO.setPageSize(PAGE_SIZE_NONE); List list = contactService.getContactPage(pageReqVO, getLoginUserId()).getList(); - return success(CrmContactConvert.INSTANCE.convertAllList(list)); + return success(BeanUtils.toBean(list, CrmContactSimpleRespVO.class)); } @GetMapping("/page") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java index 8d023618f..de248d2c6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java @@ -39,8 +39,6 @@ public interface CrmContactConvert { PageResult convertPage(PageResult page); - List convertAllList(List list); - @Mapping(target = "bizId", source = "reqVO.id") CrmPermissionTransferReqBO convert(CrmContactTransferReqVO reqVO, Long userId); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 520038008..d55ce447b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.*; import cn.iocoder.yudao.module.crm.convert.contact.CrmContactConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.mysql.contact.CrmContactMapper; -import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; @@ -47,32 +46,35 @@ public class CrmContactServiceImpl implements CrmContactService { @Resource private AdminUserApi adminUserApi; - @Resource - private CrmContactBusinessMapper contactBusinessLinkMapper; - @Override @Transactional(rollbackFor = Exception.class) + // TODO @zyna:增加操作日志,可以参考 CustomerService;内容是 新建了联系人【名字】 public Long createContact(CrmContactCreateReqVO createReqVO, Long userId) { - // 1.1 校验 + // 1. 校验 validateRelationDataExists(createReqVO); - // 1.2 插入 + + // 2. 插入联系人 CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO); contactMapper.insert(contact); - // 2. 创建数据权限 + // 3. 创建数据权限 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) .setBizType(CrmBizTypeEnum.CRM_CONTACT.getType()).setBizId(contact.getId()) .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); + + // TODO @zyna:特殊逻辑:如果在【商机】详情那,点击【新增联系人】时,可以自动绑定商机 return contact.getId(); } @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) + // TODO @zyna:增加操作日志,可以参考 CustomerService;需要 diff 出字段 public void updateContact(CrmContactUpdateReqVO updateReqVO) { // 1. 校验存在 validateContactExists(updateReqVO.getId()); validateRelationDataExists(updateReqVO); - // 2. 更新 + + // 2. 更新联系人 CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO); contactMapper.updateById(updateObj); } @@ -102,10 +104,15 @@ public class CrmContactServiceImpl implements CrmContactService { public void deleteContact(Long id) { // 校验存在 validateContactExists(id); + // TODO @zyna:如果有关联的合同,不允许删除;Contract.contactId + // 删除 contactMapper.deleteById(id); // 删除数据权限 crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id); + // TODO @zyna:删除商机联系人关联 + + // TODO @puhui999:删除跟进记录 } private void validateContactExists(Long id) { @@ -140,6 +147,8 @@ public class CrmContactServiceImpl implements CrmContactService { } @Override + // TODO @puhui999:权限校验 + // TODO @puhui999:记录操作日志;将联系人【名字】转移给【新负责人】 public void transferContact(CrmContactTransferReqVO reqVO, Long userId) { // 1 校验联系人是否存在 validateContactExists(reqVO.getId()); From 02324f9e6091fbaa6c867e830ea1294717a2033a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 3 Jan 2024 23:30:25 +0800 Subject: [PATCH 51/55] =?UTF-8?q?=E2=9C=A8=20CRM=EF=BC=9A=E3=80=90?= =?UTF-8?q?=E8=81=94=E7=B3=BB=E4=BA=BA=E3=80=91=E7=BB=9F=E4=B8=80=E5=AD=97?= =?UTF-8?q?=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/contact/vo/CrmContactBaseVO.java | 30 ++++++++--------- .../dal/dataobject/contact/CrmContactDO.java | 33 +++++++++++-------- .../dataobject/customer/CrmCustomerDO.java | 7 ++-- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBaseVO.java index eb984884d..f210bfd8f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBaseVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactBaseVO.java @@ -8,11 +8,11 @@ import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotNull; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotNull; import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; @@ -75,29 +75,29 @@ public class CrmContactBaseVO { @ExcelProperty(value = "邮箱",order = 4) private String email; + @Schema(description = "地区编号", example = "20158") + private Integer areaId; + @ExcelProperty(value = "地址",order = 5) @Schema(description = "地址") - private String address; - - @Schema(description = "下次联系时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) - @ExcelProperty(value = "下次联系时间",order = 6) - private LocalDateTime nextTime; + private String detailAddress; @Schema(description = "备注", example = "你说的对") @ExcelProperty(value = "备注",order = 6) private String remark; - @Schema(description = "最后跟进时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - @ExcelProperty(value = "最后跟进时间",order = 6) - private LocalDateTime lastTime; - @Schema(description = "负责人用户编号", example = "14334") @NotNull(message = "负责人不能为空") private Long ownerUserId; - @Schema(description = "地区编号", example = "20158") - private Integer areaId; + @Schema(description = "最后跟进时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @ExcelProperty(value = "最后跟进时间",order = 6) + private LocalDateTime contactLastTime; + + @Schema(description = "下次联系时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + @ExcelProperty(value = "下次联系时间",order = 6) + private LocalDateTime contactNextTime; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java index 75d6bd565..74ced6032 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contact/CrmContactDO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.contact; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -29,9 +30,11 @@ public class CrmContactDO extends BaseDO { @TableId private Long id; /** - * 下次联系时间 + * 客户编号 + * + * 关联 {@link CrmCustomerDO#getId()} */ - private LocalDateTime nextTime; + private Long customerId; /** * 手机号 */ @@ -45,21 +48,20 @@ public class CrmContactDO extends BaseDO { */ private String email; /** - * 客户编号 + * 所在地 + * + * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段 */ - private Long customerId; + private Integer areaId; /** - * 地址 + * 详细地址 */ - private String address; + private String detailAddress; /** * 备注 */ private String remark; - /** - * 最后跟进时间 - */ - private LocalDateTime lastTime; + /** * 直属上级 * @@ -100,10 +102,13 @@ public class CrmContactDO extends BaseDO { private Long ownerUserId; /** - * 所在地 - * - * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段 + * 最后跟进时间 */ - private Integer areaId; + private LocalDateTime contactLastTime; + // TODO @puhui999:增加一个字段 contactLastContent;最后跟进内容 + /** + * 下次联系时间 + */ + private LocalDateTime contactNextTime; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java index 3cc42a5d2..c35778e3e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java @@ -12,7 +12,7 @@ import java.time.LocalDateTime; // TODO 芋艿:调整下字段 /** - * 客户 DO + * CRM 客户 DO * * @author Wanwan */ @@ -104,13 +104,16 @@ public class CrmCustomerDO extends BaseDO { */ private Long ownerUserId; /** - * 地区编号 + * 所在地 + * + * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段 */ private Integer areaId; /** * 详细地址 */ private String detailAddress; + /** * 最后跟进时间 */ From b9f1e8ffaf831e03867a063d21e4a61bd31c7623 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 4 Jan 2024 07:53:00 +0800 Subject: [PATCH 52/55] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9A=E3=80=90?= =?UTF-8?q?=E8=81=94=E7=B3=BB=E4=BA=BA=E3=80=91code=20review=20=E5=95=86?= =?UTF-8?q?=E6=9C=BA=E7=9A=84=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=A1=A5=E5=85=A8?= =?UTF-8?q?=E5=AF=B9=E5=BA=94=E7=9A=84=20todo=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/business/CrmBusinessController.java | 1 + .../dal/dataobject/business/package-info.java | 4 --- .../business/CrmBusinessServiceImpl.java | 27 +++++++++++-------- .../CrmProductCategoryServiceImpl.java | 13 +++++---- 4 files changed, 23 insertions(+), 22 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/package-info.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java index e7bc01e18..5a5a423cd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java @@ -50,6 +50,7 @@ public class CrmBusinessController { @Resource private CrmBusinessStatusService businessStatusService; + // TODO @商机待定:CrmBusinessCreateReqVO、CrmBusinessUpdateReqVO、CrmBusinessRespVO 按照新的 VO 规范 @PostMapping("/create") @Operation(summary = "创建商机") @PreAuthorize("@ss.hasPermission('crm:business:create')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/package-info.java deleted file mode 100644 index df6e44536..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 商机(销售机会) - */ -package cn.iocoder.yudao.module.crm.dal.dataobject.business; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index d2d45ba99..58c2bccfe 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; -import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import jakarta.annotation.Resource; @@ -45,22 +44,22 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Resource private CrmPermissionService permissionService; @Resource - private CrmContactService contactService; - @Resource private CrmContactBusinessService contactBusinessService; @Override @Transactional(rollbackFor = Exception.class) + // TODO @商机待定:操作日志; public Long createBusiness(CrmBusinessCreateReqVO createReqVO, Long userId) { - // 插入 + // 1. 插入商机 CrmBusinessDO business = CrmBusinessConvert.INSTANCE.convert(createReqVO); businessMapper.insert(business); + // TODO 商机待定:插入商机与产品的关联表;校验商品存在 - // 创建数据权限 + // TODO 商机待定:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表 + + // 2. 创建数据权限 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 - - // 返回 return business.getId(); } @@ -68,12 +67,17 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Transactional(rollbackFor = Exception.class) @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) + // TODO @商机待定:操作日志; public void updateBusiness(CrmBusinessUpdateReqVO updateReqVO) { - // 校验存在 + // 1. 校验存在 validateBusinessExists(updateReqVO.getId()); - // 更新 + + // 2. 更新商机 CrmBusinessDO updateObj = CrmBusinessConvert.INSTANCE.convert(updateReqVO); businessMapper.updateById(updateObj); + // TODO 商机待定:插入商机与产品的关联表;校验商品存在 + + // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表 } @Override @@ -82,6 +86,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { public void deleteBusiness(Long id) { // 校验存在 validateBusinessExists(id); + // TODO @商机待定:需要校验有没关联合同。CrmContractDO 的 businessId 字段 + // 删除 businessMapper.deleteById(id); // 删除数据权限 @@ -137,6 +143,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Override @Transactional(rollbackFor = Exception.class) + // TODO @puhui999:操作日志 public void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId) { // 1 校验商机是否存在 validateBusinessExists(reqVO.getId()); @@ -146,8 +153,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())); // 2.2 设置新的负责人 businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); - - // 3. TODO 记录转移日志 } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java index 388f6133b..23fab65e4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java @@ -40,7 +40,7 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService validateParentProductCategory(createReqVO.getParentId()); // 1.2 分类名称是否存在 validateProductNameExists(null, createReqVO.getParentId(), createReqVO.getName()); - // 2. 插入 + // 2. 插入分类 CrmProductCategoryDO category = BeanUtils.toBean(createReqVO, CrmProductCategoryDO.class); productCategoryMapper.insert(category); return category.getId(); @@ -54,7 +54,7 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService validateParentProductCategory(updateReqVO.getParentId()); // 1.3 分类名称是否存在 validateProductNameExists(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); - // 2. 更新 + // 2. 更新分类 CrmProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, CrmProductCategoryDO.class); productCategoryMapper.updateById(updateObj); } @@ -92,18 +92,17 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService @Override public void deleteProductCategory(Long id) { - // TODO zange:参考 mall: ProductCategoryServiceImpl 补充下必要的参数校验; - // 校验存在 + // 1.1 校验存在 validateProductCategoryExists(id); - // 校验是否还有子分类 + // 1.2 校验是否还有子分类 if (productCategoryMapper.selectCountByParentId(id) > 0) { throw exception(product_CATEGORY_EXISTS_CHILDREN); } - // 校验是否被产品使用 + // 1.3 校验是否被产品使用 if (crmProductService.getProductByCategoryId(id) !=null) { throw exception(PRODUCT_CATEGORY_USED); } - // 删除 + // 2. 删除 productCategoryMapper.deleteById(id); } From 2668e0cfebd0b3793d6698dfa66ecb4444e97c8e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 4 Jan 2024 08:01:04 +0800 Subject: [PATCH 53/55] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9A=E3=80=90?= =?UTF-8?q?=E4=BA=A7=E5=93=81=E3=80=91code=20review=20=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=A1=A5=E5=85=A8=E5=AF=B9?= =?UTF-8?q?=E5=BA=94=E7=9A=84=20todo=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/customer/CrmCustomerLimitConfigServiceImpl.java | 3 +++ .../crm/service/customer/CrmCustomerPoolConfigServiceImpl.java | 1 + .../crm/service/product/CrmProductCategoryServiceImpl.java | 3 +++ .../module/crm/service/product/CrmProductServiceImpl.java | 3 +++ 4 files changed, 10 insertions(+) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java index be8ddd968..d9f177549 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerLimitConfigServiceImpl.java @@ -40,6 +40,7 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig private AdminUserApi adminUserApi; @Override + // TODO @puhui999:操作日志 public Long createCustomerLimitConfig(CrmCustomerLimitConfigCreateReqVO createReqVO) { validateUserAndDept(createReqVO.getUserIds(), createReqVO.getDeptIds()); // 插入 @@ -50,6 +51,7 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig } @Override + // TODO @puhui999:操作日志 public void updateCustomerLimitConfig(CrmCustomerLimitConfigUpdateReqVO updateReqVO) { // 校验存在 validateCustomerLimitConfigExists(updateReqVO.getId()); @@ -60,6 +62,7 @@ public class CrmCustomerLimitConfigServiceImpl implements CrmCustomerLimitConfig } @Override + // TODO @puhui999:操作日志 public void deleteCustomerLimitConfig(Long id) { // 校验存在 validateCustomerLimitConfigExists(id); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java index 069bb9ab6..82aa4378f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerPoolConfigServiceImpl.java @@ -38,6 +38,7 @@ public class CrmCustomerPoolConfigServiceImpl implements CrmCustomerPoolConfigSe * @param saveReqVO 更新信息 */ @Override + // TODO @puhui999:操作日志 public void saveCustomerPoolConfig(CrmCustomerPoolConfigSaveReqVO saveReqVO) { // 存在,则进行更新 CrmCustomerPoolConfigDO dbConfig = getCustomerPoolConfig(); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java index 23fab65e4..c91ab87e1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductCategoryServiceImpl.java @@ -35,6 +35,7 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService private CrmProductService crmProductService; @Override + // TODO @puhui999:操作日志 public Long createProductCategory(CrmProductCategoryCreateReqVO createReqVO) { // 1.1 校验父分类存在 validateParentProductCategory(createReqVO.getParentId()); @@ -47,6 +48,7 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService } @Override + // TODO @puhui999:操作日志 public void updateProductCategory(CrmProductCategoryCreateReqVO updateReqVO) { // 1.1 校验存在 validateProductCategoryExists(updateReqVO.getId()); @@ -91,6 +93,7 @@ public class CrmProductCategoryServiceImpl implements CrmProductCategoryService } @Override + // TODO @puhui999:操作日志 public void deleteProductCategory(Long id) { // 1.1 校验存在 validateProductCategoryExists(id); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java index ba7b8ac83..e604a47ac 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java @@ -48,6 +48,7 @@ public class CrmProductServiceImpl implements CrmProductService { private AdminUserApi adminUserApi; @Override + // TODO @puhui999:操作日志 public Long createProduct(CrmProductSaveReqVO createReqVO) { // 校验产品 adminUserApi.validateUserList(Collections.singleton(createReqVO.getOwnerUserId())); @@ -66,6 +67,7 @@ public class CrmProductServiceImpl implements CrmProductService { } @Override + // TODO @puhui999:操作日志 public void updateProduct(CrmProductSaveReqVO updateReqVO) { // 校验产品 updateReqVO.setOwnerUserId(null); // 不修改负责人 @@ -102,6 +104,7 @@ public class CrmProductServiceImpl implements CrmProductService { } @Override + // TODO @puhui999:操作日志 public void deleteProduct(Long id) { // 校验存在 validateProductExists(id); From c6a975151102dc6f221ac86159ad8a38d871ac55 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 4 Jan 2024 09:18:44 +0800 Subject: [PATCH 54/55] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9A=E3=80=90?= =?UTF-8?q?=E5=90=88=E5=90=8C=E3=80=91code=20review=20=E5=90=88=E5=90=8C?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=A1=A5=E5=85=A8=E5=AF=B9?= =?UTF-8?q?=E5=BA=94=E7=9A=84=20todo=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../contract/CrmContractServiceImpl.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 00d6c5e4c..bb010265f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -42,8 +42,10 @@ public class CrmContractServiceImpl implements CrmContractService { private CrmPermissionService crmPermissionService; @Override + // TODO @puhui999:添加操作日志 public Long createContract(CrmContractCreateReqVO createReqVO, Long userId) { - // 插入 + // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO + // 插入合同 CrmContractDO contract = CrmContractConvert.INSTANCE.convert(createReqVO); contractMapper.insert(contract); @@ -57,18 +59,26 @@ public class CrmContractServiceImpl implements CrmContractService { @Override @Transactional(rollbackFor = Exception.class) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) + // TODO @puhui999:添加操作日志 public void updateContract(CrmContractUpdateReqVO updateReqVO) { + // TODO @合同待定:只有草稿、审批中,可以编辑; // 校验存在 validateContractExists(updateReqVO.getId()); - // 更新 + // 更新合同 CrmContractDO updateObj = CrmContractConvert.INSTANCE.convert(updateReqVO); contractMapper.updateById(updateObj); + // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO } + // TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum + + // TODO @合同待定:缺一个发起审批的接口;只有草稿可以发起审批;CrmAuditStatusEnum + @Override @Transactional(rollbackFor = Exception.class) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteContract(Long id) { + // TODO @合同待定:如果被 CrmReceivableDO 所使用,则不允许删除 // 校验存在 validateContractExists(id); // 删除 @@ -112,6 +122,8 @@ public class CrmContractServiceImpl implements CrmContractService { @Override @Transactional(rollbackFor = Exception.class) + // 3. TODO @puhui999:记录转移日志 + // TODO @puhui999:权限校验,这里要搞哇? public void transferContract(CrmContractTransferReqVO reqVO, Long userId) { // 1. 校验合同是否存在 validateContractExists(reqVO.getId()); @@ -121,9 +133,7 @@ public class CrmContractServiceImpl implements CrmContractService { CrmContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType())); // 2.2 设置负责人 contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); - - // 3. TODO 记录转移日志 - } + // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒; } From a974d055b6e2ed323f47aae550e985d38ae8ab08 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 4 Jan 2024 09:41:58 +0800 Subject: [PATCH 55/55] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9A=E3=80=90?= =?UTF-8?q?=E8=BF=98=E6=AC=BE=E3=80=91code=20review=20=E8=BF=98=E6=AC=BE?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=A1=A5=E5=85=A8=E5=AF=B9?= =?UTF-8?q?=E5=BA=94=E7=9A=84=20todo=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/service/business/package-info.java | 4 ---- .../module/crm/service/clue/package-info.java | 4 ---- .../crm/service/product/package-info.java | 4 ---- .../CrmReceivablePlanServiceImpl.java | 6 +++++ .../receivable/CrmReceivableServiceImpl.java | 22 +++++++++++++++---- .../crm/service/receivable/package-info.java | 4 ---- 6 files changed, 24 insertions(+), 20 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/package-info.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/package-info.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/package-info.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/package-info.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/package-info.java deleted file mode 100644 index 8995e1242..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 商机(销售机会) - */ -package cn.iocoder.yudao.module.crm.service.business; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/package-info.java deleted file mode 100644 index 5cb8b6ec7..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 线索 - */ -package cn.iocoder.yudao.module.crm.service.clue; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/package-info.java deleted file mode 100644 index cae179aea..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 产品表 - */ -package cn.iocoder.yudao.module.crm.service.product; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index e6940e793..453c82d39 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -52,7 +52,10 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { private CrmPermissionService crmPermissionService; @Override + // TODO @puhui999:操作日志 public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO, Long userId) { + // TODO @liuhongfeng:第几期的计算;基于是 contractId + contractDO 的第几个还款 + // TODO @liuhongfeng contractId:校验合同是否存在 // 插入 CrmReceivablePlanDO receivablePlan = CrmReceivablePlanConvert.INSTANCE.convert(createReqVO); receivablePlan.setFinishStatus(false); @@ -87,7 +90,9 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) + // TODO @puhui999:操作日志 public void updateReceivablePlan(CrmReceivablePlanUpdateReqVO updateReqVO) { + // TODO @liuhongfeng:如果已经有对应的还款,则不允许编辑; // 校验存在 validateReceivablePlanExists(updateReqVO.getId()); @@ -136,6 +141,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { return receivablePlanMapper.selectPageByCustomerId(pageReqVO); } + // TODO @puhui999:这个没有 transfer 接口;可能是的哈 @Override public void transferReceivablePlan(CrmReceivablePlanTransferReqVO reqVO, Long userId) { // 1 校验回款计划是否存在 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index 6071c2615..5100ddd6e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -53,10 +53,10 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { @Resource private CrmPermissionService crmPermissionService; - // TODO @liuhongfeng:创建还款后,是不是什么时候,要更新 plan? @Override + // TODO @puhui999:操作日志 public Long createReceivable(CrmReceivableCreateReqVO createReqVO) { - // 插入 + // 插入还款 CrmReceivableDO receivable = CrmReceivableConvert.INSTANCE.convert(createReqVO); if (ObjectUtil.isNull(receivable.getAuditStatus())) { receivable.setAuditStatus(CommonStatusEnum.ENABLE.getStatus()); @@ -64,15 +64,17 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { receivable.setAuditStatus(CrmAuditStatusEnum.DRAFT.getStatus()); // TODO @liuhongfeng:一般来说,逻辑的写法,是要先检查,后操作 db;所以,你这个 check 应该放到 CrmReceivableDO receivable 之前; - // 校验 checkReceivable(receivable); receivableMapper.insert(receivable); + + // TODO @liuhongfeng:需要更新关联的 plan return receivable.getId(); } // TODO @liuhongfeng:这里的括号要注意排版; private void checkReceivable(CrmReceivableDO receivable) { + // TODO @liuhongfeng:校验 no 的唯一性 // TODO @liuhongfeng:这个放在参数校验合适 if (ObjectUtil.isNull(receivable.getContractId())) { throw exception(CONTRACT_NOT_EXISTS); @@ -96,17 +98,29 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { } @Override + // TODO @puhui999:操作日志 + // TODO @puhui999:权限校验 public void updateReceivable(CrmReceivableUpdateReqVO updateReqVO) { // 校验存在 validateReceivableExists(updateReqVO.getId()); + // TODO @liuhongfeng:只有在草稿、审核中,可以提交修改 - // 更新 + // 更新还款 CrmReceivableDO updateObj = CrmReceivableConvert.INSTANCE.convert(updateReqVO); receivableMapper.updateById(updateObj); + + // TODO @liuhongfeng:需要更新关联的 plan } + // TODO @liuhongfeng:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum + + // TODO @liuhongfeng:缺一个发起审批的接口;只有草稿可以发起审批;CrmAuditStatusEnum + @Override + // TODO @puhui999:操作日志 + // TODO @puhui999:权限校验 public void deleteReceivable(Long id) { + // TODO @liuhongfeng:如果被 CrmReceivablePlanDO 所使用,则不允许删除 // 校验存在 validateReceivableExists(id); // 删除 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/package-info.java deleted file mode 100644 index 4004b301d..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 回款 - */ -package cn.iocoder.yudao.module.crm.service.receivable;