增加了导出贵阳市局陈月猛主任需要的委托季度统计报表的功能

master
杨海航 3 weeks ago
parent 5afb12bc84
commit 319630873a
  1. 12
      src/main/java/digital/laboratory/platform/entrustment/controller/EntrustMaterialCheckoutResultController.java
  2. 5
      src/main/java/digital/laboratory/platform/entrustment/controller/EntrustmentIdentificationMaterialController.java
  3. 4
      src/main/java/digital/laboratory/platform/entrustment/convert/EntrustMaterialCheckoutResultConvert.java
  4. 7
      src/main/java/digital/laboratory/platform/entrustment/dto/EntrustMaterialCheckoutResultDTO.java
  5. 11
      src/main/java/digital/laboratory/platform/entrustment/dto/GenerateQuarterlyReportDTO.java
  6. 1
      src/main/java/digital/laboratory/platform/entrustment/dto/ResultExcelDTO.java
  7. 6
      src/main/java/digital/laboratory/platform/entrustment/entity/EntrustMaterialCheckoutResult.java
  8. 14
      src/main/java/digital/laboratory/platform/entrustment/entity/EntrustmentIdentificationMaterial.java
  9. 5
      src/main/java/digital/laboratory/platform/entrustment/service/EntrustMaterialCheckoutResultService.java
  10. 516
      src/main/java/digital/laboratory/platform/entrustment/service/impl/EntrustMaterialCheckoutResultServiceImpl.java
  11. 6
      src/main/java/digital/laboratory/platform/entrustment/vo/EntrustMaterialCheckoutResultVO.java
  12. 1
      src/main/resources/mapper/EntrustMaterialCheckoutResultMapper.xml

@ -9,6 +9,7 @@ import digital.laboratory.platform.common.mybatis.security.service.DLPUser;
import digital.laboratory.platform.common.security.util.SecurityUtils;
import digital.laboratory.platform.entrustment.convert.EntrustMaterialCheckoutResultConvert;
import digital.laboratory.platform.entrustment.dto.EntrustMaterialCheckoutResultDTO;
import digital.laboratory.platform.entrustment.dto.GenerateQuarterlyReportDTO;
import digital.laboratory.platform.entrustment.dto.ResultExcelDTO;
import digital.laboratory.platform.entrustment.query.BaseQuery;
import digital.laboratory.platform.entrustment.query.EntrustMaterialCheckoutResultQuery;
@ -24,8 +25,10 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.sql.Array;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
@ -114,4 +117,13 @@ public class EntrustMaterialCheckoutResultController {
return R.ok(entrustMaterialCheckoutResultService.pushSuspectDetectionResultTask(dlpUser));
}
@GetMapping("/generateQuarterlyReportExcel")
public R generateQuarterlyReportExcel(@RequestBody GenerateQuarterlyReportDTO dto, HttpServletResponse response) throws IOException {
if (dto == null || dto.getQuarterlyList() == null || dto.getQuarterlyList().size() == 0 || dto.getYear() == 0) {
return R.failed("请输入正确的参数");
}
entrustMaterialCheckoutResultService.generateQuarterlyReportExcel(dto, response);
return R.ok("导出成功!");
}
}

