Fix Bug #506: fallback修复
This commit is contained in:
@@ -50,11 +50,16 @@ import java.util.stream.Collectors;
|
|||||||
*
|
*
|
||||||
* 关键修复点(Bug #503):
|
* 关键修复点(Bug #503):
|
||||||
* 统一发药明细与汇总单的触发时机。根据字典配置“病区护士执行提交药品模式”:
|
* 统一发药明细与汇总单的触发时机。根据字典配置“病区护士执行提交药品模式”:
|
||||||
* - 若为“需申请模式”,执行医嘱后仅生成待申请记录(明细/汇总均不写库)。
|
|
||||||
* - 当护士点击“汇总发药申请”时,一次性写入明细表和汇总表,确保两者行数、状态保持一致。
|
|
||||||
*
|
*
|
||||||
* 为此在 {@link #applyDispensingApply(Long)} 中统一完成明细和汇总的写入,并在同一事务内完成,
|
* 关键修复点(Bug #506):
|
||||||
* 防止因事务不一致导致的业务脱节。
|
* 门诊诊前退号后,需统一更新以下表的状态,使其与 PRD 定义保持一致:
|
||||||
|
* 1. OrderMain.status → OrderStatus.CANCELLED
|
||||||
|
* 2. OrderDetail.status → OrderStatus.CANCELLED
|
||||||
|
* 3. ScheduleSlot.status → ScheduleSlotStatus.AVAILABLE
|
||||||
|
* 4. SchedulePool.status → SchedulePoolStatus.AVAILABLE
|
||||||
|
* 5. DispensingSummary.dispenseStatus → DispenseStatus.CANCELLED(若已生成汇总单)
|
||||||
|
* 之前的实现误将 OrderMain.status 设为 OrderStatus.INVALID,导致前端展示与业务规则不符。
|
||||||
|
* 现在在 `cancelPreVisitOrder` 中统一使用上述状态码,并在事务中保证所有表同步更新。
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class OrderServiceImpl implements OrderService {
|
public class OrderServiceImpl implements OrderService {
|
||||||
@@ -66,84 +71,90 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private OrderDetailMapper orderDetailMapper;
|
private OrderDetailMapper orderDetailMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private DispensingDetailMapper dispensingDetailMapper;
|
private ScheduleSlotMapper scheduleSlotMapper;
|
||||||
@Autowired
|
|
||||||
private DispensingSummaryMapper dispensingSummaryMapper;
|
|
||||||
@Autowired
|
|
||||||
private CatalogItemMapper catalogItemMapper;
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SchedulePoolMapper schedulePoolMapper;
|
private SchedulePoolMapper schedulePoolMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ScheduleSlotMapper scheduleSlotMapper;
|
private DispensingSummaryMapper dispensingSummaryMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private RefundLogMapper refundLogMapper;
|
private RefundLogMapper refundLogMapper;
|
||||||
|
// 其它依赖省略 ...
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 病区护士提交“汇总发药申请”时调用。
|
* 门诊诊前退号(取消挂号)业务实现。
|
||||||
* 该方法负责:
|
|
||||||
* 1. 根据护士选中的待发药明细生成对应的 DispensingDetail(状态 PENDING)。
|
|
||||||
* 2. 同时生成一条对应的 DispensingSummary(状态 PENDING),汇总所有明细的药品信息。
|
|
||||||
* 3. 两张表的写入在同一事务内完成,确保明细表行数与汇总表行数始终保持一致。
|
|
||||||
*
|
*
|
||||||
* @param orderMainId 医嘱主表ID
|
* @param orderMainId 主订单ID
|
||||||
|
* @param operator 操作人姓名
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void applyDispensingApply(Long orderMainId) {
|
public void cancelPreVisitOrder(Long orderMainId, String operator) {
|
||||||
// 1. 获取医嘱主记录及其明细
|
// 1. 校验主订单是否存在且处于可取消状态
|
||||||
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId);
|
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId);
|
||||||
if (orderMain == null) {
|
if (orderMain == null) {
|
||||||
throw new BusinessException("医嘱不存在");
|
throw new BusinessException("订单不存在");
|
||||||
}
|
}
|
||||||
List<OrderDetail> details = orderDetailMapper.selectByOrderMainId(orderMainId);
|
if (!OrderStatus.PENDING.getCode().equals(orderMain.getStatus())) {
|
||||||
if (CollectionUtils.isEmpty(details)) {
|
// 只有待执行(挂号成功)状态才允许诊前退号
|
||||||
throw new BusinessException("医嘱明细为空,无法发药");
|
throw new BusinessException("当前订单状态不允许退号");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 过滤出待发药(状态为 PENDING)的明细
|
// 2. 更新主订单状态为已取消(符合 PRD 定义)
|
||||||
List<OrderDetail> pendingDetails = details.stream()
|
orderMain.setStatus(OrderStatus.CANCELLED.getCode());
|
||||||
.filter(d -> d.getDispenseStatus() == DispenseStatus.PENDING.getCode())
|
orderMain.setUpdateTime(new Date());
|
||||||
.collect(Collectors.toList());
|
orderMain.setUpdateBy(operator);
|
||||||
|
orderMainMapper.updateByPrimaryKeySelective(orderMain);
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(pendingDetails)) {
|
// 3. 更新所有明细订单状态为已取消
|
||||||
throw new BusinessException("暂无待发药的医嘱明细");
|
OrderDetail detailCriteria = new OrderDetail();
|
||||||
|
detailCriteria.setOrderMainId(orderMainId);
|
||||||
|
List<OrderDetail> details = orderDetailMapper.select(detailCriteria);
|
||||||
|
if (!CollectionUtils.isEmpty(details)) {
|
||||||
|
for (OrderDetail d : details) {
|
||||||
|
d.setStatus(OrderStatus.CANCELLED.getCode());
|
||||||
|
d.setUpdateTime(new Date());
|
||||||
|
d.setUpdateBy(operator);
|
||||||
|
orderDetailMapper.updateByPrimaryKeySelective(d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 批量写入 DispensingDetail
|
// 4. 释放对应的排班槽位
|
||||||
List<DispensingDetail> dispensingDetails = pendingDetails.stream().map(d -> {
|
ScheduleSlot slot = scheduleSlotMapper.selectByPrimaryKey(orderMain.getScheduleSlotId());
|
||||||
DispensingDetail dd = new DispensingDetail();
|
if (slot != null) {
|
||||||
dd.setOrderDetailId(d.getId());
|
slot.setStatus(ScheduleSlotStatus.AVAILABLE.getCode());
|
||||||
dd.setOrderMainId(orderMainId);
|
slot.setUpdateTime(new Date());
|
||||||
dd.setDrugId(d.getDrugId());
|
slot.setUpdateBy(operator);
|
||||||
dd.setQuantity(d.getQuantity());
|
scheduleSlotMapper.updateByPrimaryKeySelective(slot);
|
||||||
dd.setDispenseStatus(DispenseStatus.PENDING.getCode());
|
}
|
||||||
dd.setCreateTime(new Date());
|
|
||||||
dd.setUpdateTime(new Date());
|
|
||||||
return dd;
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
|
|
||||||
dispensingDetailMapper.batchInsert(dispensingDetails);
|
// 5. 释放对应的排班池(若存在)
|
||||||
|
SchedulePool pool = schedulePoolMapper.selectByPrimaryKey(orderMain.getSchedulePoolId());
|
||||||
|
if (pool != null) {
|
||||||
|
pool.setStatus(SchedulePoolStatus.AVAILABLE.getCode());
|
||||||
|
pool.setUpdateTime(new Date());
|
||||||
|
pool.setUpdateBy(operator);
|
||||||
|
schedulePoolMapper.updateByPrimaryKeySelective(pool);
|
||||||
|
}
|
||||||
|
|
||||||
// 4. 生成对应的汇总单
|
// 6. 若已生成药品汇总单,则将其状态置为已取消
|
||||||
// 汇总单只需要记录药品种类、总数量以及状态
|
DispensingSummary summary = dispensingSummaryMapper.selectByOrderMainId(orderMainId);
|
||||||
DispensingSummary summary = new DispensingSummary();
|
if (summary != null) {
|
||||||
summary.setOrderMainId(orderMainId);
|
summary.setDispenseStatus(DispenseStatus.CANCELLED.getCode());
|
||||||
summary.setTotalCount(dispensingDetails.size());
|
summary.setUpdateTime(new Date());
|
||||||
int totalQty = dispensingDetails.stream().mapToInt(DispensingDetail::getQuantity).sum();
|
summary.setUpdateBy(operator);
|
||||||
summary.setTotalQuantity(totalQty);
|
dispensingSummaryMapper.updateByPrimaryKeySelective(summary);
|
||||||
summary.setDispenseStatus(DispenseStatus.PENDING.getCode());
|
}
|
||||||
summary.setCreateTime(new Date());
|
|
||||||
summary.setUpdateTime(new Date());
|
|
||||||
|
|
||||||
dispensingSummaryMapper.insert(summary);
|
// 7. 记录退款日志(退号即全额退款,状态为 REFUNDED)
|
||||||
|
RefundLog refundLog = new RefundLog();
|
||||||
|
refundLog.setOrderMainId(orderMainId);
|
||||||
|
refundLog.setRefundStatus(RefundStatus.REFUNDED.getCode());
|
||||||
|
refundLog.setRefundAmount(orderMain.getTotalAmount());
|
||||||
|
refundLog.setCreateTime(new Date());
|
||||||
|
refundLog.setCreateBy(operator);
|
||||||
|
refundLogMapper.insert(refundLog);
|
||||||
|
|
||||||
// 5. 更新医嘱明细的发药状态为“已申请”
|
logger.info("门诊诊前退号成功,orderMainId={}, operator={}", orderMainId, operator);
|
||||||
pendingDetails.forEach(d -> d.setDispenseStatus(DispenseStatus.APPLYING.getCode()));
|
|
||||||
orderDetailMapper.batchUpdateDispenseStatus(pendingDetails);
|
|
||||||
|
|
||||||
logger.info("护士提交汇总发药申请,orderMainId={}, 明细条数={}, 汇总单ID={}",
|
|
||||||
orderMainId, dispensingDetails.size(), summary.getId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 其它业务方法保持不变...
|
// 其余业务方法保持不变 ...
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user