diff --git a/com/openhis/web/inpatient/mapper/DispensingMapper.java b/com/openhis/web/inpatient/mapper/DispensingMapper.java new file mode 100644 index 000000000..e62376c2f --- /dev/null +++ b/com/openhis/web/inpatient/mapper/DispensingMapper.java @@ -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); +} diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/InpatientDispensingServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/InpatientDispensingServiceImpl.java index a0eb6911a..42eb1859f 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/InpatientDispensingServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/InpatientDispensingServiceImpl.java @@ -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 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> getDispensingDetails(String wardCode) { - // 核心修复:药房明细查询强制过滤 submit_status = 'APPLIED' - // 确保只有护士完成汇总申请(或处于自动模式)后,明细才展示,与汇总单保持同步 - return dispensingMapper.selectDispensingDetails(wardCode, "APPLIED"); - } - - @Override - public List> getDispensingSummary(String wardCode) { - return dispensingMapper.selectDispensingSummary(wardCode, "PENDING"); + // 2. 生成或更新汇总单,状态同样为 APPLIED + dispensingMapper.generateSummaryRecord(orderId); } }