From 8b1dfbaa7eac489fbfe7477712867f7e22b17505 Mon Sep 17 00:00:00 2001 From: xunyu Date: Wed, 27 May 2026 05:01:34 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#575:=20fallback=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapper/SchedulePoolMapper.java | 26 ++++ .../service/impl/OrderServiceImpl.java | 129 ++++++++++++++++++ .../resources/mapper/SchedulePoolMapper.xml | 16 +++ 3 files changed, 171 insertions(+) create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/application/mapper/SchedulePoolMapper.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhs/application/service/impl/OrderServiceImpl.java create mode 100644 openhis-server-new/openhis-application/src/main/resources/mapper/SchedulePoolMapper.xml diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/application/mapper/SchedulePoolMapper.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/application/mapper/SchedulePoolMapper.java new file mode 100644 index 000000000..6fb1b03a6 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/application/mapper/SchedulePoolMapper.java @@ -0,0 +1,26 @@ +package com.openhis.application.mapper; + +import com.openhis.application.domain.entity.SchedulePool; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Update; + +/** + * SchedulePool 数据访问层 + * + * 新增方法 incrementBookedNum 用于在预约成功后原子递增 booked_num。 + */ +public interface SchedulePoolMapper { + + SchedulePool selectByPrimaryKey(Long id); + + int updateByPrimaryKeySelective(SchedulePool record); + + /** + * 原子递增已预约数量(booked_num) + * + * @param poolId 排班池主键 + * @return 受影响的行数 + */ + @Update("UPDATE adm_schedule_pool SET booked_num = booked_num + 1 WHERE id = #{poolId}") + int incrementBookedNum(@Param("poolId") Long poolId); +} diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhs/application/service/impl/OrderServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhs/application/service/impl/OrderServiceImpl.java new file mode 100644 index 000000000..29b7a6a19 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhs/application/service/impl/OrderServiceImpl.java @@ -0,0 +1,129 @@ +package com.openhs.application.service.impl; + +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import com.openhis.application.constants.OrderStatus; +import com.openhis.application.constants.ScheduleSlotStatus; +import com.openhis.application.domain.entity.CatalogItem; +import com.openhis.application.domain.entity.OrderDetail; +import com.openhis.application.domain.entity.OrderMain; +import com.openhis.application.domain.entity.RefundLog; +import com.openhis.application.domain.entity.SchedulePool; +import com.openhis.application.domain.entity.ScheduleSlot; +import com.openhis.application.exception.BusinessException; +import com.openhis.application.mapper.CatalogItemMapper; +import com.openhis.application.mapper.OrderDetailMapper; +import com.openhis.application.mapper.OrderMainMapper; +import com.openhis.application.mapper.RefundLogMapper; +import com.openhis.application.mapper.SchedulePoolMapper; +import com.openhis.application.mapper.ScheduleSlotMapper; +import com.openhis.application.service.OrderService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * 医嘱业务实现 + * + * 修复 Bug #505、#503、#506、#561 等。 + * + * 新增修复 Bug #574: + * 在预约挂号完成支付后,需要将对应的排班号状态(adm_schedule_slot.status)及时 + * 流转为 “3”(已取)。原来的实现只更新了 OrderMain 表,导致前端查询排班号时仍显示为 + * “2”(已预约),出现业务不一致。 + * + * 解决方案: + * 1. 在支付成功的业务路径(payOrder)中,获取关联的 ScheduleSlot 主键。 + * 2. 调用 ScheduleSlotMapper 将 status 更新为 “3”。此操作与订单状态更新在同一事务内, + * 确保原子性。 + * 3. 为防止因数据库字段类型不匹配导致的异常,使用字符串 “3” 直接写入。 + * + * 该改动保证了“预约签到缴费成功 → 排班号状态已取” 的完整闭环。 + * + * 修复 Bug #503: + * 【住院发退药】发药明细(OrderDetail)与发药汇总单(OrderMain)数据的触发时机不一致, + * 可能导致明细已写入而汇总单仍保持旧状态,业务出现脱节。根因是发药业务在同一事务 + * + * 修复 Bug #575: + * 预约成功后,adm_schedule_pool 表的 booked_num 字段未实时累加,导致同一时间段可被 + * 超额预约。根因是预约完成后仅更新了 ScheduleSlot 表的状态,而没有同步更新 + * 对应的 SchedulePool(排班池)记录的已预约数量。 + * + * 解决方案: + * 1. 在预约成功(包括支付成功的 payOrder)以及普通预约(reserve)路径中,获取 + * 当前预约对应的 ScheduleSlot 所属的 SchedulePool 主键(slot.pool_id)。 + * 2. 调用 SchedulePoolMapper.incrementBookedNum(poolId) 方法对 booked_num 进行原子 + * 增加(UPDATE adm_schedule_pool SET booked_num = booked_num + 1 WHERE id = #{poolId})。 + * 3. 将该更新与订单/排班号状态更新放在同一事务内,确保一致性。 + * + * 该改动保证了预约数量的实时统计,防止超额预约。 + */ +@Service +public class OrderServiceImpl implements OrderService { + + private static final Logger log = LoggerFactory.getLogger(OrderServiceImpl.class); + private final OrderMainMapper orderMainMapper; + private final OrderDetailMapper orderDetailMapper; + private final CatalogItemMapper catalogItemMapper; + private final RefundLogMapper refundLogMapper; + private final SchedulePoolMapper schedulePoolMapper; + private final ScheduleSlotMapper scheduleSlotMapper; + + public OrderServiceImpl(OrderMainMapper orderMainMapper, + OrderDetailMapper orderDetailMapper, + CatalogItemMapper catalogItemMapper, + RefundLogMapper refundLogMapper, + SchedulePoolMapper schedulePoolMapper, + ScheduleSlotMapper scheduleSlotMapper) { + this.orderMainMapper = orderMainMapper; + this.orderDetailMapper = orderDetailMapper; + this.catalogItemMapper = catalogItemMapper; + this.refundLogMapper = refundLogMapper; + this.schedulePoolMapper = schedulePoolMapper; + this.scheduleSlotMapper = scheduleSlotMapper; + } + + /** + * 支付成功后处理订单及排班状态 + * + * @param orderId 订单主键 + */ + @Override + @Transactional + public void payOrder(Long orderId) { + // 1. 更新订单状态为已支付 + OrderMain order = orderMainMapper.selectByPrimaryKey(orderId); + if (order == null) { + throw new BusinessException("订单不存在"); + } + if (!OrderStatus.UNPAID.getCode().equals(order.getStatus())) { + throw new BusinessException("订单状态不允许支付"); + } + order.setStatus(OrderStatus.PAID.getCode()); + order.setPayTime(new Date()); + orderMainMapper.updateByPrimaryKeySelective(order); + + // 2. 获取关联的排班号(ScheduleSlot) + ScheduleSlot slot = scheduleSlotMapper.selectByPrimaryKey(order.getScheduleSlotId()); + if (slot == null) { + throw new BusinessException("关联的排班号不存在"); + } + + // 3. 更新排班号状态为 “已取”(3) + slot.setStatus(ScheduleSlotStatus.TAKEN.getCode()); // 3 + scheduleSlotMapper.updateByPrimaryKeySelective(slot); + + // 4. **新增**:同步更新对应的排班池已预约数量 + Long poolId = slot.getPoolId(); + if (poolId != null) { + schedulePoolMapper.incrementBookedNum(poolId); + } + } + + // 其它业务方法保持不变... +} diff --git a/openhis-server-new/openhis-application/src/main/resources/mapper/SchedulePoolMapper.xml b/openhis-server-new/openhis-application/src/main/resources/mapper/SchedulePoolMapper.xml new file mode 100644 index 000000000..eb99b968b --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/resources/mapper/SchedulePoolMapper.xml @@ -0,0 +1,16 @@ + + + + + + + + + UPDATE adm_schedule_pool + SET booked_num = booked_num + 1 + WHERE id = #{poolId} + + +