检测计划统计功能
This commit is contained in:
@@ -22,6 +22,7 @@ import com.njcn.gather.device.service.IPqDevService;
|
||||
import com.njcn.gather.plan.pojo.param.AdPlanParam;
|
||||
import com.njcn.gather.plan.pojo.po.AdPlan;
|
||||
import com.njcn.gather.plan.pojo.vo.AdPlanVO;
|
||||
import com.njcn.gather.plan.pojo.vo.PlanStatisticsVO;
|
||||
import com.njcn.gather.plan.service.AsyncPlanHandler;
|
||||
import com.njcn.gather.plan.service.IAdPlanService;
|
||||
import com.njcn.gather.type.pojo.po.DevType;
|
||||
@@ -198,6 +199,17 @@ public class AdPlanController extends BaseController {
|
||||
adPlanService.analyse(ids);
|
||||
}
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@PostMapping("/statistics")
|
||||
@ApiOperation("检测计划统计")
|
||||
@ApiImplicitParam(name = "param", value = "检测计划统计参数", required = true)
|
||||
public HttpResult<PlanStatisticsVO> statistics(@RequestBody @Validated AdPlanParam.StatisticsParam param) {
|
||||
String methodDescribe = getMethodDescribe("statistics");
|
||||
LogUtil.njcnDebug(log, "{},查询数据为:{}", methodDescribe, param);
|
||||
PlanStatisticsVO result = adPlanService.statistics(param.getPlanId());
|
||||
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
|
||||
}
|
||||
|
||||
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
|
||||
@PostMapping("/listByPlanId")
|
||||
@ApiOperation("查询出所有已绑定的设备")
|
||||
|
||||
@@ -130,4 +130,11 @@ public class AdPlanParam {
|
||||
private String patternId;
|
||||
private String scriptType;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class StatisticsParam {
|
||||
@ApiModelProperty(value = "检测计划ID", required = true)
|
||||
@NotBlank(message = DetectionValidMessage.PLAN_ID_NOT_BLANK)
|
||||
private String planId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.njcn.gather.plan.pojo.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 检测计划单个检测项统计结果。
|
||||
*/
|
||||
@Data
|
||||
public class PlanStatisticsItemVO {
|
||||
|
||||
/**
|
||||
* 检测项ID。
|
||||
*/
|
||||
private String itemId;
|
||||
|
||||
/**
|
||||
* 检测项名称。
|
||||
*/
|
||||
private String itemName;
|
||||
|
||||
/**
|
||||
* 执行次数。
|
||||
*/
|
||||
private Integer totalCount;
|
||||
|
||||
/**
|
||||
* 合格次数。
|
||||
*/
|
||||
private Integer qualifiedCount;
|
||||
|
||||
/**
|
||||
* 不合格次数。
|
||||
*/
|
||||
private Integer unqualifiedCount;
|
||||
|
||||
/**
|
||||
* 合格率,百分制。
|
||||
*/
|
||||
private BigDecimal passRate;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.njcn.gather.plan.pojo.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 检测计划统计结果。
|
||||
*/
|
||||
@Data
|
||||
public class PlanStatisticsVO {
|
||||
|
||||
/**
|
||||
* 检测计划ID。
|
||||
*/
|
||||
private String planId;
|
||||
|
||||
/**
|
||||
* 检测计划名称。
|
||||
*/
|
||||
private String planName;
|
||||
|
||||
/**
|
||||
* 所有设备检测次数之和。
|
||||
*/
|
||||
private Integer totalCheckCount;
|
||||
|
||||
/**
|
||||
* 已检设备总数。
|
||||
*/
|
||||
private Integer checkedDeviceCount;
|
||||
|
||||
/**
|
||||
* 第一次检测合格的设备数量。
|
||||
*/
|
||||
private Integer firstQualifiedDeviceCount;
|
||||
|
||||
/**
|
||||
* 第二次检测后合格的设备数量。
|
||||
*/
|
||||
private Integer secondQualifiedDeviceCount;
|
||||
|
||||
/**
|
||||
* 第三次及以上检测后合格的设备数量。
|
||||
*/
|
||||
private Integer thirdOrMoreQualifiedDeviceCount;
|
||||
|
||||
/**
|
||||
* 最终不合格的设备数量。
|
||||
*/
|
||||
private Integer unqualifiedDeviceCount;
|
||||
|
||||
/**
|
||||
* 存在不合格结果的检测项数量。
|
||||
*/
|
||||
private Integer unqualifiedItemCount;
|
||||
|
||||
/**
|
||||
* 一次合格率,百分制。
|
||||
*/
|
||||
private BigDecimal firstPassRate;
|
||||
|
||||
/**
|
||||
* 二次合格率,百分制。
|
||||
*/
|
||||
private BigDecimal secondPassRate;
|
||||
|
||||
/**
|
||||
* 三次及以上合格率,百分制。
|
||||
*/
|
||||
private BigDecimal thirdOrMorePassRate;
|
||||
|
||||
/**
|
||||
* 不合格率,百分制。
|
||||
*/
|
||||
private BigDecimal unqualifiedRate;
|
||||
|
||||
/**
|
||||
* 检测项分布。
|
||||
*/
|
||||
private List<PlanStatisticsItemVO> itemDistributions;
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import com.njcn.gather.device.pojo.po.PqStandardDev;
|
||||
import com.njcn.gather.plan.pojo.param.AdPlanParam;
|
||||
import com.njcn.gather.plan.pojo.po.AdPlan;
|
||||
import com.njcn.gather.plan.pojo.vo.AdPlanVO;
|
||||
import com.njcn.gather.plan.pojo.vo.PlanStatisticsVO;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -105,6 +106,14 @@ public interface IAdPlanService extends IService<AdPlan> {
|
||||
*/
|
||||
void analyse(List<String> ids);
|
||||
|
||||
/**
|
||||
* 统计检测计划结果。
|
||||
*
|
||||
* @param planId 检测计划ID
|
||||
* @return 检测计划统计结果
|
||||
*/
|
||||
PlanStatisticsVO statistics(String planId);
|
||||
|
||||
/**
|
||||
* 导出检测计划数据
|
||||
*
|
||||
|
||||
@@ -69,7 +69,9 @@ import com.njcn.gather.script.service.IPqScriptService;
|
||||
import com.njcn.gather.source.pojo.po.PqSource;
|
||||
import com.njcn.gather.source.service.IPqSourceService;
|
||||
import com.njcn.gather.storage.pojo.param.StorageParam;
|
||||
import com.njcn.gather.storage.pojo.po.SimAndDigBaseResult;
|
||||
import com.njcn.gather.storage.service.SimAndDigHarmonicService;
|
||||
import com.njcn.gather.storage.service.SimAndDigNonHarmonicService;
|
||||
import com.njcn.gather.storage.service.TableGenService;
|
||||
import com.njcn.gather.system.cfg.pojo.enums.SceneEnum;
|
||||
import com.njcn.gather.system.cfg.pojo.po.SysTestConfig;
|
||||
@@ -107,6 +109,8 @@ import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -133,6 +137,7 @@ public class AdPlanServiceImpl extends ServiceImpl<AdPlanMapper, AdPlan> impleme
|
||||
private final IDevTypeService devTypeService;
|
||||
private final IDictTypeService dictTypeService;
|
||||
private final SimAndDigHarmonicService adHarmonicService;
|
||||
private final SimAndDigNonHarmonicService adNonHarmonicService;
|
||||
private final PqDevMapper pqDevMapper;
|
||||
private final IPqDevSubService pqDevSubService;
|
||||
private final IAdPlanStandardDevService adPlanStandardDevService;
|
||||
@@ -555,6 +560,7 @@ public class AdPlanServiceImpl extends ServiceImpl<AdPlanMapper, AdPlan> impleme
|
||||
child.put("name", adPlan.getName());
|
||||
child.put("timeCheck", adPlan.getTimeCheck());
|
||||
child.put("dataRule", adPlan.getDataRule());
|
||||
child.put("testState", adPlan.getTestState());
|
||||
|
||||
List<PqStandardDev> pqStandardDevs = adPlanStandardDevMapper.listByPlanId(Collections.singletonList(adPlan.getId()));
|
||||
List<String> devTypeIdList = pqStandardDevs.stream().map(PqStandardDev::getDevType).collect(Collectors.toList());
|
||||
@@ -809,6 +815,234 @@ public class AdPlanServiceImpl extends ServiceImpl<AdPlanMapper, AdPlan> impleme
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlanStatisticsVO statistics(String planId) {
|
||||
AdPlan plan = this.getById(planId);
|
||||
if (ObjectUtil.isNull(plan)) {
|
||||
throw new BusinessException(DetectionResponseEnum.PLAN_NOT_EXIST);
|
||||
}
|
||||
if (!CheckStateEnum.CHECKED.getValue().equals(plan.getTestState())) {
|
||||
throw new BusinessException(DetectionResponseEnum.NOT_CHECKED_PLAN_CANNOT_ANALYSE);
|
||||
}
|
||||
|
||||
List<PqDevVO> checkedDevices = listCheckedDevices(plan.getId());
|
||||
PlanStatisticsVO statistics = new PlanStatisticsVO();
|
||||
statistics.setPlanId(plan.getId());
|
||||
statistics.setPlanName(plan.getName());
|
||||
statistics.setCheckedDeviceCount(checkedDevices.size());
|
||||
statistics.setTotalCheckCount(checkedDevices.stream().mapToInt(dev -> defaultZero(dev.getRecheckNum())).sum());
|
||||
|
||||
int firstQualifiedCount = (int) checkedDevices.stream()
|
||||
.filter(dev -> Objects.equals(dev.getRecheckNum(), 1))
|
||||
.filter(dev -> Objects.equals(dev.getCheckResult(), CheckResultEnum.ACCORD.getValue()))
|
||||
.count();
|
||||
int secondQualifiedCount = (int) checkedDevices.stream()
|
||||
.filter(dev -> Objects.equals(dev.getRecheckNum(), 2))
|
||||
.filter(dev -> Objects.equals(dev.getCheckResult(), CheckResultEnum.ACCORD.getValue()))
|
||||
.count();
|
||||
int thirdOrMoreQualifiedCount = (int) checkedDevices.stream()
|
||||
.filter(dev -> defaultZero(dev.getRecheckNum()) >= 3)
|
||||
.filter(dev -> Objects.equals(dev.getCheckResult(), CheckResultEnum.ACCORD.getValue()))
|
||||
.count();
|
||||
int unqualifiedDeviceCount = (int) checkedDevices.stream()
|
||||
.filter(dev -> Objects.equals(dev.getCheckResult(), CheckResultEnum.NOT_ACCORD.getValue()))
|
||||
.count();
|
||||
|
||||
statistics.setFirstQualifiedDeviceCount(firstQualifiedCount);
|
||||
statistics.setSecondQualifiedDeviceCount(secondQualifiedCount);
|
||||
statistics.setThirdOrMoreQualifiedDeviceCount(thirdOrMoreQualifiedCount);
|
||||
statistics.setUnqualifiedDeviceCount(unqualifiedDeviceCount);
|
||||
statistics.setFirstPassRate(rate(firstQualifiedCount, checkedDevices.size()));
|
||||
statistics.setSecondPassRate(rate(secondQualifiedCount, checkedDevices.size()));
|
||||
statistics.setThirdOrMorePassRate(rate(thirdOrMoreQualifiedCount, checkedDevices.size()));
|
||||
statistics.setUnqualifiedRate(rate(unqualifiedDeviceCount, checkedDevices.size()));
|
||||
|
||||
List<PlanStatisticsItemVO> itemDistributions = buildItemDistributions(plan, checkedDevices);
|
||||
statistics.setItemDistributions(itemDistributions);
|
||||
statistics.setUnqualifiedItemCount(itemDistributions.stream()
|
||||
.mapToInt(item -> defaultZero(item.getUnqualifiedCount()))
|
||||
.sum());
|
||||
return statistics;
|
||||
}
|
||||
|
||||
private List<PqDevVO> listCheckedDevices(String planId) {
|
||||
PqDevParam.QueryParam queryParam = new PqDevParam.QueryParam();
|
||||
queryParam.setPlanIdList(Collections.singletonList(planId));
|
||||
List<PqDevVO> pqDevVOList = pqDevMapper.selectByQueryParam(queryParam);
|
||||
if (CollUtil.isEmpty(pqDevVOList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return pqDevVOList.stream()
|
||||
.filter(dev -> !Objects.equals(dev.getCheckResult(), CheckResultEnum.UNCHECKED.getValue()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<PlanStatisticsItemVO> buildItemDistributions(AdPlan plan, List<PqDevVO> checkedDevices) {
|
||||
if (CollUtil.isEmpty(checkedDevices) || StrUtil.isBlank(plan.getScriptId()) || ObjectUtil.isNull(plan.getCode())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Map<Integer, ScriptItemInfo> scriptItemInfoMap = getScriptItemInfoMap(plan.getScriptId());
|
||||
if (CollUtil.isEmpty(scriptItemInfoMap)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Map<String, PlanStatisticsItemAccumulator> itemAccumulatorMap = new TreeMap<>();
|
||||
for (PqDevVO device : checkedDevices) {
|
||||
List<SimAndDigBaseResult> deviceResultList = new ArrayList<>();
|
||||
deviceResultList.addAll(adNonHarmonicService.listSimAndDigBaseResult(plan.getScriptId(), plan.getCode() + "", device.getId()));
|
||||
deviceResultList.addAll(adHarmonicService.listAllResultData(plan.getScriptId(), plan.getCode() + "", device.getId()));
|
||||
if (CollUtil.isEmpty(deviceResultList)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, List<SimAndDigBaseResult>> deviceItemResultMap = deviceResultList.stream()
|
||||
.filter(result -> ObjectUtil.isNotNull(result.getSort()))
|
||||
.map(result -> new AbstractMap.SimpleEntry<>(scriptItemInfoMap.get(result.getSort()), result))
|
||||
.filter(entry -> ObjectUtil.isNotNull(entry.getKey()))
|
||||
.collect(Collectors.groupingBy(
|
||||
entry -> entry.getKey().getItemId(),
|
||||
TreeMap::new,
|
||||
Collectors.mapping(Map.Entry::getValue, Collectors.toList())
|
||||
));
|
||||
|
||||
deviceItemResultMap.forEach((itemId, results) -> {
|
||||
boolean hasUnqualified = results.stream().anyMatch(result -> isUnqualifiedResultFlag(result.getResultFlag()));
|
||||
boolean hasQualified = results.stream().anyMatch(result -> Objects.equals(result.getResultFlag(), 1));
|
||||
if (!hasUnqualified && !hasQualified) {
|
||||
return;
|
||||
}
|
||||
|
||||
ScriptItemInfo itemInfo = scriptItemInfoMap.get(results.get(0).getSort());
|
||||
PlanStatisticsItemAccumulator accumulator = itemAccumulatorMap.computeIfAbsent(
|
||||
itemId,
|
||||
key -> new PlanStatisticsItemAccumulator(itemId, itemInfo.getItemName())
|
||||
);
|
||||
accumulator.totalCount++;
|
||||
if (hasUnqualified) {
|
||||
accumulator.unqualifiedCount++;
|
||||
} else {
|
||||
accumulator.qualifiedCount++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return itemAccumulatorMap.values().stream()
|
||||
.map(PlanStatisticsItemAccumulator::toVO)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Map<Integer, ScriptItemInfo> getScriptItemInfoMap(String scriptId) {
|
||||
List<PqScriptDtls> scriptDtlsList = pqScriptDtlsService.list(new LambdaQueryWrapper<PqScriptDtls>()
|
||||
.eq(PqScriptDtls::getScriptId, scriptId)
|
||||
.ne(PqScriptDtls::getScriptIndex, -1)
|
||||
.eq(PqScriptDtls::getEnable, DataStateEnum.ENABLE.getCode())
|
||||
);
|
||||
if (CollUtil.isEmpty(scriptDtlsList)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
List<String> scriptTypeIds = scriptDtlsList.stream()
|
||||
.map(PqScriptDtls::getScriptType)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
Map<String, DictTree> dictTreeMap = Collections.emptyMap();
|
||||
if (CollUtil.isNotEmpty(scriptTypeIds)) {
|
||||
dictTreeMap = dictTreeService.getDictTreeById(scriptTypeIds).stream()
|
||||
.collect(Collectors.toMap(DictTree::getId, dictTree -> dictTree, (left, right) -> left));
|
||||
}
|
||||
|
||||
Map<String, DictTree> finalDictTreeMap = dictTreeMap;
|
||||
return scriptDtlsList.stream()
|
||||
.collect(Collectors.groupingBy(PqScriptDtls::getScriptIndex, TreeMap::new, Collectors.toList()))
|
||||
.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> resolveScriptItemInfo(entry.getKey(), entry.getValue(), finalDictTreeMap),
|
||||
(left, right) -> left,
|
||||
TreeMap::new
|
||||
));
|
||||
}
|
||||
|
||||
private ScriptItemInfo resolveScriptItemInfo(Integer sort, List<PqScriptDtls> dtlsList, Map<String, DictTree> dictTreeMap) {
|
||||
if (CollUtil.isEmpty(dtlsList)) {
|
||||
return new ScriptItemInfo(String.valueOf(sort), "检测项" + sort);
|
||||
}
|
||||
PqScriptDtls first = dtlsList.get(0);
|
||||
DictTree dictTree = dictTreeMap.get(first.getScriptType());
|
||||
if (ObjectUtil.isNotNull(dictTree) && StrUtil.isNotBlank(dictTree.getName())) {
|
||||
return new ScriptItemInfo(dictTree.getId(), dictTree.getName());
|
||||
}
|
||||
if (StrUtil.isNotBlank(first.getScriptType())) {
|
||||
return new ScriptItemInfo(first.getScriptType(), "检测项" + sort);
|
||||
}
|
||||
return new ScriptItemInfo(String.valueOf(sort), "检测项" + sort);
|
||||
}
|
||||
|
||||
private boolean isUnqualifiedResultFlag(Integer resultFlag) {
|
||||
return ObjectUtil.isNotNull(resultFlag)
|
||||
&& !Objects.equals(resultFlag, 1)
|
||||
&& !Objects.equals(resultFlag, 4)
|
||||
&& !Objects.equals(resultFlag, 5);
|
||||
}
|
||||
|
||||
private Integer defaultZero(Integer value) {
|
||||
return ObjectUtil.isNull(value) ? 0 : value;
|
||||
}
|
||||
|
||||
private BigDecimal rate(Integer numerator, Integer denominator) {
|
||||
if (ObjectUtil.isNull(denominator) || denominator == 0) {
|
||||
return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
return BigDecimal.valueOf(defaultZero(numerator))
|
||||
.multiply(BigDecimal.valueOf(100))
|
||||
.divide(BigDecimal.valueOf(denominator), 2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
private class PlanStatisticsItemAccumulator {
|
||||
private final String itemId;
|
||||
private final String itemName;
|
||||
private int totalCount;
|
||||
private int qualifiedCount;
|
||||
private int unqualifiedCount;
|
||||
|
||||
private PlanStatisticsItemAccumulator(String itemId, String itemName) {
|
||||
this.itemId = itemId;
|
||||
this.itemName = itemName;
|
||||
}
|
||||
|
||||
private PlanStatisticsItemVO toVO() {
|
||||
PlanStatisticsItemVO itemVO = new PlanStatisticsItemVO();
|
||||
itemVO.setItemId(itemId);
|
||||
itemVO.setItemName(itemName);
|
||||
itemVO.setTotalCount(totalCount);
|
||||
itemVO.setQualifiedCount(qualifiedCount);
|
||||
itemVO.setUnqualifiedCount(unqualifiedCount);
|
||||
itemVO.setPassRate(rate(qualifiedCount, totalCount));
|
||||
return itemVO;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ScriptItemInfo {
|
||||
private final String itemId;
|
||||
private final String itemName;
|
||||
|
||||
private ScriptItemInfo(String itemId, String itemName) {
|
||||
this.itemId = itemId;
|
||||
this.itemName = itemName;
|
||||
}
|
||||
|
||||
private String getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
|
||||
private String getItemName() {
|
||||
return itemName;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportPlan(AdPlanParam.QueryParam queryParam) {
|
||||
DictData dictData = dictDataService.getDictDataById(queryParam.getPatternId());
|
||||
|
||||
Reference in New Issue
Block a user