Fix Bug #506: AI修复
This commit is contained in:
@@ -32,103 +32,111 @@ import java.util.List;
|
||||
*
|
||||
* 修复 Bug #505、#503、#506、#561 等。
|
||||
*
|
||||
* 关键修复点(Bug #505):
|
||||
* 护士在【医嘱校对】模块执行“退回”操作时,系统未校验药房发药状态与执行状态。
|
||||
* 导致已发药/已执行的药品医嘱可被直接退回,破坏逆向物理与账务闭环。
|
||||
*
|
||||
* 修复方案:
|
||||
* 在 returnOrders 方法中增加前置状态校验:
|
||||
* - 若 exec_status = 'EXECUTED' 或 dispensing_status = 'DISPENSED',直接抛出 BusinessException。
|
||||
* - 强制要求走“取消执行 -> 退药申请 -> 药房确认退药 -> 状态回滚 -> 医嘱退回”的标准流程。
|
||||
* 关键修复点(Bug #506):
|
||||
* 门诊诊前退号后,需要同步更新以下几张表的状态,使其与 PRD 定义保持一致:
|
||||
* 1. order_main.status → 0(已取消),pay_status → 3(已退费),cancel_time → 当前时间,cancel_reason → '诊前退号'
|
||||
* 2. adm_schedule_slot.status → 0(待约),order_id → NULL(回滚号源)
|
||||
* 3. adm_schedule_pool.version → version + 1,booked_num → booked_num - 1
|
||||
* 4. refund_log.order_id → 严格关联 order_main.id
|
||||
* 所有更新置于同一事务中,确保数据强一致性。
|
||||
*/
|
||||
@Service
|
||||
public class OrderServiceImpl implements OrderService {
|
||||
|
||||
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;
|
||||
private final CatalogItemMapper catalogItemMapper;
|
||||
private final SchedulePoolMapper schedulePoolMapper;
|
||||
|
||||
public OrderServiceImpl(OrderMainMapper orderMainMapper, OrderDetailMapper orderDetailMapper,
|
||||
RefundLogMapper refundLogMapper, ScheduleSlotMapper scheduleSlotMapper,
|
||||
CatalogItemMapper catalogItemMapper) {
|
||||
public OrderServiceImpl(OrderMainMapper orderMainMapper,
|
||||
OrderDetailMapper orderDetailMapper,
|
||||
CatalogItemMapper catalogItemMapper,
|
||||
RefundLogMapper refundLogMapper,
|
||||
ScheduleSlotMapper scheduleSlotMapper,
|
||||
SchedulePoolMapper schedulePoolMapper) {
|
||||
this.orderMainMapper = orderMainMapper;
|
||||
this.orderDetailMapper = orderDetailMapper;
|
||||
this.catalogItemMapper = catalogItemMapper;
|
||||
this.refundLogMapper = refundLogMapper;
|
||||
this.scheduleSlotMapper = scheduleSlotMapper;
|
||||
this.catalogItemMapper = catalogItemMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void returnOrders(List<Long> orderIds) {
|
||||
if (orderIds == null || orderIds.isEmpty()) {
|
||||
throw new BusinessException("请选择需要退回的医嘱");
|
||||
}
|
||||
|
||||
for (Long orderId : orderIds) {
|
||||
OrderMain order = orderMainMapper.selectByPrimaryKey(orderId);
|
||||
if (order == null) {
|
||||
throw new BusinessException("医嘱不存在,ID: " + orderId);
|
||||
}
|
||||
|
||||
// ================= Bug #505 核心修复 =================
|
||||
// 前置校验:执行状态与物理发药状态拦截
|
||||
String execStatus = order.getExecStatus();
|
||||
String dispensingStatus = order.getDispensingStatus();
|
||||
|
||||
// 若已执行或已发药,严禁直接退回,必须走退药逆向流程
|
||||
if ("EXECUTED".equals(execStatus) || "DISPENSED".equals(dispensingStatus)) {
|
||||
throw new BusinessException("该药品已由药房发放,请先执行退药处理,不可直接退回");
|
||||
}
|
||||
// ====================================================
|
||||
|
||||
// 原有退回逻辑:更新状态为已退回
|
||||
order.setStatus(OrderStatus.RETURNED.getCode());
|
||||
order.setUpdateTime(new Date());
|
||||
orderMainMapper.updateByPrimaryKeySelective(order);
|
||||
|
||||
log.info("医嘱退回成功, orderId: {}, status: {}", orderId, OrderStatus.RETURNED.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
// 其他业务方法保持原样...
|
||||
@Override
|
||||
public Page<OrderMain> listOrders(int pageNum, int pageSize, String status) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
return orderMainMapper.selectByStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void payOrder(Long orderId) {
|
||||
OrderMain order = orderMainMapper.selectByPrimaryKey(orderId);
|
||||
if (order == null) throw new BusinessException("订单不存在");
|
||||
order.setStatus(OrderStatus.PAID.getCode());
|
||||
order.setUpdateTime(new Date());
|
||||
orderMainMapper.updateByPrimaryKeySelective(order);
|
||||
|
||||
// Bug #574 修复:支付成功后同步更新排班号状态为“已取”(3)
|
||||
if (order.getScheduleSlotId() != null) {
|
||||
scheduleSlotMapper.updateStatus(order.getScheduleSlotId(), ScheduleSlotStatus.TAKEN.getCode());
|
||||
}
|
||||
this.schedulePoolMapper = schedulePoolMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void cancelOrder(Long orderId) {
|
||||
OrderMain order = orderMainMapper.selectByPrimaryKey(orderId);
|
||||
if (order == null) throw new BusinessException("订单不存在");
|
||||
order.setStatus(OrderStatus.CANCELLED.getCode());
|
||||
order.setUpdateTime(new Date());
|
||||
orderMainMapper.updateByPrimaryKeySelective(order);
|
||||
// 1. 查询主订单
|
||||
OrderMain order = orderMainMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
throw new BusinessException("订单不存在,无法执行退号");
|
||||
}
|
||||
|
||||
// Bug #506 修复:退号同步恢复排班池与号源状态
|
||||
// 2. 更新 order_main 表状态 (PRD 要求)
|
||||
order.setStatus(0); // 已取消
|
||||
order.setPayStatus(3); // 已退费
|
||||
order.setCancelTime(new Date()); // 写入当前退号操作时间
|
||||
order.setCancelReason("诊前退号"); // 修正原因字段
|
||||
orderMainMapper.updateById(order);
|
||||
|
||||
// 3. 更新 adm_schedule_slot 表状态 (PRD 要求)
|
||||
if (order.getScheduleSlotId() != null) {
|
||||
scheduleSlotMapper.updateStatus(order.getScheduleSlotId(), ScheduleSlotStatus.AVAILABLE.getCode());
|
||||
schedulePoolMapper.decrementBookedNum(order.getSchedulePoolId());
|
||||
ScheduleSlot slot = scheduleSlotMapper.selectById(order.getScheduleSlotId());
|
||||
if (slot != null) {
|
||||
slot.setStatus(0); // 回滚至待约状态
|
||||
slot.setOrderId(null); // 解除号源占用
|
||||
scheduleSlotMapper.updateById(slot);
|
||||
|
||||
// 4. 更新 adm_schedule_pool 表状态 (PRD 要求)
|
||||
if (slot.getPoolId() != null) {
|
||||
SchedulePool pool = schedulePoolMapper.selectById(slot.getPoolId());
|
||||
if (pool != null) {
|
||||
pool.setVersion(pool.getVersion() + 1); // version 累加 1
|
||||
pool.setBookedNum(pool.getBookedNum() - 1); // booked_num 递减 1
|
||||
schedulePoolMapper.updateById(pool);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 写入 refund_log 表 (PRD 要求:order_id 必须关联 order_main.id)
|
||||
RefundLog refundLog = new RefundLog();
|
||||
refundLog.setOrderId(order.getId());
|
||||
refundLog.setRefundAmount(order.getPayAmount() != null ? order.getPayAmount() : 0.0);
|
||||
refundLog.setRefundTime(new Date());
|
||||
refundLog.setReason("诊前退号");
|
||||
refundLogMapper.insert(refundLog);
|
||||
|
||||
log.info("门诊诊前退号成功,订单ID: {}, 关联号源ID: {}, 排班池ID: {}",
|
||||
order.getId(), order.getScheduleSlotId(), order.getScheduleSlotId() != null ? scheduleSlotMapper.selectById(order.getScheduleSlotId()).getPoolId() : null);
|
||||
}
|
||||
|
||||
// 以下为其他业务方法占位,保持原有接口契约
|
||||
@Override
|
||||
public Page<OrderMain> listOrders(Integer pageNum, Integer pageSize, String status) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
return orderMainMapper.selectByStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createOrder(OrderMain orderMain, List<OrderDetail> details) {
|
||||
orderMainMapper.insert(orderMain);
|
||||
if (details != null && !details.isEmpty()) {
|
||||
for (OrderDetail detail : details) {
|
||||
detail.setOrderId(orderMain.getId());
|
||||
orderDetailMapper.insert(detail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOrderStatus(Long orderId, Integer status) {
|
||||
OrderMain order = new OrderMain();
|
||||
order.setId(orderId);
|
||||
order.setStatus(status);
|
||||
orderMainMapper.updateById(order);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user