Browse Source

fix--问责人数修改

master
buaixuexideshitongxue 1 month ago
parent
commit
724a66c4d8
  1. 293
      src/main/java/com/biutag/supervision/service/datav/DatavServiceImpl.java
  2. 451
      src/main/java/com/biutag/supervision/service/subDatav/SubDatavServiceImpl.java
  3. 222
      src/main/java/com/biutag/supervision/util/AccountabilityCountUtil.java

293
src/main/java/com/biutag/supervision/service/datav/DatavServiceImpl.java

@ -1,6 +1,5 @@
package com.biutag.supervision.service.datav;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
@ -17,19 +16,18 @@ import com.biutag.supervision.pojo.entity.mailbox.Mail;
import com.biutag.supervision.pojo.entity.report.ReportProject;
import com.biutag.supervision.pojo.param.*;
import com.biutag.supervision.pojo.param.dataAudit.DataAuditQueryParam;
import com.biutag.supervision.pojo.param.negativeBlame.NegativeBlameQueryParam;
import com.biutag.supervision.pojo.request.datav.DataVRequest;
import com.biutag.supervision.pojo.vo.*;
import com.biutag.supervision.repository.dataAudit.DataAuditResourceService;
import com.biutag.supervision.repository.dataCaseVerif.DataCaseVerifResourceService;
import com.biutag.supervision.repository.dataPetitionComplaint.DataPetitionComplaintResourceService;
import com.biutag.supervision.repository.negative.NegativeResourceService;
import com.biutag.supervision.repository.negativeBlame.NegativeBlameResourceService;
import com.biutag.supervision.repository.reportproject.ReportProjectResourceService;
import com.biutag.supervision.repository.supExternalDepart.SupExternalDepartResourceService;
import com.biutag.supervision.repository.supdepart.SupDepartResourceService;
import com.biutag.supervision.service.DataPetition12337Service;
import com.biutag.supervision.service.SuperviseReportService;
import com.biutag.supervision.util.AccountabilityCountUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -102,13 +100,11 @@ public class DatavServiceImpl implements DatavService {
@Resource
private SuperviseReportService superviseReportService;
@Resource
private NegativeBlameResourceService negativeBlameResourceService;
@Resource
private DataCaseVerifMapper dataCaseVerifMapper;
private static final String NO_BLAME = "不予追责";
@Resource
private AccountabilityCountUtil accountabilityCountUtil;
private static final BigDecimal WAN = new BigDecimal("10000");
@ -409,14 +405,14 @@ public class DatavServiceImpl implements DatavService {
List<Negative> ssList = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList();
List<Negative> completedList = negatives.stream().filter(item -> ProcessingStatusEnum.completed.name().equals(item.getProcessingStatus())).toList();
// 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
VideoSuperviseCountVo overview = new VideoSuperviseCountVo();
overview.setTotal(negatives.size());
overview.setCompletionProblem((long) completedList.size());
overview.setDiscoverProblem((long) ssList.size());
overview.setRelativeOrg(accountabilityCountResult.unitCount());
overview.setRelativePer(accountabilityCountResult.personTotalCount());
overview.setRelativeOrg(accountabilityCountResult.newUnitCount());
overview.setRelativePer(accountabilityCountResult.newPersonTotalCount());
JSONObject data = new JSONObject().fluentPut("overview", overview);
return Result.success(data);
}
@ -437,14 +433,14 @@ public class DatavServiceImpl implements DatavService {
List<Negative> ssList = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList();
List<Negative> completedList = negatives.stream().filter(item -> ProcessingStatusEnum.completed.name().equals(item.getProcessingStatus())).toList();
// 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
VideoSuperviseMapIconVo videoSuperviseMapIconVo = new VideoSuperviseMapIconVo();
videoSuperviseMapIconVo.setName(fxsj.getShortName());
videoSuperviseMapIconVo.setDepartId(fxsj.getId());
videoSuperviseMapIconVo.setDiscoverProblem(ssList.size());
videoSuperviseMapIconVo.setCompletionProblem(completedList.size());
videoSuperviseMapIconVo.setRelativeOrg(Math.toIntExact(accountabilityCountResult.unitCount()));
videoSuperviseMapIconVo.setRelativePer(Math.toIntExact(accountabilityCountResult.personTotalCount()));
videoSuperviseMapIconVo.setRelativeOrg(Math.toIntExact(accountabilityCountResult.newUnitCount()));
videoSuperviseMapIconVo.setRelativePer(Math.toIntExact(accountabilityCountResult.newPersonTotalCount()));
videoSuperviseMapIconVoList.add(videoSuperviseMapIconVo);
}
videoSuperviseMapIconVoList.forEach(VideoSuperviseMapIconVo::initDefaultIfNull);
@ -585,7 +581,7 @@ public class DatavServiceImpl implements DatavService {
superviseReportLambdaQueryWrapper.eq(SuperviseReport::getType, "1");
List<SuperviseReport> superviseReportList = superviseReportService.list(superviseReportLambdaQueryWrapper);
// 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
// 通报问题数
overView.setProblemNumber(negatives.size());
@ -596,8 +592,8 @@ public class DatavServiceImpl implements DatavService {
// 已办结
overView.setCompletedNumber((long) completedList.size());
// 问责单位数
overView.setDepartNumber(accountabilityCountResult.unitCount());
overView.setPersonNumber(accountabilityCountResult.personTotalCount());
overView.setDepartNumber(accountabilityCountResult.newUnitCount());
overView.setPersonNumber(accountabilityCountResult.newPersonTotalCount());
return Result.success(overView);
}
@ -632,14 +628,14 @@ public class DatavServiceImpl implements DatavService {
superviseReportLambdaQueryWrapper.in(CollectionUtil.isNotEmpty(allDepartIds), SuperviseReport::getCrtDepartId, allDepartIds);
List<SuperviseReport> superviseReportList = superviseReportService.list(superviseReportLambdaQueryWrapper);
// 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
superviseMapIconVo.setDepartId(fxsj.getId());
superviseMapIconVo.setName(fxsj.getShortName());
superviseMapIconVo.setTotalPro(negatives.size());
superviseMapIconVo.setProcessingNumber(processingList.size());
superviseMapIconVo.setCompletedNumber(completedList.size());
superviseMapIconVo.setRelationOrg(String.valueOf(accountabilityCountResult.unitCount()));
superviseMapIconVo.setPersonNum(String.valueOf(accountabilityCountResult.personTotalCount()));
superviseMapIconVo.setRelationOrg(String.valueOf(accountabilityCountResult.newUnitCount()));
superviseMapIconVo.setPersonNum(String.valueOf(accountabilityCountResult.newPersonTotalCount()));
superviseMapIconVo.setReportNumber(String.valueOf(superviseReportList.size()));
superviseTempMapVoList.add(superviseMapIconVo);
}
@ -798,7 +794,7 @@ public class DatavServiceImpl implements DatavService {
.filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList();
// 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
//计算查实率(向上取整)
Double verificationRate = 0.0;
if (!dataCaseVerifs.isEmpty() || !jbNegatvieList.isEmpty()) {
@ -808,8 +804,8 @@ public class DatavServiceImpl implements DatavService {
overview.setTotal(dataCaseVerifs.size() + jbNegatvieList.size());
overview.setConfirmed(ssNegative.size());
overview.setDealCasePro((long) negatives.size());
overview.setPunishPre(accountabilityCountResult.personTotalCount());
overview.setPunishOrg(accountabilityCountResult.unitCount());
overview.setPunishPre(accountabilityCountResult.newPersonTotalCount());
overview.setPunishOrg(accountabilityCountResult.newUnitCount());
overview.setRate(verificationRate);
JSONObject res = new JSONObject().fluentPut("overview", overview);
return Result.success(res);
@ -838,7 +834,7 @@ public class DatavServiceImpl implements DatavService {
// 交办案件数
List<Negative> jbNegatvieList = negatives.stream().filter(one -> ldjbCode.contains(one.getProblemSourcesCode())).toList();
// 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
Double verificationRate = 0.0;
if (!dataCaseVerifs.isEmpty() || !jbNegatvieList.isEmpty()) {
@ -851,8 +847,8 @@ public class DatavServiceImpl implements DatavService {
caseVerificationMapVo.setTotal(dataCaseVerifs.size() + jbNegatvieList.size());
caseVerificationMapVo.setConfirmed(ssNegative.size());
caseVerificationMapVo.setDealCasePro(negatives.size());
caseVerificationMapVo.setPunishPre(Math.toIntExact(accountabilityCountResult.personTotalCount()));
caseVerificationMapVo.setPunishOrg(Math.toIntExact(accountabilityCountResult.unitCount()));
caseVerificationMapVo.setPunishPre(Math.toIntExact(accountabilityCountResult.newPersonTotalCount()));
caseVerificationMapVo.setPunishOrg(Math.toIntExact(accountabilityCountResult.newUnitCount()));
caseVerificationMapVo.setRate(verificationRate);
caseVerificationMapList.add(caseVerificationMapVo);
}
@ -893,7 +889,7 @@ public class DatavServiceImpl implements DatavService {
}
// 问责处理情况
AccountabilityCountResult accountabilityCountResult = this.buildAccountabilityCountResult(negatives);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
Map<String, Long> dealResultDistribution = accountabilityCountResult.dealResultDistribution();
for (Map.Entry<String, Long> entry : dealResultDistribution.entrySet()) {
EchartsVo echartsVo = new EchartsVo();
@ -1064,21 +1060,14 @@ public class DatavServiceImpl implements DatavService {
@Override
public Result<JSONObject> getResultCount(DataVRequest request) {
List<EchartsVo> resultCountArray = new ArrayList<>();
NegativeQueryParam negativeQueryParam = new NegativeQueryParam();
negativeQueryParam.setCrtTime(List.of(request.getBeginTime(), request.getEndTime()));
negativeQueryParam.setProblemSourcesCode(GROUP_21_22_23_24_25);
List<Negative> negatives = negativeResourceService.query(negativeQueryParam);
BlameResult blameResult = this.buildBlameResult(negatives);
List<NegativeBlame> negativeBlames = blameResult.personalBlames();
// 问责处理情况与统一统计口径保持一致:先拆分多处理结果,再按单项处理结果聚合。
Map<String, Long> blames = negativeBlames.stream()
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream()
.map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName))
.map(item -> item.substring(item.lastIndexOf('_') + 1))
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
for (Map.Entry<String, Long> entry : blames.entrySet()) {
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
List<EchartsVo> resultCountArray = new ArrayList<>();
for (Map.Entry<String, Long> entry : accountabilityCountResult.dealResultDistribution().entrySet()) {
EchartsVo echartsVo = new EchartsVo();
echartsVo.setName(entry.getKey());
echartsVo.setValue(entry.getValue().intValue());
@ -1115,7 +1104,7 @@ public class DatavServiceImpl implements DatavService {
negativeQueryParam.setProblemSourcesCode(List.of(ZFTZSJ.getValue()));
List<Negative> negativeListData = negativeResourceService.query(negativeQueryParam);
// 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negativeListData);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negativeListData);
BigDecimal zftzje = this.sumAmountInWan(reportProjects, ReportProject::getReportMoney);
BigDecimal zftzsjje = this.sumAmountInWan(reportProjects, ReportProject::getArchivingReduceMoney);
@ -1123,7 +1112,7 @@ public class DatavServiceImpl implements DatavService {
auditOverview.setAuditAmount(zftzje);
auditOverview.setAuditSjAmount(zftzsjje);
auditOverview.setNegativeNumber(negativeListData.size());
auditOverview.setAccountableNumber(accountabilityCountResult.personTotalCount());
auditOverview.setAccountableNumber(accountabilityCountResult.newPersonTotalCount());
} else {
DataAuditQueryParam dataAuditQueryParam = new DataAuditQueryParam();
dataAuditQueryParam.setAuditTimeStart(toLocalDateTime(request.getBeginTime()));
@ -1135,14 +1124,14 @@ public class DatavServiceImpl implements DatavService {
negativeQueryParam.setProblemSourcesCode(List.of(request.getAuditType()));
List<Negative> negativeListData = negativeResourceService.query(negativeQueryParam);
// 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negativeListData);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negativeListData);
BigDecimal je = this.sumAmount(dataAuditList, DataAudit::getAuditAmount, new BigDecimal(1));
BigDecimal zsjje = this.sumAmount(dataAuditList, DataAudit::getIssueAmount, new BigDecimal(1));
auditOverview.setProjectNumber(BigDecimal.valueOf(dataAuditList.size()));
auditOverview.setAuditAmount(je);
auditOverview.setAuditSjAmount(zsjje);
auditOverview.setNegativeNumber(negativeListData.size());
auditOverview.setAccountableNumber(accountabilityCountResult.personTotalCount());
auditOverview.setAccountableNumber(accountabilityCountResult.newPersonTotalCount());
}
JSONObject object = new JSONObject();
object.fluentPut("fxData", fxData);
@ -1198,7 +1187,7 @@ public class DatavServiceImpl implements DatavService {
negativeQueryParam.setProblemSourcesCode(GROUP_27_28_29_30);
List<Negative> negativeListData = negativeResourceService.query(negativeQueryParam);
// 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negativeListData);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negativeListData);
// 政府投资总金额
BigDecimal zftzje = this.sumAmountInWan(reportProjects, ReportProject::getReportMoney);
// 政府投资审减金额
@ -1211,7 +1200,7 @@ public class DatavServiceImpl implements DatavService {
overview.setAuditAmount(zftzje.add(qtsjje));
overview.setAuditSjAmount(zftzsjje.add(qtsjwtje));
overview.setNegativeNumber(negativeListData.size());
overview.setAccountableNumber(accountabilityCountResult.personTotalCount());
overview.setAccountableNumber(accountabilityCountResult.newPersonTotalCount());
return Result.success(overview);
}
@ -1249,7 +1238,7 @@ public class DatavServiceImpl implements DatavService {
List<Negative> negativeListData = negativeMapper.getNegativeListData(key, request.getBeginTime(), request.getEndTime(), GROUP_27_28_29_30);
// 使用统一的问责次数统计口径,便于核对大屏与导出逻辑差异
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negativeListData);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negativeListData);
// 政府投资总金额
BigDecimal zftzje = this.sumAmountInWan(reportProjects, ReportProject::getReportMoney);
// 政府投资审减金额
@ -1263,7 +1252,7 @@ public class DatavServiceImpl implements DatavService {
auditSuperviseMapIconVo.setAuditAmount(zftzje.add(qtsjje));
auditSuperviseMapIconVo.setAuditSjAmount(zftzsjje.add(qtsjwtje));
auditSuperviseMapIconVo.setNegativeNumber(negativeListData.size());
auditSuperviseMapIconVo.setAccountableNumber(Math.toIntExact(accountabilityCountResult.personTotalCount()));
auditSuperviseMapIconVo.setAccountableNumber(Math.toIntExact(accountabilityCountResult.newPersonTotalCount()));
auditSuperviseMapIconVoList.add(auditSuperviseMapIconVo);
}
JSONObject data = new JSONObject().fluentPut("auditSuperviseMapIconVoList", auditSuperviseMapIconVoList);
@ -1392,222 +1381,6 @@ public class DatavServiceImpl implements DatavService {
private static final Set<String> NO_ACCOUNTABILITY_SET = Set.of("不予问责", "不予追责");
private record AccountabilityCountResult(
long personalCount,
long leaderCount,
long personTotalCount,
long unitCount,
Map<String, Long> dealResultDistribution,
// 新增:问责人数(blameName非空 + 处理结果非"不予追责")
long newPersonalCount,
// 新增:问责领导人数(blameName非空 + leadName非空 + 处理结果非"不予追责")
long newLeaderCount,
// 新增:新问责总人数
long newPersonTotalCount
) {}
private AccountabilityCountResult buildAccountabilityCountResult(List<Negative> negatives) {
if (CollectionUtil.isEmpty(negatives)) {
return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L);
}
List<String> effectiveNegativeIds = negatives.stream()
.filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode())
|| CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode()))
.map(Negative::getId)
.filter(StrUtil::isNotBlank)
.distinct()
.toList();
if (CollectionUtil.isEmpty(effectiveNegativeIds)) {
return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L);
}
NegativeBlameQueryParam param = new NegativeBlameQueryParam();
param.setNegativeIds(effectiveNegativeIds);
List<NegativeBlame> negativeBlames = negativeBlameResourceService.query(param);
if (CollectionUtil.isEmpty(negativeBlames)) {
return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L);
}
long personalCount = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream()
.map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName))
.distinct()
.count();
long leaderCount = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> StrUtil.isNotBlank(one.getLeadName()))
.flatMap(one -> splitValidAccountabilityResults(one.getLeadHandleResultName()).stream()
.map(resultName -> one.getNegativeId() + "_" + one.getLeadName() + "_" + resultName))
.distinct()
.count();
long unitCount = negativeBlames.stream()
.filter(one -> BlameType.department.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream()
.map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName))
.distinct()
.count();
// 统计处理结果分布(普通人员 + 领导)
Map<String, Long> dealResultDistribution = buildDealResultDistribution(negativeBlames);
// 新增:问责人数(blameName非空 + 处理结果非"不予追责")
long newPersonalCount = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> !isNoAccountability(one.getHandleResultName()))
.count();
// 新增:问责领导人数(blameName非空 + leadName非空 + 处理结果非"不予追责")
long newLeaderCount = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> StrUtil.isNotBlank(one.getLeadName()))
.filter(one -> !isNoAccountability(one.getLeadHandleResultName()))
.count();
// 新增:新问责总人数
long newPersonTotalCount = newPersonalCount + newLeaderCount;
return new AccountabilityCountResult(
personalCount,
leaderCount,
personalCount + leaderCount,
unitCount,
dealResultDistribution,
newPersonalCount,
newLeaderCount,
newPersonTotalCount
);
}
/**
* 构建处理结果分布统计普通人员 + 领导
* buildAccountabilityCountResult 中的 personalCount + leaderCount 保持口径一致
*/
private Map<String, Long> buildDealResultDistribution(List<NegativeBlame> negativeBlames) {
// 统计普通人员处理结果(type=personal + blameName非空)
Map<String, Long> personalResults = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream()
.map(result -> one.getNegativeId() + "_" + one.getBlameName() + "_" + result))
.distinct()
.collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting()));
// 统计领导处理结果(type=personal + blameName非空 + leadName非空)
Map<String, Long> leaderResults = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> StrUtil.isNotBlank(one.getLeadName()))
.flatMap(one -> splitValidAccountabilityResults(one.getLeadHandleResultName()).stream()
.map(result -> one.getNegativeId() + "_" + one.getLeadName() + "_" + result))
.distinct()
.collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting()));
// 合并
Map<String, Long> merged = new HashMap<>(personalResults);
leaderResults.forEach((key, value) -> merged.merge(key, value, Long::sum));
return merged;
}
private List<String> splitValidAccountabilityResults(String raw) {
if (StrUtil.isBlank(raw)) {
return List.of();
}
return Arrays.stream(raw.split("[、,,]"))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.filter(item -> !NO_ACCOUNTABILITY_SET.contains(item))
.distinct()
.toList();
}
/**
* 判断问责情况是否全为"不予追责"即没有有效的问责处理结果
* @param raw 原始问责情况字符串
* @return true表示全部为"不予追责"false表示有有效问责处理结果
*/
private boolean isNoAccountability(String raw) {
if (StrUtil.isBlank(raw)) {
return true;
}
List<String> results = Arrays.stream(raw.split("[、,,]"))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.toList();
// 如果拆分后为空,或者所有结果都是"不予追责",则返回true
if (results.isEmpty()) {
return true;
}
return results.stream().allMatch(item -> NO_ACCOUNTABILITY_SET.contains(item));
}
public record BlameResult(
List<NegativeBlame> personalBlames,
List<NegativeBlame> leadBlames,
List<NegativeBlame> unitBlames
) {
}
public BlameResult buildBlameResult(List<Negative> negativeListData) {
if (CollUtil.isEmpty(negativeListData)) {
return new BlameResult(List.of(), List.of(), List.of());
}
// 1. 筛选有效 negative
List<Negative> validNegatives = negativeListData.stream()
.filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode())
|| CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode()))
.toList();
if (CollUtil.isEmpty(validNegatives)) {
return new BlameResult(List.of(), List.of(), List.of());
}
// 2. 查询问责数据
NegativeBlameQueryParam param = new NegativeBlameQueryParam();
param.setNegativeIds(validNegatives.stream()
.map(Negative::getId)
.toList());
List<NegativeBlame> negativeBlames = negativeBlameResourceService.query(param);
if (CollUtil.isEmpty(negativeBlames)) {
return new BlameResult(List.of(), List.of(), List.of());
}
// 3. 个人问责
List<NegativeBlame> personalBlames = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getHandleResultName()))
.filter(one -> !NO_BLAME.equals(one.getHandleResultName()))
.toList();
// 4. 领导问责(去重)
Set<String> seenLead = new HashSet<>();
List<NegativeBlame> leadBlames = negativeBlames.stream()
.filter(one -> StrUtil.isNotBlank(one.getLeadHandleResultName()))
.filter(one -> !NO_BLAME.equals(one.getLeadHandleResultName()))
.filter(one -> seenLead.add(
one.getNegativeId() + "_" + one.getLeadHandleResultName() + "_" + one.getLeadName()
))
.toList();
// 5. 单位问责
List<NegativeBlame> unitBlames = negativeBlames.stream()
.filter(one -> BlameType.department.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getHandleResultName()))
.filter(one -> !"不予追责".equals(one.getHandleResultName()))
.toList();
return new BlameResult(personalBlames, leadBlames, unitBlames);
}
private LocalDateTime toLocalDateTime(Date date) {
if (date == null) {
return null;

451
src/main/java/com/biutag/supervision/service/subDatav/SubDatavServiceImpl.java

@ -1,6 +1,5 @@
package com.biutag.supervision.service.subDatav;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
@ -15,29 +14,23 @@ import com.biutag.supervision.pojo.dto.common.PieItem;
import com.biutag.supervision.pojo.entity.*;
import com.biutag.supervision.pojo.entity.mailbox.Mail;
import com.biutag.supervision.pojo.param.*;
import com.biutag.supervision.pojo.param.negativeBlame.NegativeBlameQueryParam;
import com.biutag.supervision.pojo.request.datav.DataVRequest;
import com.biutag.supervision.pojo.request.subdatav.SubDataVRequest;
import com.biutag.supervision.pojo.vo.*;
import com.biutag.supervision.repository.dataPetitionComplaint.DataPetitionComplaintResourceService;
import com.biutag.supervision.repository.mail.MailResourceService;
import com.biutag.supervision.repository.negative.NegativeResourceService;
import com.biutag.supervision.repository.negativeBlame.NegativeBlameResourceService;
import com.biutag.supervision.repository.reportproject.ReportProjectResourceService;
import com.biutag.supervision.repository.supExternalDepart.SupExternalDepartResourceService;
import com.biutag.supervision.repository.supdepart.SupDepartResourceService;
import com.biutag.supervision.service.DataPetition12337Service;
import com.biutag.supervision.service.SuperviseReportService;
import com.biutag.supervision.service.datav.DatavServiceImpl;
import com.biutag.supervision.util.AccountabilityCountUtil;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -92,18 +85,14 @@ public class SubDatavServiceImpl implements SubDatavService {
@Resource
private NegativeMapper negativeMapper;
@Resource
private NegativeBlameResourceService negativeBlameResourceService;
@Resource
private DataCaseVerifMapper dataCaseVerifMapper;
@Resource
private SuperviseReportService superviseReportService;
private static final String NO_BLAME = "不予追责";
private static final Set<String> NO_ACCOUNTABILITY_SET = Set.of("不予问责", "不予追责");
@Resource
private AccountabilityCountUtil accountabilityCountUtil;
private static final BigDecimal WAN = new BigDecimal("10000");
@ -311,14 +300,14 @@ public class SubDatavServiceImpl implements SubDatavService {
List<Negative> ssList = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList();
List<Negative> completedList = negatives.stream().filter(item -> ProcessingStatusEnum.completed.name().equals(item.getProcessingStatus())).toList();
// 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
VideoSuperviseCountVo overview = new VideoSuperviseCountVo();
overview.setTotal(negatives.size());
overview.setCompletionProblem((long) completedList.size());
overview.setDiscoverProblem((long) ssList.size());
overview.setRelativeOrg(accountabilityCountResult.unitCount());
overview.setRelativePer(accountabilityCountResult.personTotalCount());
overview.setRelativeOrg(accountabilityCountResult.newUnitCount());
overview.setRelativePer(accountabilityCountResult.newPersonTotalCount());
JSONObject data = new JSONObject().fluentPut("overview", overview);
return Result.success(data);
}
@ -342,41 +331,16 @@ public class SubDatavServiceImpl implements SubDatavService {
List<Negative> ssList = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList();
List<Negative> completedList = negatives.stream().filter(item -> ProcessingStatusEnum.completed.name().equals(item.getProcessingStatus())).toList();
NegativeBlameQueryParam negativeBlameQueryParam = new NegativeBlameQueryParam();
negativeBlameQueryParam.setNegativeIds(ssList.stream().map(Negative::getId).toList());
List<NegativeBlame> negativeBlames = negativeBlameResourceService.query(negativeBlameQueryParam);
// 3. 个人问责
List<NegativeBlame> personalBlames = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getHandleResultName()))
.filter(one -> !"不予追责".equals(one.getHandleResultName()))
.toList();
// 4. 领导问责(按 negativeId + 领导姓名 + 领导处理结果 去重)
Set<String> seenLead = new HashSet<>();
List<NegativeBlame> leadBlames = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getLeadHandleResultName()))
.filter(one -> !"不予追责".equals(one.getLeadHandleResultName()))
.filter(one -> seenLead.add(
one.getNegativeId() + "_" + one.getLeadHandleResultName() + "_" + one.getLeadName()
))
.toList();
// 5. 单位问责
List<NegativeBlame> unitBlames = negativeBlames.stream()
.filter(one -> BlameType.department.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getHandleResultName()))
.filter(one -> !"不予追责".equals(one.getHandleResultName()))
.toList();
// 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
VideoSuperviseMapIconVo videoSuperviseMapIconVo = new VideoSuperviseMapIconVo();
videoSuperviseMapIconVo.setName(pcs.getShortName());
videoSuperviseMapIconVo.setDepartId(pcs.getId());
videoSuperviseMapIconVo.setDiscoverProblem(ssList.size());
videoSuperviseMapIconVo.setCompletionProblem(completedList.size());
videoSuperviseMapIconVo.setRelativeOrg(unitBlames.size());
videoSuperviseMapIconVo.setRelativePer(personalBlames.size() + leadBlames.size());
videoSuperviseMapIconVo.setRelativeOrg(Math.toIntExact(accountabilityCountResult.newUnitCount()));
videoSuperviseMapIconVo.setRelativePer(Math.toIntExact(accountabilityCountResult.newPersonTotalCount()));
videoSuperviseMapIconVoList.add(videoSuperviseMapIconVo);
}
@ -509,15 +473,15 @@ public class SubDatavServiceImpl implements SubDatavService {
superviseReportLambdaQueryWrapper.eq(SuperviseReport::getCrtDepartId, supDepart.getId());
List<SuperviseReport> superviseReportList = superviseReportService.list(superviseReportLambdaQueryWrapper);
// 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
SuperviseMapIconVo superviseMapIconVo = new SuperviseMapIconVo();
superviseMapIconVo.setName(supDepart.getShortName());
superviseMapIconVo.setDepartId(supDepart.getId());
superviseMapIconVo.setTotalPro(negatives.size());
superviseMapIconVo.setCompletedNumber(completedList.size());
superviseMapIconVo.setProcessingNumber(processingList.size());
superviseMapIconVo.setPersonNum(String.valueOf(accountabilityCountResult.personTotalCount()));
superviseMapIconVo.setRelationOrg(String.valueOf(accountabilityCountResult.unitCount()));
superviseMapIconVo.setPersonNum(String.valueOf(accountabilityCountResult.newPersonTotalCount()));
superviseMapIconVo.setRelationOrg(String.valueOf(accountabilityCountResult.newUnitCount()));
superviseMapIconVo.setReportNumber(String.valueOf(superviseReportList.size()));
superviseTempMapVoList.add(superviseMapIconVo);
}
@ -547,13 +511,13 @@ public class SubDatavServiceImpl implements SubDatavService {
superviseReportLambdaQueryWrapper.in(CollectionUtil.isNotEmpty(allDepartIds), SuperviseReport::getCrtDepartId, allDepartIds);
List<SuperviseReport> superviseReportList = superviseReportService.list(superviseReportLambdaQueryWrapper);
// 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。
AccountabilityCountResult accountabilityCountResult = buildAccountabilityCountResult(negatives);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
overView.setProblemNumber(negatives.size());
overView.setProcessingNumber((long) processingList.size());
overView.setCompletedNumber((long) completedList.size());
overView.setReportNumber((long) superviseReportList.size());
overView.setDepartNumber(accountabilityCountResult.unitCount());
overView.setPersonNumber(accountabilityCountResult.personTotalCount());
overView.setDepartNumber(accountabilityCountResult.newUnitCount());
overView.setPersonNumber(accountabilityCountResult.newPersonTotalCount());
return Result.success(new JSONObject().fluentPut("overview", overView));
}
@ -709,31 +673,8 @@ public class SubDatavServiceImpl implements SubDatavService {
List<Negative> ssNegative = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList();
// 交办案件数
List<Negative> jbNegatvieList = negatives.stream().filter(one -> ldjbCode.contains(one.getProblemSourcesCode())).toList();
NegativeBlameQueryParam negativeBlameQueryParam = new NegativeBlameQueryParam();
negativeBlameQueryParam.setNegativeIds(ssNegative.stream().map(Negative::getId).toList());
List<NegativeBlame> negativeBlames = negativeBlameResourceService.query(negativeBlameQueryParam);
// 3. 个人问责
List<NegativeBlame> personalBlames = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getHandleResultName()))
.filter(one -> !"不予追责".equals(one.getHandleResultName()))
.toList();
// 4. 领导问责(按 negativeId + 领导姓名 + 领导处理结果 去重)
Set<String> seenLead = new HashSet<>();
List<NegativeBlame> leadBlames = negativeBlames.stream()
.filter(one -> StrUtil.isNotBlank(one.getLeadHandleResultName()))
.filter(one -> !"不予追责".equals(one.getLeadHandleResultName()))
.filter(one -> seenLead.add(
one.getNegativeId() + "_" + one.getLeadHandleResultName() + "_" + one.getLeadName()
))
.toList();
// 5. 单位问责
List<NegativeBlame> unitBlames = negativeBlames.stream()
.filter(one -> BlameType.department.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getHandleResultName()))
.filter(one -> !"不予追责".equals(one.getHandleResultName()))
.toList();
// 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
Double verificationRate = 0.0;
if (!dataCaseVerifs.isEmpty() || !jbNegatvieList.isEmpty()) {
@ -744,8 +685,8 @@ public class SubDatavServiceImpl implements SubDatavService {
overview.setTotal(dataCaseVerifs.size() + jbNegatvieList.size());
overview.setConfirmed(ssNegative.size());
overview.setDealCasePro((long) negatives.size());
overview.setPunishPre((long) (personalBlames.size() + leadBlames.size()));
overview.setPunishOrg((long) unitBlames.size());
overview.setPunishPre(accountabilityCountResult.newPersonTotalCount());
overview.setPunishOrg(accountabilityCountResult.newUnitCount());
overview.setRate(verificationRate);
JSONObject res = new JSONObject().fluentPut("overview", overview);
return Result.success(res);
@ -772,33 +713,10 @@ public class SubDatavServiceImpl implements SubDatavService {
List<Negative> negatives = negativeMapper.getNegativeListData(pcs.getId(), request.getBeginTime(), request.getEndTime(), proCode);
// 交办案件数
List<Negative> jbNegatvieList = negatives.stream().filter(one -> ldjbCode.contains(one.getProblemSourcesCode())).toList();
// 问责情况
// 属实问题
List<Negative> ssNegative = negatives.stream().filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode()) || CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode())).toList();
NegativeBlameQueryParam negativeBlameQueryParam = new NegativeBlameQueryParam();
negativeBlameQueryParam.setNegativeIds(ssNegative.stream().map(Negative::getId).toList());
List<NegativeBlame> negativeBlames = negativeBlameResourceService.query(negativeBlameQueryParam);
// 3. 个人问责
List<NegativeBlame> personalBlames = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getHandleResultName()))
.filter(one -> !"不予追责".equals(one.getHandleResultName()))
.toList();
// 4. 领导问责(按 negativeId + 领导姓名 + 领导处理结果 去重)
Set<String> seenLead = new HashSet<>();
List<NegativeBlame> leadBlames = negativeBlames.stream()
.filter(one -> StrUtil.isNotBlank(one.getLeadHandleResultName()))
.filter(one -> !"不予追责".equals(one.getLeadHandleResultName()))
.filter(one -> seenLead.add(
one.getNegativeId() + "_" + one.getLeadHandleResultName() + "_" + one.getLeadName()
))
.toList();
// 5. 单位问责
List<NegativeBlame> unitBlames = negativeBlames.stream()
.filter(one -> BlameType.department.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getHandleResultName()))
.filter(one -> !"不予追责".equals(one.getHandleResultName()))
.toList();
// 与 DatavServiceImpl 保持一致:按“有效问题 + 多处理结果拆分 + negativeId/对象/处理结果去重”的口径统计。
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
int totalCaseCount = dataCaseVerifs.size() + jbNegatvieList.size();
double verificationRate = 0.0;
@ -813,8 +731,8 @@ public class SubDatavServiceImpl implements SubDatavService {
caseVerificationMapVo.setTotal(dataCaseVerifs.size() + jbNegatvieList.size());
caseVerificationMapVo.setConfirmed(ssNegative.size());
caseVerificationMapVo.setDealCasePro(negatives.size());
caseVerificationMapVo.setPunishPre(personalBlames.size() + leadBlames.size());
caseVerificationMapVo.setPunishOrg(unitBlames.size());
caseVerificationMapVo.setPunishPre(Math.toIntExact(accountabilityCountResult.newPersonTotalCount()));
caseVerificationMapVo.setPunishOrg(Math.toIntExact(accountabilityCountResult.newUnitCount()));
caseVerificationMapVo.setRate(verificationRate);
caseVerificationMapList.add(caseVerificationMapVo);
}
@ -855,7 +773,7 @@ public class SubDatavServiceImpl implements SubDatavService {
}
// 问责处理情况
AccountabilityCountResult accountabilityCountResult = this.buildAccountabilityCountResult(negatives);
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
for (Map.Entry<String, Long> entry : accountabilityCountResult.dealResultDistribution().entrySet()) {
EchartsVo echartsVo = new EchartsVo();
echartsVo.setName(entry.getKey());
@ -1034,18 +952,11 @@ public class SubDatavServiceImpl implements SubDatavService {
@Override
public Result<JSONObject> getSubOneResultCount( SubDataVRequest request) {
List<EchartsVo> resultCountArray = new ArrayList<>();
List<Negative> negatives = negativeMapper.getNegativeListData(request.getDepartId(), request.getBeginTime(), request.getEndTime(), GROUP_21_22_23_24_25);
DatavServiceImpl.BlameResult blameResult = this.buildBlameResult(negatives);
List<NegativeBlame> negativeBlames = blameResult.personalBlames();
// 问责处理情况与统一统计口径保持一致:先拆分多处理结果,再按单项处理结果聚合。
Map<String, Long> blames = negativeBlames.stream()
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream()
.map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName))
.map(item -> item.substring(item.lastIndexOf('_') + 1))
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
for (Map.Entry<String, Long> entry : blames.entrySet()) {
AccountabilityCountUtil.AccountabilityCountResult accountabilityCountResult = accountabilityCountUtil.buildAccountabilityCountResult(negatives);
List<EchartsVo> resultCountArray = new ArrayList<>();
for (Map.Entry<String, Long> entry : accountabilityCountResult.dealResultDistribution().entrySet()) {
EchartsVo echartsVo = new EchartsVo();
echartsVo.setName(entry.getKey());
echartsVo.setValue(entry.getValue().intValue());
@ -1169,310 +1080,6 @@ public class SubDatavServiceImpl implements SubDatavService {
.filter(e -> e.getValue() != null && e.getValue() > 0)
.toList();
}
public record BlameResult(
List<NegativeBlame> personalBlames,
List<NegativeBlame> leadBlames
) {
}
/**
* 统一问责统计口径
* 1. 仅统计核查属实部分属实的问题
* 2. 同一条问责记录中若包含多个处理结果按分隔符拆分后分别计数
* 3. 通过 negativeId + 问责对象 + 处理结果 去重避免重复累计
*/
private record AccountabilityCountResult(
long personalCount,
long leaderCount,
long personTotalCount,
long unitCount,
Map<String, Long> dealResultDistribution
) {
}
/**
* DatavServiceImpl 的问责人数问责单位数统计逻辑保持一致避免区县大屏与一级大屏口径不一致
*/
private AccountabilityCountResult buildAccountabilityCountResult(List<Negative> negatives) {
if (CollectionUtil.isEmpty(negatives)) {
return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of());
}
List<String> effectiveNegativeIds = negatives.stream()
.filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode())
|| CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode()))
.map(Negative::getId)
.filter(StrUtil::isNotBlank)
.distinct()
.toList();
if (CollectionUtil.isEmpty(effectiveNegativeIds)) {
return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of());
}
NegativeBlameQueryParam param = new NegativeBlameQueryParam();
param.setNegativeIds(effectiveNegativeIds);
List<NegativeBlame> negativeBlames = negativeBlameResourceService.query(param);
if (CollectionUtil.isEmpty(negativeBlames)) {
return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of());
}
long personalCount = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream()
.map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName))
.distinct()
.count();
long leaderCount = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> StrUtil.isNotBlank(one.getLeadName()))
.flatMap(one -> splitValidAccountabilityResults(one.getLeadHandleResultName()).stream()
.map(resultName -> one.getNegativeId() + "_" + one.getLeadName() + "_" + resultName))
.distinct()
.count();
long unitCount = negativeBlames.stream()
.filter(one -> BlameType.department.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream()
.map(resultName -> one.getNegativeId() + "_" + one.getBlameName() + "_" + resultName))
.distinct()
.count();
// 统计处理结果分布(普通人员 + 领导)
Map<String, Long> dealResultDistribution = buildDealResultDistribution(negativeBlames);
return new AccountabilityCountResult(
personalCount,
leaderCount,
personalCount + leaderCount,
unitCount,
dealResultDistribution
);
}
/**
* 构建处理结果分布统计普通人员 + 领导
* buildAccountabilityCountResult 中的 personalCount + leaderCount 保持口径一致
*/
private Map<String, Long> buildDealResultDistribution(List<NegativeBlame> negativeBlames) {
// 统计普通人员处理结果(type=personal + blameName非空)
Map<String, Long> personalResults = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream()
.map(result -> one.getNegativeId() + "_" + one.getBlameName() + "_" + result))
.distinct()
.collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting()));
// 统计领导处理结果(type=personal + blameName非空 + leadName非空)
Map<String, Long> leaderResults = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> StrUtil.isNotBlank(one.getLeadName()))
.flatMap(one -> splitValidAccountabilityResults(one.getLeadHandleResultName()).stream()
.map(result -> one.getNegativeId() + "_" + one.getLeadName() + "_" + result))
.distinct()
.collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting()));
// 合并
Map<String, Long> merged = new HashMap<>(personalResults);
leaderResults.forEach((key, value) -> merged.merge(key, value, Long::sum));
return merged;
}
private List<String> splitValidAccountabilityResults(String raw) {
if (StrUtil.isBlank(raw)) {
return List.of();
}
return Arrays.stream(raw.split("[、,,]"))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.filter(item -> !NO_ACCOUNTABILITY_SET.contains(item))
.distinct()
.toList();
}
public DatavServiceImpl.BlameResult buildBlameResult(List<Negative> negativeListData) {
if (CollUtil.isEmpty(negativeListData)) {
return new DatavServiceImpl.BlameResult(List.of(), List.of(), List.of());
}
// 1. 筛选有效 negative
List<Negative> validNegatives = negativeListData.stream()
.filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode())
|| CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode()))
.toList();
if (CollUtil.isEmpty(validNegatives)) {
return new DatavServiceImpl.BlameResult(List.of(), List.of(), List.of());
}
// 2. 查询问责数据
NegativeBlameQueryParam param = new NegativeBlameQueryParam();
param.setNegativeIds(validNegatives.stream()
.map(Negative::getId)
.toList());
List<NegativeBlame> negativeBlames = negativeBlameResourceService.query(param);
if (CollUtil.isEmpty(negativeBlames)) {
return new DatavServiceImpl.BlameResult(List.of(), List.of(), List.of());
}
// 3. 个人问责
List<NegativeBlame> personalBlames = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getHandleResultName()))
.filter(one -> !NO_BLAME.equals(one.getHandleResultName()))
.toList();
// 4. 领导问责(去重)
Set<String> seenLead = new HashSet<>();
List<NegativeBlame> leadBlames = negativeBlames.stream()
.filter(one -> StrUtil.isNotBlank(one.getLeadHandleResultName()))
.filter(one -> !NO_BLAME.equals(one.getLeadHandleResultName()))
.filter(one -> seenLead.add(
one.getNegativeId() + "_" + one.getLeadHandleResultName() + "_" + one.getLeadName()
))
.toList();
// 5. 单位问责
List<NegativeBlame> unitBlames = negativeBlames.stream()
.filter(one -> BlameType.department.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getHandleResultName()))
.filter(one -> !"不予追责".equals(one.getHandleResultName()))
.toList();
return new DatavServiceImpl.BlameResult(personalBlames, leadBlames, unitBlames);
}
private LocalDateTime toLocalDateTime(Date date) {
if (date == null) {
return null;
}
return date.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
}
private long calculateRate(long numerator, long denominator) {
if (denominator == 0) {
return 0L;
}
return (numerator * 100 + denominator / 2) / denominator;
}
private List<AuditNegativeVo> buildAuditNegativeVoList(List<SupDepart> departs, DataVRequest request) {
List<AuditNegativeVo> result = new ArrayList<>();
for (SupDepart depart : departs) {
List<Negative> negativeListData = negativeMapper.getNegativeListData(
depart.getId(),
request.getBeginTime(),
request.getEndTime(),
List.of(request.getAuditType())
);
long numerator = negativeListData.stream()
.filter(one -> "1".equals(one.getIsRectifyCode()))
.count();
long denominator = negativeListData.size();
AuditNegativeVo vo = new AuditNegativeVo();
vo.setLabel(depart.getShortName());
vo.setNumerator(numerator);
vo.setDenominator(denominator);
vo.setValue(calculateRate(numerator, denominator));
result.add(vo);
}
return result.stream()
// 过滤没有问题数据的
.filter(vo -> vo.getDenominator() > 0)
// 按整改率降序
.sorted(Comparator.comparing(AuditNegativeVo::getValue).reversed())
.toList();
}
private <T> BigDecimal sumAmount(List<T> list, Function<T, BigDecimal> mapper, BigDecimal divisor) {
BigDecimal sum = list.stream()
.map(mapper)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
if (divisor == null || BigDecimal.ONE.compareTo(divisor) == 0) {
return sum;
}
return sum.divide(divisor, 2, RoundingMode.HALF_UP);
}
private <T> BigDecimal sumAmountInWan(List<T> list, Function<T, BigDecimal> mapper) {
return list.stream()
.map(mapper)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add)
.divide(WAN, 2, RoundingMode.HALF_UP);
}
public Result<JSONObject> mockData() {
List<RankVo> fxsj = new ArrayList<>();
List<RankVo> jsdw = new ArrayList<>();
fxsj.add(build("城东派出所", "pcs_001", 15, 20, 8, 12));
fxsj.add(build("城西派出所", "pcs_002", 10, 18, 6, 12));
fxsj.add(build("开发区派出所", "pcs_003", 20, 30, 10, 20));
jsdw.add(build("刑侦大队", "team_001", 12, 15, 7, 8));
jsdw.add(build("治安大队", "team_002", 8, 12, 5, 7));
jsdw.add(build("网安大队", "team_003", 10, 25, 12, 13));
long total = Stream.concat(fxsj.stream(), jsdw.stream())
.mapToLong(vo -> Long.parseLong(vo.getDenominator()))
.sum();
long completed = Stream.concat(fxsj.stream(), jsdw.stream())
.mapToLong(vo -> Long.parseLong(vo.getNumerator()))
.sum();
long processing = total - completed;
double rate = total == 0 ? 0.0 :
BigDecimal.valueOf(completed)
.multiply(BigDecimal.valueOf(100))
.divide(BigDecimal.valueOf(total), 1, RoundingMode.HALF_UP)
.doubleValue();
DayTimeSuperviseVo overview = new DayTimeSuperviseVo();
overview.setProTotal((int) total);
overview.setProcessingNumber(processing);
overview.setCompletedNumber(completed);
overview.setCompletedRate(rate);
JSONObject data = new JSONObject()
.fluentPut("overview", overview)
.fluentPut("fxsjChangedRankList", fxsj)
.fluentPut("jsdwChangedRankList", jsdw);
return Result.success(data);
}
private RankVo build(String name, String id, int completed, int total, int city, int county) {
RankVo vo = new RankVo();
vo.setLabel(name);
vo.setDepartId(id);
vo.setNumerator(String.valueOf(completed));
vo.setDenominator(String.valueOf(total));
vo.setCityNumber(String.valueOf(city));
vo.setCountyNumber(String.valueOf(county));
String rate = BigDecimal.valueOf(completed)
.multiply(BigDecimal.valueOf(100))
.divide(BigDecimal.valueOf(total), 1, RoundingMode.HALF_UP)
.toString();
vo.setRate(rate);
vo.setValue(rate);
return vo;
}
// endregion

