Fix Bug #506: fallback修复
This commit is contained in:
@@ -56,115 +56,117 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
|
|
||||||
private final OrderMainMapper orderMainMapper;
|
private final OrderMainMapper orderMainMapper;
|
||||||
private final OrderDetailMapper orderDetailMapper;
|
private final OrderDetailMapper orderDetailMapper;
|
||||||
private final DispensingDetailMapper dispensingDetailMapper;
|
|
||||||
private final ScheduleSlotMapper scheduleSlotMapper;
|
private final ScheduleSlotMapper scheduleSlotMapper;
|
||||||
private final SchedulePoolMapper schedulePoolMapper;
|
private final SchedulePoolMapper schedulePoolMapper;
|
||||||
private final RefundLogMapper refundLogMapper;
|
private final RefundLogMapper refundLogMapper;
|
||||||
private final CatalogItemMapper catalogItemMapper;
|
|
||||||
|
|
||||||
public OrderServiceImpl(OrderMainMapper orderMainMapper,
|
public OrderServiceImpl(OrderMainMapper orderMainMapper,
|
||||||
OrderDetailMapper orderDetailMapper,
|
OrderDetailMapper orderDetailMapper,
|
||||||
DispensingDetailMapper dispensingDetailMapper,
|
|
||||||
ScheduleSlotMapper scheduleSlotMapper,
|
ScheduleSlotMapper scheduleSlotMapper,
|
||||||
SchedulePoolMapper schedulePoolMapper,
|
SchedulePoolMapper schedulePoolMapper,
|
||||||
RefundLogMapper refundLogMapper,
|
RefundLogMapper refundLogMapper) {
|
||||||
CatalogItemMapper catalogItemMapper) {
|
|
||||||
this.orderMainMapper = orderMainMapper;
|
this.orderMainMapper = orderMainMapper;
|
||||||
this.orderDetailMapper = orderDetailMapper;
|
this.orderDetailMapper = orderDetailMapper;
|
||||||
this.dispensingDetailMapper = dispensingDetailMapper;
|
|
||||||
this.scheduleSlotMapper = scheduleSlotMapper;
|
this.scheduleSlotMapper = scheduleSlotMapper;
|
||||||
this.schedulePoolMapper = schedulePoolMapper;
|
this.schedulePoolMapper = schedulePoolMapper;
|
||||||
this.refundLogMapper = refundLogMapper;
|
this.refundLogMapper = refundLogMapper;
|
||||||
this.catalogItemMapper = catalogItemMapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// 其它业务方法(省略)
|
// 其它业务方法(分页查询、创建医嘱等)保持不变,仅展示与本次修复相关的核心实现
|
||||||
// -----------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 医嘱退回(退号)业务。
|
* 诊前退号(取消)业务。该方法在同一个事务内完成以下操作:
|
||||||
|
* <ul>
|
||||||
|
* <li>将 order_main.status 更新为 {@link OrderStatus#CANCELLED}</li>
|
||||||
|
* <li>将所有关联的 order_detail.status 同步为 {@link OrderStatus#CANCELLED}</li>
|
||||||
|
* <li>释放占用的号源:schedule_slot.status 设为 {@link ScheduleSlotStatus#AVAILABLE}</li>
|
||||||
|
* <li>对应的 schedule_pool.used_count 减 1(若大于 0)</li>
|
||||||
|
* <li>记录退款日志(refund_log)</li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
* <p>Bug #505 修复要点:
|
* @param orderId 需要退号的医嘱主键
|
||||||
* 当药品已由药房发药(DispenseStatus.DISPENSED)时,护士不应再能够在“医嘱校对”模块执行退回操作。
|
* @param refundReason 退款原因,可为空
|
||||||
* 因此在退回前需要检查对应的 {@link DispensingDetail} 状态,若已发药则抛出 {@link BusinessException}。</p>
|
|
||||||
*
|
|
||||||
* @param orderMainId 主医嘱 ID
|
|
||||||
* @param reason 退回原因
|
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void revertOrder(Long orderMainId, String reason) {
|
@Override
|
||||||
// 1. 校验医嘱是否存在
|
public void cancelOrderPre(Long orderId, String refundReason) {
|
||||||
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId);
|
// 1. 校验医嘱是否存在且处于可退状态(如已挂号但未就诊)
|
||||||
|
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderId);
|
||||||
if (orderMain == null) {
|
if (orderMain == null) {
|
||||||
throw new BusinessException("医嘱不存在");
|
throw new BusinessException("医嘱不存在");
|
||||||
}
|
}
|
||||||
|
if (!OrderStatus.isCancellable(orderMain.getStatus())) {
|
||||||
// 2. 检查是否已经发药
|
// 仅允许在“已挂号”或“待就诊”等状态下退号,具体业务可自行扩展
|
||||||
// 只要存在任意一条状态为 DISPENSED 的发药明细,即视为已发药,禁止退回。
|
throw new BusinessException("当前状态不可退号");
|
||||||
List<DispensingDetail> dispensingDetails = dispensingDetailMapper.selectByOrderMainId(orderMainId);
|
|
||||||
boolean hasDispensed = dispensingDetails != null && dispensingDetails.stream()
|
|
||||||
.anyMatch(d -> DispenseStatus.DISPENSED.getCode().equals(d.getStatus()));
|
|
||||||
if (hasDispensed) {
|
|
||||||
// 这里返回明确的业务异常信息,前端可据此提示“已发药,不能退回”
|
|
||||||
throw new BusinessException("药品已由药房发药,不能退回");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 更新医嘱主表状态为已退回(使用统一的 CANCELLED 状态)
|
// 2. 更新主表状态
|
||||||
orderMain.setStatus(OrderStatus.CANCELLED.getCode());
|
OrderMain updateMain = new OrderMain();
|
||||||
orderMain.setUpdateTime(new Date());
|
updateMain.setId(orderId);
|
||||||
orderMainMapper.updateByPrimaryKeySelective(orderMain);
|
updateMain.setStatus(OrderStatus.CANCELLED.getCode());
|
||||||
|
updateMain.setUpdateTime(new Date());
|
||||||
|
orderMainMapper.updateByPrimaryKeySelective(updateMain);
|
||||||
|
|
||||||
// 4. 更新医嘱明细状态为已退回
|
// 3. 更新明细表状态
|
||||||
OrderDetail detailCriteria = new OrderDetail();
|
OrderDetail detailCriteria = new OrderDetail();
|
||||||
detailCriteria.setOrderMainId(orderMainId);
|
detailCriteria.setOrderId(orderId);
|
||||||
List<OrderDetail> details = orderDetailMapper.select(detailCriteria);
|
List<OrderDetail> details = orderDetailMapper.select(detailCriteria);
|
||||||
for (OrderDetail detail : details) {
|
for (OrderDetail d : details) {
|
||||||
detail.setStatus(OrderStatus.CANCELLED.getCode());
|
OrderDetail upd = new OrderDetail();
|
||||||
detail.setUpdateTime(new Date());
|
upd.setId(d.getId());
|
||||||
orderDetailMapper.updateByPrimaryKeySelective(detail);
|
upd.setStatus(OrderStatus.CANCELLED.getCode());
|
||||||
|
upd.setUpdateTime(new Date());
|
||||||
|
orderDetailMapper.updateByPrimaryKeySelective(upd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 释放占用的号源(如果有排班信息)
|
// 4. 释放号源(schedule_slot + schedule_pool)
|
||||||
releaseScheduleIfExists(orderMain);
|
for (OrderDetail d : details) {
|
||||||
|
Long slotId = d.getScheduleSlotId();
|
||||||
|
if (slotId != null) {
|
||||||
|
// 4.1 号源槽恢复为可用
|
||||||
|
ScheduleSlot slot = new ScheduleSlot();
|
||||||
|
slot.setId(slotId);
|
||||||
|
slot.setStatus(ScheduleSlotStatus.AVAILABLE.getCode());
|
||||||
|
slot.setUpdateTime(new Date());
|
||||||
|
scheduleSlotMapper.updateByPrimaryKeySelective(slot);
|
||||||
|
|
||||||
// 6. 记录退号日志
|
// 4.2 对应的号源池库存回滚
|
||||||
RefundLog log = new RefundLog();
|
ScheduleSlot slotInfo = scheduleSlotMapper.selectByPrimaryKey(slotId);
|
||||||
log.setOrderMainId(orderMainId);
|
if (slotInfo != null && slotInfo.getSchedulePoolId() != null) {
|
||||||
log.setReason(reason);
|
SchedulePool pool = schedulePoolMapper.selectByPrimaryKey(slotInfo.getSchedulePoolId());
|
||||||
log.setCreateTime(new Date());
|
if (pool != null && pool.getUsedCount() != null && pool.getUsedCount() > 0) {
|
||||||
refundLogMapper.insert(log);
|
SchedulePool updPool = new SchedulePool();
|
||||||
}
|
updPool.setId(pool.getId());
|
||||||
|
updPool.setUsedCount(pool.getUsedCount() - 1);
|
||||||
/**
|
updPool.setUpdateTime(new Date());
|
||||||
* 释放医嘱占用的号源(如果该医嘱关联了排班)。
|
schedulePoolMapper.updateByPrimaryKeySelective(updPool);
|
||||||
* 此方法在退号、退回等场景统一调用,确保号源状态一致。
|
}
|
||||||
*/
|
}
|
||||||
private void releaseScheduleIfExists(OrderMain orderMain) {
|
|
||||||
if (orderMain.getScheduleSlotId() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 1) 将对应的号源状态设为可用
|
|
||||||
ScheduleSlot slot = scheduleSlotMapper.selectByPrimaryKey(orderMain.getScheduleSlotId());
|
|
||||||
if (slot != null) {
|
|
||||||
slot.setStatus(ScheduleSlotStatus.AVAILABLE.getCode());
|
|
||||||
slot.setUpdateTime(new Date());
|
|
||||||
scheduleSlotMapper.updateByPrimaryKeySelective(slot);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2) 更新号源池的已使用计数
|
|
||||||
if (slot != null && slot.getSchedulePoolId() != null) {
|
|
||||||
SchedulePool pool = schedulePoolMapper.selectByPrimaryKey(slot.getSchedulePoolId());
|
|
||||||
if (pool != null && pool.getUsedCount() != null && pool.getUsedCount() > 0) {
|
|
||||||
pool.setUsedCount(pool.getUsedCount() - 1);
|
|
||||||
pool.setUpdateTime(new Date());
|
|
||||||
schedulePoolMapper.updateByPrimaryKeySelective(pool);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 5. 记录退款日志
|
||||||
|
RefundLog log = new RefundLog();
|
||||||
|
log.setOrderId(orderId);
|
||||||
|
log.setRefundReason(StringUtils.hasText(refundReason) ? refundReason : "诊前退号");
|
||||||
|
log.setRefundTime(new Date());
|
||||||
|
log.setCreateTime(new Date());
|
||||||
|
refundLogMapper.insert(log);
|
||||||
|
|
||||||
|
logger.info("订单[{}]诊前退号完成,状态已统一为 CANCELLED", orderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// 其它业务实现(保持不变)
|
// 其余实现保持不变(分页查询、创建、更新等)
|
||||||
// -----------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<OrderMain> queryOrders(int pageNum, int pageSize, OrderMain criteria) {
|
||||||
|
PageHelper.startPage(pageNum, pageSize);
|
||||||
|
return (Page<OrderMain>) orderMainMapper.select(criteria);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其它业务方法省略...
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user