diff --git a/app/Http/Controllers/Admin/PplaceController.php b/app/Http/Controllers/Admin/PplaceController.php index 17fdc28..a9a4745 100644 --- a/app/Http/Controllers/Admin/PplaceController.php +++ b/app/Http/Controllers/Admin/PplaceController.php @@ -122,18 +122,15 @@ class PplaceController extends Controller public function export() { - $headers = [ - "Content-type" => "text/csv;charset=UTF-8", - "Content-Disposition" => "attachment; filename=Pplace.csv", - ]; + $filename = '駐輪車室マスタ' . now()->format('YmdHis') . '.csv'; - $data = Pplace::all(); - $columns = ['ID', '番号', '備考', 'オペレータID']; - - $filename = "Pplace.csv"; $file = fopen($filename, 'w+'); + fwrite($file, "\xEF\xBB\xBF"); // BOM追加(UTF-8) + + $columns = ['駐輪車室ID', '番号', '備考', 'オペレータID']; fputcsv($file, $columns); + $data = Pplace::all(); foreach ($data as $item) { fputcsv($file, [ $item->pplace_id, @@ -144,9 +141,16 @@ class PplaceController extends Controller } fclose($file); - return Response::download($filename, $filename, $headers); + + $headers = [ + "Content-Type" => "text/csv; charset=UTF-8", + "Content-Disposition" => "attachment; filename={$filename}", + ]; + + return response()->download($filename, $filename, $headers)->deleteFileAfterSend(true); } + public function import(Request $request) { $file = $request->file('file'); diff --git a/app/Http/Controllers/Admin/PriceController.php b/app/Http/Controllers/Admin/PriceController.php index 1d96168..d29744c 100644 --- a/app/Http/Controllers/Admin/PriceController.php +++ b/app/Http/Controllers/Admin/PriceController.php @@ -14,7 +14,6 @@ use Illuminate\Support\Facades\DB; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Validator; -// use Response; use Illuminate\Support\Facades\Response; class PriceController extends Controller @@ -137,62 +136,51 @@ class PriceController extends Controller return self::whereIn('price_parkplaceid', $ids)->delete(); } - public function exportGet(Request $request) + public function export() { - $headers = [ - "Content-Type" => "text/csv; charset=UTF-8", - "Content-Disposition" => "attachment; filename=駐輪場所、料金マスタ.csv", - ]; + $filename = '駐輪場所、料金マスタ' . now()->format('YmdHis') . '.csv'; - $query = Price::query(); + $file = fopen($filename, 'w+'); + fwrite($file, "\xEF\xBB\xBF"); // BOM追加(UTF-8) - // 🔹 パラメータ取得(GETでもOK) - if ($request->filled('park_id')) { - $query->where('park_id', $request->input('park_id')); - } - - if ($request->filled('sort')) { - $query->orderBy($request->input('sort'), $request->input('sort_type', 'asc')); - } - - $dataExport = $query->get(); - - // 🔹 CSV列定義 $columns = [ - '駐車場所ID', '商品名', '期間', '駐輪場ID', '駐輪場名', - '車種区分ID', '車種区分', '駐輪分類ID', '駐輪分類', - '利用者分類ID', '利用者分類', '駐車車室ID', '駐輪料金(税込)', + '駐輪場所ID', + '駐輪場ID', + '商品名', + '期間', + '利用者分類ID', + '駐輪料金(税込)', + '車種区分ID', + '駐輪分類ID', + '駐車車室ID', ]; - // 🔹 CSV生成 - $filename = '駐輪場所、料金マスタ.csv'; - $path = storage_path('app/' . $filename); - $file = fopen($path, 'w+'); - fwrite($file, "\xEF\xBB\xBF"); // Excel対応のBOM fputcsv($file, $columns); - foreach ($dataExport as $item) { + $data = Price::all(); + foreach ($data as $item) { fputcsv($file, [ - $item->price_parkplaceid, - $item->prine_name, - $item->price_month, - $item->park_id, - optional($item->getPark())->park_name, - $item->psection_id, - optional($item->getPSection())->psection_subject, - $item->price_ptypeid, - optional($item->getPType())->ptype_subject, - $item->user_categoryid, - optional($item->getUserType())->print_name, - $item->pplace_id, - $item->price, + $item->price_parkplaceid, // 駐輪場所ID + $item->park_id, // 駐輪場ID + optional($item->getUserType())->print_name, // 利用者分類名 + $item->price_month, // 期間 + optional($item->getUserType())->print_name, // 利用者分類ID + $item->price, // 駐輪料金(税込) + optional($item->getPSection())->psection_subject, // 車種区分名 + optional($item->getPType())->ptype_subject, // 駐輪分類名 + $item->pplace_id, // 駐車車室ID ]); } + fclose($file); - // 🔹 ダウンロードレスポンス - return response()->download($path, $filename, $headers)->deleteFileAfterSend(true); + $headers = [ + "Content-Type" => "text/csv; charset=UTF-8", + "Content-Disposition" => "attachment; filename={$filename}", + ]; + + return response()->download($filename, $filename, $headers)->deleteFileAfterSend(true); } public function import(Request $request) diff --git a/app/Http/Controllers/Admin/PrintAreaController.php b/app/Http/Controllers/Admin/PrintAreaController.php index a086544..2f336d5 100644 --- a/app/Http/Controllers/Admin/PrintAreaController.php +++ b/app/Http/Controllers/Admin/PrintAreaController.php @@ -25,7 +25,7 @@ class PrintAreaController extends Controller ]); } - // 新規登録 + // 新規 public function add(Request $request) { if ($request->isMethod('post')) { @@ -72,35 +72,67 @@ class PrintAreaController extends Controller return view('admin.print_areas.info', compact('record')); } - public function delete(Request $request) + /** + * 印刷範囲マスタ削除処理 + */ + public function delete(Request $request, $id = null) { - // バリデーション:'pk'は必須、配列の場合は各要素が整数 + // 一覧画面(checkboxで複数削除) + $ids = $request->input('pk'); + + // 編集画面(単体削除) + if ($id) { + $ids = [$id]; + } + + // 削除対象が空 + if (empty($ids)) { + return redirect() + ->route('print_areas') + ->with('error', '削除対象が選択されていません。'); + } + + // バリデーション:配列 or 単一でも整数確認 $request->validate([ - 'pk' => 'required', + 'pk' => 'nullable', 'pk.*' => 'integer', ]); - // pkを配列化(単一でも配列でも対応) - $ids = (array)$request->input('pk'); + try { + // 削除処理 + $deleted = PrintArea::destroy($ids); - // 削除処理 - $deleted = PrintArea::destroy($ids); + if ($deleted > 0) { + return redirect() + ->route('print_areas') + ->with('success', '削除しました。'); + } else { + return redirect() + ->route('print_areas') + ->with('error', '削除に失敗しました。'); + } + } catch (\Exception $e) { + \Log::error('印刷範囲削除エラー: ' . $e->getMessage()); - // 削除結果によってメッセージを分岐 - if ($deleted > 0) { - return redirect()->route('print_areas')->with('success', '削除しました。'); - } else { - return redirect()->route('print_areas')->with('error', '削除に失敗しました。'); + return redirect() + ->route('print_areas') + ->with('error', '削除中にエラーが発生しました。'); } } - // CSVエクスポート public function export(Request $request) { - $filename = 'print_areas_' . now()->format('Ymd_His') . '.csv'; + // ファイル名を日本語付きで指定(Excelで問題なく開けるようにUTF-8にBOMも付加) + $filename = 'シール印刷範囲マスタ' . now()->format('YmdHis') . '.csv'; + $data = PrintArea::with('park')->get(); + // UTF-8 BOM (Excel用) + $bom = "\xEF\xBB\xBF"; + + // CSVヘッダー $csv = implode(",", ['印刷範囲ID', '印刷範囲名', '駐輪場ID', '駐輪場名']) . "\n"; + foreach ($data as $item) { $csv .= implode(",", [ $item->print_area_id, @@ -110,11 +142,13 @@ class PrintAreaController extends Controller ]) . "\n"; } - return response($csv) - ->header('Content-Type', 'text/csv') - ->header('Content-Disposition', "attachment; filename=$filename"); + return response($bom . $csv) + ->header('Content-Type', 'text/csv; charset=UTF-8') + // filename* にすれば日本語名も安全に動作 + ->header('Content-Disposition', "attachment; filename*=UTF-8''" . rawurlencode($filename)); } + // CSVインポート(仮) public function import(Request $request) { diff --git a/app/Http/Controllers/Admin/RegularTypeController.php b/app/Http/Controllers/Admin/RegularTypeController.php index 0bbc423..a9e3e49 100644 --- a/app/Http/Controllers/Admin/RegularTypeController.php +++ b/app/Http/Controllers/Admin/RegularTypeController.php @@ -33,17 +33,21 @@ class RegularTypeController extends Controller ]; $viewData = array_merge($inputs, $dataList); + $record = new RegularType(); + if ($request->isMethod('POST')) { $validation = new RegularTypeRequest(); $rules = $validation->rules(); $validator = Validator::make($request->all(), $rules, $validation->messages()); if ($validator->fails()) { - $viewData['errorMsg'] = $this->buildErrorMessages($validator); - return view('admin.regular_types.add', array_merge($viewData, $request->all())); + return redirect() + ->back() + ->withErrors($validator) + ->withInput(); } - // 仅允许写入的字段(白名单) + // バリデーション成功 $payload = array_intersect_key($request->all(), array_flip([ 'city_id', 'regular_class_1', @@ -61,41 +65,47 @@ class RegularTypeController extends Controller $new->save(); }); - $request->session()->flash('success', __('登録に成功しました。')); + $request->session()->flash('success', __('登録しました。')); return redirect()->route('regular_types'); } - return view('admin.regular_types.add', $viewData); + return view('admin.regular_types.add', array_merge($viewData, [ + 'record' => $record, + ])); } public function edit(Request $request, $id, $view = '') { - $regular_type = RegularType::getById($id); - if (empty($id) || empty($regular_type)) { + // --- データ取得 --- + $record = RegularType::getById($id); + if (empty($id) || empty($record)) { abort(404); } + // --- 初期表示用データ --- $data = array_merge( - $regular_type->getAttributes(), + $record->getAttributes(), $this->getDataDropList(), [ - 'regular_type' => $regular_type, + 'record' => $record, 'isEdit' => true, ] ); - + // --- 更新処理 --- if ($request->isMethod('POST')) { $validation = new RegularTypeRequest(); $rules = $validation->rules(); $validator = Validator::make($request->all(), $rules, $validation->messages()); + // city_name → city_id の補正 $requestAll = $request->all(); if (isset($requestAll['city_name']) && !isset($requestAll['city_id'])) { $requestAll['city_id'] = $requestAll['city_name']; } + // 書き込み対象のカラムのみ許可 $payload = array_intersect_key($requestAll, array_flip([ 'city_id', 'regular_class_1', @@ -106,23 +116,26 @@ class RegularTypeController extends Controller 'memo', ])); + // バリデーションエラー if ($validator->fails()) { $data['errorMsg'] = $this->buildErrorMessages($validator); - $data = array_merge($data, $payload); + if ($view !== '') return view($view, $data); return view('admin.regular_types.edit', $data); } - DB::transaction(function () use (&$regular_type, $payload) { - $regular_type->fill($payload); - $regular_type->save(); + // 更新 + DB::transaction(function () use (&$record, $payload) { + $record->fill($payload); + $record->save(); }); $request->session()->flash('success', __('更新に成功しました')); return redirect()->route('regular_types'); } + // --- 画面表示 --- if ($view !== '') { return view($view, $data); } @@ -135,24 +148,29 @@ class RegularTypeController extends Controller return implode("\n", $validator->errors()->all()); } - public function delete(Request $request) + public function delete(Request $request, $id = null) { - $arr_pk = $request->get('pk'); // 配列で受け取る + // 一覧画面(checkbox で複数削除) + $ids = $request->input('pk'); - if ($arr_pk) { - $deleted = RegularType::destroy($arr_pk); - - if ($deleted > 0) { - return redirect()->route('regular_types') - ->with('success', __("削除が完了しました。")); - } else { - return redirect()->route('regular_types') - ->with('error', __('削除に失敗しました。')); - } + // 編集画面(単体削除) + if ($id) { + $ids = [$id]; } - return redirect()->route('regular_types') - ->with('error', __('削除するデータを選択してください。')); + // 削除対象が空の場合 + if (empty($ids)) { + return redirect() + ->route('regular_types') + ->with('error', '削除対象が選択されていません。'); + } + + // 削除処理 + RegularType::destroy($ids); + + return redirect() + ->route('regular_types') + ->with('success', '削除しました。'); } diff --git a/resources/views/admin/prices/list.blade.php b/resources/views/admin/prices/list.blade.php index 127ad36..b6dfa9a 100644 --- a/resources/views/admin/prices/list.blade.php +++ b/resources/views/admin/prices/list.blade.php @@ -41,16 +41,12 @@ {{-- 削除 --}} - -
+ {{-- エクスポート(条件選択モーダル) --}}