krgm.so-manager-dev.com/app/Http/Controllers/Admin/CityController.php
kin.rinzen 57199fe92b
All checks were successful
Deploy main / deploy (push) Successful in 22s
市区マスタ規約修正
2026-02-05 19:54:35 +09:00

262 lines
8.0 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use App\Models\City;
class CityController extends Controller
{
public function list(Request $request)
{
$sort = $request->input('sort', 'city_id');
$sortType = $request->input('sort_type', 'asc');
$page = (int)$request->get('page', 1);
$menuAccessService = app(\App\Services\MenuAccessService::class);
// メニューアクセス制御: 非ソーリンユーザーは所属自治体のみ表示
$query = City::query();
if (!$menuAccessService->isSorin()) {
$operator = auth()->user();
if ($operator && isset($operator->management_id)) {
$query->where('management_id', $operator->management_id);
}
}
if ($request->filled('city_name')) {
$query->where('city_name', 'like', '%' . $request->input('city_name') . '%');
}
if (!empty($sort)) {
$query->orderBy($sort, $sortType);
}
$list = $query->paginate(50);
// インデックス超過処理
if ($list->total() > 0 && $page > $list->lastPage()) {
return redirect()->route('city', [
'sort' => $sort,
'sort_type' => $sortType,
]);
}
return view('admin.cities.list', [
'sort' => $sort,
'sort_type' => $sortType,
'list' => $list,
'page' => $page,
]);
}
/** 新規画面 */
public function add(Request $request)
{
$record = new City();
return view('admin.cities.add', [
'record' => $record,
'errorMsg' => [],
]);
}
/** 登録 */
public function store(Request $request)
{
[$rules, $messages] = $this->rulesAndMessages();
$validator = Validator::make($request->all(), $rules, $messages);
$record = new City();
if ($validator->fails()) {
$record->fill($request->only(['city_name', 'print_layout', 'city_remarks']));
return view('admin.cities.add', [
'record' => $record,
'errorMsg' => $validator->errors()->all(),
]);
}
$maxId = DB::table('city')->max('city_id');
$newCityId = $maxId ? $maxId + 1 : 1;
$record->city_id = $newCityId;
$record->fill($request->only([
'city_name',
'print_layout',
'city_remarks',
]));
if ($record->save()) {
return redirect()->route('city')->with('success', __('登録に成功しました'));
}
return back()->withInput()->with('error', __('登録に失敗しました'));
}
/** 編集画面 */
public function edit(Request $request, $id)
{
$record = City::find($id);
if (!$record) {
abort(404);
}
$this->authorizeCityAccess($record);
return view('admin.cities.edit', [
'record' => $record,
'errorMsg' => [],
]);
}
/** 更新 */
public function update(Request $request, $id)
{
$record = City::find($id);
if (!$record) {
abort(404);
}
$this->authorizeCityAccess($record);
[$rules, $messages] = $this->rulesAndMessages();
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()) {
// 画面に戻る時に入力を保持
$record->fill($request->only(['city_name', 'print_layout', 'city_remarks']));
return view('admin.cities.edit', [
'record' => $record,
'errorMsg' => $validator->errors()->all(),
]);
}
$record->fill($request->only([
'city_name',
'print_layout',
'city_remarks',
]));
if ($record->save()) {
return redirect()->route('city')->with('success', __('更新に成功しました'));
}
return back()->withInput()->with('error', __('更新に失敗しました'));
}
public function delete(Request $request)
{
$arr_pk = $request->get('pk');
if (!$arr_pk) {
return redirect()->route('city')->with('error', __('削除する市区を選択してください。'));
}
if (City::destroy($arr_pk)) {
return redirect()->route('city')->with('success', __("削除が完了しました。"));
}
return redirect()->route('city')->with('error', __('削除に失敗しました。'));
}
private function rulesAndMessages(): array
{
$rules = [
// 市区名:全角 / 必須 / 最大20文字
'city_name' => [
'required',
'string',
'max:20',
'regex:/^[^ -~。-゚]+$/u',
],
// 印字レイアウトファイル:半角英数字 / 必須 / 最大255文字
'print_layout' => [
'required',
'string',
'max:255',
'regex:/^[A-Za-z0-9]+$/',
],
// 備考:任意 / 最大255文字
'city_remarks' => [
'nullable',
'string',
'max:255',
],
];
$messages = [
'city_name.required' => '市区名は必須です。',
'city_name.regex' => '市区名は全角文字で入力してください。',
'city_name.max' => '市区名は20文字以内で入力してください。',
'print_layout.required' => '印字レイアウトファイルは必須です。',
'print_layout.regex' => '印字レイアウトファイルは半角英数字で入力してください。',
'print_layout.max' => '印字レイアウトファイルは255文字以内で入力してください。',
'city_remarks.max' => '備考は255文字以内で入力してください。',
];
return [$rules, $messages];
}
private function authorizeCityAccess(City $city): void
{
$menuAccessService = app(\App\Services\MenuAccessService::class);
if (!$menuAccessService->canAccessCity($city->city_id)) {
abort(403, 'この自治体へのアクセス権限がありません。');
}
}
/**
* 自治体ダッシュボード(そのまま残すなら、別途 route 追加が必要)
*/
public function dashboard(Request $request, $city_id)
{
$city = City::find($city_id);
if (!$city) {
return redirect()->route('city')->with('error', '指定された自治体が見つかりません。');
}
$parks = \App\Models\Park::where('city_id', $city_id)->get();
$parkIds = $parks->pluck('park_id')->toArray();
$contractsCount = 0;
$usersCount = 0;
$waitingCount = 0;
if (!empty($parkIds)) {
$contractsCount = \App\Models\RegularContract::whereIn('park_id', $parkIds)->count();
$userIds = \App\Models\RegularContract::whereIn('park_id', $parkIds)
->distinct()
->pluck('user_id')
->toArray();
$usersCount = count(array_filter($userIds));
$waitingCount = DB::table('reserve')
->whereIn('park_id', $parkIds)
->where('valid_flag', 1)
->whereNotNull('reserve_order')
->where('reserve_order', '>', 0)
->count();
}
$stats = [
'parks_count' => $parks->count(),
'contracts_count' => $contractsCount,
'users_count' => $usersCount,
'waiting_count' => $waitingCount,
];
return view('admin.CityMaster.dashboard', compact('city', 'parks', 'stats'));
}
}