filters(); $parks = $this->parkService->paginate($filters, 20); $cities = City::orderBy('city_id')->get(); $sort = $filters['sort'] ?? 'p.park_id'; $sort_type = $filters['sort_type'] ?? 'asc'; return view('admin.parks.index', compact( 'parks', 'cities', 'sort', 'sort_type' )); } /** * 新規(画面) */ public function create() { $cities = City::orderBy('city_id')->get(); return view('admin.parks.create', compact('cities')); } /** * 新規(登録) */ public function store(ParkRequest $request) { $operatorId = (int) (auth()->user()->ope_id ?? 1); $payload = $request->payload(); // 駐輪場五十音を設定 $payload['park_syllabary'] = $this->toSyllabaryGroup( $payload['park_ruby'] ?? null ); // 駐輪場五十音を設定してから Service に渡す $this->parkService->create( $payload, $operatorId ); return redirect() ->route('parks.index') ->with('success', __('新規登録に完了しました。')); } /** * 編集(画面) */ public function edit(int $id) { $record = $this->parkService->findOrFail($id); $cities = City::orderBy('city_id')->get(); return view('admin.parks.edit', compact( 'record', 'cities' )); } /** * 編集(更新) */ public function update(ParkRequest $request, int $id) { $park = $this->parkService->findOrFail($id); $operatorId = (int) (auth()->user()->ope_id ?? 1); $payload = $request->payload(); // 駐輪場五十音を設定 $payload['park_syllabary'] = $this->toSyllabaryGroup( $payload['park_ruby'] ?? null); // 駐輪場五十音を設定してから Service に渡す $this->parkService->update( $park, $payload, $operatorId); $this->parkService->update( $park, $request->payload(), $operatorId ); return redirect() ->route('parks.index') ->with('success', __('更新に成功しました。')); } /** * 削除(複数) */ public function destroy(Request $request) { $ids = (array) $request->input('pk', []); if (empty($ids)) { return redirect() ->route('parks.index') ->with('error', __('削除するデータを選択してください。')); } $ok = $this->parkService->deleteByIds($ids); return redirect() ->route('parks.index') ->with( $ok ? 'success' : 'error', $ok ? __('削除が完了しました。') : __('削除に失敗しました。') ); } /** * CSV 出力 */ public function export(): StreamedResponse { $columns = [ '駐輪場ID','市区','駐輪場名','駐輪場ふりがな','駐輪場五十音','住所', '閉設フラグ','閉設日','残警告チェックフラグ','印字数','最新キープアライブ', '更新オペレータID','更新期間開始日','更新期間開始時', '更新期間終了日','更新期間終了時','駐輪開始期間', 'リマインダー種別','リマインダー時間','契約後即利用許可', '項目表示設定:性別','項目表示設定:生年月日','項目表示設定:防犯登録番号', '二点間距離','駐車場座標(緯度)','駐車場座標(経度)','電話番号', '駐輪場契約形態(定期)','駐輪場契約形態(一時利用)', '車種制限','手続方法','支払方法', '利用可能時間制限フラグ','利用可能時間(開始)','利用可能時間(終了)', '常駐管理人フラグ','常駐時間(開始)','常駐時間(終了)', '屋根フラグ','シール発行機フラグ','駐輪場利用方法', '定期更新期間','空き待ち予約','特記事項','学生証確認種別', '減免案内表示フラグ','減免対象年齢','減免案内表示開始月数','年跨ぎ', ]; $rows = $this->parkService->exportRows(); return response()->streamDownload(function () use ($rows, $columns) { $fp = fopen('php://output', 'w'); fwrite($fp, "\xEF\xBB\xBF"); fputcsv($fp, $columns); foreach ($rows as $r) { fputcsv($fp, [ $r->park_id, $r->city_id, $r->park_name, $r->park_ruby, $r->park_syllabary, $r->park_adrs, $r->park_close_flag, $r->park_day, $r->alert_flag, $r->print_number, $r->keep_alive, $r->operator_id, $r->update_grace_period_start_date, $r->update_grace_period_start_time, $r->update_grace_period_end_date, $r->update_grace_period_end_time, $r->parking_start_grace_period, $r->reminder_type, $r->reminder_time, $r->immediate_use_permit, $r->gender_display_flag, $r->bd_display_flag, $r->securityreg_display_flag, $r->distance_twopoints, $r->park_latitude, $r->park_longitude, $r->park_tel, $r->park_fixed_contract, $r->park_temporary_contract, $r->park_restriction, $r->park_procedure, $r->park_payment, $r->park_available_time_flag, $r->park_available_time_from, $r->park_available_time_to, $r->park_manager_flag, $r->park_manager_resident_from, $r->park_manager_resident_to, $r->park_roof_flag, $r->park_issuing_machine_flag, $r->park_using_method, $r->park_contract_renewal_term, $r->park_reservation, $r->park_reference, $r->student_id_confirm_type, $r->reduction_guide_display_flag, $r->reduction_age, $r->reduction_guide_display_start_month, $r->overyear_flag, ]); } fclose($fp); }, '駐輪場マスタ.csv', [ 'Content-Type' => 'text/csv; charset=UTF-8', ]); } /** * 重複チェック(AJAX) */ public function checkDuplicate(Request $request) { $parkName = (string) $request->input('park_name', ''); if ($parkName === '') { return response()->json(['duplicate' => false]); } $dup = $this->parkService->checkDuplicateByName($parkName); if (!$dup) { return response()->json(['duplicate' => false]); } return response()->json([ 'duplicate' => true, 'park_id' => $dup->park_id, 'park_name' => $dup->park_name, ]); } private function toSyllabaryGroup(?string $ruby): ?string { $ruby = trim((string) $ruby); if ($ruby === '') { return null; } // 先取第1文字(UTF-8) $first = mb_substr($ruby, 0, 1, 'UTF-8'); // 小书き/濁点などを正規化(必要最低限) $map = [ 'が'=>'か','ぎ'=>'き','ぐ'=>'く','げ'=>'け','ご'=>'こ', 'ざ'=>'さ','じ'=>'し','ず'=>'す','ぜ'=>'せ','ぞ'=>'そ', 'だ'=>'た','ぢ'=>'ち','づ'=>'つ','で'=>'て','ど'=>'と', 'ば'=>'は','び'=>'ひ','ぶ'=>'ふ','べ'=>'へ','ぼ'=>'ほ', 'ぱ'=>'は','ぴ'=>'ひ','ぷ'=>'ふ','ぺ'=>'へ','ぽ'=>'ほ', 'ぁ'=>'あ','ぃ'=>'い','ぅ'=>'う','ぇ'=>'え','ぉ'=>'お', 'ゃ'=>'や','ゅ'=>'ゆ','ょ'=>'よ','っ'=>'つ', 'ゎ'=>'わ', ]; $first = $map[$first] ?? $first; // グループ判定(先頭文字で分類) $groups = [ 'あ' => ['あ','い','う','え','お'], 'か' => ['か','き','く','け','こ'], 'さ' => ['さ','し','す','せ','そ'], 'た' => ['た','ち','つ','て','と'], 'な' => ['な','に','ぬ','ね','の'], 'は' => ['は','ひ','ふ','へ','ほ'], 'ま' => ['ま','み','む','め','も'], 'や' => ['や','ゆ','よ'], 'ら' => ['ら','り','る','れ','ろ'], 'わ' => ['わ','を','ん'], ]; foreach ($groups as $head => $chars) { if (in_array($first, $chars, true)) { return $head; } } // ひらがな以外(空/英数など)は null return null; } }