From 820866b30eeca2db6de37e7347d461a1e5e7e4ee Mon Sep 17 00:00:00 2001 From: sa0ChunLuyu Date: Mon, 3 Aug 2026 15:48:15 +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 | 99 +++++++++---------- 1 file changed, 44 insertions(+), 55 deletions(-) diff --git a/Laravel/app/Services/Admin/YeWu/PlanListService.php b/Laravel/app/Services/Admin/YeWu/PlanListService.php index 00ab5f0..4337973 100644 --- a/Laravel/app/Services/Admin/YeWu/PlanListService.php +++ b/Laravel/app/Services/Admin/YeWu/PlanListService.php @@ -1465,61 +1465,7 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme } - //更新计划明细表使用数量(使用乐观锁) - $up_plan_count_all_success = true; - $versionMismatchIds = []; - foreach ($roster_detail_counts as $key => $planCount) { - $countToDeduct = $plan_qudao_tempCount[$key]; - if ($countToDeduct == 0) continue; - - if ($is_emergency !== 1) { - $affected = DB::table('s_source_roster_detail_count') - ->where(['id' => $planCount->id, 'version' => $planCount->version]) - ->whereRaw('count >= (used_count + IFNULL(locked_count, 0) + ?)', [$countToDeduct]) - ->update([ - 'used_count' => DB::raw('used_count + ' . $countToDeduct), - 'version' => DB::raw('version + 1'), - 'updated_at' => date('Y-m-d H:i:s') - ]); - } else { - $affected = DB::table('s_source_roster_detail_count') - ->where(['id' => $planCount->id, 'version' => $planCount->version]) - ->update([ - 'used_count' => DB::raw('used_count + ' . $countToDeduct), - 'version' => DB::raw('version + 1'), - 'updated_at' => date('Y-m-d H:i:s') - ]); - if ($affected == 0) { - $check = DB::table('s_source_roster_detail_count')->find($planCount->id); - if (!$check) { - $up_plan_count_all_success = false; - break; - } - $affected = DB::table('s_source_roster_detail_count') - ->where(['id' => $planCount->id]) - ->update([ - 'used_count' => DB::raw('used_count + ' . $countToDeduct), - 'version' => DB::raw('version + 1'), - 'updated_at' => date('Y-m-d H:i:s') - ]); - } - } - - if ($affected == 0 && $is_emergency !== 1) { - $versionMismatchIds[] = $planCount->id; - $up_plan_count_all_success = false; - } - } - - if (!$up_plan_count_all_success && $is_emergency !== 1) { - if (count($versionMismatchIds) > 0) { - Log::warning("预约乐观锁冲突", ['planid' => $planid, 'conflict_ids' => $versionMismatchIds]); - throw new \Exception('号源数据已被其他用户修改,请刷新后重试'); - } - throw new \Exception('名额不足,扣减失败'); - } - - // === 号源总量校验(扣减后、更新s_list前)=== + // === 号源总量校验 + 精确扣减(替换原乐观锁扣减)=== // 加急预约允许超量,跳过总量校验 if ($is_emergency !== 1) { // 校验①:合并渠道总额校验(计数器维度) @@ -1583,6 +1529,49 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme } // end if ($is_emergency !== 1) // === 号源总量校验结束 === + // === 精确扣减号源占位(在 lockForUpdate 和总量校验之后)=== + // 按实际占位逻辑(共享取max、非共享累加)分配到各渠道,逐渠道扣减 used_count + $channelDeduct = []; + foreach ($itemChannelMap as $mid => $channels) { + $useSeats = $itemSeatsQueue[$mid] ?? 0; + if ($useSeats <= 0) continue; + foreach ($channels as $cId => $cnt) { + $channelDeduct[$cId] = ($channelDeduct[$cId] ?? 0) + $cnt; + } + } + foreach ($channelDeduct as $cId => $deductCount) { + if ($deductCount <= 0) continue; + $channelInfo = null; + foreach ($roster_detail_counts as $rc) { + if ($rc->id == $cId) { $channelInfo = $rc; break; } + } + if (!$channelInfo) { + throw new \Exception('号源扣减失败:渠道不存在(id=' . $cId . ')'); + } + // 加急预约允许超量,不校验单渠道上限 + if ($is_emergency !== 1) { + $afterDeduct = $channelInfo->used_count + $deductCount; + if ($afterDeduct > $channelInfo->count) { + Log::warning('号源单渠道超限', [ + 'planid' => $planid, + 'channelId' => $cId, + 'used_count' => $channelInfo->used_count, + 'deductCount' => $deductCount, + 'count' => $channelInfo->count, + ]); + throw new \Exception('号源不足,渠道容量' . $channelInfo->count . ',已用' . $channelInfo->used_count . ',本次需' . $deductCount); + } + } + DB::table('s_source_roster_detail_count') + ->where('id', $cId) + ->update([ + 'used_count' => DB::raw('used_count + ' . $deductCount), + 'version' => DB::raw('version + 1'), + 'updated_at' => date('Y-m-d H:i:s') + ]); + } + // === 精确扣减结束 === + $list_all_success = true; $savedDataMap = []; // 记录每条项目的实际写入数据 foreach ($mainlistids as $id) {