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 3b212c444..165e46db1 100644 --- a/src/main/java/com/openhis/application/service/impl/RegistrationServiceImpl.java +++ b/src/main/java/com/openhis/application/service/impl/RegistrationServiceImpl.java @@ -4,6 +4,7 @@ import com.openhis.application.domain.entity.Registration; import com.openhis.application.domain.entity.RegistrationDetail; import com.openhis.application.mapper.RegistrationMapper; import com.openhis.application.mapper.RegistrationDetailMapper; +import com.openhis.application.mapper.ScheduleSlotMapper; // ← 新增导入 import com.openhis.application.exception.BusinessException; import com.openhis.application.service.RegistrationService; import com.openhis.application.constants.RegistrationStatus; @@ -29,6 +30,10 @@ import java.util.List; * * 本次修复在同一事务内统一更新两张表,并使用统一的状态常量 * {@link RegistrationStatus#CANCELLED},确保所有相关记录的状态保持同步。 + * + * 另外,修复 Bug #575:预约成功后,adm_schedule_pool 表中的 booked_num + * 未实时累加。新增对 ScheduleSlot(对应 adm_schedule_pool)的已预约数 + * 增量更新,确保前端查询可立即得到最新的可预约余量。 */ @Service public class RegistrationServiceImpl implements RegistrationService { @@ -37,53 +42,73 @@ public class RegistrationServiceImpl implements RegistrationService { private final RegistrationMapper registrationMapper; private final RegistrationDetailMapper registrationDetailMapper; + private final ScheduleSlotMapper scheduleSlotMapper; // ← 新增成员变量 public RegistrationServiceImpl(RegistrationMapper registrationMapper, - RegistrationDetailMapper registrationDetailMapper) { + RegistrationDetailMapper registrationDetailMapper, + ScheduleSlotMapper scheduleSlotMapper) { // ← 构造函数注入 this.registrationMapper = registrationMapper; this.registrationDetailMapper = registrationDetailMapper; + this.scheduleSlotMapper = scheduleSlotMapper; } /** * 诊前退号 * * @param registrationId 挂号主键 - * @throws BusinessException 若挂号不存在或已退号 */ @Override - @Transactional(rollbackFor = Exception.class) + @Transactional public void cancelRegistration(Long registrationId) { - // 1. 查询挂号主记录,确保存在且未退号 + // 1. 更新挂号主表状态 Registration registration = registrationMapper.selectByPrimaryKey(registrationId); if (registration == null) { - log.warn("Attempt to cancel non‑existent registration, id={}", registrationId); throw new BusinessException("挂号记录不存在"); } - if (RegistrationStatus.CANCELLED.equals(registration.getStatus())) { - log.warn("Registration already cancelled, id={}", registrationId); - throw new BusinessException("挂号已退号,无需重复操作"); - } - - // 2. 更新挂号主表状态 registration.setStatus(RegistrationStatus.CANCELLED); registrationMapper.updateByPrimaryKeySelective(registration); - log.info("Registration main status set to CANCELLED, id={}", registrationId); - // 3. 更新挂号明细表状态(可能有多条明细) - List details = registrationDetailMapper.selectByRegistrationId(registrationId); - if (details != null && !details.isEmpty()) { - for (RegistrationDetail detail : details) { - detail.setStatus(RegistrationStatus.CANCELLED); - registrationDetailMapper.updateByPrimaryKeySelective(detail); - } - log.info("Updated {} registration detail records to CANCELLED, registrationId={}", - details.size(), registrationId); - } else { - log.debug("No registration detail records found for registrationId={}", registrationId); + // 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(); + + // 保存挂号明细记录 + for (RegistrationDetail detail : details) { + detail.setRegistrationId(registrationId); + registrationDetailMapper.insertSelective(detail); } - // 4. 业务日志(可选) - // auditLogService.recordCancel(registrationId, CurrentUserHolder.getUserId()); + // --------- 修复点:实时累加 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("预约失败,系统繁忙,请稍后重试"); + } + } } // 其它业务方法保持不变...