krgm.so-manager-dev.com/app/Http/Controllers/Admin/OperatorQueController.php
kin.rinzen 1cf94bc8aa
All checks were successful
Deploy main / deploy (push) Successful in 22s
インボイス設定画面の修正
2025-10-08 17:55:23 +09:00

297 lines
9.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpFoundation\StreamedResponse;
// モデル
use App\Models\OperatorQue; // operator_que テーブル
use App\Models\User; // 利用者候補user_seq / user_name / user_mobile / user_homephone
use App\Models\Park; // 駐輪場候補park_id / park_name
class OperatorQueController extends Controller
{
/**
* 一覧
* ルート: operator_ques
*/
public function list(Request $request)
{
$sort = $request->input('sort', 'que_id');
$sort_type = $request->input('sort_type', 'asc');
$que_status = $request->input('que_status');
// 許可されたカラム名のリストDB定義に合わせて
$allowedSorts = ['que_id', 'ope_id', 'que_status', 'created_at', 'updated_at', 'user_id', 'park_id', 'que_class'];
if (!in_array($sort, $allowedSorts)) {
$sort = 'que_id';
}
if (!in_array($sort_type, ['asc', 'desc'])) {
$sort_type = 'desc';
}
$query = OperatorQue::query();
// フィルタリング(絞り込み)
if (!empty($que_status)) {
$query->where('que_status', $que_status);
}
$list = $query->orderBy($sort, $sort_type)
->paginate(\App\Utils::item_per_page ?? 20);
// view に $que_status を渡す
return view('admin.operator_ques.list', compact('list', 'sort', 'sort_type', 'que_status'));
}
/**
* 新規登録(画面/処理)
*/
public function add(Request $request)
{
if ($request->isMethod('get')) {
// 新規時は空のレコードを用意してフォーム描画
return view('admin.operator_ques.add', array_merge(
$this->formPayload(),
[
'isEdit' => false,
'record' => new OperatorQue(), // ← ★ _form.blade.php で使う用
'que_id' => null,
]
));
}
// POST時バリデーション
$data = $this->validateRequest($request);
// 登録処理
OperatorQue::create($data);
return redirect()->route('operator_ques')->with('success', '登録しました。');
}
/**
* 編集(画面/処理)
*/
public function edit($id, Request $request)
{
$que = OperatorQue::findOrFail($id);
if ($request->isMethod('get')) {
return view('admin.operator_ques.edit', array_merge(
$this->formPayload($que),
[
'que_id' => $que->que_id,
'record' => $que,
]
));
}
$data = $this->validateRequest($request, $que->que_id);
$que->fill($data)->save();
return redirect()->route('operator_ques')->with('success', '更新しました。');
}
/**
* 詳細(参照)
*/
public function info($id)
{
$que = OperatorQue::findOrFail($id);
return view('admin.operator_ques.info', array_merge(
$this->formPayload($que),
['que_id' => $que->que_id]
));
}
/**
* 削除(複数可)
*/
public function delete(Request $request)
{
$ids = [];
if ($request->filled('id')) {
$ids[] = (int) $request->input('id');
}
if (is_array($request->input('pk'))) {
$ids = array_merge($ids, $request->input('pk'));
}
$ids = array_values(array_unique(array_map('intval', $ids)));
if (!$ids) {
return back()->with('error', '削除対象が選択されていません。');
}
OperatorQue::whereIn('que_id', $ids)->delete();
return redirect()->route('operator_ques')->with('success', '削除しました。');
}
/**
* CSV インポート
*/
public function import(Request $request)
{
$validator = Validator::make($request->all(), [
'file' => 'required|file|mimes:csv,txt|max:20480',
]);
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
$file = $request->file('file')->getRealPath();
if (!$handle = fopen($file, 'r')) {
return back()->with('error', 'CSVを読み取れません。');
}
$header = fgetcsv($handle) ?: [];
$header = array_map(fn($h) => trim(ltrim($h ?? '', "\xEF\xBB\xBF")), $header);
$fillable = (new OperatorQue())->getFillable();
$rows = [];
while (($row = fgetcsv($handle)) !== false) {
$assoc = [];
foreach ($header as $i => $key) {
if (in_array($key, $fillable, true)) {
$assoc[$key] = $row[$i] ?? null;
}
}
if ($assoc) {
$rows[] = $assoc;
}
}
fclose($handle);
DB::transaction(function () use ($rows) {
foreach ($rows as $data) {
OperatorQue::create($data);
}
});
return redirect()->route('operator_ques')->with('success', count($rows) . '件をインポートしました。');
}
/**
* CSV エクスポート
*/
public function export(): StreamedResponse
{
$filename = 'operator_que_' . now()->format('Ymd_His') . '.csv';
$fillable = (new OperatorQue())->getFillable(); // 見出しは fillable を流用
$response = new StreamedResponse(function () use ($fillable) {
$out = fopen('php://output', 'w');
// UTF-8 BOM
fprintf($out, chr(0xEF) . chr(0xBB) . chr(0xBF));
fputcsv($out, $fillable);
OperatorQue::orderBy('que_id')->chunk(500, function ($chunk) use ($out, $fillable) {
foreach ($chunk as $row) {
$line = [];
foreach ($fillable as $f) {
$line[] = $row->$f ?? '';
}
fputcsv($out, $line);
}
});
fclose($out);
});
$response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
$response->headers->set('Content-Disposition', "attachment; filename={$filename}");
return $response;
}
/**
* フォームに渡す値/候補
*/
private function formPayload(?OperatorQue $que = null): array
{
// 値
$payload = [
'que_id' => $que->que_id ?? '',
'user_id' => $que->user_id ?? '',
'contract_id' => $que->contract_id ?? '',
'park_id' => $que->park_id ?? '',
'que_class' => $que->que_class ?? '',
'que_comment' => $que->que_comment ?? '',
'que_status' => $que->que_status ?? '',
'que_status_comment' => $que->que_status_comment?? '',
'work_instructions' => $que->work_instructions ?? '',
];
// 候補
$payload['users'] = $this->fetchUsers();
$payload['parks'] = $this->fetchParks();
return $payload;
}
/**
* バリデーション
* ※ 実テーブルの型に合わせて必要に応じて調整
*/
private function validateRequest(Request $request, $queId = null): array
{
$rules = [
'user_id' => 'nullable|integer',
'contract_id' => 'nullable|integer',
'park_id' => 'nullable|integer',
'que_class' => 'required|integer',
'que_comment' => 'nullable|string|max:2000',
'que_status' => 'required|integer',
'que_status_comment' => 'nullable|string|max:2000',
'work_instructions' => 'nullable|string|max:2000',
// 'operator_id' => 'nullable|integer', // ログインユーザIDを使うなら不要
];
return $request->validate($rules);
}
/**
* 利用者候補user_seq, user_name, user_mobile, user_homephone
* Blade 側では $users をそのまま @foreach
*/
private function fetchUsers()
{
try {
return User::select('user_seq', 'user_name', 'user_mobile', 'user_homephone')
->orderBy('user_name')
->get();
} catch (\Throwable $e) {
return DB::table('users')
->select(['user_seq', 'user_name', 'user_mobile', 'user_homephone'])
->orderBy('user_name')
->get();
}
}
/**
* 駐輪場候補park_id => park_name
*/
private function fetchParks()
{
try {
return Park::orderBy('park_name')->pluck('park_name', 'park_id');
} catch (\Throwable $e) {
return DB::table('parks')->orderBy('park_name')->pluck('park_name', 'park_id');
}
}
}