diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/common/model/entity/DataDTO.java b/pmapi/src/main/java/com/ningdatech/pmapi/common/model/entity/DataDTO.java
new file mode 100644
index 0000000..b5086fa
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/common/model/entity/DataDTO.java
@@ -0,0 +1,33 @@
+package com.ningdatech.pmapi.common.model.entity;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import java.math.BigDecimal;
+
+/**
+ *
+ * DataDTO
+ *
+ *
+ * @author ZPF
+ * @since 16:40 2023/12/05
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class DataDTO {
+
+ @ApiModelProperty("编号")
+ private String code;
+
+ @ApiModelProperty("名称")
+ private String name;
+
+ @ApiModelProperty("数量")
+ private Integer num;
+
+ @ApiModelProperty("比例")
+ private BigDecimal rate;
+}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/controller/StatisticsController.java b/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/controller/StatisticsController.java
index 82130e7..72aaa14 100644
--- a/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/controller/StatisticsController.java
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/controller/StatisticsController.java
@@ -2,6 +2,7 @@ package com.ningdatech.pmapi.dashboard.controller;
import com.ningdatech.pmapi.dashboard.manage.ExpertStatisticsManage;
import com.ningdatech.pmapi.dashboard.manage.FundStatisticsManage;
+import com.ningdatech.pmapi.dashboard.manage.MeetingStatisticsManage;
import com.ningdatech.pmapi.dashboard.model.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -24,6 +25,8 @@ public class StatisticsController {
private final ExpertStatisticsManage expertStatisticsManage;
+ private final MeetingStatisticsManage meetingStatisticsManage;
+
@GetMapping("/fund")
@ApiOperation("项目资金统计")
public FundStatisticsVO fund(@RequestParam(required = false) Integer year) {
@@ -35,4 +38,10 @@ public class StatisticsController {
public ExpertStatisticsVO expert(@RequestParam(required = false) Integer year) {
return expertStatisticsManage.statistics(year);
}
+
+ @GetMapping("/meeting")
+ @ApiOperation("评审会议统计")
+ public MeetingStatisticsVO meeting(@RequestParam(required = false) Integer year) {
+ return meetingStatisticsManage.statistics(year);
+ }
}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/manage/ExpertStatisticsManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/manage/ExpertStatisticsManage.java
index 0e2f01d..e42257a 100644
--- a/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/manage/ExpertStatisticsManage.java
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/manage/ExpertStatisticsManage.java
@@ -6,6 +6,7 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.ningdatech.pmapi.common.constant.RegionConst;
import com.ningdatech.pmapi.common.helper.RegionCacheHelper;
+import com.ningdatech.pmapi.common.model.entity.DataDTO;
import com.ningdatech.pmapi.dashboard.constant.DashboardConstant;
import com.ningdatech.pmapi.dashboard.model.vo.ExpertStatisticsVO;
import com.ningdatech.pmapi.expert.constant.ExpertUserInfoStepEnum;
@@ -142,9 +143,9 @@ public class ExpertStatisticsManage {
* @param res
*/
private void threeYearsCompleteExpert(ExpertStatisticsVO res,List experts) {
- List threeYearsAdds = Lists.newArrayList();
+ List threeYearsAdds = Lists.newArrayList();
for (Integer year : threeYears){
- ExpertStatisticsVO.ExpertData expert = new ExpertStatisticsVO.ExpertData();
+ DataDTO expert = new DataDTO();
expert.setName(year.toString());
expert.setCode(year.toString());
expert.setNum(experts.stream().filter(e -> {
@@ -206,7 +207,7 @@ public class ExpertStatisticsManage {
*/
private void computeLevels(ExpertStatisticsVO res, List experts,
List expertDictionaries,Map dictionMap) {
- List levels = Lists.newArrayList();
+ List levels = Lists.newArrayList();
Set userSets = Sets.newHashSet();
Map expertUserFullInfoMap = experts.stream()
@@ -216,7 +217,7 @@ public class ExpertStatisticsManage {
Map> dictionaryMap = expertDictionaries.stream()
.collect(Collectors.groupingBy(ExpertDictionary::getDictionaryCode));
for(String levelCode : LEVELS){
- ExpertStatisticsVO.ExpertData expertData = new ExpertStatisticsVO.ExpertData();
+ DataDTO expertData = new DataDTO();
if(dictionaryMap.containsKey(levelCode)){
List dictionaries = dictionaryMap.get(levelCode);
expertData.setNum(dictionaries.stream().filter(d -> {
@@ -241,7 +242,7 @@ public class ExpertStatisticsManage {
*/
private void computeTypes(ExpertStatisticsVO res, List experts,
List expertDictionaries,Map dictionMap) {
- List types = Lists.newArrayList();
+ List types = Lists.newArrayList();
Set userSets = Sets.newHashSet();
Map expertUserFullInfoMap = experts.stream()
@@ -251,7 +252,7 @@ public class ExpertStatisticsManage {
Map> dictionaryMap = expertDictionaries.stream()
.collect(Collectors.groupingBy(ExpertDictionary::getDictionaryCode));
for(String typeCode : TYPES){
- ExpertStatisticsVO.ExpertData expertData = new ExpertStatisticsVO.ExpertData();
+ DataDTO expertData = new DataDTO();
if(dictionaryMap.containsKey(typeCode)){
List dictionaries = dictionaryMap.get(typeCode);
expertData.setNum(dictionaries.stream().filter(d -> {
@@ -277,7 +278,7 @@ public class ExpertStatisticsManage {
.filter(u -> userSets.add(u.getUserId()))
.collect(Collectors.toMap(ExpertUserFullInfo::getUserId, e -> e));
- Map> typeDistribution = Maps.newHashMap();
+ Map> typeDistribution = Maps.newHashMap();
Map> tagsMap =
expertTags.stream().filter(e -> Objects.nonNull(e.getTagCode()))
@@ -288,14 +289,14 @@ public class ExpertStatisticsManage {
.collect(Collectors.toMap(TagDTO::getTagCode, TagDTO::getTagName));
//1.省维度
- List shengWeidu = Lists.newArrayList();
+ List shengWeidu = Lists.newArrayList();
for(String code : SHENGWEIDU){
shengWeidu.add(getExpertData(expertUserFullInfoMap,
tagsMap, tagNameMap, code));
}
//2.市维度
- List shiWeidu = Lists.newArrayList();
+ List shiWeidu = Lists.newArrayList();
for(String code : SHIWEIDU){
shiWeidu.add(getExpertData(expertUserFullInfoMap,
tagsMap, tagNameMap, code));
@@ -314,8 +315,8 @@ public class ExpertStatisticsManage {
* @param code
* @return
*/
- private static ExpertStatisticsVO.ExpertData getExpertData(Map expertUserFullInfoMap, Map> tagsMap, Map tagNameMap, String code) {
- ExpertStatisticsVO.ExpertData data = new ExpertStatisticsVO.ExpertData();
+ private static DataDTO getExpertData(Map expertUserFullInfoMap, Map> tagsMap, Map tagNameMap, String code) {
+ DataDTO data = new DataDTO();
data.setCode(code);
data.setName(tagNameMap.get(code));
if(tagsMap.containsKey(code)){
@@ -332,9 +333,9 @@ public class ExpertStatisticsManage {
//计算区域专家
private static void computeRegionExperts(ExpertStatisticsVO res, List intentionWorkRegions, Map expertMap, List regions) {
- List regionExpert = Lists.newArrayList();
+ List regionExpert = Lists.newArrayList();
for(RegionDTO region : regions){
- ExpertStatisticsVO.ExpertData expertData = new ExpertStatisticsVO.ExpertData();
+ DataDTO expertData = new DataDTO();
expertData.setName(region.getRegionName());
expertData.setCode(region.getRegionCode());
expertData.setNum(intentionWorkRegions.stream().filter(w -> {
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/manage/MeetingStatisticsManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/manage/MeetingStatisticsManage.java
new file mode 100644
index 0000000..b91f21f
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/manage/MeetingStatisticsManage.java
@@ -0,0 +1,216 @@
+package com.ningdatech.pmapi.dashboard.manage;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.google.common.collect.Lists;
+import com.ningdatech.pmapi.common.constant.RegionConst;
+import com.ningdatech.pmapi.common.helper.RegionCacheHelper;
+import com.ningdatech.pmapi.common.model.entity.DataDTO;
+import com.ningdatech.pmapi.dashboard.model.vo.MeetingStatisticsVO;
+import com.ningdatech.pmapi.ding.constants.DingOrganizationContant;
+import com.ningdatech.pmapi.expert.constant.ReviewResultEnum;
+import com.ningdatech.pmapi.expert.model.entity.ExpertReview;
+import com.ningdatech.pmapi.expert.model.enumeration.ReviewTemplateTypeEnum;
+import com.ningdatech.pmapi.expert.service.IExpertReviewService;
+import com.ningdatech.pmapi.meeting.entity.domain.Meeting;
+import com.ningdatech.pmapi.meeting.service.IMeetingService;
+import com.ningdatech.pmapi.organization.model.entity.DingOrganization;
+import com.ningdatech.pmapi.organization.service.IDingOrganizationService;
+import com.ningdatech.pmapi.projectlib.model.entity.Project;
+import com.ningdatech.pmapi.projectlib.service.IProjectService;
+import com.ningdatech.pmapi.sys.model.dto.RegionDTO;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * @Classname MeetingStatisticsManage
+ * @Description
+ * @Date 2023/12/05 17:44
+ * @Author PoffyZhang
+ */
+@Component
+@RequiredArgsConstructor
+@Slf4j
+public class MeetingStatisticsManage {
+
+ private final IMeetingService meetingService;
+
+ private final IExpertReviewService expertReviewService;
+
+ private final RegionCacheHelper regionCacheHelper;
+
+ private final IDingOrganizationService dingOrganizationService;
+
+ private final IProjectService projectService;
+
+ public MeetingStatisticsVO statistics(Integer year) {
+ MeetingStatisticsVO res = new MeetingStatisticsVO();
+ List meetings = meetingService.list(Wrappers.lambdaQuery(Meeting.class));
+ //查出 年份的 会议数据
+ meetings = meetings.stream().filter(m -> {
+ if(Objects.nonNull(m.getStartTime()) &&
+ (Objects.isNull(year) || year.equals(m.getStartTime().getYear()))){
+ return Boolean.TRUE;
+ }
+ return Boolean.FALSE;
+ }).collect(Collectors.toList());
+ List meetingIds = meetings.stream().map(Meeting::getId)
+ .collect(Collectors.toList());
+
+ //会议总数
+ res.setMeetingTotal(meetings.size());
+
+ //评审数
+ List expertReviews = Lists.newArrayList();
+ Integer reviewsTotal = 0;
+ if(CollUtil.isNotEmpty(meetingIds)){
+ expertReviews = expertReviewService.list(Wrappers.lambdaQuery(ExpertReview.class)
+ .eq(ExpertReview::getIsFinal, Boolean.TRUE)
+ .in(ExpertReview::getMeetingId,meetingIds));
+ reviewsTotal = expertReviews.size();
+ }
+ //通过的评审
+ List passExpertReviews = expertReviews.stream()
+ .filter(r -> Objects.nonNull(r.getReviewResult()) &&
+ r.getReviewResult().equals(ReviewResultEnum.PASSED.getCode()))
+ .collect(Collectors.toList());
+ //不通过的评审
+ List notpassExpertReviews = expertReviews.stream()
+ .filter(r -> Objects.nonNull(r.getReviewResult()) &&
+ r.getReviewResult().equals(ReviewResultEnum.REFUSED.getCode()))
+ .collect(Collectors.toList());
+ res.setPassReview(passExpertReviews.size());
+ res.setNotPassRate(reviewsTotal.compareTo(0) == 0 ? BigDecimal.ZERO :
+ BigDecimal.valueOf(notpassExpertReviews.size()).multiply(BigDecimal.valueOf(100)
+ .divide(BigDecimal.valueOf(reviewsTotal), RoundingMode.HALF_UP)));
+
+ //各区域
+ List regions = regionCacheHelper.listChildren(RegionConst.RC_LS, RegionConst.RL_CITY)
+ .stream().filter(r -> r.getRegionLevel().equals(RegionConst.RL_COUNTY))
+ .sorted(Comparator.comparing(RegionDTO::getRegionCode)).collect(Collectors.toList());
+ List regionMeetngs = Lists.newArrayList();
+ for(RegionDTO region : regions){
+ DataDTO data = new DataDTO();
+ data.setCode(region.getRegionCode());
+ data.setName(region.getRegionName());
+ data.setNum(meetings.stream().filter(m -> {
+ if(StringUtils.isNotBlank(m.getRegionCode()) &&
+ m.getRegionCode().equals(region.getRegionCode())){
+ return Boolean.TRUE;
+ }
+ return Boolean.FALSE;
+ }).collect(Collectors.toList()).size());
+ regionMeetngs.add(data);
+ }
+ res.setRegionMeetings(regionMeetngs);
+
+ //预审 验收 会议
+ List meetingTypes = Lists.newArrayList();
+ DataDTO yushen = new DataDTO();
+ yushen.setCode(ReviewTemplateTypeEnum.PRELIMINARY_SCHEME_REVIEW.getCode().toString());
+ yushen.setName("预审会议");
+ yushen.setNum(meetings.stream().filter(m -> {
+ if(StringUtils.isNotBlank(m.getType()) &&
+ m.getType().equals(ReviewTemplateTypeEnum.PRELIMINARY_SCHEME_REVIEW.getCode()
+ .toString())){
+ return Boolean.TRUE;
+ }
+ return Boolean.FALSE;
+ }).collect(Collectors.toList()).size());
+ meetingTypes.add(yushen);
+ DataDTO yanshou = new DataDTO();
+ yanshou.setCode(ReviewTemplateTypeEnum.ACCEPTANCE_SCHEME_REVIEW.getCode().toString());
+ yanshou.setName("验收会议");
+ Long yanshouCount = meetings.stream().filter(m -> {
+ if (StringUtils.isNotBlank(m.getType()) &&
+ m.getType().equals(ReviewTemplateTypeEnum.ACCEPTANCE_SCHEME_REVIEW.getCode()
+ .toString())) {
+ return Boolean.TRUE;
+ }
+ return Boolean.FALSE;
+ }).count();
+ yanshou.setNum(yanshouCount.intValue());
+ meetingTypes.add(yanshou);
+ res.setMeetingTypes(meetingTypes);
+
+ //各区县评审 不通过率
+ List regionNotpassReview = Lists.newArrayList();
+ for(RegionDTO region : regions){
+ DataDTO data = new DataDTO();
+ data.setCode(region.getRegionCode());
+ data.setName(region.getRegionName());
+ //先求出 此区域会议
+ List regionMeetingIds = meetings.stream().filter(m -> {
+ if (StringUtils.isNotBlank(m.getRegionCode()) &&
+ m.getRegionCode().equals(region.getRegionCode())) {
+ return Boolean.TRUE;
+ }
+ return Boolean.FALSE;
+ }).map(Meeting::getId).collect(Collectors.toList());
+
+ List regionReviews = expertReviews.stream().filter(r -> {
+ if (Objects.nonNull(r.getMeetingId()) &&
+ regionMeetingIds.contains(r.getMeetingId())) {
+ return Boolean.TRUE;
+ }
+ return Boolean.FALSE;
+ }).collect(Collectors.toList());
+ long regionNotpass = regionReviews.stream().filter(r -> Objects.nonNull(r.getReviewResult()) &&
+ r.getReviewResult().equals(ReviewResultEnum.REFUSED.getCode()))
+ .count();
+
+ data.setRate(CollUtil.isEmpty(regionReviews) ? BigDecimal.ZERO :
+ BigDecimal.valueOf(regionNotpass).multiply(BigDecimal.valueOf(100))
+ .divide(BigDecimal.valueOf(regionReviews.size()),BigDecimal.ROUND_CEILING,RoundingMode.HALF_UP));
+
+ regionNotpassReview.add(data);
+ }
+ res.setNotPassRegionMeetings(regionNotpassReview);
+
+ //各部门 不通过项目TOP10
+ List organizations = dingOrganizationService.list(Wrappers.lambdaQuery(DingOrganization.class)
+ .in(DingOrganization::getTypeCode, Lists.newArrayList(DingOrganizationContant.UNIT_TYPE,
+ DingOrganizationContant.GOV_TEMPORARY)));
+ List projects = projectService.list(Wrappers.lambdaQuery(Project.class)
+ .eq(Project::getNewest, Boolean.TRUE));
+
+ //TOP10
+ List finalExpertReviews = expertReviews;
+ List notpassTop10 = organizations.stream()
+ .map(o -> {
+ DataDTO data = new DataDTO();
+ data.setCode(o.getOrganizationCode());
+ data.setName(o.getOrganizationName());
+ List orgProjects = projects.stream().filter(p -> Objects.nonNull(p.getBuildOrgCode()) &&
+ p.getBuildOrgCode().equals(o.getOrganizationCode()))
+ .collect(Collectors.toList());
+ List projectCodes = orgProjects.stream().map(Project::getProjectCode)
+ .collect(Collectors.toList());
+ if(CollUtil.isEmpty(projectCodes)){
+ data.setRate(BigDecimal.ZERO);
+ return data;
+ }
+ List reviews = finalExpertReviews.stream().filter(r -> Objects.nonNull(r.getProjectCode()) &&
+ projectCodes.contains(r.getProjectCode())).collect(Collectors.toList());
+ long orgNotpass = reviews.stream().filter(r -> Objects.nonNull(r.getReviewResult()) &&
+ r.getReviewResult().equals(ReviewResultEnum.REFUSED.getCode()))
+ .count();
+ data.setRate(CollUtil.isEmpty(reviews) ? BigDecimal.ZERO :
+ BigDecimal.valueOf(orgNotpass).multiply(BigDecimal.valueOf(100))
+ .divide(BigDecimal.valueOf(reviews.size()),BigDecimal.ROUND_CEILING,RoundingMode.HALF_UP));
+ return data;
+ })
+ .sorted(Comparator.comparing(DataDTO::getRate).reversed())
+ .limit(10).collect(Collectors.toList());
+ res.setNotPassTop10(notpassTop10);
+ return res;
+ }
+}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/model/vo/ExpertStatisticsVO.java b/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/model/vo/ExpertStatisticsVO.java
index 259f7a9..bf139a0 100644
--- a/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/model/vo/ExpertStatisticsVO.java
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/model/vo/ExpertStatisticsVO.java
@@ -1,5 +1,6 @@
package com.ningdatech.pmapi.dashboard.model.vo;
+import com.ningdatech.pmapi.common.model.entity.DataDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -23,29 +24,17 @@ public class ExpertStatisticsVO implements Serializable {
private Integer active = 0;
@ApiModelProperty("各区县专家数")
- private List regionExpert;
+ private List regionExpert;
@ApiModelProperty("近三年专家数")
- private List threeYearsAdded;
+ private List threeYearsAdded;
@ApiModelProperty("专家类型分布")
- private Map> typeDistribution;
+ private Map> typeDistribution;
@ApiModelProperty("专家类型")
- private List types;
+ private List types;
@ApiModelProperty("专家等级")
- private List levels;
-
- @Data
- public static class ExpertData {
- @ApiModelProperty("名称")
- private String name;
-
- @ApiModelProperty("编码")
- private String code;
-
- @ApiModelProperty("数量")
- private Integer num = 0;
- }
+ private List levels;
}
\ No newline at end of file
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/model/vo/MeetingStatisticsVO.java b/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/model/vo/MeetingStatisticsVO.java
new file mode 100644
index 0000000..f9b196f
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/dashboard/model/vo/MeetingStatisticsVO.java
@@ -0,0 +1,36 @@
+package com.ningdatech.pmapi.dashboard.model.vo;
+
+import com.ningdatech.pmapi.common.model.entity.DataDTO;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@ApiModel(value = "评审会议统计", description = "")
+public class MeetingStatisticsVO implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty("评审召开总数")
+ private Integer meetingTotal = 0;
+
+ @ApiModelProperty("评审通过数")
+ private Integer passReview = 0;
+
+ @ApiModelProperty("评审不通过率")
+ private BigDecimal notPassRate = BigDecimal.ZERO;
+
+ @ApiModelProperty("各区县召开总数")
+ private List regionMeetings;
+
+ @ApiModelProperty("预审/验收 会议情况")
+ private List meetingTypes;
+
+ @ApiModelProperty("各区县不通过率")
+ private List notPassRegionMeetings;
+
+ @ApiModelProperty("各部门不通过top10")
+ private List notPassTop10;
+}
\ No newline at end of file