From e4886ec4a12dcbd1868001e46429052b1a4a4d09 Mon Sep 17 00:00:00 2001 From: xunyu Date: Wed, 27 May 2026 03:30:24 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#506:=20fallback=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/RegistrationServiceImpl.java | 86 +++++++++---------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/openhis/application/service/impl/RegistrationServiceImpl.java b/src/main/java/com/openhis/application/service/impl/RegistrationServiceImpl.java index 165e46db1..8075347e3 100644 --- a/src/main/java/com/openhis/application/service/impl/RegistrationServiceImpl.java +++ b/src/main/java/com/openhis/application/service/impl/RegistrationServiceImpl.java @@ -2,9 +2,10 @@ package com.openhis.application.service.impl; import com.openhis.application.domain.entity.Registration; import com.openhis.application.domain.entity.RegistrationDetail; +import com.openhis.application.domain.entity.ScheduleSlot; import com.openhis.application.mapper.RegistrationMapper; import com.openhis.application.mapper.RegistrationDetailMapper; -import com.openhis.application.mapper.ScheduleSlotMapper; // ← 新增导入 +import com.openhos.application.mapper.ScheduleSlotMapper; import com.openhis.application.exception.BusinessException; import com.openhis.application.service.RegistrationService; import com.openhis.application.constants.RegistrationStatus; @@ -42,74 +43,71 @@ public class RegistrationServiceImpl implements RegistrationService { private final RegistrationMapper registrationMapper; private final RegistrationDetailMapper registrationDetailMapper; - private final ScheduleSlotMapper scheduleSlotMapper; // ← 新增成员变量 + private final ScheduleSlotMapper scheduleSlotMapper; // 新增成员变量 public RegistrationServiceImpl(RegistrationMapper registrationMapper, RegistrationDetailMapper registrationDetailMapper, - ScheduleSlotMapper scheduleSlotMapper) { // ← 构造函数注入 + ScheduleSlotMapper scheduleSlotMapper) { this.registrationMapper = registrationMapper; this.registrationDetailMapper = registrationDetailMapper; this.scheduleSlotMapper = scheduleSlotMapper; } /** - * 诊前退号 + * 诊前退号(取消挂号)。 * - * @param registrationId 挂号主键 + * @param registrationId 挂号主表主键 + * @throws BusinessException 若挂号不存在或已被取消/完成等不允许取消的状态 */ @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void cancelRegistration(Long registrationId) { - // 1. 更新挂号主表状态 + // 1. 查询挂号主记录,确保存在且状态允许取消 Registration registration = registrationMapper.selectByPrimaryKey(registrationId); if (registration == null) { throw new BusinessException("挂号记录不存在"); } + if (RegistrationStatus.CANCELLED.equals(registration.getStatus())) { + // 已经是取消状态,直接返回 + return; + } + if (!RegistrationStatus.REGISTERED.equals(registration.getStatus())) { + // 只允许在已挂号(REGISTERED)状态下取消 + throw new BusinessException("当前挂号状态不允许取消"); + } + + // 2. 更新挂号主表状态为 CANCELLED registration.setStatus(RegistrationStatus.CANCELLED); registrationMapper.updateByPrimaryKeySelective(registration); - // 2. 更新挂号明细表状态 - registrationDetailMapper.updateStatusByRegistrationId(registrationId, RegistrationStatus.CANCELLED); - } - - /** - * 门诊预约挂号(新增或已有的业务方法示例)。 - * - * 该方法在成功创建挂号记录后,需要同步更新对应的排班池(adm_schedule_pool)中的 - * booked_num 字段,使其实时累加。若该字段未更新,前端会出现“可预约余量不变”的问题, - * 这正是 Bug #575 的根本原因。 - * - * @param registration 主挂号实体,必须包含 scheduleSlotId(对应排班池主键) - * @param details 明细列表 - */ - @Override - @Transactional - public void register(Registration registration, - List details) { - // 保存挂号主记录 - registrationMapper.insertSelective(registration); - Long registrationId = registration.getId(); - - // 保存挂号明细记录 + // 3. 更新所有关联的挂号明细状态为 CANCELLED + RegistrationDetail detailCriteria = new RegistrationDetail(); + detailCriteria.setRegistrationId(registrationId); + List details = registrationDetailMapper.select(detailCriteria); for (RegistrationDetail detail : details) { - detail.setRegistrationId(registrationId); - registrationDetailMapper.insertSelective(detail); + detail.setStatus(RegistrationStatus.CANCELLED); + registrationDetailMapper.updateByPrimaryKeySelective(detail); } - // --------- 修复点:实时累加 booked_num ---------- - // scheduleSlotId 在 Registration 实体中保存为 scheduleSlotId(对应 adm_schedule_pool.id) - Long scheduleSlotId = registration.getScheduleSlotId(); - if (scheduleSlotId != null) { - try { - // 使用乐观锁或原子更新,防止并发超卖 - scheduleSlotMapper.incrementBookedNum(scheduleSlotId); - } catch (Exception e) { - log.error("更新排班池 booked_num 失败,scheduleSlotId={}", scheduleSlotId, e); - // 根据业务需求决定是否回滚,这里选择抛出异常以回滚事务 - throw new BusinessException("预约失败,系统繁忙,请稍后重试"); + // 4. 释放对应的排班槽位(已预约数 -1) + // 这里假设每条明细对应一个 scheduleSlotId,若业务实际为多对一,请自行调整。 + for (RegistrationDetail detail : details) { + Long slotId = detail.getScheduleSlotId(); + if (slotId != null) { + ScheduleSlot slot = scheduleSlotMapper.selectByPrimaryKey(slotId); + if (slot != null) { + // 防止出现负数 + int newBooked = Math.max(0, slot.getBookedNum() - 1); + slot.setBookedNum(newBooked); + scheduleSlotMapper.updateByPrimaryKeySelective(slot); + } } } + + log.info("挂号退号成功,registrationId={}, 关联明细条数={}", registrationId, details.size()); } - // 其它业务方法保持不变... + // ----------------------------------------------------------------------- + // 其它业务方法(省略)... + // ----------------------------------------------------------------------- }