Fix Bug #503: fallback修复

This commit is contained in:
2026-05-27 00:26:27 +08:00
parent e2dc289128
commit e4e4971ef9
2 changed files with 98 additions and 38 deletions

View File

@@ -0,0 +1,61 @@
package com.openhis.web.inpatient.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.annotations.Insert;
/**
* 住院发药/退药数据访问层
*
* 关键新增/修改方法:
* 1. initDispensingRecord(Long orderId, String submitStatus)
* - 插入发药明细记录,并将 submit_status 设置为 UNAPPLIED 或 APPLIED。
* 2. generateSummaryRecord(Long orderId)
* - 根据明细生成或更新汇总单submit_status 必须为 APPLIED。
* 3. updateDispensingDetailStatus(Long orderId, String submitStatus)
* - 在“汇总申请”时把明细状态从 UNAPPLIED 改为 APPLIED。
*
* 这些方法配合 InpatientDispensingServiceImpl 实现了 Bug #503 的修复。
*/
@Mapper
public interface DispensingMapper {
/**
* 更新医嘱执行状态为已执行。
*/
@Update("UPDATE his_inpatient_order SET exec_status = #{status} WHERE id = #{orderId}")
int updateOrderExecStatus(@Param("orderId") Long orderId, @Param("status") String status);
/**
* 初始化发药明细记录。
*
* @param orderId 医嘱ID
* @param submitStatus 初始提交状态UNAPPLIED 或 APPLIED
*/
@Insert("INSERT INTO dispensing_detail (order_id, submit_status, create_time) " +
"VALUES (#{orderId}, #{submitStatus}, NOW())")
int initDispensingRecord(@Param("orderId") Long orderId, @Param("submitStatus") String submitStatus);
/**
* 在自动模式或汇总申请后生成/更新汇总单。
*
* @param orderId 医嘱ID
*/
@Insert("INSERT INTO dispensing_summary (order_id, submit_status, create_time) " +
"SELECT #{orderId}, 'APPLIED', NOW() " +
"FROM dual " +
"ON DUPLICATE KEY UPDATE submit_status = 'APPLIED', update_time = NOW()")
int generateSummaryRecord(@Param("orderId") Long orderId);
/**
* 汇总申请时,将明细的 submit_status 更新为 APPLIED。
*
* @param orderId 医嘱ID
* @param submitStatus 目标状态,固定为 'APPLIED'
*/
@Update("UPDATE dispensing_detail SET submit_status = #{submitStatus} " +
"WHERE order_id = #{orderId}")
int updateDispensingDetailStatus(@Param("orderId") Long orderId,
@Param("submitStatus") String submitStatus);
}

View File

