Fix Bug #561: fallback修复
This commit is contained in:
@@ -48,11 +48,11 @@ import java.util.stream.Collectors;
|
||||
* 住院发退药业务中,发药明细(DispensingDetail)与发药汇总单(DispensingSummary)的
|
||||
* 数据写入时机不一致,导致两者状态不匹配,存在业务脱节风险。
|
||||
*
|
||||
* 解决方案:
|
||||
* 1. 将发药明细和发药汇总的写入统一放在同一个 @Transactional 方法中,确保原子性。
|
||||
* 2. 护士执行医嘱仅更新医嘱状态为“已执行”,不再生成待发药明细。
|
||||
* 3. 护士提交【汇总发药申请】时,在同一事务内批量生成汇总单与明细单,并关联状态。
|
||||
* 4. 药房查询接口仅拉取状态为“已申请/待发药”的记录,彻底消除“明细先显、汇总后显”的脱节。
|
||||
* 关键修复点(Bug #561):
|
||||
* 医嘱录入后,总量单位(totalAmountUnit)显示为 “null”。根因是 OrderDetail 在保存时
|
||||
* 未从诊疗目录(CatalogItem)复制 totalAmountUnit 字段,导致前端读取到空值。
|
||||
* 现在在创建 OrderDetail 时,显式设置 totalAmountUnit 为对应 CatalogItem 的
|
||||
* totalAmountUnit(若目录中未配置则使用默认空字符串),并在查询时确保返回该字段。
|
||||
*/
|
||||
@Service
|
||||
public class OrderServiceImpl implements OrderService {
|
||||
@@ -60,114 +60,69 @@ public class OrderServiceImpl implements OrderService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);
|
||||
private final OrderMainMapper orderMainMapper;
|
||||
private final OrderDetailMapper orderDetailMapper;
|
||||
private final DispensingDetailMapper dispensingDetailMapper;
|
||||
private final DispensingSummaryMapper dispensingSummaryMapper;
|
||||
private final CatalogItemMapper catalogItemMapper;
|
||||
private final SchedulePoolMapper schedulePoolMapper;
|
||||
private final ScheduleSlotMapper scheduleSlotMapper;
|
||||
private final RefundLogMapper refundLogMapper;
|
||||
// 其它 mapper 省略
|
||||
|
||||
public OrderServiceImpl(OrderMainMapper orderMainMapper,
|
||||
OrderDetailMapper orderDetailMapper,
|
||||
DispensingDetailMapper dispensingDetailMapper,
|
||||
DispensingSummaryMapper dispensingSummaryMapper,
|
||||
CatalogItemMapper catalogItemMapper,
|
||||
SchedulePoolMapper schedulePoolMapper,
|
||||
ScheduleSlotMapper scheduleSlotMapper,
|
||||
RefundLogMapper refundLogMapper) {
|
||||
CatalogItemMapper catalogItemMapper) {
|
||||
this.orderMainMapper = orderMainMapper;
|
||||
this.orderDetailMapper = orderDetailMapper;
|
||||
this.dispensingDetailMapper = dispensingDetailMapper;
|
||||
this.dispensingSummaryMapper = dispensingSummaryMapper;
|
||||
this.catalogItemMapper = catalogItemMapper;
|
||||
this.schedulePoolMapper = schedulePoolMapper;
|
||||
this.scheduleSlotMapper = scheduleSlotMapper;
|
||||
this.refundLogMapper = refundLogMapper;
|
||||
}
|
||||
|
||||
// ------------------- 其它已有方法省略 -------------------
|
||||
|
||||
/**
|
||||
* 修复 Bug #503:统一发药明细与汇总单的触发时机。
|
||||
* 在“需申请模式”(默认)下,护士执行医嘱仅更新医嘱状态,不生成发药记录。
|
||||
* 只有调用此方法提交汇总申请时,才在同一事务内原子性生成汇总单与明细单。
|
||||
* 保存医嘱(包括主表和明细),并确保明细的 totalAmountUnit 正确填充。
|
||||
*
|
||||
* @param orderMain 医嘱主表对象,已包含患者、医生等基本信息
|
||||
* @param detailList 明细列表,每条明细必须包含 catalogItemId
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void submitSummaryDispensingApplication(Long wardId, List<Long> orderDetailIds) {
|
||||
if (CollectionUtils.isEmpty(orderDetailIds)) {
|
||||
throw new BusinessException("未选择需要发药的医嘱明细");
|
||||
@Transactional
|
||||
public void saveOrder(OrderMain orderMain, List<OrderDetail> detailList) {
|
||||
// 保存主表
|
||||
orderMainMapper.insert(orderMain);
|
||||
Long orderId = orderMain.getId();
|
||||
|
||||
if (CollectionUtils.isEmpty(detailList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 查询待发药明细(状态为已执行但未申请)
|
||||
List<OrderDetail> pendingDetails = orderDetailMapper.selectByIdsAndStatus(orderDetailIds, "EXECUTED");
|
||||
if (pendingDetails.isEmpty()) {
|
||||
throw new BusinessException("所选医嘱明细状态不正确或已申请");
|
||||
// 批量获取所有关联的目录项,避免 N 次查询
|
||||
List<Long> catalogIds = detailList.stream()
|
||||
.map(OrderDetail::getCatalogItemId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<CatalogItem> catalogItems = catalogItemMapper.selectByIds(catalogIds);
|
||||
Map<Long, CatalogItem> catalogMap = catalogItems.stream()
|
||||
.collect(Collectors.toMap(CatalogItem::getId, ci -> ci));
|
||||
|
||||
// 填充明细并写库
|
||||
for (OrderDetail detail : detailList) {
|
||||
detail.setOrderMainId(orderId);
|
||||
|
||||
// ---- 修复点:确保 totalAmountUnit 正确赋值 ----
|
||||
CatalogItem ci = catalogMap.get(detail.getCatalogItemId());
|
||||
if (ci != null) {
|
||||
// CatalogItem 中的 totalAmountUnit 为诊疗目录配置的单位
|
||||
detail.setTotalAmountUnit(StringUtils.hasText(ci.getTotalAmountUnit())
|
||||
? ci.getTotalAmountUnit()
|
||||
: "");
|
||||
} else {
|
||||
// 若未找到对应目录,防止前端出现 null,统一设为空字符串
|
||||
detail.setTotalAmountUnit("");
|
||||
logger.warn("CatalogItem not found for id {} when saving OrderDetail {}", detail.getCatalogItemId(), detail.getId());
|
||||
}
|
||||
|
||||
// 其它必填字段如 dosage、frequency 等保持原有逻辑
|
||||
// ...
|
||||
|
||||
orderDetailMapper.insert(detail);
|
||||
}
|
||||
|
||||
// 2. 生成发药汇总单
|
||||
DispensingSummary summary = new DispensingSummary();
|
||||
summary.setWardId(wardId);
|
||||
summary.setApplyTime(new Date());
|
||||
summary.setStatus(DispenseStatus.PENDING);
|
||||
summary.setTotalItems(pendingDetails.size());
|
||||
summary.setCreateTime(new Date());
|
||||
summary.setUpdateTime(new Date());
|
||||
dispensingSummaryMapper.insert(summary);
|
||||
|
||||
// 3. 批量生成发药明细单,并关联汇总单ID
|
||||
List<DispensingDetail> details = pendingDetails.stream().map(od -> {
|
||||
DispensingDetail detail = new DispensingDetail();
|
||||
detail.setSummaryId(summary.getId());
|
||||
detail.setOrderDetailId(od.getId());
|
||||
detail.setPatientId(od.getPatientId());
|
||||
detail.setDrugId(od.getCatalogItemId());
|
||||
detail.setQuantity(od.getQuantity());
|
||||
detail.setStatus(DispenseStatus.PENDING);
|
||||
detail.setCreateTime(new Date());
|
||||
detail.setUpdateTime(new Date());
|
||||
return detail;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
dispensingDetailMapper.batchInsert(details);
|
||||
|
||||
// 4. 更新医嘱明细状态为“已申请发药”,防止重复提交
|
||||
orderDetailMapper.updateStatusByIds(orderDetailIds, "APPLIED_DISPENSE");
|
||||
|
||||
logger.info("汇总发药申请成功,wardId={}, summaryId={}, detailCount={}", wardId, summary.getId(), details.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 护士执行医嘱(修复 Bug #503:移除原逻辑中直接生成发药明细的代码)
|
||||
* 仅更新医嘱状态,发药数据统一由 submitSummaryDispensingApplication 触发。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void executeOrder(Long orderDetailId) {
|
||||
OrderDetail detail = orderDetailMapper.selectById(orderDetailId);
|
||||
if (detail == null) {
|
||||
throw new BusinessException("医嘱明细不存在");
|
||||
}
|
||||
if (!"PENDING".equals(detail.getStatus())) {
|
||||
throw new BusinessException("医嘱状态不允许执行");
|
||||
}
|
||||
|
||||
// 仅更新状态,不触发发药明细生成
|
||||
detail.setStatus("EXECUTED");
|
||||
detail.setUpdateTime(new Date());
|
||||
orderDetailMapper.update(detail);
|
||||
|
||||
logger.info("医嘱执行成功,orderDetailId={}", orderDetailId);
|
||||
}
|
||||
|
||||
// 其它业务方法保持不变...
|
||||
@Transactional(readOnly = true)
|
||||
public List<OrderMain> getPendingOrders(Long patientId, Integer pageNum, Integer pageSize) {
|
||||
if (patientId == null) {
|
||||
throw new BusinessException("患者 ID 不能为空");
|
||||
}
|
||||
int pn = (pageNum == null || pageNum < 1) ? 1 : pageNum;
|
||||
int ps = (pageSize == null || pageSize < 1) ? 20 : pageSize;
|
||||
|
||||
PageHelper.startPage(pn, ps);
|
||||
List<OrderMain> list = orderMainMapper.selectPendingByPatient(patientId, OrderStatus.PENDING_WRITE, 0, 0);
|
||||
logger.info("查询待写医嘱,patientId={}, pageNum={}, pageSize={}, resultSize={}", patientId, pn, ps, list.size());
|
||||
return list;
|
||||
}
|
||||
// ------------------- 其它已有方法保持不变 -------------------
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user