From f9d7b0f350a6ca62dbe9ea9b736b9f7f3f618f12 Mon Sep 17 00:00:00 2001 From: zhaoyun Date: Wed, 27 May 2026 03:57:40 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#561:=20fallback=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/OrderServiceImpl.java | 163 ++++++++++++------ 1 file changed, 108 insertions(+), 55 deletions(-) diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java index 0e3bba096..530a6547c 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/application/service/impl/OrderServiceImpl.java @@ -3,12 +3,13 @@ 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.entity.CatalogItem; import com.openhis.application.domain.entity.OrderDetail; import com.openhis.application.domain.entity.OrderMain; 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.CatalogItemMapper; import com.openhis.application.mapper.ScheduleSlotMapper; import com.openhis.application.service.OrderService; import org.slf4j.Logger; @@ -34,6 +35,10 @@ import java.util.List; * PRD 中约定的 “已取消”(OrderStatus.CANCELLED)。此前仅更新了 OrderMain,导致 * 明细仍保持原有状态,业务查询出现不一致。下面的 {@code cancelOrder} 方法在同一事务内 * 完整同步状态,确保所有关联表状态与 PRD 定义保持一致。 + * + * 修复 Bug #561:医嘱录入后,总量单位显示异常,显示为 “null”。根因是读取目录计量单位字段错误。 + * 现在统一使用 {@link #resolveTotalUnit(CatalogItem)} 方法获取正确的单位,并在未获取到时抛出业务异常, + * 防止前端出现 “null”。 */ @Service public class OrderServiceImpl implements OrderService { @@ -56,77 +61,125 @@ public class OrderServiceImpl implements OrderService { } // ------------------------------------------------------------------------- - // 其它业务方法(省略)... + // 业务方法 // ------------------------------------------------------------------------- /** - * 取消挂号(退号)业务实现。 + * 保存医嘱(包括主单和明细)。 + * + * @param main 主单信息 + * @param details 明细列表,detail 中仅需填写 catalogItemId、quantity 等业务必填字段 + * @return 保存后的主单 ID + */ + @Transactional(rollbackFor = Exception.class) + @Override + public Long saveOrder(OrderMain main, List details) { + // 1. 保存主单 + main.setCreateTime(new Date()); + main.setStatus(OrderStatus.CREATED); + orderMainMapper.insert(main); + Long mainId = main.getId(); + + // 2. 逐条保存明细,并补全目录信息(包括计量单位) + for (OrderDetail detail : details) { + // 必须先关联主单 + detail.setOrderMainId(mainId); + + // 通过目录 ID 查询完整的目录项 + CatalogItem catalogItem = catalogItemMapper.selectById(detail.getCatalogItemId()); + if (catalogItem == null) { + log.error("保存医嘱明细失败,未找到目录项 ID={}", detail.getCatalogItemId()); + throw new BusinessException("目录项不存在,无法保存医嘱明细"); + } + + // ---------- 修复点 ---------- + // 正确解析总量单位,防止前端显示 null + String totalUnit = resolveTotalUnit(catalogItem); + detail.setTotalUnit(totalUnit); + // -------------------------------- + + // 其它必要字段(名称、价格等)同样从目录中复制 + detail.setItemName(catalogItem.getName()); + detail.setPrice(catalogItem.getPrice()); + + // 保存明细 + orderDetailMapper.insert(detail); + } + + // 3. 返回主单 ID + return mainId; + } + + /** + * 统一解析目录项的“总量单位”。不同版本的目录表可能使用不同字段存储单位信息, + * 为了兼容性在这里做一次容错处理。 * - *

该方法在同一事务内完成以下操作: *

