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