join('park_number as pn', 'p.park_id', '=', 'pn.park_id') // 旧: join('ptype as pt', 'pn.ptype_id', '=', 'pt.ptype_id') ->leftJoin('psection as ps', 'pn.psection_id', '=', 'ps.psection_id') // ✅ 新しい車種取得方法 ->select([ 'p.park_id', 'p.park_name', // 'pt.ptype_id', // 'pt.ptype_subject', 'ps.psection_subject', // 車種(psection_subject)に変更 // 限界収容台数 'pn.park_limit', // 現在収容台数 \DB::raw('COALESCE(pn.park_number, 0) as current_count'), // 空き = 収容上限 - 現在 \DB::raw('GREATEST(0, COALESCE(pn.park_limit, 0) - COALESCE(pn.park_number, 0)) as available'), // 利用率 = 現在 / 上限 * 100 \DB::raw("CASE WHEN COALESCE(pn.park_limit, 0) > 0 THEN ROUND((COALESCE(pn.park_number, 0) / pn.park_limit) * 100, 1) ELSE 0 END as usage_rate"), ]) ->where('p.park_close_flag', '!=', 1); if (!empty($parkId)) { $query->where('p.park_id', $parkId); } $results = $query // 表示順:自転車 → 原付 → その他 ->orderByRaw("CASE ps.psection_subject WHEN '自転車' THEN 1 WHEN '原付' THEN 2 ELSE 3 END") ->orderBy('p.park_name') ->get(); return $results; } /** * 駐輪場一覧を取得(選択用) */ public function getParkList(): Collection { return Park::select('park_id', 'park_name') ->where('park_close_flag', '!=', 1) ->orderBy('park_name') ->get(); } /** * 合計行の計算 * * @param Collection $stats * @return array{total_limit:int,total_current:int,total_available:int,total_usage_rate:float} */ public function calculateTotals(Collection $stats): array { $totalLimit = (int) $stats->sum('park_limit'); $totalCurrent = (int) $stats->sum('current_count'); $totalAvailable = $totalLimit - $totalCurrent; $totalUsageRate = $totalLimit > 0 ? round(($totalCurrent / $totalLimit * 100), 1) : 0.0; return [ 'total_limit' => $totalLimit, 'total_current' => $totalCurrent, 'total_available' => $totalAvailable, 'total_usage_rate' => $totalUsageRate, ]; } }