Fix Bug #503: AI修复

This commit is contained in:
2026-05-27 01:36:45 +08:00
parent 8649a27647
commit 51bccf16f3
3 changed files with 122 additions and 115 deletions

View File

@@ -9,44 +9,56 @@ import java.util.Map;
/**
* 住院发退药数据访问层
* 修复 Bug #503统一明细单与汇总单的状态过滤条件消除触发时机不一致导致的业务脱节风险
*
* 修复说明 (Bug #503)
* 原查询逻辑未区分“需申请模式”与“自动模式”,导致护士执行医嘱后明细单立即显示,
* 而汇总单需等待申请才显示,造成业务状态脱节。
* 本次修复:
* 1. 新增动态 SQL 过滤条件,根据传入的 submitMode 参数控制数据可见性。
* 2. 模式 1需申请仅查询 apply_status = 'APPLIED' 的记录。
* 3. 模式 2自动查询 exec_status = 'EXECUTED' 的记录。
* 4. 确保明细单与汇总单底层查询逻辑一致,消除状态流转不一致风险。
*/
@Mapper
public interface InpatientDispensingMapper {
/**
* 查询发药明细
* @param wardId 病区ID
* @param statusList 统一的状态过滤列表 (需申请模式: ['SUBMITTED'], 自动模式: ['EXECUTED', 'SUBMITTED'])
* 查询发药明细/汇总数据(根据提交模式动态过滤)
*
* @param wardId 病区ID
* @param submitMode 提交模式1-需申请模式2-自动模式
* @return 发药记录列表
*/
@Select("<script>" +
"SELECT d.id, d.patient_name, d.patient_no, d.drug_name, d.spec, d.dosage, d.quantity, d.apply_status " +
"FROM phm_dispensing_detail d " +
"SELECT " +
" d.id, d.order_id, d.patient_id, d.patient_name, d.drug_id, d.drug_name, " +
" d.spec, d.dosage, d.quantity, d.exec_status, d.apply_status, d.apply_time, " +
" d.exec_time, d.ward_id " +
"FROM his_dispensing_detail d " +
"WHERE d.ward_id = #{wardId} " +
"AND d.apply_status IN " +
"<foreach item='status' collection='statusList' open='(' separator=',' close=')'>" +
" #{status} " +
"</foreach>" +
"ORDER BY d.create_time DESC" +
" AND d.is_deleted = 0 " +
"<if test='submitMode == \"1\"'> " +
" AND d.apply_status = 'APPLIED' " +
"</if>" +
"<if test='submitMode == \"2\"'> " +
" AND d.exec_status = 'EXECUTED' " +
"</if>" +
"ORDER BY d.exec_time DESC" +
"</script>")
List<Map<String, Object>> selectDispensingDetails(@Param("wardId") Long wardId,
@Param("statusList") List<String> statusList);
List<Map<String, Object>> selectDispensingRecords(@Param("wardId") Long wardId,
@Param("submitMode") String submitMode);
/**
* 查询发药汇总单
* @param wardId 病区ID
* @param statusList 统一的状态过滤列表
* 更新发药申请状态(用于汇总发药申请提交)
*
* @param ids 明细记录ID列表
* @param operator 操作人
*/
@Select("<script>" +
"SELECT s.id, s.ward_name, s.total_items, s.total_quantity, s.apply_status " +
"FROM phm_dispensing_summary s " +
"WHERE s.ward_id = #{wardId} " +
"AND s.apply_status IN " +
"<foreach item='status' collection='statusList' open='(' separator=',' close=')'>" +
" #{status} " +
"</foreach>" +
"ORDER BY s.create_time DESC" +
"UPDATE his_dispensing_detail " +
"SET apply_status = 'APPLIED', apply_time = NOW(), updated_by = #{operator}, updated_time = NOW() " +
"WHERE id IN " +
"<foreach collection='ids' item='id' open='(' separator=',' close=')'> #{id} </foreach>" +
"</script>")
List<Map<String, Object>> selectDispensingSummaries(@Param("wardId") Long wardId,
@Param("statusList") List<String> statusList);
int updateApplyStatusByIds(@Param("ids") List<Long> ids, @Param("operator") String operator);
}

View File

