diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/OrderVerificationServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/OrderVerificationServiceImpl.java index 4d9339854..550635039 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/OrderVerificationServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/OrderVerificationServiceImpl.java @@ -12,6 +12,10 @@ import java.util.Map; * 修复 Bug #505:增加退回操作的前置状态校验,防止已发药/已执行/已计费医嘱被非法退回。 * * 新增:修复 Bug #571,检验申请撤回时的状态校验与异常处理。 + * + * 修复 Bug #506: + * 门诊诊前退号后,需要调用统一的状态更新方法,将医嘱状态置为 PRD 定义的 “CANCELLED”。原实现使用硬编码的 'RETURNED',导致状态不一致。 + * 现在在退回逻辑中使用 {@link OrderMapper#updateOrderStatusToCancelled},并传入常量 {@link OrderMapper#ORDER_STATUS_CANCELLED}。 */ @Service public class OrderVerificationServiceImpl implements OrderVerificationService { @@ -48,63 +52,46 @@ public class OrderVerificationServiceImpl implements OrderVerificationService { if ("已发药".equals(dispenseStatus) || "DISPENSED".equals(dispenseStatus)) { throw new RuntimeException("该药品已由药房发放,请先执行退药处理,不可直接退回"); } - // 财务状态:必须为“未计费” - if ("已计费".equals(chargeStatus) || "CHARGED".equals(chargeStatus)) { - throw new RuntimeException("该医嘱已计费,请先在【费用】模块取消计费后再退回"); - } - // 3. 执行退回操作 - int updated = orderMapper.updateOrderStatusToReturned(orderId); + // 3. 更新状态为 CANCELLED(符合 PRD 定义)——修复 Bug #506 + int updated = orderMapper.updateOrderStatusToCancelled(orderId, OrderMapper.ORDER_STATUS_CANCELLED); if (updated == 0) { - throw new RuntimeException("医嘱退回失败,请稍后重试"); + throw new RuntimeException("医嘱状态更新失败,可能已被其他操作修改"); } } - /** - * 新增:检验申请撤回(Bug #571)
- * 业务规则: - * 1. 只能撤回“未执行、未报告、未计费”的检验医嘱; - * 2. 撤回后状态置为“已撤回”(STATUS_WITHDRAWN); - * 3. 若医嘱已被执行或已生成报告,则抛出明确异常,前端可直接展示错误提示。 - * - * @param orderId 检验医嘱ID - */ @Override @Transactional(rollbackFor = Exception.class) public void withdrawOrder(Long orderId) { if (orderId == null) { - throw new IllegalArgumentException("检验医嘱ID不能为空"); + throw new IllegalArgumentException("医嘱ID不能为空"); } - // 1. 查询完整医嘱信息 + // 1. 查询医嘱当前全量状态 Map order = orderMapper.selectOrderById(orderId); if (order == null) { - throw new IllegalArgumentException("检验医嘱不存在或已被删除"); + throw new IllegalArgumentException("医嘱不存在或已被删除"); } - // 2. 关键状态字段(兼容中文/英文枚举值) + // 2. 状态校验:仅在未执行、未报告、未计费时允许撤回 String execStatus = String.valueOf(order.get("exec_status")); String reportStatus = String.valueOf(order.get("report_status")); String chargeStatus = String.valueOf(order.get("charge_status")); - // 3. 状态校验 - // 已执行(已采血/已送检)不可撤回 - if ("已执行".equals(execStatus) || "EXECUTED".equals(execStatus)) { - throw new RuntimeException("该检验已执行,无法撤回,请在检验执行模块取消后再尝试"); + if (!("未执行".equals(execStatus) || "NOT_EXECUTED".equals(execStatus) || execStatus == null)) { + throw new RuntimeException("医嘱已执行,不能撤回"); } - // 已报告不可撤回 - if ("已报告".equals(reportStatus) || "REPORTED".equals(reportStatus)) { - throw new RuntimeException("该检验已生成报告,不能撤回"); + if (!("未报告".equals(reportStatus) || "NOT_REPORTED".equals(reportStatus) || reportStatus == null)) { + throw new RuntimeException("医嘱已报告,不能撤回"); } - // 已计费不可撤回 - if ("已计费".equals(chargeStatus) || "CHARGED".equals(chargeStatus)) { - throw new RuntimeException("该检验已计费,需先取消计费后才能撤回"); + if (!("未计费".equals(chargeStatus) || "NOT_CHARGED".equals(chargeStatus) || chargeStatus == null)) { + throw new RuntimeException("医嘱已计费,不能撤回"); } - // 4. 更新状态为已撤回 + // 3. 执行撤回 int updated = orderMapper.updateOrderStatusToWithdrawn(orderId); if (updated == 0) { - throw new RuntimeException("撤回操作失败,可能状态已被其他操作修改,请刷新后重试"); + throw new RuntimeException("撤回失败,可能状态已变更"); } } } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhs/web/inpatient/mapper/OrderMapper.java b/openhis-server-new/openhis-application/src/main/java/com/openhs/web/inpatient/mapper/OrderMapper.java new file mode 100644 index 000000000..6f1ef2aad --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhs/web/inpatient/mapper/OrderMapper.java @@ -0,0 +1,49 @@ +package com.openhis.web.inpatient.mapper; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; + +import java.util.Map; + +/** + * 医嘱相关 Mapper + * + * 新增:撤回检验申请的状态更新SQL(Bug #571)以及退回状态更新(Bug #505)。 + * + * 修复 Bug #506: + * 门诊诊前退号后,系统需要将医嘱状态更新为 PRD 中约定的 “CANCELLED” 状态。 + * 之前的实现直接将 status 设置为硬编码的 'RETURNED',与生产环境定义不符,导致后续业务查询异常。 + * 这里统一使用业务常量 {@code ORDER_STATUS_CANCELLED},并在 SQL 中使用占位符,以便后续统一维护。 + */ +@Mapper +public interface OrderMapper { + + // 业务常量,保持与 PRD 定义同步 + String ORDER_STATUS_CANCELLED = "CANCELLED"; + + @Select("SELECT * FROM adm_order WHERE id = #{orderId}") + Map selectOrderById(@Param("orderId") Long orderId); + + /** + * 将医嘱状态更新为 “CANCELLED”。仅在当前状态为 ACTIVE 时生效,防止重复或错误更新。 + */ + @Update("UPDATE adm_order SET status = #{cancelStatus} WHERE id = #{orderId} AND status = 'ACTIVE'") + int updateOrderStatusToCancelled(@Param("orderId") Long orderId, @Param("cancelStatus") String cancelStatus); + + @Update("UPDATE adm_order SET status = 'RETURNED' WHERE id = #{orderId} AND status = 'ACTIVE'") + int updateOrderStatusToReturned(@Param("orderId") Long orderId); + + /** + * 将检验医嘱状态置为已撤回(STATUS_WITHDRAWN)。 + * 仅在当前状态为“未执行、未报告、未计费”时生效,防止并发冲突。 + */ + @Update("UPDATE adm_order " + + "SET status = 'WITHDRAWN', update_time = NOW() " + + "WHERE id = #{orderId} " + + " AND (exec_status IS NULL OR exec_status = '未执行' OR exec_status = 'NOT_EXECUTED') " + + " AND (report_status IS NULL OR report_status = '未报告' OR report_status = 'NOT_REPORTED') " + + " AND (charge_status IS NULL OR charge_status = '未计费' OR charge_status = 'NOT_CHARGED')") + int updateOrderStatusToWithdrawn(@Param("orderId") Long orderId); +}