【駐輪規定マスタ】初版作成
All checks were successful
Deploy main / deploy (push) Successful in 22s

This commit is contained in:
OU.ZAIKOU 2026-02-02 00:40:00 +09:00
parent f49a573d78
commit 041bef0546
14 changed files with 508 additions and 7 deletions

View File

@ -0,0 +1,204 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Models\Park;
use App\Models\ParkingRegulation;
class ParkingRegulationsController extends Controller
{
/**
* 一覧表示
*/
public function list(Request $request)
{
// park_id 検証
$request->validate([
'park_id' => 'required|integer|exists:park,park_id',
], [
'park_id.required' => '駐輪場IDは必須です。',
'park_id.integer' => '駐輪場IDは整数である必要があります。',
'park_id.exists' => '指定された駐輪場が見つかりません。',
]);
$parkId = (int) $request->input('park_id');
// 駐輪場情報取得
$park = Park::where('park_id', $parkId)->firstOrFail();
// parking_regulations を取得し、psection / ptype 名を JOIN して表示
$data = DB::table('parking_regulations')
->leftJoin('psection', 'parking_regulations.psection_id', '=', 'psection.psection_id')
->leftJoin('ptype', 'parking_regulations.ptype_id', '=', 'ptype.ptype_id')
->where('parking_regulations.park_id', $parkId)
->select(
'parking_regulations.parking_regulations_seq',
'parking_regulations.park_id',
'parking_regulations.psection_id',
'parking_regulations.ptype_id',
'parking_regulations.regulations_text',
'psection.psection_subject as psection_subject',
'ptype.ptype_subject as ptype_subject'
)
->orderBy('parking_regulations.psection_id')
->orderBy('parking_regulations.ptype_id')
->paginate(50);
return view('admin.parking_regulations.list', [
'park' => $park,
'parkId' => $parkId,
'regulations' => $data,
]);
}
/**
* 新規作成フォーム表示/登録
*/
public function add(Request $request)
{
$parkId = $request->input('park_id');
// 駐輪場存在確認
if (!$parkId) {
return redirect()->back()->withErrors(['park_id' => '駐輪場IDが指定されていません。']);
}
$park = Park::where('park_id', $parkId)->firstOrFail();
// マスタの選択肢取得
$psections = DB::table('psection')->orderBy('psection_id')->get();
$ptypes = DB::table('ptype')->orderBy('ptype_id')->get();
if ($request->isMethod('post')) {
// 登録処理
$validated = $request->validate([
'park_id' => 'required|integer|exists:park,park_id',
'psection_id' => 'required|integer',
'ptype_id' => 'required|integer',
'regulations_text' => 'nullable|string',
], [
'park_id.required' => '駐輪場IDは必須です。',
'psection_id.required' => '車種区分は必須です。',
'ptype_id.required' => '駐輪分類は必須です。',
]);
// 重複チェック
$exists = DB::table('parking_regulations')
->where('park_id', $validated['park_id'])
->where('psection_id', $validated['psection_id'])
->where('ptype_id', $validated['ptype_id'])
->exists();
if ($exists) {
return back()->withErrors(['duplicate' => '同じ組み合わせの規定が既に存在します。'])->withInput();
}
ParkingRegulation::create([
'park_id' => $validated['park_id'],
'psection_id' => $validated['psection_id'],
'ptype_id' => $validated['ptype_id'],
'regulations_text' => $validated['regulations_text'] ?? null,
]);
return redirect()->route('parking_regulations_list', ['park_id' => $validated['park_id']])->with('success', '登録しました。');
}
return view('admin.parking_regulations.add', [
'park' => $park,
'parkId' => $parkId,
'psections' => $psections,
'ptypes' => $ptypes,
]);
}
/**
* 編集フォーム表示
*/
public function edit($seq, Request $request)
{
$record = DB::table('parking_regulations')->where('parking_regulations_seq', $seq)->first();
if (!$record) {
return redirect()->back()->withErrors(['not_found' => '指定の規定が見つかりません。']);
}
$park = Park::where('park_id', $record->park_id)->firstOrFail();
$psections = DB::table('psection')->orderBy('psection_id')->get();
$ptypes = DB::table('ptype')->orderBy('ptype_id')->get();
return view('admin.parking_regulations.edit', [
'park' => $park,
'record' => $record,
'psections' => $psections,
'ptypes' => $ptypes,
]);
}
/**
* 更新処理
*/
public function update($seq, Request $request)
{
$validated = $request->validate([
'psection_id' => 'required|integer',
'ptype_id' => 'required|integer',
'regulations_text' => 'nullable|string',
], [
'psection_id.required' => '車種区分は必須です。',
'ptype_id.required' => '駐輪分類は必須です。',
]);
// 対象レコード取得
$record = DB::table('parking_regulations')->where('parking_regulations_seq', $seq)->first();
if (!$record) {
return back()->withErrors(['not_found' => '指定の規定が見つかりません。']);
}
// 重複チェック(自分自身は除外)
$exists = DB::table('parking_regulations')
->where('park_id', $record->park_id)
->where('psection_id', $validated['psection_id'])
->where('ptype_id', $validated['ptype_id'])
->where('parking_regulations_seq', '<>', $seq)
->exists();
if ($exists) {
return back()->withErrors(['duplicate' => '同じ組み合わせの規定が既に存在します。'])->withInput();
}
DB::table('parking_regulations')->where('parking_regulations_seq', $seq)->update([
'psection_id' => $validated['psection_id'],
'ptype_id' => $validated['ptype_id'],
'regulations_text' => $validated['regulations_text'] ?? null,
'updated_at' => now(),
]);
return redirect()->route('parking_regulations_list', ['park_id' => $record->park_id])->with('success', '更新しました。');
}
/**
* 削除処理
*/
public function delete(Request $request)
{
$validated = $request->validate([
'parking_regulations_seq' => 'required|integer',
], [
'parking_regulations_seq.required' => '削除対象が指定されていません。',
]);
$seq = (int) $validated['parking_regulations_seq'];
$record = DB::table('parking_regulations')->where('parking_regulations_seq', $seq)->first();
if (!$record) {
return back()->withErrors(['not_found' => '指定の規定が見つかりません。']);
}
DB::table('parking_regulations')->where('parking_regulations_seq', $seq)->delete();
return redirect()->route('parking_regulations_list', ['park_id' => $record->park_id])->with('success', '削除しました。');
}
}

