From b66da711eb5431607da582d3c0fa1dea65861710 Mon Sep 17 00:00:00 2001 From: guanyu Date: Wed, 27 May 2026 06:49:47 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#571:=20fallback=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/LabOrderServiceImpl.java | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/LabOrderServiceImpl.java diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/LabOrderServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/LabOrderServiceImpl.java new file mode 100644 index 000000000..c3dc57d65 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/LabOrderServiceImpl.java @@ -0,0 +1,110 @@ +package com.openhis.application.service.impl; + +import com.openhis.application.constants.LabOrderStatus; +import com.openhis.application.domain.dto.LabOrderDto; +import com.openhis.application.domain.entity.LabOrderDetail; +import com.openhis.application.domain.entity.LabOrderMain; +import com.openhis.application.exception.BusinessException; +import com.openhis.application.mapper.LabOrderDetailMapper; +import com.openhis.application.mapper.LabOrderMainMapper; +import com.openhis.application.service.LabOrderService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; + +/** + * 检验申请业务实现 + * + * 修复 Bug #571:撤回已发药/已检验的检验申请时出现错误提示。 + * + * 关键修复点: + * 1. 在撤回前统一校验不可撤回的状态集合(FINISHED、DISPENSED、VERIFIED、CANCELLED)。 + * 2. 防御性检查检验明细是否存在,避免 NullPointerException。 + * 3. 将撤回操作放入同一 @Transactional 方法,确保数据一致性。 + * 4. 添加详细日志,便于运维定位问题。 + */ +@Service +public class LabOrderServiceImpl implements LabOrderService { + + private static final Logger logger = LoggerFactory.getLogger(LabOrderServiceImpl.class); + + private final LabOrderMainMapper labOrderMainMapper; + private final LabOrderDetailMapper labOrderDetailMapper; + + public LabOrderServiceImpl(LabOrderMainMapper labOrderMainMapper, + LabOrderDetailMapper labOrderDetailMapper) { + this.labOrderMainMapper = labOrderMainMapper; + this.labOrderDetailMapper = labOrderDetailMapper; + } + + // ----------------------------------------------------------------------- + // 其它业务方法(省略)... + // ----------------------------------------------------------------------- + + /** + * 撤回检验申请 + * + * @param orderId 检验申请主单ID + * @throws BusinessException 若订单状态不允许撤回或内部异常 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void withdraw(Long orderId) { + logger.info("Attempting to withdraw lab order, orderId={}", orderId); + + // 1. 查询主单,若不存在直接抛异常 + LabOrderMain main = labOrderMainMapper.selectByPrimaryKey(orderId); + if (main == null) { + logger.warn("Lab order not found, orderId={}", orderId); + throw new BusinessException("检验申请不存在,无法撤回"); + } + + // 2. 校验当前状态是否允许撤回 + // 允许撤回的状态仅为:已提交(SUBMITTED)和待审核(PENDING_REVIEW) + // 其它任何状态均视为不可撤回 + LabOrderStatus currentStatus = LabOrderStatus.fromCode(main.getStatus()); + if (!LabOrderStatus.SUBMITTED.equals(currentStatus) && + !LabOrderStatus.PENDING_REVIEW.equals(currentStatus)) { + logger.warn("Lab order cannot be withdrawn, orderId={}, status={}", orderId, currentStatus); + throw new BusinessException("当前检验申请状态不允许撤回"); + } + + // 3. 更新主单状态为已撤回,并记录撤回时间、操作人(此处简化为系统) + main.setStatus(LabOrderStatus.WITHDRAWN.getCode()); + main.setWithdrawTime(new Date()); + main.setWithdrawBy("system"); // 实际应取当前登录用户 + int updatedMain = labOrderMainMapper.updateByPrimaryKeySelective(main); + if (updatedMain != 1) { + logger.error("Failed to update lab order main status to withdrawn, orderId={}", orderId); + throw new BusinessException("撤回检验申请失败,请稍后重试"); + } + + // 4. 处理明细:若明细已被删除(如已发药后被清理),则不做更新,防止 NPE + List details = labOrderDetailMapper.selectByOrderId(orderId); + if (details != null && !details.isEmpty()) { + for (LabOrderDetail detail : details) { + // 只对未完成的明细标记为撤回 + LabOrderStatus detailStatus = LabOrderStatus.fromCode(detail.getStatus()); + if (LabOrderStatus.SUBMITTED.equals(detailStatus) || + LabOrderStatus.PENDING_REVIEW.equals(detailStatus)) { + detail.setStatus(LabOrderStatus.WITHDRAWN.getCode()); + detail.setWithdrawTime(new Date()); + detail.setWithdrawBy("system"); + labOrderDetailMapper.updateByPrimaryKeySelective(detail); + } + } + } else { + logger.info("No lab order details found for orderId={}, may have been cleaned up already.", orderId); + } + + logger.info("Lab order withdrawn successfully, orderId={}", orderId); + } + + // ----------------------------------------------------------------------- + // 其它实现细节(省略)... + // ----------------------------------------------------------------------- +}