预约号源BUG

main
鹿和sa0ChunLuyu 2 days ago
parent bd872eac2a
commit b68389244b

@ -1514,6 +1514,70 @@ public function YuYue($planid, $appointment_type, $mainlistids, $do_type,$is_eme
throw new \Exception('名额不足,扣减失败'); throw new \Exception('名额不足,扣减失败');
} }
// === 号源总量校验扣减后、更新s_list前===
// 加急预约允许超量,跳过总量校验
if ($is_emergency !== 1) {
// 校验①:合并渠道总额校验(计数器维度)
$afterCounts = DB::table('s_source_roster_detail_count')
->where('roster_detail_id', $planid)
->whereIn('appointment_type_id', $appointment_types)
->get();
$totalCountChannel = $afterCounts->sum('count');
$totalUsedChannel = $afterCounts->sum('used_count');
if ($totalUsedChannel > $totalCountChannel) {
Log::warning('号源总额超限-计数器维度', [
'planid' => $planid,
'totalCount' => $totalCountChannel,
'totalUsed' => $totalUsedChannel,
]);
throw new \Exception('号源总数不足,总容量' . $totalCountChannel . ',已用' . $totalUsedChannel);
}
// 校验②从s_list实际记录校验实际记录维度
// 复用correctUsedCount的分组算法按患者分组共享取max非共享累加
$activeItems = DB::table('s_list')
->leftJoin('s_check_item', 's_list.entrust_code', '=', 's_check_item.item_code')
->where('s_list.roster_id', $planid)
->whereIn('s_list.list_status', [1, 2, 3])
->where('s_list.is_nullify', 0)
->where('s_list.is_del', 0)
// 改约时排除本次操作的记录此时list_status仍为1即将被改到新排班
->when($do_type == 2, function($q) use ($mainlistids) {
$q->whereNotIn('s_list.id', $mainlistids);
})
->select('s_list.*', 's_check_item.use_seats', 's_check_item.is_share_slot')
->get();
$grouped = [];
foreach ($activeItems as $item) {
$reg = $item->reg_num;
if (!isset($grouped[$reg])) {
$grouped[$reg] = ['sharedMax' => 0, 'nonSharedSum' => 0];
}
if (!empty($item->is_share_slot)) {
$grouped[$reg]['sharedMax'] = max($grouped[$reg]['sharedMax'], (int)($item->use_seats ?? 1));
} else {
$grouped[$reg]['nonSharedSum'] += (int)($item->use_seats ?? 1);
}
}
$actualUsed = 0;
foreach ($grouped as $reg => $g) {
$actualUsed += $g['sharedMax'] + $g['nonSharedSum'];
}
// 本次新增占位量(已含共享减去已有占位的逻辑)
$totalAfterActual = $actualUsed + $zhanweiCount;
if ($totalAfterActual > $totalCountChannel) {
Log::warning('号源总额超限-实际记录维度', [
'planid' => $planid,
'actualUsed' => $actualUsed,
'zhanweiCount' => $zhanweiCount,
'totalAfter' => $totalAfterActual,
'totalCount' => $totalCountChannel,
]);
throw new \Exception('号源已约满,当前已约' . $actualUsed . ',本次新增' . $zhanweiCount . ',总容量' . $totalCountChannel);
}
} // end if ($is_emergency !== 1)
// === 号源总量校验结束 ===
$list_all_success = true; $list_all_success = true;
foreach ($mainlistids as $id) { foreach ($mainlistids as $id) {
$details = []; $details = [];
@ -1894,8 +1958,6 @@ public function correctUsedCount($rosterId)
// 计算总占位:按人隔离,共享取 max非共享累加 // 计算总占位:按人隔离,共享取 max非共享累加
$grouped = []; $grouped = [];
$firstDetail = null;
foreach ($activeItems as $item) { foreach ($activeItems as $item) {
$reg = $item->reg_num; $reg = $item->reg_num;
if (!isset($grouped[$reg])) { if (!isset($grouped[$reg])) {
@ -1906,13 +1968,6 @@ public function correctUsedCount($rosterId)
} else { } else {
$grouped[$reg]['nonSharedSum'] += (int)($item->use_seats ?? 1); $grouped[$reg]['nonSharedSum'] += (int)($item->use_seats ?? 1);
} }
// 记录第一个有 detail 的渠道
if ($firstDetail === null) {
$details = json_decode($item->appointment_use_plan_detail, true) ?: [];
if (!empty($details)) {
$firstDetail = $details;
}
}
} }
$totalUsed = 0; $totalUsed = 0;
@ -1920,24 +1975,48 @@ public function correctUsedCount($rosterId)
$totalUsed += $g['sharedMax'] + $g['nonSharedSum']; $totalUsed += $g['sharedMax'] + $g['nonSharedSum'];
} }
// 按渠道分配占位 // 按渠道分配占位:遍历所有记录的 appointment_use_plan_detail 逐条累加
if ($firstDetail && $totalUsed > 0) { $channelTotals = [];
$totalDetailCount = array_sum(array_column($firstDetail, 'count')); foreach ($activeItems as $item) {
foreach ($firstDetail as $d) { $details = json_decode($item->appointment_use_plan_detail, true) ?: [];
foreach ($details as $d) {
$cid = $d['roster_detail_count_id'] ?? null; $cid = $d['roster_detail_count_id'] ?? null;
if (!$cid) continue; $cnt = (int)($d['count'] ?? 0);
$ratio = $totalDetailCount > 0 ? ($d['count'] / $totalDetailCount) : 0; if ($cid && $cnt > 0) {
$channelUsed = (int)round($totalUsed * $ratio); $channelTotals[$cid] = ($channelTotals[$cid] ?? 0) + $cnt;
}
}
}
// 共享号源比例缩放:渠道累加值与分组总量不一致时,按比例校正
$channelSum = array_sum($channelTotals);
if ($channelSum > 0 && $channelSum != $totalUsed) {
$scale = $totalUsed / $channelSum;
foreach ($channelTotals as $cid => $val) {
$channelTotals[$cid] = (int)round($val * $scale);
}
// 处理舍入误差
$afterScaleSum = array_sum($channelTotals);
if ($afterScaleSum != $totalUsed && !empty($channelTotals)) {
$diff = $totalUsed - $afterScaleSum;
$maxCid = array_keys($channelTotals, max($channelTotals))[0];
$channelTotals[$maxCid] += $diff;
}
}
// 写回各渠道
foreach ($channelTotals as $cid => $used) {
if ($used <= 0) continue;
DB::table('s_source_roster_detail_count') DB::table('s_source_roster_detail_count')
->where('id', $cid) ->where('id', $cid)
->update(['used_count' => $channelUsed, 'version' => DB::raw('version + 1')]); ->update(['used_count' => $used, 'version' => DB::raw('version + 1')]);
}
} }
Log::info('[YuYueDebug] 校正号源', [ Log::info('[YuYueDebug] 校正号源', [
'rosterId' => $rosterId, 'rosterId' => $rosterId,
'grouped' => $grouped, 'grouped' => $grouped,
'totalUsed' => $totalUsed, 'totalUsed' => $totalUsed,
'channelTotals' => $channelTotals,
'activeItemCount' => $activeItems->count(), 'activeItemCount' => $activeItems->count(),
]); ]);
} }
@ -1990,7 +2069,6 @@ public function calculateUsedCount($rosterId, $correct = 0)
// 按患者分组计算占位 // 按患者分组计算占位
$grouped = []; $grouped = [];
$firstDetail = null;
foreach ($activeItems as $item) { foreach ($activeItems as $item) {
$reg = $item->reg_num; $reg = $item->reg_num;
@ -2024,14 +2102,6 @@ public function calculateUsedCount($rosterId, $correct = 0)
'use_seats' => $seats, 'use_seats' => $seats,
]; ];
} }
// 记录第一个有 detail 的渠道
if ($firstDetail === null) {
$details = json_decode($item->appointment_use_plan_detail, true) ?: [];
if (!empty($details)) {
$firstDetail = $details;
}
}
} }
// 计算总占位 // 计算总占位
@ -2049,17 +2119,38 @@ public function calculateUsedCount($rosterId, $correct = 0)
]; ];
} }
// 按渠道分配计算 // 按渠道分配计算:遍历所有记录的 appointment_use_plan_detail 逐条累加
$channelCalculated = []; $channelTotals = [];
$hasDiff = false; foreach ($activeItems as $item) {
if ($firstDetail && $totalUsed > 0) { $details = json_decode($item->appointment_use_plan_detail, true) ?: [];
$totalDetailCount = array_sum(array_column($firstDetail, 'count')); foreach ($details as $d) {
foreach ($firstDetail as $d) {
$cid = $d['roster_detail_count_id'] ?? null; $cid = $d['roster_detail_count_id'] ?? null;
if (!$cid) continue; $cnt = (int)($d['count'] ?? 0);
$ratio = $totalDetailCount > 0 ? ($d['count'] / $totalDetailCount) : 0; if ($cid && $cnt > 0) {
$channelUsed = (int)round($totalUsed * $ratio); $channelTotals[$cid] = ($channelTotals[$cid] ?? 0) + $cnt;
}
}
}
// 共享号源比例缩放
$channelSum = array_sum($channelTotals);
if ($channelSum > 0 && $channelSum != $totalUsed) {
$scale = $totalUsed / $channelSum;
foreach ($channelTotals as $cid => $val) {
$channelTotals[$cid] = (int)round($val * $scale);
}
$afterScaleSum = array_sum($channelTotals);
if ($afterScaleSum != $totalUsed && !empty($channelTotals)) {
$diff = $totalUsed - $afterScaleSum;
$maxCid = array_keys($channelTotals, max($channelTotals))[0];
$channelTotals[$maxCid] += $diff;
}
}
$channelCalculated = [];
$hasDiff = false;
if (!empty($channelTotals)) {
foreach ($channelTotals as $cid => $channelUsed) {
$current = $channels->firstWhere('id', $cid); $current = $channels->firstWhere('id', $cid);
$currentUsed = $current ? (int)$current->used_count : 0; $currentUsed = $current ? (int)$current->used_count : 0;
$diff = $channelUsed - $currentUsed; $diff = $channelUsed - $currentUsed;

Loading…
Cancel
Save