diff --git a/app/Http/Controllers/Admin/ProductController.php b/app/Http/Controllers/Admin/ProductController.php index 8eedc6d..cc1cba1 100644 --- a/app/Http/Controllers/Admin/ProductController.php +++ b/app/Http/Controllers/Admin/ProductController.php @@ -120,8 +120,22 @@ class ProductController extends Controller }); } - if ($request->filled('start_date') && $request->filled('end_date')) { - $logQuery->whereBetween('created_at', [$request->start_date, $request->end_date]); + $logDefaultStart = now()->startOfDay()->format('Y-m-d H:i'); + $logDefaultEnd = now()->endOfDay()->format('Y-m-d H:i'); + + if ($request->filled('start_date') || $request->filled('end_date')) { + if ($request->filled('start_date')) { + $logQuery->where('created_at', '>=', \Illuminate\Support\Carbon::parse($request->start_date)); + } + if ($request->filled('end_date')) { + $logQuery->where('created_at', '<=', \Illuminate\Support\Carbon::parse($request->end_date)->endOfMinute()); + } + } else { + $logQuery->whereBetween('created_at', [now()->startOfDay(), now()->endOfDay()]); + $request->merge([ + 'start_date' => $logDefaultStart, + 'end_date' => $logDefaultEnd + ]); } $logs = $logQuery->latest()->paginate($per_page, ['*'], 'log_page')->withQueryString(); @@ -130,18 +144,25 @@ class ProductController extends Controller 'success' => true, 'html' => view('admin.products.partials.tab-logs', [ 'logs' => $logs, - 'companies' => $companies + 'companies' => $companies, + 'logDefaultStart' => $logDefaultStart, + 'logDefaultEnd' => $logDefaultEnd ])->render() ]); } } + $logDefaultStart = now()->startOfDay()->format('Y-m-d H:i'); + $logDefaultEnd = now()->endOfDay()->format('Y-m-d H:i'); + return view('admin.products.index', [ 'products' => $products, 'categories' => $categories, 'companies' => $companies, 'companySettings' => $companySettings, - 'routeName' => $routeName + 'routeName' => $routeName, + 'logDefaultStart' => $logDefaultStart, + 'logDefaultEnd' => $logDefaultEnd ]); } diff --git a/app/Http/Controllers/Admin/SalesController.php b/app/Http/Controllers/Admin/SalesController.php index f15802d..2fbd01e 100644 --- a/app/Http/Controllers/Admin/SalesController.php +++ b/app/Http/Controllers/Admin/SalesController.php @@ -36,6 +36,14 @@ class SalesController extends Controller $startDate = $request->input('start_date'); $endDate = $request->input('end_date'); + // 判斷是否為隱含篩選 (未選日期時預設抓6個月) + $isImplicitFilter = false; + if (!$startDate || !$endDate) { + $isImplicitFilter = true; + $startDate = now()->subMonths(6)->format('Y-m-d H:i'); + $endDate = now()->format('Y-m-d H:i'); + } + $data = [ 'title' => '銷售&金流紀錄', 'description' => '銷售交易與金流明細查詢', @@ -45,9 +53,10 @@ class SalesController extends Controller 'machine_id' => $machineId, 'payment_type' => $paymentType, 'status' => $status, - 'start_date' => $startDate, - 'end_date' => $endDate, + 'start_date' => $request->input('start_date'), // 保留原始輸入以顯示於 UI (如果是隱含的則 UI 顯示空) + 'end_date' => $request->input('end_date'), ], + 'isImplicitFilter' => $isImplicitFilter, 'machines' => Machine::select('id', 'name', 'serial_no')->get(), 'paymentTypes' => Order::getPaymentTypeLabels(), ]; @@ -58,13 +67,12 @@ class SalesController extends Controller $dispenseQuery = DispenseRecord::with(['order:id,order_no,flow_id', 'machine:id,name,serial_no', 'product:id,name']); // 共用過濾器:日期 - if ($startDate && $endDate) { - $start = Carbon::parse($startDate); - $end = Carbon::parse($endDate)->endOfMinute(); - $ordersQuery->whereBetween('created_at', [$start, $end]); - $invoicesQuery->whereBetween('invoice_date', [$start, $end]); - $dispenseQuery->whereBetween('machine_time', [$start, $end]); - } + $start = Carbon::parse($startDate); + $end = Carbon::parse($endDate)->endOfMinute(); + + $ordersQuery->whereBetween('created_at', [$start, $end]); + $invoicesQuery->whereBetween('invoice_date', [$start, $end]); + $dispenseQuery->whereBetween('machine_time', [$start, $end]); // 共用過濾器:機台 if ($machineId) { @@ -195,12 +203,20 @@ class SalesController extends Controller $logQuery->where('action', $request->action); } - // 新增:日期區間篩選 - if ($request->filled('start_date') && $request->filled('end_date')) { + // 新增:日期區間篩選 (隱含 6 個月限制) + $startDate = $request->input('start_date'); + $endDate = $request->input('end_date'); + + if (!$startDate && !$endDate) { + $logQuery->where('created_at', '>=', now()->subMonths(6)); + } else { try { - $start = \Carbon\Carbon::parse($request->start_date)->startOfMinute(); - $end = \Carbon\Carbon::parse($request->end_date)->endOfMinute(); - $logQuery->whereBetween('created_at', [$start, $end]); + if ($startDate) { + $logQuery->where('created_at', '>=', \Carbon\Carbon::parse($startDate)->startOfMinute()); + } + if ($endDate) { + $logQuery->where('created_at', '<=', \Carbon\Carbon::parse($endDate)->endOfMinute()); + } } catch (\Exception $e) { } } @@ -416,12 +432,20 @@ class SalesController extends Controller $logQuery->where('action', $request->action); } - // 新增:日期區間篩選 - if ($request->filled('start_date') && $request->filled('end_date')) { + // 新增:日期區間篩選 (隱含 6 個月限制) + $startDate = $request->input('start_date'); + $endDate = $request->input('end_date'); + + if (!$startDate && !$endDate) { + $logQuery->where('created_at', '>=', now()->subMonths(6)); + } else { try { - $start = \Carbon\Carbon::parse($request->start_date)->startOfMinute(); - $end = \Carbon\Carbon::parse($request->end_date)->endOfMinute(); - $logQuery->whereBetween('created_at', [$start, $end]); + if ($startDate) { + $logQuery->where('created_at', '>=', \Carbon\Carbon::parse($startDate)->startOfMinute()); + } + if ($endDate) { + $logQuery->where('created_at', '<=', \Carbon\Carbon::parse($endDate)->endOfMinute()); + } } catch (\Exception $e) { } } diff --git a/app/Http/Controllers/Admin/WarehouseController.php b/app/Http/Controllers/Admin/WarehouseController.php index 7783b5e..295d658 100644 --- a/app/Http/Controllers/Admin/WarehouseController.php +++ b/app/Http/Controllers/Admin/WarehouseController.php @@ -191,8 +191,19 @@ class WarehouseController extends Controller if ($search = $request->input('search_order')) { $query->where('order_no', 'like', "%{$search}%"); } - if ($request->filled('start_date') && $request->filled('end_date')) { - $query->whereBetween('created_at', [$request->start_date, $request->end_date]); + if ($request->filled('start_date') || $request->filled('end_date')) { + if ($request->filled('start_date')) { + $query->where('created_at', '>=', \Illuminate\Support\Carbon::parse($request->start_date)); + } + if ($request->filled('end_date')) { + $query->where('created_at', '<=', \Illuminate\Support\Carbon::parse($request->end_date)->endOfMinute()); + } + } else { + // 隱性限制:預設只抓 6 個月內的單據以保護效能,但 UI 保持空白 + $query->where('created_at', '>=', now()->subMonths(6)->startOfDay()); + + $data['stockInDefaultStart'] = ''; + $data['stockInDefaultEnd'] = ''; } $data['orders'] = $query->paginate($request->input('per_page', 10), ['*'], 'order_page')->withQueryString(); $data['stock_in_products'] = Product::with('translations')->orderBy('name')->get(['id', 'name', 'image_url', 'name_dictionary_key']); @@ -210,8 +221,29 @@ class WarehouseController extends Controller if ($request->filled('type')) { $query->where('type', $request->input('type')); } - if ($request->filled('start_date') && $request->filled('end_date')) { - $query->whereBetween('created_at', [$request->start_date, $request->end_date]); + if ($request->filled('start_date') || $request->filled('end_date')) { + if ($request->filled('start_date')) { + $query->where('created_at', '>=', \Illuminate\Support\Carbon::parse($request->start_date)); + } + if ($request->filled('end_date')) { + $query->where('created_at', '<=', \Illuminate\Support\Carbon::parse($request->end_date)->endOfMinute()); + } + } else { + // 預設當天 + $start = now()->startOfDay(); + $end = now()->endOfDay(); + $query->whereBetween('created_at', [$start, $end]); + + $data['movementDefaultStart'] = $start->format('Y-m-d H:i'); + $data['movementDefaultEnd'] = $end->format('Y-m-d H:i'); + + // 只有在當前分頁是 movements 時才合併到 request + if ($tab === 'movements') { + $request->merge([ + 'start_date' => $data['movementDefaultStart'], + 'end_date' => $data['movementDefaultEnd'] + ]); + } } $data['movements'] = $query->paginate($request->input('per_page', 15), ['*'], 'movement_page')->withQueryString(); } @@ -378,8 +410,16 @@ class WarehouseController extends Controller if ($search = $request->input('search_order')) { $query->where('order_no', 'like', "%{$search}%"); } - if ($request->filled('start_date') && $request->filled('end_date')) { - $query->whereBetween('created_at', [$request->start_date, $request->end_date]); + if ($request->filled('start_date') || $request->filled('end_date')) { + if ($request->filled('start_date')) { + $query->where('created_at', '>=', \Illuminate\Support\Carbon::parse($request->start_date)); + } + if ($request->filled('end_date')) { + $query->where('created_at', '<=', \Illuminate\Support\Carbon::parse($request->end_date)->endOfMinute()); + } + } else { + // 隱性限制:預設只抓 6 個月內的單據以保護效能,但 UI 保持空白 + $query->where('created_at', '>=', now()->subMonths(6)->startOfDay()); } $orders = $query->paginate($request->input('per_page', 15))->withQueryString(); @@ -394,8 +434,11 @@ class WarehouseController extends Controller $warehouses = Warehouse::active()->orderBy('name')->get(['id', 'name']); $machines = Machine::orderBy('name')->get(['id', 'name', 'serial_no']); $products = Product::with('translations')->orderBy('name')->get(['id', 'name', 'image_url', 'name_dictionary_key']); + + $defaultStart = ''; + $defaultEnd = ''; - return view('admin.warehouses.transfers', compact('orders', 'warehouses', 'machines', 'products')); + return view('admin.warehouses.transfers', compact('orders', 'warehouses', 'machines', 'products', 'defaultStart', 'defaultEnd')); } /** @@ -674,8 +717,16 @@ class WarehouseController extends Controller if ($search = $request->input('search_order')) { $query->where('order_no', 'like', "%{$search}%"); } - if ($request->filled('start_date') && $request->filled('end_date')) { - $query->whereBetween('created_at', [$request->start_date, $request->end_date]); + if ($request->filled('start_date') || $request->filled('end_date')) { + if ($request->filled('start_date')) { + $query->where('created_at', '>=', \Illuminate\Support\Carbon::parse($request->start_date)); + } + if ($request->filled('end_date')) { + $query->where('created_at', '<=', \Illuminate\Support\Carbon::parse($request->end_date)->endOfMinute()); + } + } else { + // 隱性限制:預設只抓 6 個月內的單據以保護效能,但 UI 保持空白 + $query->where('created_at', '>=', now()->subMonths(6)->startOfDay()); } $orders = $query->paginate($request->input('per_page', 10))->withQueryString(); @@ -691,14 +742,16 @@ class WarehouseController extends Controller $machines = Machine::orderBy('name')->get(['id', 'name', 'serial_no']); $products = Product::with('translations')->orderBy('name')->get(['id', 'name', 'image_url', 'name_dictionary_key']); - // 同租戶帳號(用於指派人員) $userQuery = \App\Models\System\User::where('status', 1)->orderBy('name'); if (!Auth::user()->isSystemAdmin()) { $userQuery->where('company_id', Auth::user()->company_id); } $users = $userQuery->get(['id', 'name']); - return view('admin.warehouses.replenishments', compact('orders', 'warehouses', 'machines', 'products', 'users')); + $defaultStart = ''; + $defaultEnd = ''; + + return view('admin.warehouses.replenishments', compact('orders', 'warehouses', 'machines', 'products', 'users', 'defaultStart', 'defaultEnd')); } /** diff --git a/database/migrations/2026_05_16_230337_add_composite_index_to_system_operation_logs_table.php b/database/migrations/2026_05_16_230337_add_composite_index_to_system_operation_logs_table.php new file mode 100644 index 0000000..e80e4ea --- /dev/null +++ b/database/migrations/2026_05_16_230337_add_composite_index_to_system_operation_logs_table.php @@ -0,0 +1,28 @@ +index(['company_id', 'created_at']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('system_operation_logs', function (Blueprint $table) { + $table->dropIndex(['company_id', 'created_at']); + }); + } +}; diff --git a/lang/en.json b/lang/en.json index 5b8827f..447b741 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1464,6 +1464,7 @@ "Show points rules in products": "Show points rules in products", "Showing": "Showing", "Showing :from to :to of :total items": "Showing :from to :to of :total items", + "Showing last 6 months by default when no date range is selected": "Showing last 6 months by default when no date range is selected", "Sign in to your account": "Sign in to your account", "Signed in as": "Signed in as", "Slot": "Slot", diff --git a/lang/ja.json b/lang/ja.json index bcb0990..2c012c2 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -1464,6 +1464,7 @@ "Show points rules in products": "商品にポイントルールフィールドを表示する", "Showing": "表示中", "Showing :from to :to of :total items": "全 :total 件中 :from から :to 件を表示", + "Showing last 6 months by default when no date range is selected": "日付範囲が未選択の場合、デフォルトで過去6ヶ月分を表示します", "Sign in to your account": "アカウントにサインイン", "Signed in as": "ログイン中のユーザー", "Slot": "スロット", diff --git a/lang/zh_TW.json b/lang/zh_TW.json index bbf480a..e55b14a 100644 --- a/lang/zh_TW.json +++ b/lang/zh_TW.json @@ -1484,6 +1484,7 @@ "Show points rules in products": "在商品資料中顯示點數規則相關欄位", "Showing": "目前顯示", "Showing :from to :to of :total items": "顯示第 :from 到 :to 項,共 :total 項", + "Showing last 6 months by default when no date range is selected": "未選擇日期區間時,預設顯示最近 6 個月的資料", "Sign in to your account": "隨時隨地掌控您的業務。", "Signed in as": "登入身份", "Slot": "貨道", diff --git a/resources/views/admin/products/partials/tab-logs.blade.php b/resources/views/admin/products/partials/tab-logs.blade.php index 16577e2..978f1cd 100644 --- a/resources/views/admin/products/partials/tab-logs.blade.php +++ b/resources/views/admin/products/partials/tab-logs.blade.php @@ -30,49 +30,73 @@ placeholder="{{ __('Search notes or values...') }}"> - {{-- Date Range --}} -
getLocale() == 'zh_TW' ? 'zh_tw' : 'en' }}', - defaultDate: '{{ request('start_date') }}' && '{{ request('end_date') }}' ? ['{{ request('start_date') }}', '{{ request('end_date') }}'] : [], - onChange: function(selectedDates, dateStr, instance) { - if (selectedDates.length === 2) { - $refs.startDate.value = instance.formatDate(selectedDates[0], 'Y-m-d H:i'); - $refs.endDate.value = instance.formatDate(selectedDates[1], 'Y-m-d H:i'); - } else if (selectedDates.length === 0) { - $refs.startDate.value = ''; - $refs.endDate.value = ''; - } - } + defaultHour: 0, + defaultMinute: 0, + locale: 'zh_tw', + position: 'auto right', + defaultDate: '{{ request('start_date', $logDefaultStart ?? '') }}' })"> - - - + +
{{ __('Start Time') }}
+
+ + {{-- 結束時間 --}} +
+ + + + +
{{ __('End Time') }}
{{-- Buttons --}}
- {{-- 日期範圍 --}} -
- - - - + + - - - + +
{{ __('Start Time') }}
+
+ + {{-- 結束時間 --}} +
+ + + + +
{{ __('End Time') }}
@@ -73,7 +80,19 @@ -
+@if($isImplicitFilter) +
+
+ + {{ __('Showing last 6 months by default when no date range is selected') }} + +
+@endif + {{-- Table (Desktop) --}}