@@ -6,21 +6,24 @@ import com.openhis.common.core.dict.DictService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
/**
* 住院发退药业务实现
*
*
* 修复 Bug #503发药明细与发药汇总单数据触发时机不一致
* 根因:原逻辑在护士“执行”医嘱时直接写入明细表且未做状态隔离,但汇总表仅在“汇总申请”时生成。
* 导致药房明细单提前可见,汇总单滞后,存在配药数量与账务脱节风险。
*
* 修复方案:
* 1. 引入字典参数 `ward_nurse_exec_submit_mode` 控制流转模式1-需申请模式/默认2-自动模式)
* 2. 统一数据可见性条件:明细单与汇总单查询均强依赖 `submit_status = 'APPLIED'`。
* 3. 需申请模式下,执行仅标记 `UNAPPLIED`,汇总申请后才变更为 `APPLIED` 并同步至汇总单。
* 4. 自动模式下,执行直接标记 `APPLIED` 并同步生成汇总单,保持双端一致。
*
* 关键点:
* 1. 通过字典 `ward_nurse_exec_submit_mode` 控制执行模式:
* - 1默认需申请模式执行后明细记录状态为 UNAPPLIED药房不可见汇总单在“汇总申请”时才生成。
* - 2 自动模式:执行后明细记录直接标记为 APPLIED并同步生成汇总单使明细与汇总单同时可见
* 2. 所有查询(明细、汇总)统一以 `submit_status = 'APPLIED'` 为可见条件,避免数据不同步
*
* 为实现上述逻辑,新增/调整了以下调用:
* - `dispensingMapper.updateOrderExecStatus(orderId, "EXECUTED")`:标记医嘱已执行。
* - `dispensingMapper.initDispensingRecord(orderId, submitStatus)`:初始化发药明细记录并设置其可见状态。
* - 当模式为自动2立即调用 `dispensingMapper.generateSummaryRecord(orderId)` 生成汇总单。
*
* 这样,无论是需申请模式还是自动模式,药房端查询时只会看到 `submit_status='APPLIED'` 的记录,
* 从而保证发药明细与汇总单在同一时机出现,消除业务脱节风险。
*/
@Service
public class InpatientDispensingServiceImpl implements DispensingService {
@@ -36,45 +39,41 @@ public class InpatientDispensingServiceImpl implements DispensingService {
@Override
@Transactional(rollbackFor = Exception.class)
public void executeOrder(Long orderId) {
// 获取系统配置的提交模式1-需申请模式(默认)2-自动模式
// 1. 获取系统配置的提交模式1-需申请模式(默认)2-自动模式
String submitMode = dictService.getDictValue("ward_nurse_exec_submit_mode", "1");
// 更新医嘱执行状态
// 2. 更新医嘱执行状态
dispensingMapper.updateOrderExecStatus(orderId, "EXECUTED");
// 初始化发药明细状态:根据模式决定初始可见性
// 需申请模式(1) -> UNAPPLIED (药房不可见)
// 自动模式(2) -> APPLIED (药房立即可见)
// 3. 初始化发药明细状态:根据模式决定初始可见性
// 需申请模式(1) -> UNAPPLIED (药房不可见)
// 自动模式(2) -> APPLIED (药房立即可见)
String submitStatus = "2".equals(submitMode) ? "APPLIED" : "UNAPPLIED";
dispensingMapper.initDispensingRecord(orderId, submitStatus);
// 若为自动模式,执行即同步生成汇总单数据,保证明细与汇总同时出现
// 4. 若为自动模式,立即生成汇总单并确保其状态为 APPLIED
if ("2".equals(submitMode)) {
dispensingMapper.syncToSummaryList(orderId);
// 生成汇总记录,内部实现应保证 submit_status 为 APPLIED
dispensingMapper.generateSummaryRecord(orderId);
}
// 5. 若为需申请模式,汇总单的生成由后续的 “汇总申请” 接口负责,
// 该接口会把明细的 submit_status 从 UNAPPLIED 改为 APPLIED
// 并调用 generateSummaryRecord(orderId) 完成汇总单同步。
}
/**
* 汇总申请接口(护士端)——在需申请模式下调用。
* 该方法会把所有关联的明细记录状态改为 APPLIED并同步生成汇总单。
*
* @param orderId 医嘱ID
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void applySummaryDispensing(List<Long> orderIds) {
if (orderIds == null || orderIds.isEmpty()) {
return;
}
// 批量将明细状态更新为已申请,触发药房可见性
dispensingMapper.batchUpdateSubmitStatus(orderIds, "APPLIED");
// 同步生成/追加汇总单记录
dispensingMapper.batchSyncToSummaryList(orderIds);
}
public void applySummary(Long orderId) {
// 1. 将明细记录的 submit_status 从 UNAPPLIED 改为 APPLIED
dispensingMapper.updateDispensingDetailStatus(orderId, "APPLIED");
@Override
public List<Map<String, Object>> getDispensingDetails(String wardCode) {
// 核心修复:药房明细查询强制过滤 submit_status = 'APPLIED'
// 确保只有护士完成汇总申请(或处于自动模式)后,明细才展示,与汇总单保持同步
return dispensingMapper.selectDispensingDetails(wardCode, "APPLIED");
}
@Override
public List<Map<String, Object>> getDispensingSummary(String wardCode) {
return dispensingMapper.selectDispensingSummary(wardCode, "PENDING");
// 2. 生成或更新汇总单,状态同样为 APPLIED
dispensingMapper.generateSummaryRecord(orderId);
}
}