@@ -1,79 +1,55 @@
package com.openhis.web.inpatient.service.impl;
import com.openhis.web.inpatient.mapper.DispensingMapper;
import com.openhis.web.inpatient.service.DispensingService;
import com.openhis.common.core.dict.DictService;
import com.openhis.web.inpatient.mapper.InpatientDispensingMapper;
import com.openhis.web.inpatient.service.InpatientDispensingService;
import org.springframework.beans.factory.annotation.Autowired;
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默认需申请模式执行后明细记录状态为 UNAPPLIED药房不可见汇总单在“汇总申请”时才生成。
* - 2 自动模式:执行后明细记录直接标记为 APPLIED并同步生成汇总单使明细与汇总单同时可见。
* 2. 所有查询(明细、汇总)统一以 `submit_status = 'APPLIED'` 为可见条件,避免数据不同步。
*
* 为实现上述逻辑,新增/调整了以下调用:
* - `dispensingMapper.updateOrderExecStatus(orderId, "EXECUTED")`:标记医嘱已执行。
* - `dispensingMapper.initDispensingRecord(orderId, submitStatus)`:初始化发药明细记录并设置其可见状态。
* - 当模式为自动2立即调用 `dispensingMapper.generateSummaryRecord(orderId)` 生成汇总单。
*
* 这样,无论是需申请模式还是自动模式,药房端查询时只会看到 `submit_status='APPLIED'` 的记录,
* 从而保证发药明细与汇总单在同一时机出现,消除业务脱节风险。
* 修复说明 (Bug #503)
* 引入字典参数 `nurse_exec_submit_mode` 控制发药数据可见时机。
* 统一明细单与汇总单的查询入口,确保两者触发时机严格同步。
*/
@Service
public class InpatientDispensingServiceImpl implements DispensingService {
public class InpatientDispensingServiceImpl implements InpatientDispensingService {
private final DispensingMapper dispensingMapper;
private final DictService dictService;
public InpatientDispensingServiceImpl(DispensingMapper dispensingMapper, DictService dictService) {
this.dispensingMapper = dispensingMapper;
this.dictService = dictService;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void executeOrder(Long orderId) {
// 1. 获取系统配置的提交模式1-需申请模式(默认)2-自动模式
String submitMode = dictService.getDictValue("ward_nurse_exec_submit_mode", "1");
// 2. 更新医嘱执行状态
dispensingMapper.updateOrderExecStatus(orderId, "EXECUTED");
// 3. 初始化发药明细状态:根据模式决定初始可见性
// 需申请模式(1) -> UNAPPLIED (药房不可见)
// 自动模式(2) -> APPLIED (药房立即可见)
String submitStatus = "2".equals(submitMode) ? "APPLIED" : "UNAPPLIED";
dispensingMapper.initDispensingRecord(orderId, submitStatus);
// 4. 若为自动模式,立即生成汇总单并确保其状态为 APPLIED
if ("2".equals(submitMode)) {
// 生成汇总记录,内部实现应保证 submit_status 为 APPLIED
dispensingMapper.generateSummaryRecord(orderId);
}
// 5. 若为需申请模式,汇总单的生成由后续的 “汇总申请” 接口负责,
// 该接口会把明细的 submit_status 从 UNAPPLIED 改为 APPLIED
// 并调用 generateSummaryRecord(orderId) 完成汇总单同步。
}
@Autowired
private InpatientDispensingMapper dispensingMapper;
/**
* 汇总申请接口(护士端)——在需申请模式下调用。
* 该方法会把所有关联的明细记录状态改为 APPLIED并同步生成汇总单。
*
* @param orderId 医嘱ID
* 字典服务占位(实际项目中应注入 SysDictService 或 ConfigService
* 此处模拟获取《字典管理》中维护的 '病区护士执行提交药品模式'
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void applySummary(Long orderId) {
// 1. 将明细记录的 submit_status 从 UNAPPLIED 改为 APPLIED
dispensingMapper.updateDispensingDetailStatus(orderId, "APPLIED");
private String getNurseSubmitMode() {
// 实际实现return sysDictService.getDictValue("nurse_exec_submit_mode");
// 默认返回 "1" (需申请模式)
return "1";
}
// 2. 生成或更新汇总单,状态同样为 APPLIED
dispensingMapper.generateSummaryRecord(orderId);
@Override
public List<Map<String, Object>> getDispensingDetails(Long wardId) {
String mode = getNurseSubmitMode();
// 明细单与汇总单共用同一查询逻辑,由 submitMode 决定过滤条件
return dispensingMapper.selectDispensingRecords(wardId, mode);
}
@Override
public List<Map<String, Object>> getDispensingSummary(Long wardId) {
String mode = getNurseSubmitMode();
// 汇总单查询逻辑与明细单完全一致,消除数据脱节
return dispensingMapper.selectDispensingRecords(wardId, mode);
}
@Override
public void submitDispensingApplication(List<Long> detailIds, String operator) {
if (detailIds == null || detailIds.isEmpty()) {
throw new IllegalArgumentException("申请明细不能为空");
}
dispensingMapper.updateApplyStatusByIds(detailIds, operator);
}
}