| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcLineDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcLineDO; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.qc.MesQcIndicatorItemTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; |
| | | import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService; |
| | | import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcReportService; |
| | | import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcLineService; |
| | | import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcLineService; |
| | | import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcLineService; |
| | |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| | | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| | |
| | | |
| | | @Resource |
| | | private MesQcIndicatorResultService resultService; |
| | | @Resource |
| | | private MesQcReportService reportService; |
| | | @Resource |
| | | private MesQcIqcLineService iqcLineService; |
| | | @Resource |
| | |
| | | return success(voPageResult); |
| | | } |
| | | |
| | | @GetMapping("/report") |
| | | @Operation(summary = "获得检验报告单数据(打印用:表头 + 检验项树 + 平行测量 + 签字区)") |
| | | @Parameters({ |
| | | @Parameter(name = "qcId", description = "质检单ID", required = true, example = "1"), |
| | | @Parameter(name = "qcType", description = "质检类型", required = true, example = "1"), |
| | | @Parameter(name = "resultId", description = "检验结果(样品)编号,可不传;多样品时用于选择", example = "1") |
| | | }) |
| | | @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')") |
| | | public CommonResult<MesQcQcReportRespVO> getQcReportData( |
| | | @RequestParam("qcId") Long qcId, |
| | | @RequestParam("qcType") Integer qcType, |
| | | @RequestParam(value = "resultId", required = false) Long resultId) { |
| | | return success(reportService.getQcReportData(qcId, qcType, resultId)); |
| | | } |
| | | |
| | | // ==================== 拼接 VO ==================== |
| | | |
| | | /** |
| | | * 构建明细 Item 列表 |
| | | * 构建明细 Item 树(支持分组层级 + 平行测量多批次) |
| | | * |
| | | * <p>前端表单仅需:indicatorId、indicatorName、valueType、valueSpecification + 已有结果(id、value、remark)</p> |
| | | * <p>返回树形列表:顶级为分组项或独立录入项,分组项 children 挂子项; |
| | | * 每个录入项的平行测量值放在 measures(按 measureNo 升序); |
| | | * 兼容字段 id/value/remark 取第一批值,供旧数据直接展示</p> |
| | | * |
| | | * @param details 已有结果明细(空列表表示获取空值模板) |
| | | * @param qcId 质检单 ID |
| | |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | // 1.2 批量查询检测指标 |
| | | // 1.2 批量查询检测指标;子项的父分组未挂在行上时自动补全,保证树完整 |
| | | Map<Long, MesQcIndicatorDO> indicatorMap = indicatorService.getIndicatorMap(new HashSet<>(indicatorIds)); |
| | | // 1.3 构建已有明细 Map(按 indicatorId 索引) |
| | | Map<Long, MesQcIndicatorResultDetailDO> detailMap = CollUtil.isEmpty(details) |
| | | ? Collections.emptyMap() |
| | | : convertMap(details, MesQcIndicatorResultDetailDO::getIndicatorId); |
| | | Set<Long> missingParentIds = indicatorMap.values().stream() |
| | | .filter(ind -> ind.getParentId() != null && ind.getParentId() > 0 |
| | | && !indicatorMap.containsKey(ind.getParentId())) |
| | | .map(MesQcIndicatorDO::getParentId).collect(Collectors.toSet()); |
| | | if (CollUtil.isNotEmpty(missingParentIds)) { |
| | | indicatorMap.putAll(indicatorService.getIndicatorMap(missingParentIds)); |
| | | } |
| | | |
| | | // 2. 遍历指标 ID,组装 VO |
| | | List<MesQcIndicatorResultRespVO.Item> voList = new ArrayList<>(indicatorIds.size()); |
| | | for (Long indicatorId : indicatorIds) { |
| | | // 1.3 已有明细分组(indicatorId -> 多批次列表) |
| | | Map<Long, List<MesQcIndicatorResultDetailDO>> detailMap = CollUtil.isEmpty(details) |
| | | ? Collections.emptyMap() |
| | | : details.stream().collect(Collectors.groupingBy(MesQcIndicatorResultDetailDO::getIndicatorId)); |
| | | |
| | | // 2. 构建节点 |
| | | Map<Long, MesQcIndicatorResultRespVO.Item> nodeMap = new LinkedHashMap<>(); |
| | | for (Map.Entry<Long, MesQcIndicatorDO> entry : indicatorMap.entrySet()) { |
| | | Long indicatorId = entry.getKey(); |
| | | MesQcIndicatorDO indicator = entry.getValue(); |
| | | MesQcIndicatorResultRespVO.Item vo = new MesQcIndicatorResultRespVO.Item() |
| | | .setIndicatorId(indicatorId); |
| | | // 来自 indicator |
| | | findAndThen(indicatorMap, indicatorId, indicator -> vo |
| | | .setIndicatorId(indicatorId) |
| | | .setIndicatorName(indicator.getName()) |
| | | .setValueType(indicator.getResultType()) |
| | | .setValueSpecification(indicator.getResultSpecification())); |
| | | // 来自已有结果明细(如有) |
| | | findAndThen(detailMap, indicatorId, detail -> vo |
| | | .setId(detail.getId()).setResultId(detail.getResultId()) |
| | | .setValue(detail.getValue()).setRemark(detail.getRemark())); |
| | | voList.add(vo); |
| | | .setValueSpecification(indicator.getResultSpecification()) |
| | | .setParentId(Objects.requireNonNullElse(indicator.getParentId(), 0L)) |
| | | .setItemType(Objects.requireNonNullElse(indicator.getItemType(), |
| | | MesQcIndicatorItemTypeEnum.RECORD.getType())) |
| | | .setFormulaText(indicator.getFormulaText()) |
| | | .setUnitText(indicator.getUnitText()) |
| | | .setSortOrder(Objects.requireNonNullElse(indicator.getSortOrder(), 0)); |
| | | List<MesQcIndicatorResultDetailDO> itemDetails = detailMap.getOrDefault(indicatorId, Collections.emptyList()); |
| | | List<MesQcIndicatorResultRespVO.Measure> measures = new ArrayList<>(itemDetails.size()); |
| | | itemDetails.stream() |
| | | .sorted(Comparator.comparing(d -> Objects.requireNonNullElse(d.getMeasureNo(), 1))) |
| | | .forEach(detail -> measures.add(new MesQcIndicatorResultRespVO.Measure() |
| | | .setDetailId(detail.getId()).setResultId(detail.getResultId()) |
| | | .setMeasureNo(Objects.requireNonNullElse(detail.getMeasureNo(), 1)) |
| | | .setValue(detail.getValue()).setRemark(detail.getRemark()))); |
| | | vo.setMeasures(measures); |
| | | // 兼容旧字段:取第一批测量值 |
| | | if (CollUtil.isNotEmpty(measures)) { |
| | | MesQcIndicatorResultRespVO.Measure first = measures.get(0); |
| | | vo.setId(first.getDetailId()).setResultId(first.getResultId()) |
| | | .setValue(first.getValue()).setRemark(first.getRemark()); |
| | | } |
| | | nodeMap.put(indicatorId, vo); |
| | | } |
| | | return voList; |
| | | |
| | | // 3. 挂树:父不在集合内的子项提升为顶级;同级按排序号 |
| | | Comparator<MesQcIndicatorResultRespVO.Item> byOrder = |
| | | Comparator.comparing(MesQcIndicatorResultRespVO.Item::getSortOrder) |
| | | .thenComparing(MesQcIndicatorResultRespVO.Item::getIndicatorId); |
| | | List<MesQcIndicatorResultRespVO.Item> roots = new ArrayList<>(); |
| | | for (MesQcIndicatorResultRespVO.Item node : nodeMap.values()) { |
| | | MesQcIndicatorResultRespVO.Item parent = node.getParentId() > 0 ? nodeMap.get(node.getParentId()) : null; |
| | | if (parent == null) { |
| | | roots.add(node); |
| | | } else { |
| | | if (parent.getChildren() == null) { |
| | | parent.setChildren(new ArrayList<>()); |
| | | } |
| | | parent.getChildren().add(node); |
| | | } |
| | | } |
| | | roots.sort(byOrder); |
| | | roots.forEach(root -> { |
| | | if (root.getChildren() != null) { |
| | | root.getChildren().sort(byOrder); |
| | | } |
| | | }); |
| | | return roots; |
| | | } |
| | | |
| | | } |