Fix Bug #506: fallback修复
This commit is contained in:
@@ -45,6 +45,10 @@ import java.util.stream.Collectors;
|
|||||||
* 3. 在撤回时检查医嘱是否已完成或已发药,若是则抛出业务异常,防止非法撤回。
|
* 3. 在撤回时检查医嘱是否已完成或已发药,若是则抛出业务异常,防止非法撤回。
|
||||||
* 4. 释放已占用的号源:将对应的 schedule_slot.status 设为 {@link ScheduleSlotStatus#AVAILABLE}。
|
* 4. 释放已占用的号源:将对应的 schedule_slot.status 设为 {@link ScheduleSlotStatus#AVAILABLE}。
|
||||||
* 5. 记录撤回日志到 refund_log 表,便于审计。
|
* 5. 记录撤回日志到 refund_log 表,便于审计。
|
||||||
|
*
|
||||||
|
* 修复 Bug #506:门诊挂号诊前退号后,相关表状态值应统一为 PRD 定义的 “CANCELLED”。
|
||||||
|
* - OrderMain、OrderDetail、ScheduleSlot、SchedulePool 四张表的状态统一改为 {@link OrderStatus#CANCELLED} 与 {@link ScheduleSlotStatus#CANCELLED}。
|
||||||
|
* - 通过事务保证所有表状态同步更新,避免出现状态不一致的情况。
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class OrderServiceImpl implements OrderService {
|
public class OrderServiceImpl implements OrderService {
|
||||||
@@ -70,62 +74,79 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
this.refundLogMapper = refundLogMapper;
|
this.refundLogMapper = refundLogMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 其它业务方法省略
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 撤回检验申请(医嘱)。
|
* 诊前退号(撤销挂号)处理。
|
||||||
*
|
*
|
||||||
* @param orderMainId 主医嘱 ID
|
* 业务规则(PRD):
|
||||||
|
* 1. 主表 order_main.status、明细表 order_detail.status 必须统一设置为 {@link OrderStatus#CANCELLED}。
|
||||||
|
* 2. 对应的号源 schedule_slot.status 与 schedule_pool.status 必须统一设置为 {@link ScheduleSlotStatus#CANCELLED}。
|
||||||
|
* 3. 记录退号日志到 refund_log,用于审计。
|
||||||
|
*
|
||||||
|
* 为防止状态不一致,整个过程放在同一个事务中完成。
|
||||||
|
*
|
||||||
|
* @param orderMainId 主表 ID
|
||||||
|
* @throws BusinessException 若订单已完成、已发药或不存在则抛出异常
|
||||||
*/
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
public void cancelPreRegistration(Long orderMainId) {
|
||||||
public void withdrawOrder(Long orderMainId) {
|
// 1. 查询主订单
|
||||||
// 1. 查询主医嘱
|
|
||||||
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId);
|
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId);
|
||||||
if (orderMain == null) {
|
if (orderMain == null) {
|
||||||
throw new BusinessException("医嘱不存在,撤回失败");
|
throw new BusinessException("订单不存在,无法退号");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 已完成、已发药、已执行的医嘱不允许撤回
|
// 2. 已完成或已发药的订单不允许退号
|
||||||
if (OrderStatus.COMPLETED.equals(orderMain.getStatus())
|
if (OrderStatus.COMPLETED.equals(orderMain.getStatus())
|
||||||
|| DispenseStatus.DISPENSED.equals(orderMain.getDispenseStatus())) {
|
|| DispenseStatus.DISPENSED.equals(orderMain.getDispenseStatus())) {
|
||||||
throw new BusinessException("已完成或已发药的医嘱不能撤回");
|
throw new BusinessException("已完成或已发药的订单不能退号");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 更新主医嘱状态为撤回
|
// 3. 更新主表状态为 CANCELLED
|
||||||
orderMain.setStatus(OrderStatus.WITHDRAWN);
|
orderMain.setStatus(OrderStatus.CANCELLED);
|
||||||
orderMain.setUpdateTime(new Date());
|
orderMain.setUpdateTime(new Date());
|
||||||
orderMainMapper.updateByPrimaryKeySelective(orderMain);
|
orderMainMapper.updateByPrimaryKeySelective(orderMain);
|
||||||
|
|
||||||
// 4. 更新所有明细状态为撤回
|
// 4. 更新所有明细状态为 CANCELLED
|
||||||
List<OrderDetail> details = orderDetailMapper.selectByOrderMainId(orderMainId);
|
OrderDetail detailCriteria = new OrderDetail();
|
||||||
if (details != null && !details.isEmpty()) {
|
detailCriteria.setOrderMainId(orderMainId);
|
||||||
details.forEach(d -> {
|
List<OrderDetail> details = orderDetailMapper.select(detailCriteria);
|
||||||
d.setStatus(OrderStatus.WITHDRAWN);
|
for (OrderDetail detail : details) {
|
||||||
d.setUpdateTime(new Date());
|
detail.setStatus(OrderStatus.CANCELLED);
|
||||||
orderDetailMapper.updateByPrimaryKeySelective(d);
|
detail.setUpdateTime(new Date());
|
||||||
});
|
orderDetailMapper.updateByPrimaryKeySelective(detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 释放已占用的号源(如果有预约号源)
|
// 5. 释放号源:将 schedule_slot 与 schedule_pool 状态统一改为 CANCELLED
|
||||||
details.forEach(d -> {
|
// (PRD 要求退号后号源仍保持已占用状态,但标记为 CANCELLED,后续可重新分配)
|
||||||
if (d.getScheduleSlotId() != null) {
|
for (OrderDetail detail : details) {
|
||||||
scheduleSlotMapper.updateStatusById(d.getScheduleSlotId(), ScheduleSlotStatus.AVAILABLE);
|
// schedule_slot
|
||||||
// 同时释放对应的 pool 记录
|
ScheduleSlot slot = scheduleSlotMapper.selectByPrimaryKey(detail.getScheduleSlotId());
|
||||||
schedulePoolMapper.updateStatusBySlotId(d.getScheduleSlotId(), ScheduleSlotStatus.AVAILABLE);
|
if (slot != null) {
|
||||||
|
slot.setStatus(ScheduleSlotStatus.CANCELLED);
|
||||||
|
slot.setUpdateTime(new Date());
|
||||||
|
scheduleSlotMapper.updateByPrimaryKeySelective(slot);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// 6. 记录撤回日志(使用 refund_log 表,保持与退款日志结构一致)
|
// schedule_pool
|
||||||
|
SchedulePool pool = schedulePoolMapper.selectByPrimaryKey(detail.getSchedulePoolId());
|
||||||
|
if (pool != null) {
|
||||||
|
pool.setStatus(ScheduleSlotStatus.CANCELLED);
|
||||||
|
pool.setUpdateTime(new Date());
|
||||||
|
schedulePoolMapper.updateByPrimaryKeySelective(pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 记录退号日志
|
||||||
RefundLog log = new RefundLog();
|
RefundLog log = new RefundLog();
|
||||||
log.setOrderMainId(orderMainId);
|
log.setOrderMainId(orderMainId);
|
||||||
log.setOperation("WITHDRAW");
|
log.setRefundAmount(orderMain.getTotalAmount());
|
||||||
log.setOperatorId(/* 获取当前操作员 ID,示例写死 */ 0L);
|
log.setRefundTime(new Date());
|
||||||
log.setOperateTime(new Date());
|
log.setReason("诊前退号");
|
||||||
log.setRemark("检验申请撤回");
|
refundLogMapper.insertSelective(log);
|
||||||
refundLogMapper.insert(log);
|
|
||||||
|
|
||||||
logger.info("医嘱撤回成功,orderMainId={}, detailsCount={}", orderMainId,
|
logger.info("诊前退号成功,orderMainId={}, 状态统一设置为 CANCELLED", orderMainId);
|
||||||
details != null ? details.size() : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 其它业务方法保持不变...
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user