@ -49,6 +49,7 @@ import org.springframework.web.multipart.MultipartFile;
import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
@ -342,7 +343,7 @@ public class EntrustmentIdentificationMaterialController {
@ApiOperation(value = "新增检材信息11-20修改版", notes = "新增检材信息11-20修改版")
@PostMapping(value = "/create/entrustmentIdent/im")
@PreAuthorize("@pms.hasPermission('EntrustmentIdentificationMaterialCreate')")
public R<List<EntrustmentIdentificationMaterial>> createNewIm(@RequestBody List<EntrustmentIdentificationMaterial> identificationMaterialList, HttpServletRequest httpServletRequest) {
public R<List<EntrustmentIdentificationMaterial>> createNewIm(@RequestBody @Valid List<EntrustmentIdentificationMaterial> identificationMaterialList, HttpServletRequest httpServletRequest) {
Principal principal = httpServletRequest.getUserPrincipal();
DLPUser dlpUser = (DLPUser) ((OAuth2Authentication) principal).getUserAuthentication().getPrincipal();
List<EntrustmentIdentificationMaterial> newIm = entrustmentIdentificationMaterialService.createNewIm(identificationMaterialList, dlpUser);
@ -1200,7 +1201,7 @@ public class EntrustmentIdentificationMaterialController {
@GetMapping("/getMaterialPDF/{acceptNo}")
@ApiOperation(value = "查看检材图片")
@Inner(value = false)
public void getMaterialPDF(@PathVariable String acceptNo, HttpServletResponse response) {
public void getMaterialPDF(@PathVariable String acceptNo, HttpServletResponse response) {
try {
entrustmentIdentificationMaterialService.getMaterialPDF(acceptNo, response);
} catch (Exception e) {

@ -19,6 +19,9 @@ public class EntrustMaterialCheckoutResultConvert {
} else {
entrustMaterialCheckoutResult.setQualitativeResult(null);
}
if (CollUtil.isNotEmpty(dto.getMetaboliteResult())){
entrustMaterialCheckoutResult.setMetaboliteResult(JSON.toJSONString(dto.getMetaboliteResult()));
}
entrustMaterialCheckoutResult.setQuantitativeResult(dto.getQuantitativeResult());
entrustMaterialCheckoutResult.setOtherResult(dto.getOtherResult());
entrustMaterialCheckoutResult.setCheckoutRemark(dto.getCheckoutRemark());
@ -34,6 +37,7 @@ public class EntrustMaterialCheckoutResultConvert {
vo.setQuantitativeResult(entity.getQuantitativeResult());
vo.setOtherResult(entity.getOtherResult());
vo.setCheckoutRemark(entity.getCheckoutRemark());
vo.setMetaboliteResult(entity.getMetaboliteResult());
return vo;
}

@ -1,5 +1,7 @@
package digital.laboratory.platform.entrustment.dto;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import digital.laboratory.platform.sys.entity.DrugLite;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -34,6 +36,11 @@ public class EntrustMaterialCheckoutResultDTO {
@ApiModelProperty("定性结果")
private List<DrugLite> qualitativeResult;
/**
* 代谢物结果
*/
@TableField(updateStrategy = FieldStrategy.IGNORED)
private List<DrugLite> metaboliteResult;
/**
* 定量结果
*/

@ -0,0 +1,11 @@
package digital.laboratory.platform.entrustment.dto;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class GenerateQuarterlyReportDTO {
int year;
List<Integer> quarterlyList;
}

@ -11,4 +11,5 @@ public class ResultExcelDTO {
List<String> oldResult;
LocalDateTime startTime;
LocalDateTime endTime;
boolean isMetabolite;
}

@ -36,6 +36,12 @@ public class EntrustMaterialCheckoutResult extends BaseEntity {
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String quantitativeResult;
/**
* 代谢物结果
*/
@TableField(updateStrategy = FieldStrategy.IGNORED)
private String metaboliteResult;
/**
* 其他鉴定结果
*/

@ -13,6 +13,9 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang.StringUtils;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@ -70,6 +73,7 @@ public class EntrustmentIdentificationMaterial extends BaseEntity {
/**
* 检材名称
*/
@NotBlank(message = "检材名称不能为空")
@ApiModelProperty(value = "检材名称")
private String name;
@ -95,6 +99,7 @@ public class EntrustmentIdentificationMaterial extends BaseEntity {
/**
* 检材性状:继承所取物证性状或从物证性状类别选择
*/
@NotBlank(message = "检材性状不能为空")
@ApiModelProperty(value = "检材性状:继承所取物证性状或从物证性状类别选择")
private String form;
@ -102,6 +107,7 @@ public class EntrustmentIdentificationMaterial extends BaseEntity {
* 检材性状:继承所取物证性状或从物证性状类别选择
* * 2023/5/31 在咸阳分中心添加
*/
@NotBlank(message = "检材性状名称不能为空")
@ApiModelProperty(value = "检材性状名称:继承所取物证性状或从物证性状类别选择")
private String formName;
@ -128,11 +134,13 @@ public class EntrustmentIdentificationMaterial extends BaseEntity {
*/
@ApiModelProperty(value = "检材数量, 例如 3.8 克 或 4.5毫升")
@JsonSerialize(using = DynamicBigDecimalSerializer.class)
@NotNull(message = "检材质量不能为空")
private BigDecimal quantity;
/**
* 计量单位, 例如 3.8 4.5毫升
*/
@NotBlank(message = "计量单位不能为空")
@ApiModelProperty(value = "计量单位, 例如 3.8 克 或 4.5毫升")
private String unit;
@ -489,10 +497,12 @@ public class EntrustmentIdentificationMaterial extends BaseEntity {
* 1.定性分析 2.定量分析 3.定性定量分析 4.关联性判断 5其他
*/
@ApiModelProperty(value = "分析项目 1.定性分析 2.定量分析 3.定性定量分析 4.关联性判断 5。其他")
@NotNull(message = "分析项目不能为空")
private Integer analysisOption;
@ApiModelProperty(value = "将分析项目转为字符串类型")
@TableField(exist = false)
private String analysisOptionValue;
/**
@ -517,6 +527,7 @@ public class EntrustmentIdentificationMaterial extends BaseEntity {
/**
* 提取时间--贵阳新增需求
*/
@NotNull(message = "提取时间不能为空")
@ApiModelProperty(value = "提取时间--贵阳新增需求")
private LocalDateTime drawTime;
/**
@ -529,9 +540,11 @@ public class EntrustmentIdentificationMaterial extends BaseEntity {
/**
* 提取地点--贵阳新增需求
*/
@NotBlank(message = "提取地点不能为空")
@ApiModelProperty(value = "提取地点--贵阳新增需求")
private String drawPlace;
@NotNull(message = "包装是否完整不能为空")
/**
* 包装是否完整--贵阳新增需求
*/
@ -540,6 +553,7 @@ public class EntrustmentIdentificationMaterial extends BaseEntity {
/* 留存样个数--贵阳新增需求
*/
@NotNull(message = "留存样个数不能为空")
@ApiModelProperty(value = "留存样个数--贵阳新增需求")
private Integer rtSampleQuantity;

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import digital.laboratory.platform.common.core.util.R;
import digital.laboratory.platform.common.mybatis.security.service.DLPUser;
import digital.laboratory.platform.entrustment.dto.EntrustMaterialCheckoutResultDTO;
import digital.laboratory.platform.entrustment.dto.GenerateQuarterlyReportDTO;
import digital.laboratory.platform.entrustment.dto.ResultExcelDTO;
import digital.laboratory.platform.entrustment.entity.EntrustMaterialCheckoutResult;
import digital.laboratory.platform.entrustment.query.EntrustMaterialCheckoutResultQuery;
@ -18,7 +19,9 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author ChenJiangBao
@ -82,4 +85,6 @@ public interface EntrustMaterialCheckoutResultService extends IService<EntrustMa
boolean pushSuspectDetectionResult(String entrustmentId, DLPUser user) throws SQLException;
R pushSuspectDetectionResultTask(DLPUser dlpUser);
void generateQuarterlyReportExcel(GenerateQuarterlyReportDTO dto, HttpServletResponse response) throws IOException;
}

@ -8,15 +8,18 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import digital.laboratory.platform.common.core.exception.CheckedException;
import digital.laboratory.platform.common.core.util.R;
import digital.laboratory.platform.common.mybatis.security.service.DLPUser;
import digital.laboratory.platform.common.oss.service.OssFile;
import digital.laboratory.platform.entrustment.convert.DrugLiteConvert;
import digital.laboratory.platform.entrustment.convert.EntrustMaterialCheckoutResultConvert;
import digital.laboratory.platform.entrustment.dto.CheckoutResultExcelDTO;
import digital.laboratory.platform.entrustment.dto.EntrustMaterialCheckoutResultDTO;
import digital.laboratory.platform.entrustment.dto.GenerateQuarterlyReportDTO;
import digital.laboratory.platform.entrustment.dto.ResultExcelDTO;
import digital.laboratory.platform.entrustment.entity.*;
import digital.laboratory.platform.entrustment.enums.EntrustStatusConstants;
@ -30,10 +33,9 @@ import digital.laboratory.platform.entrustment.vo.EntrustmentIdentificationMater
import digital.laboratory.platform.entrustment.vo.SuspectDetectionVO;
import digital.laboratory.platform.sys.entity.Area;
import digital.laboratory.platform.sys.entity.DrugLite;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@ -44,8 +46,12 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.sql.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -77,6 +83,9 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
@Resource
private CaseEventService caseEventService;
@Resource
private OssFile ossFile;
/**
* 构建委托材料检验结果字符串
*
@ -642,6 +651,7 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
LocalDateTime endTime = excelDTO.getEndTime();
List<String> oldResults = excelDTO.getOldResult();
Integer entrustType = excelDTO.getEntrustType();
boolean metabolite = excelDTO.isMetabolite();
try {
// 1. 构建查询条件
LambdaQueryWrapper<Entrustment> qw = new LambdaQueryWrapper<>();
@ -1047,8 +1057,8 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
.isNotNull(EntrustMaterialCheckoutResult::getQualitativeResult)
.list();
if (CollectionUtils.isEmpty(results)){
throw new IllegalArgumentException("没有阳性的检验结果:" + entrustmentId+",无需进行推送!");
if (CollectionUtils.isEmpty(results)) {
throw new IllegalArgumentException("没有阳性的检验结果:" + entrustmentId + ",无需进行推送!");
}
// 获取嫌疑人信息
@ -1056,8 +1066,8 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
.eq(Suspect::getEntrustId, entrustmentId)
.list();
if (CollectionUtils.isEmpty(suspects)){
throw new IllegalArgumentException("未找到嫌疑人信息:" + entrustmentId+",请先添加嫌疑人信息!");
if (CollectionUtils.isEmpty(suspects)) {
throw new IllegalArgumentException("未找到嫌疑人信息:" + entrustmentId + ",请先添加嫌疑人信息!");
}
// 构造物证材料映射
Map<String, EntrustmentIdentificationMaterial> materialMap = entrustmentIdentificationMaterialService.lambdaQuery()
@ -1092,7 +1102,7 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
vo.setAcceptNo(material.getAcceptNo());
}
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("结果的毒品列表:"+result.getQualitativeResult());
System.out.println("结果的毒品列表:" + result.getQualitativeResult());
vo.setQualitativeResult(
DrugLiteConvert.getDrugLites(result.getQualitativeResult())
@ -1194,6 +1204,7 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
entrustment.setPlatformFlag(true);
entrustmentService.updateById(entrustment);
return true;
}
/**
@ -1217,8 +1228,8 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
List<Entrustment> entrusts = entrustmentService.lambdaQuery()
.in(Entrustment::getId, entrustSet)
.ge(Entrustment::getStatus, EntrustStatusConstants.ENTRUST_STATUS_ACCEPTED.getStatus()) // status >= 9
.and(qw ->qw
.eq(Entrustment::getPlatformFlag,false)
.and(qw -> qw
.eq(Entrustment::getPlatformFlag, false)
.or()
.isNull(Entrustment::getPlatformFlag))
.list();
@ -1228,7 +1239,7 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
.map(Entrustment::getId)
.collect(Collectors.toList());
// 查询案件信息,并构造以案件ID为键的映射
// 查询案件信息,并构造以案件ID为键 的映射
Map<String, CaseEvent> caseMap = caseEventService.lambdaQuery()
.in(CaseEvent::getId, entrusts.stream().map(Entrustment::getCaseId).collect(Collectors.toList()))
.list()
@ -1258,7 +1269,7 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
.stream()
.collect(Collectors.toMap(EntrustmentIdentificationMaterial::getId, Function.identity()));
if (materialMap.isEmpty()){
if (materialMap.isEmpty()) {
return R.failed("未查询到有检材信息!");
}
// 构造结果VO列表
@ -1284,10 +1295,487 @@ public class EntrustMaterialCheckoutResultServiceImpl extends ServiceImpl<Entrus
}
}
return R.ok("推送成功");
}
/**
* 生成指定年份和季度列表的季度统计数据
*
* @param year 统计年份
* @param quarterlyList 季度列表1~4
* @return Mapkey为季度号value为该季度对应的统计数据
*/
public HashMap<Integer, Map<String, List<Integer>>> generateQuarterlyReportData(int year, List<Integer> quarterlyList) {
// 先对季度排序,保证顺序一致
quarterlyList.sort(Comparator.naturalOrder());
HashMap<Integer, Map<String, List<Integer>>> resultMap = new HashMap<>();
for (Integer quarter : quarterlyList) {
// 计算季度起止时间
LocalDateTime startDateTime = getQuarterStartDateTime(year, quarter);
LocalDateTime endDateTime = getQuarterEndDateTime(year, quarter);
System.out.println("开始时间:" + startDateTime);
System.out.println("结束时间:" + endDateTime);
// 获取该季度所有委托数据(首次鉴定、补充鉴定、重新鉴定)
List<Entrustment> entrusts = queryEntrustments(startDateTime, endDateTime, 0,
Arrays.asList("首次鉴定", "补充鉴定", "重新鉴定"));
if (entrusts == null || entrusts.isEmpty()) {
// 如果无委托则跳过该季度
continue;
}
// 统计该季度普通材料检测情况
Map<String, List<Integer>> quarterMap = calculateMaterialStats(entrusts);
// 统计生物样本检测情况(委托类型为1)
List<Entrustment> inVivoEntrusts = queryEntrustments(startDateTime, endDateTime, 1, null);
if (inVivoEntrusts != null && !inVivoEntrusts.isEmpty()) {
quarterMap.put("生物样本", calculateEntrustmentStats(inVivoEntrusts));
}
// 统计初筛检测情况(委托类型0,鉴定结果为“初筛”)
List<Entrustment> initialScreeningEntrusts = queryEntrustments(startDateTime, endDateTime, 0, Collections.singletonList("初筛"));
if (initialScreeningEntrusts != null && !initialScreeningEntrusts.isEmpty()) {
quarterMap.put("初筛", calculateEntrustmentStats(initialScreeningEntrusts));
}
List<Entrustment> entrustments = entrustmentService.lambdaQuery()
.between(Entrustment::getAcceptTime, startDateTime, endDateTime)
.ge(Entrustment::getStatus, EntrustStatusConstants.ENTRUST_STATUS_WAITING_CHECK_CLAIM.getStatus())
.orderByAsc(Entrustment::getAcceptTime)
.list();
ArrayList<Integer> integers = new ArrayList<>();
integers.add(Integer.valueOf(entrustments.get(0).getAcceptNo().split("-")[1]));
integers.add(Integer.valueOf(entrustments.get(entrustments.size() - 1).getAcceptNo().split("-")[1]));
quarterMap.put("entrustCount", integers);
resultMap.put(quarter, quarterMap);
}
System.out.println(resultMap);
return resultMap;
}
/**
* 获取指定年份季度开始时间
*/
private LocalDateTime getQuarterStartDateTime(int year, int quarter) {
Month startMonth = Month.of((quarter - 1) * 3 + 1);
return LocalDateTime.of(LocalDate.of(year, startMonth, 1), LocalTime.MIN);
}
/**
* 获取指定年份季度结束时间
*/
private LocalDateTime getQuarterEndDateTime(int year, int quarter) {
Month startMonth = Month.of((quarter - 1) * 3 + 1);
Month endMonth = startMonth.plus(2);
LocalDate endDate = LocalDate.of(year, endMonth, 1).with(TemporalAdjusters.lastDayOfMonth());
return LocalDateTime.of(endDate, LocalTime.MAX);
}
/**
* 根据条件查询委托
*
* @param start 开始时间包含
* @param end 结束时间包含
* @param entrustmentType 委托类型0或1
* @param oldIdentificationResults 鉴定结果列表null表示不筛选此条件
* @return 符合条件的委托列表
*/
private List<Entrustment> queryEntrustments(LocalDateTime start, LocalDateTime end, int entrustmentType, List<String> oldIdentificationResults) {
LambdaQueryChainWrapper<Entrustment> query = entrustmentService.lambdaQuery()
.between(Entrustment::getAcceptTime, start, end)
.ge(Entrustment::getStatus, EntrustStatusConstants.ENTRUST_STATUS_ACCEPTED.getStatus())
.eq(Entrustment::getEntrustmentType, entrustmentType);
if (oldIdentificationResults != null && !oldIdentificationResults.isEmpty()) {
query.in(Entrustment::getOldIdentificationResult, oldIdentificationResults);
}
return query.list();
}
/**
* 根据委托列表计算普通材料的统计数据
*
* @param entrusts 委托列表
* @return key为药品名称字符串value为对应统计值列表案件总数检出数未检出数等
*/
private Map<String, List<Integer>> calculateMaterialStats(List<Entrustment> entrusts) {
Map<String, List<Integer>> quarterMap = new HashMap<>();
if (entrusts == null || entrusts.isEmpty()) return quarterMap;
// 获取所有委托ID
Set<String> entrustIds = entrusts.stream()
.map(Entrustment::getId)
.collect(Collectors.toSet());
if (entrustIds.isEmpty()) return quarterMap;
// 查询材料列表
List<EntrustmentIdentificationMaterial> materialList = entrustmentIdentificationMaterialService.lambdaQuery()
.in(EntrustmentIdentificationMaterial::getEntrustmentId, entrustIds)
.list();
if (materialList == null || materialList.isEmpty()) return quarterMap;
// 获取材料ID集合
Set<String> materialIds = materialList.stream()
.map(EntrustmentIdentificationMaterial::getId)
.collect(Collectors.toSet());
if (materialIds.isEmpty()) return quarterMap;
// 查询检测结果列表,排除空或null结果
List<EntrustMaterialCheckoutResult> resultList = this.lambdaQuery()
.in(EntrustMaterialCheckoutResult::getId, materialIds)
.notLike(EntrustMaterialCheckoutResult::getQualitativeResult, "null")
.isNotNull(EntrustMaterialCheckoutResult::getQualitativeResult)
.list();
if (resultList == null) resultList = Collections.emptyList();
// 按材料ID分组检测结果,方便判断是否检测
Map<String, List<EntrustMaterialCheckoutResult>> resultMap = resultList.stream()
.collect(Collectors.groupingBy(EntrustMaterialCheckoutResult::getId));
// 按候选药品名称分组材料(名称排序后拼接)
Map<String, List<EntrustmentIdentificationMaterial>> drugGroupMap = materialList.stream()
.collect(Collectors.groupingBy(item -> {
List<String> drugNames = DrugLiteConvert.convertDirtyLiteByJSON(item.getCandidateDrugs())
.stream()
.map(DrugLite::getName)
.sorted()
.collect(Collectors.toList());
return String.join("、", drugNames);
}));
// 遍历药品分组,统计数据
for (Map.Entry<String, List<EntrustmentIdentificationMaterial>> entry : drugGroupMap.entrySet()) {
String drugNames = entry.getKey();
List<EntrustmentIdentificationMaterial> drugMaterials = entry.getValue();
// 按委托ID分组材料
Map<String, List<EntrustmentIdentificationMaterial>> entrustToMaterials = drugMaterials.stream()
.collect(Collectors.groupingBy(EntrustmentIdentificationMaterial::getEntrustmentId));
int caseCount = entrustToMaterials.size(); // 案件总数
int checked = 0, notChecked = 0, partChecked = 0, materialCount = drugMaterials.size(), resultCount = 0;
// 遍历每个委托的材料,判断检测情况
for (Map.Entry<String, List<EntrustmentIdentificationMaterial>> e : entrustToMaterials.entrySet()) {
List<EntrustmentIdentificationMaterial> materials = e.getValue();
int mCount = materials.size();
// 材料中有检测结果的数量
int rCount = (int) materials.stream()
.filter(m -> resultMap.containsKey(m.getId()))
.count();
resultCount += rCount;
if (rCount == 0) {
notChecked++;
} else if (rCount == mCount) {
checked++;
} else {
partChecked++;
}
}
int materialNotChecked = materialCount - resultCount;
// 按顺序添加统计值
ArrayList<Integer> integers = new ArrayList<>();
integers.add(caseCount); // 案件总数
integers.add(checked); // 检出数(案件数)
integers.add(notChecked); // 未检出数(案件数)
integers.add(partChecked); // 部分检出数(案件数)
integers.add(materialCount); // 材料总数
integers.add(resultCount); // 材料检出数
integers.add(materialNotChecked);// 材料未检出数
quarterMap.put(drugNames, integers);
}
return quarterMap;
}
/**
* 根据委托列表计算生物样本或初筛的统计数据
* 该统计逻辑和材料统计类似但针对委托整体
*
* @param entrusts 委托列表
* @return 统计数据列表顺序同材料统计
*/
private List<Integer> calculateEntrustmentStats(List<Entrustment> entrusts) {
if (entrusts == null || entrusts.isEmpty()) return Collections.emptyList();
Set<String> entrustIds = entrusts.stream()
.map(Entrustment::getId)
.collect(Collectors.toSet());
if (entrustIds.isEmpty()) return Collections.emptyList();
// 查询所有相关材料
List<EntrustmentIdentificationMaterial> materials = entrustmentIdentificationMaterialService.lambdaQuery()
.in(EntrustmentIdentificationMaterial::getEntrustmentId, entrustIds)
.list();
if (materials == null) materials = Collections.emptyList();
Set<String> materialIds = materials.stream()
.map(EntrustmentIdentificationMaterial::getId)
.collect(Collectors.toSet());
if (materialIds.isEmpty()) return Collections.emptyList();
// 查询所有检测结果
List<EntrustMaterialCheckoutResult> results = this.lambdaQuery()
.in(EntrustMaterialCheckoutResult::getId, materialIds)
.notLike(EntrustMaterialCheckoutResult::getQualitativeResult, "null")
.isNotNull(EntrustMaterialCheckoutResult::getQualitativeResult)
.list();
if (results == null) results = Collections.emptyList();
// 按材料ID分组结果
Map<String, List<EntrustMaterialCheckoutResult>> resultMap = results.stream()
.collect(Collectors.groupingBy(EntrustMaterialCheckoutResult::getId));
int caseCount = entrusts.size();
int materialCount = materials.size();
int resultCount = results.size();
int checked = 0, notChecked = 0, partChecked = 0;
// 按委托ID分组材料,判断检测状态
Map<String, List<EntrustmentIdentificationMaterial>> entrustToMaterials = materials.stream()
.collect(Collectors.groupingBy(EntrustmentIdentificationMaterial::getEntrustmentId));
for (List<EntrustmentIdentificationMaterial> matList : entrustToMaterials.values()) {
int totalM = matList.size();
int detected = (int) matList.stream()
.filter(m -> resultMap.containsKey(m.getId()))
.count();
if (detected == 0) notChecked++;
else if (detected == totalM) checked++;
else partChecked++;
}
ArrayList<Integer> statistics = new ArrayList<>();
statistics.add(caseCount); // 案件总数
statistics.add(checked); // 检出数(案件数)
statistics.add(notChecked); // 未检出数(案件数)
statistics.add(partChecked); // 部分检出数(案件数)
statistics.add(materialCount); // 材料总数
statistics.add(resultCount); // 材料检出数
statistics.add(materialCount - resultCount);// 材料未检出数
return statistics;
}
@Override
public void generateQuarterlyReportExcel(GenerateQuarterlyReportDTO dto, HttpServletResponse response) throws IOException {
HashMap<Integer, Map<String, List<Integer>>> map = this.generateQuarterlyReportData(dto.getYear(), dto.getQuarterlyList());
XSSFWorkbook workbook = new XSSFWorkbook();
Set<Integer> quarterlySet = map.keySet();
quarterlySet.stream().sorted(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
for (Integer quarterly : quarterlySet) {
this.generateQuarterlyReportSheet(workbook, dto.getYear(), quarterly, map.get(quarterly));
}
workbook.write(response.getOutputStream());
}
public void generateQuarterlyReportSheet(XSSFWorkbook workbook, Integer year, Integer quarterly, Map<String, List<Integer>> map) {
String quarterlyName = "";
switch (quarterly) {
case 1:
quarterlyName = "一";
break;
case 2:
quarterlyName = "二";
break;
case 3:
quarterlyName = "三";
break;
case 4:
quarterlyName = "四";
break;
}
XSSFSheet sheet = workbook.createSheet(year + "年第" + quarterlyName + "季度统计");
int rowIndex = 0;
// 表头样式(大号黑色字体,居中)
XSSFCellStyle headStyle = workbook.createCellStyle();
headStyle.setAlignment(HorizontalAlignment.CENTER);
headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
XSSFFont headFont = workbook.createFont();
headFont.setFontHeightInPoints((short) 16);
headFont.setFontName("宋体");
headFont.setColor(IndexedColors.BLACK.getIndex());
headStyle.setFont(headFont);
// 创建边框居中样式基础
XSSFCellStyle baseStyle = workbook.createCellStyle();
baseStyle.setAlignment(HorizontalAlignment.CENTER);
baseStyle.setVerticalAlignment(VerticalAlignment.CENTER);
baseStyle.setBorderTop(BorderStyle.THIN);
baseStyle.setBorderBottom(BorderStyle.THIN);
baseStyle.setBorderLeft(BorderStyle.THIN);
baseStyle.setBorderRight(BorderStyle.THIN);
baseStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
baseStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
baseStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
baseStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
// 黑色字体样式
XSSFCellStyle blackStyle = workbook.createCellStyle();
blackStyle.cloneStyleFrom(baseStyle);
XSSFFont blackFont = workbook.createFont();
blackFont.setFontHeightInPoints((short) 12);
blackFont.setFontName("宋体");
blackFont.setColor(IndexedColors.BLACK.getIndex());
blackStyle.setFont(blackFont);
// 红色字体样式
XSSFCellStyle redStyle = workbook.createCellStyle();
redStyle.cloneStyleFrom(baseStyle);
XSSFFont redFont = workbook.createFont();
redFont.setFontHeightInPoints((short) 12);
redFont.setFontName("宋体");
redFont.setColor(IndexedColors.RED.getIndex());
redStyle.setFont(redFont);
List<Integer> integers = map.get("entrustCount");
String entrustCount = year + "年" + integers.get(0) + "-" + integers.get(1) + "号种类";
String[] nameRows = {entrustCount, "案件送检登记数", "案件检出数", "案件未检出数", "案件检出及未检出数", "检材送检登记数", "检材检出数", "检材未检出数"};
map.remove("entrustCount");
int[] wides = {25, 16, 12, 12, 19, 15, 12, 13};
// 第一行(合并单元格)
XSSFRow headRow = sheet.createRow(rowIndex);
headRow.setHeight((short) (20.25 * 20));
Cell headCell = headRow.createCell(0);
headCell.setCellValue(year + "年第" + quarterlyName + "季度");
headCell.setCellStyle(headStyle);
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, nameRows.length - 1));
// 第二行 表头列名
XSSFRow nameRow = sheet.createRow(rowIndex + 1);
nameRow.setHeight((short) (14.25 * 20));
for (int i = 0; i < nameRows.length; i++) {
sheet.setColumnWidth(i, wides[i] * 256);
Cell cell = nameRow.createCell(i);
cell.setCellValue(nameRows[i]);
// 第1列(索引1)和第5列(索引5)用红色字体样式,其他用黑色
if (i == 1 || i == 5) {
cell.setCellStyle(redStyle);
} else {
cell.setCellStyle(blackStyle);
}
}
// 第三行 空白行
XSSFRow gapRow = sheet.createRow(rowIndex + 2);
gapRow.setHeight((short) (14.25 * 20));
for (int i = 0; i < nameRows.length; i++) {
Cell cell = gapRow.createCell(i);
cell.setCellStyle(blackStyle);
}
rowIndex = 3;
// 拆分 entry 顺序
List<Map.Entry<String, List<Integer>>> normalEntries = new ArrayList<>();
List<Map.Entry<String, List<Integer>>> specialEntries = new ArrayList<>();
for (Map.Entry<String, List<Integer>> entry : map.entrySet()) {
String key = entry.getKey();
if ("生物样本".equals(key) || "初筛".equals(key)) {
specialEntries.add(entry);
} else {
normalEntries.add(entry);
}
}
// 合并成最终顺序:普通的在前,特殊的在后
List<Map.Entry<String, List<Integer>>> orderedEntries = new ArrayList<>();
orderedEntries.addAll(normalEntries);
orderedEntries.addAll(specialEntries);
Integer va1 = 0, va2 = 0, va3 = 0, va4 = 0, va5 = 0, va6 = 0, va7 = 0;
Integer[] ints = {va1, va2, va3, va4, va5, va6, va7};
for (Map.Entry<String, List<Integer>> entry : orderedEntries) {
XSSFRow dataRow = sheet.createRow(rowIndex);
dataRow.setHeight((short) (14.25 * 20));
for (int i = 0; i < nameRows.length; i++) {
Cell cell = dataRow.createCell(i);
if (i == 0) {
cell.setCellValue(entry.getKey());
} else {
Integer val = entry.getValue().get(i - 1);
if (val != null && val != 0) {
cell.setCellValue(val);
ints[i-1] += entry.getValue().get(i - 1);
}
}
if (i == 1 || i == 5) {
cell.setCellStyle(redStyle);
} else {
cell.setCellStyle(blackStyle);
}
}
// 空白行
XSSFRow emptyRow = sheet.createRow(rowIndex + 1);
emptyRow.setHeight((short) (14.25 * 20));
for (int i = 0; i < nameRows.length; i++) {
Cell cell = emptyRow.createCell(i);
cell.setCellStyle(blackStyle);
}
rowIndex += 2;
}
XSSFRow lastRow = sheet.createRow(rowIndex-1);
lastRow.setHeight((short) (14.25 * 20));
for (int i = 0; i < nameRows.length; i++) {
if (i == 0){
Cell cell = lastRow.createCell(i);
cell.setCellStyle(blackStyle);
}
if (i != 0) {
Cell cell = lastRow.createCell(i);
cell.setCellValue(ints[i - 1]);
if (i == 1 || i == 5) {
cell.setCellStyle(redStyle);
} else {
cell.setCellStyle(blackStyle);
}
}
}
}
}

@ -49,6 +49,12 @@ public class EntrustMaterialCheckoutResultVO {
@ApiModelProperty("定量结果")
private String quantitativeResult;
/**
* 定量结果
*/
@ApiModelProperty("定量结果")
private String metaboliteResult;
/**
* 其他鉴定结果
*/

@ -42,6 +42,7 @@
emr.entrust_id,
emr.qualitative_result,
emr.quantitative_result,
emr.metabolite_result,
emr.other_result,
emr.checkout_remark,
em.name,

Loading…
Cancel
Save