krgm.so-manager-dev.com/app/Http/Controllers/Admin/RegularContractController.php
你的名字 dd88338fb1
All checks were successful
Deploy main / deploy (push) Successful in 22s
【定期契約マスタ】絞り込み修正
2025-10-06 14:48:41 +09:00

881 lines
38 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Models\Park;
use Illuminate\Support\Carbon;
class RegularContractController
{
/**
* 利用者分類選択肢user_categoryid 昇順)
*/
private function buildUsertypeOptions(): array
{
return DB::table('usertype as t')
->join('regular_contract as rc', 'rc.user_categoryid', '=', 't.user_categoryid')
->select('t.user_categoryid', 't.usertype_subject1', 't.usertype_subject2', 't.usertype_subject3')
->groupBy('t.user_categoryid', 't.usertype_subject1', 't.usertype_subject2', 't.usertype_subject3')
->orderBy('t.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();
}
private function buildParkOptions(): array
{
return Park::query()
->join('regular_contract as rc', 'rc.park_id', '=', 'park.park_id')
->select('park.park_id', 'park.park_name')
->groupBy('park.park_id', 'park.park_name')
->orderBy('park.park_id', 'asc')
->get()
->mapWithKeys(fn ($park) => [
$park->park_id => $park->park_name ?: (string) $park->park_id,
])
->toArray();
}
/**
* datetime-local から受け取った値を Y-m-d H:i:s へ正規化
*/
private function normalizeDateTimeInput(?string $value, bool $endOfMinute = false): ?string
{
if ($value === null) {
return null;
}
$value = trim($value);
if ($value === '') {
return null;
}
$value = str_replace('T', ' ', $value);
if (strlen($value) === 16) {
$value .= ':00';
}
try {
$dt = Carbon::parse($value);
if ($endOfMinute) {
$dt = $dt->endOfMinute();
}
return $dt->format('Y-m-d H:i:s');
} catch (\Throwable $e) {
return null;
}
}
/**
* 名寄フリガナ検索用:全角カナへ統一し空白除去
*/
private function normalizePhoneticKeyword(?string $value): ?string
{
if ($value === null) {
return null;
}
$value = trim((string) $value);
if ($value === '') {
return null;
}
$value = mb_convert_kana($value, 'KVCS');
return str_replace([' ', ' '], '', $value);
}
/**
* 定期契約一覧
* - ベース表: regular_contractrc
* - 付加情報: useru, usertypet, parkp
* - 画面変数: $list, $sort, $sort_type既存に合わせる
*/
public function list(Request $request)
{
if ($request->isMethod('post')) {
$postParams = $request->except(['_token']);
$queryParams = $request->query();
return redirect()->route('regularcontracts', array_merge($queryParams, $postParams));
}
$params = $request->query();
// ===== ソート(既定: contract_id ASC=====
$sort = $params['sort'] ?? 'contract_id';
$sortType = strtolower($params['sort_type'] ?? 'asc') === 'desc' ? 'desc' : 'asc';
// ===== 絞り込み(テキスト系)=====
$contract_qr_id = trim((string) ($params['contract_qr_id'] ?? ''));
$user_id = trim((string) ($params['user_id'] ?? ''));
$user_tag_serial = trim((string) ($params['user_tag_serial'] ?? ''));
$park_id = trim((string) ($params['park_id'] ?? ''));
$selectedParkId = trim((string) ($params['selected_park_id'] ?? ''));
$user_phonetic = trim((string) ($params['user_phonetic'] ?? ''));
$phone = trim((string) ($params['phone'] ?? ''));
$email = trim((string) ($params['email'] ?? ''));
$user_categoryid = trim((string) ($params['user_categoryid'] ?? ''));
$park_name_kw = trim((string) ($params['park_name'] ?? ''));
$zone_keyword = trim((string) ($params['zone_keyword'] ?? ''));
$zone_name = trim((string) ($params['zone_name'] ?? ''));
$merge_phonetic_input = $params['merge_phonetic'] ?? '';
$merge_phonetic = trim((string) $merge_phonetic_input);
$merge_phonetic_normalized = $this->normalizePhoneticKeyword($merge_phonetic);
$has_address = $params['has_address'] ?? '';
$workRecordFilter = (string) ($params['work_record'] ?? '0');
if (!in_array($workRecordFilter, ['0', '1', '2'], true)) {
$workRecordFilter = '0';
}
// ===== 絞り込み(日付範囲)=====
$reserve_from = $params['reserve_date_from'] ?? '';
$reserve_to = $params['reserve_date_to'] ?? '';
$created_from = $params['contract_created_from'] ?? '';
$created_to = $params['contract_created_to'] ?? '';
$updated_from = $params['contract_updated_from'] ?? '';
$updated_to = $params['contract_updated_to'] ?? '';
$canceled_from = $params['contract_canceled_from'] ?? '';
$canceled_to = $params['contract_canceled_to'] ?? '';
$receipt_delivery_from = $params['receipt_delivery_from'] ?? '';
$receipt_delivery_to = $params['receipt_delivery_to'] ?? '';
$contract_valid_months = $params['contract_valid_months'] ?? '';
// ===== 列挙(全て/0/1=====
$contract_flag = $params['contract_flag'] ?? '';
$contract_permission = $params['contract_permission'] ?? '';
$tag_qr_flag = $params['tag_qr_flag'] ?? '';
$updateFlagFilter = (string) ($params['update_flag'] ?? '0');
if (!in_array($updateFlagFilter, ['0', '1', '2'], true)) {
$updateFlagFilter = '0';
}
$contract_cancel_flag = $params['contract_cancel_flag'] ?? '';
// ===== クエリ(結合込み)=====
$q = DB::table('regular_contract as rc')
->leftJoin('user as u', 'u.user_id', '=', 'rc.user_id')
->leftJoin('usertype as t', 't.user_categoryid', '=', 'rc.user_categoryid')
->leftJoin('park as p', 'p.park_id', '=', 'rc.park_id')
->leftJoin('zone as z', 'z.zone_id', '=', 'rc.zone_id')
->select([
'rc.*',
'u.user_seq',
'u.user_name',
'u.user_phonetic',
'u.user_mobile',
'u.user_homephone',
'u.user_primemail',
'u.user_regident_zip',
'u.user_tag_serial',
DB::raw('t.print_name as usertype_name'),
't.usertype_subject1',
't.usertype_subject2',
't.usertype_subject3',
DB::raw('p.park_name as park_name'),
DB::raw('z.zone_name as zone_name'),
]);
// ===== LIKE / キーワード =====
if ($contract_qr_id !== '') {
$q->where('rc.contract_qr_id', 'like', "%{$contract_qr_id}%");
}
if ($user_id !== '') {
$q->where('rc.user_id', 'like', "%{$user_id}%");
}
if ($user_tag_serial !== '') {
$q->where('u.user_tag_serial', 'like', "%{$user_tag_serial}%");
}
if ($park_id !== '') {
$q->where('rc.park_id', (int) $park_id);
} elseif ($selectedParkId !== '') {
$q->where('rc.park_id', (int) $selectedParkId);
}
if ($user_phonetic !== '') {
$q->where('u.user_phonetic', 'like', "%{$user_phonetic}%");
}
if ($email !== '') {
$q->where('u.user_primemail', 'like', "%{$email}%");
}
if ($user_categoryid !== '') {
$q->where('rc.user_categoryid', (int) $user_categoryid);
}
if ($park_name_kw !== '') {
$q->where('p.park_name', 'like', "%{$park_name_kw}%");
}
if ($zone_name !== '') {
$q->where('z.zone_name', 'like', "%{$zone_name}%");
}
if ($merge_phonetic_normalized !== null) {
$likeKeyword = '%' . $merge_phonetic_normalized . '%';
$q->whereRaw("REPLACE(REPLACE(IFNULL(rc.chk_user_phonetic, ''), ' ', ''), ' ', '') LIKE ?", [$likeKeyword]);
}
if ($phone !== '') {
$q->where(function ($w) use ($phone) {
$w->where('u.user_mobile', 'like', "%{$phone}%")
->orWhere('u.user_homephone', 'like', "%{$phone}%");
});
}
if ($reserve_from !== '' && ($normalized = $this->normalizeDateTimeInput($reserve_from))) {
$q->where('rc.reserve_date', '>=', $normalized);
}
if ($reserve_to !== '' && ($normalized = $this->normalizeDateTimeInput($reserve_to, true))) {
$q->where('rc.reserve_date', '<=', $normalized);
}
if ($receipt_delivery_from !== '' && ($normalized = $this->normalizeDateTimeInput($receipt_delivery_from))) {
$q->where('rc.contract_payment_day', '>=', $normalized);
}
if ($receipt_delivery_to !== '' && ($normalized = $this->normalizeDateTimeInput($receipt_delivery_to, true))) {
$q->where('rc.contract_payment_day', '<=', $normalized);
}
if ($zone_keyword !== '') {
$q->where(function ($w) use ($zone_keyword) {
$w->where('rc.zone_id', 'like', "%{$zone_keyword}%")
->orWhere('rc.pplace_no', 'like', "%{$zone_keyword}%")
->orWhere('rc.old_contract_id', 'like', "%{$zone_keyword}%");
});
}
if ($workRecordFilter === '1') {
$q->where(function ($w) {
$w->whereNull('rc.contract_flag')
->orWhere('rc.contract_flag', '=', 0);
});
} elseif ($workRecordFilter === '2') {
$q->where('rc.contract_flag', '=', 1);
}
if ($created_from !== '' && ($normalized = $this->normalizeDateTimeInput($created_from))) {
$q->where('rc.contract_created_at', '>=', $normalized);
}
if ($created_to !== '' && ($normalized = $this->normalizeDateTimeInput($created_to, true))) {
$q->where('rc.contract_created_at', '<=', $normalized);
}
if ($updated_from !== '' && ($normalized = $this->normalizeDateTimeInput($updated_from))) {
$q->where('rc.contract_updated_at', '>=', $normalized);
}
if ($updated_to !== '' && ($normalized = $this->normalizeDateTimeInput($updated_to, true))) {
$q->where('rc.contract_updated_at', '<=', $normalized);
}
if ($canceled_from !== '' && ($normalized = $this->normalizeDateTimeInput($canceled_from))) {
$q->where('rc.contract_cancelday', '>=', $normalized);
}
if ($canceled_to !== '' && ($normalized = $this->normalizeDateTimeInput($canceled_to, true))) {
$q->where('rc.contract_cancelday', '<=', $normalized);
}
if ($contract_valid_months !== '') {
$q->where('rc.enable_months', (int) $contract_valid_months);
}
if ($contract_flag !== '') {
$q->where('rc.contract_flag', (int) $contract_flag);
}
if ($contract_permission !== '') {
$q->where('rc.contract_permission', (int) $contract_permission);
}
if ($tag_qr_flag !== '') {
$q->where('rc.tag_qr_flag', (int) $tag_qr_flag);
}
if ($updateFlagFilter === '1') {
$q->where('rc.update_flag', '=', 1);
} elseif ($updateFlagFilter === '2') {
$q->where(function ($w) {
$w->whereNull('rc.update_flag')
->orWhere('rc.update_flag', '!=', 1);
});
}
if ($contract_cancel_flag !== '') {
$q->where('rc.contract_cancel_flag', (int) $contract_cancel_flag);
}
// ===== ソート(仮想列は結合側にマッピング)=====
$sortable = [
'contract_id', 'contract_qr_id', 'old_contract_id', 'zone_id', 'zone_name', 'pplace_no',
'contract_periods', 'contract_periode', 'user_id', 'user_categoryid', 'reserve_id', 'park_id',
'price_parkplaceid', 'user_securitynum', 'reserve_date', 'contract_reserve', 'contract_created_at',
'contract_updated_at', 'contract_cancelday', 'contract_reduction', 'enable_months', 'printable_date',
'billing_amount', 'contract_payment_day', 'contract_money', 'refunds', 'contract_flag',
'contract_permission', 'contract_cancel_flag', 'tag_qr_flag', 'update_flag', 'pplace_allocation_flag',
'settlement_transaction_id', 'contract_seal_issue', 'storage_company_code', 'share_storage_company_code',
'ope_id', 'park_position', 'contract_manual', 'contract_notice', 'contract_payment_number',
'user_name', 'user_phonetic', 'user_mobile', 'user_homephone', 'user_primemail', 'user_regident_zip',
'usertype_name', 'park_name',
];
if (!in_array($sort, $sortable, true)) {
$sort = 'contract_id';
}
$sortMap = [
'user_name' => 'u.user_name',
'user_phonetic' => 'u.user_phonetic',
'user_mobile' => 'u.user_mobile',
'user_homephone' => 'u.user_homephone',
'user_primemail' => 'u.user_primemail',
'user_regident_zip' => 'u.user_regident_zip',
'usertype_name' => 't.print_name',
'park_name' => 'p.park_name',
'zone_name' => 'z.zone_name',
];
$sortColumn = $sortMap[$sort] ?? ('rc.' . $sort);
$list = $q->orderBy($sortColumn, $sortType)->paginate(50)->withQueryString();
// ===== 画面へBlade 側が参照するすべての変数を渡す)=====
return view('admin.regularcontracts.list', [
'list' => $list,
'sort' => $sort,
'sort_type' => $sortType,
// 入力保持(テキスト)
'contract_qr_id' => $contract_qr_id,
'user_id' => $user_id,
'user_tag_serial' => $user_tag_serial,
'park_id' => $selectedParkId !== '' ? $selectedParkId : $park_id,
'user_phonetic' => $user_phonetic,
'phone' => $phone,
'email' => $email,
'user_categoryid' => $user_categoryid,
'park_name' => $park_name_kw,
'zone_keyword' => $zone_keyword,
'zone_name' => $zone_name,
'merge_phonetic' => $merge_phonetic,
'has_address' => $has_address,
'work_record' => $workRecordFilter,
// 入力保持(日付)
'reserve_date_from' => $reserve_from,
'reserve_date_to' => $reserve_to,
'contract_created_from' => $created_from,
'contract_created_to' => $created_to,
'contract_updated_from' => $updated_from,
'contract_updated_to' => $updated_to,
'contract_canceled_from' => $canceled_from,
'contract_canceled_to' => $canceled_to,
'receipt_delivery_from' => $receipt_delivery_from,
'receipt_delivery_to' => $receipt_delivery_to,
'contract_valid_months' => $contract_valid_months,
// 入力保持(列挙)
'contract_flag' => $contract_flag,
'contract_permission' => $contract_permission,
'tag_qr_flag' => $tag_qr_flag,
'update_flag' => $updateFlagFilter,
'contract_cancel_flag' => $contract_cancel_flag,
'userTypeOptions' => $this->buildUsertypeOptions(),
'parkOptions' => $this->buildParkOptions(),
]);
}
/**
* 定期契約編集GET: 画面表示 / POST: 更新実行)
* - 主キー: contract_id
*/
public function edit(Request $request, $id)
{
$id = (int) $id;
if ($request->isMethod('get')) {
$row = DB::table('regular_contract')->where('contract_id', $id)->first();
if (!$row) {
abort(404);
}
return view('admin.regularcontracts.edit', [
'row' => $row,
'contract_id' => $id,
]);
}
$v = Validator::make($request->all(), [
'user_id' => ['required', 'integer'],
'park_id' => ['required', 'integer'],
// 任意項目
'contract_qr_id' => ['nullable', 'string', 'max:255'],
'user_categoryid' => ['nullable', 'integer'],
'reserve_id' => ['nullable', 'integer'],
'price_parkplaceid' => ['nullable', 'integer'],
'user_securitynum' => ['nullable', 'string', 'max:255'],
'reserve_date' => ['nullable', 'date'],
'contract_reserve' => ['nullable', 'string', 'max:255'],
'contract_created_at' => ['nullable', 'date'],
'contract_updated_at' => ['nullable', 'date'],
'contract_cancelday' => ['nullable', 'date'],
'contract_flag' => ['nullable', 'integer'],
'contract_permission' => ['nullable', 'integer'],
'contract_cancel_flag' => ['nullable', 'integer'],
'tag_qr_flag' => ['nullable', 'integer'],
'park_position' => ['nullable', 'string', 'max:255'],
'ope_id' => ['nullable', 'integer'],
]);
if ($v->fails()) {
return back()->withErrors($v)->withInput();
}
$data = [
'contract_qr_id' => $request->input('contract_qr_id'),
'user_id' => (int) $request->input('user_id'),
'user_categoryid' => $request->input('user_categoryid'),
'reserve_id' => $request->input('reserve_id'),
'park_id' => (int) $request->input('park_id'),
'price_parkplaceid' => $request->input('price_parkplaceid'),
'user_securitynum' => $request->input('user_securitynum'),
'reserve_date' => $request->input('reserve_date'),
'contract_reserve' => $request->input('contract_reserve'),
'contract_created_at' => $request->input('contract_created_at'),
'contract_updated_at' => $request->input('contract_updated_at'),
'contract_cancelday' => $request->input('contract_cancelday'),
'contract_flag' => $request->input('contract_flag'),
'contract_permission' => $request->input('contract_permission'),
'contract_cancel_flag' => $request->input('contract_cancel_flag'),
'tag_qr_flag' => $request->input('tag_qr_flag'),
'park_position' => $request->input('park_position'),
'ope_id' => $request->input('ope_id'),
'updated_at' => now(),
];
DB::table('regular_contract')->where('contract_id', $id)->update($data);
return redirect()->route('regularcontracts')->with('success', '定期契約を更新しました。');
}
/**
* 定期契約削除
* - 物理削除(必要なら cancel フラグ運用に切替)
*/
public function delete(Request $request)
{
$ids = $request->input('ids', []);
if (!is_array($ids)) {
$ids = [$ids];
}
$ids = array_values(array_filter(
array_map('intval', $ids),
static fn (int $v) => $v > 0
));
if (empty($ids)) {
return redirect()->route('regularcontracts')
->with('error', '削除する定期契約が選択されていません。');
}
DB::table('regular_contract')
->whereIn('contract_id', $ids)
->delete();
return redirect()->route('regularcontracts')->with('success', '定期契約を削除しました。');
}
/**
* 定期契約インポート(仮実装)
*/
public function import(Request $request)
{
if ($request->isMethod('get')) {
// GET で来たら一覧へ
return redirect()->route('regularcontracts');
}
// ファイル必須 & 形式チェック
$request->validate([
'file' => ['required', 'file', 'mimetypes:text/plain,text/csv,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
], [], [
'file' => 'インポートファイル',
]);
$file = $request->file('file');
// TODO: ここで実際のインポート処理CSV/XLSXの解析とレコード登録を書く
// 例Storage::putFile('imports', $file); で一旦保存してバッチに回す etc.
return redirect()->route('regularcontracts')->with('success', 'インポートを受け付けました。');
}
/**
* 定期契約エクスポート(仮実装)
* - 現時点では何もしません。ルーティング確認用のプレーンテキストを返します。
* - 後で CSV / Excel 出力処理に置き換えてください。
*/
public function export(Request $request)
{
$params = $request->all();
$sort = $params['sort'] ?? 'contract_id';
$sortType = strtolower($params['sort_type'] ?? 'asc') === 'desc' ? 'desc' : 'asc';
$type = (string) ($request->query('type') ?? '');
$fileName = match ($type) {
'smbc' => '定期契約マスタ_SMBC.csv',
'city' => '定期契約マスタ_役所提出用.csv',
default => '定期契約マスタ.csv',
};
$query = $this->buildListQuery($params);
$columns = [
'contract_id' => '契約ID',
'contract_qr_id' => '定期契約ID',
'old_contract_id' => '旧定期契約番号',
'pplace_no' => '車室番号',
'user_id' => '利用者ID',
'user_categoryid' => '利用者分類ID',
'tag_qr_flag' => 'タグ・QR',
'park_id' => '駐輪場ID',
'reserve_date' => '予約日時',
'contract_periods' => '有効期間S',
'contract_periode' => '有効期間E',
'price_parkplaceid' => '駐輪場所ID',
'user_securitynum' => '防犯登録番号',
'contract_created_at' => '契約日時',
'contract_updated_at' => '更新可能日',
'contract_cancelday' => '解約日時',
'contract_reduction' => '減免措置',
'enable_months' => '定期有効月数',
'printable_date' => 'シール印刷可能日',
'billing_amount' => '請求金額',
'pplace_allocation_flag' => '車室割り当てフラグ',
'contract_payment_day' => '授受日時',
'contract_money' => '授受金額',
'contract_flag' => '授受フラグ',
'settlement_transaction_id' => '決済トランザクションID',
'contract_seal_issue' => 'シール発行数',
'storage_company_code' => '収納企業コード',
'share_storage_company_code' => '共有先収納企業コード',
'accept_number' => '受付番号',
'update_flag' => '(更新元)契約更新済フラグ',
'vehicle_type_id' => '車種区分ID',
'chk_user_phonetic' => 'チェック用_フリガナ',
'user_regident_zip' => 'チェック用_居住所郵便番号',
'user_mobile' => 'チェック用_携帯電話番号',
'user_homephone' => 'チェック用_自宅電話番号',
'old_member_number' => 'チェック用_旧会員番号',
'user_name' => '利用者氏名',
'user_phonetic' => '利用者フリガナ',
'park_name' => '駐輪場名',
'zone_name' => 'ゾーン名',
'usertype_name' => '利用者分類名',
];
$dateColumns = [
'contract_periods',
'contract_periode',
'contract_created_at',
'contract_updated_at',
'contract_cancelday',
'printable_date',
'contract_payment_day',
'reserve_date',
];
$rows = $query->orderBy($sort, $sortType)->get();
$headers = [
'Content-Type' => 'text/csv; charset=Shift_JIS',
'Content-Disposition' => "attachment; filename=\"{$fileName}\"",
];
return response()->streamDownload(function () use ($rows, $columns, $dateColumns) {
$handle = fopen('php://output', 'w');
$headerRow = array_map(fn ($label) => mb_convert_encoding($label, 'SJIS-win', 'UTF-8'), array_values($columns));
fputcsv($handle, $headerRow);
foreach ($rows as $row) {
$line = [];
foreach ($columns as $key => $label) {
$value = $row->{$key} ?? '';
if (in_array($key, $dateColumns, true) && $value) {
try {
$value = \Illuminate\Support\Carbon::parse($value)->format(str_contains($key, '_day') || str_contains($key, '_date') ? 'Y-m-d H:i' : 'Y-m-d');
} catch (\Throwable $e) {
$value = (string) $value;
}
} elseif ($key === 'tag_qr_flag' && $value !== '') {
$value = ((int) $value) === 1 ? 'QR' : 'タグ';
} elseif ($key === 'pplace_allocation_flag' && $value !== '') {
$value = ((int) $value) === 1 ? '割当済' : '未割当';
} elseif ($key === 'contract_flag' && $value !== '') {
$value = ((int) $value) === 1 ? '済' : '未';
} elseif ($key === 'update_flag' && $value !== '') {
$value = ((int) $value) === 1 ? '更新済' : '未更新';
}
$line[] = mb_convert_encoding((string) $value, 'SJIS-win', 'UTF-8');
}
fputcsv($handle, $line);
}
fclose($handle);
}, $fileName, $headers);
}
// 追加新規登録GET: 画面表示 / POST: 登録実行)
public function add(Request $request)
{
// 画面表示
if ($request->isMethod('get')) {
return view('admin.regularcontracts.add');
}
// ========= バリデーション =========
// ※ 必須最小限。その他は任意nullable
$v = Validator::make(
$request->all(),
[
'user_id' => ['required', 'integer'],
'park_id' => ['required', 'integer'],
'contract_qr_id' => ['nullable', 'string', 'max:255'],
'user_categoryid' => ['nullable', 'integer'],
'reserve_id' => ['nullable', 'integer'],
'price_parkplaceid' => ['nullable', 'integer'],
'reserve_date' => ['nullable', 'date'],
'contract_created_at' => ['nullable', 'date'],
'contract_cancelday' => ['nullable', 'date'],
'contract_permission' => ['nullable', 'integer'],
'contract_cancel_flag' => ['nullable', 'integer'],
'tag_qr_flag' => ['nullable', 'integer'],
'update_flag' => ['nullable', 'integer'],
'park_position' => ['nullable', 'string', 'max:255'],
'ope_id' => ['nullable', 'integer'],
// 画面の「定期有効月数」は DB の contract_valid_months に保存する
'enable_months' => ['nullable', 'integer', 'min:0'],
],
[],
[
'user_id' => '利用者ID',
'park_id' => '駐輪場ID',
'contract_qr_id' => '定期契約QRID',
'user_categoryid' => '利用者分類ID',
'reserve_id' => '定期予約ID',
'price_parkplaceid' => '駐輪場所ID',
'reserve_date' => '予約日時',
'contract_created_at' => '契約日時',
'contract_cancelday' => '解約日時',
'contract_permission' => 'シール発行許可',
'contract_cancel_flag' => '解約フラグ',
'tag_qr_flag' => 'タグ・QR',
'update_flag' => '(更新元)契約更新済フラグ',
'park_position' => '駐輪位置番号',
'ope_id' => 'オペレータID',
'enable_months' => '定期有効月数',
]
);
if ($v->fails()) {
return back()->withErrors($v)->withInput();
}
// ========= 登録データ作成 =========
// ここでは「regular_contract」テーブルに確実にある列を中心に保存します。
// 追加したい列があれば、同様にキーを増やして下さい。
$data = [
'contract_qr_id' => $request->input('contract_qr_id'),
'user_id' => (int) $request->input('user_id'),
'user_categoryid' => $request->input('user_categoryid'),
'reserve_id' => $request->input('reserve_id'),
'park_id' => (int) $request->input('park_id'),
'price_parkplaceid' => $request->input('price_parkplaceid'),
'reserve_date' => $request->input('reserve_date'),
'contract_created_at' => $request->input('contract_created_at') ?: now(), // 未指定なら現在時刻
'contract_cancelday' => $request->input('contract_cancelday'),
'contract_permission' => $request->input('contract_permission'),
'contract_cancel_flag' => $request->input('contract_cancel_flag'),
'tag_qr_flag' => $request->input('tag_qr_flag'),
'update_flag' => $request->input('update_flag'),
'park_position' => $request->input('park_position'),
'ope_id' => $request->input('ope_id'),
// 画面の enable_months → DB の contract_valid_months
'contract_valid_months' => $request->input('enable_months'),
'created_at' => now(),
'updated_at' => now(),
];
DB::table('regular_contract')->insert($data);
return redirect()
->route('regularcontracts')
->with('success', '定期契約を登録しました。');
}
private function buildListQuery(array $params)
{
$contract_qr_id = trim((string)($params['contract_qr_id'] ?? ''));
$user_id = trim((string)($params['user_id'] ?? ''));
$user_tag_serial = trim((string)($params['user_tag_serial'] ?? ''));
$park_id = trim((string)($params['park_id'] ?? ''));
$selectedParkId = trim((string)($params['selected_park_id'] ?? ''));
$user_phonetic = trim((string)($params['user_phonetic'] ?? ''));
$phone = trim((string)($params['phone'] ?? ''));
$email = trim((string)($params['email'] ?? ''));
$user_categoryid = trim((string)($params['user_categoryid'] ?? ''));
$park_name_kw = trim((string)($params['park_name'] ?? ''));
$zone_keyword = trim((string)($params['zone_keyword'] ?? ''));
$zone_name = trim((string)($params['zone_name'] ?? ''));
$merge_phonetic_input = $params['merge_phonetic'] ?? '';
$merge_phonetic = trim((string)$merge_phonetic_input);
$merge_phonetic_normalized = $this->normalizePhoneticKeyword($merge_phonetic);
$workRecordFilter = (string)($params['work_record'] ?? '0');
if (!in_array($workRecordFilter, ['0', '1', '2'], true)) {
$workRecordFilter = '0';
}
$reserve_from = $params['reserve_date_from'] ?? '';
$reserve_to = $params['reserve_date_to'] ?? '';
$created_from = $params['contract_created_from'] ?? '';
$created_to = $params['contract_created_to'] ?? '';
$updated_from = $params['contract_updated_from'] ?? '';
$updated_to = $params['contract_updated_to'] ?? '';
$canceled_from = $params['contract_canceled_from'] ?? '';
$canceled_to = $params['contract_canceled_to'] ?? '';
$receipt_delivery_from = $params['receipt_delivery_from'] ?? '';
$receipt_delivery_to = $params['receipt_delivery_to'] ?? '';
$contract_valid_months = $params['contract_valid_months'] ?? '';
$contract_flag = $params['contract_flag'] ?? '';
$contract_permission = $params['contract_permission'] ?? '';
$tag_qr_flag = $params['tag_qr_flag'] ?? '';
$updateFlagFilter = (string)($params['update_flag'] ?? '0');
if (!in_array($updateFlagFilter, ['0', '1', '2'], true)) {
$updateFlagFilter = '0';
}
$contract_cancel_flag = $params['contract_cancel_flag'] ?? '';
$q = DB::table('regular_contract as rc')
->leftJoin('user as u', 'u.user_id', '=', 'rc.user_id')
->leftJoin('usertype as t', 't.user_categoryid', '=', 'rc.user_categoryid')
->leftJoin('park as p', 'p.park_id', '=', 'rc.park_id')
->leftJoin('zone as z', 'z.zone_id', '=', 'rc.zone_id')
->select([
'rc.*',
'u.user_seq',
'u.user_name',
'u.user_phonetic',
'u.user_mobile',
'u.user_homephone',
'u.user_primemail',
'u.user_regident_zip',
'u.user_tag_serial',
DB::raw('t.print_name as usertype_name'),
't.usertype_subject1',
't.usertype_subject2',
't.usertype_subject3',
DB::raw('p.park_name as park_name'),
DB::raw('z.zone_name as zone_name'),
]);
if ($contract_qr_id !== '') {
$q->where('rc.contract_qr_id', 'like', "%{$contract_qr_id}%");
}
if ($user_id !== '') {
$q->where('rc.user_id', 'like', "%{$user_id}%");
}
if ($user_tag_serial !== '') {
$q->where('u.user_tag_serial', 'like', "%{$user_tag_serial}%");
}
if ($park_id !== '') {
$q->where('rc.park_id', (int)$park_id);
} elseif ($selectedParkId !== '') {
$q->where('rc.park_id', (int)$selectedParkId);
}
if ($user_phonetic !== '') {
$q->where('u.user_phonetic', 'like', "%{$user_phonetic}%");
}
if ($email !== '') {
$q->where('u.user_primemail', 'like', "%{$email}%");
}
if ($user_categoryid !== '') {
$q->where('rc.user_categoryid', (int)$user_categoryid);
}
if ($park_name_kw !== '') {
$q->where('p.park_name', 'like', "%{$park_name_kw}%");
}
if ($zone_name !== '') {
$q->where('z.zone_name', 'like', "%{$zone_name}%");
}
if ($merge_phonetic_normalized !== null) {
$likeKeyword = '%' . $merge_phonetic_normalized . '%';
$q->whereRaw("REPLACE(REPLACE(IFNULL(rc.chk_user_phonetic, ''), ' ', ''), ' ', '') LIKE ?", [$likeKeyword]);
}
if ($phone !== '') {
$q->where(function ($w) use ($phone) {
$w->where('u.user_mobile', 'like', "%{$phone}%")
->orWhere('u.user_homephone', 'like', "%{$phone}%");
});
}
if ($reserve_from !== '' && ($normalized = $this->normalizeDateTimeInput($reserve_from))) {
$q->where('rc.reserve_date', '>=', $normalized);
}
if ($reserve_to !== '' && ($normalized = $this->normalizeDateTimeInput($reserve_to, true))) {
$q->where('rc.reserve_date', '<=', $normalized);
}
if ($receipt_delivery_from !== '' && ($normalized = $this->normalizeDateTimeInput($receipt_delivery_from))) {
$q->where('rc.contract_payment_day', '>=', $normalized);
}
if ($receipt_delivery_to !== '' && ($normalized = $this->normalizeDateTimeInput($receipt_delivery_to, true))) {
$q->where('rc.contract_payment_day', '<=', $normalized);
}
if ($zone_keyword !== '') {
$q->where(function ($w) use ($zone_keyword) {
$w->where('rc.zone_id', 'like', "%{$zone_keyword}%")
->orWhere('rc.pplace_no', 'like', "%{$zone_keyword}%")
->orWhere('rc.old_contract_id', 'like', "%{$zone_keyword}%");
});
}
if ($workRecordFilter === '1') {
$q->where(function ($w) {
$w->whereNull('rc.contract_flag')
->orWhere('rc.contract_flag', '=', 0);
});
} elseif ($workRecordFilter === '2') {
$q->where('rc.contract_flag', '=', 1);
}
if ($created_from !== '' && ($normalized = $this->normalizeDateTimeInput($created_from))) {
$q->where('rc.contract_created_at', '>=', $normalized);
}
if ($created_to !== '' && ($normalized = $this->normalizeDateTimeInput($created_to, true))) {
$q->where('rc.contract_created_at', '<=', $normalized);
}
if ($updated_from !== '' && ($normalized = $this->normalizeDateTimeInput($updated_from))) {
$q->where('rc.contract_updated_at', '>=', $normalized);
}
if ($updated_to !== '' && ($normalized = $this->normalizeDateTimeInput($updated_to, true))) {
$q->where('rc.contract_updated_at', '<=', $normalized);
}
if ($canceled_from !== '' && ($normalized = $this->normalizeDateTimeInput($canceled_from))) {
$q->where('rc.contract_cancelday', '>=', $normalized);
}
if ($canceled_to !== '' && ($normalized = $this->normalizeDateTimeInput($canceled_to, true))) {
$q->where('rc.contract_cancelday', '<=', $normalized);
}
if ($contract_valid_months !== '') {
$q->where('rc.enable_months', (int)$contract_valid_months);
}
if ($contract_flag !== '') {
$q->where('rc.contract_flag', (int)$contract_flag);
}
if ($contract_permission !== '') {
$q->where('rc.contract_permission', (int)$contract_permission);
}
if ($tag_qr_flag !== '') {
$q->where('rc.tag_qr_flag', (int)$tag_qr_flag);
}
if ($updateFlagFilter === '1') {
$q->where('rc.update_flag', '=', 1);
} elseif ($updateFlagFilter === '2') {
$q->where(function ($w) {
$w->whereNull('rc.update_flag')
->orWhere('rc.update_flag', '!=', 1);
});
}
if ($contract_cancel_flag !== '') {
$q->where('rc.contract_cancel_flag', (int)$contract_cancel_flag);
}
return $q;
}
}