条件付きエクスポート機能修正
All checks were successful
Deploy main / deploy (push) Successful in 21s

This commit is contained in:
kin.rinzen 2025-10-15 17:43:14 +09:00
parent 8b85451145
commit e39fa8a87e
4 changed files with 168 additions and 92 deletions

View File

@ -9,6 +9,7 @@ use App\Models\Pplace;
use App\Models\Psection;
use App\Models\Ptype;
use App\Models\Usertype;
use App\Models\Station;
use App\Models\Utils;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
@ -183,6 +184,67 @@ class PriceController extends Controller
return response()->download($filename, $filename, $headers)->deleteFileAfterSend(true);
}
public function exportFiltered(Request $request)
{
$parkId = $request->input('park_id');
$filename = 'price_' . $parkId . '_' . now()->format('YmdHis') . '.csv';
// 一時ファイル作成
$file = fopen($filename, 'w+');
fwrite($file, "\xEF\xBB\xBF"); // UTF-8 BOM追加
// CSVヘッダ
$columns = [
'駐輪場所ID',
'商品名',
'期間',
'駐輪場ID',
'駐輪場名',
'車種区分ID',
'車種区分',
'駐輪分類ID',
'駐輪分類',
'利用者分類ID',
'利用者分類',
'駐輪車室ID',
'駐輪料金(税込)',
];
fputcsv($file, $columns);
// データ取得選択した駐輪場IDに限定
$data = \App\Models\Price::where('price_parkplaceid', $parkId)->get();
foreach ($data as $item) {
fputcsv($file, [
$item->price_parkplaceid, // 駐輪場所ID
$item->prine_name, // 商品名
$item->price_term ?? $item->price_month, // 期間
$item->park_id, // 駐輪場ID
optional($item->getPark())->park_name, // 駐輪場名
$item->psection_id, // 車種区分ID
optional($item->getPSection())->psection_subject, // 車種区分
$item->price_ptypeid, // 駐輪分類ID
optional($item->getPType())->ptype_subject, // 駐輪分類
$item->user_categoryid, // 利用者分類ID
optional($item->getUserType())->print_name, // 利用者分類
$item->pplace_id, // 駐輪車室ID
$item->price_taxin ?? $item->price, // 駐輪料金(税込)
]);
}
fclose($file);
// ヘッダ設定
$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');
@ -197,8 +259,6 @@ class PriceController extends Controller
DB::beginTransaction();
try {
// 先清空数据(全置換仕様なら残す)
Price::query()->delete();
$col = 13; // CSV 項目数
foreach ($data as $key => $items) {
@ -236,22 +296,28 @@ class PriceController extends Controller
$type = false; $msg = "行:{$record} 利用者分類IDが存在しません。"; break;
}
// TODO: 駐車車室ID チェックpplace_id
// 保存
$row = new Price();
$row->price_parkplaceid = $items[0];
$row->prine_name = $items[1];
$row->price_month = $items[2];
$row->park_id = $items[3];
$row->psection_id = $items[5];
$row->price_ptypeid = $items[7];
$row->user_categoryid = $items[9];
$row->pplace_id = $items[11];
$row->price = $items[12];
if (!$row->save()) {
$type = false; $msg = "行:{$record} データ保存に失敗しました。"; break;
if (!Pplace::where('pplace_id', $items[11])->exists()) {
$type = false; $msg = "行:{$record} 駐車車室IDが存在しません。"; break;
}
// 保存(存在すれば更新、なければ新規作成)
Price::updateOrCreate(
['price_parkplaceid' => $items[0]], // 主キー条件(存在チェック)
[
'prine_name' => $items[1],
'price_month' => $items[2],
'park_id' => $items[3],
'psection_id' => $items[5],
'price_ptypeid' => $items[7],
'user_categoryid' => $items[9],
'pplace_id' => $items[11],
'price' => $items[12],
'operator_id' => auth()->user()->operator_id ?? null, // オプション
'updated_at' => now(),
'created_at' => now(),
]
);
}
} catch (\Exception $e) {
$type = false;

View File

@ -125,6 +125,15 @@ class Price extends Model
return $this->belongsTo(Ptype::class, 'price_ptypeid'); // 外部キーが price_ptypeid
}
public function pplace()
{
return $this->belongsTo(Pplace::class, 'pplace_id'); // 外部キーが pplace_id
}
// public function getStation()
// {
// return $this->belongsTo(Station::class, 'price_parkplaceid', 'park_id');
// }

View File

@ -61,31 +61,31 @@
{{-- エクスポート用モーダル --}}
<div class="modal fade" id="exportModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form method="POST" action="{{ route('prices_export') }}">
@csrf
<div class="modal-body">
<p>エクスポートする駐輪場を選択してください。</p>
<div class="form-group row">
<label for="park_id" class="col-sm-4 col-form-label">駐輪場名</label>
<div class="col-sm-8">
<select name="park_id" id="park_id" class="form-control">
@foreach($parks as $id => $name)
<option value="{{ $id }}">{{ $name }}</option>
@endforeach
</select>
<div class="modal-dialog" role="document">
<div class="modal-content">
<form method="POST" action="{{ route('prices_export_filtered') }}">
@csrf
<div class="modal-body">
<p>エクスポートする駐輪場を選択してください。</p>
<div class="form-group row">
<label for="park_id" class="col-sm-4 col-form-label">駐輪場名</label>
<div class="col-sm-8">
<select name="park_id" id="park_id" class="form-control">
@foreach($parks as $id => $name)
<option value="{{ $id }}">{{ $name }}</option>
@endforeach
</select>
</div>
</div>
</div>
<div class="modal-footer justify-content-center">
<button type="submit" class="btn btn-primary w-25">はい</button>
<button type="button" class="btn btn-secondary w-25" data-dismiss="modal">キャンセル</button>
</div>
</form>
</div>
</div>
<div class="modal-footer justify-content-center">
<button type="submit" class="btn btn-primary w-25">はい</button>
<button type="button" class="btn btn-secondary w-25" data-dismiss="modal">キャンセル</button>
</div>
</form>
</div>
</div>
</div>
{{-- インポート用モーダル --}}
<div class="modal fade" id="importModal" tabindex="-1" role="dialog">
@ -149,69 +149,68 @@
<!-- ここから単一テーブル構成 ----------------------------------------- -->
<div class="col-lg-12 mb20">
<!-- <div class="table-responsive"> -->
<div class="table-responsive prices-wrap">
<table class="table table-bordered dataTable text-nowrap prices-table">
<thead class="thead-light">
<tr>
{{-- 1列目:チェック+編集 --}}
<th class="text-left freeze freeze-1" style="border-left:1px solid #dcdcdc;">
<input type="checkbox" onclick="$('input[name*=\'pk\']').prop('checked', this.checked);">
</th>
<table class="table table-bordered dataTable text-nowrap prices-table">
<thead class="thead-light">
<tr>
{{-- 1列目:チェック+編集 --}}
<th class="text-left freeze freeze-1" style="border-left:1px solid #dcdcdc;">
<input type="checkbox" onclick="$('input[name*=\'pk\']').prop('checked', this.checked);">
</th>
{{-- 2列目駐輪場所IDソート可 --}}
<th class="sorting freeze freeze-2 {{ ($sort=='price_parkplaceid') ? ($sort_type=='asc'?'sorting_asc':'sorting_desc') : '' }}"
sort="price_parkplaceid">
<span>駐輪場所ID</span>
</th>
{{-- 2列目駐輪場所IDソート可 --}}
<th class="sorting freeze freeze-2 {{ ($sort=='price_parkplaceid') ? ($sort_type=='asc'?'sorting_asc':'sorting_desc') : '' }}"
sort="price_parkplaceid">
<span>駐輪場所ID</span>
</th>
{{-- 3列目駐輪場IDソート可 --}}
<th class="sorting freeze freeze-3 {{ ($sort=='park_id') ? ($sort_type=='asc'?'sorting_asc':'sorting_desc') : '' }}"
sort="park_id">
<span>駐輪場ID</span>
</th>
{{-- 3列目駐輪場IDソート可 --}}
<th class="sorting freeze freeze-3 {{ ($sort=='park_id') ? ($sort_type=='asc'?'sorting_asc':'sorting_desc') : '' }}"
sort="park_id">
<span>駐輪場ID</span>
</th>
{{-- 4列目:商品名(固定ここまで) --}}
<th class="freeze freeze-4"><span>商品名</span></th>
{{-- 4列目:商品名(固定ここまで) --}}
<th class="freeze freeze-4"><span>商品名</span></th>
{{-- 以下は通常列 --}}
<th><span>期間</span></th>
<th><span>利用者分類ID</span></th>
<th><span>駐輪料金(税込)</span></th>
<th class="sorting {{ ($sort=='psection_id') ? ($sort_type=='asc'?'sorting_asc':'sorting_desc') : '' }}" sort="psection_id"><span>車種区分ID</span></th>
<th class="sorting {{ ($sort=='price_ptypeid') ? ($sort_type=='asc'?'sorting_asc':'sorting_desc') : '' }}" sort="price_ptypeid"><span>駐輪分類ID</span></th>
<th class="sorting {{ ($sort=='pplace_id') ? ($sort_type=='asc'?'sorting_asc':'sorting_desc') : '' }}" sort="pplace_id"><span>駐車車室ID</span></th>
</tr>
</thead>
{{-- 以下は通常列 --}}
<th><span>期間</span></th>
<th><span>利用者分類ID</span></th>
<th><span>駐輪料金(税込)</span></th>
<th class="sorting {{ ($sort=='psection_id') ? ($sort_type=='asc'?'sorting_asc':'sorting_desc') : '' }}" sort="psection_id"><span>車種区分ID</span></th>
<th class="sorting {{ ($sort=='price_ptypeid') ? ($sort_type=='asc'?'sorting_asc':'sorting_desc') : '' }}" sort="price_ptypeid"><span>駐輪分類ID</span></th>
<th class="sorting {{ ($sort=='pplace_id') ? ($sort_type=='asc'?'sorting_asc':'sorting_desc') : '' }}" sort="pplace_id"><span>駐車車室ID</span></th>
</tr>
</thead>
<tbody class="bg-white">
@foreach($list as $item)
<tr>
{{-- 1列目:チェック+編集 --}}
<td style="background: #faebd7;">
<div class="d-flex align-items-center">
<input type="checkbox" class="m-0 checkbox" name="pk[]" value="{{ $item->price_parkplaceid }}">
<a href="{{ route('price_edit', ['id' => $item->price_parkplaceid]) }}" class="btn btn-sm btn-default ml10">編集</a>
</div>
</td>
<tbody class="bg-white">
@foreach($list as $item)
<tr>
{{-- 1列目:チェック+編集 --}}
<td style="background: #faebd7;">
<div class="d-flex align-items-center">
<input type="checkbox" class="m-0 checkbox" name="pk[]" value="{{ $item->price_parkplaceid }}">
<a href="{{ route('price_edit', ['id' => $item->price_parkplaceid]) }}" class="btn btn-sm btn-default ml10">編集</a>
</div>
</td>
{{-- 24列目固定 --}}
<td class="sm-item text-left align-middle freeze freeze-2">{{ $item->price_parkplaceid }}</td>
<td class="sm-item text-left align-middle freeze freeze-3">{{ $parks[$item->park_id] ?? $item->park_id }}</td>
<td class="sm-item text-left align-middle freeze freeze-4">{{ $item->prine_name }}</td>
{{-- 24列目固定 --}}
<td class="sm-item text-left align-middle freeze freeze-2">{{ $item->price_parkplaceid }}</td>
<td class="sm-item text-left align-middle freeze freeze-3">{{ $parks[$item->park_id] ?? $item->park_id }}</td>
<td class="sm-item text-left align-middle freeze freeze-4">{{ $item->prine_name }}</td>
{{-- 以降は通常列 --}}
<td class="sm-item text-left align-middle">{{ $item->price_month }}ヶ月</td>
<td class="sm-item text-left align-middle">{{ $item->user_category_name }}</td>
<td class="sm-item text-left align-middle">{{ $item->price }}</td>
<td class="sm-item text-left align-middle">{{ $item->psection_subject?? '' }}</td>
{{-- 以降は通常列 --}}
<td class="sm-item text-left align-middle">{{ $item->price_month }}ヶ月</td>
<td class="sm-item text-left align-middle">{{ $item->user_category_name }}</td>
<td class="sm-item text-left align-middle">{{ $item->price }}</td>
<td class="sm-item text-left align-middle">{{ $item->psection_subject?? '' }}</td>
<td class="sm-item text-left align-middle">{{ $item->ptype_subject?? '' }}</td>
<td class="sm-item text-left align-middle">{{ $item->pplace_id }}</td>
</tr>
@endforeach
</tbody>
</table>
<td class="sm-item text-left align-middle">{{ $item->ptype_subject?? '' }}</td>
<td class="sm-item text-left align-middle">{{ $item->pplace_id }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>

View File

@ -185,6 +185,8 @@ Route::middleware('auth')->group(function () {
Route::match(['get', 'post'], '/admin/prices/delete', [PriceController::class, 'delete'])->name('prices_delete');
Route::match(['get', 'post'], '/admin/prices/import', [PriceController::class, 'import'])->name('prices_import');
Route::get('/admin/prices/export', [PriceController::class, 'export'])->name('prices_export');
// POST: 条件付きエクスポート(モーダルで選択)
Route::post('/admin/prices/export', [PriceController::class, 'exportFiltered'])->name('prices_export_filtered');
//車種区分マスタ