222
src/main/java/com/biutag/supervision/util/AccountabilityCountUtil.java

@ -0,0 +1,222 @@
package com.biutag.supervision.util;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.biutag.supervision.constants.enums.BlameType;
import com.biutag.supervision.constants.enums.CheckStatusEnum;
import com.biutag.supervision.pojo.entity.Negative;
import com.biutag.supervision.pojo.entity.NegativeBlame;
import com.biutag.supervision.pojo.param.negativeBlame.NegativeBlameQueryParam;
import com.biutag.supervision.repository.negativeBlame.NegativeBlameResourceService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 统一问责统计工具类
* 用于计算问责人次问责单位数等统计数据
*/
@Component
public class AccountabilityCountUtil {
@Resource
private NegativeBlameResourceService negativeBlameResourceService;
private static final Set<String> NO_ACCOUNTABILITY_SET = Set.of("不予问责", "不予追责");
/**
* 问责统计结果
*/
public record AccountabilityCountResult(
long personalCount,
long leaderCount,
long personTotalCount,
long unitCount,
Map<String, Long> dealResultDistribution,
// 问责人数(blameName非空 + 处理结果非"不予追责")
long newPersonalCount,
// 问责领导人数(blameName非空 + leadName非空 + 处理结果非"不予追责")
long newLeaderCount,
// 新问责总人数
long newPersonTotalCount,
// 问责单位数(blameName非空 + 处理结果非"不予问责"且非"不予追责")
long newUnitCount
) {
}
/**
* 构建问责统计结果
* 统一口径
* 1. 仅统计核查属实部分属实的问题
* 2. 同一条问责记录中若包含多个处理结果按分隔符拆分后分别计数
* 3. 通过 negativeId + 问责对象 + 处理结果 去重避免重复累计
*/
public AccountabilityCountResult buildAccountabilityCountResult(List<Negative> negatives) {
if (CollectionUtil.isEmpty(negatives)) {
return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L, 0L);
}
List<String> effectiveNegativeIds = negatives.stream()
.filter(one -> CheckStatusEnum.TRUE_SET.contains(one.getCheckStatusCode())
|| CheckStatusEnum.PART_TRUE_SET.contains(one.getCheckStatusCode()))
.map(Negative::getId)
.filter(StrUtil::isNotBlank)
.distinct()
.toList();
if (CollectionUtil.isEmpty(effectiveNegativeIds)) {
return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L, 0L);
}
NegativeBlameQueryParam param = new NegativeBlameQueryParam();
param.setNegativeIds(effectiveNegativeIds);
List<NegativeBlame> negativeBlames = negativeBlameResourceService.query(param);
if (CollectionUtil.isEmpty(negativeBlames)) {
return new AccountabilityCountResult(0L, 0L, 0L, 0L, Map.of(), 0L, 0L, 0L, 0L);
}
long personalCount = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> !isNoAccountability(one.getHandleResultName()))
.map(one -> one.getNegativeId() + "_" + one.getBlameName())
.distinct()
.count();
long leaderCount = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> StrUtil.isNotBlank(one.getLeadName()))
.filter(one -> !isNoAccountability(one.getLeadHandleResultName()))
.map(one -> one.getNegativeId() + "_" + one.getLeadName())
.distinct()
.count();
long unitCount = negativeBlames.stream()
.filter(one -> BlameType.department.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> !isNoAccountability(one.getHandleResultName()))
.map(one -> one.getNegativeId() + "_" + one.getBlameName())
.distinct()
.count();
// 统计处理结果分布(普通人员 + 领导)
Map<String, Long> dealResultDistribution = buildDealResultDistribution(negativeBlames);
// 问责人数(blameName非空 + 处理结果非"不予追责")
// 同一个问题(negativeId)+ 同一个人(blameName)只算1次
long newPersonalCount = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> !isNoAccountability(one.getHandleResultName()))
.map(one -> one.getNegativeId() + "_" + one.getBlameName())
.distinct()
.count();
// 问责领导人数(blameName非空 + leadName非空 + 处理结果非"不予追责")
// 同一个问题(negativeId)+ 同一个领导(leadName)只算1次
long newLeaderCount = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> StrUtil.isNotBlank(one.getLeadName()))
.filter(one -> !isNoAccountability(one.getLeadHandleResultName()))
.map(one -> one.getNegativeId() + "_" + one.getLeadName())
.distinct()
.count();
// 新问责总人数
long newPersonTotalCount = newPersonalCount + newLeaderCount;
// 问责单位数(blameName非空 + 处理结果非"不予问责"且非"不予追责")
// 同一个问题(negativeId)+ 同一个单位(blameName)只算1次
long newUnitCount = negativeBlames.stream()
.filter(one -> BlameType.department.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> !isNoAccountability(one.getHandleResultName()))
.map(one -> one.getNegativeId() + "_" + one.getBlameName())
.distinct()
.count();
return new AccountabilityCountResult(
personalCount,
leaderCount,
personalCount + leaderCount,
unitCount,
dealResultDistribution,
newPersonalCount,
newLeaderCount,
newPersonTotalCount,
newUnitCount
);
}
/**
* 构建处理结果分布统计普通人员 + 领导
* buildAccountabilityCountResult 中的 personalCount + leaderCount 保持口径一致
*/
private Map<String, Long> buildDealResultDistribution(List<NegativeBlame> negativeBlames) {
// 统计普通人员处理结果(type=personal + blameName非空)
Map<String, Long> personalResults = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.flatMap(one -> splitValidAccountabilityResults(one.getHandleResultName()).stream()
.map(result -> one.getNegativeId() + "_" + one.getBlameName() + "_" + result))
.distinct()
.collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting()));
// 统计领导处理结果(type=personal + blameName非空 + leadName非空)
Map<String, Long> leaderResults = negativeBlames.stream()
.filter(one -> BlameType.personal.name().equals(one.getType()))
.filter(one -> StrUtil.isNotBlank(one.getBlameName()))
.filter(one -> StrUtil.isNotBlank(one.getLeadName()))
.flatMap(one -> splitValidAccountabilityResults(one.getLeadHandleResultName()).stream()
.map(result -> one.getNegativeId() + "_" + one.getLeadName() + "_" + result))
.distinct()
.collect(Collectors.groupingBy(result -> result.substring(result.lastIndexOf("_") + 1), Collectors.counting()));
// 合并
Map<String, Long> merged = new HashMap<>(personalResults);
leaderResults.forEach((key, value) -> merged.merge(key, value, Long::sum));
return merged;
}
private List<String> splitValidAccountabilityResults(String raw) {
if (StrUtil.isBlank(raw)) {
return List.of();
}
return Arrays.stream(raw.split("[、,,]"))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.filter(item -> !NO_ACCOUNTABILITY_SET.contains(item))
.distinct()
.toList();
}
/**
* 判断问责情况是否全为"不予追责"即没有有效的问责处理结果
*
* @param raw 原始问责情况字符串
* @return true表示全部为"不予追责"false表示有有效问责处理结果
*/
private boolean isNoAccountability(String raw) {
if (StrUtil.isBlank(raw)) {
return true;
}
List<String> results = Arrays.stream(raw.split("[、,,]"))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.toList();
if (results.isEmpty()) {
return true;
}
return results.stream().allMatch(item -> NO_ACCOUNTABILITY_SET.contains(item));
}
}
Loading…
Cancel
Save