package com.ruoyi.inspect.service.impl;
|
|
import com.alibaba.excel.EasyExcel;
|
import com.alibaba.excel.ExcelWriter;
|
import com.alibaba.excel.write.metadata.WriteSheet;
|
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.basic.dto.TemplateInspectionItemDto;
|
import com.ruoyi.basic.utils.StandardTemplateInspectionItemParser;
|
import com.ruoyi.common.utils.GZipUtil;
|
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.framework.exception.ErrorException;
|
import com.ruoyi.inspect.dto.SampleReceiptActionDto;
|
import com.ruoyi.inspect.dto.SampleReceiptPageDto;
|
import com.ruoyi.inspect.dto.SampleReceiptQueryDto;
|
import com.ruoyi.inspect.mapper.*;
|
import com.ruoyi.inspect.pojo.*;
|
import com.ruoyi.inspect.service.InsOrderService;
|
import com.ruoyi.inspect.service.InsOrderStateService;
|
import com.ruoyi.inspect.service.InsSampleReceiptService;
|
import com.ruoyi.system.mapper.UserMapper;
|
import jakarta.servlet.http.HttpServletResponse;
|
import lombok.AllArgsConstructor;
|
import org.apache.commons.lang3.StringUtils;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.io.IOException;
|
import java.net.URLEncoder;
|
import java.time.LocalDateTime;
|
import java.time.format.DateTimeFormatter;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.stream.Collectors;
|
|
@Service
|
@AllArgsConstructor
|
public class InsSampleReceiptServiceImpl extends ServiceImpl<InsSampleReceiptMapper, InsSampleReceipt>
|
implements InsSampleReceiptService {
|
private static final String DIRECT_TEMPLATE_LABORATORY = "新聚";
|
|
private final InsSampleReceiptMapper receiptMapper;
|
private final InsOrderMapper insOrderMapper;
|
private final InsOrderStandardTemplateMapper insOrderStandardTemplateMapper;
|
private final InsSampleMapper insSampleMapper;
|
private final InsProductMapper insProductMapper;
|
private final InsSampleUserMapper insSampleUserMapper;
|
private final InsOrderStateService insOrderStateService;
|
private final InsOrderService insOrderService;
|
private final UserMapper userMapper;
|
|
@Override
|
public IPage<SampleReceiptPageDto> page(Page<?> page, SampleReceiptQueryDto query) {
|
IPage<SampleReceiptPageDto> result = receiptMapper.selectPage(page, query);
|
result.getRecords().forEach(this::fillInspectionItemsFromSnapshots);
|
return result;
|
}
|
|
@Override
|
public SampleReceiptPageDto detail(Integer id) {
|
SampleReceiptPageDto detail = receiptMapper.selectDetail(id);
|
fillInspectionItemsFromSnapshots(detail);
|
return detail;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void submit(SampleReceiptActionDto dto) {
|
if (dto == null || dto.getReceiptId() == null || dto.getMainInspectorId() == null) {
|
throw new ErrorException("请选择主检验人");
|
}
|
InsSampleReceipt receipt = receiptMapper.selectForUpdate(dto.getReceiptId());
|
ensurePending(receipt);
|
InsOrder order = insOrderMapper.selectById(receipt.getInsOrderId());
|
if (order == null || !Integer.valueOf(1).equals(order.getState())) {
|
throw new ErrorException("该委托当前状态不允许样品接收");
|
}
|
List<InsSample> samples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery()
|
.eq(InsSample::getInsOrderId, order.getId()).orderByAsc(InsSample::getId));
|
if (samples.size() != 1 || !samples.get(0).getId().equals(receipt.getInsSampleId())) {
|
throw new ErrorException("该委托的样品数量异常,请检查下单数据");
|
}
|
InsSample sample = samples.get(0);
|
// 只走新聚直绑模板流程:委托单必须已绑定原始记录模板(下单时生成订单模板快照)
|
Long snapshotCount = insOrderStandardTemplateMapper.selectCount(Wrappers.<InsOrderStandardTemplate>lambdaQuery()
|
.eq(InsOrderStandardTemplate::getInsOrderId, order.getId()));
|
if (snapshotCount == 0) {
|
throw new ErrorException("该委托未绑定原始记录模板,不能提交检验");
|
}
|
Long productCount = insProductMapper.selectCount(Wrappers.<InsProduct>lambdaQuery()
|
.eq(InsProduct::getInsSampleId, sample.getId()).eq(InsProduct::getState, 1));
|
if (productCount == 0) {
|
List<TemplateInspectionItemDto> items = getSnapshotInspectionItems(order.getId());
|
if (items.isEmpty()) {
|
throw new ErrorException("订单原始记录模板未配置检验项或导出值,不能提交检验");
|
}
|
int sort = 0;
|
for (TemplateInspectionItemDto item : items) {
|
InsProduct product = new InsProduct();
|
product.setInsSampleId(sample.getId());
|
product.setInspectionItem(item.getInspectionItem());
|
product.setInspectionItemClass("");
|
product.setInspectionItemSubclass("");
|
product.setLaboratory(order.getLaboratory());
|
product.setSample(order.getSample());
|
product.setTemplateId(item.getTemplateId());
|
product.setTemplateRowIndex(item.getTemplateRowIndex());
|
product.setSonLaboratory(DIRECT_TEMPLATE_LABORATORY);
|
product.setState(1);
|
product.setSort(sort++);
|
insProductMapper.insert(product);
|
}
|
}
|
if (userMapper.selectById(dto.getMainInspectorId()) == null) {
|
throw new ErrorException("主检验人不存在或已停用");
|
}
|
if (insOrderStateService.count(Wrappers.lambdaQuery(com.ruoyi.inspect.pojo.InsOrderState.class)
|
.eq(com.ruoyi.inspect.pojo.InsOrderState::getInsOrderId, order.getId())) > 0
|
|| insSampleUserMapper.selectCount(Wrappers.<InsSampleUser>lambdaQuery()
|
.eq(InsSampleUser::getInsSampleId, order.getId())) > 0) {
|
throw new ErrorException("该委托已进入检验任务,不能重复提交");
|
}
|
String appointed = LocalDateTime.now().plusHours(insProductMapper.selectOrderManDay(order.getId()))
|
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
insOrderService.upInsOrder(order.getId(), sample.getId(), appointed, dto.getMainInspectorId(), null);
|
receipt.setStatus(1);
|
receipt.setMainInspectorId(dto.getMainInspectorId());
|
receipt.setReceiveUserId(SecurityUtils.getUserId().intValue());
|
receipt.setReceiveTime(LocalDateTime.now());
|
receipt.setSubmitTime(LocalDateTime.now());
|
receiptMapper.updateById(receipt);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void reject(SampleReceiptActionDto dto) {
|
if (dto == null || dto.getReceiptId() == null || StringUtils.isBlank(dto.getRemark())) {
|
throw new ErrorException("请填写拒收备注");
|
}
|
if (dto.getRemark().trim().length() > 500) {
|
throw new ErrorException("拒收备注不能超过500个字符");
|
}
|
InsSampleReceipt receipt = receiptMapper.selectForUpdate(dto.getReceiptId());
|
ensurePending(receipt);
|
if (insOrderStateService.count(Wrappers.lambdaQuery(com.ruoyi.inspect.pojo.InsOrderState.class)
|
.eq(com.ruoyi.inspect.pojo.InsOrderState::getInsOrderId, receipt.getInsOrderId())) > 0) {
|
throw new ErrorException("该委托已进入检验任务,不能拒收");
|
}
|
receipt.setStatus(2);
|
receipt.setRejectRemark(dto.getRemark().trim());
|
receipt.setReceiveUserId(SecurityUtils.getUserId().intValue());
|
receipt.setReceiveTime(LocalDateTime.now());
|
receiptMapper.updateById(receipt);
|
InsOrder currentOrder = insOrderMapper.selectById(receipt.getInsOrderId());
|
if (currentOrder == null || StringUtils.isBlank(currentOrder.getEntrustCode())) {
|
throw new ErrorException("委托编号不存在,不能作废");
|
}
|
String originalCode = currentOrder.getEntrustCode();
|
String voidCode = originalCode + "-zf";
|
int suffix = 2;
|
// 同一原编号可能经历多次下单、拒收,保留每张作废单的唯一编号。
|
while (insOrderMapper.selectCount(Wrappers.<InsOrder>lambdaQuery()
|
.eq(InsOrder::getEntrustCode, voidCode)
|
.ne(InsOrder::getId, currentOrder.getId())) > 0) {
|
voidCode = originalCode + "-" + suffix++ + "-zf";
|
}
|
InsOrder order = new InsOrder();
|
order.setId(currentOrder.getId());
|
order.setEntrustCode(voidCode);
|
order.setState(5);
|
insOrderMapper.updateById(order);
|
insOrderMapper.updateInspectionOrderEntrustCode(order.getId(), voidCode);
|
}
|
|
private void ensurePending(InsSampleReceipt receipt) {
|
if (receipt == null || !Integer.valueOf(0).equals(receipt.getStatus())) {
|
throw new ErrorException("该样品接收记录已被处理,请刷新后重试");
|
}
|
}
|
|
private List<TemplateInspectionItemDto> getSnapshotInspectionItems(Integer orderId) {
|
List<InsOrderStandardTemplate> snapshots = insOrderStandardTemplateMapper.selectList(
|
Wrappers.<InsOrderStandardTemplate>lambdaQuery()
|
.eq(InsOrderStandardTemplate::getInsOrderId, orderId)
|
.orderByAsc(InsOrderStandardTemplate::getSort, InsOrderStandardTemplate::getId));
|
List<TemplateInspectionItemDto> items = new ArrayList<>();
|
for (InsOrderStandardTemplate snapshot : snapshots) {
|
String thing = snapshot.getThing();
|
try {
|
thing = GZipUtil.uncompress(thing);
|
} catch (RuntimeException ignored) {
|
// 兼容未压缩的历史模板快照。
|
}
|
items.addAll(StandardTemplateInspectionItemParser.parse(
|
snapshot.getTemplateId(), snapshot.getSort(), thing));
|
}
|
return items;
|
}
|
|
private void fillInspectionItemsFromSnapshots(SampleReceiptPageDto row) {
|
if (row == null || row.getOrderId() == null || StringUtils.isNotBlank(row.getInspectionItem())) {
|
return;
|
}
|
try {
|
String names = getSnapshotInspectionItems(row.getOrderId()).stream()
|
.map(TemplateInspectionItemDto::getInspectionItem)
|
.distinct().collect(Collectors.joining("\n"));
|
row.setInspectionItem(names);
|
} catch (RuntimeException ignored) {
|
// 列表仍可查看;提交检验时会返回具体的模板解析错误。
|
}
|
}
|
|
@Override
|
public void export(SampleReceiptQueryDto query, HttpServletResponse response) {
|
List<SampleReceiptPageDto> list = receiptMapper.selectExportList(query);
|
list.forEach(this::fillInspectionItemsFromSnapshots);
|
response.setContentType("application/vnd.ms-excel");
|
response.setCharacterEncoding("UTF-8");
|
try {
|
String fileName = URLEncoder.encode("样品接收导出", "UTF-8");
|
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
|
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
|
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
|
WriteSheet sheet = EasyExcel.writerSheet(0, "样品接收导出").head(SampleReceiptPageDto.class).build();
|
excelWriter.write(list, sheet);
|
excelWriter.finish();
|
} catch (IOException e) {
|
throw new RuntimeException("导出失败");
|
}
|
}
|
}
|