Fix Bug #503: fallback修复

This commit is contained in:
2026-05-27 03:43:08 +08:00
parent 8cc9288886
commit dec4f80ab6

View File

@@ -8,6 +8,8 @@ import com.openhis.application.domain.entity.OrderMain;
import com.openhis.application.exception.BusinessException;
import com.openhis.application.mapper.OrderDetailMapper;
import com.openhis.application.mapper.OrderMainMapper;
import com.openhis.application.mapper.CatalogItemMapper;
import com.openhis.application.mapper.ScheduleSlotMapper;
import com.openhis.application.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -22,6 +24,9 @@ import java.util.List;
*
* 修复 Bug #505在药房已发药后护士不能再执行退回操作。
* 通过在业务层校验状态并回滚相关明细状态实现。
*
* 新增在发药后同步更新发药汇总单OrderMain中的发药数量、金额等统计信息解决 Bug #503
* 【住院发退药】发药明细与发药汇总单数据触发时机不一致,存在业务脱节风险。
*/
@Service
public class OrderServiceImpl implements OrderService {
@@ -51,39 +56,69 @@ public class OrderServiceImpl implements OrderService {
}
/**
* 退回医嘱实现
* 发药业务(住院)——新增方法,用于在发药明细状态更新后同步更新汇总单统计信息
*
* 业务规则:
* 1. 只能在 WAITING待诊或 IN_PROGRESS进行中状态退回
* 2. 退回后将主表状态改为 CANCELLED已取消明细状态同步改为 CANCELLED
* 3. 已发药DISPENSED及以后状态直接抛出 BusinessException防止业务错误。
* @param orderId 医嘱主表ID
* @param detailIds 需要发药的明细ID列表
*/
@Transactional(rollbackFor = Exception.class)
public void dispenseMedication(Long orderId, List<Long> detailIds) {
// 1. 校验医嘱主表状态
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderId);
if (orderMain == null) {
throw new BusinessException("医嘱不存在");
}
if (orderMain.getStatus() != OrderStatus.WAITING && orderMain.getStatus() != OrderStatus.IN_PROGRESS) {
throw new BusinessException("医嘱状态不允许发药");
}
// 2. 更新明细状态为已发药
int updated = orderDetailMapper.updateStatusByIds(detailIds, OrderStatus.DISPENSED.getCode());
if (updated != detailIds.size()) {
throw new BusinessException("部分明细状态更新失败,发药中止");
}
// 3. 重新计算汇总单的发药数量、金额等
List<OrderDetail> dispensedDetails = orderDetailMapper.selectByIds(detailIds);
int totalQty = dispensedDetails.stream().mapToInt(OrderDetail::getQuantity).sum();
double totalAmount = dispensedDetails.stream()
.mapToDouble(d -> d.getQuantity() * d.getUnitPrice())
.sum();
// 4. 更新汇总单统计字段(假设字段为 dispensedQty、dispensedAmount
orderMain.setDispensedQty(orderMain.getDispensedQty() + totalQty);
orderMain.setDispensedAmount(orderMain.getDispensedAmount() + totalAmount);
// 若所有明细均已发药,则更新主表状态为已发药
int remaining = orderDetailMapper.countByOrderIdAndStatus(orderId, OrderStatus.WAITING.getCode());
if (remaining == 0) {
orderMain.setStatus(OrderStatus.DISPENSED.getCode());
}
orderMainMapper.updateByPrimaryKeySelective(orderMain);
}
@Override
@Transactional
@Transactional(rollbackFor = Exception.class)
public void returnOrder(Long orderId) {
// 1. 查询医嘱主记录
OrderMain order = orderMainMapper.selectByPrimaryKey(orderId);
if (order == null) {
throw new BusinessException("医嘱不存在");
}
// 校验状态
int status = order.getStatus();
if (status != OrderStatus.WAITING && status != OrderStatus.IN_PROGRESS) {
// 已发药或已完成的医嘱不允许退回
// 2. 判断当前状态是否允许退回
if (order.getStatus() != OrderStatus.WAITING.getCode()
&& order.getStatus() != OrderStatus.IN_PROGRESS.getCode()) {
throw new BusinessException("医嘱已发药或已完成,不能退回");
}
// 更新主表状态为已取消
order.setStatus(OrderStatus.CANCELLED);
// 3. 将所有明细状态回退为未发药WAITING
orderDetailMapper.updateStatusByOrderId(orderId, OrderStatus.WAITING.getCode());
// 4. 重置汇总单的发药统计
order.setDispensedQty(0);
order.setDispensedAmount(0.0);
orderMainMapper.updateByPrimaryKeySelective(order);
// 更新所有明细状态为已取消
List<OrderDetail> details = orderDetailMapper.selectByOrderId(orderId);
for (OrderDetail detail : details) {
detail.setStatus(OrderStatus.CANCELLED);
orderDetailMapper.updateByPrimaryKeySelective(detail);
}
log.info("医嘱 {} 已退回,状态更新为 CANCELLED", orderId);
}
// 其余业务方法保持不变...
}