join('park', 'regular_contract.park_id', '=', 'park.park_id') ->select('park.park_id', 'park.park_name') ->distinct() ->orderBy('park.park_name') ->get(); $selectedParkId = $request->input('park_id', ''); return view('admin.periodical.list', compact('parks', 'selectedParkId')); } // 画面上の3つの統計用データ public function listData(Request $request) { $parkId = $request->input('park_id'); if (empty($parkId)) { return response()->json([ 'contract_summary' => [], 'waiting_summary' => [], 'renewal_summary' => [], 'debug_info' => ['message' => 'No park_id provided'] ]); } // デバッグ情報を収集 $debugInfo = [ 'park_id' => $parkId, 'has_regular_type_id' => false, 'contract_count' => 0, 'waiting_count' => 0, 'renewal_count' => 0 ]; // 契約状況を車種別に集計 $contractData = [ ['psection_id' => 1, 'type' => '自転車'], ['psection_id' => 2, 'type' => '原付'], ['psection_id' => 0, 'type' => 'その他'] // その他は psection_id が1,2以外 ]; $contractSummary = []; $totalGeneral = 0; $totalStudent = 0; $totalUseTotal = 0; $totalVacancy = 0; $totalAll = 0; foreach ($contractData as $vehicleType) { $query = DB::table('regular_contract as rc') ->leftJoin('psection as ps', 'rc.psection_id', '=', 'ps.psection_id') ->selectRaw('SUM(CASE WHEN rc.user_categoryid = 1 THEN 1 ELSE 0 END) AS general_count') ->selectRaw('SUM(CASE WHEN rc.user_categoryid = 2 THEN 1 ELSE 0 END) AS student_count') ->selectRaw('SUM(CASE WHEN rc.contract_cancel_flag = 0 THEN 1 ELSE 0 END) AS use_total') ->selectRaw('SUM(CASE WHEN rc.contract_cancel_flag = 1 THEN 1 ELSE 0 END) AS vacancy') ->selectRaw('COUNT(*) AS total') ->where('rc.park_id', $parkId); if ($vehicleType['psection_id'] === 0) { // その他:psection_id が 1,2 以外 $query->whereNotIn('rc.psection_id', [1, 2]); } else { // 自転車または原付 $query->where('rc.psection_id', $vehicleType['psection_id']); } $result = $query->first(); $generalCount = (int) ($result->general_count ?? 0); $studentCount = (int) ($result->student_count ?? 0); $useTotal = (int) ($result->use_total ?? 0); $vacancy = (int) ($result->vacancy ?? 0); $total = (int) ($result->total ?? 0); // 最古の予約日と契約日を取得 $minReserveQuery = DB::table('regular_contract as rc2') ->join('reserve as r2', 'rc2.contract_id', '=', 'r2.contract_id') ->where('rc2.park_id', $parkId) ->where('r2.valid_flag', 1) ->where(function ($q) { $q->whereNull('r2.reserve_cancel_flag')->orWhere('r2.reserve_cancel_flag', 0); }); if ($vehicleType['psection_id'] === 0) { $minReserveQuery->whereNotIn('rc2.psection_id', [1, 2]); } else { $minReserveQuery->where('rc2.psection_id', $vehicleType['psection_id']); } $minReserveDate = null; $minContractDate = null; $reserveResult = $minReserveQuery->orderBy('r2.reserve_date', 'asc')->first(['r2.reserve_date']); if ($reserveResult) { $minReserveDate = date('Y/m/d', strtotime($reserveResult->reserve_date)); } $contractResult = $minReserveQuery->orderBy('r2.reserve_end', 'asc')->first(['r2.reserve_end']); if ($contractResult) { $minContractDate = date('Y/m/d', strtotime($contractResult->reserve_end)); } $contractSummary[] = [ 'type' => $vehicleType['type'], 'general_count' => $generalCount, 'general_extra' => '', 'student_count' => $studentCount, 'student_extra' => '', 'use_total' => $useTotal, 'vacancy' => $vacancy, 'total' => $total, 'last' => ['reserve_date' => $minReserveDate, 'contract_date' => $minContractDate], ]; $totalGeneral += $generalCount; $totalStudent += $studentCount; $totalUseTotal += $useTotal; $totalVacancy += $vacancy; $totalAll += $total; } // 合計行を追加 $contractSummary[] = [ 'type' => '計', 'general_count' => $totalGeneral, 'general_extra' => '', 'student_count' => $totalStudent, 'student_extra' => '', 'use_total' => $totalUseTotal, 'vacancy' => $totalVacancy, 'total' => $totalAll, 'last' => ['reserve_date' => null, 'contract_date' => null], ]; $debugInfo['contract_count'] = count($contractSummary); // 空き待ち状況を車種別に集計 $waitingData = [ ['psection_id' => 1, 'type' => '自転車'], ['psection_id' => 2, 'type' => '原付'], ['psection_id' => 0, 'type' => 'その他'] // その他は psection_id が1,2以外 ]; $waitingSummary = []; $totalGeneral = 0; $totalStudent = 0; $totalAll = 0; foreach ($waitingData as $vehicleType) { $query = DB::table('regular_contract as rc') ->join('reserve as r', 'rc.contract_id', '=', 'r.contract_id') ->selectRaw('SUM(CASE WHEN rc.user_categoryid = 1 THEN 1 ELSE 0 END) AS general_count') ->selectRaw('DATE_FORMAT(MIN(CASE WHEN rc.user_categoryid = 1 THEN r.reserve_date END), "%Y/%m/%d") AS general_first') ->selectRaw('SUM(CASE WHEN rc.user_categoryid = 2 THEN 1 ELSE 0 END) AS student_count') ->selectRaw('DATE_FORMAT(MIN(CASE WHEN rc.user_categoryid = 2 THEN r.reserve_date END), "%Y/%m/%d") AS student_first') ->selectRaw('COUNT(*) AS total') ->where('rc.park_id', $parkId) ->where('r.valid_flag', 1) ->where(function ($q) { $q->whereNull('r.reserve_cancel_flag')->orWhere('r.reserve_cancel_flag', 0); }); if ($vehicleType['psection_id'] === 0) { // その他:psection_id が 1,2 以外 $query->whereNotIn('rc.psection_id', [1, 2]); } else { // 自転車または原付 $query->where('rc.psection_id', $vehicleType['psection_id']); } $result = $query->first(); $generalCount = (int) ($result->general_count ?? 0); $studentCount = (int) ($result->student_count ?? 0); $typeTotal = $generalCount + $studentCount; $waitingSummary[] = [ 'type' => $vehicleType['type'], 'general_count' => $generalCount, 'general_first' => $result->general_first ?? null, 'student_count' => $studentCount, 'student_first' => $result->student_first ?? null, 'total' => $typeTotal, ]; $totalGeneral += $generalCount; $totalStudent += $studentCount; $totalAll += $typeTotal; } // 合計行を追加 $waitingSummary[] = [ 'type' => '計', 'general_count' => $totalGeneral, 'general_first' => null, 'student_count' => $totalStudent, 'student_first' => null, 'total' => $totalAll, ]; $debugInfo['waiting_count'] = count($waitingSummary); // まず期間タイプフィールドが存在するかチェック $hasRegularTypeId = false; try { $columns = DB::select('DESCRIBE regular_contract'); foreach ($columns as $column) { if ($column->Field === 'regular_type_id') { $hasRegularTypeId = true; break; } } } catch (\Exception $e) { // エラーの場合はデフォルトで false } $debugInfo['has_regular_type_id'] = $hasRegularTypeId; $renewalQuery = DB::table('regular_contract as rc') ->join('reserve as r', 'rc.contract_id', '=', 'r.contract_id') ->where('rc.park_id', $parkId) ->whereNotNull('r.reserve_start') ->where('r.valid_flag', 1) ->selectRaw("DATE_FORMAT(r.reserve_start, '%Y-%m') AS month"); if ($hasRegularTypeId) { $renewalQuery->selectRaw('COALESCE(rc.regular_type_id, 1) AS period_type'); } else { $renewalQuery->selectRaw('1 AS period_type'); // デフォルト値 } $renewalSummary = $renewalQuery ->selectRaw('SUM(CASE WHEN rc.psection_id = 1 AND rc.user_categoryid = 1 THEN 1 ELSE 0 END) AS bicycle_general') ->selectRaw('SUM(CASE WHEN rc.psection_id = 1 AND rc.user_categoryid = 2 THEN 1 ELSE 0 END) AS bicycle_student') ->selectRaw('SUM(CASE WHEN rc.psection_id = 2 AND rc.user_categoryid = 1 THEN 1 ELSE 0 END) AS moped_general') ->selectRaw('SUM(CASE WHEN rc.psection_id = 2 AND rc.user_categoryid = 2 THEN 1 ELSE 0 END) AS moped_student') ->selectRaw('SUM(CASE WHEN rc.psection_id NOT IN (1,2) AND rc.user_categoryid = 1 THEN 1 ELSE 0 END) AS other_general') ->selectRaw('SUM(CASE WHEN rc.psection_id NOT IN (1,2) AND rc.user_categoryid = 2 THEN 1 ELSE 0 END) AS other_student') ->groupBy(['month', 'period_type']) ->orderBy('month') ->orderBy('period_type') ->limit(50) ->get(); // 月別期間別データを構造化 $structuredData = []; $periodLabels = [ 1 => '1ヶ月', 2 => '2ヶ月', 3 => '3ヶ月', 6 => '6ヶ月', 12 => '12ヶ月' ]; // regular_type_id がない場合のデフォルト処理 if (!$hasRegularTypeId) { // フィールドがない場合は、月ごとに「計」行のみ表示 $monthlyTotals = []; foreach ($renewalSummary as $row) { $monthKey = $row->month; if (!isset($monthlyTotals[$monthKey])) { $monthlyTotals[$monthKey] = [ 'bicycle_general' => 0, 'bicycle_student' => 0, 'moped_general' => 0, 'moped_student' => 0, 'other_general' => 0, 'other_student' => 0, ]; } $monthlyTotals[$monthKey]['bicycle_general'] += (int) $row->bicycle_general; $monthlyTotals[$monthKey]['bicycle_student'] += (int) $row->bicycle_student; $monthlyTotals[$monthKey]['moped_general'] += (int) $row->moped_general; $monthlyTotals[$monthKey]['moped_student'] += (int) $row->moped_student; $monthlyTotals[$monthKey]['other_general'] += (int) $row->other_general; $monthlyTotals[$monthKey]['other_student'] += (int) $row->other_student; } foreach ($monthlyTotals as $monthKey => $totals) { $structuredData[$monthKey] = [ 'month' => $monthKey, 'rows' => [[ 'label' => '計', 'bicycle_general' => $totals['bicycle_general'], 'bicycle_student' => $totals['bicycle_student'], 'bicycle_total' => $totals['bicycle_general'] + $totals['bicycle_student'], 'moped_general' => $totals['moped_general'], 'moped_student' => $totals['moped_student'], 'moped_total' => $totals['moped_general'] + $totals['moped_student'], 'other_general' => $totals['other_general'], 'other_student' => $totals['other_student'], 'other_total' => $totals['other_general'] + $totals['other_student'], ]] ]; } } else { // regular_type_id がある場合の通常処理 foreach ($renewalSummary as $row) { $monthKey = $row->month; $periodType = (int)$row->period_type; $periodLabel = $periodLabels[$periodType] ?? "{$periodType}ヶ月"; if (!isset($structuredData[$monthKey])) { $structuredData[$monthKey] = [ 'month' => $monthKey, 'rows' => [], 'totals' => [ 'bicycle_general' => 0, 'bicycle_student' => 0, 'moped_general' => 0, 'moped_student' => 0, 'other_general' => 0, 'other_student' => 0, ] ]; } $bicycle_total = (int) $row->bicycle_general + (int) $row->bicycle_student; $moped_total = (int) $row->moped_general + (int) $row->moped_student; $other_total = (int) $row->other_general + (int) $row->other_student; // 期間別データを追加 $structuredData[$monthKey]['rows'][] = [ 'label' => $periodLabel, 'bicycle_general' => (int) $row->bicycle_general, 'bicycle_student' => (int) $row->bicycle_student, 'bicycle_total' => $bicycle_total, 'moped_general' => (int) $row->moped_general, 'moped_student' => (int) $row->moped_student, 'moped_total' => $moped_total, 'other_general' => (int) $row->other_general, 'other_student' => (int) $row->other_student, 'other_total' => $other_total, ]; // 月別合計を計算 $structuredData[$monthKey]['totals']['bicycle_general'] += (int) $row->bicycle_general; $structuredData[$monthKey]['totals']['bicycle_student'] += (int) $row->bicycle_student; $structuredData[$monthKey]['totals']['moped_general'] += (int) $row->moped_general; $structuredData[$monthKey]['totals']['moped_student'] += (int) $row->moped_student; $structuredData[$monthKey]['totals']['other_general'] += (int) $row->other_general; $structuredData[$monthKey]['totals']['other_student'] += (int) $row->other_student; } // 各月に計行を追加 foreach ($structuredData as &$monthData) { $totals = $monthData['totals']; $monthData['rows'][] = [ 'label' => '計', 'bicycle_general' => $totals['bicycle_general'], 'bicycle_student' => $totals['bicycle_student'], 'bicycle_total' => $totals['bicycle_general'] + $totals['bicycle_student'], 'moped_general' => $totals['moped_general'], 'moped_student' => $totals['moped_student'], 'moped_total' => $totals['moped_general'] + $totals['moped_student'], 'other_general' => $totals['other_general'], 'other_student' => $totals['other_student'], 'other_total' => $totals['other_general'] + $totals['other_student'], ]; } } $renewalSummary = array_values($structuredData); $debugInfo['renewal_count'] = count($renewalSummary); return response()->json([ 'contract_summary' => $contractSummary, 'waiting_summary' => $waitingSummary, 'renewal_summary' => $renewalSummary, 'debug_info' => $debugInfo ]); } } ?>