【定期利用・契約状況】データ不表示を修正
All checks were successful
Deploy main / deploy (push) Successful in 22s

This commit is contained in:
你的名字 2025-09-30 16:01:53 +09:00
parent 4137794126
commit 75bbec6f5a
2 changed files with 584 additions and 272 deletions

View File

@ -10,13 +10,13 @@ class PeriodicalController extends Controller
// 画面
public function list(Request $request)
{
// Bladeで使うカラム名id, nameで取得
$parks = DB::table('park')
->select('park_id', 'park_name')
->orderBy('park_name')
$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();
// 必要なら選択中のpark_idも渡す
$selectedParkId = $request->input('park_id', '');
return view('admin.periodical.list', compact('parks', 'selectedParkId'));
@ -27,73 +27,365 @@ class PeriodicalController extends Controller
{
$parkId = $request->input('park_id');
// 契約状況
$bicycleGeneral = DB::table('regular_contract')
->where('park_id', $parkId)
->where('user_categoryid', 1)
->where('ptype_id', 1) // 1:自転車
->where('contract_cancel_flag', 0)
->count();
$bicycleStudent = DB::table('regular_contract')
->where('park_id', $parkId)
->where('user_categoryid', 2)
->where('ptype_id', 1)
->where('contract_cancel_flag', 0)
->count();
// 原付・その他も同様に集計
$contractSummary = [
[
'type' => '自転車',
'general_count' => $bicycleGeneral,
'general_extra' => '',
'student_count' => $bicycleStudent,
'student_extra' => '',
'use_total' => $bicycleGeneral + $bicycleStudent,
'vacancy' => 8, // 例: 空き数
'total' => $bicycleGeneral + $bicycleStudent + 8,
'last' => [
'reserve_date' => '2025/07/27',
'contract_date' => '',
],
],
// 原付・その他も同様に
];
// 空き待ち状況
$waitingSummary = [
[
'type' => '自転車',
'general_count' => 28,
'general_head' => '2023/03/08',
'student_count' => 6,
'student_head' => '2023/11/04',
'total' => 34,
],
// 原付・その他も同様に
];
// 更新状況
$renewalSummary = [];
for ($m = 1; $m <= 12; $m++) {
$renewalSummary[] = [
'month' => sprintf('%02d月', $m),
'bicycle_general' => 0,
'bicycle_student' => 0,
'bicycle_total' => 0,
'moped_general' => 0,
'moped_student' => 0,
'moped_total' => 0,
'others_general' => 0,
'others_student' => 0,
'others_total' => 0,
];
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,
'waiting_summary' => $waitingSummary,
'renewal_summary' => $renewalSummary,
'debug_info' => $debugInfo
]);
}
}
?>

View File

