input('sort', 'city_id'); $sortType = $request->input('sort_type', 'asc'); $page = $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(20); // インデックス超過処理 if ($list->total() > 0 && $page > $list->lastPage()) { return redirect()->route('city', [ 'sort' => $sort, 'sort_type' => $sortType, ]); } return view('admin.CityMaster.list', [ 'isMethodPost' => $request->isMethod('post'), 'sort' => $sort, 'sort_type' => $sortType, 'list' => $list, 'page' => $page, ]); } public function add(Request $request) { $inputs = [ 'city_name' => '', 'print_layout' => '', 'city_user' => '', 'city_remarks' => '', ]; if ($request->isMethod('POST')) { $rules = [ 'city_name' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], 'print_layout' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], 'city_user' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], 'city_remarks' => ['nullable', 'string', 'max:20'], ]; $messages = [ 'city_name.required' => '市区名は必須です。', 'city_name.regex' => '市区名は全角で入力してください。', 'print_layout.required' => '印字レイアウトファイルは必須です。', 'print_layout.regex' => '印字レイアウトファイルは全角で入力してください。', 'city_user.required' => '顧客M入力不要フィールドIDは必須です。', 'city_user.regex' => '顧客M入力不要フィールドIDは全角で入力してください。', 'city_remarks.max' => '備考は20文字以内で入力してください。', ]; $validator = Validator::make($request->all(), $rules, $messages); $inputs = array_merge($inputs, $request->all()); if (!$validator->fails()) { $maxId = DB::table('city')->max('city_id'); $newCityId = $maxId ? $maxId + 1 : 1; $city = new City(); $city->city_id = $newCityId; $city->fill($request->only([ 'city_name', 'print_layout', 'city_user', 'city_remarks', ])); if ($city->save()) { $request->session()->flash('success', __('登録に成功しました')); return redirect()->route('city'); } else { $request->session()->flash('error', __('登録に失敗しました')); } } else { $inputs['errorMsg'] = $validator->errors()->all(); } } return view('admin.CityMaster.add', $inputs); } public function edit(Request $request, $pk, $view = '') { $city = City::find($pk); if (!$city) { abort(404); } // メニューアクセス制御確認 $menuAccessService = app(\App\Services\MenuAccessService::class); if (!$menuAccessService->canAccessCity($city->city_id)) { abort(403, 'この自治体へのアクセス権限がありません。'); } if ($request->isMethod('POST')) { $rules = [ 'city_name' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], 'print_layout' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], 'city_user' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], 'city_remarks' => ['nullable', 'string', 'max:20'], ]; $messages = [ 'city_name.required' => '市区名は必須です。', 'city_name.regex' => '市区名は全角で入力してください。', 'print_layout.required' => '印字レイアウトファイルは必須です。', 'print_layout.regex' => '印字レイアウトファイルは全角で入力してください。', 'city_user.required' => '顧客M入力不要フィールドIDは必須です。', 'city_user.regex' => '顧客M入力不要フィールドIDは全角で入力してください。', 'city_remarks.max' => '備考は20文字以内で入力してください。', ]; $validator = Validator::make($request->all(), $rules, $messages); if (!$validator->fails()) { $city->fill($request->only([ 'city_name', 'print_layout', 'city_user', 'city_remarks', ])); if ($city->save()) { $request->session()->flash('success', __('更新に成功しました')); return redirect()->route('city'); } else { $request->session()->flash('error', __('更新に失敗しました')); } } else { return view('admin.CityMaster.edit', [ 'city' => $city, 'errorMsg' => $validator->errors()->all(), ]); } } return view($view ?: 'admin.CityMaster.edit', [ 'city' => $city, ]); } public function info(Request $request, $pk) { return $this->edit($request, $pk, 'CityMaster.info'); } 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', __("削除が完了しました。")); } else { return redirect()->route('city')->with('error', __('削除に失敗しました。')); } } /** * 自治体ダッシュボード */ 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)); // 予約待ち人数を取得(valid_flag = 1 かつ reserve_order が設定されているもの) $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')); } }