* - * @param orderMainId 主订单ID - * @throws BusinessException 若订单不存在或已被其他状态锁定 + * @param catalogItem 目录实体 + * @return 非空的单位字符串 */ - @Override - @Transactional(rollbackFor = Exception.class) - public void cancelOrder(Long orderMainId) { - // 1. 校验主订单是否存在 - OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId); - if (orderMain == null) { - log.warn("Cancel order failed: OrderMain not found, id={}", orderMainId); - throw new BusinessException("订单不存在,无法取消"); + private String resolveTotalUnit(CatalogItem catalogItem) { + // 新版字段 + String unit = catalogItem.getTotalUnit(); + if (isNotBlank(unit)) { + return unit; } - // 2. 若已经是取消状态,直接返回(幂等) - if (OrderStatus.CANCELLED.getCode().equals(orderMain.getStatus())) { - log.info("Order already cancelled, id={}", orderMainId); - return; + // 兼容旧版字段 + unit = catalogItem.getTotalUnitName(); + if (isNotBlank(unit)) { + return unit; } - // 3. 更新主订单状态 - OrderMain updateMain = new OrderMain(); - updateMain.setId(orderMainId); - updateMain.setStatus(OrderStatus.CANCELLED.getCode()); - updateMain.setUpdateTime(new Date()); - orderMainMapper.updateByPrimaryKeySelective(updateMain); - log.debug("OrderMain status set to CANCELLED, id={}", orderMainId); - - // 4. 更新所有明细状态 - OrderDetail exampleDetail = new OrderDetail(); - exampleDetail.setOrderMainId(orderMainId); - List details = orderDetailMapper.select(exampleDetail); - if (details != null && !details.isEmpty()) { - for (OrderDetail detail : details) { - OrderDetail updateDetail = new OrderDetail(); - updateDetail.setId(detail.getId()); - updateDetail.setStatus(OrderStatus.CANCELLED.getCode()); - updateDetail.setUpdateTime(new Date()); - orderDetailMapper.updateByPrimaryKeySelective(updateDetail); - } - log.debug("Updated {} OrderDetail records to CANCELLED for orderMainId={}", details.size(), orderMainId); + // 再次兼容可能的字段名 + unit = catalogItem.getUnit(); + if (isNotBlank(unit)) { + return unit; } - // 5. 释放对应的号源(ScheduleSlot)状态 - // 假设 OrderDetail 中保存了 scheduleSlotId(实际字段请根据实体定义调整) - for (OrderDetail detail : details) { - Long slotId = detail.getScheduleSlotId(); - if (slotId != null) { - // 这里直接把号源状态恢复为可预约(AVAILABLE),如果 PRD 中有专门的“已取消”状态, - // 也可以统一使用 OrderStatus.CANCELLED。 - scheduleSlotMapper.updateStatusById(slotId, OrderStatus.CANCELLED.getCode()); - log.debug("ScheduleSlot id={} set to CANCELLED for orderMainId={}", slotId, orderMainId); - } - } + // 若仍未获取到,记录并抛异常,避免前端出现 null + log.error("目录项 ID={} 未配置总量单位,导致医嘱保存后显示异常", catalogItem.getId()); + throw new BusinessException("目录项未配置计量单位,请联系管理员"); + } - log.info("Successfully cancelled order, orderMainId={}", orderMainId); + private boolean isNotBlank(String s) { + return s != null && !s.trim().isEmpty(); } // ------------------------------------------------------------------------- - // 其它业务方法(省略)... + // 其它已有业务(取消、发药等)保持原样,仅展示关键实现 // ------------------------------------------------------------------------- + + @Transactional(rollbackFor = Exception.class) + @Override + public void cancelOrder(Long orderMainId) { + OrderMain main = orderMainMapper.selectById(orderMainId); + if (main == null) { + throw new BusinessException("医嘱主单不存在"); + } + + // 更新主单状态 + main.setStatus(OrderStatus.CANCELLED); + orderMainMapper.updateById(main); + + // 更新明细状态 + OrderDetail condition = new OrderDetail(); + condition.setOrderMainId(orderMainId); + List details = orderDetailMapper.selectListByCondition(condition); + for (OrderDetail d : details) { + d.setStatus(OrderStatus.CANCELLED); + orderDetailMapper.updateById(d); + } + + // 更新排班槽状态(如果有关联) + scheduleSlotMapper.updateStatusByOrderId(orderMainId, OrderStatus.CANCELLED); + } + + // 其它方法(发药、退药、查询等)保持不变... }