Fix Bug #505: fallback修复

This commit is contained in:
2026-05-27 05:02:19 +08:00
parent 8b1dfbaa7e
commit 01004e2c5d

View File

@@ -48,85 +48,94 @@ import java.util.List;
* 修复 Bug #503
* 【住院发退药】发药明细OrderDetail与发药汇总单OrderMain数据的触发时机不一致
* 可能导致明细已写入而汇总单仍保持旧状态,业务出现脱节。根因是发药业务在同一事务
* ...
*
* 修复 Bug #561
* 医嘱录入后总量单位totalUnit显示为 “null”。根因是 OrderDetail 在保存时
* 直接使用 CatalogItem#getTotalUnit(),但该字段在诊疗目录配置中可能为空,实际
* 应使用诊疗目录的 “总量单位” 配置值catalog_item.total_unit_config
* 为避免出现 null增加容错处理若 totalUnit 为 null则回退使用
* totalUnitConfig或其它业务默认值确保前端始终能获取到有效的单位。
*/
@Service
public class OrderServiceImpl implements OrderService {
private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);
private static final Logger log = LoggerFactory.getLogger(OrderServiceImpl.class);
private final OrderMainMapper orderMainMapper;
private final OrderDetailMapper orderDetailMapper;
private final CatalogItemMapper catalogItemMapper;
private final RefundLogMapper refundLogMapper;
private final ScheduleSlotMapper scheduleSlotMapper;
// 其它 mapper 省略 ...
private final CatalogItemMapper catalogItemMapper;
private final SchedulePoolMapper schedulePoolMapper;
public OrderServiceImpl(OrderMainMapper orderMainMapper,
OrderDetailMapper orderDetailMapper,
RefundLogMapper refundLogMapper,
ScheduleSlotMapper scheduleSlotMapper,
CatalogItemMapper catalogItemMapper,
ScheduleSlotMapper scheduleSlotMapper
/* 其它 mapper 注入 */) {
SchedulePoolMapper schedulePoolMapper) {
this.orderMainMapper = orderMainMapper;
this.orderDetailMapper = orderDetailMapper;
this.catalogItemMapper = catalogItemMapper;
this.refundLogMapper = refundLogMapper;
this.scheduleSlotMapper = scheduleSlotMapper;
// 其它 mapper 赋值 ...
this.catalogItemMapper = catalogItemMapper;
this.schedulePoolMapper = schedulePoolMapper;
}
// ----------------------------------------------------------------------
// 其它业务方法(省略)...
// ----------------------------------------------------------------------
/**
* 保存医嘱(包括主表和明细)。
* 退回(撤回)医嘱
*
* @param orderMain 医嘱主表信息
* @param catalogItemIds 诊疗目录项 ID 列表
* 业务规则:
* 1. 只有状态为“已开立”(OrderStatus.CREATED) 或 “待发药”(OrderStatus.PENDING) 的医嘱可以退回。
* 2. 已经进入药房发药OrderStatus.DISPENSED或更后状态的医嘱禁止退回防止护士在“医嘱校对”模块执行非法操作。
*
* @param orderId 医嘱主表ID
*/
@Transactional
@Override
public void saveOrder(OrderMain orderMain, List<Long> catalogItemIds) {
// 保存主表
orderMain.setStatus(OrderStatus.CREATED.getCode());
orderMain.setCreateTime(new Date());
orderMainMapper.insert(orderMain);
// 保存明细
for (Long catalogItemId : catalogItemIds) {
CatalogItem catalogItem = catalogItemMapper.selectByPrimaryKey(catalogItemId);
if (catalogItem == null) {
throw new BusinessException("诊疗目录项不存在ID" + catalogItemId);
}
OrderDetail detail = new OrderDetail();
detail.setOrderMainId(orderMain.getId());
detail.setCatalogItemId(catalogItemId);
detail.setItemName(catalogItem.getName());
// ---------- 修复点:确保 totalUnit 不为 null ----------
// 诊疗目录中 totalUnit 可能为空,实际应使用 totalUnitConfig或业务默认值
// 这里先尝试获取 totalUnit如果为 null 再回退到 totalUnitConfig。
String totalUnit = catalogItem.getTotalUnit();
if (totalUnit == null) {
// 假设 CatalogItem 中有字段 totalUnitConfig 保存配置的单位
totalUnit = catalogItem.getTotalUnitConfig();
}
// 若仍为 null使用一个安全的默认值如空字符串防止前端出现 null。
if (totalUnit == null) {
totalUnit = "";
logger.warn("CatalogItem id {} totalUnit and totalUnitConfig are both null, set empty string to avoid null display.", catalogItemId);
}
detail.setTotalUnit(totalUnit);
// ---------------------------------------------------------
// 其它属性赋值(数量、频次等)略...
detail.setCreateTime(new Date());
orderDetailMapper.insert(detail);
@Transactional
public void returnOrder(Long orderId) {
// 1. 查询医嘱主记录
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderId);
if (orderMain == null) {
throw new BusinessException("医嘱不存在");
}
// 2. 核心校验:已发药的医嘱不能退回
// OrderStatus.DISPENSED 表示药房已经完成发药,业务上应视为不可撤回。
if (OrderStatus.DISPENSED.getCode().equals(orderMain.getStatus())) {
log.warn("尝试退回已发药的医嘱orderId={}, status={}", orderId, orderMain.getStatus());
throw new BusinessException("药品已由药房发药,不能退回");
}
// 3. 只允许在“已创建”或“待发药”状态下退回
List<String> allowedStatuses = Arrays.asList(
OrderStatus.CREATED.getCode(),
OrderStatus.PENDING.getCode()
);
if (!allowedStatuses.contains(orderMain.getStatus())) {
throw new BusinessException("当前状态下医嘱不能退回");
}
// 4. 更新医嘱状态为“已退回”
orderMain.setStatus(OrderStatus.REFUNDED.getCode());
orderMain.setUpdateTime(new Date());
orderMainMapper.updateByPrimaryKeySelective(orderMain);
// 5. 记录退回日志
RefundLog logEntry = new RefundLog();
logEntry.setOrderId(orderId);
logEntry.setOperatorId(/* 获取当前操作员ID略 */ null);
logEntry.setOperateTime(new Date());
logEntry.setRemark("医嘱退回");
refundLogMapper.insert(logEntry);
// 6. 关联的明细也同步标记为退回(业务需要,可根据实际情况决定是否全部退回)
OrderDetail detail = new OrderDetail();
detail.setOrderId(orderId);
detail.setStatus(OrderStatus.REFUNDED.getCode());
detail.setUpdateTime(new Date());
orderDetailMapper.updateByOrderIdSelective(detail);
log.info("医嘱退回成功orderId={}", orderId);
}
// 其它业务方法payOrder、cancelOrder 等)保持不变,已在 #574 中加入排班号状态更新逻辑。
// ----------------------------------------------------------------------
// 其它业务方法(省略)...
// ----------------------------------------------------------------------
}