diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/controller/ProcessStatisticsController.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/controller/ProcessStatisticsController.java index 7ebf22f..dfa1e40 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/sys/controller/ProcessStatisticsController.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/controller/ProcessStatisticsController.java @@ -1,8 +1,8 @@ package com.ningdatech.pmapi.sys.controller; -import com.ningdatech.pmapi.projectlib.enumeration.InstTypeEnum; import com.ningdatech.pmapi.sys.manage.ProcessStatisticsManage; import com.ningdatech.pmapi.sys.model.vo.ProcessDetailStatVO; +import io.swagger.annotations.ApiOperation; import lombok.AllArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; import javax.validation.constraints.NotNull; +import java.util.List; import java.util.concurrent.TimeUnit; /** @@ -30,10 +31,17 @@ public class ProcessStatisticsController { private final ProcessStatisticsManage processStatisticsManage; - @GetMapping("detailByInstType") - public ProcessDetailStatVO processDetailStat(@RequestParam(required = false, defaultValue = "DAYS") TimeUnit unit, - @Valid @NotNull(message = "流程类型不能为空") InstTypeEnum instType) { - return processStatisticsManage.processDetailStat(unit, instType); + @GetMapping("/detail") + @ApiOperation("流程统计详情") + public ProcessDetailStatVO processStatDetail(@RequestParam(required = false, defaultValue = "DAYS") TimeUnit unit, + @Valid @NotNull(message = "流程类型不能为空") Integer instType) { + return processStatisticsManage.processStatDetail(unit, instType); + } + + @GetMapping("/list") + @ApiOperation("流程统计详情列表") + public List listProcessStatDetail(@RequestParam(required = false, defaultValue = "DAYS") TimeUnit unit) { + return processStatisticsManage.processStatDetailList(unit); } } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/manage/ProcessStatisticsManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/manage/ProcessStatisticsManage.java index 7ad08f6..f5eb50a 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/sys/manage/ProcessStatisticsManage.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/manage/ProcessStatisticsManage.java @@ -14,9 +14,7 @@ import org.flowable.engine.HistoryService; import org.flowable.engine.history.HistoricProcessInstance; import org.springframework.stereotype.Component; -import java.util.HashSet; -import java.util.List; -import java.util.LongSummaryStatistics; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -35,14 +33,12 @@ public class ProcessStatisticsManage { private final HistoryService historyService; private final IProjectInstService projectInstService; - public ProcessDetailStatVO processDetailStat(TimeUnit unit, InstTypeEnum instType) { - if (!TimeUnit.DAYS.equals(unit) && !TimeUnit.HOURS.equals(unit)) { - throw BizException.wrap("仅支持以天和小时为单位的统计"); - } + public ProcessDetailStatVO processStatDetail(TimeUnit unit, Integer instType) { + unitCheck(unit); ProcessDetailStatVO detailStat = ProcessDetailStatVO.init(); LambdaQueryWrapper modelQuery = Wrappers.lambdaQuery(ProjectInst.class) .select(ProjectInst::getInstCode) - .eq(ProjectInst::getInstType, instType.getCode()); + .eq(ProjectInst::getInstType, instType); List projectInsts = projectInstService.list(modelQuery); if (projectInsts.isEmpty()) { return detailStat; @@ -51,24 +47,74 @@ public class ProcessStatisticsManage { List instances = historyService.createHistoricProcessInstanceQuery() .processInstanceIds(new HashSet<>(instCodeList)) .list(); - detailStat.setTotalInst(instances.size()); + buildProcessDetailStat(unit, detailStat, instances); + return detailStat; + } + + private static void unitCheck(TimeUnit unit) { + if (!TimeUnit.DAYS.equals(unit) && !TimeUnit.HOURS.equals(unit)) { + throw BizException.wrap("仅支持以天和小时为单位的统计"); + } + } + + private static void buildProcessDetailStat(TimeUnit unit, ProcessDetailStatVO stat, + List instances) { + stat.setTotalInst(instances.size()); LongSummaryStatistics statistics = instances.stream().filter(w -> { boolean finished = w.getEndTime() != null; if (finished) { - detailStat.incrFinished(); + stat.incrFinished(); } else { - detailStat.incrPending(); + stat.incrPending(); } return finished; }).map(HistoricProcessInstance::getDurationInMillis) .collect(Collectors.summarizingLong(Long::longValue)); - if (detailStat.getFinishedInst() != 0) { + if (stat.getFinishedInst() != 0) { long unitMillis = unit.toMillis(1); - detailStat.setAvgTime(NumberUtil.div(statistics.getAverage(), unitMillis, 1)); - detailStat.setMaxTime(NumberUtil.div(statistics.getMax(), unitMillis, 1)); - detailStat.setMinTime(NumberUtil.div(statistics.getMin(), unitMillis, 1)); + stat.setAvgTime(NumberUtil.div(statistics.getAverage(), unitMillis, 1)); + stat.setMaxTime(NumberUtil.div(statistics.getMax(), unitMillis, 1)); + stat.setMinTime(NumberUtil.div(statistics.getMin(), unitMillis, 1)); } - return detailStat; + } + + public List processStatDetailList(TimeUnit unit) { + unitCheck(unit); + List projectInsts = projectInstService.list(); + if (projectInsts.isEmpty()) { + return Collections.emptyList(); + } + HashSet instCodes = new HashSet<>(); + Map> mapByInstType = projectInsts.stream() + .filter(w -> InstTypeEnum.getByCode(w.getInstType()) != null) + .collect(Collectors.groupingBy(w -> InstTypeEnum.getByCode(w.getInstType()), + Collectors.mapping(w -> { + instCodes.add(w.getInstCode()); + return w.getInstCode(); + }, Collectors.toList()))); + List instances = historyService.createHistoricProcessInstanceQuery() + .processInstanceIds(new HashSet<>(instCodes)) + .list(); + List res = new ArrayList<>(); + for (Map.Entry> entry : mapByInstType.entrySet()) { + List currInstCodes = entry.getValue(); + List currInsts = new ArrayList<>(); + instances.removeIf(w -> { + boolean contains = currInstCodes.contains(w.getId()); + if (contains) { + currInsts.add(w); + } + return contains; + }); + ProcessDetailStatVO item = ProcessDetailStatVO.init(); + InstTypeEnum instType = entry.getKey(); + item.setInstType(instType.getCode()); + item.setInstTypeName(instType.getDesc()); + buildProcessDetailStat(unit, item, currInsts); + res.add(item); + } + res.sort(Comparator.comparing(ProcessDetailStatVO::getInstType)); + return res; } } diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/model/vo/ProcessDetailStatVO.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/model/vo/ProcessDetailStatVO.java index 6e92b4a..82b4bcb 100644 --- a/pmapi/src/main/java/com/ningdatech/pmapi/sys/model/vo/ProcessDetailStatVO.java +++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/model/vo/ProcessDetailStatVO.java @@ -16,6 +16,10 @@ import java.util.concurrent.TimeUnit; @Data public class ProcessDetailStatVO { + private Integer instType; + + private String instTypeName; + @ApiModelProperty("流程实例总数") private Integer totalInst;