mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-01 02:38:43 +08:00 
			
		
		
		
	!861 修改:CRM 商业智能,合并模块到 crm,优化查询
Merge pull request !861 from 安浩浩/develop
This commit is contained in:
		| @@ -10,8 +10,6 @@ | ||||
|     <modules> | ||||
|         <module>yudao-module-crm-api</module> | ||||
|         <module>yudao-module-crm-biz</module> | ||||
|         <module>yudao-module-bi-biz</module> | ||||
|         <module>yudao-module-bi-api</module> | ||||
|     </modules> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
|     <artifactId>yudao-module-crm</artifactId> | ||||
|   | ||||
| @@ -1,73 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||
|          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
|          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <parent> | ||||
|         <groupId>cn.iocoder.boot</groupId> | ||||
|         <artifactId>yudao-module-crm</artifactId> | ||||
|         <version>${revision}</version> | ||||
|     </parent> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
|     <artifactId>yudao-module-bi-api</artifactId> | ||||
|  | ||||
|     <name>${project.artifactId}</name> | ||||
|     <description> | ||||
|         bi 模块 API,暴露给其它模块调用 | ||||
|     </description> | ||||
|  | ||||
|     <dependencies> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-module-system-api</artifactId> | ||||
|             <version>${revision}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-module-crm-api</artifactId> | ||||
|             <version>${revision}</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- 业务组件 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-biz-ip</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- Web 相关 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-web</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-security</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- DB 相关 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-mybatis</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- 工具类相关 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-excel</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-biz-dict</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- Test 测试相关 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-test</artifactId> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
| </project> | ||||
| @@ -1 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bi.api; | ||||
| @@ -1 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bi.enums; | ||||
| @@ -1,74 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||
|          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
|          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
|     <parent> | ||||
|         <groupId>cn.iocoder.boot</groupId> | ||||
|         <artifactId>yudao-module-crm</artifactId> | ||||
|         <version>${revision}</version> | ||||
|     </parent> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
|     <artifactId>yudao-module-bi-biz</artifactId> | ||||
|  | ||||
|     <name>${project.artifactId}</name> | ||||
|     <description> | ||||
|         crm 包下,商业智能(Business Intelligence)。 | ||||
|         例如说:报表、图表、数据分析等等 | ||||
|     </description> | ||||
|  | ||||
|     <dependencies> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-module-system-api</artifactId> | ||||
|             <version>${revision}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-module-crm-api</artifactId> | ||||
|             <version>${revision}</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- 业务组件 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-biz-ip</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- Web 相关 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-web</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-security</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- DB 相关 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-mybatis</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- 工具类相关 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-excel</artifactId> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-biz-dict</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- Test 测试相关 --> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-spring-boot-starter-test</artifactId> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
| </project> | ||||
| @@ -1,26 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
| // TODO @anhaohao:VO 类有 swagger 注解,不写注释哈 | ||||
| /** | ||||
|  * 管理后台 - BI 排行榜 Response VO | ||||
|  * | ||||
|  * @author anhaohao | ||||
|  */ | ||||
| @Schema(description = "管理后台 - BI 合同金额排行榜 Response VO") | ||||
| @Data | ||||
| public class BiContractRanKingRespVO { | ||||
|  | ||||
|     // TODO @anhaohao:如果一定返回的字段,需要加 requiredMode = Schema.RequiredMode.REQUIRED, 哈 | ||||
|     @Schema(description = "金额", example = "1") | ||||
|     private Integer price; | ||||
|  | ||||
|     @Schema(description = "姓名", example = "1") | ||||
|     private String nickname; | ||||
|  | ||||
|     @Schema(description = "部门名称", example = "1") | ||||
|     private String deptName; | ||||
|  | ||||
| } | ||||
| @@ -1,22 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
| /** | ||||
|  * 管理后台 - 排行榜 Request VO | ||||
|  * | ||||
|  * @author anhaohao | ||||
|  */ | ||||
| @Schema(description = "管理后台 - 排行榜 Request VO") | ||||
| @Data | ||||
| public class BiRankReqVO { | ||||
|  | ||||
|     @Schema(description = "部门id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Long deptId; | ||||
|  | ||||
|     // TODO @anhaohao:这个字段,参考 BiParams 的 type 建议 | ||||
|     @Schema(description = "分析类型(1.今天 2.昨天 3.本周 4.上周 5.本月 6.上月 7.本季度 8.上季度 9.本年 10 上年)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private String type; | ||||
|  | ||||
| } | ||||
| @@ -1,25 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
| // TODO @anhaohao:参考 BiContractRanKingRespVO 的建议 | ||||
| /** | ||||
|  * 管理后台 - BI 排行榜 Response VO | ||||
|  * | ||||
|  * @author anhaohao | ||||
|  */ | ||||
| @Schema(description = "管理后台 - BI 合同金额排行榜 Response VO") | ||||
| @Data | ||||
| public class BiReceivablesRanKingRespVO { | ||||
|  | ||||
|     @Schema(description = "金额", example = "100") | ||||
|     private Integer price; | ||||
|  | ||||
|     @Schema(description = "姓名", example = "张三") | ||||
|     private String nickname; | ||||
|  | ||||
|     @Schema(description = "部门名称", example = "研发部") | ||||
|     private String deptName; | ||||
|  | ||||
| } | ||||
| @@ -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.bi.controller; | ||||
| @@ -1,31 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bi.dal.mysql; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; | ||||
| import cn.iocoder.yudao.module.bi.util.BiTimeUtil; | ||||
| import org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * @author anhaohao | ||||
|  */ | ||||
| @Mapper | ||||
| public interface BiRankingMapper extends BaseMapperX { | ||||
|     /** | ||||
|      * 合同金额排行榜 | ||||
|      * | ||||
|      * @param biTimeEntity 参数 | ||||
|      * @return List<BiContractAmountRankingRespVO> | ||||
|      */ | ||||
|     List<BiContractRanKingRespVO> contractRanKing(BiTimeUtil.BiTimeEntity biTimeEntity); | ||||
|  | ||||
|     /** | ||||
|      * 回款金额排行榜 | ||||
|      * | ||||
|      * @param biTimeEntity 参数 | ||||
|      * @return List<BiContractAmountRankingRespVO> | ||||
|      */ | ||||
|     List<BiReceivablesRanKingRespVO> receivablesRanKing(BiTimeUtil.BiTimeEntity biTimeEntity); | ||||
| } | ||||
| @@ -1,6 +0,0 @@ | ||||
| /** | ||||
|  * 属于 bi 模块的 framework 封装 | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| package cn.iocoder.yudao.module.bi.framework; | ||||
| @@ -1,24 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bi.framework.web.config; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration; | ||||
| import org.springdoc.core.models.GroupedOpenApi; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
|  | ||||
| /** | ||||
|  * bi 模块的 web 组件的 Configuration | ||||
|  * | ||||
|  * @author 芋道源码 | ||||
|  */ | ||||
| @Configuration(proxyBeanMethods = false) | ||||
| public class BiWebConfiguration { | ||||
|  | ||||
|     /** | ||||
|      * bi 模块的 API 分组 | ||||
|      */ | ||||
|     @Bean | ||||
|     public GroupedOpenApi biGroupedOpenApi() { | ||||
|         return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("bi"); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,4 +0,0 @@ | ||||
| /** | ||||
|  * bi 模块的 web 配置 | ||||
|  */ | ||||
| package cn.iocoder.yudao.module.bi.framework.web; | ||||
| @@ -1,10 +0,0 @@ | ||||
| /** | ||||
|  * crm 包下,商业智能(Business Intelligence)。 | ||||
|  * 例如说:报表、图表、数据分析等等 | ||||
|  * <p> | ||||
|  * 1. Controller URL:以 /bi/ 开头,避免和其它 Module 冲突 | ||||
|  * | ||||
|  * TODO @anhaohao:mall 当时独立拆分一个 statistics 模块的原因,是因为 mall 拆分了多个模块,没有模块适合承接统计的能力,所以独立了。 | ||||
|  * TODO crm 因为没有拆分,所以可以直接放在 crm 模块下面;这样,我们可以在 controller/admin 和 service 下,新建一个 bi 包,专门放置统计的代码。 | ||||
|  */ | ||||
| package cn.iocoder.yudao.module.bi; | ||||
| @@ -1,30 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bi.service.ranking; | ||||
|  | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * BI 排行榜 Service 接口 | ||||
|  * | ||||
|  * @author anhaohao | ||||
|  */ | ||||
| public interface BiRankingService { // TODO @anhaohao:第一个方法,和类要有一个空行 | ||||
|     /** | ||||
|      * 合同金额排行榜 | ||||
|      * | ||||
|      * @param biRankReqVO 参数 | ||||
|      * @return List<BiContractAmountRankingRespVO> | ||||
|      */ | ||||
|     List<BiContractRanKingRespVO> contractRanKing(BiRankReqVO biRankReqVO); | ||||
|  | ||||
|     /** | ||||
|      * 回款金额排行榜 | ||||
|      * | ||||
|      * @param biRankReqVO 参数 | ||||
|      * @return List<BiContractAmountRankingRespVO> | ||||
|      */ | ||||
|     List<BiReceivablesRanKingRespVO> receivablesRanKing(BiRankReqVO biRankReqVO); | ||||
| } | ||||
| @@ -1,53 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bi.service.ranking; | ||||
|  | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiParams; | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; | ||||
| import cn.iocoder.yudao.module.bi.dal.mysql.BiRankingMapper; | ||||
| import cn.iocoder.yudao.module.bi.util.BiTimeUtil; | ||||
| import jakarta.annotation.Resource; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * @author anhaohao | ||||
|  */ | ||||
| @Service(value = "biRankService") | ||||
| @Validated | ||||
| public class BiRankingServiceImpl implements BiRankingService { | ||||
|  | ||||
|     @Resource | ||||
|     private BiRankingMapper biRankingMapper; | ||||
|  | ||||
|     @Override | ||||
|     public List<BiContractRanKingRespVO> contractRanKing(BiRankReqVO biRankReqVO) { | ||||
|         BiParams biParams = new BiParams(); | ||||
|         biParams.setType(biRankReqVO.getType()); | ||||
|         biParams.setDeptId(biRankReqVO.getDeptId()); | ||||
|         biParams.setIsUser(0); | ||||
|         BiTimeUtil.BiTimeEntity biTimeEntity = BiTimeUtil.analyzeType(biParams); | ||||
|         List<Long> userIds = biTimeEntity.getUserIds(); | ||||
|         if (userIds.isEmpty()) { | ||||
|             return new ArrayList<>(); | ||||
|         } | ||||
|         return biRankingMapper.contractRanKing(biTimeEntity); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<BiReceivablesRanKingRespVO> receivablesRanKing(BiRankReqVO biRankReqVO) { | ||||
|         BiParams biParams = new BiParams(); | ||||
|         biParams.setType(biRankReqVO.getType()); | ||||
|         biParams.setDeptId(biRankReqVO.getDeptId()); | ||||
|         biParams.setIsUser(0); | ||||
|         BiTimeUtil.BiTimeEntity biTimeEntity = BiTimeUtil.analyzeType(biParams); | ||||
|         List<Long> userIds = biTimeEntity.getUserIds(); | ||||
|         if (userIds.isEmpty()) { | ||||
|             return new ArrayList<>(); | ||||
|         } | ||||
|         return biRankingMapper.receivablesRanKing(biTimeEntity); | ||||
|     } | ||||
| } | ||||
| @@ -1,250 +0,0 @@ | ||||
| package cn.iocoder.yudao.module.bi.util; | ||||
|  | ||||
| import cn.hutool.core.date.DateUnit; | ||||
| import cn.hutool.core.date.DateUtil; | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.hutool.extra.spring.SpringUtil; | ||||
| import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiParams; | ||||
| import cn.iocoder.yudao.module.system.api.dept.DeptApi; | ||||
| import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; | ||||
| import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||||
| import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | ||||
| import lombok.Data; | ||||
| import lombok.experimental.Accessors; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Date; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * bi时间工具类 | ||||
|  * | ||||
|  * @author anhaohao | ||||
|  */ | ||||
| public class BiTimeUtil { | ||||
|  | ||||
|     public static BiTimeEntity analyzeType(BiParams biParams) { | ||||
|         // 解析时间 | ||||
|         BiTimeEntity biTimeEntity = analyzeTime(biParams); | ||||
|         // 解析权限 | ||||
|         // TODO @anhaohao:涉及到数据的读取,不放在 Util 里,还是搞会到 Service 哈; | ||||
|         biTimeEntity.setUserIds(analyzeAuth(biParams)); | ||||
|         return biTimeEntity; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 解析权限 | ||||
|      * | ||||
|      * @param biParams bi参数 | ||||
|      * @return List<Long> | ||||
|      */ | ||||
|     public static List<Long> analyzeAuth(BiParams biParams) { | ||||
|         List<Long> userIdList = new ArrayList<>(); | ||||
|         Long deptId = biParams.getDeptId(); | ||||
|         Long userId = biParams.getUserId(); | ||||
|         Integer isUser = biParams.getIsUser(); | ||||
|         // 获取部门和用户的api | ||||
|         DeptApi deptApi = SpringUtil.getBean("deptApiImpl"); | ||||
|         AdminUserApi adminUserApi = SpringUtil.getBean("adminUserApiImpl"); | ||||
|         // 0.部门 1.用户 | ||||
|         if (isUser == 0) { | ||||
|             if (deptId == null) { | ||||
|                 deptId = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()).getDeptId(); | ||||
|             } | ||||
|             List<DeptRespDTO> childDeptList = deptApi.getChildDeptList(deptId); | ||||
|             List<Long> deptIds = new ArrayList<>(); | ||||
|             deptIds.add(deptId); | ||||
|             if (childDeptList != null && !childDeptList.isEmpty()) { | ||||
|                 for (DeptRespDTO deptRespDTO : childDeptList) { | ||||
|                     deptIds.add(deptRespDTO.getId()); | ||||
|                 } | ||||
|             } | ||||
|             // 获取部门下的用户 | ||||
|             adminUserApi.getUserListByDeptIds(deptIds).forEach(adminUserRespDTO -> userIdList.add(adminUserRespDTO.getId())); | ||||
|         } else { | ||||
|             if (userId == null) { | ||||
|                 List<AdminUserRespDTO> userListBySubordinate = adminUserApi.getUserListBySubordinate(SecurityFrameworkUtils.getLoginUserId()); | ||||
|                 userListBySubordinate.forEach(adminUserRespDTO -> userIdList.add(adminUserRespDTO.getId())); | ||||
|             } else { | ||||
|                 userIdList.add(userId); | ||||
|             } | ||||
|         } | ||||
|         return userIdList; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * 解析时间 | ||||
|      * | ||||
|      * @param biParams bi参数 | ||||
|      * @return BiTimeEntity | ||||
|      */ | ||||
|     public static BiTimeEntity analyzeTime(BiParams biParams) { | ||||
|         Date beginDate = DateUtil.date(); | ||||
|         Date endDate = DateUtil.date(); | ||||
|         int cycleNum = 12; | ||||
|         String sqlDateFormat = "%Y%m"; | ||||
|         String dateFormat = "yyyyMM"; | ||||
|         String type = biParams.getType(); | ||||
|         String startTime = biParams.getStartTime(); | ||||
|         String endTime = biParams.getEndTime(); | ||||
|         if (StrUtil.isNotEmpty(type)) { | ||||
|             //1.今天 2.昨天 3.本周 4.上周 5.本月 6.上月 7.本季度 8.上季度 9.本年 10 上年 | ||||
|             switch (type) { | ||||
|                 case "1": | ||||
|                     beginDate = DateUtil.beginOfDay(DateUtil.date()); | ||||
|                     endDate = DateUtil.endOfDay(DateUtil.date()); | ||||
|                     sqlDateFormat = "%Y%m%d"; | ||||
|                     dateFormat = "yyyyMMdd"; | ||||
|                     cycleNum = 1; | ||||
|                     break; | ||||
|                 case "2": | ||||
|                     beginDate = DateUtil.beginOfDay(new Date(System.currentTimeMillis() - 86400000)); | ||||
|                     endDate = DateUtil.endOfDay(new Date(System.currentTimeMillis() - 86400000)); | ||||
|                     sqlDateFormat = "%Y%m%d"; | ||||
|                     dateFormat = "yyyyMMdd"; | ||||
|                     cycleNum = 1; | ||||
|                     break; | ||||
|                 case "3": | ||||
|                     beginDate = DateUtil.beginOfWeek(DateUtil.date()); | ||||
|                     endDate = DateUtil.endOfWeek(DateUtil.date()); | ||||
|                     sqlDateFormat = "%Y%m%d"; | ||||
|                     dateFormat = "yyyyMMdd"; | ||||
|                     cycleNum = 7; | ||||
|                     break; | ||||
|                 case "4": | ||||
|                     beginDate = DateUtil.beginOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)); | ||||
|                     endDate = DateUtil.endOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)); | ||||
|                     sqlDateFormat = "%Y%m%d"; | ||||
|                     dateFormat = "yyyyMMdd"; | ||||
|                     cycleNum = 7; | ||||
|                     break; | ||||
|                 case "5": | ||||
|                     beginDate = DateUtil.beginOfMonth(DateUtil.date()); | ||||
|                     endDate = DateUtil.endOfMonth(DateUtil.date()); | ||||
|                     sqlDateFormat = "%Y%m%d"; | ||||
|                     dateFormat = "yyyyMMdd"; | ||||
|                     cycleNum = (int) DateUtil.between(beginDate, endDate, DateUnit.DAY) + 1; | ||||
|                     break; | ||||
|                 case "6": | ||||
|                     beginDate = DateUtil.beginOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1)); | ||||
|                     endDate = DateUtil.endOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1)); | ||||
|                     sqlDateFormat = "%Y%m%d"; | ||||
|                     dateFormat = "yyyyMMdd"; | ||||
|                     cycleNum = (int) DateUtil.between(beginDate, endDate, DateUnit.DAY) + 1; | ||||
|                     break; | ||||
|                 case "7": | ||||
|                     beginDate = DateUtil.beginOfQuarter(DateUtil.date()); | ||||
|                     endDate = DateUtil.endOfQuarter(DateUtil.date()); | ||||
|                     cycleNum = 3; | ||||
|                     break; | ||||
|                 case "8": | ||||
|                     beginDate = DateUtil.beginOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3)); | ||||
|                     endDate = DateUtil.endOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3)); | ||||
|                     cycleNum = 3; | ||||
|                     break; | ||||
|                 case "9": | ||||
|                     beginDate = DateUtil.beginOfYear(DateUtil.date()); | ||||
|                     endDate = DateUtil.endOfYear(DateUtil.date()); | ||||
|                     break; | ||||
|                 case "10": | ||||
|                     beginDate = DateUtil.beginOfYear(DateUtil.offsetMonth(DateUtil.date(), -12)); | ||||
|                     endDate = DateUtil.endOfYear(DateUtil.offsetMonth(DateUtil.date(), -12)); | ||||
|                     break; | ||||
|                 default: | ||||
|                     break; | ||||
|             } | ||||
|         } else if (StrUtil.isNotEmpty(startTime) && StrUtil.isNotEmpty(endTime)) { | ||||
|             Date start; | ||||
|             Date end; | ||||
|             if (startTime.length() == 6) { | ||||
|                 start = DateUtil.parse(startTime, "yyyyMM"); | ||||
|                 end = DateUtil.endOfMonth(DateUtil.parse(endTime, "yyyyMM")); | ||||
|             } else { | ||||
|                 start = DateUtil.parse(startTime); | ||||
|                 end = DateUtil.parse(endTime); | ||||
|             } | ||||
|             Integer startMonth = Integer.valueOf(DateUtil.format(start, "yyyyMM")); | ||||
|             int endMonth = Integer.parseInt(DateUtil.format(end, "yyyyMM")); | ||||
|             if (startMonth.equals(endMonth)) { | ||||
|                 sqlDateFormat = "%Y%m%d"; | ||||
|                 dateFormat = "yyyyMMdd"; | ||||
|                 long diffDay = DateUtil.between(start, end, DateUnit.DAY); | ||||
|                 cycleNum = (int) diffDay + 1; | ||||
|             } else { | ||||
|                 sqlDateFormat = "%Y%m"; | ||||
|                 dateFormat = "yyyyMM"; | ||||
|                 int diffYear = Integer.parseInt(Integer.toString(endMonth).substring(0, 4)) - Integer.parseInt(startMonth.toString().substring(0, 4)); | ||||
|                 int diffMonth = endMonth % 100 - startMonth % 100 + 1; | ||||
|                 cycleNum = diffYear * 12 + diffMonth; | ||||
|             } | ||||
|             beginDate = start; | ||||
|             endDate = end; | ||||
|         } | ||||
|         Integer beginTime = Integer.valueOf(DateUtil.format(beginDate, dateFormat)); | ||||
|         Integer finalTime = Integer.valueOf(DateUtil.format(endDate, dateFormat)); | ||||
|         return new BiTimeEntity(sqlDateFormat, dateFormat, beginDate, endDate, cycleNum, beginTime, finalTime, new ArrayList<>()); | ||||
|     } | ||||
|  | ||||
|     @Data | ||||
|     @Accessors(chain = true) | ||||
|     public static class BiTimeEntity { | ||||
|         /** | ||||
|          * sql日期格式化 | ||||
|          */ | ||||
|         private String sqlDateFormat; | ||||
|  | ||||
|         /** | ||||
|          * 日期格式化 | ||||
|          */ | ||||
|         private String dateFormat; | ||||
|  | ||||
|         /** | ||||
|          * 开始时间 | ||||
|          */ | ||||
|         private Date beginDate; | ||||
|  | ||||
|         /** | ||||
|          * 结束时间 | ||||
|          */ | ||||
|         private Date endDate; | ||||
|  | ||||
|         /** | ||||
|          * 周期 | ||||
|          */ | ||||
|         private Integer cycleNum; | ||||
|  | ||||
|         /** | ||||
|          * 开始时间 字符串格式 如20200101 | ||||
|          */ | ||||
|         private Integer beginTime; | ||||
|  | ||||
|         /** | ||||
|          * 结束时间 字符串格式 如20200101 | ||||
|          */ | ||||
|         private Integer finalTime; | ||||
|  | ||||
|         /** | ||||
|          * user列表 | ||||
|          */ | ||||
|         private List<Long> userIds = new ArrayList<>(); | ||||
|         private Integer page; | ||||
|         private Integer limit; | ||||
|  | ||||
|         public BiTimeEntity(String sqlDateFormat, String dateFormat, Date beginDate, Date endDate, Integer cycleNum, Integer beginTime, Integer finalTime, List<Long> userIds) { | ||||
|             this.sqlDateFormat = sqlDateFormat; | ||||
|             this.dateFormat = dateFormat; | ||||
|             this.beginDate = beginDate; | ||||
|             this.endDate = endDate; | ||||
|             this.cycleNum = cycleNum; | ||||
|             this.beginTime = beginTime; | ||||
|             this.finalTime = finalTime; | ||||
|             this.userIds = userIds; | ||||
|         } | ||||
|  | ||||
|         public BiTimeEntity() { | ||||
|         } | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -1,45 +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.bi.dal.mysql.BiRankingMapper"> | ||||
|  | ||||
|  | ||||
|     <select id="contractRanKing" | ||||
|             resultType="cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO"> | ||||
|         SELECT IFNULL(SUM(t.price), 0) AS price, su.nickname, t.owner_user_id, dept.name AS deptName | ||||
|         FROM crm_contract t | ||||
|         <!-- TODO @anhaohao:system_users、system_dept 是不是没用到?尽量不连这 2 个表,微服务下会是独立仓库;如果显示需要,可以在 service 读取后拼接; --> | ||||
|         LEFT JOIN system_users AS su ON su.id = t.owner_user_id | ||||
|         LEFT JOIN system_dept AS dept ON dept.id = su.dept_id | ||||
|         WHERE t.deleted = 0 | ||||
|         AND t.audit_status = 20 | ||||
|         <if test="userIds != null and userIds.size() > 0"> | ||||
|             and t.owner_user_id in | ||||
|             <foreach collection="userIds" item="item" open="(" close=")" separator=","> | ||||
|                 #{item} | ||||
|             </foreach> | ||||
|         </if> | ||||
|         <!-- TODO @anhaohao:在某个区间的时间,这么做有点浪费性能;一般做法是 beginTime 是开始时间(00:00:00),finalTime 是结束时间(23:59:59),这样实现的; --> | ||||
|         AND DATE_FORMAT(t.order_date,'${sqlDateFormat}') between #{beginTime} and #{finalTime} | ||||
|         GROUP BY t.owner_user_id | ||||
|         ORDER BY price DESC | ||||
|     </select> | ||||
|  | ||||
|     <select id="receivablesRanKing" | ||||
|             resultType="cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO"> | ||||
|         SELECT IFNULL(SUM(t.price), 0) AS price, su.nickname, t.owner_user_id, dept.name AS deptName | ||||
|         FROM crm_receivable t | ||||
|         LEFT JOIN system_users AS su ON su.id = t.owner_user_id | ||||
|         LEFT JOIN system_dept AS dept ON dept.id = su.dept_id | ||||
|         WHERE t.deleted = 0 | ||||
|         AND t.audit_status = 20 | ||||
|         <if test="userIds != null and userIds.size() > 0"> | ||||
|             and t.owner_user_id in | ||||
|             <foreach collection="userIds" item="item" open="(" close=")" separator=","> | ||||
|                 #{item} | ||||
|             </foreach> | ||||
|         </if> | ||||
|         AND DATE_FORMAT(t.return_time,'${sqlDateFormat}') between #{beginTime} and #{finalTime} | ||||
|         GROUP BY t.owner_user_id | ||||
|         ORDER BY price DESC | ||||
|     </select> | ||||
| </mapper> | ||||
| @@ -1,9 +1,9 @@ | ||||
| ### 合同金额排行榜 | ||||
| GET {{baseUrl}}/bi/rank/contract-ranKing | ||||
| GET {{baseUrl}}/crm/bi-ranking/contract-ranKing | ||||
| Authorization: Bearer {{token}} | ||||
| tenant-id: {{adminTenentId}} | ||||
| 
 | ||||
| ### 回款金额排行榜 | ||||
| GET {{baseUrl}}/bi/rank/receivables-ranKing | ||||
| GET {{baseUrl}}/crm/bi-ranking/receivables-ranKing | ||||
| Authorization: Bearer {{token}} | ||||
| tenant-id: {{adminTenentId}} | ||||
| @@ -1,11 +1,11 @@ | ||||
| package cn.iocoder.yudao.module.bi.controller.admin.ranking; | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.bi; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; | ||||
| import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; | ||||
| import cn.iocoder.yudao.module.bi.service.ranking.BiRankingService; | ||||
| 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; | ||||
| @@ -19,13 +19,10 @@ import java.util.List; | ||||
| 
 | ||||
| import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||||
| 
 | ||||
| // TODO @anhaohao:写了 swagger 注解,不写注释哈 | ||||
| /** | ||||
|  * @author anhaohao | ||||
|  */ | ||||
| 
 | ||||
| @Tag(name = "管理后台 - 排行榜") | ||||
| @RestController | ||||
| @RequestMapping("/bi/ranking") | ||||
| @RequestMapping("/crm/bi-ranking") | ||||
| @Validated | ||||
| public class BiRankingController { | ||||
| 
 | ||||
| @@ -38,8 +35,8 @@ public class BiRankingController { | ||||
|     @GetMapping("/contract-ranking") | ||||
|     @Operation(summary = "合同金额排行榜") | ||||
|     @PreAuthorize("@ss.hasPermission('bi:ranking:query')") | ||||
|     public CommonResult<List<BiContractRanKingRespVO>> contractAmountRanking(BiRankReqVO biRankReqVO) { | ||||
|         return success(biRankingService.contractRanKing(biRankReqVO)); | ||||
|     public CommonResult<List<BiRanKingRespVO>> contractAmountRanking(BiRankingReqVO biRankingReqVO) { | ||||
|         return success(biRankingService.contractRanKing(biRankingReqVO)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @@ -48,8 +45,8 @@ public class BiRankingController { | ||||
|     @GetMapping("/receivables-ranking") | ||||
|     @Operation(summary = "回款金额排行榜") | ||||
|     @PreAuthorize("@ss.hasPermission('bi:ranking:query')") | ||||
|     public CommonResult<List<BiReceivablesRanKingRespVO>> receivablesRanKing(BiRankReqVO biRankReqVO) { | ||||
|         return success(biRankingService.receivablesRanKing(biRankReqVO)); | ||||
|     public CommonResult<List<BiRanKingRespVO>> receivablesRanKing(BiRankingReqVO biRankingReqVO) { | ||||
|         return success(biRankingService.receivablesRanKing(biRankingReqVO)); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @@ -1,12 +1,10 @@ | ||||
| package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; | ||||
| 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; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| // TODO @anhaohao:这个类的命名,还是保持和其它一致使用 ReqVO 结尾;例如说,CrmStatisticsCommonParamReqVO | ||||
| /** | ||||
|  * @author anhaohao | ||||
| @@ -23,9 +21,6 @@ public class BiParams extends PageParam { | ||||
|     @Schema(description = "用户ID") | ||||
|     private Long userId; | ||||
| 
 | ||||
|     @Schema(description = "用户IDs") | ||||
|     private List<Long> userIds; | ||||
| 
 | ||||
|     // TODO @anhaohao:这个字段,可以融合到 startTime、endTime 里去,交给前端计算哈; | ||||
|     @Schema(description = "类型") | ||||
|     private String type; | ||||
| @@ -37,8 +32,4 @@ public class BiParams extends PageParam { | ||||
|     @Schema(description = "结束时间") | ||||
|     private String endTime; | ||||
| 
 | ||||
|     // TODO @anhaohao:这个字段,是不是直接只基于 deptId 和 userId 来判断即可哈? | ||||
|     @Schema(description = "0 部门 1员工") | ||||
|     private Integer isUser = 1; | ||||
| 
 | ||||
| } | ||||
| @@ -0,0 +1,23 @@ | ||||
| package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import lombok.Data; | ||||
|  | ||||
|  | ||||
| @Schema(description = "管理后台 - BI 排行榜 Response VO") | ||||
| @Data | ||||
| public class BiRanKingRespVO { | ||||
|  | ||||
|     @Schema(description = "金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Integer price; | ||||
|  | ||||
|     @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private String nickname; | ||||
|  | ||||
|     @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private String deptName; | ||||
|  | ||||
|     @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||||
|     private Long ownerUserId; | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,35 @@ | ||||
| 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; | ||||
|  | ||||
| } | ||||
| @@ -22,6 +22,7 @@ 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.*; | ||||
| @@ -44,6 +45,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti | ||||
| public class CrmContractController { | ||||
|  | ||||
|     @Resource | ||||
|     @Lazy | ||||
|     private CrmContractService contractService; | ||||
|     @Resource | ||||
|     private CrmCustomerService customerService; | ||||
|   | ||||
| @@ -26,6 +26,7 @@ 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.*; | ||||
| @@ -51,6 +52,7 @@ public class CrmReceivableController { | ||||
|     @Resource | ||||
|     private CrmReceivableService receivableService; | ||||
|     @Resource | ||||
|     @Lazy | ||||
|     private CrmContractService contractService; | ||||
|     @Resource | ||||
|     private CrmCustomerService customerService; | ||||
|   | ||||
| @@ -28,6 +28,7 @@ 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.*; | ||||
| @@ -55,6 +56,7 @@ public class CrmReceivablePlanController { | ||||
|     @Resource | ||||
|     private CrmReceivableService receivableService; | ||||
|     @Resource | ||||
|     @Lazy | ||||
|     private CrmContractService contractService; | ||||
|     @Resource | ||||
|     private CrmCustomerService customerService; | ||||
|   | ||||
| @@ -0,0 +1,31 @@ | ||||
| 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); | ||||
| } | ||||
| @@ -6,6 +6,7 @@ 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; | ||||
|  | ||||
| /** | ||||
| @@ -20,6 +21,7 @@ public class CrmContractParseFunction implements IParseFunction { | ||||
|     public static final String NAME = "getContractById"; | ||||
|  | ||||
|     @Resource | ||||
|     @Lazy | ||||
|     private CrmContractService contractService; | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -0,0 +1,31 @@ | ||||
| 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); | ||||
| } | ||||
| @@ -0,0 +1,93 @@ | ||||
| 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())); | ||||
|     } | ||||
| } | ||||
| @@ -28,6 +28,7 @@ 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; | ||||
| @@ -56,6 +57,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { | ||||
|     @Resource | ||||
|     private CrmBusinessProductService businessProductService; | ||||
|     @Resource | ||||
|     @Lazy | ||||
|     private CrmContractService contractService; | ||||
|     @Resource | ||||
|     private CrmPermissionService permissionService; | ||||
|   | ||||
| @@ -25,6 +25,7 @@ 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; | ||||
| @@ -56,6 +57,7 @@ public class CrmContactServiceImpl implements CrmContactService { | ||||
|     @Resource | ||||
|     private CrmPermissionService permissionService; | ||||
|     @Resource | ||||
|     @Lazy | ||||
|     private CrmContractService contractService; | ||||
|     @Resource | ||||
|     private CrmContactBusinessService contactBusinessService; | ||||
|   | ||||
| @@ -24,6 +24,7 @@ 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.validation.annotation.Validated; | ||||
|  | ||||
| @@ -49,6 +50,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { | ||||
|     private CrmReceivablePlanMapper receivablePlanMapper; | ||||
|  | ||||
|     @Resource | ||||
|     @Lazy | ||||
|     private CrmContractService contractService; | ||||
|     @Resource | ||||
|     private CrmCustomerService customerService; | ||||
|   | ||||
| @@ -27,6 +27,7 @@ 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.validation.annotation.Validated; | ||||
|  | ||||
| @@ -50,6 +51,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { | ||||
|     private CrmReceivableMapper receivableMapper; | ||||
|  | ||||
|     @Resource | ||||
|     @Lazy | ||||
|     private CrmContractService contractService; | ||||
|     @Resource | ||||
|     private CrmCustomerService customerService; | ||||
|   | ||||
| @@ -0,0 +1,35 @@ | ||||
| <?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> | ||||
| @@ -20,7 +20,6 @@ import java.util.List; | ||||
| public class DeptApiImpl implements DeptApi { | ||||
|  | ||||
|     @Resource | ||||
|     @Lazy // 延迟加载,解决相互依赖的问题 | ||||
|     private DeptService deptService; | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -93,11 +93,6 @@ | ||||
|             <artifactId>yudao-module-crm-biz</artifactId> | ||||
|             <version>${revision}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>cn.iocoder.boot</groupId> | ||||
|             <artifactId>yudao-module-bi-biz</artifactId> | ||||
|             <version>${revision}</version> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- ERP 相关模块。默认注释,保证编译速度 --> | ||||
|         <dependency> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 芋道源码
					芋道源码