diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/mapper/DispensingDetailMapper.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/mapper/DispensingDetailMapper.java
new file mode 100644
index 000000000..047c3a5d3
--- /dev/null
+++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/mapper/DispensingDetailMapper.java
@@ -0,0 +1,37 @@
+package com.openhis.web.inpatient.mapper;
+
+import org.apache.ibatis.annotations.*;
+
+import java.util.Map;
+
+/**
+ * 住院发药明细 Mapper
+ *
+ * 新增:
+ * 1. insertDetail – 插入单条发药明细
+ * 2. countByOrderIdForUpdate – 统计指定医嘱的明细数量并加行级锁,确保后续汇总在同一事务内读取到最新数据
+ */
+@Mapper
+public interface DispensingDetailMapper {
+
+ /**
+ * 插入发药明细记录
+ *
+ * @param detail 包含 orderId、drug_id、quantity、price 等字段的 map
+ * @return 受影响行数
+ */
+ @Insert("")
+ int insertDetail(@Param("detail") Map detail);
+
+ /**
+ * 统计指定医嘱的明细数量并加行级锁(FOR UPDATE),用于在同一事务中安全生成汇总单。
+ *
+ * @param orderId 医嘱主键
+ * @return 明细行数
+ */
+ @Select("SELECT COUNT(*) FROM dispensing_detail WHERE order_id = #{orderId} FOR UPDATE")
+ int countByOrderIdForUpdate(@Param("orderId") Long orderId);
+}
diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/mapper/DispensingSummaryMapper.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/mapper/DispensingSummaryMapper.java
new file mode 100644
index 000000000..5d16043f7
--- /dev/null
+++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/mapper/DispensingSummaryMapper.java
@@ -0,0 +1,39 @@
+package com.openhis.web.inpatient.mapper;
+
+import org.apache.ibatis.annotations.*;
+
+import java.util.Map;
+
+/**
+ * 住院发药汇总单 Mapper
+ *
+ * 新增:
+ * 1. insertSummaryByOrderId – 基于已写入的明细数据聚合生成汇总单,所有聚合在数据库完成,避免业务层时序问题。
+ */
+@Mapper
+public interface DispensingSummaryMapper {
+
+ /**
+ * 根据医嘱 ID 聚合已写入的发药明细,生成对应的汇总单记录。
+ *
+ * 汇总字段示例(实际字段请依据业务表结构):
+ * - order_id
+ * - total_quantity (SUM(quantity))
+ * - total_amount (SUM(quantity * price))
+ * - created_at
+ *
+ * @param orderId 医嘱主键
+ * @return 受影响行数
+ */
+ @Insert("")
+ int insertSummaryByOrderId(@Param("orderId") Long orderId);
+}
diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/DispensingServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/DispensingServiceImpl.java
index e902d21ac..b89305044 100644
--- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/DispensingServiceImpl.java
+++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/DispensingServiceImpl.java
@@ -44,25 +44,21 @@ public class DispensingServiceImpl implements DispensingService {
throw new IllegalArgumentException("发药参数缺失或明细为空");
}
- // 1. 写入发药明细
+ // 1. 写入发药明细(每条明细都在同一事务中)
for (Map drug : drugList) {
drug.put("orderId", orderId);
dispensingDetailMapper.insertDetail(drug);
}
- // 2. 确认明细已写入(行锁防并发)
- List