input('sort', 'reserve_id'); $sortType = strtolower($request->input('sort_type', 'asc')) === 'desc' ? 'desc' : 'asc'; // ── 絞り込み(必要最低限:利用者/駐輪場/期間)────────────────── $userId = trim((string) $request->input('user_id', '')); $parkId = trim((string) $request->input('park_id', '')); $fromDt = $request->input('reserve_date_from', ''); $toDt = $request->input('reserve_date_to', ''); $keyword = trim((string) $request->input('keyword', '')); // 利用者名かな など $validFlag = trim((string) $request->input('valid_flag', '')); $mailSentFrom = $request->input('mail_sent_from', ''); $mailSentTo = $request->input('mail_sent_to', ''); $priceUnion = DB::query()->fromSub(function ($sub) { $sub->from('price_a') ->select('price_parkplaceid', 'prine_name') ->unionAll( DB::table('price_b')->select('price_parkplaceid', 'prine_name') ); }, 'price_union'); // ── クエリ構築 ──────────────────────────────────────────────── $q = DB::table('reserve as r') ->leftJoin('user as u', 'u.user_id', '=', 'r.user_id') ->leftJoin('park as p', 'p.park_id', '=', 'r.park_id') ->leftJoin('psection as ps', 'ps.psection_id', '=', 'r.psection_id') ->leftJoin('ptype as pt', 'pt.ptype_id', '=', 'r.ptype_id') ->leftJoin('usertype as t', 't.user_categoryid', '=', 'r.user_categoryid') ->leftJoinSub($priceUnion, 'price_union', function ($join) { $join->on('price_union.price_parkplaceid', '=', 'r.price_parkplaceid'); }) ->select([ 'r.reserve_id', 'r.contract_id', 'r.contract_created_at', 'r.user_id', 'r.park_id', 'r.price_parkplaceid', 'r.psection_id', 'r.reserve_date', 'r.reserve_start', 'r.reserve_end', 'r.reserve_reduction', 'r.reserve_auto_remind', 'r.reserve_manual_remind', DB::raw('r.`800m_flag` as flag_800m'), 'r.reserve_cancelday', 'r.valid_flag', 'r.reserve_manual', 'r.reserve_notice', 'r.sent_date', 'r.reserve_order', 'r.valid_flag', 'r.ope_id', 'r.user_categoryid', DB::raw('u.user_name as user_name'), DB::raw('u.user_phonetic as user_phonetic'), DB::raw('u.user_mobile as user_mobile'), DB::raw('p.park_name as park_name'), DB::raw('pt.ptype_subject as ptype_subject'), DB::raw('ps.psection_subject as psection_subject'), DB::raw('price_union.price_parkplaceid as display_price_parkplaceid'), DB::raw('price_union.prine_name as display_prine_name'), DB::raw('t.usertype_subject1 as usertype_subject1'), DB::raw('t.usertype_subject2 as usertype_subject2'), DB::raw('t.usertype_subject3 as usertype_subject3'), ]); if ($userId !== '') $q->where('r.user_id', 'like', "%{$userId}%"); if ($parkId !== '') $q->where('r.park_id', '=', (int) $parkId); if ($fromDt) $q->whereDate('r.reserve_date', '>=', $fromDt); if ($toDt) $q->whereDate('r.reserve_date', '<=', $toDt); if ($keyword !== '') { $q->where(function ($w) use ($keyword) { $w->where('u.user_name', 'like', "%{$keyword}%") ->orWhere('u.user_phonetic', 'like', "%{$keyword}%"); }); } if (in_array($validFlag, ['0', '1'], true)) { $q->where('r.valid_flag', '=', (int) $validFlag); } if ($mailSentFrom !== null && $mailSentFrom !== '') { $q->where('r.sent_date', '>=', $mailSentFrom); } if ($mailSentTo !== null && $mailSentTo !== '') { $q->where('r.sent_date', '<=', $mailSentTo); } // ソート許可カラム(JOIN 先も含む) $sortable = [ 'reserve_id', 'contract_id', 'contract_created_at', 'user_categoryid', 'user_id', 'reserve_date', 'park_price_name', 'price_parkplaceid', 'psection_subject', 'ptype_subject', 'park_name', 'reserve_reduction', 'reserve_auto_remind', 'reserve_manual_remind', 'flag_800m', 'reserve_cancelday', 'valid_flag', 'sent_date', 'reserve_manual', 'reserve_notice', 'reserve_order', ]; if (!in_array($sort, $sortable, true)) { $sort = 'reserve_id'; } $sortMap = [ 'reserve_id' => DB::raw('r.reserve_id'), 'contract_id' => DB::raw('r.contract_id'), 'contract_created_at' => DB::raw('r.contract_created_at'), 'user_categoryid' => DB::raw('r.user_categoryid'), 'user_id' => DB::raw('r.user_id'), 'reserve_date' => DB::raw('r.reserve_date'), 'park_price_name' => DB::raw('price_union.prine_name'), 'price_parkplaceid' => DB::raw('r.price_parkplaceid'), 'psection_subject' => DB::raw('ps.psection_subject'), 'ptype_subject' => DB::raw('pt.ptype_subject'), 'park_name' => DB::raw('p.park_name'), 'reserve_reduction' => DB::raw('r.reserve_reduction'), 'reserve_auto_remind' => DB::raw('r.reserve_auto_remind'), 'reserve_manual_remind' => DB::raw('r.reserve_manual_remind'), 'flag_800m' => DB::raw('r.`800m_flag`'), 'reserve_cancelday' => DB::raw('r.reserve_cancelday'), 'valid_flag' => DB::raw('r.valid_flag'), 'sent_date' => DB::raw('r.sent_date'), 'reserve_manual' => DB::raw('r.reserve_manual'), 'reserve_notice' => DB::raw('r.reserve_notice'), 'reserve_order' => DB::raw('r.reserve_order'), ]; $sortColumn = $sortMap[$sort] ?? DB::raw('r.reserve_id'); $q->orderBy($sortColumn, $sortType); $parkOptions = Park::query() ->orderBy('park_id', 'asc') ->pluck('park_name', 'park_id') ->toArray(); $list = $q->paginate(50); $placeIds = $list->getCollection() ->pluck('price_parkplaceid') ->filter() ->unique() ->values() ->all(); if (!empty($placeIds)) { $priceNamesA = PriceA::query() ->whereIn('price_parkplaceid', $placeIds) ->pluck('prine_name', 'price_parkplaceid') ->toArray(); $priceNamesB = PriceB::query() ->whereIn('price_parkplaceid', $placeIds) ->pluck('prine_name', 'price_parkplaceid') ->toArray(); // 駐輪場所名のマッピング(price_b で上書き) $priceNames = array_replace($priceNamesA, $priceNamesB); $list->setCollection( $list->getCollection()->map(function ($row) use ($priceNames) { $id = $row->price_parkplaceid ?? null; $row->display_prine_name = ($id !== null && array_key_exists($id, $priceNames)) ? $priceNames[$id] : null; return $row; }) ); } return view('admin.reserves.list', [ 'list' => $list, 'sort' => $sort, 'sort_type' => $sortType, // 入力保持 'user_id' => $userId, 'park_id' => $parkId, 'reserve_date_from' => $fromDt, 'reserve_date_to' => $toDt, 'keyword' => $keyword, 'valid_flag' => $validFlag, 'mail_sent_from' => $mailSentFrom, 'mail_sent_to' => $mailSentTo, 'parkOptions' => $parkOptions, ]); } /** * 予約追加(GET: 画面表示 / POST: 登録) */ public function add(Request $request) { if ($request->isMethod('get')) { $userTypes = DB::table('usertype') ->orderBy('user_categoryid', 'asc') ->get([ 'user_categoryid', 'usertype_subject1', 'usertype_subject2', 'usertype_subject3', ]) ->map(function ($row) { $labels = array_filter([ $row->usertype_subject1, $row->usertype_subject2, $row->usertype_subject3, ], fn ($v) => $v !== null && $v !== ''); $row->display_name = $labels ? implode('/', $labels) : ''; return $row; }); $parks = Park::query() ->orderBy('park_id', 'asc') ->get(['park_id', 'park_name']); $priceA = PriceA::query() ->select('price_parkplaceid', 'prine_name') ->get(); $priceB = PriceB::query() ->select('price_parkplaceid', 'prine_name') ->get(); $priceOptions = $priceA->merge($priceB) ->sortBy('price_parkplaceid', SORT_NATURAL) ->unique('price_parkplaceid') ->values(); return view('admin.reserves.add', [ 'userTypes' => $userTypes, 'parks' => $parks, 'priceOptions' => $priceOptions, ]); } // 予約の最低限バリデーション(必要に応じて追加) $v = Validator::make($request->all(), [ 'user_id' => ['required', 'integer'], 'park_id' => ['required', 'integer'], 'reserve_date' => ['nullable', 'date'], 'reserve_start' => ['nullable', 'date'], 'reserve_end' => ['nullable', 'date'], ], [], [ 'user_id' => '利用者ID', 'park_id' => '駐輪場ID', ]); if ($v->fails()) { return back()->withErrors($v)->withInput(); } $now = now(); $opeId = optional(Auth::user())->ope_id; $nextReserveId = DB::transaction(function () { $currentMax = DB::table('reserve')->max('reserve_id'); return $currentMax ? $currentMax + 1 : 1; }); DB::table('reserve')->insert([ 'reserve_id' => $nextReserveId, 'user_id' => (int) $request->input('user_id'), 'park_id' => (int) $request->input('park_id'), 'contract_id' => $request->input('contract_id'), 'price_parkplaceid' => $request->input('price_parkplaceid'), 'psection_id' => $request->input('psection_id'), 'reserve_date' => $request->input('reserve_date'), 'reserve_start' => $now, 'reserve_end' => $now, 'valid_flag' => $request->input('valid_flag'), 'ope_id' => $opeId, 'created_at' => $now, 'updated_at' => $now, ]); return redirect()->route('reserves')->with('success', '予約を登録しました。'); } /** * 予約削除 */ public function delete(Request $request) { $normalizeIds = function ($raw) { if (is_string($raw)) { $raw = explode(',', $raw); } if (is_array($raw) && count($raw) === 1 && is_string($raw[0]) && str_contains($raw[0], ',')) { $raw = explode(',', $raw[0]); } $ids = array_map('intval', (array) $raw); $ids = array_values(array_unique(array_filter($ids, fn($v) => $v > 0))); return $ids; }; if ($request->isMethod('get')) { $ids = $normalizeIds($request->input('ids', [])); $rows = []; if ($ids) { $rows = DB::table('reserve as r') ->leftJoin('user as u', 'u.user_id', '=', 'r.user_id') ->leftJoin('park as p', 'p.park_id', '=', 'r.park_id') ->whereIn('r.reserve_id', $ids) ->select('r.*', 'u.user_name', 'p.park_name') ->get(); } return view('admin.reserves.delete', compact('rows', 'ids')); } if ($request->post('confirmed')) { $ids = $normalizeIds($request->input('ids', [])); if ($ids) { $deleted = DB::table('reserve')->whereIn('reserve_id', $ids)->delete(); return redirect()->route('reserves')->with( $deleted ? 'success' : 'warning', $deleted ? "{$deleted} 件を削除しました。" : '対象が見つかりませんでした。' ); } } return redirect()->route('reserves')->with('warning', '削除対象がありません。'); } public function edit(Request $request, $reserve_id) { $id = (int) $reserve_id; // 取得レコード(無ければ404) $row = DB::table('reserve')->where('reserve_id', $id)->first(); if (!$row) { abort(404); } // POST: 更新処理(※reserveテーブルに確実にある列だけ更新) if ($request->isMethod('post')) { $v = Validator::make($request->all(), [ 'user_id' => ['required', 'integer'], 'park_id' => ['required', 'integer'], 'reserve_date' => ['nullable', 'date'], 'reserve_start' => ['nullable', 'date'], 'reserve_end' => ['nullable', 'date'], ], [], [ 'user_id' => '利用者ID', 'park_id' => '駐輪場ID', ]); if ($v->fails()) { return back()->withErrors($v)->withInput(); } $data = [ 'contract_id' => $request->input('contract_id'), 'user_id' => (int) $request->input('user_id'), 'park_id' => (int) $request->input('park_id'), 'price_parkplaceid' => $request->input('price_parkplaceid'), 'psection_id' => $request->input('psection_id'), 'reserve_date' => $request->input('reserve_date'), 'reserve_start' => $request->input('reserve_start'), 'reserve_end' => $request->input('reserve_end'), 'valid_flag' => $request->input('valid_flag'), 'ope_id' => $request->input('ope_id'), 'updated_at' => now(), ]; DB::table('reserve')->where('reserve_id', $id)->update($data); return redirect()->route('reserves')->with('success', '予約を更新しました。'); } // GET: 編集画面表示用の各種プルダウン(存在するテーブルだけ読む) $userOptions = DB::table('user') ->orderBy('user_id', 'asc') ->limit(5000) ->pluck(DB::raw("concat(user_id, ' ', user_name)"), 'user_id') ->toArray(); $parkOptions = DB::table('park') ->orderBy('park_id', 'asc') ->pluck('park_name', 'park_id') ->toArray(); $userTypeOptions = Schema::hasTable('usertype') ? DB::table('usertype')->orderBy('user_categoryid') ->pluck('print_name', 'user_categoryid')->toArray() : []; $parkplaceOptions = Schema::hasTable('price_parkplace') ? DB::table('price_parkplace')->orderBy('price_parkplaceid') ->pluck('price_parkplaceid', 'price_parkplaceid')->toArray() : []; $psectionOptions = Schema::hasTable('psection') ? DB::table('psection')->orderBy('psection_id') ->pluck( Schema::hasColumn('psection', 'psection_name') ? 'psection_name' : 'psection_id', 'psection_id' )->toArray() : []; $ptypeOptions = Schema::hasTable('ptype') ? DB::table('ptype')->orderBy('ptype_id') ->pluck( Schema::hasColumn('ptype', 'ptype_name') ? 'ptype_name' : 'ptype_id', 'ptype_id' )->toArray() : []; return view('admin.reserves.edit', compact( 'row', 'userOptions', 'parkOptions', 'userTypeOptions', 'parkplaceOptions', 'psectionOptions', 'ptypeOptions' )); } }