From f8604e17a104b64891dd9b8e7fd6f18a59992312 Mon Sep 17 00:00:00 2001 From: owen Date: Sat, 25 Nov 2023 15:53:07 +0800 Subject: [PATCH 001/151] =?UTF-8?q?=E8=90=A5=E9=94=80=EF=BC=9A=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=E6=96=87=E7=AB=A0=E5=AD=97=E6=AE=B5=E5=90=8D=E3=80=81?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=96=B9=E6=B3=95=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/controller/app/article/AppArticleController.java | 2 +- .../controller/app/article/vo/article/AppArticleRespVO.java | 2 +- 2 files changed, 2 insertions(+), 2 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..eb99f9902 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 @@ -52,7 +52,7 @@ public class AppArticleController { @RequestMapping("/get") @Operation(summary = "获得文章详情") @Parameter(name = "id", description = "文章编号", example = "1024") - public CommonResult getArticlePage(@RequestParam("id") Long id) { + public CommonResult getArticle(@RequestParam("id") Long id) { return success(ArticleConvert.INSTANCE.convert01(articleService.getArticle(id))); } 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; From 5c395fc1c4ee7e685c1cc407c405e318c55d1ddb Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 8 Dec 2023 15:27:58 +0800 Subject: [PATCH 002/151] =?UTF-8?q?CRM:=20=E5=AE=8C=E5=96=84=20code=20revi?= =?UTF-8?q?ew=20=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=E6=8F=90=E5=88=B0?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C=E9=87=8D=E6=96=B0=E5=B0=81?= =?UTF-8?q?=E8=A3=85=20CrmQueryWrapperUtils?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../mybatis/core/mapper/BaseMapperX.java | 13 +++ ...rmSceneEnum.java => CrmSceneTypeEnum.java} | 13 ++- .../admin/business/CrmBusinessController.java | 10 +- .../admin/contact/CrmContactController.java | 11 +- .../admin/contract/CrmContractController.java | 8 +- .../customer/vo/CrmCustomerPageReqVO.java | 16 ++- .../receivable/CrmReceivableController.java | 11 +- .../CrmReceivablePlanController.java | 11 +- .../module/crm/controller/package-info.java | 6 -- .../convert/customer/CrmCustomerConvert.java | 3 +- .../dal/mysql/customer/CrmCustomerMapper.java | 37 +++---- .../crm/framework/vo/CrmBasePageReqVO.java | 25 ----- .../service/customer/CrmCustomerService.java | 4 +- .../customer/CrmCustomerServiceImpl.java | 13 +-- .../module/crm/util/CrmQueryPageUtils.java | 66 ------------ .../module/crm/util/CrmQueryWrapperUtils.java | 100 ++++++++++++++++++ .../main/resources/codegen/vue/api/api.js.vm | 15 ++- .../module/system/api/user/AdminUserApi.java | 7 +- .../system/api/user/AdminUserApiImpl.java | 36 ++++--- yudao-server/pom.xml | 10 +- 21 files changed, 223 insertions(+), 194 deletions(-) rename yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/{CrmSceneEnum.java => CrmSceneTypeEnum.java} (77%) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/vo/CrmBasePageReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryPageUtils.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java diff --git a/pom.xml b/pom.xml index df8fc2c6f..26dec77cf 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ - + yudao-module-crm 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..b0c0f784e 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 @@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.toolkit.Db; import com.github.yulichang.base.MPJBaseMapper; import com.github.yulichang.interfaces.MPJBaseJoin; +import com.github.yulichang.wrapper.MPJLambdaWrapper; import org.apache.ibatis.annotations.Param; import java.util.Collection; @@ -40,6 +41,18 @@ public interface BaseMapperX extends MPJBaseMapper { return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); } + default PageResult selectJoinPage(PageParam pageParam, Class clazz, MPJLambdaWrapper lambdaWrapper) { + // 特殊:不分页,直接查询全部 + if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageNo())) { + List list = selectJoinList(clazz, lambdaWrapper); + return new PageResult<>(list, (long) list.size()); + } + + IPage mpPage = MyBatisUtils.buildPage(pageParam); + mpPage = selectJoinPage(mpPage, clazz, lambdaWrapper); + return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); + } + default PageResult selectJoinPage(PageParam pageParam, Class resultTypeClass, MPJBaseJoin joinQueryWrapper) { IPage mpPage = MyBatisUtils.buildPage(pageParam); selectJoinPage(mpPage, resultTypeClass, joinQueryWrapper); diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java similarity index 77% rename from yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneEnum.java rename to yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java index a8d892a90..dc714250d 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneEnum.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java @@ -7,7 +7,6 @@ import lombok.Getter; import java.util.Arrays; -// TODO @puhui999:这个枚举,要不改成 CrmSceneTypeEnum /** * CRM 列表检索场景 * @@ -15,14 +14,14 @@ import java.util.Arrays; */ @Getter @AllArgsConstructor -public enum CrmSceneEnum implements IntArrayValuable { +public enum CrmSceneTypeEnum implements IntArrayValuable { OWNER(1, "我负责的"), FOLLOW(2, "我关注的"), - // TODO @puhui999:还有一个我参与的 - SUBORDINATE(3, "下属负责的"); + INVOLVED(3, "我参与的"), + SUBORDINATE(4, "下属负责的"); - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmSceneEnum::getType).toArray(); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmSceneTypeEnum::getType).toArray(); /** * 场景类型 @@ -41,6 +40,10 @@ public enum CrmSceneEnum implements IntArrayValuable { return ObjUtil.equal(FOLLOW.getType(), type); } + public static boolean isInvolved(Integer type) { + return ObjUtil.equal(INVOLVED.getType(), type); + } + public static boolean isSubordinate(Integer type) { return ObjUtil.equal(SUBORDINATE.getType(), type); } 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 119440378..0c6756bc7 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 @@ -22,13 +22,13 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; 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 jakarta.servlet.http.HttpServletResponse; +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.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import java.io.IOException; import java.util.List; import java.util.Objects; @@ -102,7 +102,7 @@ public class CrmBusinessController { // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈; Set customerIds = pageResult.getList().stream() .map(CrmBusinessDO::getCustomerId).filter(Objects::nonNull).collect(Collectors.toSet()); - List customerList = customerService.getCustomerList(customerIds); + List customerList = customerService.getCustomerList(customerIds, getLoginUserId()); // 处理商机状态类型名称回显 Set statusTypeIds = pageResult.getList().stream() .map(CrmBusinessDO::getStatusTypeId).filter(Objects::nonNull).collect(Collectors.toSet()); @@ -127,7 +127,7 @@ public class CrmBusinessController { // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈; Set customerIds = pageResult.getList().stream() .map(CrmBusinessDO::getCustomerId).filter(Objects::nonNull).collect(Collectors.toSet()); - List customerList = customerService.getCustomerList(customerIds); + List customerList = customerService.getCustomerList(customerIds, getLoginUserId()); // 处理商机状态类型名称回显 Set statusTypeIds = pageResult.getList().stream() .map(CrmBusinessDO::getStatusTypeId).filter(Objects::nonNull).collect(Collectors.toSet()); 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 df55ef413..811b4758e 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 @@ -22,14 +22,14 @@ import com.google.common.collect.Lists; 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 jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; 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.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import java.io.IOException; import java.util.Collections; import java.util.List; @@ -95,7 +95,8 @@ public class CrmContactController { Map userMap = adminUserApi.getUserMap(CollUtil.removeNull(Lists.newArrayList( NumberUtil.parseLong(contact.getCreator()), contact.getOwnerUserId()))); // 2. 获取客户信息 - List customerList = customerService.getCustomerList(Collections.singletonList(contact.getCustomerId())); + List customerList = customerService.getCustomerList( + Collections.singletonList(contact.getCustomerId()), getLoginUserId()); // 3. 直属上级 List parentContactList = contactService.getContactList(Collections.singletonList(contact.getParentId())); return success(ContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList)); @@ -150,7 +151,7 @@ public class CrmContactController { } // 1. 获取客户列表 List crmCustomerDOList = customerService.getCustomerList( - convertSet(contactList, CrmContactDO::getCustomerId)); + convertSet(contactList, CrmContactDO::getCustomerId), getLoginUserId()); // 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/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 b1581bc62..24426cd5a 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 @@ -18,13 +18,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; 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 jakarta.servlet.http.HttpServletResponse; +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.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import java.io.IOException; import java.util.List; import java.util.Map; @@ -124,7 +124,7 @@ public class CrmContractController { } // 1. 获取客户列表 List customerList = customerService.getCustomerList( - convertSet(contactList, CrmContractDO::getCustomerId)); + convertSet(contactList, CrmContractDO::getCustomerId), getLoginUserId()); // 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/customer/vo/CrmCustomerPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java index 59d6ae360..830b7da6d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; -import cn.iocoder.yudao.module.crm.framework.vo.CrmBasePageReqVO; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -10,7 +12,7 @@ import lombok.ToString; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class CrmCustomerPageReqVO extends CrmBasePageReqVO { +public class CrmCustomerPageReqVO extends PageParam { @Schema(description = "客户名称", example = "赵六") private String name; @@ -27,4 +29,14 @@ public class CrmCustomerPageReqVO extends CrmBasePageReqVO { @Schema(description = "客户来源", example = "1") private Integer source; + /** + * 场景类型,为 null 时则表示全部 + */ + @Schema(description = "场景类型", example = "1") + @InEnum(CrmSceneTypeEnum.class) + private Integer sceneType; + + @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + private Boolean pool; // null 则表示为不是公海数据 + } 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 45ea6f020..4c4be4a25 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 @@ -23,13 +23,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; 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 jakarta.servlet.http.HttpServletResponse; +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.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import java.io.IOException; import java.util.List; import java.util.Map; @@ -39,6 +39,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - CRM 回款") @RestController @@ -111,7 +112,7 @@ public class CrmReceivableController { @PreAuthorize("@ss.hasPermission('crm:receivable:export')") @OperateLog(type = EXPORT) public void exportReceivableExcel(@Valid CrmReceivablePageReqVO exportReqVO, - HttpServletResponse response) throws IOException { + HttpServletResponse response) throws IOException { PageResult pageResult = receivableService.getReceivablePage(exportReqVO); // 导出 Excel ExcelUtils.write(response, "回款.xls", "数据", CrmReceivableRespVO.class, @@ -131,7 +132,7 @@ public class CrmReceivableController { } // 1. 获取客户列表 List customerList = customerService.getCustomerList( - convertSet(receivableList, CrmReceivableDO::getCustomerId)); + convertSet(receivableList, CrmReceivableDO::getCustomerId), getLoginUserId()); // 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 fe569a087..f8e2e6ecd 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 @@ -25,13 +25,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; 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 jakarta.servlet.http.HttpServletResponse; +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.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import java.io.IOException; import java.util.List; import java.util.Map; @@ -41,6 +41,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - CRM 回款计划") @RestController @@ -115,7 +116,7 @@ public class CrmReceivablePlanController { @PreAuthorize("@ss.hasPermission('crm:receivable-plan:export')") @OperateLog(type = EXPORT) public void exportReceivablePlanExcel(@Valid CrmReceivablePlanPageReqVO exportReqVO, - HttpServletResponse response) throws IOException { + HttpServletResponse response) throws IOException { PageResult pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO); // 导出 Excel ExcelUtils.write(response, "回款计划.xls", "数据", CrmReceivablePlanRespVO.class, @@ -135,7 +136,7 @@ public class CrmReceivablePlanController { } // 1. 获取客户列表 List customerList = customerService.getCustomerList( - convertSet(receivablePlanList, CrmReceivablePlanDO::getCustomerId)); + convertSet(receivablePlanList, CrmReceivablePlanDO::getCustomerId), getLoginUserId()); // 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/controller/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java deleted file mode 100644 index 8354b3176..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 提供 RESTful API 给前端: - * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 - * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 - */ -package cn.iocoder.yudao.module.crm.controller; 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 fcf643f66..0e21b26b8 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 @@ -55,8 +55,7 @@ public interface CrmCustomerConvert { List convertList02(List list); @Mappings({ - @Mapping(target = "bizId", source = "reqVO.id"), - @Mapping(target = "newOwnerUserId", source = "reqVO.id") + @Mapping(target = "bizId", source = "reqVO.id") }) CrmPermissionTransferReqBO convert(CrmCustomerTransferReqVO reqVO, Long userId); 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 0ce9d9f03..9c29c668f 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 @@ -1,16 +1,13 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer; -import cn.iocoder.yudao.framework.common.pojo.PageParam; 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.MPJLambdaWrapperX; -import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.util.CrmQueryPageUtils; +import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; @@ -30,35 +27,25 @@ public interface CrmCustomerMapper extends BaseMapperX { .set(CrmCustomerDO::getOwnerUserId, ownerUserId)); } - /** - * 获取客户分页 - * - * @param pageReqVO 请求 - * @param userId 用户编号 - * @param subordinateIds 下属用户编号 - * @param isAdmin 是否为管理 - * @return 客户分页数据 - */ - default PageResult selectPage(CrmCustomerPageReqVO pageReqVO, Long userId, Collection subordinateIds, Boolean isAdmin) { - IPage mpPage = MyBatisUtils.buildPage(pageReqVO); + default PageResult selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); // 构建数据权限连表条件 - CrmQueryPageUtils.builderQuery(mpjLambdaWrapperX, pageReqVO, userId, - CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, subordinateIds, isAdmin); + CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, + userId, pageReqVO.getSceneType(), pageReqVO.getPool()); mpjLambdaWrapperX.selectAll(CrmCustomerDO.class) .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) .eqIfPresent(CrmCustomerDO::getMobile, pageReqVO.getMobile()) .eqIfPresent(CrmCustomerDO::getIndustryId, pageReqVO.getIndustryId()) .eqIfPresent(CrmCustomerDO::getLevel, pageReqVO.getLevel()) .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource()); - // 特殊:不分页,直接查询全部 - // TODO @puhui999:下面这个,封装一个方法;从 56 到 61 这里哈; - if (PageParam.PAGE_SIZE_NONE.equals(pageReqVO.getPageNo())) { - List list = selectJoinList(CrmCustomerDO.class, mpjLambdaWrapperX); - return new PageResult<>(list, (long) list.size()); - } - mpPage = selectJoinPage(mpPage, CrmCustomerDO.class, mpjLambdaWrapperX); - return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); + return selectJoinPage(pageReqVO, CrmCustomerDO.class, mpjLambdaWrapperX); + } + + default List selectBatchIds(Collection ids, Long userId) { + MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); + // 构建数据权限连表条件 + CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId); + return selectJoinList(CrmCustomerDO.class, mpjLambdaWrapperX); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/vo/CrmBasePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/vo/CrmBasePageReqVO.java deleted file mode 100644 index 14070fa19..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/vo/CrmBasePageReqVO.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.crm.framework.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.crm.enums.common.CrmSceneEnum; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -@Schema(description = "管理后台 - CRM 分页 Base Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -public class CrmBasePageReqVO extends PageParam { - - /** - * 场景类型,为 null 时则表示全部 - */ - @Schema(description = "场景类型", example = "1") - @InEnum(CrmSceneEnum.class) - private Integer sceneType; - - @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") - private Boolean pool; // null 则表示为不是公海数据 - -} 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 bf22413d4..1bd1fee47 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 @@ -6,8 +6,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageR 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.dal.dataobject.customer.CrmCustomerDO; - import jakarta.validation.Valid; + import java.util.Collection; import java.util.List; @@ -56,7 +56,7 @@ public interface CrmCustomerService { * @return 客户列表 * @author ljlleo */ - List getCustomerList(Collection ids); + List getCustomerList(Collection ids, 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 e3723c281..2460a33fb 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 @@ -15,11 +15,11 @@ 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 jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -93,17 +93,16 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override - public List getCustomerList(Collection ids) { + public List getCustomerList(Collection ids, Long userId) { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } - return customerMapper.selectBatchIds(ids); + return customerMapper.selectBatchIds(ids, userId); } @Override public PageResult getCustomerPage(CrmCustomerPageReqVO pageReqVO, Long userId) { - boolean admin = false; // TODO 如果是管理员 - return customerMapper.selectPage(pageReqVO, userId, adminUserApi.getSubordinateIds(userId), admin); + return customerMapper.selectPage(pageReqVO, userId); } /** @@ -128,9 +127,11 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 1. 校验客户是否存在 validateCustomer(reqVO.getId()); - // 2. 数据权限转移 + // 2.1 数据权限转移 crmPermissionService.transferPermission( CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); + // 2.2 转移后重新设置负责人 + customerMapper.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/util/CrmQueryPageUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryPageUtils.java deleted file mode 100644 index 5830a24a3..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryPageUtils.java +++ /dev/null @@ -1,66 +0,0 @@ -package cn.iocoder.yudao.module.crm.util; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.util.ObjUtil; -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.CrmSceneEnum; -import cn.iocoder.yudao.module.crm.framework.vo.CrmBasePageReqVO; -import com.baomidou.mybatisplus.core.toolkit.support.SFunction; -import com.github.yulichang.wrapper.MPJLambdaWrapper; - -import jakarta.annotation.Nullable; -import java.util.Collection; - -/** - * CRM 分页查询工具类 - * - * @author HUIHUI - */ -public class CrmQueryPageUtils { - - // TODO @puhui999:是不是弱化 CrmBasePageReqVO,把 sceneType 作为参数传入。默认其实 pool 不一定要传递的 - /** - * 构造 CRM 数据类型数据分页查询条件 - * - * @param queryMapper 连表查询对象 - * @param reqVO 查询条件 - * @param userId 用户编号 - * @param bizType 数据类型 {@link CrmBizTypeEnum} - * @param bizId 数据编号 - * @param subordinateIds 下属用户编号,可为空 - */ - public static , V extends CrmBasePageReqVO, S> void builderQuery( - T queryMapper, V reqVO, Long userId, - Integer bizType, SFunction bizId, - @Nullable Collection subordinateIds, // TODO @puhui999:subordinateIds 可以优化成 subordinateUserIds - Boolean isAdmin) { - // TODO @puhui999:是不是特殊处理,让这个 util 有状态,这样 isAdmin 直接从这里读取;subordinateIds 也是;这样,可以简化参数; - // 1. 构建数据权限连表条件 - if (ObjUtil.notEqual(isAdmin, Boolean.TRUE)) { // 管理员不需要数据权限 - queryMapper.innerJoin(CrmPermissionDO.class, on -> - on.eq(CrmPermissionDO::getBizType, bizType).eq(CrmPermissionDO::getBizId, bizId) - .eq(CrmPermissionDO::getUserId, userId)); - } - // 2. 拼接公海的查询条件 - if (ObjUtil.equal(reqVO.getPool(), Boolean.TRUE)) { // 情况一:公海 - queryMapper.isNull("owner_user_id"); - } else { // 情况二:不是公海 - queryMapper.isNotNull("owner_user_id"); - } - // 3. 拼接场景的查询条件 - // TODO @puhui999::1 处的数据权限,应该和 3 处的场景是结合的? - // null 时:一种处理 - // 1:一种条件; - // 2:一种条件; - // 3:一种条件; - if (CrmSceneEnum.isOwner(reqVO.getSceneType())) { // 场景一:我负责的数据 - queryMapper.eq("owner_user_id", userId); - } - // TODO puhui999: 这里有一个疑问:如果下属负责的数据权限中没有自己的话还能看吗?回复:不能 - if (CrmSceneEnum.isSubordinate(reqVO.getSceneType()) && CollUtil.isNotEmpty(subordinateIds)) { // 场景三:下属负责的数据 - queryMapper.in("owner_user_id", subordinateIds); - } - } - -} 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 new file mode 100644 index 000000000..23e422332 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java @@ -0,0 +1,100 @@ +package cn.iocoder.yudao.module.crm.util; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.extra.spring.SpringUtil; +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.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.wrapper.MPJLambdaWrapper; + +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +/** + * CRM 分页查询工具类 + * + * @author HUIHUI + */ +public class CrmQueryWrapperUtils { + + /** + * 构造 CRM 数据类型数据分页查询条件 + * + * @param queryMapper 连表查询对象 + * @param bizType 数据类型 {@link CrmBizTypeEnum} + * @param bizId 数据编号 + * @param userId 用户编号 + * @param sceneType 场景类型 + * @param pool 公海 + */ + public static , S> void builderPageQuery( + T queryMapper, Integer bizType, SFunction bizId, Long userId, Integer sceneType, Boolean pool) { + // 1. 构建数据权限连表条件 + if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 + queryMapper.innerJoin(CrmPermissionDO.class, on -> + on.eq(CrmPermissionDO::getBizType, bizType).eq(CrmPermissionDO::getBizId, bizId) + .eq(CrmPermissionDO::getUserId, userId)); + } + // 1.2 场景一:我负责的数据 + if (CrmSceneTypeEnum.isOwner(sceneType)) { + queryMapper.eq("owner_user_id", userId); + } + // 1.3 场景一:我参与的数据 + if (CrmSceneTypeEnum.isInvolved(sceneType)) { + queryMapper.ne("owner_user_id", userId); + } + // 1.4 场景二:下属负责的数据 + if (CrmSceneTypeEnum.isSubordinate(sceneType)) { + List subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId); + if (CollUtil.isNotEmpty(subordinateUsers)) { + queryMapper.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId)); + } + } + + // 2. 拼接公海的查询条件 + if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海 + queryMapper.isNull("owner_user_id"); + } else { // 情况二:不是公海 + queryMapper.isNotNull("owner_user_id"); + } + } + + /** + * 构造 CRM 数据类型批量数据查询条件 + * + * @param queryMapper 连表查询对象 + * @param bizType 数据类型 {@link CrmBizTypeEnum} + * @param bizIds 数据编号 + * @param userId 用户编号 + */ + public static , S> void builderListQueryBatch( + T queryMapper, Integer bizType, Collection bizIds, Long userId) { + // 1. 构建数据权限连表条件 + if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 + queryMapper.innerJoin(CrmPermissionDO.class, on -> + on.eq(CrmPermissionDO::getBizType, bizType).in(CrmPermissionDO::getBizId, bizIds) + .eq(CrmPermissionDO::getUserId, userId)); + } + } + + private static AdminUserApi getAdminUserApi() { + return SpringUtil.getBean(AdminUserApi.class); + } + + /** + * 校验用户是否是管理员 + * + * @param userId 用户编号 + * @return 是/否 + */ + private static boolean validateAdminUser(Long userId) { + return false; + } + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm index bfe2dc007..fcc2e9197 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm @@ -77,7 +77,6 @@ export function export${simpleClassName}Excel(params) { // ==================== 子表($subTable.classComment) ==================== ## 情况一:MASTER_ERP 时,需要分查询页子表 #if ( $table.templateType == 11 ) - // 获得${subTable.classComment}分页 export function get${subSimpleClassName}Page(params) { return request({ @@ -89,20 +88,18 @@ export function export${simpleClassName}Excel(params) { ## 情况二:非 MASTER_ERP 时,需要列表查询子表 #else #if ( $subTable.subJoinMany ) - // 获得${subTable.classComment}列表 export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}) { return request({ - url: `${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField}, + url: '${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=' + ${subJoinColumn.javaField}, method: 'get' }) } #else - // 获得${subTable.classComment} export function get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}) { return request({ - url: `${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField}, + url: '${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=' + ${subJoinColumn.javaField}, method: 'get' }) } @@ -113,7 +110,7 @@ export function export${simpleClassName}Excel(params) { // 新增${subTable.classComment} export function create${subSimpleClassName}(data) { return request({ - url: `${baseURL}/${subSimpleClassName_strikeCase}/create`, + url: '${baseURL}/${subSimpleClassName_strikeCase}/create', method: 'post', data }) @@ -122,7 +119,7 @@ export function export${simpleClassName}Excel(params) { // 修改${subTable.classComment} export function update${subSimpleClassName}(data) { return request({ - url: `${baseURL}/${subSimpleClassName_strikeCase}/update`, + url: '${baseURL}/${subSimpleClassName_strikeCase}/update', method: 'post', data }) @@ -131,7 +128,7 @@ export function export${simpleClassName}Excel(params) { // 删除${subTable.classComment} export function delete${subSimpleClassName}(id) { return request({ - url: `${baseURL}/${subSimpleClassName_strikeCase}/delete?id=` + id, + url: '${baseURL}/${subSimpleClassName_strikeCase}/delete?id=' + id, method: 'delete' }) } @@ -139,7 +136,7 @@ export function export${simpleClassName}Excel(params) { // 获得${subTable.classComment} export function get${subSimpleClassName}(id) { return request({ - url: `${baseURL}/${subSimpleClassName_strikeCase}/get?id=` + id, + url: '${baseURL}/${subSimpleClassName_strikeCase}/get?id=' + id, method: 'get' }) } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java index 39f65d3e7..c4510ba08 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java @@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Set; /** * Admin 用户 API 接口 @@ -27,10 +26,10 @@ public interface AdminUserApi { /** * 通过用户 ID 查询用户下属 * - * @param id 用户编号 - * @return 用户下属用户编号列表 + * @param userId 用户编号 + * @return 用户下属用户列表 */ - Set getSubordinateIds(Long id); + List getUserListBySubordinate(Long userId); /** * 通过用户 ID 查询用户们 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java index 25bba01b0..c7055114e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.system.api.user; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; @@ -7,13 +8,13 @@ import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; import cn.iocoder.yudao.module.system.service.dept.DeptService; import cn.iocoder.yudao.module.system.service.user.AdminUserService; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; -import jakarta.annotation.Resource; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Set; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @@ -37,21 +38,32 @@ public class AdminUserApiImpl implements AdminUserApi { } @Override - public Set getSubordinateIds(Long id) { - AdminUserDO user = userService.getUser(id); + public List getUserListBySubordinate(Long userId) { + // 1. 获取用户信息 + AdminUserDO user = userService.getUser(userId); if (user == null) { - return null; + return Collections.emptyList(); } - Set subordinateIds = null; // 下属用户编号 + // 2.1 获取用户负责的部门 + ArrayList deptIds = new ArrayList<>(); DeptDO dept = deptService.getDept(user.getDeptId()); - // TODO @puhui999:需要递归查询到子部门;并且要排除到自己噢。 - // TODO @puhui999:保持 if return 原则,这里其实要判断不等于,则返回 null;最好返回 空集合,上面也是 - if (ObjUtil.equal(dept.getLeaderUserId(), id)) { // 校验是否是该部门的负责人 - List users = userService.getUserListByDeptIds(Collections.singletonList(dept.getId())); - subordinateIds = convertSet(users, AdminUserDO::getId); + if (dept == null) { + return Collections.emptyList(); } - return subordinateIds; + if (ObjUtil.notEqual(dept.getLeaderUserId(), userId)) { // 校验为负责人 + return Collections.emptyList(); + } + deptIds.add(dept.getId()); // 加入此部门 + // 2.2 获取所有子部门 + List childDeptList = deptService.getChildDeptList(dept.getId()); + if (CollUtil.isNotEmpty(childDeptList)) { + deptIds.addAll(convertSet(childDeptList, DeptDO::getId)); + } + // 2.3 获取用户信息 + List users = userService.getUserListByDeptIds(deptIds); + users.removeIf(item -> ObjUtil.equal(item.getId(), userId)); // 排除自己 + return BeanUtils.toBean(users, AdminUserRespDTO.class); } @Override diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 20b67725b..40086477b 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -92,11 +92,11 @@ - - - - - + + cn.iocoder.boot + yudao-module-crm-biz + ${revision} + From 9ea0607339a091c3f1bf1c8d921ae1c3017158f8 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 8 Dec 2023 17:16:34 +0800 Subject: [PATCH 003/151] =?UTF-8?q?CRM-=E5=95=86=E6=9C=BA=EF=BC=9A?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9D=83=E9=99=90=E5=85=B3=E8=81=94=E3=80=81?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E5=88=86=E9=A1=B5=E6=9F=A5=E8=AF=A2=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9D=83=E9=99=90=E5=85=B3=E8=81=94=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/business/CrmBusinessController.java | 10 +---- .../vo/business/CrmBusinessPageReqVO.java | 12 ++++++ .../convert/business/CrmBusinessConvert.java | 3 +- .../dataobject/business/CrmBusinessDO.java | 7 ++++ .../dal/mysql/business/CrmBusinessMapper.java | 38 ++++++++++++------ .../service/business/CrmBusinessService.java | 4 +- .../business/CrmBusinessServiceImpl.java | 40 ++++++++----------- 7 files changed, 67 insertions(+), 47 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 0c6756bc7..c6fededc9 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 @@ -36,6 +36,7 @@ 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.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -143,20 +144,13 @@ public class CrmBusinessController { return success(CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList)); } - @GetMapping("/pool-page") - @Operation(summary = "获得商机公海分页") - @PreAuthorize("@ss.hasPermission('crm:business:query')") - public CommonResult> getBusinessPoolPage(@Valid CrmBusinessPageReqVO pageVO) { - // TODO puhui999: 等数据权限完善后再实现 - return null; - } - @GetMapping("/export-excel") @Operation(summary = "导出商机 Excel") @PreAuthorize("@ss.hasPermission('crm:business:export')") @OperateLog(type = EXPORT) public void exportBusinessExcel(@Valid CrmBusinessPageReqVO exportReqVO, HttpServletResponse response) throws IOException { + exportReqVO.setPageSize(PAGE_SIZE_NONE); PageResult pageResult = businessService.getBusinessPage(exportReqVO, getLoginUserId()); // 导出 Excel ExcelUtils.write(response, "商机.xls", "数据", CrmBusinessExcelVO.class, 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 c756b79cb..eb208b252 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 @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -18,4 +20,14 @@ public class CrmBusinessPageReqVO extends PageParam { @Schema(description = "客户编号", example = "10795") private Long customerId; + /** + * 场景类型,为 null 时则表示全部 + */ + @Schema(description = "场景类型", example = "1") + @InEnum(CrmSceneTypeEnum.class) + private Integer sceneType; + + @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + private Boolean pool; // null 则表示为不是公海数据 + } 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 affb57b55..72acdd094 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 @@ -39,8 +39,7 @@ public interface CrmBusinessConvert { List convertList02(List list); @Mappings({ - @Mapping(target = "bizId", source = "reqVO.id"), - @Mapping(target = "newOwnerUserId", source = "reqVO.id") + @Mapping(target = "bizId", source = "reqVO.id") }) CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java index 2bc1daa41..f1d5d4431 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java @@ -97,4 +97,11 @@ public class CrmBusinessDO extends BaseDO { */ private Integer followUpStatus; + /** + * 负责人的用户编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long ownerUserId; + } 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 0f3964bf7..3074094b4 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 @@ -2,13 +2,16 @@ package cn.iocoder.yudao.module.crm.dal.mysql.business; 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.business.vo.business.CrmBusinessPageReqVO; -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.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 java.util.Collection; +import java.util.List; /** * 商机 Mapper @@ -18,18 +21,29 @@ import java.util.Collection; @Mapper public interface CrmBusinessMapper extends BaseMapperX { - default PageResult selectPage(CrmBusinessPageReqVO reqVO, Collection ids) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .in(CrmBusinessDO::getId, ids) - .likeIfPresent(CrmBusinessDO::getName, reqVO.getName()) - .orderByDesc(CrmBusinessDO::getId)); + default int updateOwnerUserIdById(Long id, Long ownerUserId) { + return update(new LambdaUpdateWrapper() + .eq(CrmBusinessDO::getId, id) + .set(CrmBusinessDO::getOwnerUserId, ownerUserId)); } - default PageResult selectPageByCustomer(CrmContractPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eq(CrmBusinessDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 - .likeIfPresent(CrmBusinessDO::getName, reqVO.getName()) - .orderByDesc(CrmBusinessDO::getId)); + default PageResult selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { + MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); + // 构建数据权限连表条件 + CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId, + userId, pageReqVO.getSceneType(), pageReqVO.getPool()); + mpjLambdaWrapperX.selectAll(CrmBusinessDO.class) + .eq(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 必须传递 + .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) + .orderByDesc(CrmBusinessDO::getId); + return selectJoinPage(pageReqVO, CrmBusinessDO.class, mpjLambdaWrapperX); + } + + default List selectBatchIds(Collection ids, Long userId) { + MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); + // 构建数据权限连表条件 + CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId); + return selectJoinList(CrmBusinessDO.class, mpjLambdaWrapperX); } } 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 82839ec24..3c4a21cd4 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 @@ -8,8 +8,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi 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; - import jakarta.validation.Valid; + import java.util.Collection; import java.util.List; @@ -57,7 +57,7 @@ public interface CrmBusinessService { * @param ids 编号 * @return 商机列表 */ - List getBusinessList(Collection ids); + List getBusinessList(Collection ids, Long userId); /** * 获得商机分页 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 54946d052..76ca9a1f6 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,28 +3,28 @@ 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.module.crm.controller.admin.business.vo.business.*; +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.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.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.framework.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; import org.springframework.stereotype.Service; 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 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; /** @@ -71,7 +71,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Override @Transactional(rollbackFor = Exception.class) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, level = CrmPermissionLevelEnum.WRITE) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, level = CrmPermissionLevelEnum.OWNER) public void deleteBusiness(Long id) { // 校验存在 validateBusinessExists(id); @@ -88,38 +88,29 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } @Override - @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS,bizId = "#id", level = CrmPermissionLevelEnum.READ) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.READ) public CrmBusinessDO getBusiness(Long id) { return businessMapper.selectById(id); } @Override - public List getBusinessList(Collection ids) { + public List getBusinessList(Collection ids, Long userId) { if (CollUtil.isEmpty(ids)) { return ListUtil.empty(); } - return businessMapper.selectBatchIds(ids); + return businessMapper.selectBatchIds(ids, userId); } @Override public PageResult getBusinessPage(CrmBusinessPageReqVO pageReqVO, Long userId) { - // 1. 获取当前用户能看的分页数据 - // TODO @puhui999:如果业务的数据量比较大,in 太多可能有性能问题噢;看看是不是搞成 join 连表了;可以微信讨论下; - List permissions = crmPermissionService.getPermissionListByBizTypeAndUserId( - CrmBizTypeEnum.CRM_BUSINESS.getType(), userId); - Set ids = convertSet(permissions, CrmPermissionDO::getBizId); - if (CollUtil.isEmpty(ids)) { // 没得说明没有什么给他看的 - return PageResult.empty(); - } - - // 2. 获取商机分页数据 - return businessMapper.selectPage(pageReqVO, ids); + return businessMapper.selectPage(pageReqVO, userId); } @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) public PageResult getBusinessPageByCustomer(CrmContractPageReqVO pageReqVO) { - return businessMapper.selectPageByCustomer(pageReqVO); + //return businessMapper.selectPageByCustomer(pageReqVO); + return null; // TODO puhui999: 可以跟分页合并吗? } @Override @@ -128,10 +119,13 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { // 1 校验商机是否存在 validateBusinessExists(reqVO.getId()); - // 2. 数据权限转移 + // 2.1 数据权限转移 crmPermissionService.transferPermission( CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())); + // 2.2 设置新的负责人 + businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); + // 3. TODO 记录转移日志 } From 490418a1fc21a7806a6c081640d071ffda53eef0 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 8 Dec 2023 17:52:02 +0800 Subject: [PATCH 004/151] =?UTF-8?q?CRM-=E7=BA=BF=E7=B4=A2=EF=BC=9A?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9D=83=E9=99=90=E5=85=B3=E8=81=94=E3=80=81?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E5=88=86=E9=A1=B5=E6=9F=A5=E8=AF=A2=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9D=83=E9=99=90=E5=85=B3=E8=81=94=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/clue/CrmClueController.java | 16 +- .../admin/clue/vo/CrmClueExportReqVO.java | 52 ----- .../admin/clue/vo/CrmCluePageReqVO.java | 12 ++ .../admin/contact/vo/CrmContactPageReqVO.java | 12 ++ .../contract/vo/CrmContractPageReqVO.java | 12 ++ .../vo/plan/CrmReceivablePlanPageReqVO.java | 12 ++ .../vo/receivable/CrmReceivablePageReqVO.java | 12 ++ .../crm/dal/dataobject/clue/CrmClueDO.java | 7 + .../crm/dal/mysql/clue/CrmClueMapper.java | 48 +++-- .../core/annotations/CrmPermission.java | 3 +- .../business/CrmBusinessServiceImpl.java | 4 +- .../crm/service/clue/CrmClueService.java | 25 +-- .../crm/service/clue/CrmClueServiceImpl.java | 28 +-- .../CrmContactBusinessLinkServiceImpl.java | 10 +- .../customer/CrmCustomerServiceImpl.java | 2 + .../permission/CrmPermissionService.java | 12 +- .../permission/CrmPermissionServiceImpl.java | 13 +- .../service/clue/CrmClueServiceImplTest.java | 198 +++++++++--------- 18 files changed, 261 insertions(+), 217 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueExportReqVO.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index 759e46d13..04f1b4db0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -11,18 +11,20 @@ import cn.iocoder.yudao.module.crm.service.clue.CrmClueService; 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 jakarta.servlet.http.HttpServletResponse; +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.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import java.io.IOException; import java.util.List; 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.operatelog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - 线索") @RestController @@ -70,7 +72,7 @@ public class CrmClueController { @Operation(summary = "获得线索分页") @PreAuthorize("@ss.hasPermission('crm:clue:query')") public CommonResult> getCluePage(@Valid CrmCluePageReqVO pageVO) { - PageResult pageResult = clueService.getCluePage(pageVO); + PageResult pageResult = clueService.getCluePage(pageVO, getLoginUserId()); return success(CrmClueConvert.INSTANCE.convertPage(pageResult)); } @@ -78,9 +80,9 @@ public class CrmClueController { @Operation(summary = "导出线索 Excel") @PreAuthorize("@ss.hasPermission('crm:clue:export')") @OperateLog(type = EXPORT) - public void exportClueExcel(@Valid CrmClueExportReqVO exportReqVO, - HttpServletResponse response) throws IOException { - List list = clueService.getClueList(exportReqVO); + public void exportClueExcel(@Valid CrmCluePageReqVO pageReqVO, HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PAGE_SIZE_NONE); + List list = clueService.getCluePage(pageReqVO, getLoginUserId()).getList(); // 导出 Excel List datas = CrmClueConvert.INSTANCE.convertList02(list); ExcelUtils.write(response, "线索.xls", "数据", CrmClueExcelVO.class, datas); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueExportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueExportReqVO.java deleted file mode 100644 index fe061b365..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueExportReqVO.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; - -import lombok.*; -import java.util.*; -import io.swagger.v3.oas.annotations.media.Schema; -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import java.time.LocalDateTime; -import org.springframework.format.annotation.DateTimeFormat; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -@Schema(description = "管理后台 - 线索 Excel 导出 Request VO,参数和 CrmCluePageReqVO 是一致的") -@Data -public class CrmClueExportReqVO { - - @Schema(description = "转化状态", example = "true") - private Boolean transformStatus; - - @Schema(description = "跟进状态", example = "true") - private Boolean followUpStatus; - - @Schema(description = "线索名称", example = "线索xxx") - private String name; - - @Schema(description = "客户id", example = "520") - private Long customerId; - - @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] contactNextTime; - - @Schema(description = "电话", example = "18000000000") - private String telephone; - - @Schema(description = "手机号", example = "18000000000") - private String mobile; - - @Schema(description = "地址", example = "北京市海淀区") - private String address; - - @Schema(description = "负责人的用户编号", example = "27199") - private Long ownerUserId; - - @Schema(description = "最后跟进时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] contactLastTime; - - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java index 4d28ebc73..3bc841c2b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -21,4 +23,14 @@ public class CrmCluePageReqVO extends PageParam { @Schema(description = "手机号", example = "18000000000") private String mobile; + /** + * 场景类型,为 null 时则表示全部 + */ + @Schema(description = "场景类型", example = "1") + @InEnum(CrmSceneTypeEnum.class) + private Integer sceneType; + + @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + private Boolean pool; // null 则表示为不是公海数据 + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java index 1adfc341d..3d68c6f98 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -33,4 +35,14 @@ public class CrmContactPageReqVO extends PageParam { @Schema(description = "微信", example = "zzZ98373") private String wechat; + /** + * 场景类型,为 null 时则表示全部 + */ + @Schema(description = "场景类型", example = "1") + @InEnum(CrmSceneTypeEnum.class) + private Integer sceneType; + + @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + private Boolean pool; // null 则表示为不是公海数据 + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java index e2f286a99..97f9b70cd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -24,4 +26,14 @@ public class CrmContractPageReqVO extends PageParam { @Schema(description = "商机编号", example = "10864") private Long businessId; + /** + * 场景类型,为 null 时则表示全部 + */ + @Schema(description = "场景类型", example = "1") + @InEnum(CrmSceneTypeEnum.class) + private Integer sceneType; + + @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + private Boolean pool; // null 则表示为不是公海数据 + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java index b9249c2f2..f4987248e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -19,4 +21,14 @@ public class CrmReceivablePlanPageReqVO extends PageParam { @Schema(description = "合同名称", example = "3473") private Long contractId; + /** + * 场景类型,为 null 时则表示全部 + */ + @Schema(description = "场景类型", example = "1") + @InEnum(CrmSceneTypeEnum.class) + private Integer sceneType; + + @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + private Boolean pool; // null 则表示为不是公海数据 + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java index 9d0d4eb21..5999d4e34 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -21,4 +23,14 @@ public class CrmReceivablePageReqVO extends PageParam { @Schema(description = "客户编号", example = "4963") private Long customerId; + /** + * 场景类型,为 null 时则表示全部 + */ + @Schema(description = "场景类型", example = "1") + @InEnum(CrmSceneTypeEnum.class) + private Integer sceneType; + + @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + private Boolean pool; // null 则表示为不是公海数据 + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java index 592301b44..7d85c6ac1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java @@ -73,6 +73,13 @@ public class CrmClueDO extends BaseDO { */ private String remark; + /** + * 负责人的用户编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long ownerUserId; + // TODO 芋艿:客户级别; // TODO 芋艿:线索来源; // TODO 芋艿:客户行业; 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 8f9fea6c3..1d33d5814 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 @@ -2,12 +2,15 @@ package cn.iocoder.yudao.module.crm.dal.mysql.clue; 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.clue.vo.CrmClueExportReqVO; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +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 java.util.Collection; import java.util.List; /** @@ -18,27 +21,30 @@ import java.util.List; @Mapper public interface CrmClueMapper extends BaseMapperX { - default PageResult selectPage(CrmCluePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(CrmClueDO::getName, reqVO.getName()) - .likeIfPresent(CrmClueDO::getTelephone, reqVO.getTelephone()) - .likeIfPresent(CrmClueDO::getMobile, reqVO.getMobile()) - .orderByDesc(CrmClueDO::getId)); + default int updateOwnerUserIdById(Long id, Long ownerUserId) { + return update(new LambdaUpdateWrapper() + .eq(CrmClueDO::getId, id) + .set(CrmClueDO::getOwnerUserId, ownerUserId)); } - default List selectList(CrmClueExportReqVO reqVO) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(CrmClueDO::getTransformStatus, reqVO.getTransformStatus()) - .eqIfPresent(CrmClueDO::getFollowUpStatus, reqVO.getFollowUpStatus()) - .likeIfPresent(CrmClueDO::getName, reqVO.getName()) - .eqIfPresent(CrmClueDO::getCustomerId, reqVO.getCustomerId()) - .betweenIfPresent(CrmClueDO::getContactNextTime, reqVO.getContactNextTime()) - .likeIfPresent(CrmClueDO::getTelephone, reqVO.getTelephone()) - .likeIfPresent(CrmClueDO::getMobile, reqVO.getMobile()) - .likeIfPresent(CrmClueDO::getAddress, reqVO.getAddress()) - .betweenIfPresent(CrmClueDO::getContactLastTime, reqVO.getContactLastTime()) - .betweenIfPresent(CrmClueDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(CrmClueDO::getId)); + default PageResult selectPage(CrmCluePageReqVO pageReqVO, Long userId) { + MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); + // 构建数据权限连表条件 + CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId, + userId, pageReqVO.getSceneType(), pageReqVO.getPool()); + mpjLambdaWrapperX.selectAll(CrmClueDO.class) + .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) + .likeIfPresent(CrmClueDO::getTelephone, pageReqVO.getTelephone()) + .likeIfPresent(CrmClueDO::getMobile, pageReqVO.getMobile()) + .orderByDesc(CrmClueDO::getId); + return selectJoinPage(pageReqVO, CrmClueDO.class, mpjLambdaWrapperX); + } + + default List selectBatchIds(Collection ids, Long userId) { + MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); + // 构建数据权限连表条件 + CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId); + return selectJoinList(CrmClueDO.class, mpjLambdaWrapperX); } } 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/core/annotations/CrmPermission.java index 410637829..f92371f2b 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/core/annotations/CrmPermission.java @@ -35,9 +35,8 @@ public @interface CrmPermission { /** * 数据编号,通过 Spring EL 表达式获取 - * TODO 数据权限完成后去除 default "" */ - String bizId() default ""; + String bizId(); /** * 操作所需权限级别 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 76ca9a1f6..6b63c905d 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 @@ -71,12 +71,14 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Override @Transactional(rollbackFor = Exception.class) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, level = CrmPermissionLevelEnum.OWNER) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteBusiness(Long id) { // 校验存在 validateBusinessExists(id); // 删除 businessMapper.deleteById(id); + // 删除数据权限 + crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_BUSINESS.getType(), id); } private CrmBusinessDO validateBusinessExists(Long id) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java index 26ba0b408..52290e106 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java @@ -1,10 +1,14 @@ package cn.iocoder.yudao.module.crm.service.clue; -import java.util.*; -import jakarta.validation.*; -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; -import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; /** * 线索 Service 接口 @@ -49,22 +53,15 @@ public interface CrmClueService { * @param ids 编号 * @return 线索列表 */ - List getClueList(Collection ids); + List getClueList(Collection ids, Long userId); /** * 获得线索分页 * * @param pageReqVO 分页查询 + * @param userId 用户编号 * @return 线索分页 */ - PageResult getCluePage(CrmCluePageReqVO pageReqVO); - - /** - * 获得线索列表, 用于 Excel 导出 - * - * @param exportReqVO 查询条件 - * @return 线索列表 - */ - List getClueList(CrmClueExportReqVO exportReqVO); + PageResult getCluePage(CrmCluePageReqVO pageReqVO, Long userId); } 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 37efb98a5..3c463fa75 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 @@ -4,23 +4,25 @@ 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.clue.vo.CrmClueCreateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueExportReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; 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.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; +import jakarta.annotation.Resource; 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.CLUE_NOT_EXISTS; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; /** * 线索 Service 实现类 @@ -35,6 +37,8 @@ public class CrmClueServiceImpl implements CrmClueService { private CrmClueMapper clueMapper; @Resource private CrmCustomerService customerService; + @Resource + private CrmPermissionService crmPermissionService; @Override public Long createClue(CrmClueCreateReqVO createReqVO) { @@ -48,6 +52,7 @@ public class CrmClueServiceImpl implements CrmClueService { } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateClue(CrmClueUpdateReqVO updateReqVO) { // 校验存在 validateClueExists(updateReqVO.getId()); @@ -60,11 +65,14 @@ public class CrmClueServiceImpl implements CrmClueService { } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteClue(Long id) { // 校验存在 validateClueExists(id); // 删除 clueMapper.deleteById(id); + // 删除数据权限 + crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_LEADS.getType(), id); } private void validateClueExists(Long id) { @@ -74,26 +82,22 @@ public class CrmClueServiceImpl implements CrmClueService { } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.READ) public CrmClueDO getClue(Long id) { return clueMapper.selectById(id); } @Override - public List getClueList(Collection ids) { + public List getClueList(Collection ids, Long userId) { if (CollUtil.isEmpty(ids)) { return ListUtil.empty(); } - return clueMapper.selectBatchIds(ids); + return clueMapper.selectBatchIds(ids, userId); } @Override - public PageResult getCluePage(CrmCluePageReqVO pageReqVO) { - return clueMapper.selectPage(pageReqVO); - } - - @Override - public List getClueList(CrmClueExportReqVO exportReqVO) { - return clueMapper.selectList(exportReqVO); + public PageResult getCluePage(CrmCluePageReqVO pageReqVO, Long userId) { + return clueMapper.selectPage(pageReqVO, userId); } } 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 d8ef6a511..0a9512ffb 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 @@ -12,14 +12,18 @@ import cn.iocoder.yudao.module.crm.convert.contactbusinessslink.CrmContactBusine 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.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.service.business.CrmBusinessService; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; 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.CONTACT_BUSINESS_LINK_NOT_EXISTS; // TODO @puhui999:数据权限的校验;每个操作; @@ -54,6 +58,7 @@ public class CrmContactBusinessLinkServiceImpl implements CrmContactBusinessLink } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateContactBusinessLink(CrmContactBusinessLinkSaveReqVO updateReqVO) { // 校验存在 validateContactBusinessLinkExists(updateReqVO.getId()); @@ -80,6 +85,7 @@ public class CrmContactBusinessLinkServiceImpl implements CrmContactBusinessLink } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_BUSINESS, bizId = "#id", level = CrmPermissionLevelEnum.READ) public CrmContactBusinessLinkDO getContactBusinessLink(Long id) { return contactBusinessLinkMapper.selectById(id); } @@ -90,7 +96,7 @@ public class CrmContactBusinessLinkServiceImpl implements CrmContactBusinessLink crmContactBusinessLinkPageReqVO.setContactId(pageReqVO.getContactId()); PageResult businessLinkDOS = contactBusinessLinkMapper.selectPageByContact(crmContactBusinessLinkPageReqVO); List businessDOS = crmBusinessService.getBusinessList(CollectionUtils.convertList(businessLinkDOS.getList(), - CrmContactBusinessLinkDO::getBusinessId)); + CrmContactBusinessLinkDO::getBusinessId), getLoginUserId()); PageResult pageResult = new PageResult(); pageResult.setList(CrmBusinessConvert.INSTANCE.convert(businessDOS)); pageResult.setTotal(businessLinkDOS.getTotal()); 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 2460a33fb..24d9612e2 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 @@ -78,6 +78,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 删除 customerMapper.deleteById(id); + // 删除数据权限 + crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); } private void validateCustomerExists(Long id) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java index 75fb95fda..d2e3f80cb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java @@ -7,8 +7,8 @@ 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.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; - import jakarta.validation.Valid; + import java.util.Collection; import java.util.List; @@ -57,10 +57,18 @@ public interface CrmPermissionService { */ void deletePermission(Integer bizType, Long bizId, Integer level); + /** + * 删除数据权限 + * + * @param bizType 数据类型,关联 {@link CrmBizTypeEnum} + * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId() + */ + void deletePermission(Integer bizType, Long bizId); + /** * 批量删除数据权限 * - * @param ids 权限编号 + * @param ids 权限编号 * @param userId 用户编号 */ void deletePermissionBatch(Collection ids, Long userId); 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 8ca6b9cdd..e29e05fb0 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 @@ -11,11 +11,11 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; 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; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -137,6 +137,17 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { crmPermissionMapper.deleteBatchIds(convertSet(permissions, CrmPermissionDO::getId)); } + @Override + public void deletePermission(Integer bizType, Long bizId) { + List permissionList = crmPermissionMapper.selectByBizTypeAndBizId(bizType, bizId); + if (CollUtil.isEmpty(permissionList)) { + return; + } + + // 删除数据权限 + crmPermissionMapper.deleteBatchIds(convertSet(permissionList, CrmPermissionDO::getId)); + } + @Override public void deletePermissionBatch(Collection ids, Long userId) { List permissions = crmPermissionMapper.selectBatchIds(ids); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java index 3bb7dee63..1ff32be15 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java @@ -3,19 +3,18 @@ package cn.iocoder.yudao.module.crm.service.clue; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueExportReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; +import jakarta.annotation.Resource; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; -import jakarta.annotation.Resource; import java.util.List; -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -25,6 +24,7 @@ import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CLUE_NOT_EXIS import static org.junit.jupiter.api.Assertions.*; // TODO 芋艿:单测后续补; + /** * {@link CrmClueServiceImpl} 的单元测试类 * @@ -90,8 +90,8 @@ public class CrmClueServiceImplTest extends BaseDbUnitTest { // 调用 clueService.deleteClue(id); - // 校验数据不存在了 - assertNull(clueMapper.selectById(id)); + // 校验数据不存在了 + assertNull(clueMapper.selectById(id)); } @Test @@ -106,110 +106,102 @@ public class CrmClueServiceImplTest extends BaseDbUnitTest { @Test @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 public void testGetCluePage() { - // mock 数据 - CrmClueDO dbClue = randomPojo(CrmClueDO.class, o -> { // 等会查询到 - o.setTransformStatus(null); - o.setFollowUpStatus(null); - o.setName(null); - o.setCustomerId(null); - o.setContactNextTime(null); - o.setTelephone(null); - o.setMobile(null); - o.setAddress(null); - o.setContactLastTime(null); - o.setCreateTime(null); - }); - clueMapper.insert(dbClue); - // 测试 transformStatus 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTransformStatus(null))); - // 测试 followUpStatus 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setFollowUpStatus(null))); - // 测试 name 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setName(null))); - // 测试 customerId 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCustomerId(null))); - // 测试 contactNextTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactNextTime(null))); - // 测试 telephone 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTelephone(null))); - // 测试 mobile 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setMobile(null))); - // 测试 address 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setAddress(null))); - // 测试 contactLastTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactLastTime(null))); - // 测试 createTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCreateTime(null))); - // 准备参数 - CrmCluePageReqVO reqVO = new CrmCluePageReqVO(); - reqVO.setName(null); - reqVO.setTelephone(null); - reqVO.setMobile(null); + // mock 数据 + CrmClueDO dbClue = randomPojo(CrmClueDO.class, o -> { // 等会查询到 + o.setTransformStatus(null); + o.setFollowUpStatus(null); + o.setName(null); + o.setCustomerId(null); + o.setContactNextTime(null); + o.setTelephone(null); + o.setMobile(null); + o.setAddress(null); + o.setContactLastTime(null); + o.setCreateTime(null); + }); + clueMapper.insert(dbClue); + // 测试 transformStatus 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTransformStatus(null))); + // 测试 followUpStatus 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setFollowUpStatus(null))); + // 测试 name 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setName(null))); + // 测试 customerId 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCustomerId(null))); + // 测试 contactNextTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactNextTime(null))); + // 测试 telephone 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTelephone(null))); + // 测试 mobile 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setMobile(null))); + // 测试 address 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setAddress(null))); + // 测试 contactLastTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactLastTime(null))); + // 测试 createTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCreateTime(null))); + // 准备参数 + CrmCluePageReqVO reqVO = new CrmCluePageReqVO(); + reqVO.setName(null); + reqVO.setTelephone(null); + reqVO.setMobile(null); - // 调用 - PageResult pageResult = clueService.getCluePage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbClue, pageResult.getList().get(0)); + // 调用 + PageResult pageResult = clueService.getCluePage(reqVO, getLoginUserId()); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbClue, pageResult.getList().get(0)); } @Test @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 public void testGetClueList() { - // mock 数据 - CrmClueDO dbClue = randomPojo(CrmClueDO.class, o -> { // 等会查询到 - o.setTransformStatus(null); - o.setFollowUpStatus(null); - o.setName(null); - o.setCustomerId(null); - o.setContactNextTime(null); - o.setTelephone(null); - o.setMobile(null); - o.setAddress(null); - o.setContactLastTime(null); - o.setCreateTime(null); - }); - clueMapper.insert(dbClue); - // 测试 transformStatus 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTransformStatus(null))); - // 测试 followUpStatus 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setFollowUpStatus(null))); - // 测试 name 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setName(null))); - // 测试 customerId 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCustomerId(null))); - // 测试 contactNextTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactNextTime(null))); - // 测试 telephone 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTelephone(null))); - // 测试 mobile 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setMobile(null))); - // 测试 address 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setAddress(null))); - // 测试 contactLastTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactLastTime(null))); - // 测试 createTime 不匹配 - clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCreateTime(null))); - // 准备参数 - CrmClueExportReqVO reqVO = new CrmClueExportReqVO(); - reqVO.setTransformStatus(null); - reqVO.setFollowUpStatus(null); - reqVO.setName(null); - reqVO.setCustomerId(null); - reqVO.setContactNextTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - reqVO.setTelephone(null); - reqVO.setMobile(null); - reqVO.setAddress(null); - reqVO.setOwnerUserId(null); - reqVO.setContactLastTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - - // 调用 - List list = clueService.getClueList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbClue, list.get(0)); + // mock 数据 + CrmClueDO dbClue = randomPojo(CrmClueDO.class, o -> { // 等会查询到 + o.setTransformStatus(null); + o.setFollowUpStatus(null); + o.setName(null); + o.setCustomerId(null); + o.setContactNextTime(null); + o.setTelephone(null); + o.setMobile(null); + o.setAddress(null); + o.setContactLastTime(null); + o.setCreateTime(null); + }); + clueMapper.insert(dbClue); + // 测试 transformStatus 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTransformStatus(null))); + // 测试 followUpStatus 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setFollowUpStatus(null))); + // 测试 name 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setName(null))); + // 测试 customerId 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCustomerId(null))); + // 测试 contactNextTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactNextTime(null))); + // 测试 telephone 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setTelephone(null))); + // 测试 mobile 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setMobile(null))); + // 测试 address 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setAddress(null))); + // 测试 contactLastTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setContactLastTime(null))); + // 测试 createTime 不匹配 + clueMapper.insert(cloneIgnoreId(dbClue, o -> o.setCreateTime(null))); + // 准备参数 + CrmCluePageReqVO reqVO = new CrmCluePageReqVO(); + reqVO.setName(null); + reqVO.setTelephone(null); + reqVO.setMobile(null); + reqVO.setPageSize(PAGE_SIZE_NONE); + // 调用 + List list = clueService.getCluePage(reqVO, 1L).getList(); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbClue, list.get(0)); } } From f69a18fd230ad6bca70e7c267408e0976b03f17d Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 8 Dec 2023 18:08:41 +0800 Subject: [PATCH 005/151] =?UTF-8?q?CRM-=E8=81=94=E7=B3=BB=E4=BA=BA?= =?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?=EF=BC=8C=E6=96=B0=E5=A2=9E=E6=9D=83=E9=99=90=E5=85=B3=E8=81=94?= =?UTF-8?q?=E3=80=81=E5=9C=BA=E6=99=AF=E5=88=86=E9=A1=B5=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=EF=BC=8C=E6=96=B0=E5=A2=9E=E6=9D=83=E9=99=90=E5=85=B3=E8=81=94?= =?UTF-8?q?=E6=89=B9=E9=87=8F=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/contact/CrmContactController.java | 19 ++++--- .../dal/mysql/contact/CrmContactMapper.java | 55 +++++++++++-------- .../service/contact/CrmContactService.java | 30 +++------- .../contact/CrmContactServiceImpl.java | 31 ++++------- .../module/crm/util/CrmQueryWrapperUtils.java | 2 +- 5 files changed, 62 insertions(+), 75 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 811b4758e..d39b318da 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 @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.NumberUtil; 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.number.NumberUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; @@ -38,6 +37,7 @@ import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @@ -98,7 +98,8 @@ public class CrmContactController { List customerList = customerService.getCustomerList( Collections.singletonList(contact.getCustomerId()), getLoginUserId()); // 3. 直属上级 - List parentContactList = contactService.getContactList(Collections.singletonList(contact.getParentId())); + List parentContactList = contactService.getContactList( + Collections.singletonList(contact.getParentId()), getLoginUserId()); return success(ContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList)); } @@ -106,7 +107,9 @@ public class CrmContactController { @Operation(summary = "获得联系人列表") @PreAuthorize("@ss.hasPermission('crm:contact:query')") public CommonResult> getSimpleContactList() { - List list = contactService.getContactList(); + CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO(); + pageReqVO.setPageSize(PAGE_SIZE_NONE); + List list = contactService.getContactPage(pageReqVO, getLoginUserId()).getList(); return success(ContactConvert.INSTANCE.convertAllList(list)); } @@ -114,7 +117,7 @@ public class CrmContactController { @Operation(summary = "获得联系人分页") @PreAuthorize("@ss.hasPermission('crm:contact:query')") public CommonResult> getContactPage(@Valid CrmContactPageReqVO pageVO) { - PageResult pageResult = contactService.getContactPage(pageVO); + PageResult pageResult = contactService.getContactPage(pageVO, getLoginUserId()); return success(convertDetailContactPage(pageResult)); } @@ -122,7 +125,7 @@ public class CrmContactController { @Operation(summary = "获得联系人分页,基于指定客户") public CommonResult> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) { Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); - PageResult pageResult = contactService.getContactPageByCustomer(pageVO); + PageResult pageResult = contactService.getContactPage(pageVO, getLoginUserId()); return success(convertDetailContactPage(pageResult)); } @@ -132,8 +135,8 @@ public class CrmContactController { @OperateLog(type = EXPORT) public void exportContactExcel(@Valid CrmContactPageReqVO exportReqVO, HttpServletResponse response) throws IOException { - exportReqVO.setPageNo(PageParam.PAGE_SIZE_NONE); - PageResult pageResult = contactService.getContactPage(exportReqVO); + exportReqVO.setPageNo(PAGE_SIZE_NONE); + PageResult pageResult = contactService.getContactPage(exportReqVO, getLoginUserId()); ExcelUtils.write(response, "联系人.xls", "数据", CrmContactRespVO.class, convertDetailContactPage(pageResult).getList()); } @@ -157,7 +160,7 @@ public class CrmContactController { contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); // 3. 直属上级 List parentContactList = contactService.getContactList( - convertSet(contactList, CrmContactDO::getParentId)); + convertSet(contactList, CrmContactDO::getParentId), getLoginUserId()); return ContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList); } 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 4c8f82f1a..0ea93ab41 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 @@ -2,11 +2,17 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contact; 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.contact.vo.CrmContactPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; +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 java.util.Collection; +import java.util.List; + /** * CRM 联系人 Mapper * @@ -15,29 +21,34 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface CrmContactMapper extends BaseMapperX { - // TODO @puhui999:数据权限 - default PageResult selectPage(CrmContactPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(CrmContactDO::getMobile, reqVO.getMobile()) - .eqIfPresent(CrmContactDO::getTelephone, reqVO.getTelephone()) - .eqIfPresent(CrmContactDO::getEmail, reqVO.getEmail()) - .eqIfPresent(CrmContactDO::getCustomerId, reqVO.getCustomerId()) - .likeIfPresent(CrmContactDO::getName, reqVO.getName()) - .eqIfPresent(CrmContactDO::getQq, reqVO.getQq()) - .eqIfPresent(CrmContactDO::getWechat, reqVO.getWechat()) - .orderByDesc(CrmContactDO::getId)); + default int updateOwnerUserIdById(Long id, Long ownerUserId) { + return update(new LambdaUpdateWrapper() + .eq(CrmContactDO::getId, id) + .set(CrmContactDO::getOwnerUserId, ownerUserId)); } - default PageResult selectPageByCustomer(CrmContactPageReqVO pageVO) { - return selectPage(pageVO, new LambdaQueryWrapperX() - .eq(CrmContactDO::getCustomerId, pageVO.getCustomerId()) // 必须传递 - .likeIfPresent(CrmContactDO::getName, pageVO.getName()) - .eqIfPresent(CrmContactDO::getMobile, pageVO.getMobile()) - .eqIfPresent(CrmContactDO::getTelephone, pageVO.getTelephone()) - .eqIfPresent(CrmContactDO::getEmail, pageVO.getEmail()) - .eqIfPresent(CrmContactDO::getQq, pageVO.getQq()) - .eqIfPresent(CrmContactDO::getWechat, pageVO.getWechat()) - .orderByDesc(CrmContactDO::getId)); + default PageResult selectPage(CrmContactPageReqVO pageReqVO, Long userId) { + MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); + // 构建数据权限连表条件 + CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId, + userId, pageReqVO.getSceneType(), pageReqVO.getPool()); + mpjLambdaWrapperX.selectAll(CrmContactDO.class) + .eq(CrmContactDO::getCustomerId, pageReqVO.getCustomerId()) // 必须传递 + .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) + .eqIfPresent(CrmContactDO::getMobile, pageReqVO.getMobile()) + .eqIfPresent(CrmContactDO::getTelephone, pageReqVO.getTelephone()) + .eqIfPresent(CrmContactDO::getEmail, pageReqVO.getEmail()) + .eqIfPresent(CrmContactDO::getQq, pageReqVO.getQq()) + .eqIfPresent(CrmContactDO::getWechat, pageReqVO.getWechat()) + .orderByDesc(CrmContactDO::getId); + return selectJoinPage(pageReqVO, CrmContactDO.class, mpjLambdaWrapperX); + } + + default List selectBatchIds(Collection ids, Long userId) { + MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); + // 构建数据权限连表条件 + CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); + return selectJoinList(CrmContactDO.class, mpjLambdaWrapperX); } } 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 85aec14cc..a37b96962 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 @@ -5,9 +5,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateR 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.CrmContactDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; - import jakarta.validation.Valid; + import java.util.Collection; import java.util.List; @@ -22,7 +21,7 @@ public interface CrmContactService { * 创建联系人 * * @param createReqVO 创建信息 - * @param userId 用户编号 + * @param userId 用户编号 * @return 编号 */ Long createContact(@Valid CrmContactCreateReqVO createReqVO, Long userId); @@ -52,10 +51,11 @@ public interface CrmContactService { /** * 获得联系人列表 * - * @param ids 编号 + * @param ids 编号 + * @param userId 用户编号 * @return 联系人列表 */ - List getContactList(Collection ids); + List getContactList(Collection ids, Long userId); /** * 获得联系人分页 @@ -63,25 +63,9 @@ public interface CrmContactService { * 数据权限:基于 {@link CrmContactDO} * * @param pageReqVO 分页查询 + * @param userId 用户编号 * @return 联系人分页 */ - PageResult getContactPage(CrmContactPageReqVO pageReqVO); - - /** - * 获得联系人分页,基于指定客户 - * - * 数据权限:基于 {@link CrmCustomerDO} 读取 - * - * @param pageReqVO 分页查询 - * @return 联系人分页 - */ - PageResult getContactPageByCustomer(CrmContactPageReqVO pageReqVO); - - /** - * 获取所有联系人列表 - * - * @return 所有联系人列表 - */ - List getContactList(); + PageResult getContactPage(CrmContactPageReqVO pageReqVO, 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 d4c4fe9c2..a4ca31072 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 @@ -10,18 +10,18 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactUpdateR 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.mysql.contact.CrmContactMapper; -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.framework.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; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.util.Collection; import java.util.List; @@ -82,7 +82,7 @@ public class CrmContactServiceImpl implements CrmContactService { * * @param saveReqVO 新增/修改请求 VO */ - private void validateRelationDataExists(CrmContactBaseVO saveReqVO){ + private void validateRelationDataExists(CrmContactBaseVO saveReqVO) { // 1. 校验客户 if (saveReqVO.getCustomerId() != null && customerService.getCustomer(saveReqVO.getCustomerId()) == null) { throw exception(CUSTOMER_NOT_EXISTS); @@ -98,12 +98,14 @@ public class CrmContactServiceImpl implements CrmContactService { } @Override - @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteContact(Long id) { // 校验存在 validateContactExists(id); // 删除 contactMapper.deleteById(id); + // 删除数据权限 + crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTACT.getType(), id); } private void validateContactExists(Long id) { @@ -112,7 +114,6 @@ public class CrmContactServiceImpl implements CrmContactService { } } - // TODO 芋艿:是否要做数据权限的校验??? @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#id", level = CrmPermissionLevelEnum.READ) public CrmContactDO getContact(Long id) { @@ -120,28 +121,16 @@ public class CrmContactServiceImpl implements CrmContactService { } @Override - public List getContactList(Collection ids) { + public List getContactList(Collection ids, Long userId) { if (CollUtil.isEmpty(ids)) { return ListUtil.empty(); } - return contactMapper.selectBatchIds(ids); + return contactMapper.selectBatchIds(ids, userId); } @Override - public PageResult getContactPage(CrmContactPageReqVO pageReqVO) { - // TODO puhui999:后面要改成,基于数据权限的查询 - return contactMapper.selectPage(pageReqVO); - } - - @Override - @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) - public PageResult getContactPageByCustomer(CrmContactPageReqVO pageReqVO) { - return contactMapper.selectPageByCustomer(pageReqVO); - } - - @Override - public List getContactList() { - return contactMapper.selectList(); + public PageResult getContactPage(CrmContactPageReqVO pageReqVO, Long userId) { + return contactMapper.selectPage(pageReqVO, userId); } } 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 23e422332..0ffa8572e 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 @@ -79,7 +79,7 @@ public class CrmQueryWrapperUtils { if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 queryMapper.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType).in(CrmPermissionDO::getBizId, bizIds) - .eq(CrmPermissionDO::getUserId, userId)); + .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); } } From 7c54affb16fea44111b4ea4f14defe786e0cfff0 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 8 Dec 2023 22:43:45 +0800 Subject: [PATCH 006/151] =?UTF-8?q?CRM-=E5=90=88=E5=90=8C=EF=BC=9A?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9D=83=E9=99=90=E5=85=B3=E8=81=94=E3=80=81?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E5=88=86=E9=A1=B5=E6=9F=A5=E8=AF=A2=EF=BC=8C?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=9D=83=E9=99=90=E5=85=B3=E8=81=94=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/business/CrmBusinessController.java | 5 +- .../admin/contact/CrmContactController.java | 2 +- .../admin/contract/CrmContractController.java | 6 +-- .../dal/mysql/business/CrmBusinessMapper.java | 2 +- .../dal/mysql/contact/CrmContactMapper.java | 2 +- .../dal/mysql/contract/CrmContractMapper.java | 46 +++++++++++++------ .../service/business/CrmBusinessService.java | 4 +- .../business/CrmBusinessServiceImpl.java | 13 ++++-- .../service/contact/CrmContactService.java | 11 +++++ .../contact/CrmContactServiceImpl.java | 8 ++++ .../service/contract/CrmContractService.java | 12 +++-- .../contract/CrmContractServiceImpl.java | 28 ++++++----- .../service/customer/CrmCustomerService.java | 3 +- .../customer/CrmCustomerServiceImpl.java | 11 +++-- .../service/clue/CrmClueServiceImplTest.java | 2 +- .../contract/ContractServiceImplTest.java | 5 +- 16 files changed, 100 insertions(+), 60 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 c6fededc9..d23595290 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 @@ -9,7 +9,6 @@ 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.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; @@ -121,9 +120,9 @@ public class CrmBusinessController { @GetMapping("/page-by-customer") @Operation(summary = "获得商机分页,基于指定客户") - public CommonResult> getBusinessPageByCustomer(@Valid CrmContractPageReqVO pageReqVO) { + public CommonResult> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) { Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); - PageResult pageResult = businessService.getBusinessPageByCustomer(pageReqVO); + PageResult pageResult = businessService.getBusinessPageByCustomer(pageReqVO, getLoginUserId()); // 处理客户名称回显 // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈; Set customerIds = pageResult.getList().stream() 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 d39b318da..dbdc0663d 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 @@ -125,7 +125,7 @@ public class CrmContactController { @Operation(summary = "获得联系人分页,基于指定客户") public CommonResult> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) { Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); - PageResult pageResult = contactService.getContactPage(pageVO, getLoginUserId()); + PageResult pageResult = contactService.getContactPageByCustomerId(pageVO, getLoginUserId()); return success(convertDetailContactPage(pageResult)); } 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 24426cd5a..623a9ab91 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 @@ -87,7 +87,7 @@ public class CrmContractController { @Operation(summary = "获得合同分页") @PreAuthorize("@ss.hasPermission('crm:contract:query')") public CommonResult> getContractPage(@Valid CrmContractPageReqVO pageVO) { - PageResult pageResult = contractService.getContractPage(pageVO); + PageResult pageResult = contractService.getContractPage(pageVO, getLoginUserId()); return success(convertDetailContractPage(pageResult)); } @@ -95,7 +95,7 @@ public class CrmContractController { @Operation(summary = "获得联系人分页,基于指定客户") public CommonResult> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) { Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); - PageResult pageResult = contractService.getContractPageByCustomer(pageVO); + PageResult pageResult = contractService.getContractPageByCustomer(pageVO, getLoginUserId()); return success(convertDetailContractPage(pageResult)); } @@ -105,7 +105,7 @@ public class CrmContractController { @OperateLog(type = EXPORT) public void exportContractExcel(@Valid CrmContractPageReqVO exportReqVO, HttpServletResponse response) throws IOException { - PageResult pageResult = contractService.getContractPage(exportReqVO); + PageResult pageResult = contractService.getContractPage(exportReqVO, getLoginUserId()); // 导出 Excel ExcelUtils.write(response, "合同.xls", "数据", CrmContractExcelVO.class, ContractConvert.INSTANCE.convertList02(pageResult.getList())); 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 3074094b4..8e5d6750a 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 @@ -33,7 +33,7 @@ public interface CrmBusinessMapper extends BaseMapperX { CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); mpjLambdaWrapperX.selectAll(CrmBusinessDO.class) - .eq(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 必须传递 + .eqIfPresent(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) .orderByDesc(CrmBusinessDO::getId); return selectJoinPage(pageReqVO, CrmBusinessDO.class, mpjLambdaWrapperX); 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 0ea93ab41..266aceaa6 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 @@ -33,7 +33,7 @@ public interface CrmContactMapper extends BaseMapperX { CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); mpjLambdaWrapperX.selectAll(CrmContactDO.class) - .eq(CrmContactDO::getCustomerId, pageReqVO.getCustomerId()) // 必须传递 + .eqIfPresent(CrmContactDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) .eqIfPresent(CrmContactDO::getMobile, pageReqVO.getMobile()) .eqIfPresent(CrmContactDO::getTelephone, pageReqVO.getTelephone()) 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 a22912162..37452feb7 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 @@ -2,11 +2,17 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contract; 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.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; +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 java.util.Collection; +import java.util.List; + /** * CRM 合同 Mapper * @@ -15,22 +21,32 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface CrmContractMapper extends BaseMapperX { - default PageResult selectPage(CrmContractPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(CrmContractDO::getNo, reqVO.getNo()) - .likeIfPresent(CrmContractDO::getName, reqVO.getName()) - .eqIfPresent(CrmContractDO::getCustomerId, reqVO.getCustomerId()) - .eqIfPresent(CrmContractDO::getBusinessId, reqVO.getBusinessId()) - .orderByDesc(CrmContractDO::getId)); + default int updateOwnerUserIdById(Long id, Long ownerUserId) { + return update(new LambdaUpdateWrapper() + .eq(CrmContractDO::getId, id) + .set(CrmContractDO::getOwnerUserId, ownerUserId)); } - default PageResult selectPageByCustomer(CrmContractPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eq(CrmContractDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 - .likeIfPresent(CrmContractDO::getNo, reqVO.getNo()) - .likeIfPresent(CrmContractDO::getName, reqVO.getName()) - .eqIfPresent(CrmContractDO::getBusinessId, reqVO.getBusinessId()) - .orderByDesc(CrmContractDO::getId)); + default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId) { + MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); + // 构建数据权限连表条件 + CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContractDO::getId, + userId, pageReqVO.getSceneType(), pageReqVO.getPool()); + mpjLambdaWrapperX.selectAll(CrmContractDO.class) + .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) + .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) + .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) + .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) + .eqIfPresent(CrmContractDO::getBusinessId, pageReqVO.getBusinessId()) + .orderByDesc(CrmContractDO::getId); + return selectJoinPage(pageReqVO, CrmContractDO.class, mpjLambdaWrapperX); + } + + default List selectBatchIds(Collection ids, Long userId) { + MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); + // 构建数据权限连表条件 + CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); + return selectJoinList(CrmContractDO.class, mpjLambdaWrapperX); } } 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 3c4a21cd4..c46f5f0bf 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,7 +5,6 @@ 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.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import jakarta.validation.Valid; @@ -76,9 +75,10 @@ public interface CrmBusinessService { * 数据权限:基于 {@link CrmCustomerDO} 读取 * * @param pageReqVO 分页查询 + * @param userId 用户编号 * @return 联系人分页 */ - PageResult getBusinessPageByCustomer(CrmContractPageReqVO pageReqVO); + PageResult getBusinessPageByCustomer(CrmBusinessPageReqVO pageReqVO, Long userId); /** * 商机转移 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 6b63c905d..6e43944eb 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,13 +7,13 @@ 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.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.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.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import jakarta.annotation.Resource; @@ -38,6 +38,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Resource private CrmBusinessMapper businessMapper; + @Resource + private CrmCustomerService customerService; @Resource private CrmPermissionService crmPermissionService; @@ -109,10 +111,11 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } @Override - @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) - public PageResult getBusinessPageByCustomer(CrmContractPageReqVO pageReqVO) { - //return businessMapper.selectPageByCustomer(pageReqVO); - return null; // TODO puhui999: 可以跟分页合并吗? + public PageResult getBusinessPageByCustomer(CrmBusinessPageReqVO pageReqVO, Long userId) { + // 校验客户存在 + customerService.validateCustomer(pageReqVO.getCustomerId()); + + return businessMapper.selectPage(pageReqVO, userId); } @Override 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 a37b96962..4306d8aea 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 @@ -68,4 +68,15 @@ public interface CrmContactService { */ PageResult getContactPage(CrmContactPageReqVO pageReqVO, Long userId); + /** + * 获得联系人分页 + * + * 数据权限:基于 {@link CrmContactDO} + * + * @param pageVO 分页查询 + * @param userId 用户编号 + * @return 联系人分页 + */ + PageResult getContactPageByCustomerId(CrmContactPageReqVO pageVO, 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 a4ca31072..9220a9e66 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 @@ -133,4 +133,12 @@ public class CrmContactServiceImpl implements CrmContactService { return contactMapper.selectPage(pageReqVO, userId); } + @Override + public PageResult getContactPageByCustomerId(CrmContactPageReqVO pageVO, Long userId) { + // 校验用户存在 + customerService.validateCustomer(pageVO.getCustomerId()); + + return contactMapper.selectPage(pageVO, userId); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index e9162b1ca..0531dbe38 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -3,12 +3,12 @@ package cn.iocoder.yudao.module.crm.service.contract; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; - import jakarta.validation.Valid; + import java.util.Collection; import java.util.List; @@ -64,9 +64,10 @@ public interface CrmContractService { * 数据权限:基于 {@link CrmContractDO} 读取 * * @param pageReqVO 分页查询 + * @param userId 用户编号 * @return 合同分页 */ - PageResult getContractPage(CrmContractPageReqVO pageReqVO); + PageResult getContractPage(CrmContractPageReqVO pageReqVO, Long userId); /** * 获得合同分页,基于指定客户 @@ -74,9 +75,12 @@ public interface CrmContractService { * 数据权限:基于 {@link CrmCustomerDO} 读取 * * @param pageReqVO 分页查询 + * @param userId 用户编号 * @return 联系人分页 */ - PageResult getContractPageByCustomer(CrmContractPageReqVO pageReqVO); + default PageResult getContractPageByCustomer(CrmContractPageReqVO pageReqVO, Long userId) { + return getContractPage(pageReqVO, userId); + } /** * 合同转移 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 731711a3a..23795f94e 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 @@ -5,8 +5,8 @@ import cn.hutool.core.collection.ListUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO; import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; @@ -15,11 +15,11 @@ 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.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.util.Collection; import java.util.List; @@ -56,7 +56,7 @@ public class CrmContractServiceImpl implements CrmContractService { @Override @Transactional(rollbackFor = Exception.class) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, level = CrmPermissionLevelEnum.WRITE) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateContract(CrmContractUpdateReqVO updateReqVO) { // 校验存在 validateContractExists(updateReqVO.getId()); @@ -67,12 +67,14 @@ public class CrmContractServiceImpl implements CrmContractService { @Override @Transactional(rollbackFor = Exception.class) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteContract(Long id) { // 校验存在 validateContractExists(id); // 删除 contractMapper.deleteById(id); + // 删除数据权限 + crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CONTRACT.getType(), id); } private CrmContractDO validateContractExists(Long id) { @@ -83,7 +85,6 @@ public class CrmContractServiceImpl implements CrmContractService { return contract; } - // TODO 芋艿:是否要做数据权限的校验??? @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#id", level = CrmPermissionLevelEnum.READ) public CrmContractDO getContract(Long id) { @@ -99,27 +100,24 @@ public class CrmContractServiceImpl implements CrmContractService { } @Override - public PageResult getContractPage(CrmContractPageReqVO pageReqVO) { - return contractMapper.selectPage(pageReqVO); - } - - @Override - @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) - public PageResult getContractPageByCustomer(CrmContractPageReqVO pageReqVO) { - return contractMapper.selectPageByCustomer(pageReqVO); + public PageResult getContractPage(CrmContractPageReqVO pageReqVO, Long userId) { + return contractMapper.selectPage(pageReqVO, userId); } @Override @Transactional(rollbackFor = Exception.class) public void transferContract(CrmContractTransferReqVO reqVO, Long userId) { - // 1 校验合同是否存在 + // 1. 校验合同是否存在 validateContractExists(reqVO.getId()); - // 2. 数据权限转移 + // 2.1 数据权限转移 crmPermissionService.transferPermission( ContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType())); + // 2.2 设置负责人 + contractMapper.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/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 1bd1fee47..73be18951 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 @@ -71,9 +71,8 @@ public interface CrmCustomerService { * 校验客户是否存在 * * @param customerId 客户 id - * @return 客户 */ - CrmCustomerDO validateCustomer(Long customerId); + void validateCustomer(Long customerId); /** * 客户转移 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 24d9612e2..93589a5b0 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 @@ -111,15 +111,18 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { * 校验客户是否存在 * * @param customerId 客户 id - * @return 客户 */ @Override - public CrmCustomerDO validateCustomer(Long customerId) { - CrmCustomerDO customer = getCustomer(customerId); + public void validateCustomer(Long customerId) { + // TODO puhui999: 不返回客户不走校验应该可行 + // 校验客户是否存在 + if (customerId == null) { + throw exception(CUSTOMER_NOT_EXISTS); + } + CrmCustomerDO customer = customerMapper.selectById(customerId); if (Objects.isNull(customer)) { throw exception(CUSTOMER_NOT_EXISTS); } - return customer; } @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java index 1ff32be15..8b07804c2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java @@ -147,7 +147,7 @@ public class CrmClueServiceImplTest extends BaseDbUnitTest { reqVO.setMobile(null); // 调用 - PageResult pageResult = clueService.getCluePage(reqVO, getLoginUserId()); + PageResult pageResult = clueService.getCluePage(reqVO, 1L); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java index 35825df19..145d75325 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/contract/ContractServiceImplTest.java @@ -7,12 +7,11 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; +import jakarta.annotation.Resource; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; -import jakarta.annotation.Resource; - import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; @@ -127,7 +126,7 @@ public class ContractServiceImplTest extends BaseDbUnitTest { reqVO.setNo(null); // 调用 - PageResult pageResult = contractService.getContractPage(reqVO); + PageResult pageResult = contractService.getContractPage(reqVO, getLoginUserId()); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); From 23df8633f4fc1cedaaaabf1ec72cfd2acf395e8e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 9 Dec 2023 10:50:47 +0800 Subject: [PATCH 007/151] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 +- .../mybatis/core/mapper/BaseMapperX.java | 2 + .../crm/enums/common/CrmSceneTypeEnum.java | 9 +-- .../vo/business/CrmBusinessPageReqVO.java | 5 +- .../admin/clue/vo/CrmCluePageReqVO.java | 5 +- .../admin/contact/vo/CrmContactPageReqVO.java | 5 +- .../contract/vo/CrmContractPageReqVO.java | 7 +-- .../customer/vo/CrmCustomerPageReqVO.java | 5 +- .../vo/plan/CrmReceivablePlanPageReqVO.java | 5 +- .../vo/receivable/CrmReceivablePageReqVO.java | 5 +- .../module/crm/controller/package-info.java | 6 ++ .../convert/business/CrmBusinessConvert.java | 4 +- .../convert/customer/CrmCustomerConvert.java | 4 +- .../dal/mysql/business/CrmBusinessMapper.java | 19 +++--- .../crm/dal/mysql/clue/CrmClueMapper.java | 19 +++--- .../dal/mysql/contact/CrmContactMapper.java | 19 +++--- .../dal/mysql/customer/CrmCustomerMapper.java | 19 +++--- .../business/CrmBusinessServiceImpl.java | 4 +- .../crm/service/clue/CrmClueServiceImpl.java | 1 + .../contact/CrmContactServiceImpl.java | 2 +- .../permission/CrmPermissionServiceImpl.java | 3 +- .../module/crm/util/CrmQueryWrapperUtils.java | 41 +++++++------ .../module/system/api/user/AdminUserApi.java | 1 - .../system/api/user/AdminUserApiImpl.java | 11 ++-- yudao-server/pom.xml | 60 +++++++++---------- 25 files changed, 128 insertions(+), 139 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java diff --git a/pom.xml b/pom.xml index 26dec77cf..86f894f4a 100644 --- a/pom.xml +++ b/pom.xml @@ -15,12 +15,12 @@ yudao-module-system yudao-module-infra - + yudao-module-member - - + yudao-module-pay + yudao-module-mall yudao-module-crm 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 b0c0f784e..e466f5ed7 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 @@ -48,8 +48,10 @@ public interface BaseMapperX extends MPJBaseMapper { return new PageResult<>(list, (long) list.size()); } + // MyBatis Plus Join 查询 IPage mpPage = MyBatisUtils.buildPage(pageParam); mpPage = selectJoinPage(mpPage, clazz, lambdaWrapper); + // 转换返回 return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); } diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java index dc714250d..945d7c6a3 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java @@ -17,9 +17,8 @@ import java.util.Arrays; public enum CrmSceneTypeEnum implements IntArrayValuable { OWNER(1, "我负责的"), - FOLLOW(2, "我关注的"), - INVOLVED(3, "我参与的"), - SUBORDINATE(4, "下属负责的"); + INVOLVED(2, "我参与的"), + SUBORDINATE(3, "下属负责的"); public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmSceneTypeEnum::getType).toArray(); @@ -36,10 +35,6 @@ public enum CrmSceneTypeEnum implements IntArrayValuable { return ObjUtil.equal(OWNER.getType(), type); } - public static boolean isFollow(Integer type) { - return ObjUtil.equal(FOLLOW.getType(), type); - } - public static boolean isInvolved(Integer type) { return ObjUtil.equal(INVOLVED.getType(), type); } 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 eb208b252..579026047 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,12 +20,9 @@ public class CrmBusinessPageReqVO extends PageParam { @Schema(description = "客户编号", example = "10795") private Long customerId; - /** - * 场景类型,为 null 时则表示全部 - */ @Schema(description = "场景类型", example = "1") @InEnum(CrmSceneTypeEnum.class) - private Integer sceneType; + private Integer sceneType; // 场景类型,为 null 时则表示全部 @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") private Boolean pool; // null 则表示为不是公海数据 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java index 3bc841c2b..0b6e7a50a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java @@ -23,12 +23,9 @@ public class CrmCluePageReqVO extends PageParam { @Schema(description = "手机号", example = "18000000000") private String mobile; - /** - * 场景类型,为 null 时则表示全部 - */ @Schema(description = "场景类型", example = "1") @InEnum(CrmSceneTypeEnum.class) - private Integer sceneType; + private Integer sceneType; // 场景类型,为 null 时则表示全部 @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") private Boolean pool; // null 则表示为不是公海数据 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java index 3d68c6f98..eb6ebd76c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java @@ -35,12 +35,9 @@ public class CrmContactPageReqVO extends PageParam { @Schema(description = "微信", example = "zzZ98373") private String wechat; - /** - * 场景类型,为 null 时则表示全部 - */ @Schema(description = "场景类型", example = "1") @InEnum(CrmSceneTypeEnum.class) - private Integer sceneType; + private Integer sceneType; // 场景类型,为 null 时则表示全部 @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") private Boolean pool; // null 则表示为不是公海数据 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java index 97f9b70cd..2b3123bd9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java @@ -26,14 +26,11 @@ public class CrmContractPageReqVO extends PageParam { @Schema(description = "商机编号", example = "10864") private Long businessId; - /** - * 场景类型,为 null 时则表示全部 - */ @Schema(description = "场景类型", example = "1") @InEnum(CrmSceneTypeEnum.class) - private Integer sceneType; + private Integer sceneType; // 场景类型,为 null 时则表示全部 @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") - private Boolean pool; // null 则表示为不是公海数据 + private Boolean pool; // null 则表示为不是公海数据 TODO @puhui999:合同没有公海。目前只有【客户】【线索】有公海,其它都没 } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java index 830b7da6d..bded50473 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerPageReqVO.java @@ -29,12 +29,9 @@ public class CrmCustomerPageReqVO extends PageParam { @Schema(description = "客户来源", example = "1") private Integer source; - /** - * 场景类型,为 null 时则表示全部 - */ @Schema(description = "场景类型", example = "1") @InEnum(CrmSceneTypeEnum.class) - private Integer sceneType; + private Integer sceneType; // 场景类型,为 null 时则表示全部 @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") private Boolean pool; // null 则表示为不是公海数据 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java index f4987248e..16681ba3c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java @@ -21,12 +21,9 @@ public class CrmReceivablePlanPageReqVO extends PageParam { @Schema(description = "合同名称", example = "3473") private Long contractId; - /** - * 场景类型,为 null 时则表示全部 - */ @Schema(description = "场景类型", example = "1") @InEnum(CrmSceneTypeEnum.class) - private Integer sceneType; + private Integer sceneType; // 场景类型,为 null 时则表示全部 @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") private Boolean pool; // null 则表示为不是公海数据 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java index 5999d4e34..3eef5d013 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java @@ -23,12 +23,9 @@ public class CrmReceivablePageReqVO extends PageParam { @Schema(description = "客户编号", example = "4963") private Long customerId; - /** - * 场景类型,为 null 时则表示全部 - */ @Schema(description = "场景类型", example = "1") @InEnum(CrmSceneTypeEnum.class) - private Integer sceneType; + private Integer sceneType; // 场景类型,为 null 时则表示全部 @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") private Boolean pool; // null 则表示为不是公海数据 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java new file mode 100644 index 000000000..8354b3176 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.crm.controller; 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 72acdd094..3effb21e0 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 @@ -38,9 +38,7 @@ public interface CrmBusinessConvert { List convertList02(List list); - @Mappings({ - @Mapping(target = "bizId", source = "reqVO.id") - }) + @Mapping(target = "bizId", source = "reqVO.id") CrmPermissionTransferReqBO convert(CrmBusinessTransferReqVO reqVO, Long userId); default PageResult convertPage(PageResult page, List customerList, 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 0e21b26b8..55e2a3518 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 @@ -54,9 +54,7 @@ public interface CrmCustomerConvert { List convertList02(List list); - @Mappings({ - @Mapping(target = "bizId", source = "reqVO.id") - }) + @Mapping(target = "bizId", source = "reqVO.id") CrmPermissionTransferReqBO convert(CrmCustomerTransferReqVO reqVO, Long userId); PageResult convertPage(PageResult page); 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 8e5d6750a..7c06e57a0 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 @@ -28,22 +28,23 @@ public interface CrmBusinessMapper extends BaseMapperX { } default PageResult selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { - MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); - // 构建数据权限连表条件 - CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId, + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); - mpjLambdaWrapperX.selectAll(CrmBusinessDO.class) + // 拼接自身的查询条件 + query.selectAll(CrmBusinessDO.class) .eqIfPresent(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) .orderByDesc(CrmBusinessDO::getId); - return selectJoinPage(pageReqVO, CrmBusinessDO.class, mpjLambdaWrapperX); + return selectJoinPage(pageReqVO, CrmBusinessDO.class, query); } default List selectBatchIds(Collection ids, Long userId) { - MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); - // 构建数据权限连表条件 - CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId); - return selectJoinList(CrmBusinessDO.class, mpjLambdaWrapperX); + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId); + return selectJoinList(CrmBusinessDO.class, query); } } 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 1d33d5814..479a12f1a 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 @@ -28,23 +28,24 @@ public interface CrmClueMapper extends BaseMapperX { } default PageResult selectPage(CrmCluePageReqVO pageReqVO, Long userId) { - MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); - // 构建数据权限连表条件 - CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId, + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); - mpjLambdaWrapperX.selectAll(CrmClueDO.class) + // 拼接自身的查询条件 + query.selectAll(CrmClueDO.class) .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) .likeIfPresent(CrmClueDO::getTelephone, pageReqVO.getTelephone()) .likeIfPresent(CrmClueDO::getMobile, pageReqVO.getMobile()) .orderByDesc(CrmClueDO::getId); - return selectJoinPage(pageReqVO, CrmClueDO.class, mpjLambdaWrapperX); + return selectJoinPage(pageReqVO, CrmClueDO.class, query); } default List selectBatchIds(Collection ids, Long userId) { - MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); - // 构建数据权限连表条件 - CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId); - return selectJoinList(CrmClueDO.class, mpjLambdaWrapperX); + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId); + return selectJoinList(CrmClueDO.class, query); } } 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 266aceaa6..189f36f08 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 @@ -28,11 +28,12 @@ public interface CrmContactMapper extends BaseMapperX { } default PageResult selectPage(CrmContactPageReqVO pageReqVO, Long userId) { - MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); - // 构建数据权限连表条件 - CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId, + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); - mpjLambdaWrapperX.selectAll(CrmContactDO.class) + // 拼接自身的查询条件 + query.selectAll(CrmContactDO.class) .eqIfPresent(CrmContactDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) .eqIfPresent(CrmContactDO::getMobile, pageReqVO.getMobile()) @@ -41,14 +42,14 @@ public interface CrmContactMapper extends BaseMapperX { .eqIfPresent(CrmContactDO::getQq, pageReqVO.getQq()) .eqIfPresent(CrmContactDO::getWechat, pageReqVO.getWechat()) .orderByDesc(CrmContactDO::getId); - return selectJoinPage(pageReqVO, CrmContactDO.class, mpjLambdaWrapperX); + return selectJoinPage(pageReqVO, CrmContactDO.class, query); } default List selectBatchIds(Collection ids, Long userId) { - MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); - // 构建数据权限连表条件 - CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); - return selectJoinList(CrmContactDO.class, mpjLambdaWrapperX); + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); + return selectJoinList(CrmContactDO.class, 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 9c29c668f..86c8617b7 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 @@ -28,24 +28,25 @@ public interface CrmCustomerMapper extends BaseMapperX { } default PageResult selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { - MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); - // 构建数据权限连表条件 - CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); - mpjLambdaWrapperX.selectAll(CrmCustomerDO.class) + // 拼接自身的查询条件 + query.selectAll(CrmCustomerDO.class) .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) .eqIfPresent(CrmCustomerDO::getMobile, pageReqVO.getMobile()) .eqIfPresent(CrmCustomerDO::getIndustryId, pageReqVO.getIndustryId()) .eqIfPresent(CrmCustomerDO::getLevel, pageReqVO.getLevel()) .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource()); - return selectJoinPage(pageReqVO, CrmCustomerDO.class, mpjLambdaWrapperX); + return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); } default List selectBatchIds(Collection ids, Long userId) { - MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); - // 构建数据权限连表条件 - CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId); - return selectJoinList(CrmCustomerDO.class, mpjLambdaWrapperX); + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId); + return selectJoinList(CrmCustomerDO.class, query); } } 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 6e43944eb..98630ffdf 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 @@ -112,9 +112,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Override public PageResult getBusinessPageByCustomer(CrmBusinessPageReqVO pageReqVO, Long userId) { - // 校验客户存在 + // 校验客户存在 TODO @puhui999:这里不校验 customerService.validateCustomer(pageReqVO.getCustomerId()); - + // TODO @puhui999:感觉这里貌似不太复用用 selectPage,因为他可能没商机权限,只是因为能看 customer,所以可以看到列表 return businessMapper.selectPage(pageReqVO, userId); } 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 3c463fa75..63e2fcbd2 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 @@ -35,6 +35,7 @@ public class CrmClueServiceImpl implements CrmClueService { @Resource private CrmClueMapper clueMapper; + @Resource private CrmCustomerService customerService; @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 9220a9e66..39aac0e11 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 @@ -137,7 +137,7 @@ public class CrmContactServiceImpl implements CrmContactService { public PageResult getContactPageByCustomerId(CrmContactPageReqVO pageVO, Long userId) { // 校验用户存在 customerService.validateCustomer(pageVO.getCustomerId()); - + // TODO @puhui999:getBusinessPageByCustomer 同理 return contactMapper.selectPage(pageVO, userId); } 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 e29e05fb0..d7ebb572b 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 @@ -126,9 +126,9 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { @Override @Transactional(rollbackFor = Exception.class) public void deletePermission(Integer bizType, Long bizId, Integer level) { + // 校验存在 List permissions = crmPermissionMapper.selectListByBizTypeAndBizIdAndLevel( bizType, bizId, level); - // 校验存在 if (CollUtil.isEmpty(permissions)) { throw exception(CRM_PERMISSION_NOT_EXISTS); } @@ -139,6 +139,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { @Override public void deletePermission(Integer bizType, Long bizId) { + // TODO @puhui999:这种直接写条件删除;不需要先查询,再删除 List permissionList = crmPermissionMapper.selectByBizTypeAndBizId(bizType, bizId); if (CollUtil.isEmpty(permissionList)) { return; 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 0ffa8572e..5eb80b292 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 @@ -26,67 +26,74 @@ public class CrmQueryWrapperUtils { /** * 构造 CRM 数据类型数据分页查询条件 * - * @param queryMapper 连表查询对象 + * @param query 连表查询对象 * @param bizType 数据类型 {@link CrmBizTypeEnum} * @param bizId 数据编号 * @param userId 用户编号 * @param sceneType 场景类型 * @param pool 公海 */ - public static , S> void builderPageQuery( - T queryMapper, Integer bizType, SFunction bizId, Long userId, Integer sceneType, Boolean pool) { + // TODO @puhui999:bizId 直接传递会不会简单点 + // TODO @puhui999:builderPageQuery 应该不仅仅适合于分页查询,应该适用于所有的查询;可以改成 appendPermissionCondition + public static , S> void builderPageQuery(T query, Integer bizType, SFunction bizId, + Long userId, Integer sceneType, Boolean pool) { // 1. 构建数据权限连表条件 if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 - queryMapper.innerJoin(CrmPermissionDO.class, on -> + query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType).eq(CrmPermissionDO::getBizId, bizId) .eq(CrmPermissionDO::getUserId, userId)); } - // 1.2 场景一:我负责的数据 + // 2.1 场景一:我负责的数据 if (CrmSceneTypeEnum.isOwner(sceneType)) { - queryMapper.eq("owner_user_id", userId); + query.eq("owner_user_id", userId); } - // 1.3 场景一:我参与的数据 + // 2.2 场景二:我参与的数据 + // TODO @puhui999:参与,指的是有读写权限噢;可以把 1. 的合并到 2.2 里;因为 2.1 不需要; if (CrmSceneTypeEnum.isInvolved(sceneType)) { - queryMapper.ne("owner_user_id", userId); + query.ne("owner_user_id", userId); } - // 1.4 场景二:下属负责的数据 + // 2.3 场景三:下属负责的数据 if (CrmSceneTypeEnum.isSubordinate(sceneType)) { List subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId); + // TODO @puhui999:如果为空,不拼接,就是查询了所有数据呀? if (CollUtil.isNotEmpty(subordinateUsers)) { - queryMapper.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId)); + query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId)); } } // 2. 拼接公海的查询条件 if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海 - queryMapper.isNull("owner_user_id"); + query.isNull("owner_user_id"); } else { // 情况二:不是公海 - queryMapper.isNotNull("owner_user_id"); + query.isNotNull("owner_user_id"); } } /** * 构造 CRM 数据类型批量数据查询条件 * - * @param queryMapper 连表查询对象 + * @param query 连表查询对象 * @param bizType 数据类型 {@link CrmBizTypeEnum} * @param bizIds 数据编号 * @param userId 用户编号 */ - public static , S> void builderListQueryBatch( - T queryMapper, Integer bizType, Collection bizIds, Long userId) { - // 1. 构建数据权限连表条件 + // TODO @puhui999:可以改成 appendPermissionCondition + // TODO @puhui999:S 是不是可以删除 + public static , S> void builderListQueryBatch(T query, Integer bizType, Collection bizIds, Long userId) { + // TODO @puhui999:这里先 if return 简单点 if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 - queryMapper.innerJoin(CrmPermissionDO.class, on -> + query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType).in(CrmPermissionDO::getBizId, bizIds) .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); } } + // TODO @puhui999:需要加个变量,不用每次都拿哈; private static AdminUserApi getAdminUserApi() { return SpringUtil.getBean(AdminUserApi.class); } + // TODO @puhui999:需要实现; /** * 校验用户是否是管理员 * diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java index c4510ba08..b6cab3030 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java @@ -22,7 +22,6 @@ public interface AdminUserApi { */ AdminUserRespDTO getUser(Long id); - // TODO @puhui999:这里返回 List 方法名可以改成 getUserListBySubordinate /** * 通过用户 ID 查询用户下属 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java index c7055114e..3fce326fe 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java @@ -39,13 +39,11 @@ public class AdminUserApiImpl implements AdminUserApi { @Override public List getUserListBySubordinate(Long userId) { - // 1. 获取用户信息 + // 1.1 获取用户负责的部门 AdminUserDO user = userService.getUser(userId); if (user == null) { return Collections.emptyList(); } - - // 2.1 获取用户负责的部门 ArrayList deptIds = new ArrayList<>(); DeptDO dept = deptService.getDept(user.getDeptId()); if (dept == null) { @@ -54,13 +52,14 @@ public class AdminUserApiImpl implements AdminUserApi { if (ObjUtil.notEqual(dept.getLeaderUserId(), userId)) { // 校验为负责人 return Collections.emptyList(); } - deptIds.add(dept.getId()); // 加入此部门 - // 2.2 获取所有子部门 + deptIds.add(dept.getId()); + // 1.2 获取所有子部门 List childDeptList = deptService.getChildDeptList(dept.getId()); if (CollUtil.isNotEmpty(childDeptList)) { deptIds.addAll(convertSet(childDeptList, DeptDO::getId)); } - // 2.3 获取用户信息 + + // 2. 获取部门对应的用户信息 List users = userService.getUserListByDeptIds(deptIds); users.removeIf(item -> ObjUtil.equal(item.getId(), userId)); // 排除自己 return BeanUtils.toBean(users, AdminUserRespDTO.class); diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 40086477b..85b284c3c 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -37,11 +37,11 @@ - - - - - + + cn.iocoder.boot + yudao-module-member-biz + ${revision} + @@ -56,11 +56,11 @@ - - - - - + + cn.iocoder.boot + yudao-module-pay-biz + ${revision} + @@ -70,26 +70,26 @@ - - - - - - - - - - - - - - - - - - - - + + cn.iocoder.boot + yudao-module-promotion-biz + ${revision} + + + cn.iocoder.boot + yudao-module-product-biz + ${revision} + + + cn.iocoder.boot + yudao-module-trade-biz + ${revision} + + + cn.iocoder.boot + yudao-module-statistics-biz + ${revision} + From 5c60202c1471f9238cdd1cd4c0ef65d05ca7b604 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 8 Dec 2023 22:17:13 +0800 Subject: [PATCH 008/151] =?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 009/151] =?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 010/151] =?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 e4d3175f06ef278e8abd536fa793a28862421198 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 11 Dec 2023 12:02:41 +0800 Subject: [PATCH 011/151] =?UTF-8?q?CRM-=E6=95=B0=E6=8D=AE=E6=9D=83?= =?UTF-8?q?=E9=99=90=EF=BC=9A=E5=AE=8C=E5=96=84=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 --- .../crm/enums/common/CrmBizTypeEnum.java | 3 +- .../admin/business/CrmBusinessController.java | 2 +- .../vo/business/CrmBusinessPageReqVO.java | 3 - .../admin/contact/CrmContactController.java | 2 +- .../admin/contact/vo/CrmContactPageReqVO.java | 3 - .../admin/contract/CrmContractController.java | 2 +- .../contract/vo/CrmContractPageReqVO.java | 3 - .../receivable/CrmReceivableController.java | 8 ++- .../vo/plan/CrmReceivablePlanPageReqVO.java | 3 - .../vo/receivable/CrmReceivablePageReqVO.java | 3 - .../crm/convert/contact/ContactConvert.java | 6 +- .../crm/convert/contract/ContractConvert.java | 6 +- .../dal/mysql/business/CrmBusinessMapper.java | 15 ++-- .../crm/dal/mysql/clue/CrmClueMapper.java | 4 +- .../dal/mysql/contact/CrmContactMapper.java | 20 ++++-- .../dal/mysql/contract/CrmContractMapper.java | 18 +++-- .../dal/mysql/customer/CrmCustomerMapper.java | 4 +- .../mysql/permission/CrmPermissionMapper.java | 6 ++ .../mysql/receivable/CrmReceivableMapper.java | 39 +++++++++-- .../service/business/CrmBusinessService.java | 3 +- .../business/CrmBusinessServiceImpl.java | 9 +-- .../service/contact/CrmContactService.java | 6 +- .../contact/CrmContactServiceImpl.java | 8 +-- .../service/contract/CrmContractService.java | 5 +- .../contract/CrmContractServiceImpl.java | 6 ++ .../customer/CrmCustomerServiceImpl.java | 1 - .../permission/CrmPermissionServiceImpl.java | 11 ++- .../receivable/CrmReceivableService.java | 7 +- .../receivable/CrmReceivableServiceImpl.java | 11 ++- .../module/crm/util/CrmQueryWrapperUtils.java | 70 +++++++++++-------- .../CrmCrmReceivableServiceImplTest.java | 5 +- 31 files changed, 169 insertions(+), 123 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java index 0a441d229..da24039b2 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java @@ -22,7 +22,8 @@ public enum CrmBizTypeEnum implements IntArrayValuable { CRM_CONTACT(3, "联系人"), CRM_BUSINESS(4, "商机"), CRM_CONTRACT(5, "合同"), - CRM_PRODUCT(6, "产品") + CRM_PRODUCT(6, "产品"), + CRM_RECEIVABLE(7, "回款") ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizTypeEnum::getType).toArray(); 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 d23595290..e4e24d29d 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 @@ -122,7 +122,7 @@ public class CrmBusinessController { @Operation(summary = "获得商机分页,基于指定客户") public CommonResult> getBusinessPageByCustomer(@Valid CrmBusinessPageReqVO pageReqVO) { Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); - PageResult pageResult = businessService.getBusinessPageByCustomer(pageReqVO, getLoginUserId()); + PageResult pageResult = businessService.getBusinessPageByCustomerId(pageReqVO); // 处理客户名称回显 // TODO @ljlleo:可以使用 CollectionUtils.convertSet 替代常用的 stream 操作,更简洁一点;下面几个也是哈; Set customerIds = pageResult.getList().stream() 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 579026047..3c9520607 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 @@ -24,7 +24,4 @@ public class CrmBusinessPageReqVO extends PageParam { @InEnum(CrmSceneTypeEnum.class) private Integer sceneType; // 场景类型,为 null 时则表示全部 - @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") - private Boolean pool; // null 则表示为不是公海数据 - } 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 dbdc0663d..37db59963 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 @@ -125,7 +125,7 @@ public class CrmContactController { @Operation(summary = "获得联系人分页,基于指定客户") public CommonResult> getContactPageByCustomer(@Valid CrmContactPageReqVO pageVO) { Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); - PageResult pageResult = contactService.getContactPageByCustomerId(pageVO, getLoginUserId()); + PageResult pageResult = contactService.getContactPageByCustomerId(pageVO); return success(convertDetailContactPage(pageResult)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java index eb6ebd76c..75294a1bd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactPageReqVO.java @@ -39,7 +39,4 @@ public class CrmContactPageReqVO extends PageParam { @InEnum(CrmSceneTypeEnum.class) private Integer sceneType; // 场景类型,为 null 时则表示全部 - @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") - private Boolean pool; // null 则表示为不是公海数据 - } 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 623a9ab91..5086625a7 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 @@ -95,7 +95,7 @@ public class CrmContractController { @Operation(summary = "获得联系人分页,基于指定客户") public CommonResult> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) { Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); - PageResult pageResult = contractService.getContractPageByCustomer(pageVO, getLoginUserId()); + PageResult pageResult = contractService.getContractPageByCustomerId(pageVO); return success(convertDetailContractPage(pageResult)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java index 2b3123bd9..94199ada6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java @@ -30,7 +30,4 @@ public class CrmContractPageReqVO extends PageParam { @InEnum(CrmSceneTypeEnum.class) private Integer sceneType; // 场景类型,为 null 时则表示全部 - @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") - private Boolean pool; // null 则表示为不是公海数据 TODO @puhui999:合同没有公海。目前只有【客户】【线索】有公海,其它都没 - } 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 4c4be4a25..27dc063a5 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 @@ -36,6 +36,7 @@ import java.util.Map; import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @@ -94,7 +95,7 @@ public class CrmReceivableController { @Operation(summary = "获得回款分页") @PreAuthorize("@ss.hasPermission('crm:receivable:query')") public CommonResult> getReceivablePage(@Valid CrmReceivablePageReqVO pageReqVO) { - PageResult pageResult = receivableService.getReceivablePage(pageReqVO); + PageResult pageResult = receivableService.getReceivablePage(pageReqVO, getLoginUserId()); return success(convertDetailReceivablePage(pageResult)); } @@ -102,7 +103,7 @@ public class CrmReceivableController { @Operation(summary = "获得回款分页,基于指定客户") public CommonResult> getReceivablePageByCustomer(@Valid CrmReceivablePageReqVO pageReqVO) { Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); - PageResult pageResult = receivableService.getReceivablePageByCustomer(pageReqVO); + PageResult pageResult = receivableService.getReceivablePageByCustomerId(pageReqVO); return success(convertDetailReceivablePage(pageResult)); } @@ -113,7 +114,8 @@ public class CrmReceivableController { @OperateLog(type = EXPORT) public void exportReceivableExcel(@Valid CrmReceivablePageReqVO exportReqVO, HttpServletResponse response) throws IOException { - PageResult pageResult = receivableService.getReceivablePage(exportReqVO); + exportReqVO.setPageSize(PAGE_SIZE_NONE); + PageResult pageResult = receivableService.getReceivablePage(exportReqVO, getLoginUserId()); // 导出 Excel ExcelUtils.write(response, "回款.xls", "数据", CrmReceivableRespVO.class, convertDetailReceivablePage(pageResult).getList()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java index 16681ba3c..f86aa346d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java @@ -25,7 +25,4 @@ public class CrmReceivablePlanPageReqVO extends PageParam { @InEnum(CrmSceneTypeEnum.class) private Integer sceneType; // 场景类型,为 null 时则表示全部 - @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") - private Boolean pool; // null 则表示为不是公海数据 - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java index 3eef5d013..1bca32fa3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java @@ -27,7 +27,4 @@ public class CrmReceivablePageReqVO extends PageParam { @InEnum(CrmSceneTypeEnum.class) private Integer sceneType; // 场景类型,为 null 时则表示全部 - @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") - private Boolean pool; // null 则表示为不是公海数据 - } 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..b907c3e0c 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 @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferRe 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; @@ -48,10 +47,7 @@ public interface ContactConvert { List convertAllList(List list); - @Mappings({ - @Mapping(target = "bizId", source = "reqVO.id"), - @Mapping(target = "newOwnerUserId", source = "reqVO.id") - }) + @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/convert/contract/ContractConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java index 2041ba5de..195a08301 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java @@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferRe 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; @@ -39,10 +38,7 @@ public interface ContractConvert { List convertList02(List list); - @Mappings({ - @Mapping(target = "bizId", source = "reqVO.id"), - @Mapping(target = "newOwnerUserId", source = "reqVO.id") - }) + @Mapping(target = "bizId", source = "reqVO.id") CrmPermissionTransferReqBO convert(CrmContractTransferReqVO reqVO, Long userId); default PageResult convertPage(PageResult pageResult, Map userMap, 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 7c06e57a0..d34730018 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 @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.business; 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.business.vo.business.CrmBusinessPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; @@ -27,14 +28,20 @@ public interface CrmBusinessMapper extends BaseMapperX { .set(CrmBusinessDO::getOwnerUserId, ownerUserId)); } + default PageResult selectPageByCustomerId(CrmBusinessPageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eq(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 + .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) + .orderByDesc(CrmBusinessDO::getId)); + } + default PageResult selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId, - userId, pageReqVO.getSceneType(), pageReqVO.getPool()); + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId, + userId, pageReqVO.getSceneType(), Boolean.FALSE); // 拼接自身的查询条件 query.selectAll(CrmBusinessDO.class) - .eqIfPresent(CrmBusinessDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 .likeIfPresent(CrmBusinessDO::getName, pageReqVO.getName()) .orderByDesc(CrmBusinessDO::getId); return selectJoinPage(pageReqVO, CrmBusinessDO.class, query); @@ -43,7 +50,7 @@ public interface CrmBusinessMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId); + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId); return selectJoinList(CrmBusinessDO.class, query); } 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 479a12f1a..b78afc4fe 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,7 +30,7 @@ public interface CrmClueMapper extends BaseMapperX { default PageResult selectPage(CrmCluePageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId, + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); // 拼接自身的查询条件 query.selectAll(CrmClueDO.class) @@ -44,7 +44,7 @@ public interface CrmClueMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId); + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId); return selectJoinList(CrmClueDO.class, query); } 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 189f36f08..2a0a746f5 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 @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contact; 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.contact.vo.CrmContactPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; @@ -27,14 +28,25 @@ public interface CrmContactMapper extends BaseMapperX { .set(CrmContactDO::getOwnerUserId, ownerUserId)); } + default PageResult selectPageByCustomerId(CrmContactPageReqVO pageVO) { + return selectPage(pageVO, new LambdaQueryWrapperX() + .eq(CrmContactDO::getCustomerId, pageVO.getCustomerId()) // 指定客户编号 + .likeIfPresent(CrmContactDO::getName, pageVO.getName()) + .eqIfPresent(CrmContactDO::getMobile, pageVO.getMobile()) + .eqIfPresent(CrmContactDO::getTelephone, pageVO.getTelephone()) + .eqIfPresent(CrmContactDO::getEmail, pageVO.getEmail()) + .eqIfPresent(CrmContactDO::getQq, pageVO.getQq()) + .eqIfPresent(CrmContactDO::getWechat, pageVO.getWechat()) + .orderByDesc(CrmContactDO::getId)); + } + default PageResult selectPage(CrmContactPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId, - userId, pageReqVO.getSceneType(), pageReqVO.getPool()); + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId, + userId, pageReqVO.getSceneType(), Boolean.FALSE); // 拼接自身的查询条件 query.selectAll(CrmContactDO.class) - .eqIfPresent(CrmContactDO::getCustomerId, pageReqVO.getCustomerId()) // 指定客户编号 .likeIfPresent(CrmContactDO::getName, pageReqVO.getName()) .eqIfPresent(CrmContactDO::getMobile, pageReqVO.getMobile()) .eqIfPresent(CrmContactDO::getTelephone, pageReqVO.getTelephone()) @@ -48,7 +60,7 @@ public interface CrmContactMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); return selectJoinList(CrmContactDO.class, query); } 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 37452feb7..5bc9d5cb2 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 @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contract; 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.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; @@ -27,13 +28,22 @@ public interface CrmContractMapper extends BaseMapperX { .set(CrmContractDO::getOwnerUserId, ownerUserId)); } + default PageResult selectPageByCustomerId(CrmContractPageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eq(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) + .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) + .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) + .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) + .eqIfPresent(CrmContractDO::getBusinessId, pageReqVO.getBusinessId()) + .orderByDesc(CrmContractDO::getId)); + } + default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); // 构建数据权限连表条件 - CrmQueryWrapperUtils.builderPageQuery(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContractDO::getId, - userId, pageReqVO.getSceneType(), pageReqVO.getPool()); + CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContractDO::getId, + userId, pageReqVO.getSceneType(), Boolean.FALSE); mpjLambdaWrapperX.selectAll(CrmContractDO.class) - .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) @@ -45,7 +55,7 @@ public interface CrmContractMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); // 构建数据权限连表条件 - CrmQueryWrapperUtils.builderListQueryBatch(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); + CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); return selectJoinList(CrmContractDO.class, mpjLambdaWrapperX); } 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 86c8617b7..dece49056 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,7 +30,7 @@ public interface CrmCustomerMapper extends BaseMapperX { default PageResult selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.builderPageQuery(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), pageReqVO.getPool()); // 拼接自身的查询条件 query.selectAll(CrmCustomerDO.class) @@ -45,7 +45,7 @@ public interface CrmCustomerMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.builderListQueryBatch(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId); + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId); return selectJoinList(CrmCustomerDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java index 349318502..e7de279d8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java @@ -46,4 +46,10 @@ public interface CrmPermissionMapper extends BaseMapperX { .eq(CrmPermissionDO::getId, id).eq(CrmPermissionDO::getUserId, userId)); } + default int deletePermission(Integer bizType, Long bizId) { + return delete(new LambdaQueryWrapperX() + .eq(CrmPermissionDO::getBizType, bizType) + .eq(CrmPermissionDO::getBizId, bizId)); + } + } 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 9da130022..4839492c7 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 @@ -3,10 +3,17 @@ package cn.iocoder.yudao.module.crm.dal.mysql.receivable; 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.receivable.vo.receivable.CrmReceivablePageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; +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 java.util.Collection; +import java.util.List; + /** * 回款 Mapper * @@ -15,15 +22,13 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface CrmReceivableMapper extends BaseMapperX { - default PageResult selectPage(CrmReceivablePageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(CrmReceivableDO::getNo, reqVO.getNo()) - .eqIfPresent(CrmReceivableDO::getPlanId, reqVO.getPlanId()) - .eqIfPresent(CrmReceivableDO::getCustomerId, reqVO.getCustomerId()) - .orderByDesc(CrmReceivableDO::getId)); + default int updateOwnerUserIdById(Long id, Long ownerUserId) { + return update(new LambdaUpdateWrapper() + .eq(CrmReceivableDO::getId, id) + .set(CrmReceivableDO::getOwnerUserId, ownerUserId)); } - default PageResult selectPageByCustomer(CrmReceivablePageReqVO reqVO) { + default PageResult selectPageByCustomerId(CrmReceivablePageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .eq(CrmReceivableDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 .eqIfPresent(CrmReceivableDO::getNo, reqVO.getNo()) @@ -31,4 +36,24 @@ public interface CrmReceivableMapper extends BaseMapperX { .orderByDesc(CrmReceivableDO::getId)); } + default PageResult selectPage(CrmReceivablePageReqVO pageReqVO, Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), CrmReceivableDO::getId, + userId, pageReqVO.getSceneType(), Boolean.FALSE); + // 拼接自身的查询条件 + query.selectAll(CrmReceivableDO.class) + .eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo()) + .eqIfPresent(CrmReceivableDO::getPlanId, pageReqVO.getPlanId()) + .orderByDesc(CrmReceivableDO::getId); + return selectJoinPage(pageReqVO, CrmReceivableDO.class, query); + } + + default List selectBatchIds(Collection ids, Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), ids, userId); + return selectJoinList(CrmReceivableDO.class, query); + } + } 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 c46f5f0bf..d81a75d9a 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 @@ -75,10 +75,9 @@ public interface CrmBusinessService { * 数据权限:基于 {@link CrmCustomerDO} 读取 * * @param pageReqVO 分页查询 - * @param userId 用户编号 * @return 联系人分页 */ - PageResult getBusinessPageByCustomer(CrmBusinessPageReqVO pageReqVO, Long userId); + PageResult getBusinessPageByCustomerId(CrmBusinessPageReqVO 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 98630ffdf..f2db01b83 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 @@ -111,11 +111,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } @Override - public PageResult getBusinessPageByCustomer(CrmBusinessPageReqVO pageReqVO, Long userId) { - // 校验客户存在 TODO @puhui999:这里不校验 - customerService.validateCustomer(pageReqVO.getCustomerId()); - // TODO @puhui999:感觉这里貌似不太复用用 selectPage,因为他可能没商机权限,只是因为能看 customer,所以可以看到列表 - return businessMapper.selectPage(pageReqVO, userId); + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) + public PageResult getBusinessPageByCustomerId(CrmBusinessPageReqVO pageReqVO) { + return businessMapper.selectPageByCustomerId(pageReqVO); } @Override @@ -127,7 +125,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { // 2.1 数据权限转移 crmPermissionService.transferPermission( CrmBusinessConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType())); - // 2.2 设置新的负责人 businessMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); 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 4306d8aea..46cbec699 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 @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactCreateR 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.CrmContactDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import jakarta.validation.Valid; import java.util.Collection; @@ -71,12 +72,11 @@ public interface CrmContactService { /** * 获得联系人分页 * - * 数据权限:基于 {@link CrmContactDO} + * 数据权限:基于 {@link CrmCustomerDO} * * @param pageVO 分页查询 - * @param userId 用户编号 * @return 联系人分页 */ - PageResult getContactPageByCustomerId(CrmContactPageReqVO pageVO, Long userId); + PageResult getContactPageByCustomerId(CrmContactPageReqVO pageVO); } 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 39aac0e11..5ee1e2b29 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 @@ -134,11 +134,9 @@ public class CrmContactServiceImpl implements CrmContactService { } @Override - public PageResult getContactPageByCustomerId(CrmContactPageReqVO pageVO, Long userId) { - // 校验用户存在 - customerService.validateCustomer(pageVO.getCustomerId()); - // TODO @puhui999:getBusinessPageByCustomer 同理 - return contactMapper.selectPage(pageVO, userId); + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageVO.customerId", level = CrmPermissionLevelEnum.READ) + public PageResult getContactPageByCustomerId(CrmContactPageReqVO pageVO) { + return contactMapper.selectPageByCustomerId(pageVO); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index 0531dbe38..7d3f83335 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -75,12 +75,9 @@ public interface CrmContractService { * 数据权限:基于 {@link CrmCustomerDO} 读取 * * @param pageReqVO 分页查询 - * @param userId 用户编号 * @return 联系人分页 */ - default PageResult getContractPageByCustomer(CrmContractPageReqVO pageReqVO, Long userId) { - return getContractPage(pageReqVO, userId); - } + PageResult getContractPageByCustomerId(CrmContractPageReqVO pageReqVO); /** * 合同转移 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 23795f94e..7f1b20a0e 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 @@ -104,6 +104,12 @@ public class CrmContractServiceImpl implements CrmContractService { return contractMapper.selectPage(pageReqVO, userId); } + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) + public PageResult getContractPageByCustomerId(CrmContractPageReqVO pageReqVO) { + return contractMapper.selectPageByCustomerId(pageReqVO); + } + @Override @Transactional(rollbackFor = Exception.class) public void transferContract(CrmContractTransferReqVO reqVO, 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 93589a5b0..fd1009255 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 @@ -114,7 +114,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { */ @Override public void validateCustomer(Long customerId) { - // TODO puhui999: 不返回客户不走校验应该可行 // 校验客户是否存在 if (customerId == null) { throw exception(CUSTOMER_NOT_EXISTS); 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 d7ebb572b..58bd51149 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 @@ -139,14 +139,11 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { @Override public void deletePermission(Integer bizType, Long bizId) { - // TODO @puhui999:这种直接写条件删除;不需要先查询,再删除 - List permissionList = crmPermissionMapper.selectByBizTypeAndBizId(bizType, bizId); - if (CollUtil.isEmpty(permissionList)) { - return; - } - // 删除数据权限 - crmPermissionMapper.deleteBatchIds(convertSet(permissionList, CrmPermissionDO::getId)); + int deletedCol = crmPermissionMapper.deletePermission(bizType, bizId); + if (deletedCol == 0) { + throw exception(CRM_PERMISSION_NOT_EXISTS); + } } @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java index bf9e5571b..8f7984afe 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java @@ -6,8 +6,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.Crm import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; - import jakarta.validation.Valid; + import java.util.Collection; import java.util.List; @@ -62,9 +62,10 @@ public interface CrmReceivableService { * 数据权限:基于 {@link CrmReceivableDO} 读取 * * @param pageReqVO 分页查询 + * @param userId 用户编号 * @return 回款分页 */ - PageResult getReceivablePage(CrmReceivablePageReqVO pageReqVO); + PageResult getReceivablePage(CrmReceivablePageReqVO pageReqVO, Long userId); /** * 获得回款分页,基于指定客户 @@ -74,6 +75,6 @@ public interface CrmReceivableService { * @param pageReqVO 分页查询 * @return 回款分页 */ - PageResult getReceivablePageByCustomer(CrmReceivablePageReqVO pageReqVO); + PageResult getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO); } 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 ac3b71e08..18a289be2 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 @@ -20,10 +20,10 @@ 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.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.util.Collection; import java.util.List; @@ -129,16 +129,15 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { return receivableMapper.selectBatchIds(ids); } - // TODO @芋艿:数据权限 @Override - public PageResult getReceivablePage(CrmReceivablePageReqVO pageReqVO) { - return receivableMapper.selectPage(pageReqVO); + public PageResult getReceivablePage(CrmReceivablePageReqVO pageReqVO, Long userId) { + return receivableMapper.selectPage(pageReqVO, userId); } @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) - public PageResult getReceivablePageByCustomer(CrmReceivablePageReqVO pageReqVO) { - return receivableMapper.selectPageByCustomer(pageReqVO); + public PageResult getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO) { + return receivableMapper.selectPageByCustomerId(pageReqVO); } } 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 5eb80b292..e3e6be48b 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 @@ -6,6 +6,7 @@ import cn.hutool.extra.spring.SpringUtil; 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.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; @@ -17,7 +18,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; /** - * CRM 分页查询工具类 + * CRM 查询工具类 * * @author HUIHUI */ @@ -26,17 +27,16 @@ public class CrmQueryWrapperUtils { /** * 构造 CRM 数据类型数据分页查询条件 * - * @param query 连表查询对象 - * @param bizType 数据类型 {@link CrmBizTypeEnum} - * @param bizId 数据编号 - * @param userId 用户编号 - * @param sceneType 场景类型 - * @param pool 公海 + * @param query 连表查询对象 + * @param bizType 数据类型 {@link CrmBizTypeEnum} + * @param bizId 数据编号 + * @param userId 用户编号 + * @param sceneType 场景类型 + * @param pool 公海 */ - // TODO @puhui999:bizId 直接传递会不会简单点 - // TODO @puhui999:builderPageQuery 应该不仅仅适合于分页查询,应该适用于所有的查询;可以改成 appendPermissionCondition - public static , S> void builderPageQuery(T query, Integer bizType, SFunction bizId, - Long userId, Integer sceneType, Boolean pool) { + // TODO @puhui999:bizId 直接传递会不会简单点 回复:还是需要 SFunction 因为分页连表时不知道 bizId 是多少 + public static , S> void appendPermissionCondition(T query, Integer bizType, SFunction bizId, + Long userId, Integer sceneType, Boolean pool) { // 1. 构建数据权限连表条件 if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 query.innerJoin(CrmPermissionDO.class, on -> @@ -48,9 +48,13 @@ public class CrmQueryWrapperUtils { query.eq("owner_user_id", userId); } // 2.2 场景二:我参与的数据 - // TODO @puhui999:参与,指的是有读写权限噢;可以把 1. 的合并到 2.2 里;因为 2.1 不需要; if (CrmSceneTypeEnum.isInvolved(sceneType)) { - query.ne("owner_user_id", userId); + query + .ne("owner_user_id", userId) + .and(q -> q.eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.READ.getLevel()) + .or() + .eq(CrmPermissionDO::getLevel, CrmPermissionLevelEnum.WRITE.getLevel())); + } // 2.3 场景三:下属负责的数据 if (CrmSceneTypeEnum.isSubordinate(sceneType)) { @@ -61,7 +65,7 @@ public class CrmQueryWrapperUtils { } } - // 2. 拼接公海的查询条件 + // 3. 拼接公海的查询条件 if (ObjUtil.equal(pool, Boolean.TRUE)) { // 情况一:公海 query.isNull("owner_user_id"); } else { // 情况二:不是公海 @@ -72,28 +76,27 @@ public class CrmQueryWrapperUtils { /** * 构造 CRM 数据类型批量数据查询条件 * - * @param query 连表查询对象 - * @param bizType 数据类型 {@link CrmBizTypeEnum} - * @param bizIds 数据编号 - * @param userId 用户编号 + * @param query 连表查询对象 + * @param bizType 数据类型 {@link CrmBizTypeEnum} + * @param bizIds 数据编号 + * @param userId 用户编号 */ - // TODO @puhui999:可以改成 appendPermissionCondition - // TODO @puhui999:S 是不是可以删除 - public static , S> void builderListQueryBatch(T query, Integer bizType, Collection bizIds, Long userId) { - // TODO @puhui999:这里先 if return 简单点 - if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 - query.innerJoin(CrmPermissionDO.class, on -> - on.eq(CrmPermissionDO::getBizType, bizType).in(CrmPermissionDO::getBizId, bizIds) - .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); + public static > void appendPermissionCondition(T query, Integer bizType, Collection bizIds, Long userId) { + if (ObjUtil.equal(validateAdminUser(userId), Boolean.TRUE)) {// 管理员不需要数据权限 + return; } + + query.innerJoin(CrmPermissionDO.class, on -> + on.eq(CrmPermissionDO::getBizType, bizType).in(CrmPermissionDO::getBizId, bizIds) + .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); } - // TODO @puhui999:需要加个变量,不用每次都拿哈; private static AdminUserApi getAdminUserApi() { - return SpringUtil.getBean(AdminUserApi.class); + return AdminUserApiHolder.ADMIN_USER_API; } // TODO @puhui999:需要实现; + /** * 校验用户是否是管理员 * @@ -104,4 +107,15 @@ public class CrmQueryWrapperUtils { return false; } + /** + * 静态内部类实现 AdminUserApi 单例获取 + * + * @author HUIHUI + */ + private static class AdminUserApiHolder { + + private static final AdminUserApi ADMIN_USER_API = SpringUtil.getBean(AdminUserApi.class); + + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivableServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivableServiceImplTest.java index 93ac0c99b..1f3d821af 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivableServiceImplTest.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivableServiceImplTest.java @@ -7,12 +7,11 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.Crm import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivableMapper; +import jakarta.annotation.Resource; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; -import jakarta.annotation.Resource; - import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -133,7 +132,7 @@ public class CrmCrmReceivableServiceImplTest extends BaseDbUnitTest { reqVO.setCustomerId(null); // 调用 - PageResult pageResult = receivableService.getReceivablePage(reqVO); + PageResult pageResult = receivableService.getReceivablePage(reqVO, 1L); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); From 1ac68aca97df6718153c327a25f2bf0b04b3c464 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 11 Dec 2023 15:56:12 +0800 Subject: [PATCH 012/151] =?UTF-8?q?CRM-=E5=9B=9E=E6=AC=BE=E8=AE=A1?= =?UTF-8?q?=E5=88=92=EF=BC=9A=E6=B7=BB=E5=8A=A0=E6=95=B0=E6=8D=AE=E6=9D=83?= =?UTF-8?q?=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/enums/common/CrmBizTypeEnum.java | 3 +- .../CrmReceivablePlanController.java | 10 +-- .../receivable/CrmReceivablePlanMapper.java | 38 +++++++++-- .../permission/CrmPermissionServiceImpl.java | 1 + .../receivable/CrmReceivablePlanService.java | 9 +-- .../CrmReceivablePlanServiceImpl.java | 30 ++++++--- .../CrmCrmReceivablePlanServiceImplTest.java | 67 ++++++++++--------- .../main/resources/codegen/vue/api/api.js.vm | 11 ++- 8 files changed, 104 insertions(+), 65 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java index da24039b2..f0784cab2 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmBizTypeEnum.java @@ -23,7 +23,8 @@ public enum CrmBizTypeEnum implements IntArrayValuable { CRM_BUSINESS(4, "商机"), CRM_CONTRACT(5, "合同"), CRM_PRODUCT(6, "产品"), - CRM_RECEIVABLE(7, "回款") + CRM_RECEIVABLE(7, "回款"), + CRM_RECEIVABLE_PLAN(8, "回款计划") ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmBizTypeEnum::getType).toArray(); 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 f8e2e6ecd..a5167313f 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 @@ -38,6 +38,7 @@ import java.util.Map; import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @@ -65,7 +66,7 @@ public class CrmReceivablePlanController { @Operation(summary = "创建回款计划") @PreAuthorize("@ss.hasPermission('crm:receivable-plan:create')") public CommonResult createReceivablePlan(@Valid @RequestBody CrmReceivablePlanCreateReqVO createReqVO) { - return success(receivablePlanService.createReceivablePlan(createReqVO)); + return success(receivablePlanService.createReceivablePlan(createReqVO, getLoginUserId())); } @PutMapping("/update") @@ -98,7 +99,7 @@ public class CrmReceivablePlanController { @Operation(summary = "获得回款计划分页") @PreAuthorize("@ss.hasPermission('crm:receivable-plan:query')") public CommonResult> getReceivablePlanPage(@Valid CrmReceivablePlanPageReqVO pageReqVO) { - PageResult pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO); + PageResult pageResult = receivablePlanService.getReceivablePlanPage(pageReqVO, getLoginUserId()); return success(convertDetailReceivablePlanPage(pageResult)); } @@ -106,7 +107,7 @@ public class CrmReceivablePlanController { @Operation(summary = "获得回款计划分页,基于指定客户") public CommonResult> getReceivablePlanPageByCustomer(@Valid CrmReceivablePlanPageReqVO pageReqVO) { Assert.notNull(pageReqVO.getCustomerId(), "客户编号不能为空"); - PageResult pageResult = receivablePlanService.getReceivablePlanPageByCustomer(pageReqVO); + PageResult pageResult = receivablePlanService.getReceivablePlanPageByCustomerId(pageReqVO); return success(convertDetailReceivablePlanPage(pageResult)); } @@ -117,7 +118,8 @@ public class CrmReceivablePlanController { @OperateLog(type = EXPORT) public void exportReceivablePlanExcel(@Valid CrmReceivablePlanPageReqVO exportReqVO, HttpServletResponse response) throws IOException { - PageResult pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO); + exportReqVO.setPageSize(PAGE_SIZE_NONE); + PageResult pageResult = receivablePlanService.getReceivablePlanPage(exportReqVO, getLoginUserId()); // 导出 Excel ExcelUtils.write(response, "回款计划.xls", "数据", CrmReceivablePlanRespVO.class, convertDetailReceivablePlanPage(pageResult).getList()); 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 52d16f0e1..5c6d40a71 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 @@ -3,10 +3,17 @@ package cn.iocoder.yudao.module.crm.dal.mysql.receivable; 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.receivable.vo.plan.CrmReceivablePlanPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; +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 java.util.Collection; +import java.util.List; + /** * 回款计划 Mapper * @@ -15,18 +22,37 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface CrmReceivablePlanMapper extends BaseMapperX { - default PageResult selectPage(CrmReceivablePlanPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .eqIfPresent(CrmReceivablePlanDO::getCustomerId, reqVO.getCustomerId()) - .eqIfPresent(CrmReceivablePlanDO::getContractId, reqVO.getContractId()) - .orderByDesc(CrmReceivablePlanDO::getId)); + default int updateOwnerUserIdById(Long id, Long ownerUserId) { + return update(new LambdaUpdateWrapper() + .eq(CrmReceivablePlanDO::getId, id) + .set(CrmReceivablePlanDO::getOwnerUserId, ownerUserId)); } - default PageResult selectPageByCustomer(CrmReceivablePlanPageReqVO reqVO) { + default PageResult selectPageByCustomerId(CrmReceivablePlanPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .eq(CrmReceivablePlanDO::getCustomerId, reqVO.getCustomerId()) // 必须传递 .eqIfPresent(CrmReceivablePlanDO::getContractId, reqVO.getContractId()) .orderByDesc(CrmReceivablePlanDO::getId)); } + default PageResult selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CrmReceivablePlanDO::getId, + userId, pageReqVO.getSceneType(), Boolean.FALSE); + // 拼接自身的查询条件 + query.selectAll(CrmReceivablePlanDO.class) + .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) + .eqIfPresent(CrmReceivablePlanDO::getContractId, pageReqVO.getContractId()) + .orderByDesc(CrmReceivablePlanDO::getId); + return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query); + } + + default List selectBatchIds(Collection ids, Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), ids, userId); + return selectJoinList(CrmReceivablePlanDO.class, query); + } + } 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 58bd51149..76f37f909 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,6 +138,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { } @Override + @Transactional(rollbackFor = Exception.class) public void deletePermission(Integer bizType, Long bizId) { // 删除数据权限 int deletedCol = crmPermissionMapper.deletePermission(bizType, bizId); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java index ba8a62d04..ded059b28 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java @@ -6,8 +6,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceiv import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; - import jakarta.validation.Valid; + import java.util.Collection; import java.util.List; @@ -24,7 +24,7 @@ public interface CrmReceivablePlanService { * @param createReqVO 创建信息 * @return 编号 */ - Long createReceivablePlan(@Valid CrmReceivablePlanCreateReqVO createReqVO); + Long createReceivablePlan(@Valid CrmReceivablePlanCreateReqVO createReqVO, Long userId); /** * 更新回款计划 @@ -62,9 +62,10 @@ public interface CrmReceivablePlanService { * 数据权限:基于 {@link CrmReceivablePlanDO} 读取 * * @param pageReqVO 分页查询 + * @param userId 用户编号 * @return 回款计划分页 */ - PageResult getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO); + PageResult getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId); /** * 获得回款计划分页,基于指定客户 @@ -74,6 +75,6 @@ public interface CrmReceivablePlanService { * @param pageReqVO 分页查询 * @return 回款计划分页 */ - PageResult getReceivablePlanPageByCustomer(CrmReceivablePlanPageReqVO pageReqVO); + PageResult getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO); } 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 7fe055690..d2d1b510d 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 @@ -17,10 +17,12 @@ 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.service.contract.CrmContractService; 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; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.util.Collection; import java.util.List; @@ -28,7 +30,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; // TODO @liuhongfeng:参考 CrmReceivableServiceImpl 写的 todo 哈; -// TODO @puhui999:数据权限 + /** * 回款计划 Service 实现类 * @@ -45,9 +47,11 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { private CrmContractService contractService; @Resource private CrmCustomerService customerService; + @Resource + private CrmPermissionService crmPermissionService; @Override - public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO) { + public Long createReceivablePlan(CrmReceivablePlanCreateReqVO createReqVO, Long userId) { // 插入 CrmReceivablePlanDO receivablePlan = CrmReceivablePlanConvert.INSTANCE.convert(createReqVO); receivablePlan.setFinishStatus(false); @@ -55,29 +59,33 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { checkReceivablePlan(receivablePlan); receivablePlanMapper.insert(receivablePlan); + // 创建数据权限 + crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType()) + .setBizId(receivablePlan.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 返回 return receivablePlan.getId(); } private void checkReceivablePlan(CrmReceivablePlanDO receivablePlan) { - if(ObjectUtil.isNull(receivablePlan.getContractId())){ + if (ObjectUtil.isNull(receivablePlan.getContractId())) { throw exception(CONTRACT_NOT_EXISTS); } CrmContractDO contract = contractService.getContract(receivablePlan.getContractId()); - if(ObjectUtil.isNull(contract)){ + if (ObjectUtil.isNull(contract)) { throw exception(CONTRACT_NOT_EXISTS); } CrmCustomerDO customer = customerService.getCustomer(receivablePlan.getCustomerId()); - if(ObjectUtil.isNull(customer)){ + if (ObjectUtil.isNull(customer)) { throw exception(CUSTOMER_NOT_EXISTS); } } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateReceivablePlan(CrmReceivablePlanUpdateReqVO updateReqVO) { // 校验存在 validateReceivablePlanExists(updateReqVO.getId()); @@ -88,6 +96,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteReceivablePlan(Long id) { // 校验存在 validateReceivablePlanExists(id); @@ -102,6 +111,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE_PLAN, bizId = "#id", level = CrmPermissionLevelEnum.READ) public CrmReceivablePlanDO getReceivablePlan(Long id) { return receivablePlanMapper.selectById(id); } @@ -115,14 +125,14 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { } @Override - public PageResult getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO) { - return receivablePlanMapper.selectPage(pageReqVO); + public PageResult getReceivablePlanPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) { + return receivablePlanMapper.selectPage(pageReqVO, userId); } @Override @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#pageReqVO.customerId", level = CrmPermissionLevelEnum.READ) - public PageResult getReceivablePlanPageByCustomer(CrmReceivablePlanPageReqVO pageReqVO) { - return receivablePlanMapper.selectPageByCustomer(pageReqVO); + public PageResult getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO) { + return receivablePlanMapper.selectPageByCustomerId(pageReqVO); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivablePlanServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivablePlanServiceImplTest.java index 7fa8986b0..4f17abcba 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivablePlanServiceImplTest.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/receivable/CrmCrmReceivablePlanServiceImplTest.java @@ -7,12 +7,12 @@ import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceiv import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; import cn.iocoder.yudao.module.crm.dal.mysql.receivable.CrmReceivablePlanMapper; +import jakarta.annotation.Resource; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; -import jakarta.annotation.Resource; - +import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; @@ -22,6 +22,7 @@ import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.RECEIVABLE_PL import static org.junit.jupiter.api.Assertions.*; // TODO 芋艿:后续,需要补充测试用例 + /** * {@link CrmReceivablePlanServiceImpl} 的单元测试类 * @@ -43,7 +44,7 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { CrmReceivablePlanCreateReqVO reqVO = randomPojo(CrmReceivablePlanCreateReqVO.class); // 调用 - Long receivablePlanId = receivablePlanService.createReceivablePlan(reqVO); + Long receivablePlanId = receivablePlanService.createReceivablePlan(reqVO, 1L); // 断言 assertNotNull(receivablePlanId); // 校验记录的属性是否正确 @@ -87,8 +88,8 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { // 调用 receivablePlanService.deleteReceivablePlan(id); - // 校验数据不存在了 - assertNull(crmReceivablePlanMapper.selectById(id)); + // 校验数据不存在了 + assertNull(crmReceivablePlanMapper.selectById(id)); } @Test @@ -103,34 +104,34 @@ public class CrmCrmReceivablePlanServiceImplTest extends BaseDbUnitTest { @Test @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 public void testGetReceivablePlanPage() { - // mock 数据 - CrmReceivablePlanDO dbReceivablePlan = randomPojo(CrmReceivablePlanDO.class, o -> { // 等会查询到 - o.setPeriod(null); - o.setReturnTime(null); - o.setRemindDays(null); - o.setRemindTime(null); - o.setCustomerId(null); - o.setContractId(null); - o.setOwnerUserId(null); - o.setRemark(null); - o.setCreateTime(null); - }); - crmReceivablePlanMapper.insert(dbReceivablePlan); - // 测试 customerId 不匹配 - crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCustomerId(null))); - // 测试 contractId 不匹配 - crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setContractId(null))); - // 准备参数 - CrmReceivablePlanPageReqVO reqVO = new CrmReceivablePlanPageReqVO(); - reqVO.setCustomerId(null); - reqVO.setContractId(null); - - // 调用 - PageResult pageResult = receivablePlanService.getReceivablePlanPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbReceivablePlan, pageResult.getList().get(0)); + // mock 数据 + CrmReceivablePlanDO dbReceivablePlan = randomPojo(CrmReceivablePlanDO.class, o -> { // 等会查询到 + o.setPeriod(null); + o.setReturnTime(null); + o.setRemindDays(null); + o.setRemindTime(null); + o.setCustomerId(null); + o.setContractId(null); + o.setOwnerUserId(null); + o.setRemark(null); + o.setCreateTime(null); + }); + crmReceivablePlanMapper.insert(dbReceivablePlan); + // 测试 customerId 不匹配 + crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setCustomerId(null))); + // 测试 contractId 不匹配 + crmReceivablePlanMapper.insert(cloneIgnoreId(dbReceivablePlan, o -> o.setContractId(null))); + // 准备参数 + CrmReceivablePlanPageReqVO reqVO = new CrmReceivablePlanPageReqVO(); + reqVO.setCustomerId(null); + reqVO.setContractId(null); + reqVO.setPageSize(PAGE_SIZE_NONE); + // 调用 + PageResult pageResult = receivablePlanService.getReceivablePlanPage(reqVO, 1L); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbReceivablePlan, pageResult.getList().get(0)); } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm index fcc2e9197..835c0192e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue/api/api.js.vm @@ -63,7 +63,7 @@ export function export${simpleClassName}Excel(params) { responseType: 'blob' }) } -## 特殊:主子表专属逻辑 TODO @puhui999:下面方法的【空格】不太对 +## 特殊:主子表专属逻辑 #foreach ($subTable in $subTables) #set ($index = $foreach.count - 1) #set ($subSimpleClassName = $subSimpleClassNames.get($index)) @@ -76,7 +76,7 @@ export function export${simpleClassName}Excel(params) { // ==================== 子表($subTable.classComment) ==================== ## 情况一:MASTER_ERP 时,需要分查询页子表 - #if ( $table.templateType == 11 ) + #if ($table.templateType == 11) // 获得${subTable.classComment}分页 export function get${subSimpleClassName}Page(params) { return request({ @@ -87,7 +87,7 @@ export function export${simpleClassName}Excel(params) { } ## 情况二:非 MASTER_ERP 时,需要列表查询子表 #else - #if ( $subTable.subJoinMany ) + #if ($subTable.subJoinMany) // 获得${subTable.classComment}列表 export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}) { return request({ @@ -106,7 +106,7 @@ export function export${simpleClassName}Excel(params) { #end #end ## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作 - #if ( $table.templateType == 11 ) + #if ($table.templateType == 11) // 新增${subTable.classComment} export function create${subSimpleClassName}(data) { return request({ @@ -115,7 +115,6 @@ export function export${simpleClassName}Excel(params) { data }) } - // 修改${subTable.classComment} export function update${subSimpleClassName}(data) { return request({ @@ -124,7 +123,6 @@ export function export${simpleClassName}Excel(params) { data }) } - // 删除${subTable.classComment} export function delete${subSimpleClassName}(id) { return request({ @@ -132,7 +130,6 @@ export function export${simpleClassName}Excel(params) { method: 'delete' }) } - // 获得${subTable.classComment} export function get${subSimpleClassName}(id) { return request({ From 63431082e51c7d0d0d86ce92573ab1ae1f700553 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 11 Dec 2023 16:37:14 +0800 Subject: [PATCH 013/151] =?UTF-8?q?member:=20=E5=AE=8C=E5=96=84=E8=BF=9E?= =?UTF-8?q?=E7=BB=AD=E7=AD=BE=E5=88=B0=20review=20=E6=8F=90=E5=88=B0?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/util/date/DateUtils.java | 10 +++++ .../signin/MemberSignInRecordConvert.java | 6 +-- .../signin/MemberSignInRecordServiceImpl.java | 45 ++----------------- 3 files changed, 17 insertions(+), 44 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java index c7e50a487..53b5574f9 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java @@ -177,4 +177,14 @@ public class DateUtils { return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now()); } + /** + * 是否昨天 + * + * @param date 日期 + * @return 是否 + */ + public static boolean isYesterday(LocalDateTime date) { + return LocalDateTimeUtil.isSameDay(date, LocalDateTime.now().minusDays(1)); + } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInRecordConvert.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInRecordConvert.java index 63193b029..9da5927f1 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInRecordConvert.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/signin/MemberSignInRecordConvert.java @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.module.member.controller.admin.signin.vo.record.MemberSignInRecordRespVO; import cn.iocoder.yudao.module.member.controller.app.signin.vo.record.AppMemberSignInRecordRespVO; import cn.iocoder.yudao.module.member.dal.dataobject.signin.MemberSignInConfigDO; @@ -47,10 +48,9 @@ public interface MemberSignInRecordConvert { // 1. 计算是第几天签到 configs.sort(Comparator.comparing(MemberSignInConfigDO::getDay)); MemberSignInConfigDO lastConfig = CollUtil.getLast(configs); // 最大签到天数配置 - // 1.2. 计算今天是第几天签到 + // 1.2. 计算今天是第几天签到 (只有连续签到才加否则重置为 1) int day = 1; - // TODO @puhui999:要判断是不是昨天签到的;是否是昨天的判断,可以抽个方法到 util 里 - if (lastRecord != null) { + if (lastRecord != null && DateUtils.isYesterday(lastRecord.getCreateTime())) { day = lastRecord.getDay() + 1; } // 1.3 判断是否超出了最大签到配置 diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java index 79f7c8729..cdf32105a 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/signin/MemberSignInRecordServiceImpl.java @@ -19,14 +19,12 @@ import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum; import cn.iocoder.yudao.module.member.service.level.MemberLevelService; import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService; import cn.iocoder.yudao.module.member.service.user.MemberUserService; +import jakarta.annotation.Resource; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; -import java.time.LocalDate; -import java.util.Comparator; import java.util.List; import java.util.Set; @@ -77,50 +75,15 @@ public class MemberSignInRecordServiceImpl implements MemberSignInRecordService } summary.setTodaySignIn(DateUtils.isToday(lastRecord.getCreateTime())); - // 4. 校验今天是否签到,没有签到则直接返回 + // 4.1 校验今天是否签到,没有签到则直接返回 if (!summary.getTodaySignIn()) { return summary; } - // 4.1. 判断连续签到天数 - // TODO @puhui999:连续签到,可以基于 lastRecord 的 day 和当前时间判断呀?按 day 统计连续签到天数可能不准确 - // 1. day 只是记录第几天签到的有可能不连续,比如第一次签到是周一,第二次签到是周三这样 lastRecord 的 day 为 2 但是并不是连续的两天 - // 2. day 超出签到规则的最大天数会重置到从第一天开始签到(我理解为开始下一轮,类似一周签到七天七天结束下周又从周一开始签到) - // 1. 回复:周三签到,day 要归 1 呀。连续签到哈; - List signInRecords = signInRecordMapper.selectListByUserId(userId); - signInRecords.sort(Comparator.comparing(MemberSignInRecordDO::getCreateTime).reversed()); // 根据签到时间倒序 - summary.setContinuousDay(calculateConsecutiveDays(signInRecords)); + // 4.2 连续签到天数 + summary.setContinuousDay(lastRecord.getDay()); return summary; } - /** - * 计算连续签到天数 - * - * @param signInRecords 签到记录列表 - * @return int 连续签到天数 - */ - public int calculateConsecutiveDays(List signInRecords) { - int consecutiveDays = 1; // 初始连续天数为1 - LocalDate previousDate = null; - - for (MemberSignInRecordDO record : signInRecords) { - LocalDate currentDate = record.getCreateTime().toLocalDate(); - - if (previousDate != null) { - // 检查相邻两个日期是否连续 - if (currentDate.minusDays(1).isEqual(previousDate)) { - consecutiveDays++; - } else { - // 如果日期不连续,停止遍历 - break; - } - } - - previousDate = currentDate; - } - - return consecutiveDays; - } - @Override public PageResult getSignInRecordPage(MemberSignInRecordPageReqVO pageReqVO) { // 根据用户昵称查询出用户ids From c234f5b5f8f41c11b42f4e09357d77b902a82f84 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 11 Dec 2023 16:48:21 +0800 Subject: [PATCH 014/151] =?UTF-8?q?CRM:=20=E5=AE=8C=E5=96=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dal/mysql/business/CrmBusinessMapper.java | 7 ++++-- .../crm/dal/mysql/clue/CrmClueMapper.java | 7 ++++-- .../dal/mysql/contact/CrmContactMapper.java | 7 ++++-- .../dal/mysql/contract/CrmContractMapper.java | 10 +++++--- .../dal/mysql/customer/CrmCustomerMapper.java | 7 ++++-- .../mysql/receivable/CrmReceivableMapper.java | 7 ++++-- .../receivable/CrmReceivablePlanMapper.java | 7 ++++-- .../module/crm/util/CrmQueryWrapperUtils.java | 24 +++++++++++++------ 8 files changed, 54 insertions(+), 22 deletions(-) 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 d34730018..6dfdf8fad 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,8 +38,11 @@ public interface CrmBusinessMapper extends BaseMapperX { default PageResult selectPage(CrmBusinessPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), CrmBusinessDO::getId, - userId, pageReqVO.getSceneType(), Boolean.FALSE); + boolean condition = 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 b78afc4fe..cd558dce4 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,8 +30,11 @@ public interface CrmClueMapper extends BaseMapperX { default PageResult selectPage(CrmCluePageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), CrmClueDO::getId, - userId, pageReqVO.getSceneType(), pageReqVO.getPool()); + boolean condition = 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 2a0a746f5..adc4ced87 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,8 +43,11 @@ public interface CrmContactMapper extends BaseMapperX { default PageResult selectPage(CrmContactPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContactDO::getId, - userId, pageReqVO.getSceneType(), Boolean.FALSE); + boolean condition = 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 5bc9d5cb2..60a5ab785 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 @@ -40,9 +40,13 @@ public interface CrmContractMapper extends BaseMapperX { default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); - // 构建数据权限连表条件 - CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), CrmContractDO::getId, - userId, pageReqVO.getSceneType(), Boolean.FALSE); + // 拼接数据权限的查询条件 + boolean condition = 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()) .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) 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 dece49056..b399ca7df 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,8 +30,11 @@ public interface CrmCustomerMapper extends BaseMapperX { default PageResult selectPage(CrmCustomerPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, - userId, pageReqVO.getSceneType(), pageReqVO.getPool()); + boolean condition = 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 4839492c7..fca4e30e2 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,8 +39,11 @@ public interface CrmReceivableMapper extends BaseMapperX { default PageResult selectPage(CrmReceivablePageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), CrmReceivableDO::getId, - userId, pageReqVO.getSceneType(), Boolean.FALSE); + boolean condition = 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 5c6d40a71..e22c920b9 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,8 +38,11 @@ public interface CrmReceivablePlanMapper extends BaseMapperX selectPage(CrmReceivablePlanPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CrmReceivablePlanDO::getId, - userId, pageReqVO.getSceneType(), Boolean.FALSE); + boolean condition = 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 e3e6be48b..dfdb3ecb9 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 @@ -33,10 +33,11 @@ public class CrmQueryWrapperUtils { * @param userId 用户编号 * @param sceneType 场景类型 * @param pool 公海 + * @return 是否 (是:需要执行查询,否:不需要查询调用方法直接返回空) */ // TODO @puhui999:bizId 直接传递会不会简单点 回复:还是需要 SFunction 因为分页连表时不知道 bizId 是多少 - public static , S> void appendPermissionCondition(T query, Integer bizType, SFunction bizId, - Long userId, Integer sceneType, Boolean pool) { + public static , S> boolean appendPermissionCondition(T query, Integer bizType, SFunction bizId, + Long userId, Integer sceneType, Boolean pool) { // 1. 构建数据权限连表条件 if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 query.innerJoin(CrmPermissionDO.class, on -> @@ -59,10 +60,10 @@ public class CrmQueryWrapperUtils { // 2.3 场景三:下属负责的数据 if (CrmSceneTypeEnum.isSubordinate(sceneType)) { List subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId); - // TODO @puhui999:如果为空,不拼接,就是查询了所有数据呀? - if (CollUtil.isNotEmpty(subordinateUsers)) { - query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId)); + if (CollUtil.isEmpty(subordinateUsers)) { + return false; } + query.in("owner_user_id", convertSet(subordinateUsers, AdminUserRespDTO::getId)); } // 3. 拼接公海的查询条件 @@ -71,6 +72,8 @@ public class CrmQueryWrapperUtils { } else { // 情况二:不是公海 query.isNotNull("owner_user_id"); } + + return true; } /** @@ -95,8 +98,6 @@ public class CrmQueryWrapperUtils { return AdminUserApiHolder.ADMIN_USER_API; } - // TODO @puhui999:需要实现; - /** * 校验用户是否是管理员 * @@ -104,6 +105,15 @@ public class CrmQueryWrapperUtils { * @return 是/否 */ private static boolean validateAdminUser(Long userId) { + // TODO 查询权限配置表用户的角色信息 + //CrmPermissionConfig permissionConfig = crmPermissionConfigService.getPermissionConfigByUserId(userId); + //if (permissionConfig == null) { + // return false; + //} + //// 校验是否为管理员 + //if (permissionConfig.getIsAdmin()){ + // return true; + //} return false; } From 8fa8f2890b3bc7095ccf07bfe5b9866218ece768 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 11 Dec 2023 17:36:09 +0800 Subject: [PATCH 015/151] =?UTF-8?q?CRM:=20=E7=BA=BF=E7=B4=A2=E3=80=81?= =?UTF-8?q?=E8=81=94=E7=B3=BB=E4=BA=BA=E3=80=81=E5=9B=9E=E6=AC=BE=E3=80=81?= =?UTF-8?q?=E5=9B=9E=E6=AC=BE=E8=AE=A1=E5=88=92=E6=96=B0=E5=A2=9E=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=E8=BD=AC=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/business/CrmBusinessTransferReqVO.java | 5 ++- .../admin/clue/CrmClueController.java | 8 +++++ .../admin/clue/vo/CrmClueTransferReqVO.java | 31 +++++++++++++++++++ .../admin/contact/CrmContactController.java | 16 +++++++--- .../admin/contract/CrmContractController.java | 8 ++--- .../customer/vo/CrmCustomerTransferReqVO.java | 5 ++- .../receivable/CrmReceivableController.java | 13 +++++--- .../CrmReceivablePlanController.java | 13 +++++--- .../plan/CrmReceivablePlanTransferReqVO.java | 31 +++++++++++++++++++ .../CrmReceivableTransferReqVO.java | 31 +++++++++++++++++++ .../crm/convert/clue/CrmClueConvert.java | 14 ++++++--- ...actConvert.java => CrmContactConvert.java} | 4 +-- ...ctConvert.java => CrmContractConvert.java} | 4 +-- .../receivable/CrmReceivableConvert.java | 6 ++++ .../receivable/CrmReceivablePlanConvert.java | 6 ++++ .../crm/service/clue/CrmClueService.java | 9 ++++++ .../crm/service/clue/CrmClueServiceImpl.java | 15 +++++++++ .../service/contact/CrmContactService.java | 9 ++++++ .../contact/CrmContactServiceImpl.java | 25 ++++++++++----- .../contract/CrmContractServiceImpl.java | 8 ++--- .../receivable/CrmReceivablePlanService.java | 9 ++++++ .../CrmReceivablePlanServiceImpl.java | 15 +++++++++ .../receivable/CrmReceivableService.java | 9 ++++++ .../receivable/CrmReceivableServiceImpl.java | 26 +++++++++++++--- 24 files changed, 274 insertions(+), 46 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransferReqVO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanTransferReqVO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableTransferReqVO.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/{ContactConvert.java => CrmContactConvert.java} (97%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/{ContractConvert.java => CrmContractConvert.java} (95%) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessTransferReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessTransferReqVO.java index c76c4873f..a76c48cae 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessTransferReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessTransferReqVO.java @@ -2,16 +2,15 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - import jakarta.validation.constraints.NotNull; +import lombok.Data; @Schema(description = "管理后台 - 商机转移 Request VO") @Data public class CrmBusinessTransferReqVO { @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") - @NotNull(message = "联系人编号不能为空") + @NotNull(message = "商机编号不能为空") private Long id; /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index 04f1b4db0..7227b3d12 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -88,4 +88,12 @@ public class CrmClueController { ExcelUtils.write(response, "线索.xls", "数据", CrmClueExcelVO.class, datas); } + @PutMapping("/transfer") + @Operation(summary = "线索转移") + @PreAuthorize("@ss.hasPermission('crm:clue:update')") + public CommonResult transfer(@Valid @RequestBody CrmClueTransferReqVO reqVO) { + clueService.transferClue(reqVO, getLoginUserId()); + return success(true); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransferReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransferReqVO.java new file mode 100644 index 000000000..da71a1ec2 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransferReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; + +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - 线索转移 Request VO") +@Data +public class CrmClueTransferReqVO { + + @Schema(description = "线索编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "线索编号不能为空") + private Long id; + + /** + * 新负责人的用户编号 + */ + @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "新负责人的用户编号不能为空") + private Long newOwnerUserId; + + /** + * 老负责人加入团队后的权限级别。如果 null 说明移除 + * + * 关联 {@link CrmPermissionLevelEnum} + */ + @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Integer oldOwnerPermissionLevel; + +} 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 37db59963..9bb06a1bc 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 @@ -9,7 +9,7 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 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.*; -import cn.iocoder.yudao.module.crm.convert.contact.ContactConvert; +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; @@ -100,7 +100,7 @@ public class CrmContactController { // 3. 直属上级 List parentContactList = contactService.getContactList( Collections.singletonList(contact.getParentId()), getLoginUserId()); - return success(ContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList)); + return success(CrmContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList)); } @GetMapping("/simple-all-list") @@ -110,7 +110,7 @@ public class CrmContactController { CrmContactPageReqVO pageReqVO = new CrmContactPageReqVO(); pageReqVO.setPageSize(PAGE_SIZE_NONE); List list = contactService.getContactPage(pageReqVO, getLoginUserId()).getList(); - return success(ContactConvert.INSTANCE.convertAllList(list)); + return success(CrmContactConvert.INSTANCE.convertAllList(list)); } @GetMapping("/page") @@ -161,7 +161,15 @@ public class CrmContactController { // 3. 直属上级 List parentContactList = contactService.getContactList( convertSet(contactList, CrmContactDO::getParentId), getLoginUserId()); - return ContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList); + return CrmContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList); + } + + @PutMapping("/transfer") + @Operation(summary = "联系人转移") + @PreAuthorize("@ss.hasPermission('crm:contact:update')") + public CommonResult transfer(@Valid @RequestBody CrmContactTransferReqVO reqVO) { + contactService.transferContact(reqVO, getLoginUserId()); + return success(true); } } 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 5086625a7..f0442c4d3 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 @@ -8,7 +8,7 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 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.contract.vo.*; -import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert; +import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; @@ -80,7 +80,7 @@ public class CrmContractController { @PreAuthorize("@ss.hasPermission('crm:contract:query')") public CommonResult getContract(@RequestParam("id") Long id) { CrmContractDO contract = contractService.getContract(id); - return success(ContractConvert.INSTANCE.convert(contract)); + return success(CrmContractConvert.INSTANCE.convert(contract)); } @GetMapping("/page") @@ -108,7 +108,7 @@ public class CrmContractController { PageResult pageResult = contractService.getContractPage(exportReqVO, getLoginUserId()); // 导出 Excel ExcelUtils.write(response, "合同.xls", "数据", CrmContractExcelVO.class, - ContractConvert.INSTANCE.convertList02(pageResult.getList())); + CrmContractConvert.INSTANCE.convertList02(pageResult.getList())); } /** @@ -128,7 +128,7 @@ public class CrmContractController { // 2. 获取创建人、负责人列表 Map userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList, contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); - return ContractConvert.INSTANCE.convertPage(pageResult, userMap, customerList); + return CrmContractConvert.INSTANCE.convertPage(pageResult, userMap, customerList); } @PutMapping("/transfer") 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 c425520a9..9bdc43532 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 @@ -2,16 +2,15 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - import jakarta.validation.constraints.NotNull; +import lombok.Data; @Schema(description = "管理后台 - CRM 客户转移 Request VO") @Data public class CrmCustomerTransferReqVO { @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") - @NotNull(message = "联系人编号不能为空") + @NotNull(message = "客户编号不能为空") private Long id; /** 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 27dc063a5..a353491e7 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 @@ -7,10 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 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.receivable.vo.receivable.CrmReceivableCreateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.*; import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -144,4 +141,12 @@ public class CrmReceivableController { return CrmReceivableConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList); } + @PutMapping("/transfer") + @Operation(summary = "回款转移") + @PreAuthorize("@ss.hasPermission('crm:receivable:update')") + public CommonResult transfer(@Valid @RequestBody CrmReceivableTransferReqVO reqVO) { + receivableService.transferReceivable(reqVO, getLoginUserId()); + return success(true); + } + } 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 a5167313f..9f3c23895 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 @@ -7,10 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; 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.receivable.vo.plan.CrmReceivablePlanCreateReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.*; import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -151,4 +148,12 @@ public class CrmReceivablePlanController { return CrmReceivablePlanConvert.INSTANCE.convertPage(pageResult, userMap, customerList, contractList, receivableList); } + @PutMapping("/transfer") + @Operation(summary = "回款计划转移") + @PreAuthorize("@ss.hasPermission('crm:receivable-plan:update')") + public CommonResult transfer(@Valid @RequestBody CrmReceivablePlanTransferReqVO reqVO) { + receivablePlanService.transferReceivablePlan(reqVO, getLoginUserId()); + return success(true); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanTransferReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanTransferReqVO.java new file mode 100644 index 000000000..09f85e419 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanTransferReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; + +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - CRM 回款计划转移 Request VO") +@Data +public class CrmReceivablePlanTransferReqVO { + + @Schema(description = "回款计划编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "回款计划编号不能为空") + private Long id; + + /** + * 新负责人的用户编号 + */ + @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "新负责人的用户编号不能为空") + private Long newOwnerUserId; + + /** + * 老负责人加入团队后的权限级别。如果 null 说明移除 + * + * 关联 {@link CrmPermissionLevelEnum} + */ + @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Integer oldOwnerPermissionLevel; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableTransferReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableTransferReqVO.java new file mode 100644 index 000000000..f94ce4c1b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableTransferReqVO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; + +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - CRM 回款转移 Request VO") +@Data +public class CrmReceivableTransferReqVO { + + @Schema(description = "回款编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "回款编号不能为空") + private Long id; + + /** + * 新负责人的用户编号 + */ + @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") + @NotNull(message = "新负责人的用户编号不能为空") + private Long newOwnerUserId; + + /** + * 老负责人加入团队后的权限级别。如果 null 说明移除 + * + * 关联 {@link CrmPermissionLevelEnum} + */ + @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Integer oldOwnerPermissionLevel; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java index 76ea428c7..2649065a1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/clue/CrmClueConvert.java @@ -1,13 +1,14 @@ package cn.iocoder.yudao.module.crm.convert.clue; -import java.util.*; - import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.*; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import java.util.List; /** * 线索 Convert @@ -29,4 +30,7 @@ public interface CrmClueConvert { List convertList02(List list); + @Mapping(target = "bizId", source = "reqVO.id") + CrmPermissionTransferReqBO convert(CrmClueTransferReqVO reqVO, Long userId); + } 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/CrmContactConvert.java similarity index 97% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/ContactConvert.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java index b907c3e0c..421e3cd98 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/CrmContactConvert.java @@ -25,9 +25,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd * @author 芋道源码 */ @Mapper -public interface ContactConvert { +public interface CrmContactConvert { - ContactConvert INSTANCE = Mappers.getMapper(ContactConvert.class); + CrmContactConvert INSTANCE = Mappers.getMapper(CrmContactConvert.class); CrmContactDO convert(CrmContactCreateReqVO bean); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java similarity index 95% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java index 195a08301..74b7a4663 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/ContractConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java @@ -22,9 +22,9 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd * @author dhb52 */ @Mapper -public interface ContractConvert { +public interface CrmContractConvert { - ContractConvert INSTANCE = Mappers.getMapper(ContractConvert.class); + CrmContractConvert INSTANCE = Mappers.getMapper(CrmContractConvert.class); CrmContractDO convert(CrmContractCreateReqVO bean); 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 27502103d..e7340fc86 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 @@ -3,12 +3,15 @@ package cn.iocoder.yudao.module.crm.convert.receivable; import cn.iocoder.yudao.framework.common.pojo.PageResult; 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; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; @@ -58,4 +61,7 @@ public interface CrmReceivableConvert { findAndThen(userMap, Long.parseLong(receivable.getCreator()), user -> receivable.setCreatorName(user.getNickname())); } + @Mapping(target = "bizId", source = "reqVO.id") + CrmPermissionTransferReqBO convert(CrmReceivableTransferReqVO reqVO, Long userId); + } 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 a89140d07..70e930880 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 @@ -3,13 +3,16 @@ package cn.iocoder.yudao.module.crm.convert.receivable; import cn.iocoder.yudao.framework.common.pojo.PageResult; 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; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; @@ -63,4 +66,7 @@ public interface CrmReceivablePlanConvert { findAndThen(userMap, Long.parseLong(receivablePlan.getCreator()), user -> receivablePlan.setCreatorName(user.getNickname())); } + @Mapping(target = "bizId", source = "reqVO.id") + CrmPermissionTransferReqBO convert(CrmReceivablePlanTransferReqVO reqVO, Long userId); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java index 52290e106..f5dd48bfa 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.service.clue; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import jakarta.validation.Valid; @@ -64,4 +65,12 @@ public interface CrmClueService { */ PageResult getCluePage(CrmCluePageReqVO pageReqVO, Long userId); + /** + * 线索转移 + * + * @param reqVO 请求 + * @param userId 用户编号 + */ + void transferClue(CrmClueTransferReqVO reqVO, Long userId); + } 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 63e2fcbd2..414a52d17 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 @@ -5,6 +5,7 @@ import cn.hutool.core.collection.ListUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueUpdateReqVO; import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; @@ -101,4 +102,18 @@ public class CrmClueServiceImpl implements CrmClueService { return clueMapper.selectPage(pageReqVO, userId); } + @Override + public void transferClue(CrmClueTransferReqVO reqVO, Long userId) { + // 1 校验线索是否存在 + validateClueExists(reqVO.getId()); + + // 2.1 数据权限转移 + crmPermissionService.transferPermission( + CrmClueConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_LEADS.getType())); + // 2.2 设置新的负责人 + clueMapper.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/contact/CrmContactService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java index 46cbec699..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 @@ -3,6 +3,7 @@ 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.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.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; @@ -79,4 +80,12 @@ public interface CrmContactService { */ PageResult getContactPageByCustomerId(CrmContactPageReqVO pageVO); + /** + * 联系人转移 + * + * @param reqVO 请求 + * @param userId 用户编号 + */ + void transferContact(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 5ee1e2b29..50b1bd4be 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,11 +3,8 @@ 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.module.crm.convert.contact.ContactConvert; +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.enums.common.CrmBizTypeEnum; @@ -56,7 +53,7 @@ public class CrmContactServiceImpl implements CrmContactService { // 1.1 校验 validateRelationDataExists(createReqVO); // 1.2 插入 - CrmContactDO contact = ContactConvert.INSTANCE.convert(createReqVO); + CrmContactDO contact = CrmContactConvert.INSTANCE.convert(createReqVO); contactMapper.insert(contact); // 2. 创建数据权限 @@ -73,7 +70,7 @@ public class CrmContactServiceImpl implements CrmContactService { validateContactExists(updateReqVO.getId()); validateRelationDataExists(updateReqVO); // 2. 更新 - CrmContactDO updateObj = ContactConvert.INSTANCE.convert(updateReqVO); + CrmContactDO updateObj = CrmContactConvert.INSTANCE.convert(updateReqVO); contactMapper.updateById(updateObj); } @@ -139,4 +136,18 @@ public class CrmContactServiceImpl implements CrmContactService { return contactMapper.selectPageByCustomerId(pageVO); } + @Override + public void transferContact(CrmContactTransferReqVO reqVO, Long userId) { + // 1 校验联系人是否存在 + validateContactExists(reqVO.getId()); + + // 2.1 数据权限转移 + crmPermissionService.transferPermission( + CrmContactConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTACT.getType())); + // 2.2 设置新的负责人 + contactMapper.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/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 7f1b20a0e..6f2fc16ab 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 @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractCreat import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractUpdateReqVO; -import cn.iocoder.yudao.module.crm.convert.contract.ContractConvert; +import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; 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; @@ -44,7 +44,7 @@ public class CrmContractServiceImpl implements CrmContractService { @Override public Long createContract(CrmContractCreateReqVO createReqVO, Long userId) { // 插入 - CrmContractDO contract = ContractConvert.INSTANCE.convert(createReqVO); + CrmContractDO contract = CrmContractConvert.INSTANCE.convert(createReqVO); contractMapper.insert(contract); // 创建数据权限 @@ -61,7 +61,7 @@ public class CrmContractServiceImpl implements CrmContractService { // 校验存在 validateContractExists(updateReqVO.getId()); // 更新 - CrmContractDO updateObj = ContractConvert.INSTANCE.convert(updateReqVO); + CrmContractDO updateObj = CrmContractConvert.INSTANCE.convert(updateReqVO); contractMapper.updateById(updateObj); } @@ -118,7 +118,7 @@ public class CrmContractServiceImpl implements CrmContractService { // 2.1 数据权限转移 crmPermissionService.transferPermission( - ContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType())); + CrmContractConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType())); // 2.2 设置负责人 contractMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java index ded059b28..93d05e651 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanService.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.service.receivable; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivablePlanDO; @@ -77,4 +78,12 @@ public interface CrmReceivablePlanService { */ PageResult getReceivablePlanPageByCustomerId(CrmReceivablePlanPageReqVO pageReqVO); + /** + * 回款计划转移 + * + * @param reqVO 请求 + * @param userId 用户编号 + */ + void transferReceivablePlan(CrmReceivablePlanTransferReqVO reqVO, Long userId); + } 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 d2d1b510d..39154dd5d 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 @@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan.CrmReceivablePlanUpdateReqVO; import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivablePlanConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; @@ -135,4 +136,18 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { return receivablePlanMapper.selectPageByCustomerId(pageReqVO); } + @Override + public void transferReceivablePlan(CrmReceivablePlanTransferReqVO reqVO, Long userId) { + // 1 校验回款计划是否存在 + validateReceivablePlanExists(reqVO.getId()); + + // 2.1 数据权限转移 + crmPermissionService.transferPermission( + CrmReceivablePlanConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType())); + // 2.2 设置新的负责人 + receivablePlanMapper.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/receivable/CrmReceivableService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java index 8f7984afe..79be4b338 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.service.receivable; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.receivable.CrmReceivableDO; @@ -77,4 +78,12 @@ public interface CrmReceivableService { */ PageResult getReceivablePageByCustomerId(CrmReceivablePageReqVO pageReqVO); + /** + * 回款转移 + * + * @param reqVO 请求 + * @param userId 用户编号 + */ + void transferReceivable(CrmReceivableTransferReqVO reqVO, Long userId); + } 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 18a289be2..38bf5266e 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 @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableUpdateReqVO; import cn.iocoder.yudao.module.crm.convert.receivable.CrmReceivableConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; @@ -20,6 +21,7 @@ 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.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -48,6 +50,8 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { private CrmCustomerService customerService; @Resource private CrmReceivablePlanService receivablePlanService; + @Resource + private CrmPermissionService crmPermissionService; // TODO @liuhongfeng:创建还款后,是不是什么时候,要更新 plan? @Override @@ -70,22 +74,22 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { // TODO @liuhongfeng:这里的括号要注意排版; private void checkReceivable(CrmReceivableDO receivable) { // TODO @liuhongfeng:这个放在参数校验合适 - if(ObjectUtil.isNull(receivable.getContractId())){ + if (ObjectUtil.isNull(receivable.getContractId())) { throw exception(CONTRACT_NOT_EXISTS); } CrmContractDO contract = contractService.getContract(receivable.getContractId()); - if(ObjectUtil.isNull(contract)){ + if (ObjectUtil.isNull(contract)) { throw exception(CONTRACT_NOT_EXISTS); } CrmCustomerDO customer = customerService.getCustomer(receivable.getCustomerId()); - if(ObjectUtil.isNull(customer)){ + if (ObjectUtil.isNull(customer)) { throw exception(CUSTOMER_NOT_EXISTS); } CrmReceivablePlanDO receivablePlan = receivablePlanService.getReceivablePlan(receivable.getPlanId()); - if(ObjectUtil.isNull(receivablePlan)){ + if (ObjectUtil.isNull(receivablePlan)) { throw exception(RECEIVABLE_PLAN_NOT_EXISTS); } @@ -140,4 +144,18 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { return receivableMapper.selectPageByCustomerId(pageReqVO); } + @Override + public void transferReceivable(CrmReceivableTransferReqVO reqVO, Long userId) { + // 1 校验回款是否存在 + validateReceivableExists(reqVO.getId()); + + // 2.1 数据权限转移 + crmPermissionService.transferPermission( + CrmReceivableConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_RECEIVABLE.getType())); + // 2.2 设置新的负责人 + receivableMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); + + // 3. TODO 记录转移日志 + } + } From e71867683ed8553f480fac59d53c32b624edddb9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 12 Dec 2023 12:11:28 +0800 Subject: [PATCH 016/151] =?UTF-8?q?=F0=9F=93=96=20MALL=EF=BC=9A=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=8E=A5=E5=8F=A3=E6=96=87=E6=A1=A3=E7=9A=84=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/app/comment/vo/AppCommentPageReqVO.java | 6 +++--- .../controller/app/activity/AppActivityController.java | 3 +++ .../controller/app/coupon/AppCouponTemplateController.java | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java index e38753997..854a1c74c 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java @@ -27,12 +27,12 @@ public class AppCommentPageReqVO extends PageParam { */ public static final Integer NEGATIVE_COMMENT = 3; - @Schema(description = "商品SPU编号", example = "29502") - @NotNull(message = "商品SPU编号不能为空") + @Schema(description = "商品 SPU 编号", example = "29502") + @NotNull(message = "商品 SPU 编号不能为空") private Long spuId; @Schema(description = "app 评论页 tab 类型 (0 全部、1 好评、2 中评、3 差评)", example = "0") - @NotNull(message = "商品SPU编号不能为空") + @NotNull(message = "商品 SPU 编号不能为空") private Integer type; } 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 e7ac4ff1a..16233bef3 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 @@ -99,6 +99,9 @@ public class AppActivityController { .setSpuId(item.getSpuId()).setStartTime(item.getStartTime()).setEndTime(item.getEndTime())); }); } + + // TODO 芋艿:满减送活动 + // TODO 芋艿:限时折扣活动 return activityList; } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java index affb17262..f8694f69e 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java @@ -47,7 +47,7 @@ public class AppCouponTemplateController { @Operation(summary = "获得优惠劵模版列表") @Parameters({ @Parameter(name = "spuId", description = "商品 SPU 编号"), // 目前主要给商品详情使用 - @Parameter(name = "useType", description = "使用类型"), + @Parameter(name = "productScope", description = "使用类型"), @Parameter(name = "count", description = "数量", required = true) }) public CommonResult> getCouponTemplateList( From 72cebfca143680718310ea30b06bf216b53dd1a5 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 12 Dec 2023 16:23:48 +0800 Subject: [PATCH 017/151] =?UTF-8?q?CombinationRecordApiImpl=20=E9=87=8D?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E4=B8=80=E4=B8=8B=20recordService=20?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=20combinationRecordService=20=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E5=92=8C=20mzt-biz-log=20=E7=BB=84=E4=BB=B6=E7=9A=84?= =?UTF-8?q?=20bean=20=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/combination/CombinationRecordApiImpl.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java index a9db09ec8..354f5b359 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java @@ -7,11 +7,10 @@ import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivity import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; - import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_RECORD_NOT_EXISTS; @@ -25,21 +24,21 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINA public class CombinationRecordApiImpl implements CombinationRecordApi { @Resource - private CombinationRecordService recordService; + private CombinationRecordService combinationRecordService; @Override public void validateCombinationRecord(Long userId, Long activityId, Long headId, Long skuId, Integer count) { - recordService.validateCombinationRecord(userId, activityId, headId, skuId, count); + combinationRecordService.validateCombinationRecord(userId, activityId, headId, skuId, count); } @Override public CombinationRecordCreateRespDTO createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { - return CombinationActivityConvert.INSTANCE.convert4(recordService.createCombinationRecord(reqDTO)); + return CombinationActivityConvert.INSTANCE.convert4(combinationRecordService.createCombinationRecord(reqDTO)); } @Override public boolean isCombinationRecordSuccess(Long userId, Long orderId) { - CombinationRecordDO record = recordService.getCombinationRecord(userId, orderId); + CombinationRecordDO record = combinationRecordService.getCombinationRecord(userId, orderId); if (record == null) { throw exception(COMBINATION_RECORD_NOT_EXISTS); } @@ -48,7 +47,7 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { @Override public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count) { - return recordService.validateJoinCombination(userId, activityId, headId, skuId, count); + return combinationRecordService.validateJoinCombination(userId, activityId, headId, skuId, count); } } From c5cc818a4901024ee950926ef0d4989404495547 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 12 Dec 2023 22:29:40 +0800 Subject: [PATCH 018/151] =?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=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 | 12 ++ .../module/crm/enums/LogRecordConstants.java | 18 +++ .../admin/customer/CrmCustomerController.http | 11 +- .../admin/customer/CrmCustomerController.java | 6 +- .../customer/CrmCustomerServiceImpl.java | 6 + .../yudao-module-system-api/pom.xml | 7 + .../dal/dataobject/logger/OperateLogV2DO.java | 144 ++++++++++++++++++ .../dal/mysql/logger/OperateLogV2Mapper.java | 31 ++++ .../YudaoOperateLogV2Configuration.java | 53 +++++++ .../system/framework/bizlog/package-info.java | 1 + .../service/AdminUserParseFunction.java | 56 +++++++ .../bizlog/service/ILogRecordServiceImpl.java | 39 +++++ .../service/logger/OperateLogService.java | 7 + .../service/logger/OperateLogServiceImpl.java | 14 +- 14 files changed, 399 insertions(+), 6 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/AdminUserParseFunction.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 00ac14356..da0c4e735 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -62,6 +62,7 @@ 0.1.55 2.9.1 2.7.0 + 3.0.6 3.5.0 4.11.0 @@ -99,6 +100,17 @@ yudao-spring-boot-starter-biz-operatelog ${revision} + + io.github.mouzt + bizlog-sdk + ${bizlog-sdk.version} + + + org.springframework.boot + spring-boot-starter + + + cn.iocoder.boot yudao-spring-boot-starter-biz-dict 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 new file mode 100644 index 000000000..909a0d34a --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.crm.enums; + +/** + * CRM 操作日志枚举 + * + * @author HUIHUI + */ +public interface LogRecordConstants { + + String WHO = "【{getAdminUserById{#userId}}】"; + + //======================= 客户转移操作日志 ======================= + + String TRANSFER_CUSTOMER_LOG_TYPE = "客户转移"; + String TRANSFER_CUSTOMER_LOG_SUCCESS = WHO + "把客户【{{#crmCustomer.name}}】负责人【{getAdminUserById{#crmCustomer.ownerUserId}}】转移给了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; + String TRANSFER_CUSTOMER_LOG_FAIL = ""; + +} 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 f6ecb473b..770171d57 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,6 +1,13 @@ -### 请求 /update -GET {{baseUrl}}/crm/customer/page?pageNo=1&pageSize=10&name="张三" +### 请求 /transfer +PUT {{baseUrl}}/crm/customer/transfer +Content-Type: application/json Authorization: Bearer {{token}} tenant-id: {{adminTenentId}} +{ + "id": 11, + "newOwnerUserId": 127, + "oldOwnerPermissionLevel": 2 +} + 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..e29da139e 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 @@ -17,14 +17,14 @@ 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.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; import org.mapstruct.ap.internal.util.Collections; 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.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import java.io.IOException; import java.util.List; import java.util.Map; 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 fd1009255..402cbcb31 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 @@ -9,12 +9,15 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdat 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.mysql.customer.CrmCustomerMapper; +import cn.iocoder.yudao.module.crm.enums.LogRecordConstants; 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.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import com.mzt.logapi.context.LogRecordContext; +import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -126,11 +129,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(success = LogRecordConstants.TRANSFER_CUSTOMER_LOG_SUCCESS, + type = LogRecordConstants.TRANSFER_CUSTOMER_LOG_TYPE, bizNo = "{{#reqVO.id}}") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { // 1. 校验客户是否存在 validateCustomer(reqVO.getId()); + LogRecordContext.putVariable("crmCustomer", customerMapper.selectById(reqVO.getId())); // 2.1 数据权限转移 crmPermissionService.transferPermission( CrmCustomerConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType())); diff --git a/yudao-module-system/yudao-module-system-api/pom.xml b/yudao-module-system/yudao-module-system-api/pom.xml index 655db05a7..416413cd6 100644 --- a/yudao-module-system/yudao-module-system-api/pom.xml +++ b/yudao-module-system/yudao-module-system-api/pom.xml @@ -22,6 +22,13 @@ yudao-common + + + + io.github.mouzt + bizlog-sdk + + org.springframework.boot 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 new file mode 100644 index 000000000..3473954a7 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/logger/OperateLogV2DO.java @@ -0,0 +1,144 @@ +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 cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; +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; + +/** + * 操作日志表 + * + * @author 芋道源码 + */ +@TableName(value = "system_operate_log_v2", autoResultMap = true) +@KeySequence("system_operate_log_seq_v2") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@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; + + /** + * 日志主键 + */ + @TableId + private Long id; + /** + * 链路追踪编号 + * + * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。 + */ + private String traceId; + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 + */ + private Long userId; + /** + * 用户类型 + * + * 关联 {@link UserTypeEnum} + */ + private Integer userType; + /** + * 操作模块 + */ + private String module; + /** + * 操作名 + */ + private String name; + /** + * 操作分类 + * + * 枚举 {@link OperateTypeEnum} + */ + private Integer type; + /** + * 操作内容,记录整个操作的明细 + * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 + */ + private String content; + /** + * 拓展字段,有些复杂的业务,需要记录一些字段 + * 例如说,记录订单编号,则可以添加 key 为 "orderId",value 为订单编号 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private Map exts; + + /** + * 请求方法名 + */ + private String requestMethod; + /** + * 请求地址 + */ + private String requestUrl; + /** + * 用户 IP + */ + private String userIp; + /** + * 浏览器 UA + */ + private String userAgent; + + /** + * 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 new file mode 100644 index 000000000..e778320a7 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/logger/OperateLogV2Mapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.system.dal.mysql.logger; + +import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; +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.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::getModule, reqVO.getModule()) + .inIfPresent(OperateLogV2DO::getUserId, userIds) + .eqIfPresent(OperateLogV2DO::getType, reqVO.getType()) + .betweenIfPresent(OperateLogV2DO::getStartTime, reqVO.getStartTime()); + if (Boolean.TRUE.equals(reqVO.getSuccess())) { + query.eq(OperateLogV2DO::getResultCode, GlobalErrorCodeConstants.SUCCESS.getCode()); + } else if (Boolean.FALSE.equals(reqVO.getSuccess())) { + query.gt(OperateLogV2DO::getResultCode, GlobalErrorCodeConstants.SUCCESS.getCode()); + } + query.orderByDesc(OperateLogV2DO::getId); // 降序 + return selectPage(reqVO, query); + } + +} 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 new file mode 100644 index 000000000..04fbdefea --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/config/YudaoOperateLogV2Configuration.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.system.framework.bizlog.config; + +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.user.AdminUserApi; +import cn.iocoder.yudao.module.system.framework.bizlog.service.AdminUserParseFunction; +import cn.iocoder.yudao.module.system.framework.bizlog.service.ILogRecordServiceImpl; +import com.mzt.logapi.beans.Operator; +import com.mzt.logapi.service.IOperatorGetService; +import com.mzt.logapi.starter.annotation.EnableLogRecord; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Optional; + + +/** + * 使用 @Configuration 是因为 mzt-biz-log 的配置类是 @Configuration 的 + * + * @author HUIHUI + */ +@Configuration(proxyBeanMethods = false) +@EnableLogRecord(tenant = "${yudao.info.base-package}") +@Slf4j +public class YudaoOperateLogV2Configuration { + + //======================= mzt-biz-log ======================= + + @Bean + public ILogRecordServiceImpl iLogRecordServiceImpl(OperateLogApi operateLogApi) { + log.info("ILogRecordServiceImpl 初始化"); + return new ILogRecordServiceImpl(operateLogApi); + } + + @Bean + public IOperatorGetService operatorGetLoginUserIdService() { + // 获取操作用户编号 + return () -> Optional.of(WebFrameworkUtils.getLoginUserId()) + .map(a -> { + Operator operator = new Operator(); + operator.setOperatorId(a.toString()); + return operator; + }) + .orElseThrow(() -> new IllegalArgumentException("user is null")); + } + + @Bean + public AdminUserParseFunction adminUserParseFunction(AdminUserApi adminUserApi) { + return new AdminUserParseFunction(adminUserApi); + } + +} 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 new file mode 100644 index 000000000..c96f3a0c1 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/package-info.java @@ -0,0 +1 @@ +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/service/AdminUserParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/AdminUserParseFunction.java new file mode 100644 index 000000000..d29e3bac1 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/AdminUserParseFunction.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.system.framework.bizlog.service; + +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; +import com.mzt.logapi.service.IParseFunction; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * 自定义函数-通过用户编号获取用户信息 + * + * @author HUIHUI + */ +@Slf4j +@RequiredArgsConstructor +public class AdminUserParseFunction implements IParseFunction { + + private final AdminUserApi adminUserApi; + + @Override + public boolean executeBefore() { + return true; + } + + @Override + public String functionName() { + return "getAdminUserById"; + } + + @Override + public String apply(Object value) { + if (value == null) { + log.warn("(getAdminUserById) 解析异常参数为 null"); + return ""; + } + if (StrUtil.isEmpty(value.toString())) { + log.warn("(getAdminUserById) 解析异常参数为空"); + return ""; + } + + // 获取用户信息 + AdminUserRespDTO user = adminUserApi.getUser(Long.parseLong(value.toString())); + if (user == null) { + log.warn("(getAdminUserById) 获取用户信息失败,参数为:{}", value); + return ""; + } + // 返回格式 芋道源码(13888888888) + String nickname = user.getNickname(); + if (ObjUtil.isNotEmpty(user.getMobile())) { + return nickname.concat("(").concat(user.getMobile()).concat(")"); + } + return nickname; + } +} 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-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java new file mode 100644 index 000000000..2e2c4b5bd --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.system.framework.bizlog.service; + +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import com.mzt.logapi.beans.LogRecord; +import com.mzt.logapi.service.ILogRecordService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.Collections; +import java.util.List; + +/** + * 操作日志 ILogRecordService 实现类 + * + * 基于 {@link OperateLogApi} 实现,记录操作日志 + * + * @author HUIHUI + */ +@Slf4j +@RequiredArgsConstructor +public class ILogRecordServiceImpl implements ILogRecordService { + + private final OperateLogApi operateLogApi; + + @Override + public void record(LogRecord logRecord) { + log.info("【logRecord】log={}", logRecord); + } + + @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-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 89e562c65..9aada4999 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 @@ -19,6 +19,13 @@ public interface OperateLogService { */ void createOperateLog(OperateLogCreateReqDTO createReqDTO); + /** + * 记录操作日志 V2 + * + * @param createReqDTO 操作日志请求 + */ + void createOperateLogV2(OperateLogCreateReqDTO 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 0181e3081..32f68a3b1 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 @@ -8,14 +8,16 @@ 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.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.user.AdminUserService; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.util.Collection; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @@ -34,6 +36,8 @@ public class OperateLogServiceImpl implements OperateLogService { @Resource private OperateLogMapper operateLogMapper; + @Resource + private OperateLogV2Mapper operateLogV2Mapper; @Resource private AdminUserService userService; @@ -46,6 +50,14 @@ public class OperateLogServiceImpl implements OperateLogService { operateLogMapper.insert(log); } + @Override + public void createOperateLogV2(OperateLogCreateReqDTO createReqDTO) { + OperateLogV2DO log = BeanUtils.toBean(createReqDTO, 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); + } + @Override public PageResult getOperateLogPage(OperateLogPageReqVO pageReqVO) { // 处理基于用户昵称的查询 From 13d6c42a4869cec4608f94cc46d2876797916a8f Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 12 Dec 2023 22:42:50 +0800 Subject: [PATCH 019/151] =?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=E9=9B=86=E6=88=90=20mzt-biz-log=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../customer/CrmCustomerServiceImpl.java | 2 +- .../YudaoOperateLogV2Configuration.java | 39 +------------------ .../AdminUserParseFunction.java | 10 +++-- .../bizlog/service/ILogRecordServiceImpl.java | 8 ++-- 4 files changed, 13 insertions(+), 46 deletions(-) rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/{service => function}/AdminUserParseFunction.java (87%) 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 402cbcb31..141852584 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 @@ -135,7 +135,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { // 1. 校验客户是否存在 validateCustomer(reqVO.getId()); - + // 添加 crmCustomer 到日志上下文 LogRecordContext.putVariable("crmCustomer", customerMapper.selectById(reqVO.getId())); // 2.1 数据权限转移 crmPermissionService.transferPermission( 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 index 04fbdefea..a74dc343f 100644 --- 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 @@ -1,53 +1,16 @@ package cn.iocoder.yudao.module.system.framework.bizlog.config; -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.user.AdminUserApi; -import cn.iocoder.yudao.module.system.framework.bizlog.service.AdminUserParseFunction; -import cn.iocoder.yudao.module.system.framework.bizlog.service.ILogRecordServiceImpl; -import com.mzt.logapi.beans.Operator; -import com.mzt.logapi.service.IOperatorGetService; import com.mzt.logapi.starter.annotation.EnableLogRecord; -import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.Optional; - /** - * 使用 @Configuration 是因为 mzt-biz-log 的配置类是 @Configuration 的 + * * * @author HUIHUI */ @Configuration(proxyBeanMethods = false) @EnableLogRecord(tenant = "${yudao.info.base-package}") -@Slf4j public class YudaoOperateLogV2Configuration { - //======================= mzt-biz-log ======================= - - @Bean - public ILogRecordServiceImpl iLogRecordServiceImpl(OperateLogApi operateLogApi) { - log.info("ILogRecordServiceImpl 初始化"); - return new ILogRecordServiceImpl(operateLogApi); - } - - @Bean - public IOperatorGetService operatorGetLoginUserIdService() { - // 获取操作用户编号 - return () -> Optional.of(WebFrameworkUtils.getLoginUserId()) - .map(a -> { - Operator operator = new Operator(); - operator.setOperatorId(a.toString()); - return operator; - }) - .orElseThrow(() -> new IllegalArgumentException("user is null")); - } - - @Bean - public AdminUserParseFunction adminUserParseFunction(AdminUserApi adminUserApi) { - return new AdminUserParseFunction(adminUserApi); - } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/AdminUserParseFunction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java similarity index 87% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/AdminUserParseFunction.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java index d29e3bac1..5e4d4f254 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/AdminUserParseFunction.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AdminUserParseFunction.java @@ -1,12 +1,13 @@ -package cn.iocoder.yudao.module.system.framework.bizlog.service; +package cn.iocoder.yudao.module.system.framework.bizlog.function; 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; import com.mzt.logapi.service.IParseFunction; -import lombok.RequiredArgsConstructor; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; /** * 自定义函数-通过用户编号获取用户信息 @@ -14,10 +15,11 @@ import lombok.extern.slf4j.Slf4j; * @author HUIHUI */ @Slf4j -@RequiredArgsConstructor +@Component public class AdminUserParseFunction implements IParseFunction { - private final AdminUserApi adminUserApi; + @Resource + private AdminUserApi adminUserApi; @Override public boolean executeBefore() { 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-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java index 2e2c4b5bd..23584d247 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java @@ -3,8 +3,9 @@ package cn.iocoder.yudao.module.system.framework.bizlog.service; import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; import com.mzt.logapi.beans.LogRecord; import com.mzt.logapi.service.ILogRecordService; -import lombok.RequiredArgsConstructor; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; @@ -17,10 +18,11 @@ import java.util.List; * @author HUIHUI */ @Slf4j -@RequiredArgsConstructor +@Service public class ILogRecordServiceImpl implements ILogRecordService { - private final OperateLogApi operateLogApi; + @Resource + private OperateLogApi operateLogApi; @Override public void record(LogRecord logRecord) { From c74881c8f0c9214515cce672ed62a60ade91a968 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 13 Dec 2023 15:18:19 +0800 Subject: [PATCH 020/151] =?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=E9=9B=86=E6=88=90=20mzt-biz-log=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 15 +++- .../admin/customer/CrmCustomerController.http | 5 +- .../admin/customer/CrmCustomerController.java | 1 - .../customer/CrmCustomerServiceImpl.java | 6 +- .../dal/dataobject/logger/OperateLogV2DO.java | 70 +---------------- .../dal/mysql/logger/OperateLogV2Mapper.java | 10 +-- .../YudaoOperateLogV2Configuration.java | 5 +- .../function/AdminUserParseFunction.java | 4 +- .../bizlog/service/ILogRecordServiceImpl.java | 43 +++++++++- .../service/logger/OperateLogServiceImpl.java | 2 - .../logger/bo/OperateLogV2CreateReqBO.java | 78 +++++++++++++++++++ 11 files changed, 145 insertions(+), 94 deletions(-) create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java 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 909a0d34a..a3a9b6db4 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 @@ -7,12 +7,21 @@ package cn.iocoder.yudao.module.crm.enums; */ public interface LogRecordConstants { - String WHO = "【{getAdminUserById{#userId}}】"; + //======================= 客户模块类型 ======================= + // TODO puhui999: 确保模块命名方式为 module + 子模块名称的方式。统一定义模块名称是为了方便查询各自记录的操作日志,列如说:查询客户【张三的操作日志】就可以 module + bizId + String CRM_LEADS = "CRM-线索"; + String CRM_CUSTOMER = "CRM-客户"; + String CRM_CONTACT = "CRM-联系人"; + String CRM_BUSINESS = "CRM-商机"; + String CRM_CONTRACT = "CRM-合同"; + String CRM_PRODUCT = "CRM-产品"; + String CRM_RECEIVABLE = "CRM-回款"; + String CRM_RECEIVABLE_PLAN = "CRM-回款计划"; //======================= 客户转移操作日志 ======================= - String TRANSFER_CUSTOMER_LOG_TYPE = "客户转移"; - String TRANSFER_CUSTOMER_LOG_SUCCESS = WHO + "把客户【{{#crmCustomer.name}}】负责人【{getAdminUserById{#crmCustomer.ownerUserId}}】转移给了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; + String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer == null ? '' : #crmCustomer.name}}】负责人从" + + "【{getAdminUserById{#crmCustomer == null ? '' : #crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; String TRANSFER_CUSTOMER_LOG_FAIL = ""; } 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 770171d57..25e16366c 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 @@ -5,9 +5,8 @@ Authorization: Bearer {{token}} tenant-id: {{adminTenentId}} { - "id": 11, - "newOwnerUserId": 127, - "oldOwnerPermissionLevel": 2 + "id": 10, + "newOwnerUserId": 127 } 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 e29da139e..854c9538a 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 @@ -123,7 +123,6 @@ public class CrmCustomerController { } @PutMapping("/transfer") - @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/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 141852584..52725a675 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 @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerUpdat 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.mysql.customer.CrmCustomerMapper; -import cn.iocoder.yudao.module.crm.enums.LogRecordConstants; 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; @@ -27,6 +26,8 @@ import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 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 java.util.Collections.singletonList; /** @@ -129,8 +130,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) - @LogRecord(success = LogRecordConstants.TRANSFER_CUSTOMER_LOG_SUCCESS, - type = LogRecordConstants.TRANSFER_CUSTOMER_LOG_TYPE, bizNo = "{{#reqVO.id}}") + @LogRecord(success = TRANSFER_CUSTOMER_LOG_SUCCESS, type = CRM_CUSTOMER, subType = "客户转移", bizNo = "{{#reqVO.id}}") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#reqVO.id", level = CrmPermissionLevelEnum.OWNER) public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { // 1. 校验客户是否存在 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 3473954a7..246f45612 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,22 +1,15 @@ 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 cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum; 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 * * @author 芋道源码 */ @@ -26,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; - /** * 日志主键 */ @@ -68,22 +51,14 @@ public class OperateLogV2DO extends BaseDO { */ private String name; /** - * 操作分类 - * - * 枚举 {@link OperateTypeEnum} + * 操作模块业务编号 */ - private Integer type; + private Long bizId; /** * 操作内容,记录整个操作的明细 * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 */ private String content; - /** - * 拓展字段,有些复杂的业务,需要记录一些字段 - * 例如说,记录订单编号,则可以添加 key 为 "orderId",value 为订单编号 - */ - @TableField(typeHandler = JacksonTypeHandler.class) - private Map exts; /** * 请求方法名 @@ -102,43 +77,4 @@ public class OperateLogV2DO extends BaseDO { */ private String userAgent; - /** - * 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 e778320a7..e08686914 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 @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.dal.mysql.logger; -import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; 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; @@ -16,14 +15,7 @@ public interface OperateLogV2Mapper extends BaseMapperX { default PageResult selectPage(OperateLogPageReqVO reqVO, Collection userIds) { LambdaQueryWrapperX query = new LambdaQueryWrapperX() .likeIfPresent(OperateLogV2DO::getModule, reqVO.getModule()) - .inIfPresent(OperateLogV2DO::getUserId, userIds) - .eqIfPresent(OperateLogV2DO::getType, reqVO.getType()) - .betweenIfPresent(OperateLogV2DO::getStartTime, reqVO.getStartTime()); - if (Boolean.TRUE.equals(reqVO.getSuccess())) { - query.eq(OperateLogV2DO::getResultCode, GlobalErrorCodeConstants.SUCCESS.getCode()); - } else if (Boolean.FALSE.equals(reqVO.getSuccess())) { - query.gt(OperateLogV2DO::getResultCode, GlobalErrorCodeConstants.SUCCESS.getCode()); - } + .inIfPresent(OperateLogV2DO::getUserId, userIds); query.orderByDesc(OperateLogV2DO::getId); // 降序 return selectPage(reqVO, query); } 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 index a74dc343f..9e6a9dd85 100644 --- 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 @@ -3,14 +3,13 @@ package cn.iocoder.yudao.module.system.framework.bizlog.config; import com.mzt.logapi.starter.annotation.EnableLogRecord; import org.springframework.context.annotation.Configuration; - /** - * + * mzt-biz-log 配置类 * * @author HUIHUI */ @Configuration(proxyBeanMethods = false) -@EnableLogRecord(tenant = "${yudao.info.base-package}") +@EnableLogRecord(tenant = "") // 貌似用不上 tenant 这玩意给个空好啦 public class YudaoOperateLogV2Configuration { } 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/bizlog/function/AdminUserParseFunction.java index 5e4d4f254..21459be6b 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/bizlog/function/AdminUserParseFunction.java @@ -34,11 +34,11 @@ public class AdminUserParseFunction implements IParseFunction { @Override public String apply(Object value) { if (value == null) { - log.warn("(getAdminUserById) 解析异常参数为 null"); + //log.warn("(getAdminUserById) 解析异常参数为 null"); return ""; } if (StrUtil.isEmpty(value.toString())) { - log.warn("(getAdminUserById) 解析异常参数为空"); + //log.warn("(getAdminUserById) 解析异常参数为空"); return ""; } 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-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java index 23584d247..161d4eca6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java @@ -1,9 +1,14 @@ package cn.iocoder.yudao.module.system.framework.bizlog.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.service.logger.bo.OperateLogV2CreateReqBO; 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 org.springframework.stereotype.Service; @@ -26,7 +31,42 @@ public class ILogRecordServiceImpl implements ILogRecordService { @Override public void record(LogRecord logRecord) { - log.info("【logRecord】log={}", logRecord); + OperateLogV2CreateReqBO reqBO = new OperateLogV2CreateReqBO(); + // 补全通用字段 + reqBO.setTraceId(TracerUtils.getTraceId()); + // 补充用户信息 + fillUserFields(reqBO); + // 补全模块信息 + fillModuleFields(reqBO, logRecord); + // 补全请求信息 + fillRequestFields(reqBO); + // 异步记录日志 + log.info("操作日志 ===> {}", reqBO); + } + + private static void fillUserFields(OperateLogV2CreateReqBO 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());// 操作名称如 转移客户 + reqBO.setBizId(Long.parseLong(logRecord.getBizNo())); // 操作模块业务编号 + reqBO.setContent(logRecord.getAction());// 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 + } + + private static void fillRequestFields(OperateLogV2CreateReqBO 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)); } @Override @@ -38,4 +78,5 @@ public class ILogRecordServiceImpl implements ILogRecordService { public List queryLogByBizNo(String bizNo, String type, String subType) { return Collections.emptyList(); } + } 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 32f68a3b1..840913f62 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 @@ -53,8 +53,6 @@ public class OperateLogServiceImpl implements OperateLogService { @Override public void createOperateLogV2(OperateLogCreateReqDTO createReqDTO) { OperateLogV2DO log = BeanUtils.toBean(createReqDTO, 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/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java new file mode 100644 index 000000000..8c1675879 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.system.service.logger.bo; + +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +/** + * 系统操作日志 Create Req BO + * + * @author HUIHUI + */ +@Data +public class OperateLogV2CreateReqBO { + + /** + * 链路追踪编号 + * + * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。 + */ + private String traceId; + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 + */ + @NotEmpty(message = "用户编号不能为空") + private Long userId; + /** + * 用户类型 + * + * 关联 {@link UserTypeEnum} + */ + @NotEmpty(message = "用户类型不能为空") + private Integer userType; + /** + * 操作模块 + */ + @NotEmpty(message = "操作模块不能为空") + private String module; + /** + * 操作名 + */ + @NotEmpty(message = "操作名不能为空") + private String name; + /** + * 操作模块业务编号 + */ + @NotEmpty(message = "操作模块业务编号不能为空") + private Long bizId; + /** + * 操作内容,记录整个操作的明细 + * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 + */ + @NotEmpty(message = "操作内容不能为空") + private String content; + + /** + * 请求方法名 + */ + @NotEmpty(message = "请求方法名不能为空") + private String requestMethod; + /** + * 请求地址 + */ + @NotEmpty(message = "请求地址不能为空") + private String requestUrl; + /** + * 用户 IP + */ + @NotEmpty(message = "用户 IP 不能为空") + private String userIp; + /** + * 浏览器 UA + */ + @NotEmpty(message = "浏览器 UA 不能为空") + private String userAgent; + +} From 3c74b22933cd84bcf2c62293d76a823af29a100b Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 13 Dec 2023 17:45:43 +0800 Subject: [PATCH 021/151] =?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=E9=9B=86=E6=88=90=20mzt-biz-log=204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 3 +- yudao-module-crm/yudao-module-crm-biz/pom.xml | 4 ++ .../admin/customer/CrmCustomerController.http | 4 ++ .../admin/customer/CrmCustomerController.java | 3 +- .../admin/customer/vo/CrmCustomerBaseVO.java | 29 ++++++++++-- .../function/CrmIndustryParseFunction.java | 46 +++++++++++++++++++ .../function/CrmLevelParseFunction.java | 46 +++++++++++++++++++ .../function/CrmSourceParseFunction.java | 46 +++++++++++++++++++ .../crm/framework/bizlog/package-info.java | 1 + .../customer/CrmCustomerServiceImpl.java | 15 ++++-- .../function/AdminUserParseFunction.java | 5 -- .../bizlog/function/AreaParseFunction.java | 39 ++++++++++++++++ 12 files changed, 224 insertions(+), 17 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java 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 a3a9b6db4..92da847fd 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 @@ -20,8 +20,7 @@ public interface LogRecordConstants { //======================= 客户转移操作日志 ======================= - String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer == null ? '' : #crmCustomer.name}}】负责人从" + - "【{getAdminUserById{#crmCustomer == null ? '' : #crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; + String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; String TRANSFER_CUSTOMER_LOG_FAIL = ""; } diff --git a/yudao-module-crm/yudao-module-crm-biz/pom.xml b/yudao-module-crm/yudao-module-crm-biz/pom.xml index 15bbc932d..9e1a9e152 100644 --- a/yudao-module-crm/yudao-module-crm-biz/pom.xml +++ b/yudao-module-crm/yudao-module-crm-biz/pom.xml @@ -60,6 +60,10 @@ cn.iocoder.boot yudao-spring-boot-starter-excel + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + 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 25e16366c..6a5c6774c 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 @@ -9,4 +9,8 @@ tenant-id: {{adminTenentId}} "newOwnerUserId": 127 } +### 自定义日志记录结果 +### 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=客户转移, bizId=10, content=把客户【张三】的负责人从【芋道源码(15612345678)】变更为了【tttt】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/transfer, userIp=127.0.0.1, userAgent=Apache-HttpClient/4.5.14 (Java/17.0.9)) +### diff 日志 +### | 操作日志 ===> OperateLogV2CreateReqBO(traceId=, userId=1, userType=2, module=CRM-客户, name=更新客户, bizId=11, content=更新了客户【所属行业】从【H 住宿和餐饮业】修改为【D 电力、热力、燃气及水生产和供应业】;【客户等级】从【C (非优先客户)】修改为【A (重点客户)】;【客户来源】从【线上咨询】修改为【预约上门】, requestMethod=PUT, requestUrl=/admin-api/crm/customer/update, userIp=0:0:0:0:0:0:0:1, userAgent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36) 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 854c9538a..6ce57abf1 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 @@ -59,7 +59,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); @@ -123,6 +123,7 @@ public class CrmCustomerController { } @PutMapping("/transfer") + //@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/controller/admin/customer/vo/CrmCustomerBaseVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java index 3d03ba807..8049c344b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerBaseVO.java @@ -3,17 +3,20 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.framework.common.validation.Mobile; import cn.iocoder.yudao.framework.common.validation.Telephone; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum; +import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.Size; +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; +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; /** * 客户 Base VO,提供给添加、修改、详细的子 VO 使用 @@ -23,57 +26,73 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ public class CrmCustomerBaseVO { @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六") + @DiffLogField(name = "客户名称") @NotEmpty(message = "客户名称不能为空") private String name; @Schema(description = "所属行业", example = "1") + @DiffLogField(name = "所属行业", function = "getIndustryById") + @DictFormat(CRM_CUSTOMER_INDUSTRY) private Integer industryId; @Schema(description = "客户等级", example = "2") + @DiffLogField(name = "客户等级", function = "getLevel") @InEnum(CrmCustomerLevelEnum.class) private Integer level; @Schema(description = "客户来源", example = "3") + @DiffLogField(name = "客户来源", function = "getSource") private Integer source; @Schema(description = "手机", example = "18000000000") + @DiffLogField(name = "手机") @Mobile private String mobile; @Schema(description = "电话", example = "18000000000") + @DiffLogField(name = "电话") @Telephone private String telephone; @Schema(description = "网址", example = "https://www.baidu.com") + @DiffLogField(name = "网址") private String website; @Schema(description = "QQ", example = "123456789") + @DiffLogField(name = "QQ") @Size(max = 20, message = "QQ长度不能超过 20 个字符") private String qq; - @Schema(description = "wechat", example = "123456789") + @Schema(description = "微信", example = "123456789") + @DiffLogField(name = "微信") @Size(max = 255, message = "微信长度不能超过 255 个字符") private String wechat; - @Schema(description = "email", example = "123456789@qq.com") + @Schema(description = "邮箱", example = "123456789@qq.com") + @DiffLogField(name = "邮箱") @Email(message = "邮箱格式不正确") @Size(max = 255, message = "邮箱长度不能超过 255 个字符") private String email; @Schema(description = "客户描述", example = "任意文字") + @DiffLogField(name = "客户描述") @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") private String description; @Schema(description = "备注", example = "随便") + @DiffLogField(name = "备注") private String remark; @Schema(description = "地区编号", example = "20158") + @DiffLogField(name = "地区编号", function = "getAreaById") private Integer areaId; @Schema(description = "详细地址", example = "北京市海淀区") + @DiffLogField(name = "详细地址") private String detailAddress; @Schema(description = "下次联系时间") + @DiffLogField(name = "下次联系时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime contactNextTime; 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/bizlog/function/CrmIndustryParseFunction.java new file mode 100644 index 000000000..0a468dfa8 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmIndustryParseFunction.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.crm.framework.bizlog.function; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; +import com.mzt.logapi.service.IParseFunction; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; + +/** + * 自定义函数-通过行业编号获取行业信息 + * + * @author HUIHUI + */ +@Slf4j +@Component +public class CrmIndustryParseFunction implements IParseFunction { + + @Override + public boolean executeBefore() { + return true; // 先转换值后对比 + } + + @Override + public String functionName() { + return "getIndustryById"; + } + + @Override + public String apply(Object value) { + if (value == null) { + return ""; + } + if (StrUtil.isEmpty(value.toString())) { + return ""; + } + + // 获取行业信息 + 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/bizlog/function/CrmLevelParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java new file mode 100644 index 000000000..15af42d5e --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmLevelParseFunction.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.crm.framework.bizlog.function; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; +import com.mzt.logapi.service.IParseFunction; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL; + +/** + * 自定义函数-通过客户等级编号获取客户等级信息 + * + * @author HUIHUI + */ +@Slf4j +@Component +public class CrmLevelParseFunction implements IParseFunction { + + @Override + public boolean executeBefore() { + return true; // 先转换值后对比 + } + + @Override + public String functionName() { + return "getLevel"; + } + + @Override + public String apply(Object value) { + if (value == null) { + return ""; + } + if (StrUtil.isEmpty(value.toString())) { + return ""; + } + + // 获取客户等级信息 + try { + return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_LEVEL, 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/bizlog/function/CrmSourceParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java new file mode 100644 index 000000000..0a630dfe6 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/function/CrmSourceParseFunction.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.crm.framework.bizlog.function; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; +import com.mzt.logapi.service.IParseFunction; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE; + +/** + * 自定义函数-通过客户来源编号获取客户来源信息 + * + * @author HUIHUI + */ +@Slf4j +@Component +public class CrmSourceParseFunction implements IParseFunction { + + @Override + public boolean executeBefore() { + return true; // 先转换值后对比 + } + + @Override + public String functionName() { + return "getSource"; + } + + @Override + public String apply(Object value) { + if (value == null) { + return ""; + } + if (StrUtil.isEmpty(value.toString())) { + return ""; + } + + // 获取客户来源信息 + try { + return DictFrameworkUtils.getDictDataLabel(CRM_CUSTOMER_SOURCE, 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/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 new file mode 100644 index 000000000..b756f540d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/bizlog/package-info.java @@ -0,0 +1 @@ +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/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 52725a675..87a01653b 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,6 +2,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.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; @@ -16,6 +17,7 @@ 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 com.mzt.logapi.context.LogRecordContext; +import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -63,11 +65,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(success = "更新了客户{_DIFF{#updateReqVO}}", type = CRM_CUSTOMER, subType = "更新客户", bizNo = "{{#updateReqVO.id}}") @CrmPermission(bizType = CrmBizTypeEnum.CRM_CUSTOMER, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateCustomer(CrmCustomerUpdateReqVO updateReqVO) { // 校验存在 - validateCustomerExists(updateReqVO.getId()); + 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); @@ -86,10 +91,12 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), id); } - private void validateCustomerExists(Long id) { - if (customerMapper.selectById(id) == null) { + private CrmCustomerDO validateCustomerExists(Long id) { + CrmCustomerDO customerDO = customerMapper.selectById(id); + if (customerDO == null) { throw exception(CUSTOMER_NOT_EXISTS); } + return customerDO; } @Override @@ -135,7 +142,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { public void transferCustomer(CrmCustomerTransferReqVO reqVO, Long userId) { // 1. 校验客户是否存在 validateCustomer(reqVO.getId()); - // 添加 crmCustomer 到日志上下文 + // 添加 crmCustomer 到日志上下文 TODO 日志记录放在 service 里是因为已经过了权限校验查询时不用走两次校验 LogRecordContext.putVariable("crmCustomer", customerMapper.selectById(reqVO.getId())); // 2.1 数据权限转移 crmPermissionService.transferPermission( 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/bizlog/function/AdminUserParseFunction.java index 21459be6b..60fee85be 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/bizlog/function/AdminUserParseFunction.java @@ -21,11 +21,6 @@ public class AdminUserParseFunction implements IParseFunction { @Resource private AdminUserApi adminUserApi; - @Override - public boolean executeBefore() { - return true; - } - @Override public String functionName() { return "getAdminUserById"; 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/bizlog/function/AreaParseFunction.java new file mode 100644 index 000000000..f486a49fa --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/function/AreaParseFunction.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.system.framework.bizlog.function; + +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; + +/** + * 自定义函数-通过区域编号获取区域信息 + * + * @author HUIHUI + */ +@Slf4j +@Component +public class AreaParseFunction implements IParseFunction { + + @Override + public boolean executeBefore() { + return true; // 先转换值后对比 + } + + @Override + public String functionName() { + return "getAreaById"; + } + + @Override + public String apply(Object value) { + if (value == null) { + return ""; + } + if (StrUtil.isEmpty(value.toString())) { + return ""; + } + + return AreaUtils.format(Integer.parseInt(value.toString())); + } +} From daf4651a4f08dce7af17c424ab2a6da3af02cae5 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 14 Dec 2023 18:45:13 +0800 Subject: [PATCH 022/151] =?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=E9=9B=86=E6=88=90=20mzt-biz-log=205?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=97=A5=E5=BF=97=E4=BF=9D=E5=AD=98?= =?UTF-8?q?=E5=92=8C=E6=9F=A5=E8=AF=A2=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/customer/CrmCustomerController.java | 20 ++++ .../yudao-module-system-api/pom.xml | 10 ++ .../system/api/logger/OperateLogApi.java | 13 ++- .../api/logger/dto/OperateLogV2RespDTO.java | 93 +++++++++++++++++++ .../system/api/logger/OperateLogApiImpl.java | 35 ++++++- .../dal/dataobject/logger/OperateLogV2DO.java | 6 +- .../dal/mysql/logger/OperateLogV2Mapper.java | 8 ++ .../bizlog/service/ILogRecordServiceImpl.java | 8 +- .../service/logger/OperateLogService.java | 29 ++++-- .../service/logger/OperateLogServiceImpl.java | 21 +++-- .../logger/bo/OperateLogV2CreateReqBO.java | 5 + 11 files changed, 229 insertions(+), 19 deletions(-) create mode 100644 yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java 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 6ce57abf1..8386e80ed 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 @@ -11,6 +11,8 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.system.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.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; @@ -36,6 +38,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER; @Tag(name = "管理后台 - CRM 客户") @RestController @@ -50,6 +53,8 @@ public class CrmCustomerController { private DeptApi deptApi; @Resource private AdminUserApi adminUserApi; + @Resource + private OperateLogApi operateLogApi; @PostMapping("/create") @Operation(summary = "创建客户") @@ -130,6 +135,21 @@ public class CrmCustomerController { return success(true); } + @GetMapping("/operate-log") + @Operation(summary = "获得客户操作日志") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('crm:customer:query')") + public CommonResult> getOperateLog(@RequestParam("id") Long id) { + // 1. 获取客户 + CrmCustomerDO customer = customerService.getCustomer(id); + if (customer == null) { + return success(null); + } + + // 2. 获取操作日志 + return success(operateLogApi.getOperateLogByModuleAndBizId(CRM_CUSTOMER, id)); + } + // TODO @Joey:单独建一个属于自己业务的 ReqVO;因为前端如果模拟请求,是不是可以更新其它字段了; @PutMapping("/lock") @Operation(summary = "锁定/解锁客户") diff --git a/yudao-module-system/yudao-module-system-api/pom.xml b/yudao-module-system/yudao-module-system-api/pom.xml index 416413cd6..3c91bd974 100644 --- a/yudao-module-system/yudao-module-system-api/pom.xml +++ b/yudao-module-system/yudao-module-system-api/pom.xml @@ -29,6 +29,16 @@ bizlog-sdk + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-core + + org.springframework.boot 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 6e28c7d78..ad42c87f7 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,9 +1,11 @@ package cn.iocoder.yudao.module.system.api.logger; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; - +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import jakarta.validation.Valid; +import java.util.List; + /** * 操作日志 API 接口 * @@ -18,4 +20,13 @@ public interface OperateLogApi { */ void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO); + /** + * 获取指定模块的指定数据的操作日志 + * + * @param module 操作模块 + * @param bizId 操作模块编号 + * @return 操作日志 + */ + List getOperateLogByModuleAndBizId(String module, Long bizId); + } 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 new file mode 100644 index 000000000..9a918abe3 --- /dev/null +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/dto/OperateLogV2RespDTO.java @@ -0,0 +1,93 @@ +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 + * + * @author HUIHUI + */ +@Data +public class OperateLogV2RespDTO { + + /** + * 链路追踪编号 + * + * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。 + */ + private String traceId; + /** + * 用户编号 + * + * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 + */ + private Long userId; + /** + * 用户类型 + * + * 关联 {@link UserTypeEnum} + */ + private Integer userType; + /** + * 操作模块 + */ + private String module; + /** + * 操作名 + */ + private String name; + /** + * 操作模块业务编号 + */ + private Long bizId; + /** + * 操作内容,记录整个操作的明细 + * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 + */ + private String content; + /** + * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) + * 例如说,记录订单编号,{ orderId: "1"} + */ + private String extra; + + /** + * 请求方法名 + */ + private String requestMethod; + /** + * 请求地址 + */ + private String requestUrl; + /** + * 用户 IP + */ + private String userIp; + /** + * 浏览器 UA + */ + private String userAgent; + + /** + * 创建时间 + */ + // TODO puhui999: 木得效果怎么肥事 + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + private LocalDateTime createTime; + /** + * 创建者,关联 AdminUserDO#getId + */ + private String creator; + /** + * 创建者名称 + */ + private String creatorName; + +} 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 20aa2635d..d748bcc23 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,11 +1,23 @@ package cn.iocoder.yudao.module.system.api.logger; +import cn.hutool.core.collection.CollUtil; +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.OperateLogV2RespDTO; +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.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; +import java.util.Collections; +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; /** * 操作日志 API 实现类 @@ -18,10 +30,31 @@ public class OperateLogApiImpl implements OperateLogApi { @Resource private OperateLogService operateLogService; + @Resource + private AdminUserService adminUserService; @Override public void createOperateLog(OperateLogCreateReqDTO createReqDTO) { operateLogService.createOperateLog(createReqDTO); } + @Override + public List getOperateLogByModuleAndBizId(String module, Long bizId) { + List logList = operateLogService.getOperateLogByModuleAndBizId(module, bizId); + if (CollUtil.isEmpty(logList)) { + return Collections.emptyList(); + } + + // 获取用户 + List userList = adminUserService.getUserList(convertSet(logList, item -> Long.parseLong(item.getCreator()))); + 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()); + }); + return bean; + }); + } + } 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 246f45612..1b7b1eaab 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 @@ -59,7 +59,11 @@ public class OperateLogV2DO extends BaseDO { * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 */ private String content; - + /** + * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) + * 例如说,记录订单编号,{ orderId: "1"} + */ + private String extra; /** * 请求方法名 */ 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 e08686914..362f0d2c4 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 @@ -8,6 +8,7 @@ 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 { @@ -20,4 +21,11 @@ public interface OperateLogV2Mapper extends BaseMapperX { return selectPage(reqVO, query); } + default List selectListByModuleAndBizId(String module, Long bizId) { + return selectList(new LambdaQueryWrapperX() + .eq(OperateLogV2DO::getModule, module) + .eq(OperateLogV2DO::getBizId, bizId) + .orderByDesc(OperateLogV2DO::getCreateTime)); + } + } 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-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java index 161d4eca6..a81280f99 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.system.framework.bizlog.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.service.logger.OperateLogService; import cn.iocoder.yudao.module.system.service.logger.bo.OperateLogV2CreateReqBO; import com.mzt.logapi.beans.LogRecord; import com.mzt.logapi.service.ILogRecordService; @@ -18,7 +18,7 @@ import java.util.List; /** * 操作日志 ILogRecordService 实现类 * - * 基于 {@link OperateLogApi} 实现,记录操作日志 + * 基于 {@link OperateLogService} 实现,记录操作日志 * * @author HUIHUI */ @@ -27,7 +27,7 @@ import java.util.List; public class ILogRecordServiceImpl implements ILogRecordService { @Resource - private OperateLogApi operateLogApi; + private OperateLogService operateLogService; @Override public void record(LogRecord logRecord) { @@ -41,6 +41,7 @@ public class ILogRecordServiceImpl implements ILogRecordService { // 补全请求信息 fillRequestFields(reqBO); // 异步记录日志 + operateLogService.createOperateLogV2(reqBO); log.info("操作日志 ===> {}", reqBO); } @@ -54,6 +55,7 @@ public class ILogRecordServiceImpl implements ILogRecordService { reqBO.setName(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) { 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 9aada4999..30a1a1a7c 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 @@ -4,6 +4,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; 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 接口 @@ -19,13 +23,6 @@ public interface OperateLogService { */ void createOperateLog(OperateLogCreateReqDTO createReqDTO); - /** - * 记录操作日志 V2 - * - * @param createReqDTO 操作日志请求 - */ - void createOperateLogV2(OperateLogCreateReqDTO createReqDTO); - /** * 获得操作日志分页列表 * @@ -34,4 +31,22 @@ public interface OperateLogService { */ PageResult getOperateLogPage(OperateLogPageReqVO pageReqVO); + //======================= LOG V2 ======================= + + /** + * 记录操作日志 V2 + * + * @param createReqBO 创建请求 + */ + void createOperateLogV2(OperateLogV2CreateReqBO createReqBO); + + /** + * 获取指定模块的指定数据的操作日志 + * + * @param module 操作模块 + * @param bizId 操作模块编号 + * @return 操作日志 + */ + List getOperateLogByModuleAndBizId(String module, Long bizId); + } 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 840913f62..894cc48c8 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 @@ -12,6 +12,7 @@ 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; @@ -19,6 +20,7 @@ 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; @@ -50,12 +52,6 @@ public class OperateLogServiceImpl implements OperateLogService { operateLogMapper.insert(log); } - @Override - public void createOperateLogV2(OperateLogCreateReqDTO createReqDTO) { - OperateLogV2DO log = BeanUtils.toBean(createReqDTO, OperateLogV2DO.class); - operateLogV2Mapper.insert(log); - } - @Override public PageResult getOperateLogPage(OperateLogPageReqVO pageReqVO) { // 处理基于用户昵称的查询 @@ -70,4 +66,17 @@ public class OperateLogServiceImpl implements OperateLogService { return operateLogMapper.selectPage(pageReqVO, userIds); } + //======================= LOG V2 ======================= + + @Override + public void createOperateLogV2(OperateLogV2CreateReqBO createReqBO) { + OperateLogV2DO log = BeanUtils.toBean(createReqBO, OperateLogV2DO.class); + operateLogV2Mapper.insert(log); + } + + @Override + public List getOperateLogByModuleAndBizId(String module, Long bizId) { + return operateLogV2Mapper.selectListByModuleAndBizId(module, bizId); + } + } 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-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java index 8c1675879..d6c44604c 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-biz/src/main/java/cn/iocoder/yudao/module/system/service/logger/bo/OperateLogV2CreateReqBO.java @@ -53,6 +53,11 @@ public class OperateLogV2CreateReqBO { */ @NotEmpty(message = "操作内容不能为空") private String content; + /** + * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) + * 例如说,记录订单编号,{ orderId: "1"} + */ + private String extra; /** * 请求方法名 From c1429dd3a0d395f79365202a054a262889a43098 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 14 Dec 2023 20:07:35 +0800 Subject: [PATCH 023/151] =?UTF-8?q?=E2=9C=A8=20=E5=A2=9E=E5=8A=A0=E5=94=AE?= =?UTF-8?q?=E5=90=8E=E6=97=A5=E5=BF=97=E5=88=97=E8=A1=A8=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aftersale/vo/log/AfterSaleLogRespVO.java | 5 --- .../app/aftersale/AppAfterSaleController.java | 3 ++ .../aftersale/AppAfterSaleLogController.java | 42 +++++++++++++++++++ .../app/aftersale/vo/AppAfterSaleRespVO.java | 6 +++ .../vo/log/AppAfterSaleLogRespVO.java | 22 ++++++++++ .../order/vo/AppTradeOrderDetailRespVO.java | 10 +++++ 6 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleLogController.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/log/AppAfterSaleLogRespVO.java diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/AfterSaleLogRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/AfterSaleLogRespVO.java index c2ab47589..ea06bca71 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/AfterSaleLogRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/vo/log/AfterSaleLogRespVO.java @@ -14,26 +14,21 @@ public class AfterSaleLogRespVO { private Long id; @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22634") - @NotNull(message = "用户编号不能为空") private Long userId; @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - @NotNull(message = "用户类型不能为空") private Integer userType; @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3023") - @NotNull(message = "售后编号不能为空") private Long afterSaleId; @Schema(description = "售后状态(之前)", example = "2") private Integer beforeStatus; @Schema(description = "售后状态(之后)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "售后状态(之后)不能为空") private Integer afterStatus; @Schema(description = "操作明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "维权完成,退款金额:¥37776.00") - @NotNull(message = "操作明细不能为空") private String content; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 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 d0677d528..997d3427d 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 @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.app.aftersale; 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.module.trade.controller.admin.aftersale.vo.log.AfterSaleLogRespVO; import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleDeliveryReqVO; import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppAfterSaleRespVO; @@ -17,6 +18,8 @@ import org.springframework.web.bind.annotation.*; import jakarta.annotation.Resource; +import java.util.List; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleLogController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleLogController.java new file mode 100644 index 000000000..667733442 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleLogController.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.trade.controller.app.aftersale; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.log.AppAfterSaleLogRespVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.AfterSaleLogDO; +import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleLogService; +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 lombok.extern.slf4j.Slf4j; +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 java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 售后日志") +@RestController +@RequestMapping("/trade/after-sale-log") +@Validated +@Slf4j +public class AppAfterSaleLogController { + + @Resource + private AfterSaleLogService afterSaleLogService; + + @GetMapping("/list") + @Operation(summary = "获得售后日志列表") + @Parameter(name = "afterSaleId", description = "售后编号", required = true, example = "1") + public CommonResult> getAfterSaleLogList( + @RequestParam("afterSaleId") Long afterSaleId) { + List logs = afterSaleLogService.getAfterSaleLogList(afterSaleId); + return success(BeanUtils.toBean(logs, AppAfterSaleLogRespVO.class)); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleRespVO.java index 55ae73a03..1da0595c7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/AppAfterSaleRespVO.java @@ -35,6 +35,12 @@ public class AppAfterSaleRespVO { @Schema(description = "补充凭证图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private List applyPicUrls; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime updateTime; + // ========== 交易订单相关 ========== @Schema(description = "交易订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/log/AppAfterSaleLogRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/log/AppAfterSaleLogRespVO.java new file mode 100644 index 000000000..94af3136c --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/vo/log/AppAfterSaleLogRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.log; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - App 交易售后日志 Response VO") +@Data +public class AppAfterSaleLogRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20669") + private Long id; + + @Schema(description = "操作明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "维权完成,退款金额:¥37776.00") + private String content; + + @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/controller/app/order/vo/AppTradeOrderDetailRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java index 3033cf022..f00b45695 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderDetailRespVO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.trade.controller.app.order.vo; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -20,6 +21,9 @@ public class AppTradeOrderDetailRespVO { @Schema(description = "订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1146347329394184195") private String no; + @Schema(description = "订单类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") + private Integer type; + @Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; @@ -118,6 +122,12 @@ public class AppTradeOrderDetailRespVO { // ========== 售后基本信息 ========== + @Schema(description = "售后状态", example = "0") + private Integer refundStatus; + + @Schema(description = "退款金额,单位:分", example = "100") + private Integer refundPrice; + // ========== 营销基本信息 ========== @Schema(description = "优惠劵编号", example = "1024") From 8913572e519f7862d2786285042f6a3523e67609 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 14 Dec 2023 22:00:04 +0800 Subject: [PATCH 024/151] =?UTF-8?q?=F0=9F=90=9B=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E8=AE=A2=E5=8D=95=E8=AF=84=E8=AE=BA=E7=9A=84?= =?UTF-8?q?=20scores=E3=80=81replyStatus=20=E9=BB=98=E8=AE=A4=E5=80=BC?= =?UTF-8?q?=E6=9C=AA=E5=A1=AB=E5=86=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/ProductCommentConvert.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java index 944eb2bc2..fb6ac4f85 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java @@ -84,26 +84,27 @@ public interface ProductCommentConvert { return divide.intValue(); } - ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO); - @Mapping(target = "scores", expression = "java(convertScores(createReqDTO.getDescriptionScores(), createReqDTO.getBenefitScores()))") - default ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO, ProductSpuDO spuDO, ProductSkuDO skuDO, MemberUserRespDTO user) { - ProductCommentDO commentDO = convert(createReqDTO); + ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO); + + default ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO, + ProductSpuDO spu, ProductSkuDO sku, MemberUserRespDTO user) { + ProductCommentDO comment = convert(createReqDTO).setReplyStatus(false); if (user != null) { - commentDO.setUserId(user.getId()); - commentDO.setUserNickname(user.getNickname()); - commentDO.setUserAvatar(user.getAvatar()); + comment.setUserId(user.getId()); + comment.setUserNickname(user.getNickname()); + comment.setUserAvatar(user.getAvatar()); } - if (spuDO != null) { - commentDO.setSpuId(spuDO.getId()); - commentDO.setSpuName(spuDO.getName()); + if (spu != null) { + comment.setSpuId(spu.getId()); + comment.setSpuName(spu.getName()); } - if (skuDO != null) { - commentDO.setSkuPicUrl(skuDO.getPicUrl()); - commentDO.setSkuProperties(skuDO.getProperties()); + if (sku != null) { + comment.setSkuPicUrl(sku.getPicUrl()); + comment.setSkuProperties(sku.getProperties()); } - return commentDO; + return comment; } @Mapping(target = "visible", constant = "true") From 07e610b3f7b4dce773532818d91b1554bdea8073 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 15 Dec 2023 00:02:40 +0800 Subject: [PATCH 025/151] =?UTF-8?q?=F0=9F=94=A5=20MALL=EF=BC=9A=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E5=95=86=E5=93=81=E6=94=B6=E8=97=8F=E7=9A=84=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E6=93=8D=E4=BD=9C=E6=8E=A5=E5=8F=A3=EF=BC=8C=E7=94=B1?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E8=87=AA=E8=BA=AB=20for=20=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/favorite/AppFavoriteController.java | 17 ----------------- .../app/order/AppTradeOrderController.java | 2 +- .../order/TradeOrderQueryServiceImpl.java | 4 ++-- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java index 9f6b47883..b81c4e9d3 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java @@ -42,14 +42,6 @@ public class AppFavoriteController { return success(productFavoriteService.createFavorite(getLoginUserId(), reqVO.getSpuId())); } - @PostMapping(value = "/create-list") - @Operation(summary = "添加多个商品收藏") - @PreAuthenticated - public CommonResult createFavoriteList(@RequestBody @Valid AppFavoriteBatchReqVO reqVO) { - // todo @jason:待实现;如果有已经收藏的,不用报错,忽略即可; - return success(true); - } - @DeleteMapping(value = "/delete") @Operation(summary = "取消单个商品收藏") @PreAuthenticated @@ -58,15 +50,6 @@ public class AppFavoriteController { return success(Boolean.TRUE); } - @DeleteMapping(value = "/delete-list") - @Operation(summary = "取消多个商品收藏") - @PreAuthenticated - public CommonResult deleteFavoriteList(@RequestBody @Valid AppFavoriteBatchReqVO reqVO) { - // todo @jason:待实现 -// productFavoriteService.deleteFavorite(getLoginUserId(), reqVO.getSpuId()); - return success(Boolean.TRUE); - } - @GetMapping(value = "/page") @Operation(summary = "获得商品收藏分页") @PreAuthenticated 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 ac03d74a1..545f0adde 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 @@ -97,7 +97,7 @@ public class AppTradeOrderController { @GetMapping("/get-express-track-list") @Operation(summary = "获得交易订单的物流轨迹") @Parameter(name = "id", description = "交易订单编号") - public CommonResult> getOrderExpressTrackList(@RequestParam("id") Long id) { + public CommonResult> getOrderExpressTrackList(@RequestParam("id") Long id) { return success(TradeOrderConvert.INSTANCE.convertList02( tradeOrderQueryService.getExpressTrackList(id, getLoginUserId()))); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java index 3d15220bb..f617521c6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java @@ -206,7 +206,8 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { /** * 查询物流轨迹 - * 加个 spring 缓存,30 分钟;主要考虑及时性要求不高,但是每次调用需要钱;TODO @艿艿:这个时间不会搞了。。。交给你了哈哈哈 + * + * 缓存的目的:考虑及时性要求不高,但是每次调用需要钱 * * @param code 快递公司编码 * @param logisticsNo 发货快递单号 @@ -216,7 +217,6 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { @Cacheable(cacheNames = RedisKeyConstants.EXPRESS_TRACK, key = "#code + '-' + #logisticsNo + '-' + #receiverMobile", condition = "#result != null") public List getExpressTrackList(String code, String logisticsNo, String receiverMobile) { - // 查询物流轨迹 return expressClientFactory.getDefaultExpressClient().getExpressTrackList( new ExpressTrackQueryReqDTO().setExpressCode(code).setLogisticsNo(logisticsNo) .setPhone(receiverMobile)); From e1bb54646051f8dc454d995ef2be996e991fc5a3 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 16 Dec 2023 18:32:54 +0800 Subject: [PATCH 026/151] =?UTF-8?q?=E2=9C=A8=20MALL=EF=BC=9A1=EF=BC=89?= =?UTF-8?q?=E4=BC=98=E6=83=A0=E5=8A=B5=E5=A2=9E=E5=8A=A0=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E8=8C=83=E5=9B=B4=EF=BC=9B2=EF=BC=89?= =?UTF-8?q?=E5=95=86=E5=93=81=E5=88=86=E7=B1=BB=E5=A2=9E=E5=8A=A0=20id=20?= =?UTF-8?q?=E6=89=B9=E9=87=8F=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/category/AppCategoryController.java | 21 ++++++++++++++++++- .../app/spu/AppProductSpuController.java | 4 +--- .../app/spu/vo/AppProductSpuPageReqVO.java | 1 + .../category/ProductCategoryConvert.java | 1 - .../mysql/category/ProductCategoryMapper.java | 7 +++++++ .../dal/mysql/spu/ProductSpuMapper.java | 3 +++ .../category/ProductCategoryService.java | 9 ++++++++ .../category/ProductCategoryServiceImpl.java | 5 +++++ .../app/coupon/AppCouponController.java | 15 +++++++++++-- .../coupon/AppCouponTemplateController.java | 15 +++++++++++++ .../app/coupon/vo/coupon/AppCouponRespVO.java | 10 +++++++-- .../vo/template/AppCouponTemplateRespVO.java | 13 ++++++++++-- .../convert/coupon/CouponConvert.java | 4 ---- .../service/coupon/CouponService.java | 9 ++++++++ .../service/coupon/CouponServiceImpl.java | 5 +++++ 15 files changed, 107 insertions(+), 15 deletions(-) diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java index 4c13154b5..c4999a867 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/category/AppCategoryController.java @@ -1,18 +1,25 @@ package cn.iocoder.yudao.module.product.controller.app.category; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.product.controller.app.category.vo.AppCategoryRespVO; import cn.iocoder.yudao.module.product.convert.category.ProductCategoryConvert; import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; 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.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.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -32,7 +39,19 @@ public class AppCategoryController { public CommonResult> getProductCategoryList() { List list = categoryService.getEnableCategoryList(); list.sort(Comparator.comparing(ProductCategoryDO::getSort)); - return success(ProductCategoryConvert.INSTANCE.convertList03(list)); + return success(BeanUtils.toBean(list, AppCategoryRespVO.class)); + } + + @GetMapping("/list-by-ids") + @Operation(summary = "获得商品分类列表,指定编号") + @Parameter(name = "ids", description = "商品分类编号数组", required = true) + public CommonResult> getProductCategoryList(@RequestParam("ids") List ids) { + if (CollUtil.isEmpty(ids)) { + return success(Collections.emptyList()); + } + List list = categoryService.getEnableCategoryList(ids); + list.sort(Comparator.comparing(ProductCategoryDO::getSort)); + return success(BeanUtils.toBean(list, AppCategoryRespVO.class)); } } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java index d0784bc77..87655523b 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java @@ -78,9 +78,7 @@ public class AppProductSpuController { @GetMapping("/list-by-ids") @Operation(summary = "获得商品 SPU 列表") - @Parameters({ - @Parameter(name = "ids", description = "编号列表", required = true) - }) + @Parameter(name = "ids", description = "编号列表", required = true) public CommonResult> getSpuList(@RequestParam("ids") Set ids) { List list = productSpuService.getSpuList(ids); if (CollUtil.isEmpty(list)) { diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java index cda799d46..a6b53e4de 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuPageReqVO.java @@ -18,6 +18,7 @@ public class AppProductSpuPageReqVO extends PageParam { public static final String SORT_FIELD_PRICE = "price"; public static final String SORT_FIELD_SALES_COUNT = "salesCount"; + public static final String SORT_FIELD_CREATE_TIME = "createTime"; public static final String RECOMMEND_TYPE_HOT = "hot"; public static final String RECOMMEND_TYPE_BENEFIT = "benefit"; diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/ProductCategoryConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/ProductCategoryConvert.java index ae01ca9d5..4c4ff3fb3 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/ProductCategoryConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/category/ProductCategoryConvert.java @@ -28,5 +28,4 @@ public interface ProductCategoryConvert { List convertList(List list); - List convertList03(List list); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java index fbb88f592..50d47104c 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/category/ProductCategoryMapper.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCateg import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; import org.apache.ibatis.annotations.Mapper; +import java.util.Collection; import java.util.List; /** @@ -32,4 +33,10 @@ public interface ProductCategoryMapper extends BaseMapperX { return selectList(ProductCategoryDO::getStatus, status); } + default List selectListByIdAndStatus(Collection ids, Integer status) { + return selectList(new LambdaQueryWrapperX() + .in(ProductCategoryDO::getId, ids) + .eq(ProductCategoryDO::getStatus, status)); + } + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java index 861ca475e..aab2844fa 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java @@ -84,6 +84,9 @@ public interface ProductSpuMapper extends BaseMapperX { } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_PRICE)) { query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getPrice) .orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId); + } else if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_CREATE_TIME)) { + query.orderBy(true, pageReqVO.getSortAsc(), ProductSpuDO::getCreateTime) + .orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId); } else { query.orderByDesc(ProductSpuDO::getSort).orderByDesc(ProductSpuDO::getId); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java index 1079bfabb..3a064f466 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryService.java @@ -76,6 +76,14 @@ public interface ProductCategoryService { */ List getEnableCategoryList(); + /** + * 获得开启状态的商品分类列表,指定编号 + * + * @param ids 商品分类编号数组 + * @return 商品分类列表 + */ + List getEnableCategoryList(List ids); + /** * 校验商品分类是否有效。如下情况,视为无效: * 1. 商品分类编号不存在 @@ -84,4 +92,5 @@ public interface ProductCategoryService { * @param ids 商品分类编号数组 */ void validateCategoryList(Collection ids); + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java index 93c39374e..ae69e87b5 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java @@ -170,4 +170,9 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { return productCategoryMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus()); } + @Override + public List getEnableCategoryList(List ids) { + return productCategoryMapper.selectListByIdAndStatus(ids, CommonStatusEnum.ENABLE.getStatus()); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java index d0199bdf2..ed19d9141 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon; 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.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.*; import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; @@ -59,7 +60,8 @@ public class AppCouponController { @Operation(summary = "获得匹配指定商品的优惠劵列表", description = "用于下单页,展示优惠劵列表") public CommonResult> getMatchCouponList(AppCouponMatchReqVO matchReqVO) { // todo: 优化:优惠金额倒序 - return success(CouponConvert.INSTANCE.convertList(couponService.getMatchCouponList(getLoginUserId(), matchReqVO))); + List list = couponService.getMatchCouponList(getLoginUserId(), matchReqVO); + return success(BeanUtils.toBean(list, AppCouponMatchRespVO.class)); } @GetMapping("/page") @@ -68,7 +70,16 @@ public class AppCouponController { public CommonResult> getCouponPage(AppCouponPageReqVO pageReqVO) { PageResult pageResult = couponService.getCouponPage( CouponConvert.INSTANCE.convert(pageReqVO, Collections.singleton(getLoginUserId()))); - return success(CouponConvert.INSTANCE.convertAppPage(pageResult)); + return success(BeanUtils.toBean(pageResult, AppCouponRespVO.class)); + } + + @GetMapping("/get") + @Operation(summary = "获得优惠劵") + @Parameter(name = "id", description = "优惠劵编号", required = true, example = "1024") + @PreAuthenticated + public CommonResult getCoupon(@RequestParam("id") Long id) { + CouponDO coupon = couponService.getCoupon(getLoginUserId(), id); + return success(BeanUtils.toBean(coupon, AppCouponRespVO.class)); } @GetMapping(value = "/get-unused-count") diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java index f8694f69e..27ac4c14a 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon; 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.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; @@ -43,6 +44,20 @@ public class AppCouponTemplateController { @Resource private ProductSpuApi productSpuApi; + @GetMapping("/get") + @Operation(summary = "获得优惠劵模版") + @Parameter(name = "id", description = "优惠券模板编号", required = true, example = "1024") + public CommonResult getCouponTemplate(Long id) { + CouponTemplateDO template = couponTemplateService.getCouponTemplate(id); + if (template == null) { + return success(null); + } + // 处理是否可领取 + Map canCanTakeMap = couponService.getUserCanCanTakeMap(getLoginUserId(), List.of(template)); + return success(BeanUtils.toBean(template, AppCouponTemplateRespVO.class) + .setCanTake(canCanTakeMap.get(template.getId()))); + } + @GetMapping("/list") @Operation(summary = "获得优惠劵模版列表") @Parameters({ diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java index b9107d9f2..c0949f671 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java @@ -5,6 +5,7 @@ import lombok.Data; import jakarta.validation.constraints.Min; import java.time.LocalDateTime; +import java.util.List; @Schema(description = "用户 App - 优惠劵 Response VO") @Data @@ -19,10 +20,15 @@ public class AppCouponRespVO { @Schema(description = "优惠劵状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") // 参见 CouponStatusEnum 枚举 private Integer status; - @Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") - // 单位:分;0 - 不限制 + @Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") // 单位:分;0 - 不限制 private Integer usePrice; + @Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer productScope; + + @Schema(description = "商品范围编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private List productScopeValues; + @Schema(description = "固定日期 - 生效开始时间") private LocalDateTime validStartTime; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java index eb4549ea7..a2967ac32 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java @@ -1,10 +1,14 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.template; +import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; +import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; +import com.baomidou.mybatisplus.annotation.TableField; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import jakarta.validation.constraints.Min; import java.time.LocalDateTime; +import java.util.List; @Schema(description = "用户 App - 优惠劵模板 Response VO") @Data @@ -19,10 +23,15 @@ public class AppCouponTemplateRespVO { @Schema(description = "每人限领个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "66") // -1 - 则表示不限制 private Integer takeLimitCount; - @Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") - // 单位:分;0 - 不限制 + @Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") // 单位:分;0 - 不限制 private Integer usePrice; + @Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer productScope; + + @Schema(description = "商品范围编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private List productScopeValues; + @Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer validityType; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java index f036c90c9..542a77e84 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java @@ -58,8 +58,4 @@ public interface CouponConvert { CouponPageReqVO convert(AppCouponPageReqVO pageReqVO, Collection userIds); - PageResult convertAppPage(PageResult pageResult); - - List convertList(List list); - } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java index 7cc13e2ce..edd654275 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java @@ -168,4 +168,13 @@ public interface CouponService { */ Map getUserCanCanTakeMap(Long userId, List templates); + /** + * 获得优惠劵 + * + * @param userId 用户编号 + * @param id 编号 + * @return 优惠劵 + */ + CouponDO getCoupon(Long userId, Long id); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java index 1c2297107..0f8d54966 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java @@ -315,6 +315,11 @@ public class CouponServiceImpl implements CouponService { userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= couponTemplate.getTakeLimitCount()); } + @Override + public CouponDO getCoupon(Long userId, Long id) { + return couponMapper.selectByIdAndUserId(id, userId); + } + /** * 获得自身的代理对象,解决 AOP 生效问题 * From 4a007f0c986a5e511483f347e8d5c5f67ad8240d Mon Sep 17 00:00:00 2001 From: owen Date: Sat, 16 Dec 2023 23:48:10 +0800 Subject: [PATCH 027/151] =?UTF-8?q?=E7=BB=9F=E8=AE=A1=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=95=86=E5=93=81=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/mysql/optinal/product_statistics.sql | 34 ++++++++ .../common/pojo/SortablePageParam.java | 19 ++++ .../common/util/object/BeanUtils.java | 13 ++- .../mybatis/core/mapper/BaseMapperX.java | 12 ++- .../mybatis/core/util/MyBatisUtils.java | 56 +++++++++++- .../product/ProductStatisticsController.java | 86 +++++++++++++++---- .../product/vo/ProductStatisticsReqVO.java | 25 ++++++ .../product/vo/ProductStatisticsRespVO.java | 81 +++++++++++++++++ .../trade/TradeStatisticsController.java | 14 ++- .../trade/vo/TradeTrendSummaryRespVO.java | 2 +- .../product/ProductStatisticsDO.java | 80 +++++++++++++++++ .../product/ProductStatisticsMapper.java | 60 +++++++++++++ .../product/ProductStatisticsService.java | 52 +++++++++++ .../product/ProductStatisticsServiceImpl.java | 72 ++++++++++++++++ .../service/trade/TradeStatisticsService.java | 2 +- .../trade/TradeStatisticsServiceImpl.java | 2 +- 16 files changed, 574 insertions(+), 36 deletions(-) create mode 100644 sql/mysql/optinal/product_statistics.sql create mode 100644 yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortablePageParam.java create mode 100644 yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsReqVO.java create mode 100644 yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java create mode 100644 yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/product/ProductStatisticsDO.java create mode 100644 yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/product/ProductStatisticsMapper.java create mode 100644 yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/product/ProductStatisticsService.java create mode 100644 yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/product/ProductStatisticsServiceImpl.java diff --git a/sql/mysql/optinal/product_statistics.sql b/sql/mysql/optinal/product_statistics.sql new file mode 100644 index 000000000..6dc546c3e --- /dev/null +++ b/sql/mysql/optinal/product_statistics.sql @@ -0,0 +1,34 @@ +CREATE TABLE product_statistics +( + id bigint AUTO_INCREMENT COMMENT '编号,主键自增' PRIMARY KEY, + time date NOT NULL COMMENT '统计日期', + spu_id bigint NOT NULL COMMENT '商品SPU编号', + browse_count int DEFAULT 0 NOT NULL COMMENT '浏览量', + browse_user_count int DEFAULT 0 NOT NULL COMMENT '访客量', + favorite_count int DEFAULT 0 NOT NULL COMMENT '收藏数量', + cart_count int DEFAULT 0 NOT NULL COMMENT '加购数量', + order_count int DEFAULT 0 NOT NULL COMMENT '下单件数', + order_pay_count int DEFAULT 0 NOT NULL COMMENT '支付件数', + order_pay_price int DEFAULT 0 NOT NULL COMMENT '支付金额,单位:分', + after_sale_count int DEFAULT 0 NOT NULL COMMENT '退款件数', + after_sale_refund_price int DEFAULT 0 NOT NULL COMMENT '退款金额,单位:分', + browse_convert_percent int DEFAULT 0 NOT NULL COMMENT '访客支付转化率(百分比)', + creator varchar(64) DEFAULT '' NULL COMMENT '创建者', + create_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '创建时间', + updater varchar(64) DEFAULT '' NULL COMMENT '更新者', + update_time datetime DEFAULT CURRENT_TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + deleted bit DEFAULT b'0' NOT NULL COMMENT '是否删除', + tenant_id bigint DEFAULT 0 NOT NULL COMMENT '租户编号' +) + COMMENT '商品统计表'; + +CREATE INDEX idx_time + ON product_statistics (time); + +CREATE INDEX idx_spu_id + ON product_statistics (spu_id); + +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES ('商品统计', '', 2, 6, 2358, 'product', 'fa:product-hunt', 'statistics/product/index', 'ProductStatistics', 0, true, true, true, '', '2023-12-15 18:54:28', '', '2023-12-15 18:54:33', false); +SELECT @parentId1 := LAST_INSERT_ID(); +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES ('商品统计查询', 'statistics:product:query', 3, 1, @parentId, '', '', '', null, 0, true, true, true, '', '2023-09-30 03:22:40', '', '2023-09-30 03:22:40', false); +INSERT INTO system_menu (name, permission, type, sort, parent_id, path, icon, component, component_name, status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) VALUES ('商品统计导出', 'statistics:product:export', 3, 2, @parentId, '', '', '', null, 0, true, true, true, '', '2023-09-30 03:22:40', '', '2023-09-30 03:22:40', false); diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortablePageParam.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortablePageParam.java new file mode 100644 index 000000000..2365c41c4 --- /dev/null +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/pojo/SortablePageParam.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.framework.common.pojo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.util.List; + +@Schema(description = "可排序的分页参数") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class SortablePageParam extends PageParam { + + @Schema(description = "排序字段") + private List sortingFields; + +} \ No newline at end of file diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/BeanUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/BeanUtils.java index e14572a7f..1bd54d1d5 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/BeanUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/object/BeanUtils.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import java.util.List; +import java.util.function.Consumer; /** * Bean 工具类 @@ -27,11 +28,19 @@ public class BeanUtils { return CollectionUtils.convertList(source, s -> toBean(s, targetType)); } - public static PageResult toBean(PageResult source, Class targetType) { + public static PageResult toBean(PageResult source, Class targetType) { + return toBean(source, targetType, null); + } + + public static PageResult toBean(PageResult source, Class targetType, Consumer peek) { if (source == null) { return null; } - return new PageResult<>(toBean(source.getList(), targetType), source.getTotal()); + List list = toBean(source.getList(), targetType); + if (peek != null) { + list.forEach(peek); + } + return new PageResult<>(list, source.getTotal()); } } \ No newline at end of file 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 e466f5ed7..2c46bd082 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 @@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.mybatis.core.mapper; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; +import cn.iocoder.yudao.framework.common.pojo.SortingField; import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -27,7 +29,15 @@ import java.util.List; */ public interface BaseMapperX extends MPJBaseMapper { + default PageResult selectPage(SortablePageParam pageParam, @Param("ew") Wrapper queryWrapper) { + return selectPage(pageParam, pageParam.getSortingFields(), queryWrapper); + } + default PageResult selectPage(PageParam pageParam, @Param("ew") Wrapper queryWrapper) { + return selectPage(pageParam, null, queryWrapper); + } + + default PageResult selectPage(PageParam pageParam, Collection sortingFields, @Param("ew") Wrapper queryWrapper) { // 特殊:不分页,直接查询全部 if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) { List list = selectList(queryWrapper); @@ -35,7 +45,7 @@ public interface BaseMapperX extends MPJBaseMapper { } // MyBatis Plus 查询 - IPage mpPage = MyBatisUtils.buildPage(pageParam); + IPage mpPage = MyBatisUtils.buildPage(pageParam, sortingFields); selectPage(mpPage, queryWrapper); // 转换返回 return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java index 0b1b01b08..11ccc5b99 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java @@ -1,7 +1,12 @@ package cn.iocoder.yudao.framework.mybatis.core.util; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.lang.func.Func1; +import cn.hutool.core.lang.func.LambdaUtil; +import cn.hutool.core.util.ArrayUtil; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; import cn.iocoder.yudao.framework.common.pojo.SortingField; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.core.toolkit.StringPool; @@ -11,6 +16,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; +import org.springframework.util.Assert; import java.util.ArrayList; import java.util.Collection; @@ -45,8 +51,8 @@ public class MyBatisUtils { * 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置 * * @param interceptor 链 - * @param inner 拦截器 - * @param index 位置 + * @param inner 拦截器 + * @param index 位置 */ public static void addInterceptor(MybatisPlusInterceptor interceptor, InnerInterceptor inner, int index) { List inners = new ArrayList<>(interceptor.getInterceptors()); @@ -73,9 +79,9 @@ public class MyBatisUtils { /** * 构建 Column 对象 * - * @param tableName 表名 + * @param tableName 表名 * @param tableAlias 别名 - * @param column 字段名 + * @param column 字段名 * @return Column 对象 */ public static Column buildColumn(String tableName, Alias tableAlias, String column) { @@ -85,4 +91,46 @@ public class MyBatisUtils { return new Column(tableName + StringPool.DOT + column); } + + /** + * 构建排序字段(默认倒序) + * + * @param func 排序字段的 Lambda 表达式 + * @param 排序字段所属的类型 + * @return 排序字段 + */ + public static SortingField buildSortingField(Func1 func) { + return buildSortingField(func, SortingField.ORDER_DESC); + } + + /** + * 构建排序字段 + * + * @param func 排序字段的 Lambda 表达式 + * @param order 排序类型 {@link SortingField#ORDER_ASC} {@link SortingField#ORDER_DESC} + * @param 排序字段所属的类型 + * @return 排序字段 + */ + public static SortingField buildSortingField(Func1 func, String order) { + Object[] orderTypes = {SortingField.ORDER_ASC, SortingField.ORDER_DESC}; + Assert.isTrue(ArrayUtil.contains(orderTypes, order), String.format("字段的排序类型只能是%s/%s", orderTypes)); + + String fieldName = LambdaUtil.getFieldName(func); + return new SortingField(fieldName, order); + } + + /** + * 构建默认的排序字段 + * 如果排序字段为空,则设置排序字段;否则忽略 + * + * @param sortablePageParam 排序分页查询参数 + * @param func 排序字段的 Lambda 表达式 + * @param 排序字段所属的类型 + */ + public static void buildDefaultSortingField(SortablePageParam sortablePageParam, Func1 func) { + if (sortablePageParam != null && CollUtil.isEmpty(sortablePageParam.getSortingFields())) { + sortablePageParam.setSortingFields(List.of(buildSortingField(func))); + } + } + } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/ProductStatisticsController.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/ProductStatisticsController.java index 4e5684fb9..98c7548b2 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/ProductStatisticsController.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/ProductStatisticsController.java @@ -2,40 +2,90 @@ package cn.iocoder.yudao.module.statistics.controller.admin.product; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.statistics.dal.mysql.product.ProductSpuStatisticsDO; -import cn.iocoder.yudao.module.statistics.dal.mysql.product.ProductStatisticsDO; +import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductStatisticsReqVO; +import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductStatisticsRespVO; +import cn.iocoder.yudao.module.statistics.dal.dataobject.product.ProductStatisticsDO; +import cn.iocoder.yudao.module.statistics.service.product.ProductStatisticsService; +import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.extern.slf4j.Slf4j; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; 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.RestController; -import java.time.LocalDateTime; +import java.io.IOException; import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - 商品统计") @RestController @RequestMapping("/statistics/product") @Validated -@Slf4j public class ProductStatisticsController { - // TODO @麦子:返回 ProductStatisticsComparisonResp, 里面有两个字段,一个是选择的时间范围的合计结果,一个是对比的时间范围的合计结果; - // 例如说,选择时间范围是 2023-10-01 ~ 2023-10-02,那么对比就是 2023-09-30,再倒推 2 天; - public CommonResult getProductStatisticsComparison() { - return null; + @Resource + private ProductStatisticsService productStatisticsService; + + @Resource + private ProductSpuApi productSpuApi; + + @GetMapping("/analyse") + @Operation(summary = "获得商品统计分析") + @PreAuthorize("@ss.hasPermission('statistics:product:query')") + public CommonResult> getProductStatisticsAnalyse(ProductStatisticsReqVO reqVO) { + return success(productStatisticsService.getProductStatisticsAnalyse(reqVO)); } - // TODO @麦子:查询指定时间范围内的商品统计数据;DO 到时需要改成 VO 哈 - public CommonResult> getProductStatisticsList( - LocalDateTime[] times) { - return null; + @GetMapping("/list") + @Operation(summary = "获得商品统计明细(日期维度)") + @PreAuthorize("@ss.hasPermission('statistics:product:query')") + public CommonResult> getProductStatisticsList(ProductStatisticsReqVO reqVO) { + List list = productStatisticsService.getProductStatisticsList(reqVO); + return success(BeanUtils.toBean(list, ProductStatisticsRespVO.class)); } - // TODO @麦子:查询指定时间范围内的商品 SPU 统计数据;DO 到时需要改成 VO 哈 - // 入参是分页参数 + 时间范围 + 排序字段 - public CommonResult> getProductSpuStatisticsPage() { - return null; + @GetMapping("/export-excel") + @Operation(summary = "导出获得商品统计明细 Excel(日期维度)") + @PreAuthorize("@ss.hasPermission('statistics:product:export')") + public void exportProductStatisticsExcel(ProductStatisticsReqVO reqVO, HttpServletResponse response) throws IOException { + List list = productStatisticsService.getProductStatisticsList(reqVO); + // 导出 Excel + List voList = BeanUtils.toBean(list, ProductStatisticsRespVO.class); + ExcelUtils.write(response, "商品状况.xls", "数据", ProductStatisticsRespVO.class, voList); } -} + @GetMapping("/rank-page") + @Operation(summary = "获得商品统计排行榜分页(商品维度)") + @PreAuthorize("@ss.hasPermission('statistics:product:query')") + public CommonResult> getProductStatisticsRankPage(@Valid ProductStatisticsReqVO reqVO, + @Valid SortablePageParam pageParam) { + PageResult pageResult = productStatisticsService.getProductStatisticsRankPage(reqVO, pageParam); + // 处理商品信息 + Set spuIds = convertSet(pageResult.getList(), ProductStatisticsDO::getSpuId); + Map spuMap = convertMap(productSpuApi.getSpuList(spuIds), ProductSpuRespDTO::getId); + // 拼接返回 + return success(BeanUtils.toBean(pageResult, ProductStatisticsRespVO.class, + // 拼接商品信息 + item -> Optional.ofNullable(spuMap.get(item.getSpuId())).ifPresent(spu -> { + item.setName(spu.getName()); + item.setPicUrl(spu.getPicUrl()); + }))); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsReqVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsReqVO.java new file mode 100644 index 000000000..02387c32f --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.statistics.controller.admin.product.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +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 = "管理后台 - 商品统计分析 Request VO") +@Data +@ToString(callSuper = true) +@AllArgsConstructor +@NoArgsConstructor +public class ProductStatisticsReqVO { + + @Schema(description = "统计时间范围", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] times; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java new file mode 100644 index 000000000..2a9a2673e --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.statistics.controller.admin.product.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDate; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; + +@Schema(description = "管理后台 - 商品统计 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ProductStatisticsRespVO { + + @Schema(description = "编号,主键自增", requiredMode = Schema.RequiredMode.REQUIRED, example = "12393") + private Long id; + + @Schema(description = "统计日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-12-16") + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY) + @ExcelProperty("统计日期") + private LocalDate time; + + @Schema(description = "商品SPU编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15114") + @ExcelProperty("商品SPU编号") + private Long spuId; + + //region 商品信息 + + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "商品名称") + @ExcelProperty("商品名称") + private String name; + + @Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "15114") + @ExcelProperty("商品封面图") + private String picUrl; + + //endregion + + @Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "17505") + @ExcelProperty("浏览量") + private Integer browseCount; + + @Schema(description = "访客量", requiredMode = Schema.RequiredMode.REQUIRED, example = "11814") + @ExcelProperty("访客量") + private Integer browseUserCount; + + @Schema(description = "收藏数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20950") + @ExcelProperty("收藏数量") + private Integer favoriteCount; + + @Schema(description = "加购数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "28493") + @ExcelProperty("加购数量") + private Integer cartCount; + + @Schema(description = "下单件数", requiredMode = Schema.RequiredMode.REQUIRED, example = "18966") + @ExcelProperty("下单件数") + private Integer orderCount; + + @Schema(description = "支付件数", requiredMode = Schema.RequiredMode.REQUIRED, example = "15142") + @ExcelProperty("支付件数") + private Integer orderPayCount; + + @Schema(description = "支付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "11595") + @ExcelProperty("支付金额,单位:分") + private Integer orderPayPrice; + + @Schema(description = "退款件数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2591") + @ExcelProperty("退款件数") + private Integer afterSaleCount; + + @Schema(description = "退款金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "21709") + @ExcelProperty("退款金额,单位:分") + private Integer afterSaleRefundPrice; + + @Schema(description = "访客支付转化率(百分比)", requiredMode = Schema.RequiredMode.REQUIRED, example = "15") + private Integer browseConvertPercent; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/TradeStatisticsController.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/TradeStatisticsController.java index 0b304e0a3..bac07d107 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/TradeStatisticsController.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/TradeStatisticsController.java @@ -18,6 +18,9 @@ import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; @@ -25,9 +28,6 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import java.io.IOException; import java.util.List; @@ -67,13 +67,11 @@ public class TradeStatisticsController { return success(TradeStatisticsConvert.INSTANCE.convert(yesterdayData, beforeYesterdayData, monthData, lastMonthData)); } - // TODO @疯狂:【晚点再改和讨论;等首页的接口出来】这个要不还是叫 analyse,对比选中的时间段,和上一个时间段;类似 MemberStatisticsController 的 getMemberAnalyse - @GetMapping("/trend/summary") + @GetMapping("/analyse") @Operation(summary = "获得交易状况统计") @PreAuthorize("@ss.hasPermission('statistics:trade:query')") - public CommonResult> getTradeTrendSummaryComparison( - TradeTrendReqVO reqVO) { - return success(tradeStatisticsService.getTradeTrendSummaryComparison(ArrayUtil.get(reqVO.getTimes(), 0), + public CommonResult> getTradeStatisticsAnalyse(TradeTrendReqVO reqVO) { + return success(tradeStatisticsService.getTradeStatisticsAnalyse(ArrayUtil.get(reqVO.getTimes(), 0), ArrayUtil.get(reqVO.getTimes(), 1))); } diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryRespVO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryRespVO.java index f76d02e91..be5a93a51 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryRespVO.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryRespVO.java @@ -12,7 +12,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @Data public class TradeTrendSummaryRespVO { - @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @Schema(description = "日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-12-16") @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY) private LocalDate date; diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/product/ProductStatisticsDO.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/product/ProductStatisticsDO.java new file mode 100644 index 000000000..2e2267609 --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/dataobject/product/ProductStatisticsDO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.statistics.dal.dataobject.product; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.time.LocalDate; + +/** + * 商品统计 DO + * + * @author owen + */ +@TableName("product_statistics") +@KeySequence("product_statistics_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductStatisticsDO extends BaseDO { + + /** + * 编号,主键自增 + */ + @TableId + private Long id; + /** + * 统计日期 + */ + private LocalDate time; + /** + * 商品SPU编号 + */ + private Long spuId; + /** + * 浏览量 + */ + private Integer browseCount; + /** + * 访客量 + */ + private Integer browseUserCount; + /** + * 收藏数量 + */ + private Integer favoriteCount; + /** + * 加购数量 + */ + private Integer cartCount; + /** + * 下单件数 + */ + private Integer orderCount; + /** + * 支付件数 + */ + private Integer orderPayCount; + /** + * 支付金额,单位:分 + */ + private Integer orderPayPrice; + /** + * 退款件数 + */ + private Integer afterSaleCount; + /** + * 退款金额,单位:分 + */ + private Integer afterSaleRefundPrice; + /** + * 访客支付转化率(百分比) + */ + private Integer browseConvertPercent; + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/product/ProductStatisticsMapper.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/product/ProductStatisticsMapper.java new file mode 100644 index 000000000..f082bde90 --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/dal/mysql/product/ProductStatisticsMapper.java @@ -0,0 +1,60 @@ +package cn.iocoder.yudao.module.statistics.dal.mysql.product; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductStatisticsReqVO; +import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductStatisticsRespVO; +import cn.iocoder.yudao.module.statistics.dal.dataobject.product.ProductStatisticsDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 商品统计 Mapper + * + * @author owen + */ +@Mapper +public interface ProductStatisticsMapper extends BaseMapperX { + + default PageResult selectPageGroupBySpuId(ProductStatisticsReqVO reqVO, SortablePageParam pageParam) { + return selectPage(pageParam, buildWrapper(reqVO) + .groupBy(ProductStatisticsDO::getSpuId) + .select(ProductStatisticsDO::getSpuId) + ); + } + + default List selectListByTimeBetween(ProductStatisticsReqVO reqVO) { + return selectList(buildWrapper(reqVO) + .groupBy(ProductStatisticsDO::getTime) + .select(ProductStatisticsDO::getTime)); + } + + default ProductStatisticsRespVO selectVoByTimeBetween(ProductStatisticsReqVO reqVO) { + return selectJoinOne(ProductStatisticsRespVO.class, buildWrapper(reqVO)); + } + + /** + * 构建 LambdaWrapper + * + * @param reqVO 查询参数 + * @return LambdaWrapper + */ + private static MPJLambdaWrapperX buildWrapper(ProductStatisticsReqVO reqVO) { + return new MPJLambdaWrapperX() + .betweenIfPresent(ProductStatisticsDO::getTime, reqVO.getTimes()) + .selectSum(ProductStatisticsDO::getBrowseCount) + .selectSum(ProductStatisticsDO::getBrowseUserCount) + .selectSum(ProductStatisticsDO::getFavoriteCount) + .selectSum(ProductStatisticsDO::getCartCount) + .selectSum(ProductStatisticsDO::getOrderCount) + .selectSum(ProductStatisticsDO::getOrderPayCount) + .selectSum(ProductStatisticsDO::getOrderPayPrice) + .selectSum(ProductStatisticsDO::getAfterSaleCount) + .selectSum(ProductStatisticsDO::getAfterSaleRefundPrice) + .selectAvg(ProductStatisticsDO::getBrowseConvertPercent); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/product/ProductStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/product/ProductStatisticsService.java new file mode 100644 index 000000000..dd99f85ae --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/product/ProductStatisticsService.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.statistics.service.product; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductStatisticsReqVO; +import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductStatisticsRespVO; +import cn.iocoder.yudao.module.statistics.dal.dataobject.product.ProductStatisticsDO; + +import java.util.List; + +/** + * 商品统计 Service 接口 + * + * @author owen + */ +public interface ProductStatisticsService { + + /** + * 创建商品统计 + * + * @param entity 创建信息 + * @return 编号 + */ + Long createProductStatistics(ProductStatisticsDO entity); + + /** + * 获得商品统计排行榜分页 + * + * @param reqVO 查询条件 + * @param pageParam 分页排序查询 + * @return 商品统计分页 + */ + PageResult getProductStatisticsRankPage(ProductStatisticsReqVO reqVO, SortablePageParam pageParam); + + /** + * 获得商品状况统计分析 + * + * @param reqVO 查询条件 + * @return 统计数据对照 + */ + DataComparisonRespVO getProductStatisticsAnalyse(ProductStatisticsReqVO reqVO); + + /** + * 获得商品状况明细 + * + * @param reqVO 查询条件 + * @return 统计数据对照 + */ + List getProductStatisticsList(ProductStatisticsReqVO reqVO); + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/product/ProductStatisticsServiceImpl.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/product/ProductStatisticsServiceImpl.java new file mode 100644 index 000000000..1d1dd6cc9 --- /dev/null +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/product/ProductStatisticsServiceImpl.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.statistics.service.product; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; +import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; +import cn.iocoder.yudao.module.statistics.controller.admin.common.vo.DataComparisonRespVO; +import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductStatisticsReqVO; +import cn.iocoder.yudao.module.statistics.controller.admin.product.vo.ProductStatisticsRespVO; +import cn.iocoder.yudao.module.statistics.dal.dataobject.product.ProductStatisticsDO; +import cn.iocoder.yudao.module.statistics.dal.mysql.product.ProductStatisticsMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; + + +/** + * 商品统计 Service 实现类 + * + * @author owen + */ +@Service +@Validated +public class ProductStatisticsServiceImpl implements ProductStatisticsService { + + @Resource + private ProductStatisticsMapper productStatisticsMapper; + + @Override + public Long createProductStatistics(ProductStatisticsDO entity) { + // 计算 访客支付转化率(百分比) + if (entity.getBrowseUserCount() != null && ObjUtil.notEqual(entity.getBrowseUserCount(), 0)) { + entity.setBrowseConvertPercent(100 * entity.getOrderPayCount() / entity.getBrowseUserCount()); + } + // 插入 + productStatisticsMapper.insert(entity); + // 返回 + return entity.getId(); + } + + @Override + public PageResult getProductStatisticsRankPage(ProductStatisticsReqVO reqVO, SortablePageParam pageParam) { + // 默认浏览量倒序 + MyBatisUtils.buildDefaultSortingField(pageParam, ProductStatisticsDO::getBrowseCount); + return productStatisticsMapper.selectPageGroupBySpuId(reqVO, pageParam); + } + + @Override + public DataComparisonRespVO getProductStatisticsAnalyse(ProductStatisticsReqVO reqVO) { + LocalDateTime beginTime = ArrayUtil.get(reqVO.getTimes(), 0); + LocalDateTime endTime = ArrayUtil.get(reqVO.getTimes(), 1); + + // 统计数据 + ProductStatisticsRespVO value = productStatisticsMapper.selectVoByTimeBetween(reqVO); + // 对照数据 + LocalDateTime referenceBeginTime = beginTime.minus(Duration.between(beginTime, endTime)); + ProductStatisticsReqVO referenceReqVO = new ProductStatisticsReqVO(new LocalDateTime[]{referenceBeginTime, beginTime}); + ProductStatisticsRespVO reference = productStatisticsMapper.selectVoByTimeBetween(referenceReqVO); + return new DataComparisonRespVO<>(value, reference); + } + + @Override + public List getProductStatisticsList(ProductStatisticsReqVO reqVO) { + return productStatisticsMapper.selectListByTimeBetween(reqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java index ec2e5bd5a..225bccf9f 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsService.java @@ -20,7 +20,7 @@ public interface TradeStatisticsService { * * @return 统计数据对照 */ - DataComparisonRespVO getTradeTrendSummaryComparison( + DataComparisonRespVO getTradeStatisticsAnalyse( LocalDateTime beginTime, LocalDateTime endTime); /** diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java index a6b9b1633..465a1911d 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/trade/TradeStatisticsServiceImpl.java @@ -60,7 +60,7 @@ public class TradeStatisticsServiceImpl implements TradeStatisticsService { } @Override - public DataComparisonRespVO getTradeTrendSummaryComparison(LocalDateTime beginTime, + public DataComparisonRespVO getTradeStatisticsAnalyse(LocalDateTime beginTime, LocalDateTime endTime) { // 统计数据 TradeTrendSummaryRespVO value = tradeStatisticsMapper.selectVoByTimeBetween(beginTime, endTime); From b0b6544887982b8985191982006b9a25758dbd61 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 17 Dec 2023 09:51:24 +0800 Subject: [PATCH 028/151] =?UTF-8?q?=E2=9C=A8=20MALL=EF=BC=9A=E4=BC=9A?= =?UTF-8?q?=E5=91=98=E7=9A=84=E4=B8=AA=E4=BA=BA=E4=BF=A1=E6=81=AF=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=20sex=20=E4=BF=AE=E6=94=B9=E5=92=8C=E8=BF=94?= =?UTF-8?q?=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/app/user/vo/AppMemberUserInfoRespVO.java | 3 +++ .../controller/app/user/vo/AppMemberUserUpdateReqVO.java | 5 +++++ .../module/member/service/user/MemberUserServiceImpl.java | 5 +++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java index 25cceedc2..fa05e16d0 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserInfoRespVO.java @@ -20,6 +20,9 @@ public class AppMemberUserInfoRespVO { @Schema(description = "用户手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300") private String mobile; + @Schema(description = "用户性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer sex; + @Schema(description = "积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer point; diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java index a676f6256..cca08e926 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppMemberUserUpdateReqVO.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.member.controller.app.user.vo; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.system.enums.common.SexEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.hibernate.validator.constraints.URL; @@ -15,4 +17,7 @@ public class AppMemberUserUpdateReqVO { @URL(message = "头像必须是 URL 格式") private String avatar; + @Schema(description = "性别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer sex; + } 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 a7466d22c..37b56f001 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 @@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; 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; 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; @@ -128,8 +129,8 @@ public class MemberUserServiceImpl implements MemberUserService { @Override public void updateUser(Long userId, AppMemberUserUpdateReqVO reqVO) { - memberUserMapper.updateById(new MemberUserDO().setId(userId) - .setNickname(reqVO.getNickname()).setAvatar(reqVO.getAvatar())); + MemberUserDO updateObj = BeanUtils.toBean(reqVO, MemberUserDO.class).setId(userId); + memberUserMapper.updateById(updateObj); } @Override From ddb6fe7ec8e520df680857f9d0932c2ae5ccddde Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 17 Dec 2023 10:57:49 +0800 Subject: [PATCH 029/151] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E5=AE=A2=E6=88=B7=E7=AE=A1=E7=90=86=E7=9A=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=9D=83=E9=99=90=E3=80=81=E6=93=8D=E4=BD=9C=E6=9D=83?= =?UTF-8?q?=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 19 ++++++++++--------- .../admin/clue/vo/CrmClueTransferReqVO.java | 12 +++--------- .../admin/customer/CrmCustomerController.java | 4 ++++ .../plan/CrmReceivablePlanTransferReqVO.java | 12 +++--------- .../CrmReceivableTransferReqVO.java | 12 +++--------- .../function/CrmIndustryParseFunction.java | 1 + .../core/aop/CrmPermissionAspect.java | 1 + .../customer/CrmCustomerServiceImpl.java | 2 ++ .../permission/CrmPermissionServiceImpl.java | 7 +++---- .../CrmReceivablePlanServiceImpl.java | 6 +++--- .../module/crm/util/CrmQueryWrapperUtils.java | 16 ++++++++-------- .../yudao-module-system-api/pom.xml | 2 ++ .../api/logger/dto/OperateLogV2RespDTO.java | 16 +++++----------- .../dal/dataobject/logger/OperateLogV2DO.java | 9 +++++++++ .../YudaoOperateLogV2Configuration.java | 1 + .../function/AdminUserParseFunction.java | 1 + .../bizlog/service/ILogRecordServiceImpl.java | 1 + .../service/logger/OperateLogService.java | 3 ++- .../service/logger/OperateLogServiceImpl.java | 2 +- 19 files changed, 63 insertions(+), 64 deletions(-) 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 92da847fd..ae8c795ab 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,5 +1,6 @@ package cn.iocoder.yudao.module.crm.enums; +// TODO 芋艿:操作日志;看看这个类怎么搞个好点的规范; /** * CRM 操作日志枚举 * @@ -9,18 +10,18 @@ public interface LogRecordConstants { //======================= 客户模块类型 ======================= // TODO puhui999: 确保模块命名方式为 module + 子模块名称的方式。统一定义模块名称是为了方便查询各自记录的操作日志,列如说:查询客户【张三的操作日志】就可以 module + bizId - String CRM_LEADS = "CRM-线索"; - String CRM_CUSTOMER = "CRM-客户"; - String CRM_CONTACT = "CRM-联系人"; - String CRM_BUSINESS = "CRM-商机"; - String CRM_CONTRACT = "CRM-合同"; - String CRM_PRODUCT = "CRM-产品"; - String CRM_RECEIVABLE = "CRM-回款"; - String CRM_RECEIVABLE_PLAN = "CRM-回款计划"; + String CRM_LEADS = "CRM 线索"; + String CRM_CUSTOMER = "CRM 客户"; + String CRM_CONTACT = "CRM 联系人"; + String CRM_BUSINESS = "CRM 商机"; + String CRM_CONTRACT = "CRM 合同"; + String CRM_PRODUCT = "CRM 产品"; + String CRM_RECEIVABLE = "CRM 回款"; + String CRM_RECEIVABLE_PLAN = "CRM 回款计划"; //======================= 客户转移操作日志 ======================= String TRANSFER_CUSTOMER_LOG_SUCCESS = "把客户【{{#crmCustomer.name}}】的负责人从【{getAdminUserById{#crmCustomer.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; - String TRANSFER_CUSTOMER_LOG_FAIL = ""; + String TRANSFER_CUSTOMER_LOG_FAIL = ""; // TODO @puhui999:这个可以删除哈,一般不搞失败的日志 } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransferReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransferReqVO.java index da71a1ec2..63bdc1838 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransferReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransferReqVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; +import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; @@ -13,19 +14,12 @@ public class CrmClueTransferReqVO { @NotNull(message = "线索编号不能为空") private Long id; - /** - * 新负责人的用户编号 - */ @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") @NotNull(message = "新负责人的用户编号不能为空") private Long newOwnerUserId; - /** - * 老负责人加入团队后的权限级别。如果 null 说明移除 - * - * 关联 {@link CrmPermissionLevelEnum} - */ @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - private Integer oldOwnerPermissionLevel; + @InEnum(value = CrmPermissionLevelEnum.class) + private Integer oldOwnerPermissionLevel; // 老负责人加入团队后的权限级别。如果 null 说明移除 } 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 8386e80ed..0882ea72c 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 @@ -135,18 +135,22 @@ public class CrmCustomerController { return success(true); } + // TODO @puhui999:operate-log-list 或者 operate-log-page 如果分页 @GetMapping("/operate-log") @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)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanTransferReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanTransferReqVO.java index 09f85e419..93f5413af 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanTransferReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanTransferReqVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; +import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; @@ -13,19 +14,12 @@ public class CrmReceivablePlanTransferReqVO { @NotNull(message = "回款计划编号不能为空") private Long id; - /** - * 新负责人的用户编号 - */ @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") @NotNull(message = "新负责人的用户编号不能为空") private Long newOwnerUserId; - /** - * 老负责人加入团队后的权限级别。如果 null 说明移除 - * - * 关联 {@link CrmPermissionLevelEnum} - */ @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - private Integer oldOwnerPermissionLevel; + @InEnum(value = CrmPermissionLevelEnum.class) + private Integer oldOwnerPermissionLevel; // 老负责人加入团队后的权限级别。如果 null 说明移除 } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableTransferReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableTransferReqVO.java index f94ce4c1b..364ce4f8b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableTransferReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableTransferReqVO.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; +import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; @@ -13,19 +14,12 @@ public class CrmReceivableTransferReqVO { @NotNull(message = "回款编号不能为空") private Long id; - /** - * 新负责人的用户编号 - */ @Schema(description = "新负责人的用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10430") @NotNull(message = "新负责人的用户编号不能为空") private Long newOwnerUserId; - /** - * 老负责人加入团队后的权限级别。如果 null 说明移除 - * - * 关联 {@link CrmPermissionLevelEnum} - */ @Schema(description = "老负责人加入团队后的权限级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - private Integer oldOwnerPermissionLevel; + @InEnum(value = CrmPermissionLevelEnum.class) + private Integer oldOwnerPermissionLevel; // 老负责人加入团队后的权限级别。如果 null 说明移除 } 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/bizlog/function/CrmIndustryParseFunction.java index 0a468dfa8..f963b533a 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/bizlog/function/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:包名使用 operatelog 更合适哈; /** * 自定义函数-通过行业编号获取行业信息 * 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/core/aop/CrmPermissionAspect.java index 40a05872f..3e1cf87b2 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/core/aop/CrmPermissionAspect.java @@ -26,6 +26,7 @@ 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 切面 * 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 87a01653b..e53dc1a46 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 @@ -137,12 +137,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @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}}") @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())); // 2.1 数据权限转移 crmPermissionService.transferPermission( 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 76f37f909..14fb966c5 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,11 +138,10 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { } @Override - @Transactional(rollbackFor = Exception.class) + @Transactional(rollbackFor = Exception.class) // TODO @puhui999:这里不用加的,就一个操作哈; public void deletePermission(Integer bizType, Long bizId) { - // 删除数据权限 - int deletedCol = crmPermissionMapper.deletePermission(bizType, bizId); - if (deletedCol == 0) { + int deletedCount = crmPermissionMapper.deletePermission(bizType, bizId); + if (deletedCount == 0) { throw exception(CRM_PERMISSION_NOT_EXISTS); } } 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 39154dd5d..edfb6c70a 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 @@ -61,9 +61,9 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { receivablePlanMapper.insert(receivablePlan); // 创建数据权限 - crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType()) - .setBizId(receivablePlan.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); - // 返回 + crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) + .setBizType(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType()).setBizId(receivablePlan.getId()) + .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); return receivablePlan.getId(); } 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 dfdb3ecb9..161bff845 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 @@ -35,14 +35,14 @@ public class CrmQueryWrapperUtils { * @param pool 公海 * @return 是否 (是:需要执行查询,否:不需要查询调用方法直接返回空) */ - // TODO @puhui999:bizId 直接传递会不会简单点 回复:还是需要 SFunction 因为分页连表时不知道 bizId 是多少 + // TODO @puhui999:bizId 直接传递会不会简单点 回复:还是需要 SFunction 因为分页连表时不知道 bizId 是多少;是不是把 bizId 传入就好啦? public static , S> boolean appendPermissionCondition(T query, Integer bizType, SFunction bizId, Long userId, Integer sceneType, Boolean pool) { // 1. 构建数据权限连表条件 if (ObjUtil.notEqual(validateAdminUser(userId), Boolean.TRUE)) { // 管理员不需要数据权限 - query.innerJoin(CrmPermissionDO.class, on -> - on.eq(CrmPermissionDO::getBizType, bizType).eq(CrmPermissionDO::getBizId, bizId) - .eq(CrmPermissionDO::getUserId, userId)); + query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType) + .eq(CrmPermissionDO::getBizId, bizId) + .eq(CrmPermissionDO::getUserId, userId)); } // 2.1 场景一:我负责的数据 if (CrmSceneTypeEnum.isOwner(sceneType)) { @@ -50,15 +50,15 @@ public class CrmQueryWrapperUtils { } // 2.2 场景二:我参与的数据 if (CrmSceneTypeEnum.isInvolved(sceneType)) { - query - .ne("owner_user_id", userId) + 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())); - } // 2.3 场景三:下属负责的数据 if (CrmSceneTypeEnum.isSubordinate(sceneType)) { + // TODO @puhui999:要不如果没有下属,拼一个 owner_user_id in null,不返回结果就好啦; List subordinateUsers = getAdminUserApi().getUserListBySubordinate(userId); if (CollUtil.isEmpty(subordinateUsers)) { return false; @@ -72,7 +72,6 @@ public class CrmQueryWrapperUtils { } else { // 情况二:不是公海 query.isNotNull("owner_user_id"); } - return true; } @@ -106,6 +105,7 @@ public class CrmQueryWrapperUtils { */ private static boolean validateAdminUser(Long userId) { // TODO 查询权限配置表用户的角色信息 + // TODO @puhui999:查询用户的角色;CRM_ADMIN("crm_admin", "CRM 管理员"), //CrmPermissionConfig permissionConfig = crmPermissionConfigService.getPermissionConfigByUserId(userId); //if (permissionConfig == null) { // return false; diff --git a/yudao-module-system/yudao-module-system-api/pom.xml b/yudao-module-system/yudao-module-system-api/pom.xml index 3c91bd974..2a60b20b8 100644 --- a/yudao-module-system/yudao-module-system-api/pom.xml +++ b/yudao-module-system/yudao-module-system-api/pom.xml @@ -22,6 +22,7 @@ yudao-common + @@ -29,6 +30,7 @@ bizlog-sdk + com.fasterxml.jackson.core 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 9a918abe3..a7670541d 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 @@ -19,20 +19,14 @@ public class OperateLogV2RespDTO { /** * 链路追踪编号 - * - * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。 */ private String traceId; /** * 用户编号 - * - * 关联 MemberUserDO 的 id 属性,或者 AdminUserDO 的 id 属性 */ private Long userId; /** * 用户类型 - * - * 关联 {@link UserTypeEnum} */ private Integer userType; /** @@ -48,13 +42,11 @@ public class OperateLogV2RespDTO { */ private Long bizId; /** - * 操作内容,记录整个操作的明细 - * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 + * 操作内容 */ private String content; /** - * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) - * 例如说,记录订单编号,{ orderId: "1"} + * 拓展字段 */ private String extra; @@ -81,8 +73,10 @@ public class OperateLogV2RespDTO { // TODO puhui999: 木得效果怎么肥事 @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) private LocalDateTime createTime; + + // TODO @puhui999:下面 2 个字段不用返回;用 userId 哈;返回一个 userName /** - * 创建者,关联 AdminUserDO#getId + * 创建者 */ private String creator; /** 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 1b7b1eaab..10035c8e9 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,6 +42,7 @@ public class OperateLogV2DO extends BaseDO { * 关联 {@link UserTypeEnum} */ private Integer userType; + // TODO @puhui999:module 改成 type,name 改成 subType; /** * 操作模块 */ @@ -56,13 +57,16 @@ public class OperateLogV2DO extends BaseDO { private Long bizId; /** * 操作内容,记录整个操作的明细 + * * 例如说,修改编号为 1 的用户信息,将性别从男改成女,将姓名从芋道改成源码。 */ private String content; /** * 拓展字段,有些复杂的业务,需要记录一些字段 ( JSON 格式 ) + * * 例如说,记录订单编号,{ orderId: "1"} */ + // TODO @puhui999:看看能不能类似 exts 搞 json 格式; private String extra; /** * 请求方法名 @@ -81,4 +85,9 @@ public class OperateLogV2DO extends BaseDO { */ private String userAgent; + // TODO @芋艿:requestUrl、requestMethod + // TODO @芋艿:javaMethod、javaMethodArgs + // TODO @芋艿:startTime、duration + // TODO @芋艿:resultMsg、resultData + } 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 index 9e6a9dd85..a5f3a9eaa 100644 --- 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 @@ -3,6 +3,7 @@ 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 配置类 * 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/bizlog/function/AdminUserParseFunction.java index 60fee85be..a88073d4e 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/bizlog/function/AdminUserParseFunction.java @@ -9,6 +9,7 @@ import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +// TODO @puhui999:这个微信讨论下,function 叫啥好哈; /** * 自定义函数-通过用户编号获取用户信息 * 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-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java index a81280f99..07b25343e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/bizlog/service/ILogRecordServiceImpl.java @@ -15,6 +15,7 @@ import org.springframework.stereotype.Service; import java.util.Collections; import java.util.List; +// TODO @puhui999:这个应该搞到 operatelog 组件里哈; /** * 操作日志 ILogRecordService 实现类 * 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 30a1a1a7c..971685857 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 @@ -31,7 +31,7 @@ public interface OperateLogService { */ PageResult getOperateLogPage(OperateLogPageReqVO pageReqVO); - //======================= LOG V2 ======================= + // ======================= LOG V2 ======================= /** * 记录操作日志 V2 @@ -40,6 +40,7 @@ public interface OperateLogService { */ void createOperateLogV2(OperateLogV2CreateReqBO createReqBO); + // TODO @puhui999:module 改成 type /** * 获取指定模块的指定数据的操作日志 * 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 894cc48c8..39c84ed33 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 @@ -66,7 +66,7 @@ public class OperateLogServiceImpl implements OperateLogService { return operateLogMapper.selectPage(pageReqVO, userIds); } - //======================= LOG V2 ======================= + // ======================= LOG V2 ======================= @Override public void createOperateLogV2(OperateLogV2CreateReqBO createReqBO) { From de8f2800e59cc2a5e84c5cdeeca05c6966d59a2c Mon Sep 17 00:00:00 2001 From: owen Date: Sun, 17 Dec 2023 11:14:33 +0800 Subject: [PATCH 030/151] =?UTF-8?q?=E5=9F=BA=E7=A1=80=E8=AE=BE=E6=96=BD?= =?UTF-8?q?=EF=BC=9A=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=E5=99=A8javax?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E4=B8=BAjakarta?= 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 | 3 +-- .../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(+), 10 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..e6d96fbab 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,9 +3,8 @@ 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) #if (${column.javaType} == "BigDecimal") import java.math.BigDecimal; 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 86a9c4bbf4801ba8b72b88df2ee871e0d7bd53bb Mon Sep 17 00:00:00 2001 From: owen Date: Sun, 17 Dec 2023 11:16:29 +0800 Subject: [PATCH 031/151] =?UTF-8?q?=E5=9F=BA=E7=A1=80=E8=AE=BE=E6=96=BD?= =?UTF-8?q?=EF=BC=9A=E4=BC=98=E5=8C=96vue3=E6=A0=87=E5=87=86=E7=89=88API?= =?UTF-8?q?=E7=94=9F=E6=88=90=EF=BC=88=E5=AF=BC=E5=87=BAxxAPI=EF=BC=8C?= =?UTF-8?q?=E6=96=B9=E4=BE=BFIDE=E8=AF=86=E5=88=AB=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/codegen/vue3/api/api.ts.vm | 121 +++++++++--------- .../vue3/views/components/form_sub_erp.vue.vm | 2 +- .../views/components/form_sub_normal.vue.vm | 2 +- .../vue3/views/components/list_sub_erp.vue.vm | 2 +- .../resources/codegen/vue3/views/form.vue.vm | 5 +- .../resources/codegen/vue3/views/index.vue.vm | 24 ++-- 6 files changed, 86 insertions(+), 70 deletions(-) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm index c4b0b4332..7c2ab277b 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm @@ -1,12 +1,14 @@ import request from '@/config/axios' #set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}") +// ${table.classComment} VO export interface ${simpleClassName}VO { #foreach ($column in $columns) #if ($column.createOperation || $column.updateOperation) + // ${column.columnComment} #if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal") ${column.javaField}: number -#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime") +#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime") ${column.javaField}: Date #else ${column.javaField}: ${column.javaType.toLowerCase()} @@ -15,42 +17,44 @@ export interface ${simpleClassName}VO { #end } +// ${table.classComment} API +export const ${simpleClassName}Api = { #if ( $table.templateType != 2 ) -// 查询${table.classComment}分页 -export const get${simpleClassName}Page = async (params) => { - return await request.get({ url: `${baseURL}/page`, params }) -} + // 查询${table.classComment}分页 + get${simpleClassName}Page: async (params: any) => { + return await request.get({ url: `${baseURL}/page`, params }) + }, #else -// 查询${table.classComment}列表 -export const get${simpleClassName}List = async (params) => { - return await request.get({ url: `${baseURL}/list`, params }) -} + // 查询${table.classComment}列表 + get${simpleClassName}List: async (params) => { + return await request.get({ url: `${baseURL}/list`, params }) + }, #end -// 查询${table.classComment}详情 -export const get${simpleClassName} = async (id: number) => { - return await request.get({ url: `${baseURL}/get?id=` + id }) -} + // 查询${table.classComment}详情 + get${simpleClassName}: async (id: number) => { + return await request.get({ url: `${baseURL}/get?id=` + id }) + }, -// 新增${table.classComment} -export const create${simpleClassName} = async (data: ${simpleClassName}VO) => { - return await request.post({ url: `${baseURL}/create`, data }) -} + // 新增${table.classComment} + create${simpleClassName}: async (data: ${simpleClassName}VO) => { + return await request.post({ url: `${baseURL}/create`, data }) + }, -// 修改${table.classComment} -export const update${simpleClassName} = async (data: ${simpleClassName}VO) => { - return await request.put({ url: `${baseURL}/update`, data }) -} + // 修改${table.classComment} + update${simpleClassName}: async (data: ${simpleClassName}VO) => { + return await request.put({ url: `${baseURL}/update`, data }) + }, -// 删除${table.classComment} -export const delete${simpleClassName} = async (id: number) => { - return await request.delete({ url: `${baseURL}/delete?id=` + id }) -} + // 删除${table.classComment} + delete${simpleClassName}: async (id: number) => { + return await request.delete({ url: `${baseURL}/delete?id=` + id }) + }, -// 导出${table.classComment} Excel -export const export${simpleClassName} = async (params) => { - return await request.download({ url: `${baseURL}/export-excel`, params }) -} + // 导出${table.classComment} Excel + export${simpleClassName}: async (params) => { + return await request.download({ url: `${baseURL}/export-excel`, params }) + }, ## 特殊:主子表专属逻辑 #foreach ($subTable in $subTables) #set ($index = $foreach.count - 1) @@ -66,46 +70,47 @@ export const export${simpleClassName} = async (params) => { ## 情况一:MASTER_ERP 时,需要分查询页子表 #if ( $table.templateType == 11 ) -// 获得${subTable.classComment}分页 -export const get${subSimpleClassName}Page = async (params) => { - return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/page`, params }) -} + // 获得${subTable.classComment}分页 + get${subSimpleClassName}Page: async (params) => { + return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/page`, params }) + }, ## 情况二:非 MASTER_ERP 时,需要列表查询子表 #else #if ( $subTable.subJoinMany ) -// 获得${subTable.classComment}列表 -export const get${subSimpleClassName}ListBy${SubJoinColumnName} = async (${subJoinColumn.javaField}) => { - return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField} }) -} + // 获得${subTable.classComment}列表 + get${subSimpleClassName}ListBy${SubJoinColumnName}: async (${subJoinColumn.javaField}) => { + return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField} }) + }, #else -// 获得${subTable.classComment} -export const get${subSimpleClassName}By${SubJoinColumnName} = async (${subJoinColumn.javaField}) => { - return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField} }) -} + // 获得${subTable.classComment} + get${subSimpleClassName}By${SubJoinColumnName}: async (${subJoinColumn.javaField}) => { + return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=` + ${subJoinColumn.javaField} }) + }, #end #end ## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作 #if ( $table.templateType == 11 ) -// 新增${subTable.classComment} -export const create${subSimpleClassName} = async (data) => { - return await request.post({ url: `${baseURL}/${subSimpleClassName_strikeCase}/create`, data }) -} + // 新增${subTable.classComment} + create${subSimpleClassName}: async (data) => { + return await request.post({ url: `${baseURL}/${subSimpleClassName_strikeCase}/create`, data }) + }, -// 修改${subTable.classComment} -export const update${subSimpleClassName} = async (data) => { - return await request.put({ url: `${baseURL}/${subSimpleClassName_strikeCase}/update`, data }) -} + // 修改${subTable.classComment} + update${subSimpleClassName}: async (data) => { + return await request.put({ url: `${baseURL}/${subSimpleClassName_strikeCase}/update`, data }) + }, -// 删除${subTable.classComment} -export const delete${subSimpleClassName} = async (id: number) => { - return await request.delete({ url: `${baseURL}/${subSimpleClassName_strikeCase}/delete?id=` + id }) -} + // 删除${subTable.classComment} + delete${subSimpleClassName}: async (id: number) => { + return await request.delete({ url: `${baseURL}/${subSimpleClassName_strikeCase}/delete?id=` + id }) + }, -// 获得${subTable.classComment} -export const get${subSimpleClassName} = async (id: number) => { - return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/get?id=` + id }) -} + // 获得${subTable.classComment} + get${subSimpleClassName}: async (id: number) => { + return await request.get({ url: `${baseURL}/${subSimpleClassName_strikeCase}/get?id=` + id }) + }, #end -#end \ No newline at end of file +#end +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm index ed318875e..3996a9caa 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/components/form_sub_erp.vue.vm @@ -114,7 +114,7 @@