Files
star-erp/app/Modules/Inventory/Controllers/InventoryController.php

585 lines
25 KiB
PHP
Raw Normal View History

2025-12-30 15:03:19 +08:00
<?php
namespace App\Modules\Inventory\Controllers;
use App\Http\Controllers\Controller;
2025-12-30 15:03:19 +08:00
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use App\Modules\Inventory\Models\Warehouse;
use App\Modules\Inventory\Models\Product;
use App\Modules\Inventory\Models\Inventory;
use App\Modules\Inventory\Models\InventoryTransaction;
use App\Modules\Inventory\Models\WarehouseProductSafetyStock;
2025-12-30 15:03:19 +08:00
use App\Modules\Core\Contracts\CoreServiceInterface;
2025-12-30 15:03:19 +08:00
class InventoryController extends Controller
{
protected $coreService;
public function __construct(CoreServiceInterface $coreService)
{
$this->coreService = $coreService;
}
public function index(Request $request, Warehouse $warehouse)
2025-12-30 15:03:19 +08:00
{
// ... (existing code for index) ...
2025-12-30 15:03:19 +08:00
$warehouse->load([
'inventories.product.category',
2026-01-08 16:32:10 +08:00
'inventories.product.baseUnit',
2025-12-30 15:03:19 +08:00
'inventories.lastIncomingTransaction',
'inventories.lastOutgoingTransaction'
]);
$allProducts = Product::with('category')->get();
2025-12-30 15:03:19 +08:00
// 1. 準備 availableProducts
$availableProducts = $allProducts->map(function ($product) {
return [
2026-01-22 15:39:35 +08:00
'id' => (string) $product->id,
2025-12-30 15:03:19 +08:00
'name' => $product->name,
2026-01-22 15:39:35 +08:00
'type' => $product->category?->name ?? '其他',
2025-12-30 15:03:19 +08:00
];
});
2026-01-22 15:39:35 +08:00
// 2. 從新表格讀取安全庫存設定 (商品-倉庫層級)
$safetyStockMap = WarehouseProductSafetyStock::where('warehouse_id', $warehouse->id)
->pluck('safety_stock', 'product_id')
->mapWithKeys(fn($val, $key) => [(string)$key => (float)$val]);
// 3. 準備 inventories (批號分組)
$items = $warehouse->inventories()
->with(['product.baseUnit', 'lastIncomingTransaction', 'lastOutgoingTransaction'])
->get();
$inventories = $items->groupBy('product_id')->map(function ($batchItems) use ($safetyStockMap) {
$firstItem = $batchItems->first();
$product = $firstItem->product;
$totalQuantity = $batchItems->sum('quantity');
$totalValue = $batchItems->sum('total_value'); // 計算總價值
2026-01-22 15:39:35 +08:00
// 從獨立表格讀取安全庫存
$safetyStock = $safetyStockMap[(string)$firstItem->product_id] ?? null;
// 計算狀態
$status = '正常';
if (!is_null($safetyStock)) {
if ($totalQuantity < $safetyStock) {
$status = '低於';
}
}
2025-12-30 15:03:19 +08:00
return [
2026-01-22 15:39:35 +08:00
'productId' => (string) $firstItem->product_id,
'productName' => $product?->name ?? '未知商品',
'productCode' => $product?->code ?? 'N/A',
'baseUnit' => $product?->baseUnit?->name ?? '個',
'totalQuantity' => (float) $totalQuantity,
'totalValue' => (float) $totalValue,
2026-01-22 15:39:35 +08:00
'safetyStock' => $safetyStock,
'status' => $status,
'batches' => $batchItems->map(function ($inv) {
return [
'id' => (string) $inv->id,
'warehouseId' => (string) $inv->warehouse_id,
'productId' => (string) $inv->product_id,
'productName' => $inv->product?->name ?? '未知商品',
'productCode' => $inv->product?->code ?? 'N/A',
'unit' => $inv->product?->baseUnit?->name ?? '個',
'quantity' => (float) $inv->quantity,
'unit_cost' => (float) $inv->unit_cost,
'total_value' => (float) $inv->total_value,
2026-01-22 15:39:35 +08:00
'safetyStock' => null, // 批號層級不再有安全庫存
'status' => '正常',
'batchNumber' => $inv->batch_number ?? 'BATCH-' . $inv->id,
'expiryDate' => $inv->expiry_date ? $inv->expiry_date->format('Y-m-d') : null,
'lastInboundDate' => $inv->lastIncomingTransaction ? ($inv->lastIncomingTransaction->actual_time ? $inv->lastIncomingTransaction->actual_time->format('Y-m-d') : $inv->lastIncomingTransaction->created_at->format('Y-m-d')) : null,
'lastOutboundDate' => $inv->lastOutgoingTransaction ? ($inv->lastOutgoingTransaction->actual_time ? $inv->lastOutgoingTransaction->actual_time->format('Y-m-d') : $inv->lastOutgoingTransaction->created_at->format('Y-m-d')) : null,
];
})->values(),
2025-12-30 15:03:19 +08:00
];
})->values();
2026-01-22 15:39:35 +08:00
// 4. 準備 safetyStockSettings (從新表格讀取)
$safetyStockSettings = WarehouseProductSafetyStock::where('warehouse_id', $warehouse->id)
->with(['product.category'])
->get()
->map(function ($setting) {
return [
'id' => (string) $setting->id,
'warehouseId' => (string) $setting->warehouse_id,
'productId' => (string) $setting->product_id,
'productName' => $setting->product?->name ?? '未知商品',
'productType' => $setting->product?->category?->name ?? '其他',
'safetyStock' => (float) $setting->safety_stock,
'createdAt' => $setting->created_at->toIso8601String(),
'updatedAt' => $setting->updated_at->toIso8601String(),
];
});
return Inertia::render('Warehouse/Inventory', [
2025-12-30 15:03:19 +08:00
'warehouse' => $warehouse,
'inventories' => $inventories,
'safetyStockSettings' => $safetyStockSettings,
'availableProducts' => $availableProducts,
]);
}
public function create(Warehouse $warehouse)
2025-12-30 15:03:19 +08:00
{
// ... (unchanged) ...
$products = Product::with(['baseUnit', 'largeUnit'])
2026-01-22 15:39:35 +08:00
->select('id', 'name', 'code', 'base_unit_id', 'large_unit_id', 'conversion_rate')
->get()
->map(function ($product) {
2025-12-30 15:03:19 +08:00
return [
'id' => (string) $product->id,
'name' => $product->name,
2026-01-22 15:39:35 +08:00
'code' => $product->code,
2026-01-08 16:32:10 +08:00
'baseUnit' => $product->baseUnit?->name ?? '個',
'largeUnit' => $product->largeUnit?->name, // 可能為 null
'conversionRate' => (float) $product->conversion_rate,
2025-12-30 15:03:19 +08:00
];
});
return Inertia::render('Warehouse/AddInventory', [
2025-12-30 15:03:19 +08:00
'warehouse' => $warehouse,
'products' => $products,
]);
}
public function store(Request $request, Warehouse $warehouse)
2025-12-30 15:03:19 +08:00
{
// ... (unchanged) ...
2025-12-30 15:03:19 +08:00
$validated = $request->validate([
'inboundDate' => 'required|date',
'reason' => 'required|string',
'notes' => 'nullable|string',
'items' => 'required|array|min:1',
'items.*.productId' => 'required|exists:products,id',
'items.*.quantity' => 'required|numeric|min:0.01',
'items.*.unit_cost' => 'nullable|numeric|min:0', // 新增成本驗證
2026-01-22 15:39:35 +08:00
'items.*.batchMode' => 'required|in:existing,new',
'items.*.inventoryId' => 'required_if:items.*.batchMode,existing|nullable|exists:inventories,id',
'items.*.originCountry' => 'required_if:items.*.batchMode,new|nullable|string|max:2',
'items.*.expiryDate' => 'nullable|date',
2025-12-30 15:03:19 +08:00
]);
return DB::transaction(function () use ($validated, $warehouse) {
2025-12-30 15:03:19 +08:00
foreach ($validated['items'] as $item) {
// ... (略,傳遞 unit_cost 交給 Service 處理) ...
// 這裡需要修改呼叫 Service 的地方或直接更新邏輯
// 為求快速,我將在此更新邏輯
2026-01-22 15:39:35 +08:00
$inventory = null;
if ($item['batchMode'] === 'existing') {
// 模式 A選擇現有批號 (包含已刪除的也要能找回來累加)
$inventory = Inventory::withTrashed()->findOrFail($item['inventoryId']);
2026-01-22 15:39:35 +08:00
if ($inventory->trashed()) {
$inventory->restore();
}
// 更新成本 (若有傳入)
if (isset($item['unit_cost'])) {
$inventory->unit_cost = $item['unit_cost'];
}
2026-01-22 15:39:35 +08:00
} else {
// 模式 B建立新批號
$originCountry = $item['originCountry'] ?? 'TW';
$product = Product::find($item['productId']);
2026-01-22 15:39:35 +08:00
$batchNumber = Inventory::generateBatchNumber(
2026-01-22 15:39:35 +08:00
$product->code ?? 'UNK',
$originCountry,
$validated['inboundDate']
);
// 檢查是否存在
2026-01-22 15:39:35 +08:00
$inventory = $warehouse->inventories()->withTrashed()->firstOrNew(
[
'product_id' => $item['productId'],
'batch_number' => $batchNumber
],
[
'quantity' => 0,
'unit_cost' => $item['unit_cost'] ?? 0, // 新增
'total_value' => 0, // 稍後計算
2026-01-22 15:39:35 +08:00
'arrival_date' => $validated['inboundDate'],
'expiry_date' => $item['expiryDate'] ?? null,
'origin_country' => $originCountry,
]
);
if ($inventory->trashed()) {
$inventory->restore();
}
}
2025-12-30 15:03:19 +08:00
$currentQty = $inventory->quantity;
$newQty = $currentQty + $item['quantity'];
$inventory->quantity = $newQty;
// 更新總價值
$inventory->total_value = $inventory->quantity * $inventory->unit_cost;
$inventory->save();
2025-12-30 15:03:19 +08:00
// 寫入異動紀錄
$inventory->transactions()->create([
'type' => '手動入庫',
'quantity' => $item['quantity'],
'unit_cost' => $inventory->unit_cost, // 記錄成本
2025-12-30 15:03:19 +08:00
'balance_before' => $currentQty,
'balance_after' => $newQty,
'reason' => $validated['reason'] . ($validated['notes'] ? ' - ' . $validated['notes'] : ''),
'actual_time' => $validated['inboundDate'],
'user_id' => auth()->id(),
]);
}
return redirect()->route('warehouses.inventory.index', $warehouse->id)
->with('success', '庫存記錄已儲存成功');
});
}
// ... (getBatches unchanged) ...
public function getBatches(Warehouse $warehouse, $productId, Request $request)
2026-01-22 15:39:35 +08:00
{
$originCountry = $request->query('originCountry', 'TW');
$arrivalDate = $request->query('arrivalDate', now()->format('Y-m-d'));
$batches = Inventory::where('warehouse_id', $warehouse->id)
2026-01-22 15:39:35 +08:00
->where('product_id', $productId)
->get()
->map(function ($inventory) {
return [
'inventoryId' => (string) $inventory->id,
'batchNumber' => $inventory->batch_number,
'originCountry' => $inventory->origin_country,
'expiryDate' => $inventory->expiry_date ? $inventory->expiry_date->format('Y-m-d') : null,
'quantity' => (float) $inventory->quantity,
'unitCost' => (float) $inventory->unit_cost, // 新增
2026-01-22 15:39:35 +08:00
];
});
// 計算下一個流水號
$product = Product::find($productId);
2026-01-22 15:39:35 +08:00
$nextSequence = '01';
if ($product) {
$batchNumber = Inventory::generateBatchNumber(
2026-01-22 15:39:35 +08:00
$product->code ?? 'UNK',
$originCountry,
$arrivalDate
);
$nextSequence = substr($batchNumber, -2);
}
return response()->json([
'batches' => $batches,
'nextSequence' => $nextSequence
]);
}
public function edit(Request $request, Warehouse $warehouse, $inventoryId)
2025-12-30 15:03:19 +08:00
{
if (str_starts_with($inventoryId, 'mock-inv-')) {
return redirect()->back()->with('error', '無法編輯範例資料');
}
// 移除 'transactions.user' 預載入
$inventory = Inventory::with(['product', 'transactions' => function($query) {
2025-12-30 15:03:19 +08:00
$query->orderBy('actual_time', 'desc')->orderBy('id', 'desc');
}])->findOrFail($inventoryId);
// 手動 Hydrate 使用者資料
$userIds = $inventory->transactions->pluck('user_id')->filter()->unique()->toArray();
$users = $this->coreService->getUsersByIds($userIds)->keyBy('id');
2025-12-30 15:03:19 +08:00
// 轉換為前端需要的格式
$inventoryData = [
'id' => (string) $inventory->id,
'warehouseId' => (string) $inventory->warehouse_id,
'productId' => (string) $inventory->product_id,
2026-01-08 16:32:10 +08:00
'productName' => $inventory->product?->name ?? '未知商品',
2025-12-30 15:03:19 +08:00
'quantity' => (float) $inventory->quantity,
'unit_cost' => (float) $inventory->unit_cost,
'total_value' => (float) $inventory->total_value,
2026-01-22 15:39:35 +08:00
'batchNumber' => $inventory->batch_number ?? '-',
'expiryDate' => $inventory->expiry_date ?? null,
2025-12-30 15:03:19 +08:00
'lastInboundDate' => $inventory->updated_at->format('Y-m-d'),
'lastOutboundDate' => null,
];
// 整理異動紀錄
$transactions = $inventory->transactions->map(function ($tx) use ($users) {
$user = $tx->user_id ? ($users[$tx->user_id] ?? null) : null;
2025-12-30 15:03:19 +08:00
return [
'id' => (string) $tx->id,
'type' => $tx->type,
'quantity' => (float) $tx->quantity,
'unit_cost' => (float) $tx->unit_cost,
2025-12-30 15:03:19 +08:00
'balanceAfter' => (float) $tx->balance_after,
'reason' => $tx->reason,
'userName' => $user ? $user->name : '系統', // 手動對應
2025-12-30 15:03:19 +08:00
'actualTime' => $tx->actual_time ? $tx->actual_time->format('Y-m-d H:i') : $tx->created_at->format('Y-m-d H:i'),
];
});
return Inertia::render('Warehouse/EditInventory', [
2025-12-30 15:03:19 +08:00
'warehouse' => $warehouse,
'inventory' => $inventoryData,
'transactions' => $transactions,
]);
}
public function update(Request $request, Warehouse $warehouse, $inventoryId)
2025-12-30 15:03:19 +08:00
{
// ... (unchanged) ...
$inventory = Inventory::find($inventoryId);
2025-12-30 15:03:19 +08:00
// 如果找不到 (可能是舊路由傳 product ID)
if (!$inventory) {
$inventory = $warehouse->inventories()->where('product_id', $inventoryId)->first();
}
if (!$inventory) {
return redirect()->back()->with('error', '找不到庫存紀錄');
}
$validated = $request->validate([
'quantity' => 'required|numeric|min:0',
// 以下欄位改為 nullable支援新表單
'type' => 'nullable|string',
'operation' => 'nullable|in:add,subtract,set',
'reason' => 'nullable|string',
'notes' => 'nullable|string',
'unit_cost' => 'nullable|numeric|min:0', // 新增成本
// ...
2025-12-30 15:03:19 +08:00
'batchNumber' => 'nullable|string',
'expiryDate' => 'nullable|date',
'lastInboundDate' => 'nullable|date',
'lastOutboundDate' => 'nullable|date',
]);
return DB::transaction(function () use ($validated, $inventory) {
2026-01-22 15:39:35 +08:00
$currentQty = (float) $inventory->quantity;
$newQty = (float) $validated['quantity'];
2025-12-30 15:03:19 +08:00
2026-01-22 15:39:35 +08:00
// 判斷是否來自調整彈窗 (包含 operation 參數)
$isAdjustment = isset($validated['operation']);
$changeQty = 0;
if ($isAdjustment) {
2025-12-30 15:03:19 +08:00
switch ($validated['operation']) {
case 'add':
2026-01-22 15:39:35 +08:00
$changeQty = (float) $validated['quantity'];
2025-12-30 15:03:19 +08:00
$newQty = $currentQty + $changeQty;
break;
case 'subtract':
2026-01-22 15:39:35 +08:00
$changeQty = -(float) $validated['quantity'];
2025-12-30 15:03:19 +08:00
$newQty = $currentQty + $changeQty;
break;
case 'set':
$changeQty = $newQty - $currentQty;
break;
}
} else {
// 來自編輯頁面,直接 Set
$changeQty = $newQty - $currentQty;
}
// 更新成本 (若有傳)
if (isset($validated['unit_cost'])) {
$inventory->unit_cost = $validated['unit_cost'];
}
2025-12-30 15:03:19 +08:00
// 更新庫存
$inventory->quantity = $newQty;
// 更新總值
$inventory->total_value = $inventory->quantity * $inventory->unit_cost;
$inventory->save();
2025-12-30 15:03:19 +08:00
// 異動類型映射
2026-01-22 15:39:35 +08:00
$type = $validated['type'] ?? ($isAdjustment ? 'manual_adjustment' : 'adjustment');
2025-12-30 15:03:19 +08:00
$typeMapping = [
2026-01-22 15:39:35 +08:00
'manual_adjustment' => '手動調整庫存',
2025-12-30 15:03:19 +08:00
'adjustment' => '盤點調整',
'purchase_in' => '採購進貨',
'sales_out' => '銷售出庫',
'return_in' => '退貨入庫',
'return_out' => '退貨出庫',
'transfer_in' => '撥補入庫',
'transfer_out' => '撥補出庫',
];
$chineseType = $typeMapping[$type] ?? $type;
2026-01-22 15:39:35 +08:00
// 如果是編輯頁面來的,且沒傳 type設為手動編輯
if (!$isAdjustment && !isset($validated['type'])) {
2025-12-30 15:03:19 +08:00
$chineseType = '手動編輯';
}
2026-01-22 15:39:35 +08:00
// 整理原因
$reason = $validated['reason'] ?? ($isAdjustment ? '手動庫存調整' : '編輯頁面更新');
if (isset($validated['notes'])) {
$reason .= ' - ' . $validated['notes'];
}
2025-12-30 15:03:19 +08:00
// 寫入異動紀錄
if (abs($changeQty) > 0.0001) {
$inventory->transactions()->create([
'type' => $chineseType,
'quantity' => $changeQty,
'unit_cost' => $inventory->unit_cost, // 記錄
2025-12-30 15:03:19 +08:00
'balance_before' => $currentQty,
'balance_after' => $newQty,
2026-01-22 15:39:35 +08:00
'reason' => $reason,
'actual_time' => now(),
2025-12-30 15:03:19 +08:00
'user_id' => auth()->id(),
]);
}
return redirect()->route('warehouses.inventory.index', $inventory->warehouse_id)
->with('success', '庫存資料已更新');
});
}
public function destroy(Warehouse $warehouse, $inventoryId)
2025-12-30 15:03:19 +08:00
{
// ... (unchanged) ...
$inventory = Inventory::findOrFail($inventoryId);
2025-12-30 15:03:19 +08:00
2026-01-22 15:39:35 +08:00
// 庫存 > 0 不允許刪除 (哪怕是軟刪除)
2025-12-30 15:03:19 +08:00
if ($inventory->quantity > 0) {
2026-01-22 15:39:35 +08:00
return redirect()->back()->with('error', '庫存數量大於 0無法刪除。請先進行出庫或調整。');
}
// 歸零異動 (因為已經限制為 0 才能刪,這段邏輯可以簡化,但為了保險起見,若有微小殘值仍可記錄歸零)
if (abs($inventory->quantity) > 0.0001) {
2025-12-30 15:03:19 +08:00
$inventory->transactions()->create([
'type' => '手動編輯',
'quantity' => -$inventory->quantity,
'unit_cost' => $inventory->unit_cost,
2025-12-30 15:03:19 +08:00
'balance_before' => $inventory->quantity,
'balance_after' => 0,
'reason' => '刪除庫存品項',
'actual_time' => now(),
'user_id' => auth()->id(),
]);
}
$inventory->delete();
return redirect()->route('warehouses.inventory.index', $warehouse->id)
->with('success', '庫存品項已刪除');
}
public function history(Request $request, \App\Modules\Inventory\Models\Warehouse $warehouse)
2025-12-30 15:03:19 +08:00
{
// ... (前端 history 頁面可能也需要 unit_cost這裡可補上) ...
2026-01-22 15:39:35 +08:00
$inventoryId = $request->query('inventoryId');
$productId = $request->query('productId');
if ($productId) {
$product = Product::findOrFail($productId);
// 取得該倉庫中該商品的所有批號 ID
$inventoryIds = Inventory::where('warehouse_id', $warehouse->id)
->where('product_id', $productId)
->pluck('id')
->toArray();
$transactionsRaw = InventoryTransaction::whereIn('inventory_id', $inventoryIds)
->with('inventory') // 需要批號資訊
->orderBy('actual_time', 'desc')
->orderBy('id', 'desc')
->get();
// 手動 Hydrate 使用者資料
$userIds = $transactionsRaw->pluck('user_id')->filter()->unique()->toArray();
$users = $this->coreService->getUsersByIds($userIds)->keyBy('id');
// 計算商品在該倉庫的總量(不分批號)
$currentRunningTotal = (float) Inventory::whereIn('id', $inventoryIds)->sum('quantity');
$transactions = $transactionsRaw->map(function ($tx) use ($users, &$currentRunningTotal) {
$user = $tx->user_id ? ($users[$tx->user_id] ?? null) : null;
$balanceAfter = $currentRunningTotal;
// 為下一筆(較舊的)紀錄更新 Running Total
$currentRunningTotal -= (float) $tx->quantity;
return [
'id' => (string) $tx->id,
'type' => $tx->type,
'quantity' => (float) $tx->quantity,
'unit_cost' => (float) $tx->unit_cost,
'balanceAfter' => (float) $balanceAfter, // 顯示該商品在倉庫的累計結餘
'reason' => $tx->reason,
'userName' => $user ? $user->name : '系統',
'actualTime' => $tx->actual_time ? $tx->actual_time->format('Y-m-d H:i') : $tx->created_at->format('Y-m-d H:i'),
'batchNumber' => $tx->inventory?->batch_number ?? '-', // 補上批號資訊
];
});
// 重新計算目前的總量(用於 Header 顯示,確保一致性)
$totalQuantity = Inventory::whereIn('id', $inventoryIds)->sum('quantity');
return Inertia::render('Warehouse/InventoryHistory', [
'warehouse' => $warehouse,
'inventory' => [
'id' => null, // 跨批號查詢沒有單一 ID
'productName' => $product->name,
'productCode' => $product->code,
'batchNumber' => '所有批號',
'quantity' => (float) $totalQuantity,
],
'transactions' => $transactions
]);
2026-01-22 15:39:35 +08:00
}
if ($inventoryId) {
// 單一批號查詢
// 移除 'transactions.user'
$inventory = Inventory::with(['product', 'transactions' => function($query) {
2026-01-22 15:39:35 +08:00
$query->orderBy('actual_time', 'desc')->orderBy('id', 'desc');
}])->findOrFail($inventoryId);
// 手動 Hydrate 使用者資料
$userIds = $inventory->transactions->pluck('user_id')->filter()->unique()->toArray();
$users = $this->coreService->getUsersByIds($userIds)->keyBy('id');
2026-01-22 15:39:35 +08:00
$transactions = $inventory->transactions->map(function ($tx) use ($users) {
$user = $tx->user_id ? ($users[$tx->user_id] ?? null) : null;
2026-01-22 15:39:35 +08:00
return [
'id' => (string) $tx->id,
'type' => $tx->type,
'quantity' => (float) $tx->quantity,
'unit_cost' => (float) $tx->unit_cost,
2026-01-22 15:39:35 +08:00
'balanceAfter' => (float) $tx->balance_after,
'reason' => $tx->reason,
'userName' => $user ? $user->name : '系統', // 手動對應
2026-01-22 15:39:35 +08:00
'actualTime' => $tx->actual_time ? $tx->actual_time->format('Y-m-d H:i') : $tx->created_at->format('Y-m-d H:i'),
];
});
return Inertia::render('Warehouse/InventoryHistory', [
2026-01-22 15:39:35 +08:00
'warehouse' => $warehouse,
'inventory' => [
'id' => (string) $inventory->id,
'productName' => $inventory->product?->name ?? '未知商品',
'productCode' => $inventory->product?->code ?? 'N/A',
'batchNumber' => $inventory->batch_number ?? '-',
'quantity' => (float) $inventory->quantity,
'unit_cost' => (float) $inventory->unit_cost,
'total_value' => (float) $inventory->total_value,
2026-01-22 15:39:35 +08:00
],
'transactions' => $transactions
]);
}
return redirect()->back()->with('error', '未提供查詢參數');
2025-12-30 15:03:19 +08:00
}
}