309 lines
9.9 KiB
PHP
309 lines
9.9 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Http\Controllers\Admin;
|
||
|
||
use App\Http\Controllers\Controller;
|
||
use App\Http\Requests\ParkRequest;
|
||
use App\Models\City;
|
||
use App\Services\ParkService;
|
||
use Illuminate\Http\Request;
|
||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||
|
||
class ParkController extends Controller
|
||
{
|
||
public function __construct(
|
||
private readonly ParkService $parkService
|
||
) {
|
||
}
|
||
|
||
/**
|
||
* 一覧
|
||
*/
|
||
public function index(ParkRequest $request)
|
||
{
|
||
$filters = $request->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;
|
||
}
|
||
|
||
}
|