@ -4,223 +4,243 @@
@section('content')
<div class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-lg-6">
<h1 class="m-0 text-dark">定期利用・契約状況</h1>
</div>
<div class="col-lg-6">
<ol class="breadcrumb float-sm-right text-sm">
<li class="breadcrumb-item"><a href="{{ route('home') }}">ホーム</a></li>
<li class="breadcrumb-item active">定期利用・契約状況</li>
</ol>
</div>
</div>
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6"><h1 class="m-0 text-dark">定期利用・契約状況</h1></div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right text-sm">
<li class="breadcrumb-item"><a href="{{ route('home') }}">ホーム</a></li>
<li class="breadcrumb-item active">定期利用・契約状況</li>
</ol>
</div>
</div>
</div>
</div>
<section class="content">
<div class="container-fluid">
{{-- 検索条件 --}}
<div class="card mb-3">
<div class="card-body">
<form id="filter-form" class="form-inline" onsubmit="return false;">
<label class="mr-2">駐輪場:</label>
<select name="park_id" id="park_id" class="form-control mr-3">
<option value="">全て</option>
@foreach($parks as $pk)
<option value="{{ $pk->park_id }}" {{ (string) $pk->park_id === (string) ($selectedParkId ?? '') ? 'selected' : '' }}>
{{ $pk->park_name }}
</option>
@endforeach
</select>
</form>
<small class="text-muted d-block mt-2">以下に記載以外の期間情報を参照したい場合は、マスタ管理>定期期間マスタ のCSV出力を利用してください。</small>
</div>
</div>
{{-- 契約状況 --}}
<div class="card mb-4">
<div class="card-header bg-light">
<strong>契約状況</strong>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-bordered mb-0 text-center">
<thead>
<tr>
<th rowspan="2" class="align-middle">契約状況</th>
<th colspan="2">一般</th>
<th colspan="2">学生</th>
<th rowspan="2" class="align-middle">利用計</th>
<th rowspan="2" class="align-middle">空き</th>
<th rowspan="2" class="align-middle">合計</th>
<th colspan="2">直近契約</th>
</tr>
<tr>
<th>件数</th>
<th><!-- 予備 --></th>
<th>件数</th>
<th><!-- 予備 --></th>
<th>予約日</th>
<th>契約日</th>
</tr>
</thead>
<tbody id="tbl-contract-summary"></tbody>
</table>
</div>
</div>
</div>
{{-- 空き待ち状況 --}}
<div class="card mb-4">
<div class="card-header bg-light">
<strong>空き待ち状況</strong>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-bordered mb-0 text-center">
<thead>
<tr>
<th rowspan="2" class="align-middle">空き待ち状況</th>
<th colspan="2">一般</th>
<th colspan="2">学生</th>
<th rowspan="2" class="align-middle">合計</th>
</tr>
<tr>
<th>件数</th>
<th>先頭日</th>
<th>件数</th>
<th>先頭日</th>
</tr>
</thead>
<tbody id="tbl-waiting-summary"></tbody>
</table>
</div>
</div>
</div>
{{-- 更新状況 --}}
<div class="card mb-4">
<div class="card-header bg-light">
<strong>更新状況</strong>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-bordered mb-0 text-center">
<thead>
<tr>
<th rowspan="2" class="align-middle" style="min-width:70px"></th>
<th colspan="3">自転車</th>
<th colspan="3">原付</th>
<th colspan="3">その他</th>
</tr>
<tr>
<th>一般</th>
<th>学生</th>
<th></th>
<th>一般</th>
<th>学生</th>
<th></th>
<th>一般</th>
<th>学生</th>
<th></th>
</tr>
</thead>
<tbody id="tbl-renewal-summary"></tbody>
</table>
</div>
</div>
</div>
<div class="container-fluid">
<div class="card card-body mb-3">
<form class="form-inline" onsubmit="return false;">
<label class="mr-2 mb-0">駐輪場:</label>
<select name="park_id" id="park_id" class="form-control mr-3">
<option value="">全て</option>
@foreach ($parks as $p)
<option value="{{ $p->park_id }}" {{ (string)$selectedParkId === (string)$p->park_id ? 'selected' : '' }}>
{{ $p->park_name }}
</option>
@endforeach
</select>
</form>
<small class="text-muted d-block mt-2">
以下に記載以外の期間情報を参照したい場合は、マスタ管理定期期間マスタのCSV出力を利用してください。
</small>
</div>
<div id="stats-sections" style="display:none;">
<div class="card mb-3">
<div class="card-header p-2">契約状況</div>
<div class="card-body p-2">
<table class="table table-bordered mb-0 text-center">
<thead>
<tr>
<th rowspan="2" class="align-middle">契約状況</th>
<th rowspan="2" class="align-middle">一般</th>
<th rowspan="2" class="align-middle">学生</th>
<th rowspan="2" class="align-middle">利用計</th>
<th rowspan="2" class="align-middle">空き</th>
<th rowspan="2" class="align-middle">合計</th>
<th colspan="2">直近契約</th>
</tr>
<tr>
<th>予約日</th>
<th>契約日</th>
</tr>
</thead>
<tbody id="tbl-contract-summary"></tbody>
</table>
</div>
</div>
<div class="card mb-3">
<div class="card-header p-2">空き待ち状況</div>
<div class="card-body p-2">
<table class="table table-bordered mb-0 text-center">
<thead>
<tr>
<th rowspan="2" class="align-middle">空き待ち状況</th>
<th colspan="2">一般</th>
<th colspan="2">学生</th>
<th rowspan="2" class="align-middle">合計</th>
</tr>
<tr>
<th>件数</th>
<th>先頭日</th>
<th>件数</th>
<th>先頭日</th>
</tr>
</thead>
<tbody id="tbl-waiting-summary"></tbody>
</table>
</div>
</div>
<div class="card">
<div class="card-header p-2">更新状況</div>
<div class="card-body p-2">
<table class="table table-bordered mb-0 text-center">
<thead>
<tr>
<th rowspan="2" class="align-middle" style="min-width:70px"></th>
<th rowspan="2" class="align-middle" style="min-width:60px">更新状況</th>
<th colspan="3">自転車</th>
<th colspan="3">原付</th>
<th colspan="3">その他</th>
</tr>
<tr>
<th>一般</th><th>学生</th><th></th>
<th>一般</th><th>学生</th><th></th>
<th>一般</th><th>学生</th><th></th>
</tr>
</thead>
<tbody id="tbl-renewal-summary"></tbody>
</table>
</div>
</div>
</div>
</div>
</section>
@endsection
@push('scripts')
<script>
$(function () {
loadStats();
(function() {
function $(sel){return document.querySelector(sel)}
function $tb(id){return document.getElementById(id)}
function escapeHtml(s){const d=document.createElement('div');d.textContent=(s??'');return d.innerHTML}
function numberOrDash(v){const n=Number(v);return Number.isFinite(n)?n.toString():'-'}
function formatDate(d){return d && d !== 'null' ? d : '-'}
function formatMonth(m){
if(!m || m === 'null') return '-';
// YYYY-MM 形式を MM月 形式に変換
const parts = m.split('-');
if(parts.length === 2) {
const monthNum = parseInt(parts[1], 10);
return `${monthNum}月`;
}
return m.replace('-', '/');
}
$('#park_id').on('change', function () {
loadStats();
const park = $('#park_id');
const stats = $('#stats-sections');
park.addEventListener('change', loadStats);
loadStats();
function loadStats(){
const id = park.value;
if(!id){ stats.style.display='none'; clearTables(); return; }
fetch("{{ route('periodical.listData') }}?park_id="+encodeURIComponent(id), {headers:{'Accept':'application/json'}})
.then(r => r.ok ? r.json() : Promise.reject(r))
.then(res => {
stats.style.display='block';
// デバッグ情報があれば表示
if(res.debug_info) {
console.log('Debug info:', res.debug_info);
}
renderContractSummary(res.contract_summary||[]);
renderWaitingSummary(res.waiting_summary||[]);
renderRenewalSummary(res.renewal_summary||[]);
})
.catch(err => {
stats.style.display='none';
clearTables();
});
}
function clearTables(){
['tbl-contract-summary','tbl-waiting-summary','tbl-renewal-summary'].forEach(id => $tb(id).innerHTML='');
}
// 契約状況
function renderContractSummary(list){
const tb = $tb('tbl-contract-summary'); tb.innerHTML='';
if(!Array.isArray(list)||!list.length){
tb.innerHTML = noDataRow(8);
return;
}
list.forEach(row=>{
const rowClass = row.type === '計' ? ' class="font-weight-bold"' : '';
tb.insertAdjacentHTML('beforeend', `
<tr${rowClass}>
<td>${escapeHtml(row.type)}</td>
<td>${formatPair(row.general_count, row.general_extra)}</td>
<td>${formatPair(row.student_count, row.student_extra)}</td>
<td>${numberOrDash(row.use_total)}</td>
<td>${numberOrDash(row.vacancy)}</td>
<td>${numberOrDash(row.total)}</td>
<td>${formatDate(row?.last?.reserve_date)}</td>
<td>${formatDate(row?.last?.contract_date)}</td>
</tr>`);
});
}
function formatPair(c,e){
const n = Number.isFinite(Number(c))?Number(c):0;
const m = Number.isFinite(Number(e))?Number(e):0;
return `${n}${m}`;
}
function loadStats() {
$.ajax({
url: "{{ route('periodical.listData') }}",
type: 'GET',
data: { park_id: $('#park_id').val() },
success: function (res) {
renderContractSummary(res.contract_summary || []);
renderWaitingSummary(res.waiting_summary || []);
renderRenewalSummary(res.renewal_summary || []);
},
error: function (xhr) {
console.error(xhr.responseText || xhr.statusText);
}
});
}
// 空き待ち
function renderWaitingSummary(list){
const tb = $tb('tbl-waiting-summary'); tb.innerHTML='';
if(!Array.isArray(list)||!list.length){ tb.innerHTML = noDataRow(6); return; }
list.forEach(r=>{
const rowClass = r.type === '計' ? ' class="font-weight-bold"' : '';
tb.insertAdjacentHTML('beforeend', `
<tr${rowClass}>
<td>${escapeHtml(r.type)}</td>
<td>${numberOrDash(r.general_count)}</td>
<td>${formatDate(r.general_first)}</td>
<td>${numberOrDash(r.student_count)}</td>
<td>${formatDate(r.student_first)}</td>
<td>${numberOrDash(r.total)}</td>
</tr>`);
});
}
function nz(v) { return (v === null || v === undefined || v === '') ? '' : v; }
function renderContractSummary(rows) {
const $tb = $('#tbl-contract-summary').empty();
rows.forEach(r => {
$tb.append(`
<tr>
<td class="text-left">${r.type}</td>
<td>${nz(r.general_count)}</td>
<td>${nz(r.general_extra)}</td>
<td>${nz(r.student_count)}</td>
<td>${nz(r.student_extra)}</td>
<td>${nz(r.use_total)}</td>
<td>${nz(r.vacancy)}</td>
<td>${nz(r.total)}</td>
<td>${r.last && r.last.reserve_date ? r.last.reserve_date : ''}</td>
<td>${r.last && r.last.contract_date ? r.last.contract_date : ''}</td>
</tr>
`);
});
}
function renderWaitingSummary(rows) {
const $tb = $('#tbl-waiting-summary').empty();
rows.forEach(r => {
$tb.append(`
<tr>
<td class="text-left">${r.type}</td>
<td>${nz(r.general_count)}</td>
<td>${nz(r.general_head)}</td>
<td>${nz(r.student_count)}</td>
<td>${nz(r.student_head)}</td>
<td>${nz(r.total)}</td>
</tr>
`);
});
}
function renderRenewalSummary(rows) {
const $tb = $('#tbl-renewal-summary').empty();
rows.forEach(r => {
$tb.append(`
<tr>
<td class="text-left">${r.month}</td>
<td>${nz(r.bicycle_general)}</td>
<td>${nz(r.bicycle_student)}</td>
<td>${nz(r.bicycle_total)}</td>
<td>${nz(r.moped_general)}</td>
<td>${nz(r.moped_student)}</td>
<td>${nz(r.moped_total)}</td>
<td>${nz(r.others_general)}</td>
<td>${nz(r.others_student)}</td>
<td>${nz(r.others_total)}</td>
</tr>
`);
});
}
});
// 更新状況(月ブロック形式)
function renderRenewalSummary(blocks){
const tb = $tb('tbl-renewal-summary'); tb.innerHTML='';
if(!Array.isArray(blocks)||!blocks.length){ tb.innerHTML = noDataRow(11); return; }
// 新形式: [{month:'YYYY-MM', rows:[{label,...}]}]
blocks.forEach(b=>{
const rows = Array.isArray(b.rows)?b.rows:[];
if(rows.length === 0) return;
rows.forEach((r,idx)=>{
const monthCell = idx===0 ? `<td rowspan="${rows.length}" class="align-middle">${formatMonth(b.month)}</td>` : '';
const rowClass = r.label === '計' ? ' class="font-weight-bold"' : '';
tb.insertAdjacentHTML('beforeend', `
<tr${rowClass}>
${monthCell}
<td>${escapeHtml(r.label)}</td>
<td>${numberOrDash(r.bicycle_general)}</td>
<td>${numberOrDash(r.bicycle_student)}</td>
<td>${numberOrDash(r.bicycle_total)}</td>
<td>${numberOrDash(r.moped_general)}</td>
<td>${numberOrDash(r.moped_student)}</td>
<td>${numberOrDash(r.moped_total)}</td>
<td>${numberOrDash(r.other_general)}</td>
<td>${numberOrDash(r.other_student)}</td>
<td>${numberOrDash(r.other_total)}</td>
</tr>`);
});
});
}
function noDataRow(colspan){ return `<tr><td colspan="${colspan}">データがありません</td></tr>`; }
})();
</script>
@endpush
@endsection