将常规毒品鉴定报告的功能从文书系统迁移至送检受理系统
This commit is contained in:
@@ -3,6 +3,7 @@ package digital.laboratory.platform.entrustment.service.impl;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
@@ -32,18 +33,20 @@ import digital.laboratory.platform.entrustment.vo.DetectionRateVO;
|
|||||||
import digital.laboratory.platform.entrustment.vo.EntrustMaterialCheckoutResultVO;
|
import digital.laboratory.platform.entrustment.vo.EntrustMaterialCheckoutResultVO;
|
||||||
import digital.laboratory.platform.entrustment.vo.EntrustmentIdentificationMaterialVO;
|
import digital.laboratory.platform.entrustment.vo.EntrustmentIdentificationMaterialVO;
|
||||||
import digital.laboratory.platform.entrustment.vo.SuspectDetectionVO;
|
import digital.laboratory.platform.entrustment.vo.SuspectDetectionVO;
|
||||||
|
import digital.laboratory.platform.othersys.utils.HttpsUtils;
|
||||||
import digital.laboratory.platform.sys.entity.Area;
|
import digital.laboratory.platform.sys.entity.Area;
|
||||||
import digital.laboratory.platform.sys.entity.DrugLite;
|
import digital.laboratory.platform.sys.entity.DrugLite;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.poi.ss.usermodel.*;
|
import org.apache.poi.ss.usermodel.*;
|
||||||
import org.apache.poi.ss.util.CellRangeAddress;
|
import org.apache.poi.ss.util.CellRangeAddress;
|
||||||
import org.apache.poi.xssf.usermodel.*;
|
import org.apache.poi.xssf.usermodel.*;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.http.*;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import springfox.documentation.spring.web.json.Json;
|
import org.springframework.web.client.RestClientException;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -67,6 +70,7 @@ import java.util.stream.Collectors;
|
|||||||
* @createDate 2024-12-30 16:16:25
|
* @createDate 2024-12-30 16:16:25
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
@Slf4j
|
||||||
public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<EntrustMaterialCheckoutResultMapper, EntrustMaterialCheckoutResult>
|
public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<EntrustMaterialCheckoutResultMapper, EntrustMaterialCheckoutResult>
|
||||||
implements EntrustMaterialCheckoutResultService {
|
implements EntrustMaterialCheckoutResultService {
|
||||||
|
|
||||||
@@ -1122,10 +1126,16 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
|
|||||||
.map(r -> buildResultVO(r, materialMap))
|
.map(r -> buildResultVO(r, materialMap))
|
||||||
.sorted(Comparator.comparingInt(EntrustMaterialCheckoutResultVO::getOrderNo))
|
.sorted(Comparator.comparingInt(EntrustMaterialCheckoutResultVO::getOrderNo))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
boolean push = pushToDatabase(suspects, resultVOS, entrustment, caseEvent, user);
|
||||||
|
if (entrustment.getEntrustmentType() == 0) {
|
||||||
|
push = this.pushQualitativeReportData(entrustment, user);
|
||||||
|
}
|
||||||
|
if (push) {
|
||||||
|
entrustment.setPlatformFlag(true);
|
||||||
|
entrustmentService.updateById(entrustment);
|
||||||
|
}
|
||||||
// 数据推送至目标数据库
|
// 数据推送至目标数据库
|
||||||
return pushToDatabase(suspects, resultVOS, entrustment, caseEvent, user);
|
return push;
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntrustMaterialCheckoutResultVO buildResultVO(EntrustMaterialCheckoutResult result, Map<String, EntrustmentIdentificationMaterial> materialMap) {
|
private EntrustMaterialCheckoutResultVO buildResultVO(EntrustMaterialCheckoutResult result, Map<String, EntrustmentIdentificationMaterial> materialMap) {
|
||||||
@@ -1241,12 +1251,239 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
entrustment.setPlatformFlag(true);
|
|
||||||
entrustmentService.updateById(entrustment);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean pushQualitativeReportData(Entrustment entrust, DLPUser dlpUser) {
|
||||||
|
JSONObject jsonObject = this.buildQualitativeReportJsonPayload(entrust, dlpUser);
|
||||||
|
log.info("推送定性报告数据, 受理编号: {}, 请求数据: {}", entrust.getAcceptNo(), jsonObject);
|
||||||
|
try {
|
||||||
|
ResponseEntity<String> response = exchangeRemoteApi(jsonObject, "http://83.3.9.45/thirdparty/report-generate/dingXingReport/v1");
|
||||||
|
if (response.getStatusCode().is2xxSuccessful() && response.getBody().contains("\"status\":200")) {
|
||||||
|
log.info("推送定性报告数据成功, 受理编号: {}, 响应: {}", entrust.getAcceptNo(), response.getBody());
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
log.warn("推送定性报告数据失败, 受理编号: {}, 状态码: {}, 响应: {}",
|
||||||
|
entrust.getAcceptNo(), response.getStatusCode(), response.getBody());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (RestClientException e) {
|
||||||
|
log.error("推送定性报告数据到 LabsCare 失败, 受理编号: {}", entrust.getAcceptNo(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过POST请求与远程API进行交互
|
||||||
|
*
|
||||||
|
* @param jsonObject 包含请求数据的JSONObject对象
|
||||||
|
* @param url 远程API的URL
|
||||||
|
* @return ResponseEntity<String> 包含远程API响应数据的ResponseEntity对象
|
||||||
|
*/
|
||||||
|
private ResponseEntity<String> exchangeRemoteApi(JSONObject jsonObject, String url) {
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON); // 设置为 application/json
|
||||||
|
HttpEntity<JSONObject> requestEntity = new HttpEntity<>(jsonObject, headers);
|
||||||
|
ResponseEntity<String> response = HttpsUtils
|
||||||
|
.genRestTemplate()
|
||||||
|
.exchange(
|
||||||
|
url,
|
||||||
|
HttpMethod.POST,
|
||||||
|
requestEntity,
|
||||||
|
String.class
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建推送定性报告的json数据
|
||||||
|
*
|
||||||
|
* @param entrust 委托信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private JSONObject buildQualitativeReportJsonPayload(Entrustment entrust, DLPUser dlpUser) {
|
||||||
|
|
||||||
|
List<EntrustmentIdentificationMaterial> materialList = entrustmentIdentificationMaterialService.lambdaQuery()
|
||||||
|
.eq(EntrustmentIdentificationMaterial::getEntrustmentId, entrust.getId())
|
||||||
|
.list();
|
||||||
|
|
||||||
|
CaseEvent caseEvent = caseEventService.getById(entrust.getCaseId());
|
||||||
|
|
||||||
|
String[] splitAcceptNo = entrust.getAcceptNo().split("-");
|
||||||
|
// 封装推送定性报告数据
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.set("jcxz", buildMaterialCharacterDesc(materialList)); // 检材性状描述
|
||||||
|
jsonObject.set("jiandingwenshuhao", String.format("[%s]%s号", splitAcceptNo[0], splitAcceptNo[1])); // 鉴定文书号
|
||||||
|
jsonObject.set("jdyq", entrust.getEntrustRequirement()); // 鉴定要求
|
||||||
|
jsonObject.set("jyaq", caseEvent.getCaseBrief()); // 简要案情
|
||||||
|
jsonObject.set("jyy1qm", dlpUser.getName()); // 检测人
|
||||||
|
jsonObject.set("jyyr2qm", dlpUser.getName()); // 检测人
|
||||||
|
jsonObject.set("jyy1zc", "#NULL#"); // 检验人1专业技术资格或职称
|
||||||
|
jsonObject.set("jyy2zc", "#NULL#"); // 检验人2专业技术资格或职称
|
||||||
|
jsonObject.set("qfrq", "#NULL#");
|
||||||
|
jsonObject.set("qrcode", "#NULL#"); // 二维码地址
|
||||||
|
jsonObject.set("sjr1List", CollUtil.newArrayList(entrust.getDeliverer1Name(), entrust.getDeliverer2Name())); // 送检人
|
||||||
|
jsonObject.set("slrq", entrust.getAcceptTime().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
|
||||||
|
jsonObject.set("wtdw", entrust.getClientOrgName()); // 委托单位
|
||||||
|
jsonObject.set("zrqm", "#NULL#"); // 授权签字人
|
||||||
|
jsonObject.set("zrzc", "#NULL#"); // 授权签字人专业技术资格或职称
|
||||||
|
|
||||||
|
// 定性检验报告样品 检测信息
|
||||||
|
JSONObject inspectDataInfo = new JSONObject();
|
||||||
|
inspectDataInfo.set("dxff", "《疑似毒品中 2-氟苯丙胺等 388种麻醉药品和精神药品的定性检验 气相色谱-质谱法》(JD/Y JY01.07-2024)");
|
||||||
|
inspectDataInfo.set("jysj", entrust.getAcceptTime().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
|
||||||
|
inspectDataInfo.set("outStr", this.buildResultStr(entrust.getId()));
|
||||||
|
cn.hutool.json.JSONArray gauging = new cn.hutool.json.JSONArray();
|
||||||
|
gauging.add(inspectDataInfo);
|
||||||
|
// 定性检验报告样品信息
|
||||||
|
JSONObject sampleJson = new JSONObject();
|
||||||
|
sampleJson.put("gauging", gauging);
|
||||||
|
cn.hutool.json.JSONArray sampleArrayJSON = new cn.hutool.json.JSONArray();
|
||||||
|
sampleArrayJSON.add(sampleJson);
|
||||||
|
jsonObject.set("sample", sampleArrayJSON);
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String buildResultStr(String entrustId) {
|
||||||
|
List<EntrustMaterialCheckoutResult> list = this.lambdaQuery()
|
||||||
|
.eq(EntrustMaterialCheckoutResult::getEntrustId, entrustId)
|
||||||
|
.isNotNull(EntrustMaterialCheckoutResult::getQualitativeResult)
|
||||||
|
.list();
|
||||||
|
|
||||||
|
Set<String> idList = list.stream()
|
||||||
|
.map(EntrustMaterialCheckoutResult::getId)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
Map<String, EntrustMaterialCheckoutResult> resultMap = list.stream()
|
||||||
|
.collect(Collectors.toMap(EntrustMaterialCheckoutResult::getId, Function.identity()));
|
||||||
|
|
||||||
|
List<EntrustmentIdentificationMaterial> materialList = entrustmentIdentificationMaterialService.lambdaQuery()
|
||||||
|
.in(EntrustmentIdentificationMaterial::getId, idList)
|
||||||
|
.list();
|
||||||
|
|
||||||
|
materialList.sort(Comparator.comparing(sample -> extractTailNumber(sample.getAcceptNo())));
|
||||||
|
|
||||||
|
// drugName -> List<orderNo>
|
||||||
|
Map<String, List<Integer>> drugToOrderNos = new HashMap<>();
|
||||||
|
|
||||||
|
for (EntrustmentIdentificationMaterial material : materialList) {
|
||||||
|
List<DrugLite> drugLites = DrugLiteConvert.getDrugLites(resultMap.get(material.getId()).getQualitativeResult());
|
||||||
|
Integer orderNo = material.getOrderNo();
|
||||||
|
for (DrugLite drug : drugLites) {
|
||||||
|
drugToOrderNos
|
||||||
|
.computeIfAbsent(drug.getName(), k -> new ArrayList<>())
|
||||||
|
.add(orderNo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按每个药品对应的最小 orderNo 进行排序,确保先输出最小号的药品
|
||||||
|
List<Map.Entry<String, List<Integer>>> entries = new ArrayList<>(drugToOrderNos.entrySet());
|
||||||
|
entries.sort(Comparator.comparingInt(e -> Collections.min(e.getValue())));
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (Map.Entry<String, List<Integer>> entry : entries) {
|
||||||
|
String drugName = entry.getKey();
|
||||||
|
List<Integer> orderNos = entry.getValue();
|
||||||
|
Collections.sort(orderNos);
|
||||||
|
|
||||||
|
sb.append("从");
|
||||||
|
|
||||||
|
if (isConsecutive(orderNos) && orderNos.size() >= 2) {
|
||||||
|
sb.append(orderNos.get(0)).append("号和").append(orderNos.get(orderNos.size() - 1)).append("号检材中");
|
||||||
|
} else {
|
||||||
|
sb.append(orderNos.stream()
|
||||||
|
.map(no -> no + "号检材")
|
||||||
|
.collect(Collectors.joining("、")))
|
||||||
|
.append("中");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("检出").append(drugName).append(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去掉最后一个逗号,添加句号
|
||||||
|
if (sb.length() > 0 && sb.charAt(sb.length() - 1) == ',') {
|
||||||
|
sb.setCharAt(sb.length() - 1, '。');
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isConsecutive(List<Integer> list) {
|
||||||
|
for (int i = 1; i < list.size(); i++) {
|
||||||
|
if (list.get(i) - list.get(i - 1) != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String buildMaterialCharacterDesc(List<EntrustmentIdentificationMaterial> materialList) {
|
||||||
|
if (CollUtil.isEmpty(materialList)) {
|
||||||
|
return StrUtil.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按尾号排序(提取编号尾号进行比较)
|
||||||
|
materialList.sort(Comparator.comparing(sample -> extractTailNumber(sample.getAcceptNo())));
|
||||||
|
|
||||||
|
List<String> descriptions = new ArrayList<>();
|
||||||
|
int start = -1, prev = -1;
|
||||||
|
String prevForm = null;
|
||||||
|
List<String> mergedOrderNos = new ArrayList<>();
|
||||||
|
|
||||||
|
// 遍历排序后的检材编号,合并相邻且性状相同的编号
|
||||||
|
for (EntrustmentIdentificationMaterial material : materialList) {
|
||||||
|
int current = extractTailNumber(material.getAcceptNo()); // 提取尾号
|
||||||
|
String form = material.getForm();
|
||||||
|
|
||||||
|
if (start == -1) { // 初始化
|
||||||
|
start = prev = current;
|
||||||
|
prevForm = form;
|
||||||
|
} else if (current == prev + 1 && form.equals(prevForm)) {
|
||||||
|
// 只有连续尾号 + 相同性状才能合并
|
||||||
|
prev = current;
|
||||||
|
} else {
|
||||||
|
// 遇到新性状或不连续尾号,存储前一段描述
|
||||||
|
mergedOrderNos.add(formatRange(start, prev) + "检材为" + prevForm);
|
||||||
|
start = prev = current;
|
||||||
|
prevForm = form;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 处理最后一组数据
|
||||||
|
mergedOrderNos.add(formatRange(start, prev) + "检材为" + prevForm);
|
||||||
|
|
||||||
|
// **如果只有一个检材,省略编号**
|
||||||
|
if (mergedOrderNos.size() == 1 && materialList.size() == 1) {
|
||||||
|
return "检材为" + prevForm + "。";
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.join(";", mergedOrderNos) + "。";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成编号范围的字符串
|
||||||
|
*
|
||||||
|
* @param start 起始编号
|
||||||
|
* @param end 结束编号
|
||||||
|
* @return 生成的范围字符串,例如 "1号至3号" 或 "5号"
|
||||||
|
*/
|
||||||
|
private String formatRange(int start, int end) {
|
||||||
|
return (start == end) ? start + "号" : start + "号至" + end + "号";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提取检材编号的尾号(即最后一个 `-` 之后的数值)
|
||||||
|
*
|
||||||
|
* @param orderNo 检材编号(格式:2025-89-13)
|
||||||
|
* @return 尾号(示例:返回 13)
|
||||||
|
*/
|
||||||
|
private int extractTailNumber(String orderNo) {
|
||||||
|
String[] parts = orderNo.split("-");
|
||||||
|
return (parts.length > 0) ? Integer.parseInt(parts[parts.length - 1]) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 推送嫌疑人毒检结果任务
|
* 推送嫌疑人毒检结果任务
|
||||||
*
|
*
|
||||||
@@ -1827,7 +2064,6 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user