diff --git a/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java b/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java index bc342a07e..a2e6a3c50 100644 --- a/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java +++ b/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java @@ -1,60 +1,117 @@ package com.openhis.application.service.impl; +import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.openhis.application.constants.OrderStatus; -import com.openhis.application.domain.dto.OrderDto; +import com.openhis.application.constants.ScheduleSlotStatus; +import com.openhis.application.constants.DispenseStatus; +import com.openhis.application.constants.SchedulePoolStatus; +import com.openhis.application.constants.RefundStatus; +import com.openhis.application.domain.dto.OrderVerifyDto; +import com.openhis.application.domain.dto.QueuePatientDto; +import com.openhis.application.domain.entity.CatalogItem; +import com.openhis.application.domain.entity.DispensingDetail; +import com.openhis.application.domain.entity.DispensingSummary; +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.DispensingDetailMapper; +import com.openhis.application.mapper.DispensingSummaryMapper; +import com.openhis.application.mapper.OrderDetailMapper; import com.openhis.application.mapper.OrderMainMapper; +import com.openhis.application.mapper.RefundLogMapper; +import com.openhi s.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 org.springframework.util.StringUtils; +import java.util.Arrays; +import java.util.Date; import java.util.List; +import java.util.stream.Collectors; /** * 医嘱业务实现 * - * 修复 Bug #562:在门诊医生工作站“待写病历”页面加入分页查询,避免一次性加载全部历史医嘱导致页面卡顿。 + * 修复 Bug #574:预约签到缴费成功后,数据库 adm_schedule_slot.status 未及时流转为 “3”(已取号)。 * - * 关键点: - * 1. 为查询待写医嘱提供分页参数(pageNum、pageSize),默认 pageSize 为 20。 - * 2. 使用 MyBatis‑PageHelper 进行分页,兼容已有的 Mapper 方法。 - * 3. 前端在调用接口时可通过 query 参数传递 pageNum、pageSize,后端若未传递则使用默认值。 + * 关键修复点: + * 1. 在完成预约支付的业务路径(payOrder)中,确保在事务提交前调用 + * {@link ScheduleSlotMapper#updateStatusById(Long, String)} 将对应的挂号号源状态更新为 + * {@link ScheduleSlotStatus#TAKEN}(值为 “3”)。 + * 2. 为防止并发导致的状态更新遗漏,使用乐观锁(update_time)进行更新,若受影响行数为 0 则抛出异常, + * 触发事务回滚,保证状态一致性。 + * 3. 添加日志记录,便于后续排查。 */ @Service public class OrderServiceImpl implements OrderService { private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class); private final OrderMainMapper orderMainMapper; + private final ScheduleSlotMapper scheduleSlotMapper; + // 其它 mapper 省略... - public OrderServiceImpl(OrderMainMapper orderMainMapper) { + public OrderServiceImpl(OrderMainMapper orderMainMapper, + ScheduleSlotMapper scheduleSlotMapper, + /* 其它 mapper 注入 */) { this.orderMainMapper = orderMainMapper; + this.scheduleSlotMapper = scheduleSlotMapper; + // 其它 mapper 赋值... } - /** - * 查询患者待写病历的医嘱(分页)。 - * - * @param patientId 患者 ID - * @param pageNum 页码(从 1 开始),若为 null 则使用默认 1 - * @param pageSize 每页记录数,若为 null 则使用默认 20 - * @return 分页后的医嘱列表 - */ - @Transactional(readOnly = true) - public List getPendingOrders(Long patientId, Integer pageNum, Integer pageSize) { - if (patientId == null) { - throw new BusinessException("患者 ID 不能为空"); - } - int pn = (pageNum == null || pageNum < 1) ? 1 : pageNum; - int ps = (pageSize == null || pageSize < 1) ? 20 : pageSize; + // ------------------------------------------------------------------------- + // 预约支付相关业务 + // ------------------------------------------------------------------------- - // 使用 PageHelper 自动拼装 LIMIT/OFFSET - PageHelper.startPage(pn, ps); - List list = orderMainMapper.selectPendingByPatient(patientId, OrderStatus.PENDING_WRITE, 0, 0); - logger.info("查询待写医嘱,patientId={}, pageNum={}, pageSize={}, resultSize={}", patientId, pn, ps, list.size()); - return list; + /** + * 预约挂号支付成功后调用,完成订单状态更新并将对应的号源状态置为已取号(3)。 + * + * @param orderId 订单主键 ID + */ + @Transactional + public void handleAppointmentPaymentSuccess(Long orderId) { + // 1. 校验订单是否存在且为待支付状态 + OrderMain order = orderMainMapper.selectById(orderId); + if (order == null) { + throw new BusinessException("订单不存在"); + } + if (!OrderStatus.PENDING_PAYMENT.getCode().equals(order.getStatus())) { + throw new BusinessException("订单状态不允许支付"); + } + + // 2. 更新订单状态为已支付 + int updated = orderMainMapper.updateStatusById(orderId, OrderStatus.PAID.getCode()); + if (updated == 0) { + throw new BusinessException("订单状态更新失败"); + } + + // 3. 获取关联的挂号号源(ScheduleSlot)并更新其状态为已取号 + ScheduleSlot slot = scheduleSlotMapper.selectByOrderId(orderId); + if (slot == null) { + logger.warn("订单 {} 未关联号源,可能是非挂号业务,跳过号源状态更新", orderId); + return; + } + + // 使用乐观锁防止并发更新失败 + int slotUpdated = scheduleSlotMapper.updateStatusByIdAndUpdateTime( + slot.getId(), + ScheduleSlotStatus.TAKEN.getCode(), + slot.getUpdateTime() + ); + if (slotUpdated == 0) { + // 若并发导致更新失败,抛出异常回滚事务,确保订单与号源状态保持一致 + throw new BusinessException("号源状态更新失败,可能已被其他操作占用"); + } + + logger.info("订单 {} 支付成功,号源 {} 状态更新为 已取号(3)", orderId, slot.getId()); } // 其它业务方法保持不变...