391 lines
17 KiB
PHP
391 lines
17 KiB
PHP
<?php
|
||
namespace App\Http\Controllers\Admin;
|
||
|
||
use App\Http\Controllers\Controller;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
class PeriodicalController extends Controller
|
||
{
|
||
// 画面
|
||
public function list(Request $request)
|
||
{
|
||
$parks = DB::table('regular_contract')
|
||
->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
|
||
]);
|
||
}
|
||
}
|
||
?>
|