package cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.*;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDetailDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcLineDO;
|
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 cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcLineService;
|
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameters;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
import jakarta.annotation.Resource;
|
import jakarta.validation.Valid;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.validation.annotation.Validated;
|
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;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
|
|
@Tag(name = "管理后台 - MES 检验结果")
|
@RestController
|
@RequestMapping("/mes/qc/indicator-result")
|
@Validated
|
public class MesQcIndicatorResultController {
|
|
@Resource
|
private MesQcIndicatorResultService resultService;
|
@Resource
|
private MesQcReportService reportService;
|
@Resource
|
private MesQcIqcLineService iqcLineService;
|
@Resource
|
private MesQcIpqcLineService ipqcLineService;
|
@Resource
|
private MesQcOqcLineService oqcLineService;
|
@Resource
|
private MesQcRqcLineService rqcLineService;
|
@Resource
|
private MesQcIndicatorService indicatorService;
|
|
@PostMapping("/create")
|
@Operation(summary = "创建检验结果")
|
@PreAuthorize("@ss.hasPermission('mes:qc-iqc:create')")
|
public CommonResult<Long> createIndicatorResult(@Valid @RequestBody MesQcIndicatorResultSaveReqVO createReqVO) {
|
return success(resultService.createIndicatorResult(createReqVO));
|
}
|
|
@PutMapping("/update")
|
@Operation(summary = "更新检验结果")
|
@PreAuthorize("@ss.hasPermission('mes:qc-iqc:update')")
|
public CommonResult<Boolean> updateIndicatorResult(@Valid @RequestBody MesQcIndicatorResultSaveReqVO updateReqVO) {
|
resultService.updateIndicatorResult(updateReqVO);
|
return success(true);
|
}
|
|
@DeleteMapping("/delete")
|
@Operation(summary = "删除检验结果")
|
@Parameter(name = "id", description = "编号", required = true)
|
@PreAuthorize("@ss.hasPermission('mes:qc-iqc:delete')")
|
public CommonResult<Boolean> deleteIndicatorResult(@RequestParam("id") Long id) {
|
resultService.deleteIndicatorResult(id);
|
return success(true);
|
}
|
|
@GetMapping("/get-detail")
|
@Operation(summary = "获得检验结果明细(含检测项模板)")
|
@Parameters({
|
@Parameter(name = "id", description = "检验结果编号(编辑时传入;新增时不传)", example = "1024"),
|
@Parameter(name = "qcId", description = "质检单ID", required = true, example = "1"),
|
@Parameter(name = "qcType", description = "质检类型", required = true, example = "1")
|
})
|
@PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')")
|
public CommonResult<MesQcIndicatorResultRespVO> getIndicatorResultDetail(
|
@RequestParam(value = "id", required = false) Long id,
|
@RequestParam("qcId") Long qcId,
|
@RequestParam("qcType") Integer qcType) {
|
MesQcIndicatorResultRespVO respVO;
|
List<MesQcIndicatorResultDetailDO> details;
|
if (id != null) {
|
// 编辑:加载已有结果主表 + 已有明细
|
MesQcIndicatorResultDO result = resultService.getIndicatorResult(id);
|
respVO = BeanUtils.toBean(result, MesQcIndicatorResultRespVO.class);
|
details = resultService.getIndicatorResultDetailListByResultId(id);
|
} else {
|
// 新增:返回空壳 RespVO,仅填充检测项模板
|
respVO = new MesQcIndicatorResultRespVO();
|
details = Collections.emptyList();
|
}
|
respVO.setItems(buildDetailItemList(details, qcId, qcType));
|
return success(respVO);
|
}
|
|
@GetMapping("/page")
|
@Operation(summary = "获得检验结果分页")
|
@PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')")
|
public CommonResult<PageResult<MesQcIndicatorResultRespVO>> getIndicatorResultPage(@Valid MesQcIndicatorResultPageReqVO pageReqVO) {
|
PageResult<MesQcIndicatorResultDO> pageResult = resultService.getIndicatorResultPage(pageReqVO);
|
// 前端列表只展示 code、sn、remark,无需关联查询
|
PageResult<MesQcIndicatorResultRespVO> voPageResult = BeanUtils.toBean(pageResult, MesQcIndicatorResultRespVO.class);
|
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 树(支持分组层级 + 平行测量多批次)
|
*
|
* <p>返回树形列表:顶级为分组项或独立录入项,分组项 children 挂子项;
|
* 每个录入项的平行测量值放在 measures(按 measureNo 升序);
|
* 兼容字段 id/value/remark 取第一批值,供旧数据直接展示</p>
|
*
|
* @param details 已有结果明细(空列表表示获取空值模板)
|
* @param qcId 质检单 ID
|
* @param qcType 质检类型
|
*/
|
private List<MesQcIndicatorResultRespVO.Item> buildDetailItemList(
|
List<MesQcIndicatorResultDetailDO> details, Long qcId, Integer qcType) {
|
// 1.1 获取检验单行的指标 ID 列表(知道有哪些检测指标)
|
List<Long> indicatorIds;
|
if (Objects.equals(qcType, MesQcTypeEnum.IQC.getType())) {
|
List<MesQcIqcLineDO> lines = iqcLineService.getIqcLineListByIqcId(qcId);
|
indicatorIds = CollUtil.isEmpty(lines) ? Collections.emptyList()
|
: new ArrayList<>(convertSet(lines, MesQcIqcLineDO::getIndicatorId));
|
} else if (Objects.equals(qcType, MesQcTypeEnum.IPQC.getType())) {
|
List<MesQcIpqcLineDO> lines = ipqcLineService.getIpqcLineListByIpqcId(qcId);
|
indicatorIds = CollUtil.isEmpty(lines) ? Collections.emptyList()
|
: new ArrayList<>(convertSet(lines, MesQcIpqcLineDO::getIndicatorId));
|
} else if (Objects.equals(qcType, MesQcTypeEnum.OQC.getType())) {
|
List<MesQcOqcLineDO> lines = oqcLineService.getOqcLineListByOqcId(qcId);
|
indicatorIds = CollUtil.isEmpty(lines) ? Collections.emptyList()
|
: new ArrayList<>(convertSet(lines, MesQcOqcLineDO::getIndicatorId));
|
} else if (Objects.equals(qcType, MesQcTypeEnum.RQC.getType())) {
|
List<MesQcRqcLineDO> lines = rqcLineService.getRqcLineListByRqcId(qcId);
|
indicatorIds = CollUtil.isEmpty(lines) ? Collections.emptyList()
|
: new ArrayList<>(convertSet(lines, MesQcRqcLineDO::getIndicatorId));
|
} else {
|
throw new IllegalArgumentException("暂不支持 qcType=" + qcType);
|
}
|
if (CollUtil.isEmpty(indicatorIds)) {
|
return Collections.emptyList();
|
}
|
|
// 1.2 批量查询检测指标;子项的父分组未挂在行上时自动补全,保证树完整
|
Map<Long, MesQcIndicatorDO> indicatorMap = indicatorService.getIndicatorMap(new HashSet<>(indicatorIds));
|
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));
|
}
|
|
// 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)
|
.setIndicatorName(indicator.getName())
|
.setValueType(indicator.getResultType())
|
.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);
|
}
|
|
// 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;
|
}
|
|
}
|