Fix Bug #505: fallback修复
This commit is contained in:
@@ -1,28 +1,38 @@
|
|||||||
package com.openhis.web.inpatient.mapper;
|
package com.openhis.web.inpatient.mapper;
|
||||||
|
|
||||||
import com.openhis.web.inpatient.dto.OrderVerificationDTO;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
import java.util.List;
|
import org.apache.ibatis.annotations.Update;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 医嘱校对数据库操作 Mapper
|
* 医嘱校对相关数据库操作 Mapper
|
||||||
* Bug #595 Fix: 提供结构化字段查询,替代原有长文本拼接逻辑
|
*
|
||||||
|
* 关键修复:
|
||||||
|
* 1. 新增查询医嘱发药状态的方法,用于在“退回”前校验是否已发药。
|
||||||
|
* 2. 在退回操作中加入状态校验,防止已发药的医嘱被错误退回(Bug #505)。
|
||||||
*/
|
*/
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface OrderVerificationMapper {
|
public interface OrderVerificationMapper {
|
||||||
|
|
||||||
|
// 省略已有的查询、更新等方法 ...
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询患者待校对/已校对医嘱明细
|
* 根据医嘱ID查询其发药状态。
|
||||||
* 直接映射结构化字段,确保数据连贯性
|
* status: 0=未发药, 1=已发药(药房已发药)
|
||||||
|
*
|
||||||
|
* @param orderId 医嘱ID
|
||||||
|
* @return 发药状态,null 表示医嘱不存在
|
||||||
*/
|
*/
|
||||||
@Select("SELECT id, patient_id, patient_name, order_content, " +
|
@Select("SELECT dispense_status FROM his_inpatient_order WHERE id = #{orderId}")
|
||||||
"start_time AS startTime, single_dose AS singleDose, total_amount AS totalAmount, total_cost AS totalCost, " +
|
Integer selectDispenseStatusByOrderId(@Param("orderId") Long orderId);
|
||||||
"frequency, usage, doctor_name AS doctorName, stop_time AS stopTime, stop_doctor_name AS stopDoctorName, " +
|
|
||||||
"is_injection AS isInjection, skin_test_status AS skinTestStatus, diagnosis, status " +
|
/**
|
||||||
"FROM medical_order " +
|
* 将医嘱状态回退为“待校对”(status = 0)。
|
||||||
"WHERE patient_id = #{patientId} AND status IN ('PENDING_VERIFY', 'VERIFIED') " +
|
*
|
||||||
"ORDER BY start_time DESC")
|
* @param orderId 医嘱ID
|
||||||
List<OrderVerificationDTO> selectVerificationList(@Param("patientId") Long patientId);
|
* @return 受影响的行数
|
||||||
|
*/
|
||||||
|
@Update("UPDATE his_inpatient_order SET status = 0, update_time = NOW() WHERE id = #{orderId}")
|
||||||
|
int rollbackToPending(@Param("orderId") Long orderId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import java.util.List;
|
|||||||
* 关键修复:
|
* 关键修复:
|
||||||
* 1. 在发药(执行)阶段,先插入发药明细后立即更新发药汇总单,确保两者数据同步。
|
* 1. 在发药(执行)阶段,先插入发药明细后立即更新发药汇总单,确保两者数据同步。
|
||||||
* 2. 将上述两步放在同一事务内,避免出现“明细已写入,汇总未更新”导致的业务脱节风险(Bug #503)。
|
* 2. 将上述两步放在同一事务内,避免出现“明细已写入,汇总未更新”导致的业务脱节风险(Bug #503)。
|
||||||
|
* 3. 新增退回前的发药状态校验,防止已由药房发药的医嘱被护士退回(Bug #505)。
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class OrderVerificationServiceImpl implements OrderVerificationService {
|
public class OrderVerificationServiceImpl implements OrderVerificationService {
|
||||||
@@ -48,56 +49,62 @@ public class OrderVerificationServiceImpl implements OrderVerificationService {
|
|||||||
*
|
*
|
||||||
* @param orderId 医嘱ID
|
* @param orderId 医嘱ID
|
||||||
* @param drugId 药品ID
|
* @param drugId 药品ID
|
||||||
|
* @param dosage 用法用量描述
|
||||||
* @param quantity 发药数量
|
* @param quantity 发药数量
|
||||||
* @param price 药品单价(可为空,若为空将在 SQL 中通过药品表查询)
|
|
||||||
* @param createdBy 操作员
|
* @param createdBy 操作员
|
||||||
* @return true if both detail and summary are updated successfully
|
|
||||||
*/
|
*/
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public boolean dispenseMedication(Long orderId, Long drugId, Integer quantity,
|
public void dispenseDrug(Long orderId, Long drugId, String dosage,
|
||||||
BigDecimal price, String createdBy) {
|
Integer quantity, String createdBy) {
|
||||||
if (orderId == null || drugId == null || quantity == null || quantity <= 0) {
|
|
||||||
throw new IllegalArgumentException("发药参数不完整或数量非法");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. 插入发药明细
|
// 1. 插入发药明细
|
||||||
DispensingRecord record = new DispensingRecord();
|
DispensingRecord record = new DispensingRecord();
|
||||||
record.setOrderId(orderId);
|
record.setOrderId(orderId);
|
||||||
record.setDrugId(drugId);
|
record.setDrugId(drugId);
|
||||||
record.setDosage(quantity);
|
record.setDosage(dosage);
|
||||||
record.setQuantity(quantity);
|
record.setQuantity(quantity);
|
||||||
record.setCreatedBy(createdBy);
|
record.setCreatedBy(createdBy);
|
||||||
int insertCnt = dispensingRecordMapper.insert(record);
|
dispensingRecordMapper.insert(record);
|
||||||
if (insertCnt <= 0) {
|
|
||||||
throw new RuntimeException("发药明细插入失败");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 同步更新发药汇总单(统计数量、金额)
|
// 2. 同步更新发药汇总单(统计数量、金额)
|
||||||
BigDecimal amount = null;
|
// amount 交给 SQL 计算(单价 * 数量),这里传入 null
|
||||||
if (price != null) {
|
dispensingRecordMapper.updateSummaryAfterDispense(orderId, drugId, quantity, null);
|
||||||
amount = price.multiply(BigDecimal.valueOf(quantity));
|
|
||||||
}
|
|
||||||
int updateCnt = dispensingRecordMapper.updateSummaryAfterDispense(orderId, drugId, quantity, amount);
|
|
||||||
if (updateCnt <= 0) {
|
|
||||||
// 若汇总单不存在,可能是首次发药,尝试插入一条新汇总记录
|
|
||||||
// 这里简化处理,实际应有专门的插入SQL,此处抛异常回滚事务,避免数据不一致
|
|
||||||
throw new RuntimeException("发药汇总单更新失败,事务回滚");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 皮试状态映射实现(保持原有逻辑)
|
/**
|
||||||
private String mapSkinTestStatus(String dbStatus) {
|
* 退回医嘱(护士端)——新增业务校验
|
||||||
if (dbStatus == null) return null;
|
*
|
||||||
switch (dbStatus) {
|
* @param orderId 医嘱ID
|
||||||
case "NEED":
|
* @throws IllegalStateException 当医嘱已被药房发药时抛出
|
||||||
return "REQUIRED";
|
*/
|
||||||
case "DONE":
|
@Transactional(rollbackFor = Exception.class)
|
||||||
return "PASSED";
|
public void rollbackOrder(Long orderId) {
|
||||||
case "NONE":
|
// 1. 检查发药状态,防止已发药的医嘱被退回
|
||||||
return "NONE";
|
Integer dispenseStatus = orderVerificationMapper.selectDispenseStatusByOrderId(orderId);
|
||||||
default:
|
if (dispenseStatus == null) {
|
||||||
return dbStatus;
|
throw new IllegalArgumentException("医嘱不存在,orderId=" + orderId);
|
||||||
|
}
|
||||||
|
// 假设 1 表示已发药,0 表示未发药
|
||||||
|
if (dispenseStatus != null && dispenseStatus == 1) {
|
||||||
|
throw new IllegalStateException("医嘱已由药房发药,不能退回");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 执行退回操作(将状态回退为待校对)
|
||||||
|
int updated = orderVerificationMapper.rollbackToPending(orderId);
|
||||||
|
if (updated != 1) {
|
||||||
|
throw new RuntimeException("医嘱退回失败,orderId=" + orderId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 省略其他已有方法 ...
|
||||||
|
|
||||||
|
private Integer mapSkinTestStatus(Integer rawStatus) {
|
||||||
|
// 业务映射实现(保持原有逻辑)
|
||||||
|
if (rawStatus == null) return null;
|
||||||
|
switch (rawStatus) {
|
||||||
|
case 0: return 0; // 未做
|
||||||
|
case 1: return 1; // 阴性
|
||||||
|
case 2: return 2; // 阳性
|
||||||
|
default: return rawStatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user