krgm.so-manager-dev.com/app/Http/Controllers/Admin/TaxController.php
kin.rinzen 5c1b33cedc
All checks were successful
Deploy main / deploy (push) Successful in 21s
SWA-67/SWA-80/SWA-89 画面修正
2025-10-01 18:00:19 +09:00

294 lines
10 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 App\Models\Tax;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpFoundation\StreamedResponse;
class TaxController extends Controller
{
/**
* 一覧:キーワード/適用日範囲で絞り込み + ソート + ページング
*/
public function list(Request $request)
{
$query = Tax::query();
// 絞り込み
$keyword = trim((string) $request->input('kw'));
if ($keyword !== '') {
// 数値型でも互換のため部分一致を残す
$query->where('tax_percent', 'like', "%{$keyword}%");
}
$from = $request->input('from');
$to = $request->input('to');
if ($from) {
$query->whereDate('tax_day', '>=', $from);
}
if ($to) {
$query->whereDate('tax_day', '<=', $to);
}
// ソート(既定:適用日 降順)
$sort = $request->input('sort', 'tax_day');
$type = strtolower($request->input('sort_type', 'desc'));
$allow = ['tax_day', 'tax_percent', 'updated_at', 'created_at', 'tax_id'];
if (!in_array($sort, $allow, true)) {
$sort = 'tax_day';
}
if (!in_array($type, ['asc', 'desc'], true)) {
$type = 'desc';
}
$query->orderBy($sort, $type);
$list = $query->paginate(20)->appends($request->except('page'));
return view('admin.tax.list', [
'taxes' => $list,
'kw' => $keyword,
'from' => $from,
'to' => $to,
'sort' => $sort,
'sort_type' => $type,
]);
}
public function add(Request $request)
{
if ($request->isMethod('post')) {
$data = $request->validate([
'tax_percent' => ['required', 'numeric', 'min:0', 'max:1000'],
'tax_day' => ['required', 'date', 'unique:tax,tax_day'],
]);
$data['operator_id'] = optional(\Auth::user())->ope_id ?? null;
$data['tax_percent'] = number_format((float)$data['tax_percent'], 2, '.', '');
\App\Models\Tax::create($data);
return redirect()->route('tax')->with('success', '登録しました。');
}
return view('admin.tax.add', [
'tax' => null,
'isEdit' => false,
'isInfo' => false,
]);
}
public function edit(int $tax_id, Request $request)
{
$tax = \App\Models\Tax::findOrFail($tax_id);
if ($request->isMethod('post')) {
$data = $request->validate([
'tax_percent' => ['required', 'numeric', 'min:0', 'max:1000'],
'tax_day' => ['required', 'date', 'unique:tax,tax_day,' . $tax->tax_id . ',tax_id'],
]);
$data['operator_id'] = optional(\Auth::user())->ope_id ?? null;
$data['tax_percent'] = number_format((float)$data['tax_percent'], 2, '.', '');
$tax->update($data);
return redirect()->route('tax')->with('success', '更新しました。');
}
return view('admin.tax.edit', [
'tax' => $tax,
'isEdit' => true,
'isInfo' => false,
]);
}
public function info(int $tax_id)
{
$tax = \App\Models\Tax::findOrFail($tax_id);
return view('admin.tax.info', [
'tax' => $tax,
'isEdit' => false,
'isInfo' => true,
]);
}
/**
* 一括削除(一覧のチェックボックスで送られてくる想定)
* フォーム側 name="ids[]" の配列を POST
*/
public function delete(Request $request)
{
$pk = $request->input('pk', []);
// 配列に統一
$ids = is_array($pk) ? $pk : [$pk];
// 数字チェック
$ids = array_values(array_filter($ids, fn($v) => preg_match('/^\d+$/', (string) $v)));
if (empty($ids)) {
return redirect()->route('tax')->with('error', '削除対象が選択されていません。');
}
// 削除
Tax::whereIn('tax_id', $ids)->delete();
return redirect()->route('tax')->with('success', '削除しました。');
}
// /**
// * CSVインポート
// * カラム想定: tax_percent, tax_day
// * - 1行目はヘッダ可
// * - tax_day をキーとして「存在すれば更新 / 無ければ作成」
// */
// public function import(Request $request)
// {
// $request->validate([
// 'file' => ['required', 'file', 'mimetypes:text/plain,text/csv,text/tsv', 'max:2048'],
// ]);
// $path = $request->file('file')->getRealPath();
// if (!$path || !is_readable($path)) {
// return redirect()->route('tax')->with('error', 'ファイルを読み込めません。');
// }
// $created = 0;
// $updated = 0;
// $skipped = 0;
// DB::beginTransaction();
// try {
// if (($fp = fopen($path, 'r')) !== false) {
// $line = 0;
// while (($row = fgetcsv($fp)) !== false) {
// $line++;
// // 空行スキップ
// if (count($row) === 1 && trim((string) $row[0]) === '') {
// continue;
// }
// // ヘッダ行っぽい場合1行目に 'tax_percent' を含む)
// if ($line === 1) {
// $joined = strtolower(implode(',', $row));
// if (str_contains($joined, 'tax_percent') && str_contains($joined, 'tax_day')) {
// continue; // ヘッダスキップ
// }
// }
// // 取り出し(列数が足りない場合スキップ)
// $percent = $row[0] ?? null;
// $day = $row[1] ?? null;
// if ($percent === null || $day === null) {
// $skipped++;
// continue;
// }
// // 正規化 & 検証
// $percent = trim((string) $percent);
// $percent = rtrim($percent, '%');
// $percent = preg_replace('/[^\d.]/', '', $percent) ?? '0';
// $percentF = (float) $percent;
// if ($percentF < 0) {
// $skipped++;
// continue;
// }
// $percentF = (float) number_format($percentF, 2, '.', '');
// $day = date('Y-m-d', strtotime((string) $day));
// if (!$day) {
// $skipped++;
// continue;
// }
// // upsert: 適用日ユニーク運用
// $existing = Tax::whereDate('tax_day', $day)->first();
// $payload = [
// 'tax_percent' => $percentF,
// 'tax_day' => $day,
// 'operator_id' => optional(Auth::user())->ope_id ?? null,
// ];
// if ($existing) {
// $existing->update($payload);
// $updated++;
// } else {
// Tax::create($payload);
// $created++;
// }
// }
// fclose($fp);
// }
// DB::commit();
// return redirect()->route('tax')->with('success', "インポート完了:新規 {$created} 件、更新 {$updated} 件、スキップ {$skipped} 件");
// } catch (\Throwable $e) {
// DB::rollBack();
// return redirect()->route('tax')->with('error', 'インポートに失敗しました:' . $e->getMessage());
// }
// }
// /**
// * CSVエクスポート現在の絞り込み/ソート条件を反映
// */
// public function export(Request $request): StreamedResponse
// {
// $query = Tax::query();
// $keyword = trim((string) $request->input('kw'));
// if ($keyword !== '') {
// $query->where('tax_percent', 'like', "%{$keyword}%");
// }
// $from = $request->input('from');
// $to = $request->input('to');
// if ($from) {
// $query->whereDate('tax_day', '>=', $from);
// }
// if ($to) {
// $query->whereDate('tax_day', '<=', $to);
// }
// $sort = $request->input('sort', 'tax_day');
// $type = strtolower($request->input('sort_type', 'desc'));
// $allow = ['tax_day', 'tax_percent', 'updated_at', 'created_at', 'tax_id'];
// if (!in_array($sort, $allow, true)) {
// $sort = 'tax_day';
// }
// if (!in_array($type, ['asc', 'desc'], true)) {
// $type = 'desc';
// }
// $query->orderBy($sort, $type);
// $filename = 'tax_' . now()->format('Ymd_His') . '.csv';
// return response()->streamDownload(function () use ($query) {
// $out = fopen('php://output', 'w');
// // Header設計書の主要カラム
// fputcsv($out, ['消費税ID', '消費税率', '適用日', '登録日時', '更新日時', '更新オペレータID']);
// $query->chunk(500, function ($rows) use ($out) {
// foreach ($rows as $r) {
// fputcsv($out, [
// $r->tax_id,
// // 画面仕様に合わせたい場合は getDisplayTaxPercentAttribute() に置換可
// is_numeric($r->tax_percent)
// ? number_format((float) $r->tax_percent, 2, '.', '')
// : (string) $r->tax_percent,
// optional($r->tax_day)->format('Y-m-d'),
// optional($r->created_at)->format('Y-m-d H:i:s'),
// optional($r->updated_at)->format('Y-m-d H:i:s'),
// $r->operator_id,
// ]);
// }
// });
// fclose($out);
// }, $filename, [
// 'Content-Type' => 'text/csv; charset=UTF-8',
// ]);
// }
}