Commit e9a29e6dd40445a93fb6d1e3f2c59514626270f8

Authored by YunaiV
1 parent 1fd731a9

CRM:优化合同金额排行、回款金额排行

Showing 23 changed files with 252 additions and 281 deletions
... ... @@ -16,7 +16,7 @@
16 16 <module>yudao-module-system</module>
17 17 <module>yudao-module-infra</module>
18 18 <!-- <module>yudao-module-member</module>-->
19   -<!-- <module>yudao-module-bpm</module>-->
  19 + <module>yudao-module-bpm</module>
20 20 <!-- <module>yudao-module-report</module>-->
21 21 <!-- <module>yudao-module-mp</module>-->
22 22 <!-- <module>yudao-module-pay</module>-->
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.java deleted
1   -package cn.iocoder.yudao.module.crm.controller.admin.bi;
2   -
3   -
4   -
5   -import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6   -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO;
7   -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO;
8   -import cn.iocoder.yudao.module.crm.service.bi.BiRankingService;
9   -import io.swagger.v3.oas.annotations.Operation;
10   -import io.swagger.v3.oas.annotations.tags.Tag;
11   -import jakarta.annotation.Resource;
12   -import org.springframework.security.access.prepost.PreAuthorize;
13   -import org.springframework.validation.annotation.Validated;
14   -import org.springframework.web.bind.annotation.GetMapping;
15   -import org.springframework.web.bind.annotation.RequestMapping;
16   -import org.springframework.web.bind.annotation.RestController;
17   -
18   -import java.util.List;
19   -
20   -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
21   -
22   -
23   -@Tag(name = "管理后台 - 排行榜")
24   -@RestController
25   -@RequestMapping("/crm/bi-ranking")
26   -@Validated
27   -public class BiRankingController {
28   -
29   - @Resource
30   - private BiRankingService biRankingService;
31   -
32   - /**
33   - * 合同金额排行榜
34   - */
35   - @GetMapping("/contract-ranking")
36   - @Operation(summary = "合同金额排行榜")
37   - @PreAuthorize("@ss.hasPermission('bi:ranking:query')")
38   - public CommonResult<List<BiRanKingRespVO>> contractAmountRanking(BiRankingReqVO biRankingReqVO) {
39   - return success(biRankingService.contractRanKing(biRankingReqVO));
40   - }
41   -
42   - /**
43   - * 回款金额排行榜
44   - */
45   - @GetMapping("/receivables-ranking")
46   - @Operation(summary = "回款金额排行榜")
47   - @PreAuthorize("@ss.hasPermission('bi:ranking:query')")
48   - public CommonResult<List<BiRanKingRespVO>> receivablesRanKing(BiRankingReqVO biRankingReqVO) {
49   - return success(biRankingService.receivablesRanKing(biRankingReqVO));
50   - }
51   -
52   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.http renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http
1 1 ### 合同金额排行榜
2   -GET {{baseUrl}}/crm/bi-ranking/contract-ranKing
  2 +GET {{baseUrl}}/crm/bi-rank/get-contract-price-rank?deptId=100&times[0]=2022-12-12 00:00:00&times[1]=2024-12-12 23:59:59
3 3 Authorization: Bearer {{token}}
4 4 tenant-id: {{adminTenentId}}
5 5  
6 6 ### 回款金额排行榜
7   -GET {{baseUrl}}/crm/bi-ranking/receivables-ranKing
  7 +GET {{baseUrl}}/crm/bi-rank/get-receivable-price-rank?deptId=100&times[0]=2022-12-12 00:00:00&times[1]=2024-12-12 23:59:59
8 8 Authorization: Bearer {{token}}
9 9 tenant-id: {{adminTenentId}}
10 10 \ No newline at end of file
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.controller.admin.bi;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO;
  6 +import cn.iocoder.yudao.module.crm.service.bi.CrmBiRankingService;
  7 +import io.swagger.v3.oas.annotations.Operation;
  8 +import io.swagger.v3.oas.annotations.tags.Tag;
  9 +import jakarta.annotation.Resource;
  10 +import jakarta.validation.Valid;
  11 +import org.springframework.security.access.prepost.PreAuthorize;
  12 +import org.springframework.validation.annotation.Validated;
  13 +import org.springframework.web.bind.annotation.GetMapping;
  14 +import org.springframework.web.bind.annotation.RequestMapping;
  15 +import org.springframework.web.bind.annotation.RestController;
  16 +
  17 +import java.util.List;
  18 +
  19 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  20 +
  21 +
  22 +@Tag(name = "管理后台 - CRM BI 排行榜")
  23 +@RestController
  24 +@RequestMapping("/crm/bi-rank")
  25 +@Validated
  26 +public class CrmBiRankController {
  27 +
  28 + @Resource
  29 + private CrmBiRankingService rankingService;
  30 +
  31 + @GetMapping("/get-contract-price-rank")
  32 + @Operation(summary = "获得合同金额排行榜")
  33 + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')")
  34 + public CommonResult<List<CrmBiRanKRespVO>> getContractPriceRank(@Valid CrmBiRankReqVO rankingReqVO) {
  35 + return success(rankingService.getContractPriceRank(rankingReqVO));
  36 + }
  37 +
  38 + @GetMapping("/get-receivable-price-rank")
  39 + @Operation(summary = "获得回款金额排行榜")
  40 + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')")
  41 + public CommonResult<List<CrmBiRanKRespVO>> getReceivablePriceRank(@Valid CrmBiRankReqVO rankingReqVO) {
  42 + return success(rankingService.getReceivablePriceRank(rankingReqVO));
  43 + }
  44 +
  45 +}
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiParams.java deleted
1   -package cn.iocoder.yudao.module.crm.controller.admin.bi.vo;
2   -
3   -import cn.iocoder.yudao.framework.common.pojo.PageParam;
4   -import io.swagger.v3.oas.annotations.media.Schema;
5   -import lombok.Data;
6   -import lombok.EqualsAndHashCode;
7   -
8   -// TODO @anhaohao:这个类的命名,还是保持和其它一致使用 ReqVO 结尾;例如说,CrmStatisticsCommonParamReqVO
9   -/**
10   - * @author anhaohao
11   - * bi参数
12   - */
13   -@EqualsAndHashCode(callSuper = true)
14   -@Schema(description = "bi查询相关参数")
15   -@Data
16   -public class BiParams extends PageParam {
17   -
18   - @Schema(description = "部门ID")
19   - private Long deptId;
20   -
21   - @Schema(description = "用户ID")
22   - private Long userId;
23   -
24   - // TODO @anhaohao:这个字段,可以融合到 startTime、endTime 里去,交给前端计算哈;
25   - @Schema(description = "类型")
26   - private String type;
27   -
28   - // TODO @anhaohao:还是使用 LocalDateTime
29   - @Schema(description = "开始时间")
30   - private String startTime;
31   -
32   - @Schema(description = "结束时间")
33   - private String endTime;
34   -
35   -}
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRanKingRespVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRanKRespVO.java
... ... @@ -4,12 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
5 5  
6 6  
7   -@Schema(description = "管理后台 - BI 排行榜 Response VO")
  7 +@Schema(description = "管理后台 - CRM BI 排行榜 Response VO")
8 8 @Data
9   -public class BiRanKingRespVO {
  9 +public class CrmBiRanKRespVO {
10 10  
11   - @Schema(description = "金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
12   - private Integer price;
  11 + @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  12 + private Long ownerUserId;
13 13  
14 14 @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
15 15 private String nickname;
... ... @@ -17,7 +17,13 @@ public class BiRanKingRespVO {
17 17 @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
18 18 private String deptName;
19 19  
20   - @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
21   - private Long ownerUserId;
  20 + /**
  21 + * 数量是个特别“抽象”的概念,在不同排行下,代表不同含义
  22 + *
  23 + * 1. 金额:合同金额排行、回款金额排行
  24 + * 2. 个数:签约合同排行、产品销量排行、产品销量排行、新增客户数排行、新增联系人排行、跟进次数排行、跟进客户数排行
  25 + */
  26 + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  27 + private Integer count;
22 28  
23 29 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRankingReqVO.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.bi.vo;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotEmpty;
  5 +import jakarta.validation.constraints.NotNull;
4 6 import lombok.Data;
5 7 import org.springframework.format.annotation.DateTimeFormat;
6 8  
... ... @@ -9,27 +11,25 @@ import java.util.List;
9 11  
10 12 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
11 13  
12   -/**
13   - * 管理后台 - 排行榜 Request VO
14   - *
15   - * @author anhaohao
16   - */
17   -@Schema(description = "管理后台 - 排行榜 Request VO")
  14 +@Schema(description = "管理后台 - CRM BI 排行榜 Request VO")
18 15 @Data
19   -public class BiRankingReqVO {
  16 +public class CrmBiRankReqVO {
20 17  
21   - @Schema(description = "部门id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  18 + @Schema(description = "部门 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  19 + @NotNull(message = "部门 id 不能为空")
22 20 private Long deptId;
23 21  
24   - @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-12-12 00:00:00")
25   - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
26   - private LocalDateTime startTime;
  22 + /**
  23 + * userIds 目前不用前端传递,目前是方便后端通过 deptId 读取编号后,设置回来
  24 + *
  25 + * 后续,可能会支持选择部分用户进行查询
  26 + */
  27 + @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2")
  28 + private List<Long> userIds;
27 29  
28   - @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-12-12 23:59:59")
  30 + @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.REQUIRED)
29 31 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
30   - private LocalDateTime endTime;
31   -
32   - @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1")
33   - private List<Long> userIds;
  32 + @NotEmpty(message = "时间范围不能为空")
  33 + private LocalDateTime[] times;
34 34  
35 35 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java
... ... @@ -45,7 +45,6 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
45 45 public class CrmContractController {
46 46  
47 47 @Resource
48   - @Lazy
49 48 private CrmContractService contractService;
50 49 @Resource
51 50 private CrmCustomerService customerService;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java
... ... @@ -26,7 +26,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
26 26 import jakarta.annotation.Resource;
27 27 import jakarta.servlet.http.HttpServletResponse;
28 28 import jakarta.validation.Valid;
29   -import org.springframework.context.annotation.Lazy;
30 29 import org.springframework.security.access.prepost.PreAuthorize;
31 30 import org.springframework.validation.annotation.Validated;
32 31 import org.springframework.web.bind.annotation.*;
... ... @@ -52,7 +51,6 @@ public class CrmReceivableController {
52 51 @Resource
53 52 private CrmReceivableService receivableService;
54 53 @Resource
55   - @Lazy
56 54 private CrmContractService contractService;
57 55 @Resource
58 56 private CrmCustomerService customerService;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/BiRankingMapper.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java
1 1 package cn.iocoder.yudao.module.crm.dal.mysql.bi;
2 2  
3   -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4   -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO;
5   -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO;
  3 +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO;
6 5 import org.apache.ibatis.annotations.Mapper;
7 6  
8 7 import java.util.List;
9 8  
10 9 /**
  10 + * CRM BI 排行榜 Mapper
  11 + *
11 12 * @author anhaohao
12 13 */
13 14 @Mapper
14   -public interface BiRankingMapper extends BaseMapperX {
  15 +public interface CrmBiRankingMapper {
  16 +
15 17 /**
16   - * 合同金额排行榜
  18 + * 查询合同金额排行榜
17 19 *
18   - * @param biRankingReqVO 参数
19   - * @return List<BiContractAmountRankingRespVO>
  20 + * @param rankReqVO 参数
  21 + * @return 合同金额排行榜
20 22 */
21   - List<BiRanKingRespVO> contractRanKing(BiRankingReqVO biRankingReqVO);
22   -
  23 + List<CrmBiRanKRespVO> selectContractPriceRank(CrmBiRankReqVO rankReqVO);
23 24  
24 25 /**
25   - * 回款金额排行榜
  26 + * 查询回款金额排行榜
26 27 *
27   - * @param biRankingReqVO 参数
28   - * @return List<BiContractAmountRankingRespVO>
  28 + * @param rankReqVO 参数
  29 + * @return 回款金额排行榜
29 30 */
30   - List<BiRanKingRespVO> receivablesRanKing(BiRankingReqVO biRankingReqVO);
  31 + List<CrmBiRanKRespVO> selectReceivablePriceRank(CrmBiRankReqVO rankReqVO);
  32 +
31 33 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java
... ... @@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.crm.service.contract.CrmContractService;
6 6 import com.mzt.logapi.service.IParseFunction;
7 7 import jakarta.annotation.Resource;
8 8 import lombok.extern.slf4j.Slf4j;
9   -import org.springframework.context.annotation.Lazy;
10 9 import org.springframework.stereotype.Component;
11 10  
12 11 /**
... ... @@ -21,7 +20,6 @@ public class CrmContractParseFunction implements IParseFunction {
21 20 public static final String NAME = "getContractById";
22 21  
23 22 @Resource
24   - @Lazy
25 23 private CrmContractService contractService;
26 24  
27 25 @Override
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingServiceImpl.java deleted
1   -package cn.iocoder.yudao.module.crm.service.bi;
2   -
3   -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
4   -
5   -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO;
6   -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO;
7   -import cn.iocoder.yudao.module.crm.dal.mysql.bi.BiRankingMapper;
8   -import cn.iocoder.yudao.module.system.api.dept.DeptApi;
9   -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
10   -import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
11   -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
12   -import jakarta.annotation.Resource;
13   -import org.springframework.stereotype.Service;
14   -import org.springframework.validation.annotation.Validated;
15   -
16   -import java.util.ArrayList;
17   -import java.util.List;
18   -import java.util.Map;
19   -import java.util.function.Function;
20   -import java.util.stream.Collectors;
21   -
22   -@Service(value = "biRankingService")
23   -@Validated
24   -public class BiRankingServiceImpl implements BiRankingService {
25   -
26   - @Resource
27   - private BiRankingMapper biRankingMapper;
28   - @Resource
29   - private AdminUserApi adminUserApi;
30   - @Resource
31   - private DeptApi deptApi;
32   -
33   - @Override
34   - public List<BiRanKingRespVO> contractRanKing(BiRankingReqVO biRankingReqVO) {
35   - return processRanking(biRankingReqVO, biRankingMapper::contractRanKing);
36   - }
37   -
38   - @Override
39   - public List<BiRanKingRespVO> receivablesRanKing(BiRankingReqVO biRankingReqVO) {
40   - return processRanking(biRankingReqVO, biRankingMapper::receivablesRanKing);
41   - }
42   -
43   - /**
44   - * 处理排行榜
45   - *
46   - * @param biRankingReqVO 参数
47   - * @param rankingFunction 排行榜方法
48   - * @return List<BiRanKingRespVO>
49   - */
50   - private List<BiRanKingRespVO> processRanking(BiRankingReqVO biRankingReqVO, Function<BiRankingReqVO, List<BiRanKingRespVO>> rankingFunction) {
51   - analyzeAuth(biRankingReqVO);
52   - if (biRankingReqVO.getUserIds().isEmpty()) {
53   - return new ArrayList<>();
54   - }
55   - List<BiRanKingRespVO> biRanKingRespVOS = rankingFunction.apply(biRankingReqVO);
56   - return setName(biRanKingRespVOS);
57   - }
58   -
59   - /**
60   - * 设置用户名称
61   - *
62   - * @param biRanKingRespVOS 排行榜数据
63   - * @return List<BiRanKingRespVO>
64   - */
65   - private List<BiRanKingRespVO> setName(List<BiRanKingRespVO> biRanKingRespVOS) {
66   - List<Long> userIds = biRanKingRespVOS.stream().map(BiRanKingRespVO::getOwnerUserId).collect(Collectors.toList());
67   - Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
68   - Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(userMap.values().stream().map(AdminUserRespDTO::getDeptId).collect(Collectors.toList()));
69   - for (BiRanKingRespVO biRanKingRespVO : biRanKingRespVOS) {
70   - AdminUserRespDTO adminUserRespDTO = userMap.get(biRanKingRespVO.getOwnerUserId());
71   - if (adminUserRespDTO != null) {
72   - biRanKingRespVO.setNickname(adminUserRespDTO.getNickname());
73   - DeptRespDTO deptRespDTO = deptMap.get(adminUserRespDTO.getDeptId());
74   - if (deptRespDTO != null) {
75   - biRanKingRespVO.setDeptName(deptRespDTO.getName());
76   - }
77   - }
78   - }
79   - return biRanKingRespVOS;
80   - }
81   -
82   - /**
83   - * 分析权限
84   - *
85   - * @param biRankingReqVO 参数
86   - */
87   - public void analyzeAuth(BiRankingReqVO biRankingReqVO) {
88   - Long deptId = biRankingReqVO.getDeptId() == null ? adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()).getDeptId() : biRankingReqVO.getDeptId();
89   - List<Long> deptIds = deptApi.getChildDeptList(deptId).stream().map(DeptRespDTO::getId).collect(Collectors.toList());
90   - deptIds.add(deptId);
91   - biRankingReqVO.setUserIds(adminUserApi.getUserListByDeptIds(deptIds).stream().map(AdminUserRespDTO::getId).collect(Collectors.toList()));
92   - }
93   -}
94 0 \ No newline at end of file
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingService.java renamed to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java
1 1 package cn.iocoder.yudao.module.crm.service.bi;
2 2  
3 3  
4   -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO;
5   -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO;
  4 +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO;
6 6  
7 7 import java.util.List;
8 8  
9 9 /**
10   - * BI 排行榜 Service 接口
  10 + * CRM BI 排行榜 Service 接口
11 11 *
12 12 * @author anhaohao
13 13 */
14   -public interface BiRankingService {
  14 +public interface CrmBiRankingService {
15 15  
16 16 /**
17   - * 合同金额排行榜
  17 + * 获得合同金额排行榜
18 18 *
19   - * @param biRankingReqVO 参数
20   - * @return List<BiContractAmountRankingRespVO>
  19 + * @param rankReqVO 排行参数
  20 + * @return 合同金额排行榜
21 21 */
22   - List<BiRanKingRespVO> contractRanKing(BiRankingReqVO biRankingReqVO);
  22 + List<CrmBiRanKRespVO> getContractPriceRank(CrmBiRankReqVO rankReqVO);
23 23  
24 24 /**
25   - * 回款金额排行榜
  25 + * 获得回款金额排行榜
26 26 *
27   - * @param biRankingReqVO 参数
28   - * @return List<BiContractAmountRankingRespVO>
  27 + * @param rankReqVO 排行参数
  28 + * @return 回款金额排行榜
29 29 */
30   - List<BiRanKingRespVO> receivablesRanKing(BiRankingReqVO biRankingReqVO);
  30 + List<CrmBiRanKRespVO> getReceivablePriceRank(CrmBiRankReqVO rankReqVO);
  31 +
31 32 }
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.crm.service.bi;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
  5 +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO;
  6 +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO;
  7 +import cn.iocoder.yudao.module.crm.dal.mysql.bi.CrmBiRankingMapper;
  8 +import cn.iocoder.yudao.module.system.api.dept.DeptApi;
  9 +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
  10 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  11 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
  12 +import jakarta.annotation.Resource;
  13 +import org.springframework.stereotype.Service;
  14 +import org.springframework.validation.annotation.Validated;
  15 +
  16 +import java.util.Collections;
  17 +import java.util.Comparator;
  18 +import java.util.List;
  19 +import java.util.Map;
  20 +import java.util.function.Function;
  21 +
  22 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  23 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  24 +
  25 +/**
  26 + * CRM BI 排行榜 Service 实现类
  27 + *
  28 + * @author anhaohao
  29 + */
  30 +@Service
  31 +@Validated
  32 +public class CrmBiRankingServiceImpl implements CrmBiRankingService {
  33 +
  34 + @Resource
  35 + private CrmBiRankingMapper biRankingMapper;
  36 +
  37 + @Resource
  38 + private AdminUserApi adminUserApi;
  39 + @Resource
  40 + private DeptApi deptApi;
  41 +
  42 + @Override
  43 + public List<CrmBiRanKRespVO> getContractPriceRank(CrmBiRankReqVO rankReqVO) {
  44 + return getRank(rankReqVO, biRankingMapper::selectContractPriceRank);
  45 + }
  46 +
  47 + @Override
  48 + public List<CrmBiRanKRespVO> getReceivablePriceRank(CrmBiRankReqVO rankReqVO) {
  49 + return getRank(rankReqVO, biRankingMapper::selectReceivablePriceRank);
  50 + }
  51 +
  52 + /**
  53 + * 获得排行版数据
  54 + *
  55 + * @param rankReqVO 参数
  56 + * @param rankFunction 排行榜方法
  57 + * @return 排行版数据
  58 + */
  59 + private List<CrmBiRanKRespVO> getRank(CrmBiRankReqVO rankReqVO, Function<CrmBiRankReqVO, List<CrmBiRanKRespVO>> rankFunction) {
  60 + // 1. 获得用户编号数组
  61 + rankReqVO.setUserIds(getUserIds(rankReqVO.getDeptId()));
  62 + if (CollUtil.isEmpty(rankReqVO.getUserIds())) {
  63 + return Collections.emptyList();
  64 + }
  65 + // 2. 获得排行数据
  66 + List<CrmBiRanKRespVO> ranks = rankFunction.apply(rankReqVO);
  67 + if (CollUtil.isEmpty(ranks)) {
  68 + return Collections.emptyList();
  69 + }
  70 + ranks.sort(Comparator.comparing(CrmBiRanKRespVO::getCount).reversed());
  71 + // 3. 拼接用户信息
  72 + appendUserInfo(ranks);
  73 + return ranks;
  74 + }
  75 +
  76 + /**
  77 + * 拼接用户信息(昵称、部门)
  78 + *
  79 + * @param ranks 排行榜数据
  80 + */
  81 + private void appendUserInfo(List<CrmBiRanKRespVO> ranks) {
  82 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSet(ranks, CrmBiRanKRespVO::getOwnerUserId));
  83 + Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
  84 + ranks.forEach(rank -> MapUtils.findAndThen(userMap, rank.getOwnerUserId(), user -> {
  85 + rank.setNickname(user.getNickname());
  86 + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> rank.setDeptName(dept.getName()));
  87 + }));
  88 + }
  89 +
  90 + /**
  91 + * 获得部门下的用户编号数组,包括子部门的
  92 + *
  93 + * @param deptId 部门编号
  94 + * @return 用户编号数组
  95 + */
  96 + public List<Long> getUserIds(Long deptId) {
  97 + // 1. 获得部门列表
  98 + List<Long> deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId);
  99 + deptIds.add(deptId);
  100 + // 2. 获得用户编号
  101 + return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId);
  102 + }
  103 +
  104 +}
0 105 \ No newline at end of file
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java
... ... @@ -57,7 +57,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService {
57 57 @Resource
58 58 private CrmBusinessProductService businessProductService;
59 59 @Resource
60   - @Lazy
  60 + @Lazy // 延迟加载,避免循环依赖
61 61 private CrmContractService contractService;
62 62 @Resource
63 63 private CrmPermissionService permissionService;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
... ... @@ -25,7 +25,6 @@ import com.mzt.logapi.context.LogRecordContext;
25 25 import com.mzt.logapi.service.impl.DiffParseFunction;
26 26 import com.mzt.logapi.starter.annotation.LogRecord;
27 27 import jakarta.annotation.Resource;
28   -import org.springframework.context.annotation.Lazy;
29 28 import org.springframework.stereotype.Service;
30 29 import org.springframework.transaction.annotation.Transactional;
31 30 import org.springframework.validation.annotation.Validated;
... ... @@ -57,7 +56,6 @@ public class CrmContactServiceImpl implements CrmContactService {
57 56 @Resource
58 57 private CrmPermissionService permissionService;
59 58 @Resource
60   - @Lazy
61 59 private CrmContractService contractService;
62 60 @Resource
63 61 private CrmContactBusinessService contactBusinessService;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java
... ... @@ -50,7 +50,6 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService {
50 50 private CrmReceivablePlanMapper receivablePlanMapper;
51 51  
52 52 @Resource
53   - @Lazy
54 53 private CrmContractService contractService;
55 54 @Resource
56 55 private CrmCustomerService customerService;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
... ... @@ -51,7 +51,6 @@ public class CrmReceivableServiceImpl implements CrmReceivableService {
51 51 private CrmReceivableMapper receivableMapper;
52 52  
53 53 @Resource
54   - @Lazy
55 54 private CrmContractService contractService;
56 55 @Resource
57 56 private CrmCustomerService customerService;
... ...
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/BiRankingMapper.xml deleted
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3   -<mapper namespace="cn.iocoder.yudao.module.crm.dal.mysql.bi.BiRankingMapper">
4   -
5   -
6   - <select id="contractRanKing"
7   - resultType="cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO">
8   - SELECT IFNULL(SUM(t.price), 0) AS price, t.owner_user_id
9   - FROM crm_contract t
10   - WHERE t.deleted = 0
11   - AND t.audit_status = 20
12   - and t.owner_user_id in
13   - <foreach collection="userIds" item="item" open="(" close=")" separator=",">
14   - #{item}
15   - </foreach>
16   - AND t.order_date between #{startTime} and #{endTime}
17   - GROUP BY t.owner_user_id
18   - ORDER BY price DESC
19   - </select>
20   -
21   - <select id="receivablesRanKing"
22   - resultType="cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO">
23   - SELECT IFNULL(SUM(t.price), 0) AS price, t.owner_user_id
24   - FROM crm_receivable t
25   - WHERE t.deleted = 0
26   - AND t.audit_status = 20
27   - and t.owner_user_id in
28   - <foreach collection="userIds" item="item" open="(" close=")" separator=",">
29   - #{item}
30   - </foreach>
31   - AND t.return_time between #{startTime} and #{endTime}
32   - GROUP BY t.owner_user_id
33   - ORDER BY price DESC
34   - </select>
35   -</mapper>
yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3 +<mapper namespace="cn.iocoder.yudao.module.crm.dal.mysql.bi.CrmBiRankingMapper">
  4 +
  5 + <select id="selectContractPriceRank"
  6 + resultType="cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO">
  7 + SELECT IFNULL(SUM(price), 0) AS count, owner_user_id
  8 + FROM crm_contract
  9 + WHERE deleted = 0
  10 + AND audit_status = 20
  11 + and owner_user_id in
  12 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  13 + #{userId}
  14 + </foreach>
  15 + AND order_date between #{times[0],javaType=java.time.LocalDateTime} and #{times[1],javaType=java.time.LocalDateTime}
  16 + GROUP BY owner_user_id
  17 + </select>
  18 +
  19 + <select id="selectReceivablePriceRank"
  20 + resultType="cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO">
  21 + SELECT IFNULL(SUM(price), 0) AS count, owner_user_id
  22 + FROM crm_receivable
  23 + WHERE deleted = 0
  24 + AND audit_status = 20
  25 + and owner_user_id in
  26 + <foreach collection="userIds" item="userId" open="(" close=")" separator=",">
  27 + #{userId}
  28 + </foreach>
  29 + AND return_time between #{times[0],javaType=java.time.LocalDateTime} and #{times[1],javaType=java.time.LocalDateTime}
  30 + GROUP BY owner_user_id
  31 + </select>
  32 +
  33 +</mapper>
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java
... ... @@ -44,6 +44,9 @@ public class AuthPermissionInfoRespVO {
44 44 @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.jpg")
45 45 private String avatar;
46 46  
  47 + @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
  48 + private Long deptId;
  49 +
47 50 }
48 51  
49 52 @Schema(description = "管理后台 - 登录用户的菜单信息 Response VO")
... ...
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java
1 1 package cn.iocoder.yudao.module.system.convert.auth;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
4 5 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
5 6 import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
6 7 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
... ... @@ -29,7 +30,7 @@ public interface AuthConvert {
29 30  
30 31 default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) {
31 32 return AuthPermissionInfoRespVO.builder()
32   - .user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build())
  33 + .user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class))
33 34 .roles(convertSet(roleList, RoleDO::getCode))
34 35 // 权限标识信息
35 36 .permissions(convertSet(menuList, MenuDO::getPermission))
... ...
yudao-server/pom.xml
... ... @@ -46,11 +46,11 @@
46 46 <!-- <version>${revision}</version>-->
47 47 <!-- </dependency>-->
48 48 <!-- 工作流。默认注释,保证编译速度 -->
49   -<!-- <dependency>-->
50   -<!-- <groupId>cn.iocoder.boot</groupId>-->
51   -<!-- <artifactId>yudao-module-bpm-biz</artifactId>-->
52   -<!-- <version>${revision}</version>-->
53   -<!-- </dependency>-->
  49 + <dependency>
  50 + <groupId>cn.iocoder.boot</groupId>
  51 + <artifactId>yudao-module-bpm-biz</artifactId>
  52 + <version>${revision}</version>
  53 + </dependency>
54 54 <!-- 支付服务。默认注释,保证编译速度 -->
55 55 <!-- <dependency>-->
56 56 <!-- <groupId>cn.iocoder.boot</groupId>-->
... ...