diff --git a/app/Http/Controllers/ParkWaitlistController.php b/app/Http/Controllers/ParkWaitlistController.php new file mode 100644 index 0000000..51389b9 --- /dev/null +++ b/app/Http/Controllers/ParkWaitlistController.php @@ -0,0 +1,184 @@ +where('user_id', $user_id)->first(); + + // 空き待ち予約状況データ取得 + $waitlists = DB::table('reserve') + ->where('reserve.user_id', $user_id) + ->where('reserve.valid_flag', 1) + ->leftJoin('park', 'reserve.park_id', '=', 'park.park_id') + ->leftJoin('station', 'park.park_id', '=', 'station.park_id') + ->leftJoin('ptype', 'reserve.ptype_id', '=', 'ptype.ptype_id') + ->leftJoin('psection', 'reserve.psection_id', '=', 'psection.psection_id') + ->select( + 'reserve.reserve_id', + 'reserve.reserve_date', + 'park.park_name', + 'station.station_neighbor_station', + 'ptype.ptype_subject', + 'psection.psection_subject' + ) + ->orderBy('reserve.reserve_date', 'desc') + ->get(); + + \Log::info('空き待ち状況確認画面にアクセス', [ + 'user_id' => $user_id, + ]); + + return view('park_waitlist.index', [ + 'active_menu' => 'SWC-11-1', // この画面のID + 'user_name' => $user ? $user->user_name : '', // ユーザー名(ヘッダー用) + 'waitlists' => $waitlists, + ]); + } + + public function check(Request $request) + { + $user_id = session('user_id'); + if (!$user_id) { + return redirect('/login'); + } + + $park_id = $request->input('park_id'); + $psection_id = $request->input('psection_id'); + $ptype_id = $request->input('ptype_id'); + + $existingReservation = DB::table('reserve') + ->where('user_id', $user_id) + ->where('park_id', $park_id) + ->where('psection_id', $psection_id) + ->where('ptype_id', $ptype_id) + ->where('valid_flag', 1) + ->first(); + + if ($existingReservation) { + return response()->json(['status' => 'exists']); + } else { + return response()->json(['status' => 'ok']); + } + } + + public function create(Request $request) + { + $user_id = session('user_id'); + if (!$user_id) { + return redirect('/login'); + } + $user = DB::table('user')->where('user_id', $user_id)->first(); + + $park_id = $request->input('park_id'); + $psection_id = $request->input('psection_id'); + $ptype_id = $request->input('ptype_id'); + + // 予約順を決定 + $reserve_order = DB::table('reserve') + ->where('park_id', $park_id) + ->where('psection_id', $psection_id) + ->where('ptype_id', $ptype_id) + ->where('valid_flag', 1) + ->count() + 1; + + // 予約情報を追加 + DB::table('reserve')->insert([ + 'created_at' => now(), + 'updated_at' => now(), + 'user_categoryid' => $user->user_categoryid, + 'user_id' => $user_id, + 'park_id' => $park_id, + 'psection_id' => $psection_id, + 'reserve_date' => now(), + 'valid_flag' => 1, + 'ptype_id' => $ptype_id, + 'reserve_order' => $reserve_order + ]); + + return redirect()->route('park_waitlist.index'); + } + + public function cancelConfirm($reserve_id) + { + $user_id = session('user_id'); + if (!$user_id) { + return redirect('/login'); + } + $user_name = DB::table('user')->where('user_id', $user_id)->value('user_name'); + + \Log::info('空き待ち状況確認 - キャンセル確認画面にアクセス', [ + 'user_id' => $user_id, + ]); + + return view('park_waitlist.cancel', [ + 'active_menu' => 'SWC-11-1', // この画面のID + 'user_name' => $user_name, // ユーザー名(ヘッダー用) + 'reserve_id' => $reserve_id, + ]); + } + + public function cancel($reserve_id) + { + $user_id = session('user_id'); + if (!$user_id) { + return redirect('/login'); + } + $user = DB::table('user')->where('user_id', $user_id)->first(); + + // 定期予約をキャンセル + DB::table('reserve')->where('reserve_id', $reserve_id)->update([ + 'valid_flag' => 0, + 'updated_at' => now(), + 'reserve_cancelday' => date('Y-m-d'), + ]); + + // メール送信用データ取得 + $reserve = DB::table('reserve') + ->leftJoin('park', 'reserve.park_id', '=', 'park.park_id') + ->leftJoin('psection', 'reserve.psection_id', '=', 'psection.psection_id') + ->leftJoin('ptype', 'reserve.ptype_id', '=', 'ptype.ptype_id') + ->select( + 'park.park_name', + 'psection.psection_subject', + 'ptype.ptype_subject' + ) + ->where('reserve.reserve_id', $reserve_id) + ->first(); + + // メール送信処理 + try { + Mail::to($user->user_primemail)->send( + new ReservationCancelledMail( + $user->user_name, + $reserve + ) + ); + } catch (\Exception $e) { + Log::error('予約キャンセルメール送信エラー: ' . $e->getMessage()); + } + + \Log::info('空き待ち状況確認 - キャンセル完了画面にアクセス', [ + 'user_id' => $user_id, + ]); + + return view('park_waitlist.cancel_complete', [ + 'reserve' => $reserve, + 'active_menu' => 'SWC-11-1', // この画面のID + 'user_name' => $user ? $user->user_name : '', // ユーザー名(ヘッダー用) + ]); + } +} diff --git a/app/Mail/ReservationCancelledMail.php b/app/Mail/ReservationCancelledMail.php new file mode 100644 index 0000000..79409d7 --- /dev/null +++ b/app/Mail/ReservationCancelledMail.php @@ -0,0 +1,31 @@ +user_name = $user_name; + $this->reserve = $reserve; + } + + public function build() + { + return $this->subject('So-Manager:空き待ちのキャンセルが完了しました') + ->view('emails.reservation_cancelled') + ->with([ + 'user_name' => $this->user_name, + 'reserve' => $this->reserve, + ]); + } +} diff --git a/resources/views/emails/reservation_cancelled.blade.php b/resources/views/emails/reservation_cancelled.blade.php new file mode 100644 index 0000000..87e3cf3 --- /dev/null +++ b/resources/views/emails/reservation_cancelled.blade.php @@ -0,0 +1,22 @@ +{!! nl2br(e( +$user_name . ' 様 + +So-Manager自動応答システムです。 + +下記駐輪場の空き待ちのキャンセルを受け付けました。 + +空き駐輪場: ' . $reserve->park_name . ' +車種区分 : ' . $reserve->psection_subject . ' +駐輪分類 : ' . $reserve->ptype_subject . ' + +So-Manager.comのユーザー登録は解約されておりません。別の駐輪場でのご契約や空き待ちをご希望の際には、マイページをご活用ください。 + + +■お問合せ先■ +So-Managerコールセンター(ソーマネージャーコールセンター) +●電話:03-5856-4720 +●メールでのお問合せ(専用フォームよりお問合わせください) + +※本メールアドレスは送信専用です。ご返信には回答致しかねますのでご了承ください。 +※本メールにお心あたりのない場合には、コールセンターまでご連絡くださいますようお願い致します。' +)) !!} \ No newline at end of file diff --git a/resources/views/park_waitlist/cancel.blade.php b/resources/views/park_waitlist/cancel.blade.php new file mode 100644 index 0000000..0efb498 --- /dev/null +++ b/resources/views/park_waitlist/cancel.blade.php @@ -0,0 +1,29 @@ +@extends('layouts.app') +@section('content') +
+
+

