diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/mapper/InpatientDrugMapper.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/mapper/InpatientDrugMapper.java
index 7f9d034c5..5edebc398 100644
--- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/mapper/InpatientDrugMapper.java
+++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/mapper/InpatientDrugMapper.java
@@ -12,8 +12,9 @@ import java.util.Map;
* 2. insertDrugReturnDetail – 插入退药明细(负向数量)。
* 3. upsertDrugDispenseSummary – 汇总单 UPSERT(INSERT … ON DUPLICATE KEY UPDATE),
* 用于累计正负数量,保持明细与汇总的一致性。
+ * 4. selectDispensedFlag – 查询医嘱是否已完成发药(用于“退回”业务校验)。
*
- * 通过上述三条 SQL,业务层在同一事务内先写明细再写汇总,彻底消除
+ * 通过上述四条 SQL,业务层在同一事务内先写明细再写汇总,彻底消除
* “发药明细与汇总单触发时机不一致” 的风险。
*/
@Mapper
@@ -52,26 +53,31 @@ public interface InpatientDrugMapper {
@Param("operator") String operator);
/**
- * 汇总单 UPSERT:如果已存在对应 order_id、drug_id 的汇总记录,则累计 quantity;
- * 否则插入新记录。此方法用于在同一事务内保持明细与汇总的一致性。
+ * 汇总单 UPSERT:累计正负数量
*
* @param orderId 医嘱ID
* @param drugId 药品ID
- * @param quantity 本次操作的数量(正数为发药,负数为退药)
- * @param operator 操作人
+ * @param quantity 本次操作数量(正数为发药,负数为退药)
*/
- @Insert({
- ""
- })
+ @Insert("INSERT INTO inpatient_drug_dispense_summary " +
+ "(order_id, drug_id, total_quantity, last_update) " +
+ "VALUES (#{orderId}, #{drugId}, #{quantity}, NOW()) " +
+ "ON DUPLICATE KEY UPDATE " +
+ "total_quantity = total_quantity + #{quantity}, " +
+ "last_update = NOW()")
int upsertDrugDispenseSummary(@Param("orderId") Long orderId,
@Param("drugId") Long drugId,
- @Param("quantity") Integer quantity,
- @Param("operator") String operator);
+ @Param("quantity") Integer quantity);
+
+ /**
+ * 查询医嘱是否已完成发药(即汇总单中正向数量大于 0 且无未退药的负向数量)。
+ *
+ * @param orderId 医嘱ID
+ * @return true 已发药,false 未发药
+ */
+ @Select("SELECT EXISTS(" +
+ "SELECT 1 FROM inpatient_drug_dispense_summary " +
+ "WHERE order_id = #{orderId} AND total_quantity > 0" +
+ ")")
+ boolean selectDispensedFlag(@Param("orderId") Long orderId);
}
diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/InpatientDrugServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/InpatientDrugServiceImpl.java
index f5395fd02..274215347 100644
--- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/InpatientDrugServiceImpl.java
+++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/inpatient/service/impl/InpatientDrugServiceImpl.java
@@ -24,10 +24,15 @@ import java.util.Map;
* 3. 对于退药操作,同样遵循“先明细后汇总”的顺序,并在汇总时使用
* 正负数量进行累计,避免出现负库存或统计错误。
*
- * 该实现依赖 InpatientDrugMapper 中新增的两条 SQL:
+ * 该实现依赖 InpatientDrugMapper 中新增的四条 SQL:
* - insertDrugDispenseDetail(...)
+ * - insertDrugReturnDetail(...)
* - upsertDrugDispenseSummary(...)
- * 若对应 Mapper 尚未同步,请参考 Mapper 注释进行相应添加。
+ * - selectDispensedFlag(...)
+ *
+ * 另外,新增退回(Return)业务校验:已发药的医嘱在“医嘱校对”模块
+ * 只能执行“退药”而不能直接“退回”。若前端尝试调用 returnDrugs,
+ * 本方法会抛出 IllegalStateException,前端捕获后展示错误信息。
*/
@Service
public class InpatientDrugServiceImpl implements InpatientDrugService {
@@ -49,35 +54,58 @@ public class InpatientDrugServiceImpl implements InpatientDrugService {
Long drugId = (Long) drug.get("drugId");
Integer quantity = (Integer) drug.get("quantity");
String operator = (String) drug.get("operator");
-
- // 插入明细(正向数量)
drugMapper.insertDrugDispenseDetail(orderId, drugId, quantity, operator);
-
- // 更新/插入汇总单,使用相同的数量(正数)
- drugMapper.upsertDrugDispenseSummary(orderId, drugId, quantity, operator);
+ // 2. 同步更新/插入汇总单(正向数量)
+ drugMapper.upsertDrugDispenseSummary(orderId, drugId, quantity);
}
}
/**
- * 退药(数量为负数)
+ * 退药(负向数量)
*
* @param orderId 医嘱主键
- * @param drugList 每种药品的退药信息,键包括 drugId、quantity(正数表示退药量)、operator 等
+ * @param drugList 每种药品的退药信息,quantity 为正数(内部转为负数保存)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void returnDrugs(Long orderId, List