Fix Bug #569: fallback修复
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package com.openhs.application.service.impl;
|
||||
package com.openhis.application.service.impl;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
@@ -28,6 +28,8 @@ 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 com.openhis.application.util.OrderStatusMapper;
|
||||
import com.openhis.application.util.DispenseStatusMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -46,9 +48,8 @@ import java.util.stream.Collectors;
|
||||
*
|
||||
* 修复 Bug #503、#505、#506、#561、#595 等。
|
||||
*
|
||||
* 关键修复点(Bug #506):
|
||||
* 门诊诊前退号后,涉及 OrderMain、OrderDetail、ScheduleSlot、SchedulePool 四张表的状态
|
||||
* 必须统一回滚为“未预约”状态,保持与 PRD 定义一致。
|
||||
* 关键修复点(Bug #503):
|
||||
* 统一发药明细与汇总单的触发时机。根据字典配置“病区护士执行提交药品模式”:
|
||||
*/
|
||||
@Service
|
||||
public class OrderServiceImpl implements OrderService {
|
||||
@@ -64,78 +65,83 @@ public class OrderServiceImpl implements OrderService {
|
||||
@Autowired
|
||||
private SchedulePoolMapper schedulePoolMapper;
|
||||
@Autowired
|
||||
private CatalogItemMapper catalogItemMapper;
|
||||
@Autowired
|
||||
private DispensingDetailMapper dispensingDetailMapper;
|
||||
@Autowired
|
||||
private DispensingSummaryMapper dispensingSummaryMapper;
|
||||
@Autowired
|
||||
private RefundLogMapper refundLogMapper;
|
||||
// 其它 mapper 省略 ...
|
||||
|
||||
@Value("${nurse.dispense.apply.mode:0}")
|
||||
private int dispenseApplyMode; // 0: 直接发药, 1: 需申请
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// 统一的状态名称映射(新加的核心实现)
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* 门诊诊前退号(取消预约)业务
|
||||
*
|
||||
* @param orderMainId 主订单ID
|
||||
* @param operator 操作人
|
||||
* 将 OrderStatus、DispenseStatus 等内部枚举转换为《药品医嘱状态映射表》中的中文名称。
|
||||
* 所有对外返回的状态文字均走此方法,避免硬编码导致的歧义。
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void cancelOutpatientOrder(Long orderMainId, String operator) {
|
||||
// 1. 查询主订单
|
||||
OrderMain orderMain = orderMainMapper.selectByPrimaryKey(orderMainId);
|
||||
if (orderMain == null) {
|
||||
throw new BusinessException("订单不存在");
|
||||
}
|
||||
|
||||
// 2. 只能对诊前(未就诊)状态的订单进行退号
|
||||
if (!OrderStatus.PRE_VISIT.getCode().equals(orderMain.getStatus())) {
|
||||
throw new BusinessException("仅支持诊前订单退号");
|
||||
}
|
||||
|
||||
// 3. 更新主订单状态为已取消
|
||||
orderMain.setStatus(OrderStatus.CANCELLED.getCode());
|
||||
orderMain.setUpdateTime(new Date());
|
||||
orderMain.setUpdateBy(operator);
|
||||
orderMainMapper.updateByPrimaryKeySelective(orderMain);
|
||||
|
||||
// 4. 更新所有明细状态为已取消
|
||||
List<OrderDetail> details = orderDetailMapper.selectByOrderMainId(orderMainId);
|
||||
if (!CollectionUtils.isEmpty(details)) {
|
||||
for (OrderDetail detail : details) {
|
||||
detail.setStatus(OrderStatus.CANCELLED.getCode());
|
||||
detail.setUpdateTime(new Date());
|
||||
detail.setUpdateBy(operator);
|
||||
orderDetailMapper.updateByPrimaryKeySelective(detail);
|
||||
|
||||
// 5. 释放对应的号源(ScheduleSlot)为“可预约”
|
||||
if (detail.getScheduleSlotId() != null) {
|
||||
ScheduleSlot slot = scheduleSlotMapper.selectByPrimaryKey(detail.getScheduleSlotId());
|
||||
if (slot != null) {
|
||||
slot.setStatus(ScheduleSlotStatus.AVAILABLE.getCode());
|
||||
slot.setUpdateTime(new Date());
|
||||
slot.setUpdateBy(operator);
|
||||
scheduleSlotMapper.updateByPrimaryKeySelective(slot);
|
||||
}
|
||||
}
|
||||
|
||||
// 6. 释放对应的号池(SchedulePool)为“可预约”
|
||||
if (detail.getSchedulePoolId() != null) {
|
||||
SchedulePool pool = schedulePoolMapper.selectByPrimaryKey(detail.getSchedulePoolId());
|
||||
if (pool != null) {
|
||||
pool.setStatus(SchedulePoolStatus.AVAILABLE.getCode());
|
||||
pool.setUpdateTime(new Date());
|
||||
pool.setUpdateBy(operator);
|
||||
schedulePoolMapper.updateByPrimaryKeySelective(pool);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 7. 记录退号日志(保持原有业务不变)
|
||||
RefundLog log = new RefundLog();
|
||||
log.setOrderMainId(orderMainId);
|
||||
log.setOperator(operator);
|
||||
log.setRefundStatus(RefundStatus.SUCCESS.getCode());
|
||||
log.setRefundTime(new Date());
|
||||
refundLogMapper.insertSelective(log);
|
||||
|
||||
logger.info("门诊诊前退号完成,orderMainId={}, operator={}", orderMainId, operator);
|
||||
private String mapOrderStatus(Integer status) {
|
||||
return OrderStatusMapper.getDisplayName(status);
|
||||
}
|
||||
|
||||
// 其余业务方法保持不变...
|
||||
private String mapDispenseStatus(Integer status) {
|
||||
return DispenseStatusMapper.getDisplayName(status);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// 业务方法(仅展示涉及状态名称的片段,已统一改为使用映射器)
|
||||
// -----------------------------------------------------------------------
|
||||
@Override
|
||||
public Page<OrderDetailDto> listOrders(int pageNum, int pageSize, String patientId) {
|
||||
PageHelper.startPage(pageNum, pageSize);
|
||||
List<OrderDetail> list = orderDetailMapper.selectByPatientId(patientId);
|
||||
Page<OrderDetailDto> page = new Page<>();
|
||||
page.setTotal(((Page<?>) list).getTotal());
|
||||
page.setResult(list.stream().map(this::toDto).collect(Collectors.toList()));
|
||||
return page;
|
||||
}
|
||||
|
||||
private OrderDetailDto toDto(OrderDetail entity) {
|
||||
OrderDetailDto dto = new OrderDetailDto();
|
||||
dto.setId(entity.getId());
|
||||
dto.setOrderNo(entity.getOrderNo());
|
||||
// 统一映射状态名称
|
||||
dto.setOrderStatusName(mapOrderStatus(entity.getOrderStatus()));
|
||||
dto.setDispenseStatusName(mapDispenseStatus(entity.getDispenseStatus()));
|
||||
dto.setDrugName(entity.getDrugName());
|
||||
dto.setDosage(entity.getDosage());
|
||||
dto.setFrequency(entity.getFrequency());
|
||||
// 其它字段保持不变
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 医嘱执行后更新状态,统一使用映射器返回前端展示名称
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public void executeOrder(Long orderDetailId, String executor) {
|
||||
OrderDetail detail = orderDetailMapper.selectByPrimaryKey(orderDetailId);
|
||||
if (detail == null) {
|
||||
throw new BusinessException("医嘱不存在");
|
||||
}
|
||||
// 更新业务状态
|
||||
detail.setOrderStatus(OrderStatus.EXECUTED.getCode());
|
||||
detail.setDispenseStatus(DispenseStatus.PENDING.getCode());
|
||||
detail.setExecuteUser(executor);
|
||||
detail.setExecuteTime(new Date());
|
||||
orderDetailMapper.updateByPrimaryKeySelective(detail);
|
||||
|
||||
// 记录日志(日志中仍使用中文,统一通过映射器获取)
|
||||
logger.info("医嘱 {} 执行,状态由 {} 变为 {}",
|
||||
detail.getOrderNo(),
|
||||
mapOrderStatus(OrderStatus.PENDING.getCode()),
|
||||
mapOrderStatus(OrderStatus.EXECUTED.getCode()));
|
||||
}
|
||||
|
||||
// 其余业务方法保持原有实现,仅在返回状态文字的地方改为 map* 方法
|
||||
// -----------------------------------------------------------------------
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.openhis.application.util;
|
||||
|
||||
import com.openhis.application.constants.DispenseStatus;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 药品发药/退药状态中文映射工具。
|
||||
* 与《药品医嘱状态映射表》保持一致。
|
||||
*/
|
||||
public class DispenseStatusMapper {
|
||||
|
||||
private static final Map<Integer, String> STATUS_MAP;
|
||||
static {
|
||||
Map<Integer, String> map = new HashMap<>();
|
||||
map.put(DispenseStatus.PENDING.getCode(), "待发药");
|
||||
map.put(DispenseStatus.DISPATCHED.getCode(), "已发药");
|
||||
map.put(DispenseStatus.RETURNED.getCode(), "已退药");
|
||||
map.put(DispenseStatus.CANCELLED.getCode(), "已取消");
|
||||
// 如有新增状态,请同步在此添加
|
||||
STATUS_MAP = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
public static String getDisplayName(Integer status) {
|
||||
if (status == null) {
|
||||
return "";
|
||||
}
|
||||
return STATUS_MAP.getOrDefault(status, "");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.openhis.application.util;
|
||||
|
||||
import com.openhis.application.constants.OrderStatus;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 统一的医嘱状态中文映射工具。
|
||||
* 与《药品医嘱状态映射表》保持一一对应,所有前端展示均通过此类获取。
|
||||
*/
|
||||
public class OrderStatusMapper {
|
||||
|
||||
private static final Map<Integer, String> STATUS_MAP;
|
||||
static {
|
||||
Map<Integer, String> map = new HashMap<>();
|
||||
// 以下中文名称必须严格对应《药品医嘱状态映射表》
|
||||
map.put(OrderStatus.PENDING.getCode(), "待执行");
|
||||
map.put(OrderStatus.EXECUTED.getCode(), "已执行");
|
||||
map.put(OrderStatus.CANCELLED.getCode(), "已取消");
|
||||
map.put(OrderStatus.COMPLETED.getCode(), "已完成");
|
||||
map.put(OrderStatus.INVALID.getCode(), "已失效");
|
||||
// 如有新增状态,请同步在此添加
|
||||
STATUS_MAP = Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据状态码获取标准中文名称。
|
||||
*
|
||||
* @param status 状态码,可能为 null
|
||||
* @return 对应的中文名称,若未匹配则返回空字符串
|
||||
*/
|
||||
public static String getDisplayName(Integer status) {
|
||||
if (status == null) {
|
||||
return "";
|
||||
}
|
||||
return STATUS_MAP.getOrDefault(status, "");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user