空き待ち状況確認 > キャンセル

+
+
+
+
+

キャンセルしますか?

+
    +
  • キャンセル確定を押されますと確認ページは表示されません。即キャンセルになりますのでご注意ください。
  • +
  • 一度キャンセルされると再度予約しても順番は最後になります。予めご了承ください。
  • +
  • 再度予約を希望の場合は、空き待ち申込からお手続きください。
  • +
+
+
+ 戻る +
+
+
+ @csrf + +
+
+
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/park_waitlist/cancel_complete.blade.php b/resources/views/park_waitlist/cancel_complete.blade.php new file mode 100644 index 0000000..d6b2aca --- /dev/null +++ b/resources/views/park_waitlist/cancel_complete.blade.php @@ -0,0 +1,19 @@ +@extends('layouts.app') +@section('content') +
+
+

空き待ち状況確認 > キャンセル完了

+
+
+
+
+

駐輪場名:{{ $reserve->park_name }}

+

上記の空き待ちキャンセルが完了しました。確認のメールを会員情報のメールアドレスに送信しました。

+
+ +
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/park_waitlist/index.blade.php b/resources/views/park_waitlist/index.blade.php new file mode 100644 index 0000000..cc24e9e --- /dev/null +++ b/resources/views/park_waitlist/index.blade.php @@ -0,0 +1,55 @@ +@extends('layouts.app') +@section('content') +
+ +
+

空き待ち状況確認 > 予約状況

