Fix Bug #503: fallback修复
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
package com.openhis.application.service.impl;
|
package com.openhs.application.service.impl;
|
||||||
|
|
||||||
import com.github.pagehelper.Page;
|
import com.github.pagehelper.Page;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
@@ -50,6 +50,11 @@ import java.util.stream.Collectors;
|
|||||||
*
|
*
|
||||||
* 关键修复点(Bug #503):
|
* 关键修复点(Bug #503):
|
||||||
* 统一发药明细与汇总单的触发时机。根据字典配置“病区护士执行提交药品模式”:
|
* 统一发药明细与汇总单的触发时机。根据字典配置“病区护士执行提交药品模式”:
|
||||||
|
* - 若为“需申请模式”,执行医嘱后仅生成待申请记录(明细/汇总均不写库)。
|
||||||
|
* - 当护士点击“汇总发药申请”时,一次性写入明细表和汇总表,确保两者行数、状态保持一致。
|
||||||
|
*
|
||||||
|
* 为此在 {@link #applyDispensingApply(Long)} 中统一完成明细和汇总的写入,并在同一事务内完成,
|
||||||
|
* 防止因事务不一致导致的业务脱节。
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class OrderServiceImpl implements OrderService {
|
public class OrderServiceImpl implements OrderService {
|
||||||
@@ -61,87 +66,84 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private OrderDetailMapper orderDetailMapper;
|
private OrderDetailMapper orderDetailMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ScheduleSlotMapper scheduleSlotMapper;
|
|
||||||
@Autowired
|
|
||||||
private SchedulePoolMapper schedulePoolMapper;
|
|
||||||
@Autowired
|
|
||||||
private CatalogItemMapper catalogItemMapper;
|
|
||||||
@Autowired
|
|
||||||
private DispensingDetailMapper dispensingDetailMapper;
|
private DispensingDetailMapper dispensingDetailMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private DispensingSummaryMapper dispensingSummaryMapper;
|
private DispensingSummaryMapper dispensingSummaryMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private CatalogItemMapper catalogItemMapper;
|
||||||
|
@Autowired
|
||||||
|
private SchedulePoolMapper schedulePoolMapper;
|
||||||
|
@Autowired
|
||||||
|
private ScheduleSlotMapper scheduleSlotMapper;
|
||||||
|
@Autowired
|
||||||
private RefundLogMapper refundLogMapper;
|
private RefundLogMapper refundLogMapper;
|
||||||
|
|
||||||
@Value("${nurse.dispense.apply.mode:0}")
|
|
||||||
private int dispenseApplyMode; // 0: 直接发药, 1: 需申请
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// 统一的状态名称映射(新加的核心实现)
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
/**
|
/**
|
||||||
* 将 OrderStatus、DispenseStatus 等内部枚举转换为《药品医嘱状态映射表》中的中文名称。
|
* 病区护士提交“汇总发药申请”时调用。
|
||||||
* 所有对外返回的状态文字均走此方法,避免硬编码导致的歧义。
|
* 该方法负责:
|
||||||
|
* 1. 根据护士选中的待发药明细生成对应的 DispensingDetail(状态 PENDING)。
|
||||||
|
* 2. 同时生成一条对应的 DispensingSummary(状态 PENDING),汇总所有明细的药品信息。
|
||||||
|
* 3. 两张表的写入在同一事务内完成,确保明细表行数与汇总表行数始终保持一致。
|
||||||
|
*
|
||||||
|
* @param orderMainId 医嘱主表ID
|
||||||
*/
|
*/
|
||||||
private String mapOrderStatus(Integer status) {
|
|
||||||
return OrderStatusMapper.getDisplayName(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String mapDispenseStatus(Integer status) {
|
|
||||||
return DispenseStatusMapper.getDisplayName(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// 业务方法(仅展示涉及状态名称的片段,已统一改为使用映射器)
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
@Override
|
@Override
|
||||||
public Page<OrderDetailDto> listOrders(int pageNum, int pageSize, String patientId) {
|
@Transactional(rollbackFor = Exception.class)
|
||||||
PageHelper.startPage(pageNum, pageSize);
|
public void applyDispensingApply(Long orderMainId) {
|
||||||
List<OrderDetail> list = orderDetailMapper.selectByPatientId(patientId);
|
// 1. 获取医嘱主记录及其明细
|
||||||
Page<OrderDetailDto> page = new Page<>();
|
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId);
|
||||||
page.setTotal(((Page<?>) list).getTotal());
|
if (orderMain == null) {
|
||||||
page.setResult(list.stream().map(this::toDto).collect(Collectors.toList()));
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
private OrderDetailDto toDto(OrderDetail entity) {
|
|
||||||
OrderDetailDto dto = new OrderDetailDto();
|
|
||||||
dto.setId(entity.getId());
|
|
||||||
dto.setOrderNo(entity.getOrderNo());
|
|
||||||
// 统一映射状态名称
|
|
||||||
dto.setOrderStatusName(mapOrderStatus(entity.getOrderStatus()));
|
|
||||||
dto.setDispenseStatusName(mapDispenseStatus(entity.getDispenseStatus()));
|
|
||||||
dto.setDrugName(entity.getDrugName());
|
|
||||||
dto.setDosage(entity.getDosage());
|
|
||||||
dto.setFrequency(entity.getFrequency());
|
|
||||||
// 其它字段保持不变
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 医嘱执行后更新状态,统一使用映射器返回前端展示名称
|
|
||||||
*/
|
|
||||||
@Transactional
|
|
||||||
@Override
|
|
||||||
public void executeOrder(Long orderDetailId, String executor) {
|
|
||||||
OrderDetail detail = orderDetailMapper.selectByPrimaryKey(orderDetailId);
|
|
||||||
if (detail == null) {
|
|
||||||
throw new BusinessException("医嘱不存在");
|
throw new BusinessException("医嘱不存在");
|
||||||
}
|
}
|
||||||
// 更新业务状态
|
List<OrderDetail> details = orderDetailMapper.selectByOrderMainId(orderMainId);
|
||||||
detail.setOrderStatus(OrderStatus.EXECUTED.getCode());
|
if (CollectionUtils.isEmpty(details)) {
|
||||||
detail.setDispenseStatus(DispenseStatus.PENDING.getCode());
|
throw new BusinessException("医嘱明细为空,无法发药");
|
||||||
detail.setExecuteUser(executor);
|
}
|
||||||
detail.setExecuteTime(new Date());
|
|
||||||
orderDetailMapper.updateByPrimaryKeySelective(detail);
|
|
||||||
|
|
||||||
// 记录日志(日志中仍使用中文,统一通过映射器获取)
|
// 2. 过滤出待发药(状态为 PENDING)的明细
|
||||||
logger.info("医嘱 {} 执行,状态由 {} 变为 {}",
|
List<OrderDetail> pendingDetails = details.stream()
|
||||||
detail.getOrderNo(),
|
.filter(d -> d.getDispenseStatus() == DispenseStatus.PENDING.getCode())
|
||||||
mapOrderStatus(OrderStatus.PENDING.getCode()),
|
.collect(Collectors.toList());
|
||||||
mapOrderStatus(OrderStatus.EXECUTED.getCode()));
|
|
||||||
|
if (CollectionUtils.isEmpty(pendingDetails)) {
|
||||||
|
throw new BusinessException("暂无待发药的医嘱明细");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 批量写入 DispensingDetail
|
||||||
|
List<DispensingDetail> dispensingDetails = pendingDetails.stream().map(d -> {
|
||||||
|
DispensingDetail dd = new DispensingDetail();
|
||||||
|
dd.setOrderDetailId(d.getId());
|
||||||
|
dd.setOrderMainId(orderMainId);
|
||||||
|
dd.setDrugId(d.getDrugId());
|
||||||
|
dd.setQuantity(d.getQuantity());
|
||||||
|
dd.setDispenseStatus(DispenseStatus.PENDING.getCode());
|
||||||
|
dd.setCreateTime(new Date());
|
||||||
|
dd.setUpdateTime(new Date());
|
||||||
|
return dd;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
|
dispensingDetailMapper.batchInsert(dispensingDetails);
|
||||||
|
|
||||||
|
// 4. 生成对应的汇总单
|
||||||
|
// 汇总单只需要记录药品种类、总数量以及状态
|
||||||
|
DispensingSummary summary = new DispensingSummary();
|
||||||
|
summary.setOrderMainId(orderMainId);
|
||||||
|
summary.setTotalCount(dispensingDetails.size());
|
||||||
|
int totalQty = dispensingDetails.stream().mapToInt(DispensingDetail::getQuantity).sum();
|
||||||
|
summary.setTotalQuantity(totalQty);
|
||||||
|
summary.setDispenseStatus(DispenseStatus.PENDING.getCode());
|
||||||
|
summary.setCreateTime(new Date());
|
||||||
|
summary.setUpdateTime(new Date());
|
||||||
|
|
||||||
|
dispensingSummaryMapper.insert(summary);
|
||||||
|
|
||||||
|
// 5. 更新医嘱明细的发药状态为“已申请”
|
||||||
|
pendingDetails.forEach(d -> d.setDispenseStatus(DispenseStatus.APPLYING.getCode()));
|
||||||
|
orderDetailMapper.batchUpdateDispenseStatus(pendingDetails);
|
||||||
|
|
||||||
|
logger.info("护士提交汇总发药申请,orderMainId={}, 明细条数={}, 汇总单ID={}",
|
||||||
|
orderMainId, dispensingDetails.size(), summary.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 其余业务方法保持原有实现,仅在返回状态文字的地方改为 map* 方法
|
// 其它业务方法保持不变...
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user