From 3d825364046a8418e13e187d80dba341c2afa114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=A0=E7=9A=84=E5=90=8D=E5=AD=97?= <你的邮箱> Date: Wed, 1 Oct 2025 12:00:32 +0900 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=8C=BA=E7=94=BB=E5=88=A5=E5=88=A9?= =?UTF-8?q?=E7=94=A8=E7=8E=87=E7=8A=B6=E6=B3=81=E3=80=91=E3=83=87=E3=83=BC?= =?UTF-8?q?=E3=82=BF=E5=8F=96=E5=BE=97=E5=85=83=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Admin/UsingStatusController.php | 80 +++++-------------- app/Services/UsingStatusService.php | 54 ++++++------- .../views/admin/using_status/index.blade.php | 44 +++++----- 3 files changed, 64 insertions(+), 114 deletions(-) diff --git a/app/Http/Controllers/Admin/UsingStatusController.php b/app/Http/Controllers/Admin/UsingStatusController.php index 16f67bf..dac10fc 100644 --- a/app/Http/Controllers/Admin/UsingStatusController.php +++ b/app/Http/Controllers/Admin/UsingStatusController.php @@ -38,76 +38,36 @@ class UsingStatusController extends Controller public function index(Request $request, UsingStatusService $service) { try { - // CSRF トークンの自動検証(Laravel 12標準機能) - - // リクエストパラメータの取得 - // Laravel 12変更点:$request->input()の使用を推奨 - $parkId = $request->input('park_id', null); - $isSearchRequest = $request->has('search') || $request->isMethod('post'); - - // ログ出力(デバッグ用) - Log::info('区画別利用率状況ページアクセス', [ - 'park_id' => $parkId, - 'is_search' => $isSearchRequest, - 'method' => $request->method() - ]); - - // 駐輪場一覧の取得(選択用ドロップダウン) + $parkId = $request->input('park_id'); // GET/POST どちらでも取得 $parkList = $service->getParkList(); - // 利用率統計データの取得 - // Laravel 12変更点:デフォルトで全データを表示(ユーザー選択不要) - $utilizationStats = $service->getUtilizationStats($parkId); - - // データが空の場合の処理 - if ($utilizationStats->isEmpty() && $parkId) { - // 指定された駐輪場のデータが見つからない場合 - return redirect()->route('using_status') - ->with('warning', '選択された駐輪場のデータが見つかりませんでした。'); + // 駐輪場が選択されている場合のみ取得。「全て/空」の場合は空コレクションを返す + $utilizationStats = collect(); + if ($parkId !== null && $parkId !== '') { + $utilizationStats = $service->getUtilizationStats($parkId); } - // 検索要求でない場合は全データを表示 - if (!$isSearchRequest && !$parkId) { - $utilizationStats = $service->getUtilizationStats(null); - } - - // 合計値の計算 $totals = $service->calculateTotals($utilizationStats); + $hasData = $utilizationStats->isNotEmpty(); + $isSearchRequest = ($request->isMethod('post') || $request->has('park_id')); + $selectedPark = $parkList->firstWhere('park_id', $parkId); - // 選択された駐輪場の情報 - $selectedPark = null; - if ($parkId && $parkList->isNotEmpty()) { - $selectedPark = $parkList->firstWhere('park_id', $parkId); - } - - // ビューに渡すデータの準備 - $viewData = [ - 'parkList' => $parkList, // 駐輪場選択用リスト - 'utilizationStats' => $utilizationStats, // 利用率統計データ - 'totals' => $totals, // 合計値 - 'selectedParkId' => $parkId, // 選択された駐輪場ID - 'selectedPark' => $selectedPark, // 選択された駐輪場情報 - 'isSearchRequest' => $isSearchRequest, // 検索リクエストかどうか - 'hasData' => $utilizationStats->isNotEmpty() // データが存在するかどうか - ]; - - // 成功メッセージの設定(検索時) - if ($isSearchRequest && $utilizationStats->isNotEmpty()) { - session()->flash('success', '利用率データを正常に取得しました。'); - } - - return view('admin.using_status.index', $viewData); - + return view('admin.using_status.index', [ + 'parkList' => $parkList, + 'utilizationStats' => $utilizationStats, + 'totals' => $totals, + 'selectedParkId' => $parkId, + 'selectedPark' => $selectedPark, + 'isSearchRequest' => $isSearchRequest, + 'hasData' => $hasData, + ]); } catch (\Exception $e) { - // エラーログの出力 Log::error('区画別利用率状況ページエラー', [ 'error' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'park_id' => $parkId ?? null + 'file' => $e->getFile(), + 'line' => $e->getLine(), + 'park_id' => $parkId ?? null, ]); - - // エラー発生時のリダイレクト return redirect()->route('using_status') ->with('error', 'データの取得中にエラーが発生しました。管理者にお問い合わせください。'); } diff --git a/app/Services/UsingStatusService.php b/app/Services/UsingStatusService.php index 55559df..9baa73a 100644 --- a/app/Services/UsingStatusService.php +++ b/app/Services/UsingStatusService.php @@ -16,54 +16,52 @@ class UsingStatusService /** * 駐輪場別利用率統計を取得 * + * 取得元: + * - 限界収容台数: park_number.park_limit + * - 現在収容台数: park_number.park_number + * - 空き : park_number.park_limit - park_number.park_number + * - 利用率 : (現在収容台数 / 限界収容台数) * 100 + * * @param int|null $parkId 駐輪場ID(null の場合は全て) - * @return Collection 統計データのコレクション + * @return Collection */ public function getUtilizationStats(?int $parkId = null): Collection { - // 暫定的な収容台数(実DBに無いカラムのため) - $defaultCapacity = [ - 1 => 100, // 自転車 - 2 => 50, // 原付 - 3 => 30, // その他 - ]; - + // park_number に車種IDが ptype_id で入っている前提 + // 異なる場合は 'pn.ptype_id' 部分を実テーブル定義に合わせて変更してください $query = DB::table('park as p') - ->leftJoin('price_a as pr', 'p.park_id', '=', 'pr.park_id') - ->leftJoin('ptype as pt', 'pr.price_ptypeid', '=', 'pt.ptype_id') - ->leftJoin('regular_contract as rc', function ($join) { - $join->on('pr.price_parkplaceid', '=', 'rc.price_parkplaceid') - ->where('rc.contract_cancel_flag', '=', 0); - }) + ->join('park_number as pn', 'p.park_id', '=', 'pn.park_id') + ->join('ptype as pt', 'pn.ptype_id', '=', 'pt.ptype_id') ->select([ 'p.park_id', 'p.park_name', 'pt.ptype_id', 'pt.ptype_subject', - DB::raw('COUNT(rc.contract_id) as current_count'), + // 限界収容台数 + '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"), ]) - ->whereNotNull('pr.price_parkplaceid') - ->whereNotNull('pt.ptype_id') ->where('p.park_close_flag', '!=', 1); - if ($parkId) { + if (!empty($parkId)) { $query->where('p.park_id', $parkId); } $results = $query - ->groupBy(['p.park_id', 'p.park_name', 'pt.ptype_id', 'pt.ptype_subject']) + // 表示順:自転車 → 原付 → その他 + ->orderByRaw("CASE pt.ptype_subject WHEN '自転車' THEN 1 WHEN '原付' THEN 2 ELSE 3 END") ->orderBy('p.park_name') - ->orderBy('pt.ptype_subject') ->get(); - // 後計算で容量・空き・利用率を付与 - foreach ($results as $result) { - $capacity = $defaultCapacity[$result->ptype_id] ?? 50; - $result->park_limit = $capacity; - $result->available = $capacity - $result->current_count; - $result->usage_rate = $capacity > 0 ? round(($result->current_count / $capacity * 100), 1) : 0; - } - return $results; } diff --git a/resources/views/admin/using_status/index.blade.php b/resources/views/admin/using_status/index.blade.php index e090a87..23adcec 100644 --- a/resources/views/admin/using_status/index.blade.php +++ b/resources/views/admin/using_status/index.blade.php @@ -70,7 +70,7 @@ Laravel 12移行対応:区画別利用率状況ページ Laravel 12変更点:CSRFトークンの自動処理 route() ヘルパーの使用 --}} -
+ @csrf
@@ -82,7 +82,7 @@ Laravel 12移行対応:区画別利用率状況ページ
- {{-- Laravel 12変更点:Bladeディレクティブの最適化 @@ -106,7 +106,7 @@ Laravel 12移行対応:区画別利用率状況ページ
{{-- データ表示テーブル --}} -
+
@@ -236,19 +236,22 @@ JavaScript処理の最適化 @section('scripts')