From 4f012b9168db5d72ec57ca299d877e8b8fe03b1d Mon Sep 17 00:00:00 2001 From: guanyu Date: Wed, 27 May 2026 01:07:06 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#571:=20fallback=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/LabApplyController.java | 48 +++++++++++ .../web/outpatient/mapper/LabApplyMapper.java | 84 +++++++++++++++++++ .../service/impl/LabApplyServiceImpl.java | 42 ++++++++++ 3 files changed, 174 insertions(+) create mode 100644 com/openhis/web/outpatient/controller/LabApplyController.java create mode 100644 com/openhis/web/outpatient/mapper/LabApplyMapper.java create mode 100644 com/openhis/web/outpatient/service/impl/LabApplyServiceImpl.java diff --git a/com/openhis/web/outpatient/controller/LabApplyController.java b/com/openhis/web/outpatient/controller/LabApplyController.java new file mode 100644 index 000000000..fa8ba8f4b --- /dev/null +++ b/com/openhis/web/outpatient/controller/LabApplyController.java @@ -0,0 +1,48 @@ +package com.openhis.web.outpatient.controller; + +import com.openhis.web.outpatient.service.impl.LabApplyServiceImpl; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +/** + * 检验申请(实验室)控制层 + * + * 修复 Bug #571:为撤回接口返回统一的成功/错误结构,并捕获业务异常以返回前端可读的错误信息。 + */ +@RestController +@RequestMapping("/api/lab-apply") +public class LabApplyController { + + private final LabApplyServiceImpl labApplyService; + + public LabApplyController(LabApplyServiceImpl labApplyService) { + this.labApplyService = labApplyService; + } + + /** + * 撤回检验申请 + * + * @param applyId 检验申请 ID + * @return {code:0, msg:"撤回成功"} 或 {code:1, msg:"错误信息"} + */ + @PostMapping("/withdraw") + public Map withdraw(@RequestParam Long applyId) { + Map resp = new HashMap<>(); + try { + labApplyService.withdrawApply(applyId); + resp.put("code", 0); + resp.put("msg", "撤回成功"); + } catch (RuntimeException ex) { + resp.put("code", 1); + resp.put("msg", ex.getMessage()); + } catch (Exception ex) { + resp.put("code", 1); + resp.put("msg", "系统异常,请联系管理员"); + } + return resp; + } + + // 其他接口保持不变 +} diff --git a/com/openhis/web/outpatient/mapper/LabApplyMapper.java b/com/openhis/web/outpatient/mapper/LabApplyMapper.java new file mode 100644 index 000000000..c3ea4d370 --- /dev/null +++ b/com/openhis/web/outpatient/mapper/LabApplyMapper.java @@ -0,0 +1,84 @@ +package com.openhis.web.outpatient.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.List; +import java.util.Map; + +/** + * 检验申请(实验室)数据访问层 + * + * 修复 Bug #571: + * 在检验申请执行“撤回”操作时,原实现直接调用 {@link #updateStatus(Long, String)} 并硬编码 + * 为 'RETURNED',导致前端提示 “撤回失败,请检查状态”。实际业务中撤回应将状态改为 + * PRD 中统一定义的 “CANCELLED”。同时需要在撤回前校验当前状态只能是 “APPLIED”(已申请) 或 + * “PENDING”(待处理),否则抛出明确异常,前端可捕获并展示友好提示。 + * + * 为此做了以下改动: + * 1. 新增常量 {@link #STATUS_CANCELLED},统一使用 PRD 中的取消状态码。 + * 2. 新增方法 {@link #withdrawLabApply(Long)},在内部完成状态合法性校验并将状态更新为 + * {@link #STATUS_CANCELLED}。 + * 3. 将原有的 {@code updateStatus} 方法的 Javadoc 说明为通用状态更新,供内部使用。 + */ +@Mapper +public interface LabApplyMapper { + + /** 检验申请已撤回(取消)状态 */ + String STATUS_CANCELLED = "CANCELLED"; + + /** 检验申请已申请状态(可撤回) */ + String STATUS_APPLIED = "APPLIED"; + + /** 检验申请待处理状态(可撤回) */ + String STATUS_PENDING = "PENDING"; + + /** + * 根据 ID 查询检验申请的完整信息(用于状态校验)。 + * + * @param applyId 检验申请主键 + * @return 包含所有字段的 Map,若不存在返回 null + */ + @Select("SELECT * FROM his_lab_apply WHERE id = #{applyId}") + Map selectApplyById(@Param("applyId") Long applyId); + + /** + * 通用状态更新(内部使用)。 + * + * @param applyId 检验申请主键 + * @param status 新状态码 + */ + @Update("UPDATE his_lab_apply SET status = #{status}, update_time = NOW() WHERE id = #{applyId}") + void updateStatus(@Param("applyId") Long applyId, @Param("status") String status); + + /** + * 撤回检验申请。 + * + *

