diff --git a/dlp-drugtesting-api/src/main/java/digital/laboratory/platform/inspetion/api/entity/TestRecord.java b/dlp-drugtesting-api/src/main/java/digital/laboratory/platform/inspetion/api/entity/TestRecord.java index d863a23..6211506 100644 --- a/dlp-drugtesting-api/src/main/java/digital/laboratory/platform/inspetion/api/entity/TestRecord.java +++ b/dlp-drugtesting-api/src/main/java/digital/laboratory/platform/inspetion/api/entity/TestRecord.java @@ -93,4 +93,7 @@ public class TestRecord extends BaseEntity { @ApiModelProperty("实验结束时间") @JsonFormat(pattern = "yyyy/MM/dd", timezone = "GMT+8") private LocalDate testEndDate; + + @ApiModelProperty("业务Id,特指委托ID") + private String businessId; } diff --git a/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/dto/TestRecordSampleDataDocDTO.java b/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/dto/TestRecordSampleDataDocDTO.java index 7dbdb1e..7312ce0 100644 --- a/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/dto/TestRecordSampleDataDocDTO.java +++ b/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/dto/TestRecordSampleDataDocDTO.java @@ -3,6 +3,8 @@ package digital.laboratory.platform.inspection.dto; import digital.laboratory.platform.inspection.entity.TestRecordSampleData; import lombok.Data; +import java.math.BigDecimal; + @Data public class TestRecordSampleDataDocDTO extends TestRecordSampleData { @@ -53,4 +55,12 @@ public class TestRecordSampleDataDocDTO extends TestRecordSampleData { * 样本索引编号 */ private String indexNum; + + + /** + * 质荷比(m/z), nps案件 + * p 表示打印 (Print) + */ + private String pMassToChargeRatio; + } diff --git a/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/InspectRecordServiceImpl.java b/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/InspectRecordServiceImpl.java index 9aadd1f..22c6eba 100644 --- a/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/InspectRecordServiceImpl.java +++ b/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/InspectRecordServiceImpl.java @@ -1,4 +1,5 @@ package digital.laboratory.platform.inspection.service.impl; + import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; @@ -37,6 +38,7 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; +import java.math.BigDecimal; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -80,7 +82,7 @@ public class InspectRecordServiceImpl implements InspectRecordService { /** * 生成检验记录-贵阳禁毒 * - * @param businessId 委托id + * @param businessId 委托id * @param materialType 标注当前委托的检材是尿液还是毛发 * @return * @throws Exception @@ -141,19 +143,6 @@ public class InspectRecordServiceImpl implements InspectRecordService { // 生成基础数据 HashMap data = buildCommonInspectRecordDocMap(entrustInfo, testRecord, materialType); - // 获取仪器设备数据(批量查询,减少数据库压力) - List deviceIdList = testRecord.getDeviceIdList(); - List instruments = CollectionUtils.isEmpty(deviceIdList) - ? Collections.emptyList() - : testRecordInstrumentService.list(Wrappers.lambdaQuery() - .in(TestRecordInstrument::getId, deviceIdList)); - - data.put("instrumentName", CollectionUtils.isEmpty(instruments) - ? "未找到仪器设备数据!" - : instruments.stream() - .map(i -> "\u3000\u3000" + i.getInstrumentName()) // 使用 Unicode 全角空格 - .collect(Collectors.joining("\n"))); - // 获取样品数据 List dataList = testRecordSampleDataService.list( @@ -275,11 +264,138 @@ public class InspectRecordServiceImpl implements InspectRecordService { .collect(Collectors.toList())); // 返回处理后的数据 data.put("dataDtos", dataDtos); - data.put("sampleSize", dataDtos.size()); + data.put("sampleSize", dataDtos.size() / 2); data.put("inspectOpinion", this.buildInspectOpinion(dataList)); return data; } + public Map buildInVitroRecordData(EntrustInfo entrustInfo, TestRecord testRecord) { + Map data = new HashMap<>(); + + // 1️⃣ 按化合物名称分组 TestRecordSampleData + Map> compoundSampleDataMap = testRecordSampleDataService + .lambdaQuery() + .eq(TestRecordSampleData::getTestId, testRecord.getId()) + .list() + .stream() + .collect(Collectors.groupingBy(TestRecordSampleData::getCompoundName)); + + // 2️⃣ 过滤出 "标准物质" 类别的试剂,并转换为 Map (key=药品名称, value=试剂VO) + List reagentConsumablesList = testRecord.getReagentConsumablesList(); + Map reagentMap = reagentConsumablesList.stream() + .map(testRecordReagentService::getVOById) + .filter(vo -> "标准物质".equals(vo.getCategory())) // 仅保留 "标准物质" + .collect(Collectors.toMap(vo -> vo.getDrug().getName(), vo -> vo)); + + List dataDtos = new ArrayList<>(); + + // 3️⃣ 遍历每种化合物,处理实验数据 + for (Map.Entry> entry : compoundSampleDataMap.entrySet()) { + String compoundName = entry.getKey(); + List sampleDataList = entry.getValue(); + + // 按 sampleType 分组(如 STD, Analyte) + Map> sampleTypeMap = sampleDataList.stream() + .collect(Collectors.groupingBy(TestRecordSampleData::getSampleType)); + + // 获取标准样本(STD) + List stdList = sampleTypeMap.get("STD"); + if (stdList == null || stdList.isEmpty()) { + continue; // 没有 STD 样本,跳过该化合物 + } + TestRecordSampleData stdSample = stdList.get(0); + + // 4️⃣ 获取 STD 样本的扩展数据 (以 MassToChargeRatio 为 key) + Map expandMap = testRecordSampledataExpandService.lambdaQuery() + .eq(TestRecordSampleDataExpand::getTestDataId, stdSample.getId()) + .list() + .stream() + .collect(Collectors.toMap(TestRecordSampleDataExpand::getMassToChargeRatio, Function.identity())); + + // 5️⃣ 获取当前化合物对应的试剂,提取特征离子 + TestRecordReagentVO reagentVO = reagentMap.get(compoundName); + if (reagentVO == null || reagentVO.getDrug().getCharacteristicIons() == null) { + continue; // 没有对应试剂或特征离子数据,跳过 + } + String[] peaks = reagentVO.getDrug().getCharacteristicIons().split("、"); + + // 6️⃣ 处理 "标样" 数据 (STD) + for (int i = 0; i < peaks.length; i++) { + String peak = (i == 0) ? peaks[i].substring(0, peaks[i].length() - 1) : peaks[i]; + TestRecordSampleDataExpand expand = expandMap.get(new BigDecimal(peak)); + + if (expand != null) { + TestRecordSampleDataDocDTO dto = new TestRecordSampleDataDocDTO(); + BeanUtils.copyProperties(stdSample, dto); + dto.setName("标样"); + dto.setPTargetRtTime(dto.getTargetRtTime().toString()); + dto.setPRtTimeError("±1"); + dto.setPRtTimeWithinError("/"); + dto.setPMassToChargeRatio(i == 0 ? peak + "(基峰)" : peak); + dto.setPIonAbundanceRatio(expand.getIonAbundanceRatio().toString()); + dto.setPIonAbundanceRatioError(expand.getIonAbundanceRatioError().toString()); + dto.setPIonAbundanceRatioWithinError(expand.getIonAbundanceRatioWithinError()); + dto.setPIsDetected("/"); + dataDtos.add(dto); + } + } + + // 7️⃣ 处理 "标样空白" 数据 + for (String peak : peaks) { + TestRecordSampleDataDocDTO dto = new TestRecordSampleDataDocDTO(); + dto.setName("标样空白"); + dto.setCompoundName(compoundName); + dto.setPTargetRtTime("/"); + dto.setPRtTimeError("/"); + dto.setPRtTimeWithinError("/"); + dto.setPMassToChargeRatio(peak.equals(peaks[0]) ? peak + "(基峰)" : peak); + dto.setPIonAbundanceRatio("/"); + dto.setPIonAbundanceRatioError("/"); + dto.setPIonAbundanceRatioWithinError(peak.equals(peaks[0]) ? "/" : "否"); + dto.setPIsDetected("/"); + dataDtos.add(dto); + } + + // 8️⃣ 处理 "Analyte" 样本 + List analyteList = sampleTypeMap.get("Analyte"); + if (analyteList != null) { + analyteList.sort(testRecordSampleDataService.getSortBySampleNo()); // 按样本编号排序 + + for (TestRecordSampleData analyte : analyteList) { + Map analyteExpandMap = testRecordSampledataExpandService.lambdaQuery() + .eq(TestRecordSampleDataExpand::getTestDataId, analyte.getId()) + .list() + .stream() + .collect(Collectors.toMap(TestRecordSampleDataExpand::getMassToChargeRatio, Function.identity())); + + for (int i = 0; i < peaks.length; i++) { + String peak = (i == 0) ? peaks[i].substring(0, peaks[i].length() - 1) : peaks[i]; + TestRecordSampleDataExpand expand = analyteExpandMap.get(new BigDecimal(peak)); + + if (expand != null) { + TestRecordSampleDataDocDTO dto = new TestRecordSampleDataDocDTO(); + BeanUtils.copyProperties(analyte, dto); + dto.setPTargetRtTime(dto.getTargetRtTime().toString()); + dto.setPRtTimeError(dto.getRtTimeWithinError()); + dto.setPRtTimeWithinError(dto.getRtTimeWithinError()); + dto.setPMassToChargeRatio(i == 0 ? peak + "(基峰)" : peak); + dto.setPIonAbundanceRatio(expand.getIonAbundanceRatio().toString()); + dto.setPIonAbundanceRatioError(expand.getIonAbundanceRatioError().toString()); + dto.setPIonAbundanceRatioWithinError(expand.getIonAbundanceRatioWithinError()); + dto.setPIsDetected(dto.getIsDetected() == 1 ? "是" : "否"); + dataDtos.add(dto); + } + } + } + } + } + + // 9️⃣ 返回处理后的数据 + data.put("dataDtos", dataDtos); + return data; + } + + public void buildIonPairAndCE(Map data, List reagentIdList) { List ionPairAndCEVOS = new ArrayList<>(); @@ -387,14 +503,20 @@ public class InspectRecordServiceImpl implements InspectRecordService { /** * 生成常规毒品的检验记录(贵阳禁毒) */ - public String generateCommonDrugInpectRecord(String entrustId) throws Exception { - Map docMap = buildCommonDrugDocMap(entrustId); + public String generateCommonDrugInpectRecord(String businessId) throws Exception { + Map docMap = buildCommonDrugDocMap(businessId); + EntrustInfo entrustInfo = entrustInfoService.getById(businessId); + TestRecord testRecord = testRecordService.lambdaQuery() + .eq(TestRecord::getBusinessId, businessId) + .one(); + Map data = this.buildInVitroRecordData(entrustInfo, testRecord); + docMap.putAll(data); String templatePath = "/template" + "/贵阳禁毒常规毒品检验记录模板.docx"; LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy(); Configure config = Configure.builder(). bind("dataDtos", policy) .build(); - return buildDocFileAndUploadToOss(entrustId, templatePath, config, docMap); + return buildDocFileAndUploadToOss(businessId, templatePath, config, docMap); } /** @@ -402,8 +524,8 @@ public class InspectRecordServiceImpl implements InspectRecordService { * * @return */ - private Map buildCommonDrugDocMap(String entrustId) { - EntrustInfo entrustInfo = entrustInfoService.getById(entrustId); + private Map buildCommonDrugDocMap(String businessId) { + EntrustInfo entrustInfo = entrustInfoService.getById(businessId); // 这里因为检验记录实体并未关联业务id, 只能先查询实验数据,在通过实验数据获取到检验记录信息 TestRecord testRecord = testRecordService.getTestRecordByBusinessId(entrustInfo.getId()); @@ -411,6 +533,7 @@ public class InspectRecordServiceImpl implements InspectRecordService { // 封装数据到map中 Map docMap = buildCommonInspectRecordDocMap(entrustInfo, testRecord, ""); + return docMap; } @@ -461,6 +584,20 @@ public class InspectRecordServiceImpl implements InspectRecordService { data.put("materialCharacterDesc", materialCharacterDesc); data.put("materialIngredient", targetObjectStr); + // 获取仪器设备数据(批量查询,减少数据库压力) + List deviceIdList = testRecord.getDeviceIdList(); + List instruments = CollectionUtils.isEmpty(deviceIdList) + ? Collections.emptyList() + : testRecordInstrumentService.list(Wrappers.lambdaQuery() + .in(TestRecordInstrument::getId, deviceIdList)); + + data.put("instrumentName", CollectionUtils.isEmpty(instruments) + ? "未找到仪器设备数据!" + : instruments.stream() + .map(i -> "\u3000\u3000" + i.getInstrumentName()) // 使用 Unicode 全角空格 + .collect(Collectors.joining("\n"))); + + // 设置使用的标准物质和试剂 List references = testRecordReagentService.list(Wrappers.lambdaQuery() .in(TestRecordReagent::getId, testRecord.getReagentConsumablesList()) diff --git a/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/TestRecordServiceImpl.java b/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/TestRecordServiceImpl.java index 7014b16..6497be5 100644 --- a/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/TestRecordServiceImpl.java +++ b/dlp-drugtesting-biz/src/main/java/digital/laboratory/platform/inspection/service/impl/TestRecordServiceImpl.java @@ -161,6 +161,9 @@ public class TestRecordServiceImpl extends ServiceImpl 0) { + if (testRecord.getBusinessDtoList().size()>1){ + throw new RuntimeException("一次只能选择一个业务!"); + } List businessDtoList = testRecord.getBusinessDtoList(); this.judgmentBusinessType(businessDtoList);//判断是否有不同类型的业务 businessDtoList.forEach(item -> { @@ -183,6 +186,7 @@ public class TestRecordServiceImpl extends ServiceImpl