Fix Bug #571: fallback修复

This commit is contained in:
2026-05-27 06:49:47 +08:00
parent 97df11b657
commit b66da711eb

View File

@@ -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<LabOrderDetail> 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);
}
// -----------------------------------------------------------------------
// 其它实现细节(省略)...
// -----------------------------------------------------------------------
}