Parcourir la source

评审会议报表

master
PoffyZhang il y a 11 mois
Parent
révision
eae16006fa
6 fichiers modifiés avec 314 ajouts et 30 suppressions
  1. +33
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/common/model/entity/DataDTO.java
  2. +9
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/dashboard/controller/StatisticsController.java
  3. +14
    -13
      pmapi/src/main/java/com/ningdatech/pmapi/dashboard/manage/ExpertStatisticsManage.java
  4. +216
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/dashboard/manage/MeetingStatisticsManage.java
  5. +6
    -17
      pmapi/src/main/java/com/ningdatech/pmapi/dashboard/model/vo/ExpertStatisticsVO.java
  6. +36
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/dashboard/model/vo/MeetingStatisticsVO.java

+ 33
- 0
pmapi/src/main/java/com/ningdatech/pmapi/common/model/entity/DataDTO.java Voir le fichier

@@ -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;

/**
* <p>
* DataDTO
* </p>
*
* @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;
}

+ 9
- 0
pmapi/src/main/java/com/ningdatech/pmapi/dashboard/controller/StatisticsController.java Voir le fichier

@@ -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);
}
}

+ 14
- 13
pmapi/src/main/java/com/ningdatech/pmapi/dashboard/manage/ExpertStatisticsManage.java Voir le fichier

@@ -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<ExpertUserFullInfo> experts) {
List<ExpertStatisticsVO.ExpertData> threeYearsAdds = Lists.newArrayList();
List<DataDTO> 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<ExpertUserFullInfo> experts,
List<ExpertDictionary> expertDictionaries,Map<String, String> dictionMap) {
List<ExpertStatisticsVO.ExpertData> levels = Lists.newArrayList();
List<DataDTO> levels = Lists.newArrayList();

Set<Long> userSets = Sets.newHashSet();
Map<Long, ExpertUserFullInfo> expertUserFullInfoMap = experts.stream()
@@ -216,7 +217,7 @@ public class ExpertStatisticsManage {
Map<String, List<ExpertDictionary>> 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<ExpertDictionary> dictionaries = dictionaryMap.get(levelCode);
expertData.setNum(dictionaries.stream().filter(d -> {
@@ -241,7 +242,7 @@ public class ExpertStatisticsManage {
*/
private void computeTypes(ExpertStatisticsVO res, List<ExpertUserFullInfo> experts,
List<ExpertDictionary> expertDictionaries,Map<String, String> dictionMap) {
List<ExpertStatisticsVO.ExpertData> types = Lists.newArrayList();
List<DataDTO> types = Lists.newArrayList();

Set<Long> userSets = Sets.newHashSet();
Map<Long, ExpertUserFullInfo> expertUserFullInfoMap = experts.stream()
@@ -251,7 +252,7 @@ public class ExpertStatisticsManage {
Map<String, List<ExpertDictionary>> 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<ExpertDictionary> 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<String,List<ExpertStatisticsVO.ExpertData>> typeDistribution = Maps.newHashMap();
Map<String,List<DataDTO>> typeDistribution = Maps.newHashMap();

Map<String, List<ExpertTag>> 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<ExpertStatisticsVO.ExpertData> shengWeidu = Lists.newArrayList();
List<DataDTO> shengWeidu = Lists.newArrayList();
for(String code : SHENGWEIDU){
shengWeidu.add(getExpertData(expertUserFullInfoMap,
tagsMap, tagNameMap, code));
}

//2.市维度
List<ExpertStatisticsVO.ExpertData> shiWeidu = Lists.newArrayList();
List<DataDTO> 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<Long, ExpertUserFullInfo> expertUserFullInfoMap, Map<String, List<ExpertTag>> tagsMap, Map<String, String> tagNameMap, String code) {
ExpertStatisticsVO.ExpertData data = new ExpertStatisticsVO.ExpertData();
private static DataDTO getExpertData(Map<Long, ExpertUserFullInfo> expertUserFullInfoMap, Map<String, List<ExpertTag>> tagsMap, Map<String, String> 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<ExpertIntentionWorkRegion> intentionWorkRegions, Map<Long, ExpertUserFullInfo> expertMap, List<RegionDTO> regions) {
List<ExpertStatisticsVO.ExpertData> regionExpert = Lists.newArrayList();
List<DataDTO> 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 -> {


+ 216
- 0
pmapi/src/main/java/com/ningdatech/pmapi/dashboard/manage/MeetingStatisticsManage.java Voir le fichier

@@ -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<Meeting> 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<Long> meetingIds = meetings.stream().map(Meeting::getId)
.collect(Collectors.toList());

//会议总数
res.setMeetingTotal(meetings.size());

//评审数
List<ExpertReview> 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<ExpertReview> passExpertReviews = expertReviews.stream()
.filter(r -> Objects.nonNull(r.getReviewResult()) &&
r.getReviewResult().equals(ReviewResultEnum.PASSED.getCode()))
.collect(Collectors.toList());
//不通过的评审
List<ExpertReview> 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<RegionDTO> 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<DataDTO> 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<DataDTO> 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<DataDTO> regionNotpassReview = Lists.newArrayList();
for(RegionDTO region : regions){
DataDTO data = new DataDTO();
data.setCode(region.getRegionCode());
data.setName(region.getRegionName());
//先求出 此区域会议
List<Long> 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<ExpertReview> 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<DingOrganization> organizations = dingOrganizationService.list(Wrappers.lambdaQuery(DingOrganization.class)
.in(DingOrganization::getTypeCode, Lists.newArrayList(DingOrganizationContant.UNIT_TYPE,
DingOrganizationContant.GOV_TEMPORARY)));
List<Project> projects = projectService.list(Wrappers.lambdaQuery(Project.class)
.eq(Project::getNewest, Boolean.TRUE));

//TOP10
List<ExpertReview> finalExpertReviews = expertReviews;
List<DataDTO> notpassTop10 = organizations.stream()
.map(o -> {
DataDTO data = new DataDTO();
data.setCode(o.getOrganizationCode());
data.setName(o.getOrganizationName());
List<Project> orgProjects = projects.stream().filter(p -> Objects.nonNull(p.getBuildOrgCode()) &&
p.getBuildOrgCode().equals(o.getOrganizationCode()))
.collect(Collectors.toList());
List<String> projectCodes = orgProjects.stream().map(Project::getProjectCode)
.collect(Collectors.toList());
if(CollUtil.isEmpty(projectCodes)){
data.setRate(BigDecimal.ZERO);
return data;
}
List<ExpertReview> 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;
}
}

+ 6
- 17
pmapi/src/main/java/com/ningdatech/pmapi/dashboard/model/vo/ExpertStatisticsVO.java Voir le fichier

@@ -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<ExpertData> regionExpert;
private List<DataDTO> regionExpert;

@ApiModelProperty("近三年专家数")
private List<ExpertData> threeYearsAdded;
private List<DataDTO> threeYearsAdded;

@ApiModelProperty("专家类型分布")
private Map<String,List<ExpertData>> typeDistribution;
private Map<String,List<DataDTO>> typeDistribution;

@ApiModelProperty("专家类型")
private List<ExpertData> types;
private List<DataDTO> types;

@ApiModelProperty("专家等级")
private List<ExpertData> levels;

@Data
public static class ExpertData {
@ApiModelProperty("名称")
private String name;

@ApiModelProperty("编码")
private String code;

@ApiModelProperty("数量")
private Integer num = 0;
}
private List<DataDTO> levels;
}

+ 36
- 0
pmapi/src/main/java/com/ningdatech/pmapi/dashboard/model/vo/MeetingStatisticsVO.java Voir le fichier

@@ -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<DataDTO> regionMeetings;

@ApiModelProperty("预审/验收 会议情况")
private List<DataDTO> meetingTypes;

@ApiModelProperty("各区县不通过率")
private List<DataDTO> notPassRegionMeetings;

@ApiModelProperty("各部门不通过top10")
private List<DataDTO> notPassTop10;
}

Chargement…
Annuler
Enregistrer