|
|
|
@ -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;
|
|
|
|
DB::table('s_source_roster_detail_count')
|
|
|
|
}
|
|
|
|
->where('id', $cid)
|
|
|
|
}
|
|
|
|
->update(['used_count' => $channelUsed, 'version' => DB::raw('version + 1')]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 共享号源比例缩放:渠道累加值与分组总量不一致时,按比例校正
|
|
|
|
|
|
|
|
$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')
|
|
|
|
|
|
|
|
->where('id', $cid)
|
|
|
|
|
|
|
|
->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;
|
|
|
|
|