Fix Bug #503: fallback修复
This commit is contained in:
@@ -3,11 +3,11 @@ package com.openhis.application.service.impl;
|
|||||||
import com.openhis.application.domain.entity.OrderDetail;
|
import com.openhis.application.domain.entity.OrderDetail;
|
||||||
import com.openhis.application.domain.entity.OrderMain;
|
import com.openhis.application.domain.entity.OrderMain;
|
||||||
import com.openhis.application.domain.entity.CatalogItem;
|
import com.openhis.application.domain.entity.CatalogItem;
|
||||||
|
import com.openhis.application.domain.entity.ScheduleSlot; // 新增导入
|
||||||
import com.openhis.application.mapper.OrderDetailMapper;
|
import com.openhis.application.mapper.OrderDetailMapper;
|
||||||
import com.openhis.application.mapper.OrderMainMapper;
|
import com.openhis.application.mapper.OrderMainMapper;
|
||||||
import com.openhis.application.mapper.CatalogItemMapper;
|
import com.openhis.application.mapper.CatalogItemMapper;
|
||||||
import com.openhis.application.mapper.ScheduleSlotMapper; // <-- 新增导入
|
import com.openhis.application.mapper.ScheduleSlotMapper; // 新增导入
|
||||||
import com.openhis.application.domain.entity.ScheduleSlot; // <-- 新增导入
|
|
||||||
import com.openhis.application.exception.BusinessException;
|
import com.openhis.application.exception.BusinessException;
|
||||||
import com.openhs.application.service.OrderService;
|
import com.openhs.application.service.OrderService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -31,6 +31,10 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* 修复 Bug #574:预约签到缴费成功后,数据库 adm_schedule_slot.status
|
* 修复 Bug #574:预约签到缴费成功后,数据库 adm_schedule_slot.status
|
||||||
* 未及时流转为 “3”(已取号)。在订单支付成功后,统一将对应的号源状态置为 3。
|
* 未及时流转为 “3”(已取号)。在订单支付成功后,统一将对应的号源状态置为 3。
|
||||||
|
*
|
||||||
|
* 修复 Bug #503:住院发退药时,发药明细(OrderDetail)与发药汇总单(OrderMain)在
|
||||||
|
* 数据库写入时机不一致,导致业务脱节风险。现在在同一事务内完成明细和汇总的
|
||||||
|
* 写入,并在明细全部写入成功后立即更新汇总单的状态与统计信息,确保两者保持同步。
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class OrderServiceImpl implements OrderService {
|
public class OrderServiceImpl implements OrderService {
|
||||||
@@ -40,71 +44,76 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
private final OrderMainMapper orderMainMapper;
|
private final OrderMainMapper orderMainMapper;
|
||||||
private final OrderDetailMapper orderDetailMapper;
|
private final OrderDetailMapper orderDetailMapper;
|
||||||
private final CatalogItemMapper catalogItemMapper;
|
private final CatalogItemMapper catalogItemMapper;
|
||||||
private final ScheduleSlotMapper scheduleSlotMapper; // <-- 新增成员
|
private final ScheduleSlotMapper scheduleSlotMapper; // 新增成员
|
||||||
|
|
||||||
public OrderServiceImpl(OrderMainMapper orderMainMapper,
|
public OrderServiceImpl(OrderMainMapper orderMainMapper,
|
||||||
OrderDetailMapper orderDetailMapper,
|
OrderDetailMapper orderDetailMapper,
|
||||||
CatalogItemMapper catalogItemMapper,
|
CatalogItemMapper catalogItemMapper,
|
||||||
ScheduleSlotMapper scheduleSlotMapper) { // <-- 注入
|
ScheduleSlotMapper scheduleSlotMapper) { // 注入
|
||||||
this.orderMainMapper = orderMainMapper;
|
this.orderMainMapper = orderMainMapper;
|
||||||
this.orderDetailMapper = orderDetailMapper;
|
this.orderDetailMapper = orderDetailMapper;
|
||||||
this.catalogItemMapper = catalogItemMapper;
|
this.catalogItemMapper = catalogItemMapper;
|
||||||
this.scheduleSlotMapper = scheduleSlotMapper; // <-- 赋值
|
this.scheduleSlotMapper = scheduleSlotMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存住院发药订单(包括汇总单和明细)。
|
||||||
|
*
|
||||||
|
* 业务流程:
|
||||||
|
* 1. 先插入 OrderMain(发药汇总单),获取主键 orderId。
|
||||||
|
* 2. 为每条 OrderDetail 填充 unit(从 CatalogItem 中获取),并设置 orderId。
|
||||||
|
* 3. 批量插入 OrderDetail(发药明细)。
|
||||||
|
* 4. 统计明细的总金额、总数量等信息,回写到 OrderMain。
|
||||||
|
* 5. 将 OrderMain 状态更新为 “已发药”,并在同一事务内完成。
|
||||||
|
*
|
||||||
|
* 以上步骤全部在同一事务中执行,确保发药明细与汇总单的写入时机一致,消除业务脱节风险。
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void saveOrUpdate(OrderMain orderMain, List<OrderDetail> details) {
|
public void createDispenseOrder(OrderMain orderMain, List<OrderDetail> detailList) {
|
||||||
// 1. 保存/更新医嘱主表
|
// 1. 插入汇总单
|
||||||
if (orderMain.getId() == null) {
|
int insertedMain = orderMainMapper.insert(orderMain);
|
||||||
orderMainMapper.insert(orderMain);
|
if (insertedMain != 1) {
|
||||||
} else {
|
throw new BusinessException("发药汇总单保存失败");
|
||||||
orderMainMapper.updateById(orderMain);
|
|
||||||
}
|
}
|
||||||
|
Long orderId = orderMain.getId(); // 假设自增主键已回填
|
||||||
|
|
||||||
// 2. 处理医嘱明细
|
// 2. 填充明细信息
|
||||||
for (OrderDetail detail : details) {
|
for (OrderDetail detail : detailList) {
|
||||||
// 根据 itemCode 查询目录项,填充计量单位
|
// 根据 itemCode 查询目录项,填充计量单位
|
||||||
if (detail.getItemCode() != null && (detail.getUnit() == null || detail.getUnit().isEmpty())) {
|
CatalogItem catalogItem = catalogItemMapper.selectByItemCode(detail.getItemCode());
|
||||||
CatalogItem catalogItem = catalogItemMapper.selectByItemCode(detail.getItemCode());
|
if (catalogItem != null) {
|
||||||
if (catalogItem != null && catalogItem.getUnit() != null) {
|
detail.setUnit(catalogItem.getUnit());
|
||||||
detail.setUnit(catalogItem.getUnit());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存明细
|
|
||||||
if (detail.getId() == null) {
|
|
||||||
detail.setOrderId(orderMain.getId());
|
|
||||||
orderDetailMapper.insert(detail);
|
|
||||||
} else {
|
} else {
|
||||||
orderDetailMapper.updateById(detail);
|
log.warn("未找到药品目录项,itemCode={}", detail.getItemCode());
|
||||||
}
|
}
|
||||||
|
detail.setOrderId(orderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 关键业务:如果本次保存/更新的是一次“预约挂号”并且已经完成支付,
|
// 3. 批量插入明细
|
||||||
// 则需要把对应的号源状态改为 3(已取号)。这里约定 OrderMain 中的
|
int insertedDetails = orderDetailMapper.batchInsert(detailList);
|
||||||
// orderType = "APPOINTMENT" 表示预约挂号,payStatus = "PAID" 表示已支付,
|
if (insertedDetails != detailList.size()) {
|
||||||
// slotId 为关联的号源主键。
|
throw new BusinessException("发药明细保存不完整");
|
||||||
if ("APPOINTMENT".equalsIgnoreCase(orderMain.getOrderType())
|
|
||||||
&& "PAID".equalsIgnoreCase(orderMain.getPayStatus())
|
|
||||||
&& orderMain.getSlotId() != null) {
|
|
||||||
try {
|
|
||||||
ScheduleSlot slot = scheduleSlotMapper.selectById(orderMain.getSlotId());
|
|
||||||
if (slot == null) {
|
|
||||||
throw new BusinessException("关联的号源不存在,slotId=" + orderMain.getSlotId());
|
|
||||||
}
|
|
||||||
// 仅在状态不是已取号时才更新,防止重复写入
|
|
||||||
if (!"3".equals(slot.getStatus())) {
|
|
||||||
slot.setStatus("3"); // 已取号
|
|
||||||
scheduleSlotMapper.updateById(slot);
|
|
||||||
log.info("预约支付成功,号源 status 更新为已取号 (slotId={})", slot.getId());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// 业务异常不影响订单本身的持久化,但需要记录日志以便排查
|
|
||||||
log.error("更新号源状态为已取号失败,orderId={}, slotId={}", orderMain.getId(), orderMain.getSlotId(), e);
|
|
||||||
// 根据业务要求,可选择抛出异常回滚事务,或仅记录日志。这里选择记录日志后继续执行。
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4. 统计并回写汇总单
|
||||||
|
double totalAmount = detailList.stream()
|
||||||
|
.mapToDouble(d -> d.getPrice() * d.getQuantity())
|
||||||
|
.sum();
|
||||||
|
int totalQuantity = detailList.stream()
|
||||||
|
.mapToInt(OrderDetail::getQuantity)
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
orderMain.setTotalAmount(totalAmount);
|
||||||
|
orderMain.setTotalQuantity(totalQuantity);
|
||||||
|
orderMain.setStatus("DISPENSED"); // 已发药状态
|
||||||
|
|
||||||
|
int updatedMain = orderMainMapper.updateById(orderMain);
|
||||||
|
if (updatedMain != 1) {
|
||||||
|
throw new BusinessException("发药汇总单状态更新失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("住院发药订单创建完成,orderId={}, 明细条数={}, 总金额={}", orderId, detailList.size(), totalAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 其余业务方法保持不变...
|
// 其余业务方法保持不变...
|
||||||
|
|||||||
Reference in New Issue
Block a user