Fix Bug #503: fallback修复
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package com.openhis.web.inpatient.service;
|
||||
|
||||
import com.openhis.web.inpatient.mapper.DispensingDetailMapper;
|
||||
import com.openhis.web.inpatient.mapper.DispensingSummaryMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 住院发退药业务实现
|
||||
*
|
||||
* 修复 Bug #503:发药明细与发药汇总单的触发时机不一致导致业务脱节风险。
|
||||
*
|
||||
* 解决思路:
|
||||
* 1. 将发药明细的写入与发药汇总单的生成放在同一个事务中,确保两者要么同时成功,要么同时回滚。
|
||||
* 2. 在写入明细后立即查询已写入的明细行数,只有在明细写入成功且行数大于 0 时才生成汇总单。
|
||||
* 3. 将生成汇总单的 SQL 改为基于已写入的明细数据进行聚合,而不是基于旧的业务状态字段,避免因状态延迟导致汇总单提前生成。
|
||||
* 4. 为防止并发冲突,在生成汇总单时使用行级锁 (FOR UPDATE) 锁定相关明细记录。
|
||||
*/
|
||||
@Service
|
||||
public class DispensingServiceImpl implements DispensingService {
|
||||
|
||||
private final DispensingDetailMapper dispensingDetailMapper;
|
||||
private final DispensingSummaryMapper dispensingSummaryMapper;
|
||||
|
||||
public DispensingServiceImpl(DispensingDetailMapper dispensingDetailMapper,
|
||||
DispensingSummaryMapper dispensingSummaryMapper) {
|
||||
this.dispensingDetailMapper = dispensingDetailMapper;
|
||||
this.dispensingSummaryMapper = dispensingSummaryMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发药操作,包含明细写入和汇总单生成,保持事务原子性。
|
||||
*
|
||||
* @param orderId 住院医嘱主键
|
||||
* @param drugList 发药明细列表,每条包含 drugId、quantity 等信息
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void dispense(Long orderId, List<Map<String, Object>> drugList) {
|
||||
if (orderId == null || drugList == null || drugList.isEmpty()) {
|
||||
throw new IllegalArgumentException("发药参数缺失或明细为空");
|
||||
}
|
||||
|
||||
// 1. 写入发药明细
|
||||
for (Map<String, Object> drug : drugList) {
|
||||
drug.put("orderId", orderId);
|
||||
dispensingDetailMapper.insertDetail(drug);
|
||||
}
|
||||
|
||||
// 2. 确认明细已写入(行锁防并发)
|
||||
List<Map<String, Object>> writtenDetails = dispensingDetailMapper.selectDetailsForOrderForUpdate(orderId);
|
||||
if (writtenDetails == null || writtenDetails.isEmpty()) {
|
||||
throw new IllegalStateException("发药明细写入失败,无法生成汇总单");
|
||||
}
|
||||
|
||||
// 3. 基于已写入的明细聚合生成汇总单
|
||||
Map<String, Object> summary = dispensingSummaryMapper.calculateSummaryFromDetails(orderId);
|
||||
if (summary == null || summary.isEmpty()) {
|
||||
throw new IllegalStateException("汇总单计算失败");
|
||||
}
|
||||
|
||||
// 4. 写入汇总单
|
||||
dispensingSummaryMapper.insertSummary(summary);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user