View File

@ -104,7 +104,7 @@ class ReductionConfirmMasterController extends Controller
} }
}); });
return redirect()->route('reduction_confirm.list', ['park_id' => $parkId]) return redirect()->route('reduction_confirm_list', ['park_id' => $parkId])
->with('success', '減免確認マスタを更新しました。'); ->with('success', '減免確認マスタを更新しました。');
} catch (\Exception $e) { } catch (\Exception $e) {
\Log::error('ReductionConfirm update failed', [ \Log::error('ReductionConfirm update failed', [

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,88 @@
@php
// $psections: 車種区分コレクション
// $ptypes: 駐輪分類コレクション
// $parkId: 駐輪場ID
// $record: 編集用レコードnull = 新規)
$selectedPsection = old('psection_id', $record->psection_id ?? null);
$selectedPtype = old('ptype_id', $record->ptype_id ?? null);
$regulationsText = old('regulations_text', $record->regulations_text ?? '');
@endphp
<input type="hidden" name="park_id" value="{{ $parkId }}">
<input type="hidden" name="park_id" value="{{ $parkId }}">
{{-- 駐輪場名(編集不可) --}}
<div class="mb-3 row">
<label class="col-md-2 col-form-label font-weight-bold">駐輪場名</label>
<div class="col-md-10">
<input type="text"
class="form-control"
value="{{ $park->park_name }}"
readonly>
</div>
</div>
{{-- 車種区分 --}}
<div class="mb-3 row">
<label class="col-md-2 col-form-label font-weight-bold">車種区分 <span class="text-danger">*</span></label>
<div class="col-md-10">
<select name="psection_id" class="form-control" required>
<option value="">選択してください</option>
@foreach($psections as $ps)
<option value="{{ $ps->psection_id }}"
@selected($selectedPsection == $ps->psection_id)>
{{ $ps->psection_subject }}
</option>
@endforeach
</select>
</div>
</div>
{{-- 駐輪分類 --}}
<div class="mb-3 row">
<label class="col-md-2 col-form-label font-weight-bold">駐輪分類 <span class="text-danger">*</span></label>
<div class="col-md-10">
<select name="ptype_id" class="form-control" required>
<option value="">選択してください</option>
@foreach($ptypes as $pt)
<option value="{{ $pt->ptype_id }}"
@selected($selectedPtype == $pt->ptype_id)>
{{ $pt->ptype_subject }}
</option>
@endforeach
</select>
</div>
</div>
{{-- 駐輪規定 --}}
<div class="mb-3 row">
<label class="col-md-2 col-form-label font-weight-bold">
駐輪規定 <span class="text-danger">*</span>
</label>
<div class="col-md-10">
<textarea name="regulations_text"
class="form-control js-summernote"
required>{!! $regulationsText !!}</textarea>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
$('.js-summernote').summernote({
height: 420,
minHeight: 420,
toolbar: [
['style', ['style']],
['font', ['bold', 'underline', 'italic', 'clear']],
['fontname', ['fontname']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
['insert', ['link', 'picture']],
['view', ['fullscreen', 'codeview', 'help']]
]
});
});
</script>

View File

@ -0,0 +1,43 @@
@extends('layouts.app')
@section('title', '駐輪規定 新規登録')
@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"><a href="{{ route('parking_regulations_list', ['park_id' => $parkId]) }}">駐輪規定マスタ</a></li>
<li class="breadcrumb-item active">新規登録</li>
</ol>
</div>
</div>
</div>
</div>
<section class="content">
<div class="container-fluid">
@if ($errors->any())
<div class="alert alert-danger">@foreach($errors->all() as $e) <div>{{ $e }}</div> @endforeach</div>
@endif
<div class="card">
<div class="card-body">
<form method="POST" action="{{ route('parking_regulations_add') }}">
@csrf
@include('admin.parking_regulations._form', ['psections' => $psections, 'ptypes' => $ptypes, 'parkId' => $parkId, 'record' => null])
<div class="text-end">
<button type="submit" class="btn btn-primary">登録</button>
<a href="{{ route('parking_regulations_list', ['park_id' => $parkId]) }}" class="btn btn-default">戻る</a>
</div>
</form>
</div>
</div>
</div>
</section>
@endsection

View File

@ -0,0 +1,44 @@
@extends('layouts.app')
@section('title', '駐輪規定 編集')
@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"><a href="{{ route('parking_regulations_list', ['park_id' => $park->park_id]) }}">駐輪規定マスタ</a></li>
<li class="breadcrumb-item active">編集</li>
</ol>
</div>
</div>
</div>
</div>
<section class="content">
<div class="container-fluid">
@if ($errors->any())
<div class="alert alert-danger">@foreach($errors->all() as $e) <div>{{ $e }}</div> @endforeach</div>
@endif
<div class="card">
<div class="card-body">
<form method="POST" action="{{ route('parking_regulations_update', ['seq' => $record->parking_regulations_seq]) }}">
@csrf
@include('admin.parking_regulations._form', ['psections' => $psections, 'ptypes' => $ptypes, 'parkId' => $park->park_id, 'record' => $record])
<div class="text-end">
<button type="submit" class="btn btn-success">登録</button>
<button type="submit" class="btn btn-danger" onclick="return confirm('削除してよいですか?')">削除</button>
<a href="{{ route('parking_regulations_list', ['park_id' => $park->park_id]) }}" class="btn btn-secondary">戻る</a>
</div>
</form>
</div>
</div>
</div>
</section>
@endsection

View File

@ -0,0 +1,110 @@
@extends('layouts.app')
@section('title', '駐輪規定マスタ')
@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>
</div>
<section class="content">
<div class="container-fluid">
@if ($errors->any())
<div class="alert alert-danger">
@foreach ($errors->all() as $e)
<div>{{ $e }}</div>
@endforeach
</div>
@endif
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
<div class="card">
<div class="card-header">
<h3 class="card-title">駐輪場情報</h3>
</div>
<div class="card-body">
<div class="d-flex align-items-center">
<div style="width:180px;" class="font-weight-bold">
駐輪場名
</div>
<div class="ml-3">
{{ $park->park_name ?? '' }}
</div>
</div>
</div>
</div>
<div class="d-flex justify-content-between align-items-center mb-2">
<a href="{{ route('parking_regulations_add', ['park_id' => $parkId]) }}" class="btn btn-primary mr-2">新規</a>
{{-- 件数 + ページネーション --}}
<div class="d-flex justify-content-between align-items-center mb-3 px-3 pt-3">
<div class="text-right ml-auto">
<div>
{{ $regulations->total() }} 件中
{{ $regulations->firstItem() }}{{ $regulations->lastItem() }} 件を表示
</div>
<div>
{{ $regulations->appends(request()->query())->links('pagination') }}
</div>
</div>
</div>
</div>
<div class="table-responsive">
<table class="table table-bordered table-sm">
<thead class="thead-light">
<tr>
<th style="width:100px">操作</th>
<th style="width:15%">車種区分</th>
<th style="width:15%">駐輪分類</th>
<th>駐輪規定</th>
</tr>
</thead>
<tbody style="background:#fff;">
@forelse($regulations as $r)
<tr>
<td>
<a href="{{ route('parking_regulations_edit', ['seq' => $r->parking_regulations_seq]) }}" class="btn btn-sm btn-outline-primary">編集</a>
<form method="POST" action="{{ route('parking_regulations_delete') }}" style="display:inline">
@csrf
<input type="hidden" name="parking_regulations_seq" value="{{ $r->parking_regulations_seq }}">
</form>
</td>
<td>{{ $r->psection_subject ?? $r->psection_id }}</td>
<td>{{ $r->ptype_subject ?? $r->ptype_id }}</td>
<td>{{ Str::limit($r->regulations_text ?? '', 200) }}</td>
</tr>
@empty
<tr>
<td colspan="4" class="text-center text-muted">規定がありません。</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<div class="mt-2">
{{ $regulations->appends(request()->query())->links('pagination') }}
</div>
</div>
</section>
@endsection

View File

@ -31,10 +31,10 @@
{{-- ボタンエリア(上部) --}} {{-- ボタンエリア(上部) --}}
<div class="mt-2"> <div class="mt-2">
<button type="button" class="btn btn-default mt-2 btn-submit">登録</button> <button type="button" class="btn btn-default mt-2 btn-submit">登録</button>
<a href="{{ route('reduction_confirm.list', ['park_id' => $park->park_id]) }}" class="btn btn-default mt-2"> <a href="{{ route('reduction_confirm_list', ['park_id' => $park->park_id]) }}" class="btn btn-default mt-2">
減免確認編集 減免確認編集
</a> </a>
<a href="javascript:void(0)" class="btn btn-default mt-2">駐輪状況編集</a> <a href="{{ route('parking_regulations_list', ['park_id' => $park->park_id]) }}" class="btn btn-default mt-2">駐輪規定編集</a>
<button type="button" class="btn btn-default mt-2">削除</button> <button type="button" class="btn btn-default mt-2">削除</button>
</div> </div>
</div> </div>

View File

@ -72,7 +72,7 @@
</div> </div>
<!-- 減免確認マスタ テーブル --> <!-- 減免確認マスタ テーブル -->
<div class="col-lg-12 px-0 "> <div class="col-lg-12 px-0 ">
<form action="{{ route('reduction_confirm.store') }}" method="POST" id="reduction-form"> <form action="{{ route('reduction_confirm_store') }}" method="POST" id="reduction-form">
<div class="d-flex justify-content-between align-items-center mb-2"> <div class="d-flex justify-content-between align-items-center mb-2">
{{-- 左側:登録ボタン --}} {{-- 左側:登録ボタン --}}
<button type="submit" class="btn btn-primary btn-submit">登録</button> <button type="submit" class="btn btn-primary btn-submit">登録</button>

View File

@ -39,7 +39,7 @@
<link href="{{ asset('css/app.css') }}" rel="stylesheet"> <link href="{{ asset('css/app.css') }}" rel="stylesheet">
<!-- kin 追加 --> <!-- kin 追加 -->
<link href="{{ asset('assets/css/app.css') }}" rel="stylesheet"> <link href="{{ asset('assets/css/app.css') }}" rel="stylesheet">
<link rel="stylesheet" href="{{ asset('plugins/summernote/summernote.min.css') }}">
</head> </head>
<body class="hold-transition sidebar-mini"> <body class="hold-transition sidebar-mini">
@ -982,6 +982,7 @@
<!-- jQuery --> <!-- jQuery -->
<script src="{{ asset('plugins/jquery/jquery.min.js') }}"></script> <script src="{{ asset('plugins/jquery/jquery.min.js') }}"></script>
<script src="{{ asset('plugins/summernote/summernote.min.js') }}"></script>
<script src="{{ asset('plugins/bootstrap/js/bootstrap.bundle.min.js') }}"></script> <script src="{{ asset('plugins/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
<script src="{{ asset('plugins/select2/js/select2.full.min.js') }}"></script> <script src="{{ asset('plugins/select2/js/select2.full.min.js') }}"></script>
<script src="{{ asset('plugins/moment/moment.min.js') }}"></script> <script src="{{ asset('plugins/moment/moment.min.js') }}"></script>

View File

@ -43,6 +43,7 @@ use App\Http\Controllers\Admin\InvSettingController;
use App\Http\Controllers\Admin\ZoneController; use App\Http\Controllers\Admin\ZoneController;
use App\Http\Controllers\Admin\PplaceController; use App\Http\Controllers\Admin\PplaceController;
use App\Http\Controllers\Admin\ReductionConfirmMasterController; use App\Http\Controllers\Admin\ReductionConfirmMasterController;
use App\Http\Controllers\Admin\ParkingRegulationsController;
use App\Http\Controllers\HomeController; use App\Http\Controllers\HomeController;
use App\Http\Controllers\Auth\EmailOtpController; use App\Http\Controllers\Auth\EmailOtpController;
@ -278,8 +279,15 @@ Route::middleware('auth')->group(function () {
Route::match(['get', 'post'], '/usertypes/export', [UsertypeController::class, 'export'])->name('usertypes_export'); Route::match(['get', 'post'], '/usertypes/export', [UsertypeController::class, 'export'])->name('usertypes_export');
// 減免確認マスタ // 減免確認マスタ
Route::get('/reduction-confirm-master', [ReductionConfirmMasterController::class, 'list'])->name('reduction_confirm.list'); Route::get('/reduction-confirm-master', [ReductionConfirmMasterController::class, 'list'])->name('reduction_confirm_list');
Route::post('/reduction-confirm-master', [ReductionConfirmMasterController::class, 'store'])->name('reduction_confirm.store'); Route::post('/reduction-confirm-master', [ReductionConfirmMasterController::class, 'store'])->name('reduction_confirm_store');
// 駐輪規定マスタ
Route::match(['get', 'post'], '/admin/parking-regulations', [ParkingRegulationsController::class, 'list'])->name('parking_regulations_list');
Route::match(['get', 'post'], '/admin/parking-regulations/add', [ParkingRegulationsController::class, 'add'])->name('parking_regulations_add');
Route::match(['get', 'post'], '/admin/parking-regulations/edit/{seq}', [ParkingRegulationsController::class, 'edit'])->name('parking_regulations_edit')->where(['seq' => '[0-9]+']);
Route::post('/admin/parking-regulations/update/{seq}', [ParkingRegulationsController::class, 'update'])->name('parking_regulations_update');
Route::post('/admin/parking-regulations/delete', [ParkingRegulationsController::class, 'delete'])->name('parking_regulations_delete');