From 260b608e838e1c7a95966b9470607d2249a4007e Mon Sep 17 00:00:00 2001 From: sa0ChunLuyu Date: Mon, 3 Aug 2026 15:09:43 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A2=84=E7=BA=A6=E5=8F=B7=E6=BA=90BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/Admin/YeWu/PlanListService.php | 117 ++++++++++-------- 1 file changed, 62 insertions(+), 55 deletions(-) diff --git a/Laravel/app/Services/Admin/YeWu/PlanListService.php b/Laravel/app/Services/Admin/YeWu/PlanListService.php index d2c843e..00ab5f0 100644 --- a/Laravel/app/Services/Admin/YeWu/PlanListService.php +++ b/Laravel/app/Services/Admin/YeWu/PlanListService.php @@ -313,7 +313,7 @@ public function GetEnablePlan($regnum, $entrustids, $episodeid, $appointment_typ $existingSharedAtPlan = []; if (!empty($regnum)) { $existingSharedItems = DB::table('s_list') - ->join('s_check_item', 's_list.entrust', '=', 's_check_item.item_name') + ->join('s_check_item', 's_list.entrust_code', '=', 's_check_item.item_code') ->where('s_list.reg_num', $regnum) ->where('s_list.list_status', 1) ->where('s_list.roster_id', '>', 0) @@ -557,7 +557,7 @@ public function GetOptimalPlan($type, $regnum, $entrustids, $episodeid, $appoint $shareSlotMap = []; if (!empty($entrustIds)) { $itemData = DB::table('s_list') - ->join('s_check_item', 's_list.entrust', '=', 's_check_item.item_name') + ->join('s_check_item', 's_list.entrust_code', '=', 's_check_item.item_code') ->whereIn('s_list.entrust_id', $entrustIds) ->select('s_list.entrust_id', 's_check_item.use_seats', 's_check_item.is_share_slot') ->get(); @@ -602,7 +602,7 @@ public function GetOptimalPlan($type, $regnum, $entrustids, $episodeid, $appoint // 查询该患者已有共享项目在各排班下的 max $existingSharedAtPlan = []; $existingSharedItems = DB::table('s_list') - ->join('s_check_item', 's_list.entrust', '=', 's_check_item.item_name') + ->join('s_check_item', 's_list.entrust_code', '=', 's_check_item.item_code') ->where('s_list.reg_num', $regnum) ->where('s_list.list_status', 1) ->where('s_list.is_nullify', 0) @@ -1108,10 +1108,10 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme //查询用户预约中的医嘱 $status_1 = DB::table('s_list') ->select('s_check_item.item_code', 's_list.entrust', 's_list.reservation_date', 's_list.reservation_time') - ->leftJoin('s_check_item', 's_list.entrust', '=', 's_check_item.item_name') + ->leftJoin('s_check_item', 's_list.entrust_code', '=', 's_check_item.item_code') ->where(['s_list.reg_num' => $mainInfo->reg_num, 's_list.list_status' => 1, 's_list.is_del' => 0, 's_list.is_nullify' => 0]) //排除自身,自己不能互斥自己 - ->whereNotIn('item_name', [$mainInfo->entrust]) + ->whereNotIn('s_list.entrust_code', [$mainInfo->entrust_code]) ->get(); if (count($status_1) > 0) { foreach ($status_1 as $key => $value) { @@ -1196,7 +1196,7 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme } - // 共享号源项目合并计算:只保留最大值,其余设为0 + // 共享号源预计算(不依赖排班数据的部分) $shareSlotIds = []; $shareSlotMax = 0; foreach ($itemSeatsData as $id => $data) { @@ -1205,28 +1205,6 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme $shareSlotMax = max($shareSlotMax, $data['use_seats']); } } - - // 查询该排班下已有共享项目的 max - $existingSharedMax = 0; - $additionalNeeded = 0; - $regNum = $oldMainInfos[0]->reg_num ?? null; - if (!empty($shareSlotIds) && $regNum) { - $existingSharedItems = DB::table('s_list') - ->join('s_check_item', 's_list.entrust', '=', 's_check_item.item_name') - ->where('s_list.reg_num', $regNum) - ->where('s_list.roster_id', $planid) - ->where('s_list.list_status', 1) - ->where('s_check_item.is_share_slot', 1) - ->select('s_check_item.use_seats') - ->get(); - if ($existingSharedItems->isNotEmpty()) { - $existingSharedMax = $existingSharedItems->max('use_seats'); - } - $overallMax = max($existingSharedMax, $shareSlotMax); - $additionalNeeded = max(0, $overallMax - $existingSharedMax); - } - - // 找到 use_seats 最高的共享项目,将 max 分配给它 $maxShareSlotId = null; $maxShareSeats = 0; foreach ($itemSeatsData as $id => $data) { @@ -1235,33 +1213,10 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme $maxShareSlotId = $id; } } - + // 以下变量在事务内计算 + $existingSharedMax = 0; + $additionalNeeded = 0; $zhanweiCount = 0; - foreach ($itemSeatsData as $id => $data) { - if (!empty($data['is_share_slot'])) { - if ($id === $maxShareSlotId) { - $itemSeatsQueue[$id] = $additionalNeeded; - $zhanweiCount += $additionalNeeded; - } else { - $itemSeatsQueue[$id] = 0; - } - } else { - $itemSeatsQueue[$id] = $data['use_seats']; - $zhanweiCount += $data['use_seats']; - } - } - - Log::info('[YuYueDebug] YuYue 预约参数', [ - 'planid' => $planid, - 'mainlistids' => $mainlistids, - 'itemSeatsData' => $itemSeatsData, - 'shareSlotMax' => $shareSlotMax, - 'existingSharedMax' => $existingSharedMax, - 'additionalNeeded' => $additionalNeeded, - 'maxShareSlotId' => $maxShareSlotId, - 'itemSeatsQueue' => $itemSeatsQueue, - 'zhanweiCount' => $zhanweiCount, - ]); DB::beginTransaction(); try { @@ -1275,6 +1230,13 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme } } $oldRosterIds = array_unique($oldRosterIds); + // 锁定旧排班渠道行,防止并发竞态 + if (!empty($oldRosterIds)) { + DB::table('s_source_roster_detail_count') + ->whereIn('roster_detail_id', $oldRosterIds) + ->lockForUpdate() + ->get(); + } } //查询号源渠道是否有合并 @@ -1292,6 +1254,49 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme ->orderBy('appointment_type_id','asc') ->lockForUpdate() // 添加行级锁 ★ 关键 ->get(); + + // === 共享号源计算(在锁保护下查询已有共享占位)=== + $regNum = $oldMainInfos[0]->reg_num ?? null; + if (!empty($shareSlotIds) && $regNum) { + $existingSharedItems = DB::table('s_list') + ->join('s_check_item', 's_list.entrust_code', '=', 's_check_item.item_code') + ->where('s_list.reg_num', $regNum) + ->where('s_list.roster_id', $planid) + ->where('s_list.list_status', 1) + ->where('s_check_item.is_share_slot', 1) + ->select('s_check_item.use_seats') + ->get(); + if ($existingSharedItems->isNotEmpty()) { + $existingSharedMax = $existingSharedItems->max('use_seats'); + } + $overallMax = max($existingSharedMax, $shareSlotMax); + $additionalNeeded = max(0, $overallMax - $existingSharedMax); + } + foreach ($itemSeatsData as $id => $data) { + if (!empty($data['is_share_slot'])) { + if ($id === $maxShareSlotId) { + $itemSeatsQueue[$id] = $additionalNeeded; + $zhanweiCount += $additionalNeeded; + } else { + $itemSeatsQueue[$id] = 0; + } + } else { + $itemSeatsQueue[$id] = $data['use_seats']; + $zhanweiCount += $data['use_seats']; + } + } + Log::info('[YuYueDebug] YuYue 预约参数', [ + 'planid' => $planid, + 'mainlistids' => $mainlistids, + 'itemSeatsData' => $itemSeatsData, + 'shareSlotMax' => $shareSlotMax, + 'existingSharedMax' => $existingSharedMax, + 'additionalNeeded' => $additionalNeeded, + 'maxShareSlotId' => $maxShareSlotId, + 'itemSeatsQueue' => $itemSeatsQueue, + 'zhanweiCount' => $zhanweiCount, + ]); + $planZongCount=0;//合并后的各个渠道总名额 $planZongUsedCount=0;//合并后的各个渠道已预约的名额 $planZongLockedCount=0;//合并后的各个渠道占位名额 @@ -1579,6 +1584,7 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme // === 号源总量校验结束 === $list_all_success = true; + $savedDataMap = []; // 记录每条项目的实际写入数据 foreach ($mainlistids as $id) { $details = []; if (isset($itemChannelMap[$id])) { @@ -1636,6 +1642,7 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme $list_all_success = false; break; } + $savedDataMap[$id] = $u_data; // 更新后读回确认 $afterUpdate = DB::table('s_list')->where('id', $id)->value('appointment_use_plan_detail'); @@ -1660,7 +1667,7 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme 'new_status' => 1, 'create_user' => $do_user, 'note' => $note, - 'data' => json_encode($u_data) + 'data' => json_encode($savedDataMap[$oldMainInfo->id] ?? []) ]); }