262 lines
9.9 KiB
PHP
262 lines
9.9 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers\Admin;
|
||
|
||
use App\Http\Controllers\Controller;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
class ContractorListController extends Controller
|
||
{
|
||
/**
|
||
* 一覧表示(GET/POST)
|
||
*/
|
||
public function list(Request $request)
|
||
{
|
||
// ベースクエリを構築
|
||
$q = DB::table('regular_contract as rc')
|
||
->leftJoin('user as u','rc.user_id','=','u.user_id')
|
||
->select([
|
||
'rc.contract_id',
|
||
'rc.contract_qr_id',
|
||
'rc.user_id',
|
||
'rc.user_categoryid',
|
||
'rc.park_id',
|
||
'rc.contract_created_at',
|
||
'rc.contract_periods',
|
||
'rc.contract_periode',
|
||
'rc.tag_qr_flag',
|
||
'rc.contract_flag',
|
||
'rc.contract_cancel_flag',
|
||
'rc.contract_payment_day',
|
||
'rc.contract_money',
|
||
'rc.billing_amount',
|
||
'rc.contract_permission',
|
||
'rc.contract_manual',
|
||
'rc.contract_notice',
|
||
'rc.update_flag',
|
||
'rc.user_securitynum',
|
||
'rc.contract_seal_issue',
|
||
'p.park_name',
|
||
'u.user_name',
|
||
'u.user_phonetic',
|
||
'u.user_mobile',
|
||
'u.user_seq',
|
||
'u.user_homephone',
|
||
'u.user_primemail',
|
||
'u.user_gender',
|
||
'u.user_birthdate',
|
||
'u.user_regident_zip',
|
||
'u.user_regident_pre',
|
||
'u.user_regident_city',
|
||
'u.user_regident_add',
|
||
'u.user_relate_zip',
|
||
'u.user_relate_pre',
|
||
'u.user_relate_city',
|
||
'u.user_relate_add',
|
||
'u.user_graduate',
|
||
'u.user_workplace',
|
||
'u.user_school',
|
||
'u.user_remarks',
|
||
'u.user_tag_serial_64',
|
||
'u.user_reduction',
|
||
DB::raw('rc.user_securitynum as crime_prevention'),
|
||
DB::raw('rc.contract_seal_issue as seal_issue_count'),
|
||
DB::raw("CASE rc.enable_months
|
||
WHEN 1 THEN '月極(1ヶ月)'
|
||
WHEN 3 THEN '3ヶ月'
|
||
WHEN 6 THEN '6ヶ月'
|
||
WHEN 12 THEN '年'
|
||
ELSE CONCAT(rc.enable_months, 'ヶ月') END as ticket_type"),
|
||
DB::raw('ps.psection_subject as vehicle_type'),
|
||
// 利用者分類のラベル(usertype テーブルの subject を取得)
|
||
DB::raw('ut.usertype_subject1 as user_category1'),
|
||
DB::raw('ut.usertype_subject2 as user_category2'),
|
||
DB::raw('ut.usertype_subject3 as user_category3'),
|
||
])
|
||
->leftJoin('park as p', 'rc.park_id', '=', 'p.park_id')
|
||
->leftJoin('psection as ps', 'rc.psection_id', '=', 'ps.psection_id')
|
||
->leftJoin('usertype as ut', 'u.user_categoryid', '=', 'ut.user_categoryid');
|
||
|
||
// ===== 絞り込み条件 =====
|
||
|
||
// 駐輪場で絞る(完全一致)
|
||
if ($request->filled('park_id')) {
|
||
$q->where('rc.park_id', $request->park_id);
|
||
}
|
||
|
||
// 利用者IDで絞る(完全一致)
|
||
if ($request->filled('user_id')) {
|
||
$q->where('rc.user_id', $request->user_id);
|
||
}
|
||
|
||
// 利用者分類で絞る(※ select の value を user_categoryid にしているため、user テーブルのカラムで比較)
|
||
if ($request->filled('user_category1')) {
|
||
$q->where('u.user_categoryid', $request->user_category1);
|
||
}
|
||
|
||
// タグシリアル64進で部分一致検索
|
||
if ($request->filled('user_tag_serial_64')) {
|
||
$val = $request->user_tag_serial_64;
|
||
$q->where('u.user_tag_serial_64','like','%'.$val.'%');
|
||
}
|
||
|
||
// 有効期限で絞る(指定日以前を抽出する= <= を使用)
|
||
if ($request->filled('contract_periode')) {
|
||
$raw = trim($request->contract_periode);
|
||
$norm = str_replace('/', '-', $raw); // スラッシュ入力を許容
|
||
try {
|
||
$target = \Carbon\Carbon::parse($norm)->format('Y-m-d');
|
||
// 指定日「以前」を含める
|
||
$q->whereDate('rc.contract_periode', '<=', $target);
|
||
} catch (\Exception $e) {
|
||
// 無効な日付は無視する
|
||
}
|
||
}
|
||
|
||
// フリガナで部分一致
|
||
if ($request->filled('user_phonetic')) {
|
||
$q->where('u.user_phonetic', 'like', '%' . $request->user_phonetic . '%');
|
||
}
|
||
|
||
// 携帯電話で部分一致
|
||
if ($request->filled('user_mobile')) {
|
||
$q->where('u.user_mobile', 'like', '%' . $request->user_mobile . '%');
|
||
}
|
||
|
||
// メールアドレスで部分一致
|
||
if ($request->filled('user_primemail')) {
|
||
$q->where('u.user_primemail', 'like', '%' . $request->user_primemail . '%');
|
||
}
|
||
|
||
// 勤務先で部分一致
|
||
if ($request->filled('user_workplace')) {
|
||
$q->where('u.user_workplace', 'like', '%' . $request->user_workplace . '%');
|
||
}
|
||
|
||
// 学校で部分一致
|
||
if ($request->filled('user_school')) {
|
||
$q->where('u.user_school', 'like', '%' . $request->user_school . '%');
|
||
}
|
||
|
||
// タグ・QR フラグで絞る(空文字は無視)
|
||
if ($request->filled('tag_qr_flag') && $request->tag_qr_flag !== '') {
|
||
$q->where('rc.tag_qr_flag', $request->tag_qr_flag);
|
||
}
|
||
|
||
// ===== ソート処理 =====
|
||
// 指定があればその列でソート、なければデフォルトで契約IDの昇順
|
||
$sort = $request->input('sort'); // null 許容
|
||
$sortType = $request->input('sort_type','asc');
|
||
|
||
$allowSorts = [
|
||
'rc.contract_id',
|
||
'rc.user_id',
|
||
'u.user_name',
|
||
'rc.tag_qr_flag',
|
||
'p.park_name',
|
||
];
|
||
if ($sort && in_array($sort, $allowSorts)) {
|
||
$sortType = $sortType === 'desc' ? 'desc' : 'asc';
|
||
$q->orderBy($sort, $sortType);
|
||
} else {
|
||
// デフォルトソート
|
||
$sort = null;
|
||
$sortType = null;
|
||
$q->orderBy('rc.contract_id','asc');
|
||
}
|
||
|
||
// ページネーション(クエリ文字列を引き継ぐ)
|
||
$rows = $q->paginate(20)->appends($request->query());
|
||
|
||
// 駐輪場セレクト用データ取得
|
||
$parks = DB::table('park')->select('park_id', 'park_name')->orderBy('park_name')->get();
|
||
|
||
// 利用者分類セレクト用:実際に使用されている分類のみを取得する
|
||
$categories = $this->buildCategoryOptions(true);
|
||
|
||
// ビューに渡す
|
||
return view('admin.contractor_list.list', compact('rows', 'sort', 'sortType', 'parks', 'categories'));
|
||
}
|
||
|
||
/**
|
||
* 詳細表示
|
||
*/
|
||
public function info($id)
|
||
{
|
||
// 指定契約IDの詳細を取得
|
||
$contract = DB::table('regular_contract as rc')
|
||
->select([
|
||
'rc.*',
|
||
'p.park_name',
|
||
'u.user_name',
|
||
'u.user_phonetic',
|
||
'u.user_mobile',
|
||
'u.user_homephone',
|
||
'u.user_primemail',
|
||
'u.user_gender',
|
||
'u.user_birthdate',
|
||
'u.user_regident_city',
|
||
])
|
||
->leftJoin('park as p', 'rc.park_id', '=', 'p.park_id')
|
||
->leftJoin('user as u', 'rc.user_id', '=', 'u.user_id')
|
||
->where('rc.contract_id', $id)
|
||
->first();
|
||
|
||
if (!$contract) { abort(404); }
|
||
|
||
return view('admin.contractor_List.info', compact('contract'));
|
||
}
|
||
|
||
/**
|
||
* 利用者分類選択肢を取得
|
||
*
|
||
* @param bool $onlyUsed true の場合は regular_contract に出現する分類のみ返す
|
||
* @return array [user_categoryid => label, ...]
|
||
*/
|
||
private function buildCategoryOptions(bool $onlyUsed = false): array
|
||
{
|
||
if (! $onlyUsed) {
|
||
// 全件取得(既存の挙動)
|
||
return DB::table('usertype')
|
||
->orderBy('user_categoryid', 'asc')
|
||
->get()
|
||
->mapWithKeys(function ($row) {
|
||
$label = collect([
|
||
$row->usertype_subject1 ?? '',
|
||
$row->usertype_subject2 ?? '',
|
||
$row->usertype_subject3 ?? '',
|
||
])->filter(fn ($v) => $v !== '')->implode('/');
|
||
|
||
return [$row->user_categoryid => $label !== '' ? $label : (string) $row->user_categoryid];
|
||
})
|
||
->toArray();
|
||
}
|
||
|
||
// 実際に使用されている分類のみ取得する(内部結合で user と regular_contract と紐付くもの)
|
||
$rows = DB::table('usertype as ut')
|
||
->join('user as u', 'u.user_categoryid', '=', 'ut.user_categoryid')
|
||
->join('regular_contract as rc', 'rc.user_id', '=', 'u.user_id')
|
||
->select(
|
||
'ut.user_categoryid',
|
||
'ut.usertype_subject1',
|
||
'ut.usertype_subject2',
|
||
'ut.usertype_subject3'
|
||
)
|
||
->groupBy('ut.user_categoryid', 'ut.usertype_subject1', 'ut.usertype_subject2', 'ut.usertype_subject3')
|
||
->orderBy('ut.user_categoryid', 'asc')
|
||
->get();
|
||
|
||
// ラベルを組み立てて配列で返す
|
||
return $rows->mapWithKeys(function ($row) {
|
||
$label = collect([
|
||
$row->usertype_subject1 ?? '',
|
||
$row->usertype_subject2 ?? '',
|
||
$row->usertype_subject3 ?? '',
|
||
])->filter(fn ($v) => $v !== '')->implode('/');
|
||
|
||
return [$row->user_categoryid => $label !== '' ? $label : (string) $row->user_categoryid];
|
||
})->toArray();
|
||
}
|
||
}
|