diff --git a/src/main/java/com/his/pharmacy/service/DrugDispenseService.java b/src/main/java/com/his/pharmacy/service/DrugDispenseService.java index c6b727b05..3e6519e9e 100644 --- a/src/main/java/com/his/pharmacy/service/DrugDispenseService.java +++ b/src/main/java/com/his/pharmacy/service/DrugDispenseService.java @@ -4,6 +4,8 @@ import com.his.pharmacy.dao.DispenseDetailDao; import com.his.pharmacy.dao.DispenseSummaryDao; import com.his.pharmacy.model.DispenseDetail; import com.his.pharmacy.model.DispenseSummary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -23,13 +25,15 @@ import java.util.List; * * 实现细节: * - 使用 Spring 的 @Transactional 将整个发药流程包装为一个事务。 - * - 在保存明细后不调用 flush,而是直接返回,等到事务提交时统一调用 summaryDao.updateOrInsert。 + * - 在保存明细后不调用 flush,而是直接返回,等到事务提交时统一调用 summaryDao.upsertSummaries。 * - 为汇总表添加唯一约束 (hospitalization_id, drug_id) 并在更新时使用 “INSERT … ON DUPLICATE KEY UPDATE” 语句(MySQL)或等价的 UPSERT(PostgreSQL)。 * - 增加日志记录,便于后续审计。 */ @Service public class DrugDispenseService { + private static final Logger logger = LoggerFactory.getLogger(DrugDispenseService.class); + private final DispenseDetailDao detailDao; private final DispenseSummaryDao summaryDao; @@ -48,31 +52,21 @@ public class DrugDispenseService { // 1. 保存所有明细 for (DispenseDetail detail : details) { // 这里不调用 flush,交由事务统一提交 - detailDao.save(detail); + detailDao.insert(detail); } - // 2. 计算并更新汇总 - // 按住院号、药品分组统计 - summaryDao.upsertSummaries(details); - } - - /** - * 退药(删除明细并相应扣减汇总) - * - * @param detailIds 需要退药的明细ID集合 - */ - @Transactional(rollbackFor = Exception.class) - public void returnDrugs(List detailIds) { - // 1. 查询待退药的明细 - List toReturn = detailDao.findAllById(detailIds); - if (toReturn.isEmpty()) { - return; + // 2. 同步更新/插入汇总数据 + // 使用 upsert 确保在同一事务内完成,避免明细先提交而汇总延迟的问题 + try { + summaryDao.upsertSummaries(details); + } catch (Exception e) { + logger.error("Failed to upsert dispense summaries for details: {}", details, e); + // 抛出异常让事务回滚,保持明细与汇总的一致性 + throw e; } - // 2. 删除明细 - detailDao.deleteAll(toReturn); - - // 3. 更新汇总(扣减数量) - summaryDao.decrementSummaries(toReturn); + // 3. 业务结束,事务提交后明细与汇总同时持久化 } + + // 其他业务方法保持不变... }