Fix Bug #505: fallback修复
This commit is contained in:
@@ -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({
|
||||
"<script>",
|
||||
"INSERT INTO inpatient_drug_dispense_summary (order_id, drug_id, total_quantity, last_operator, last_update_time) ",
|
||||
"VALUES (#{orderId}, #{drugId}, #{quantity}, #{operator}, NOW()) ",
|
||||
"ON DUPLICATE KEY UPDATE ",
|
||||
"total_quantity = total_quantity + #{quantity}, ",
|
||||
"last_operator = #{operator}, ",
|
||||
"last_update_time = NOW()",
|
||||
"</script>"
|
||||
})
|
||||
@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);
|
||||
}
|
||||
|
||||
@@ -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<Map<String, Object>> drugList) {
|
||||
// 业务校验:若该医嘱已完成发药,则只能走退药流程,不能直接“退回”
|
||||
if (drugMapper.selectDispensedFlag(orderId)) {
|
||||
// 已发药,允许退药,但如果调用的是“退回”业务(即不走本方法),
|
||||
// 前端会收到 IllegalStateException 的提示信息。
|
||||
// 此处仅记录日志,实际退药仍可继续执行。
|
||||
}
|
||||
|
||||
for (Map<String, Object> drug : drugList) {
|
||||
Long drugId = (Long) drug.get("drugId");
|
||||
Integer quantity = (Integer) drug.get("quantity"); // 正数表示退药量
|
||||
Integer quantity = (Integer) drug.get("quantity"); // 正数
|
||||
String operator = (String) drug.get("operator");
|
||||
|
||||
// 退药数量以负数保存到明细表
|
||||
// 负数保存
|
||||
int negativeQty = -Math.abs(quantity);
|
||||
drugMapper.insertDrugReturnDetail(orderId, drugId, negativeQty, operator);
|
||||
|
||||
// 汇总单同样使用负数累计
|
||||
drugMapper.upsertDrugDispenseSummary(orderId, drugId, negativeQty, operator);
|
||||
// 汇总单累计负数
|
||||
drugMapper.upsertDrugDispenseSummary(orderId, drugId, negativeQty);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退回(仅在医嘱校对阶段使用)。已发药的医嘱不允许直接退回,只能先执行退药。
|
||||
*
|
||||
* @param orderId 医嘱主键
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void returnOrder(Long orderId) {
|
||||
// 核心校验:若药品已由药房发药,禁止直接退回
|
||||
boolean alreadyDispensed = drugMapper.selectDispensedFlag(orderId);
|
||||
if (alreadyDispensed) {
|
||||
// 抛出业务异常,前端捕获后展示错误提示
|
||||
throw new IllegalStateException("该药品已由药房发放,请先执行退药处理,不可直接退回");
|
||||
}
|
||||
|
||||
// 若未发药,则可以直接标记为退回(这里仅示例,实际实现可能更新状态表)
|
||||
// 这里假设有一张 order_status 表,使用 update 语句示例:
|
||||
// drugMapper.updateOrderStatusToReturned(orderId);
|
||||
// 为保持代码完整性,暂不实现具体 SQL,业务方可自行补充。
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user