+
+
+ @if($waitlists->count()) +
+ + + + + + + + + + + + @foreach($waitlists as $row) + + + + + + + + @endforeach + +
予約日駐輪場名駅名駐輪分類車種区分
{{ \Carbon\Carbon::parse($row->reserve_date)->format('Y/m/d') }} + {{ $row->park_name }} + {{ $row->station_neighbor_station }}{{ $row->ptype_subject }}{{ $row->psection_subject }}
+
+ @else +
予約している駐輪場はありません。
+ @endif +
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/park_waitlist/park_detail.blade.php b/resources/views/park_waitlist/park_detail.blade.php new file mode 100644 index 0000000..34e1e81 --- /dev/null +++ b/resources/views/park_waitlist/park_detail.blade.php @@ -0,0 +1,47 @@ + + + + + \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index b034ca1..9804dbb 100644 --- a/routes/web.php +++ b/routes/web.php @@ -83,102 +83,58 @@ Route::get('/mypage', function () { '; })->name('mypage'); -// ユーザー情報確認画面 -Route::get('/user/info', [UserInfoController::class, 'show']) - ->name('user.info'); +// ユーザー情報確認・編集 +Route::get('/user/info', [UserInfoController::class, 'show'])->name('user.info'); +Route::get('/user/edit', [UserEditController::class, 'show'])->name('user.edit'); +Route::post('/user/edit', [UserEditController::class, 'update'])->name('user.edit.post'); +Route::get('/user/edit/confirm', [UserEditConfirmController::class, 'show'])->name('user.confirm'); +Route::post('/user/edit/submit', [UserEditConfirmController::class, 'submit'])->name('user.edit.submit'); +Route::get('/user/edit/verify', [UserEditConfirmController::class, 'verify'])->name('user.edit.verify'); -// ユーザー情報編集画面(GET: 編集フォーム表示) -Route::get('/user/edit', [UserEditController::class, 'show']) - ->name('user.edit'); - -// ユーザー情報編集(POST: 編集内容保存) -Route::post('/user/edit', [UserEditController::class, 'update']) - ->name('user.edit.post'); - -// ユーザー情報編集確認 -Route::get('/user/edit/confirm', [UserEditConfirmController::class, 'show']) - ->name('user.confirm'); - -// 入力内容確認画面から「変更を確定する」ボタン押下時(認証メール送信) -Route::post('/user/edit/submit', [UserEditConfirmController::class, 'submit']) - ->name('user.edit.submit'); - -// 認証メール内URLクリック時(変更確定処理) -Route::get('/user/edit/verify', [UserEditConfirmController::class, 'verify']) - ->name('user.edit.verify'); - -// 退会画面(GET: 退会確認) -Route::get('/user/withdraw', [UserWithdrawController::class, 'showConfirm']) - ->name('user.withdraw'); -// 退会処理(POST: 退会確定) -Route::post('/user/withdraw/confirm', [UserWithdrawController::class, 'withdraw']) - ->name('user.withdraw.confirm'); +// 退会 +Route::get('/user/withdraw', [UserWithdrawController::class, 'showConfirm'])->name('user.withdraw'); +Route::post('/user/withdraw/confirm', [UserWithdrawController::class, 'withdraw'])->name('user.withdraw.confirm'); // 定期契約情報確認 -Route::get('regular_contract/info', [RegularContractController::class, 'showInfo']) - ->name('regular_contract.info'); +Route::get('regular_contract/info', [RegularContractController::class, 'showInfo'])->name('regular_contract.info'); -// 領収書宛名入力画面 -Route::get('receipt/input/{contract_id}', [ReceiptController::class, 'input']) - ->name('receipt.input'); -Route::get('receipt/download/{contract_id}', [ReceiptController::class, 'download']) - ->name('receipt.download'); +// 領収書発行 +Route::get('receipt/input/{contract_id}', [ReceiptController::class, 'input'])->name('receipt.input'); +Route::get('receipt/download/{contract_id}', [ReceiptController::class, 'download'])->name('receipt.download'); Route::post('receipt/issue/{contract_id}', [ReceiptController::class, 'issue']); -// 新規定期契約画面 -Route::get('regular_contract/create', [RegularContractCreateController::class, 'show']) - ->name('regular_contract.create'); +// 新規定期契約 +Route::get('regular_contract/create', [RegularContractCreateController::class, 'show'])->name('regular_contract.create'); Route::get('/api/park-detail/{park_id}', [ParkDetailController::class, 'show']); Route::get('/regular-contract/regulationCheck', [RegularContractCreateController::class, 'regulationCheck']); -Route::get('/regular-contract/regulation', [RegularContractCreateController::class, 'showRegulation']) - ->name('regular_contract.regulation'); +Route::get('/regular-contract/regulation', [RegularContractCreateController::class, 'showRegulation'])->name('regular_contract.regulation'); Route::post('/regular-contract/insertRegulation', [RegularContractCreateController::class, 'insertRegulation']); Route::get('/regular-contract/input', [RegularContractCreateController::class, 'showContractForm'])->name('regular_contract.input'); Route::post('/regular_contract/input/check', [RegularContractCreateController::class, 'inputCheck'])->name('regular_contract.input.check'); Route::get('/regular-contract/upload_identity_create', [RegularContractCreateController::class, 'showUploadIdentityCreate'])->name('regular_contract.upload_identity_create'); - Route::post('regular_contract/confirm_upload_identity/{contract_id}', [RegularContractCreateController::class, 'confirmUploadIdentity'])->name('regular_contract.confirm_upload_identity'); Route::get('regular_contract/create_confirm', [RegularContractCreateController::class, 'createConfirm'])->name('regular_contract.create_confirm'); Route::post('/regular_contract/create_confirm_next/{contract_id}', [RegularContractCreateController::class, 'createConfirmNext'])->name('regular_contract.create_confirm_next'); -Route::post('regular_contract/create_select_period', [RegularContractCreateController::class, 'selectPeriod']) - ->name('regular_contract.create_select_period'); +Route::post('regular_contract/create_select_period', [RegularContractCreateController::class, 'selectPeriod'])->name('regular_contract.create_select_period'); + // 定期契約更新 -Route::get('regular_contract/update', [RegularContractController::class, 'showInfo']) - ->name('regular_contract.update'); +Route::get('regular_contract/update', [RegularContractController::class, 'showInfo'])->name('regular_contract.update'); Route::get('regular_contract/update/{contract_id}', [RegularContractController::class, 'update']); -// 契約区分確認 -Route::get('regular_contract/confirm_category/{contract_id}', [RegularContractController::class, 'confirmCategory']) - ->name('regular_contract.confirm_category'); -Route::get('regular_contract/confirm_category_next/{contract_id}', [RegularContractController::class, 'confirmCategoryNext']) - ->name('regular_contract.confirm_category_next'); -// 本人確認書類アップロード -Route::get('regular_contract/upload_identity/{contract_id}', [RegularContractController::class, 'uploadIdentity']) - ->name('regular_contract.upload_identity'); -// 本人確認書類確認中 -Route::post('regular_contract/upload_identity/{contract_id}', [RegularContractController::class, 'uploadIdentitySubmit']) - ->name('regular_contract.upload_identity_submit'); -// 利用期間選択 -Route::get('regular_contract/select_period/{contract_id}', [RegularContractController::class, 'selectPeriod']) - ->name('regular_contract.select_period'); -Route::post('regular_contract/update_period', [RegularContractController::class, 'updatePeriod']) - ->name('regular_contract.update_period'); +Route::get('regular_contract/confirm_category/{contract_id}', [RegularContractController::class, 'confirmCategory'])->name('regular_contract.confirm_category'); +Route::get('regular_contract/confirm_category_next/{contract_id}', [RegularContractController::class, 'confirmCategoryNext'])->name('regular_contract.confirm_category_next'); +Route::get('regular_contract/upload_identity/{contract_id}', [RegularContractController::class, 'uploadIdentity'])->name('regular_contract.upload_identity'); +Route::post('regular_contract/upload_identity/{contract_id}', [RegularContractController::class, 'uploadIdentitySubmit'])->name('regular_contract.upload_identity_submit'); +Route::get('regular_contract/select_period/{contract_id}', [RegularContractController::class, 'selectPeriod'])->name('regular_contract.select_period'); +Route::post('regular_contract/update_period', [RegularContractController::class, 'updatePeriod'])->name('regular_contract.update_period'); // 定期契約履歴 -Route::get('regular_contract/history', [RegularContractController::class, 'showHistory']) - ->name('regular_contract.history'); +Route::get('regular_contract/history', [RegularContractController::class, 'showHistory'])->name('regular_contract.history'); + // 駐輪場検索 -Route::get('park_search', [RegularContractCreateController::class, 'show']) - ->name('park_search'); +Route::get('park_search', [RegularContractCreateController::class, 'show'])->name('park_search'); -// 空き待ち状況確認画面 -Route::get('park_waitlist', [ParkWaitlistController::class, 'index']) - ->name('park_waitlist.index'); - -Route::post('/login', function (Request $request) { - $user_id = $request->input('user_id'); - Session::put('user_id', $user_id); // 入力されたIDをそのまま保存 - return redirect('/user/info'); // 認証なしでリダイレクト -}); +// 空き待ち状況確認 +Route::get('park_waitlist', [ParkWaitlistController::class, 'index'])->name('park_waitlist.index'); // ウェルネット決済画面(仮) Route::get('/wellnet/payment', function (): mixed {