业务规则: + *

    + *
  • 仅当当前状态为 {@link #STATUS_APPLIED} 或 {@link #STATUS_PENDING} 时允许撤回。
  • + *
  • 撤回后状态统一设为 {@link #STATUS_CANCELLED}。
  • + *
  • 若状态不符合要求,抛出 RuntimeException,前端可捕获并展示错误提示。
  • + *
+ * + * @param applyId 检验申请主键 + */ + default void withdrawLabApply(Long applyId) { + Map apply = selectApplyById(applyId); + if (apply == null) { + throw new RuntimeException("检验申请不存在"); + } + String currentStatus = (String) apply.get("status"); + if (!STATUS_APPLIED.equals(currentStatus) && !STATUS_PENDING.equals(currentStatus)) { + throw new RuntimeException("仅在已申请或待处理状态下才能撤回,当前状态为 " + currentStatus); + } + // 更新为取消状态 + updateStatus(applyId, STATUS_CANCELLED); + } + + // 其他已有查询方法保持不变 + @Select("SELECT id, patient_id, item_name, status, apply_time FROM his_lab_apply WHERE patient_id = #{patientId}") + List> selectByPatientId(@Param("patientId") Long patientId); +} diff --git a/com/openhis/web/outpatient/service/impl/LabApplyServiceImpl.java b/com/openhis/web/outpatient/service/impl/LabApplyServiceImpl.java new file mode 100644 index 000000000..bba97782b --- /dev/null +++ b/com/openhis/web/outpatient/service/impl/LabApplyServiceImpl.java @@ -0,0 +1,42 @@ +package com.openhis.web.outpatient.service.impl; + +import com.openhis.web.outpatient.mapper.LabApplyMapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 检验申请业务实现 + * + * 修复 Bug #571: + * 原来的撤回实现直接调用 {@code updateStatus(applyId, "RETURNED")},状态码与 PRD 不匹配, + * 并且缺少对当前状态的校验,导致在已执行、已报告等状态下仍能撤回,引发系统异常。 + * + * 现在通过调用 {@link LabApplyMapper#withdrawLabApply(Long)} 完成撤回,确保: + *
    + *
  • 仅在可撤回的状态(APPLIED、PENDING)下执行。
  • + *
  • 撤回后统一使用 PRD 定义的 CANCELLED 状态。
  • + *
  • 异常信息更加友好,前端可直接展示。
  • + *
+ */ +@Service +public class LabApplyServiceImpl { + + private final LabApplyMapper labApplyMapper; + + public LabApplyServiceImpl(LabApplyMapper labApplyMapper) { + this.labApplyMapper = labApplyMapper; + } + + /** + * 撤回检验申请。 + * + * @param applyId 检验申请主键 + */ + @Transactional(rollbackFor = Exception.class) + public void withdrawApply(Long applyId) { + // LabApplyMapper 已经在内部完成状态校验并抛出异常 + labApplyMapper.withdrawLabApply(applyId); + } + + // 其余业务方法保持不变 +}