[FEAT] 合併機台日誌層級篩選與銷售紀錄付款/出貨狀態篩選
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
commit
06d68a2783
@ -35,6 +35,7 @@ class SalesController extends Controller
|
|||||||
$machineId = $request->input('machine_id');
|
$machineId = $request->input('machine_id');
|
||||||
$paymentType = $request->input('payment_type');
|
$paymentType = $request->input('payment_type');
|
||||||
$status = $request->input('status');
|
$status = $request->input('status');
|
||||||
|
$deliveryStatus = $request->input('delivery_status');
|
||||||
$startDate = $request->input('start_date');
|
$startDate = $request->input('start_date');
|
||||||
$endDate = $request->input('end_date');
|
$endDate = $request->input('end_date');
|
||||||
|
|
||||||
@ -55,6 +56,7 @@ class SalesController extends Controller
|
|||||||
'machine_id' => $machineId,
|
'machine_id' => $machineId,
|
||||||
'payment_type' => $paymentType,
|
'payment_type' => $paymentType,
|
||||||
'status' => $status,
|
'status' => $status,
|
||||||
|
'delivery_status' => $deliveryStatus,
|
||||||
'start_date' => $request->input('start_date'), // 保留原始輸入以顯示於 UI (如果是隱含的則 UI 顯示空)
|
'start_date' => $request->input('start_date'), // 保留原始輸入以顯示於 UI (如果是隱含的則 UI 顯示空)
|
||||||
'end_date' => $request->input('end_date'),
|
'end_date' => $request->input('end_date'),
|
||||||
],
|
],
|
||||||
@ -126,6 +128,11 @@ class SalesController extends Controller
|
|||||||
if ($tab === 'orders') {
|
if ($tab === 'orders') {
|
||||||
if ($paymentType) $ordersQuery->where('payment_type', $paymentType);
|
if ($paymentType) $ordersQuery->where('payment_type', $paymentType);
|
||||||
if ($status) $ordersQuery->where('status', $status);
|
if ($status) $ordersQuery->where('status', $status);
|
||||||
|
// 出貨狀態:唯有付款成功(completed/paid)的單才有出貨結果,需與列表顯示邏輯 (hasDeliveryOutcome) 一致
|
||||||
|
if ($deliveryStatus !== null && $deliveryStatus !== '') {
|
||||||
|
$ordersQuery->whereIn('status', [Order::STATUS_COMPLETED, 'paid'])
|
||||||
|
->where('delivery_status', $deliveryStatus);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 發票專用過濾器:狀態(pending/issued/failed/void)
|
// 發票專用過濾器:狀態(pending/issued/failed/void)
|
||||||
|
|||||||
@ -112,9 +112,11 @@
|
|||||||
"All Categories": "All Categories",
|
"All Categories": "All Categories",
|
||||||
"All Command Types": "All Command Types",
|
"All Command Types": "All Command Types",
|
||||||
"All Companies": "All Companies",
|
"All Companies": "All Companies",
|
||||||
|
"All Dispense Statuses": "All Dispense Statuses",
|
||||||
"All Levels": "All Levels",
|
"All Levels": "All Levels",
|
||||||
"All Machines": "All Machines",
|
"All Machines": "All Machines",
|
||||||
"All Normal": "All Normal",
|
"All Normal": "All Normal",
|
||||||
|
"All Payment Statuses": "All Payment Statuses",
|
||||||
"All Permissions": "All Permissions",
|
"All Permissions": "All Permissions",
|
||||||
"All Products (ALL)": "All Products (ALL)",
|
"All Products (ALL)": "All Products (ALL)",
|
||||||
"All Slots": "All Slots",
|
"All Slots": "All Slots",
|
||||||
@ -1525,6 +1527,7 @@
|
|||||||
"Page 69": "Page 69",
|
"Page 69": "Page 69",
|
||||||
"Page 7": "Page 7",
|
"Page 7": "Page 7",
|
||||||
"Page Lock Status": "Page Lock Status",
|
"Page Lock Status": "Page Lock Status",
|
||||||
|
"Paid": "Paid",
|
||||||
"Parameters": "Parameters",
|
"Parameters": "Parameters",
|
||||||
"Partial Dispense Success": "Partial Dispense Success",
|
"Partial Dispense Success": "Partial Dispense Success",
|
||||||
"Pass Code": "Pass Code",
|
"Pass Code": "Pass Code",
|
||||||
|
|||||||
@ -112,9 +112,11 @@
|
|||||||
"All Categories": "すべてのカテゴリ",
|
"All Categories": "すべてのカテゴリ",
|
||||||
"All Command Types": "すべてのコマンドタイプ",
|
"All Command Types": "すべてのコマンドタイプ",
|
||||||
"All Companies": "すべての会社",
|
"All Companies": "すべての会社",
|
||||||
|
"All Dispense Statuses": "すべての出庫ステータス",
|
||||||
"All Levels": "すべてのレベル",
|
"All Levels": "すべてのレベル",
|
||||||
"All Machines": "すべての機器",
|
"All Machines": "すべての機器",
|
||||||
"All Normal": "すべて正常",
|
"All Normal": "すべて正常",
|
||||||
|
"All Payment Statuses": "すべての決済ステータス",
|
||||||
"All Permissions": "すべての権限",
|
"All Permissions": "すべての権限",
|
||||||
"All Products (ALL)": "全商品 (ALL)",
|
"All Products (ALL)": "全商品 (ALL)",
|
||||||
"All Slots": "すべてのスロット",
|
"All Slots": "すべてのスロット",
|
||||||
@ -1525,6 +1527,7 @@
|
|||||||
"Page 69": "ページ 69 (購入キャンセル)",
|
"Page 69": "ページ 69 (購入キャンセル)",
|
||||||
"Page 7": "ページ 7 (ロックページ)",
|
"Page 7": "ページ 7 (ロックページ)",
|
||||||
"Page Lock Status": "ページロックステータス",
|
"Page Lock Status": "ページロックステータス",
|
||||||
|
"Paid": "支払い済み",
|
||||||
"Parameters": "パラメータ設定",
|
"Parameters": "パラメータ設定",
|
||||||
"Partial Dispense Success": "一部出庫成功",
|
"Partial Dispense Success": "一部出庫成功",
|
||||||
"Pass Code": "パスコード",
|
"Pass Code": "パスコード",
|
||||||
|
|||||||
@ -112,9 +112,11 @@
|
|||||||
"All Categories": "所有分類",
|
"All Categories": "所有分類",
|
||||||
"All Command Types": "所有指令類型",
|
"All Command Types": "所有指令類型",
|
||||||
"All Companies": "所有公司",
|
"All Companies": "所有公司",
|
||||||
|
"All Dispense Statuses": "所有出貨狀態",
|
||||||
"All Levels": "所有層級",
|
"All Levels": "所有層級",
|
||||||
"All Machines": "所有機台",
|
"All Machines": "所有機台",
|
||||||
"All Normal": "運作正常",
|
"All Normal": "運作正常",
|
||||||
|
"All Payment Statuses": "所有付款狀態",
|
||||||
"All Permissions": "全部權限",
|
"All Permissions": "全部權限",
|
||||||
"All Products (ALL)": "全部商品 (ALL)",
|
"All Products (ALL)": "全部商品 (ALL)",
|
||||||
"All Slots": "所有貨道",
|
"All Slots": "所有貨道",
|
||||||
@ -1525,6 +1527,7 @@
|
|||||||
"Page 69": "取消購買",
|
"Page 69": "取消購買",
|
||||||
"Page 7": "鎖定頁",
|
"Page 7": "鎖定頁",
|
||||||
"Page Lock Status": "頁面鎖定狀態",
|
"Page Lock Status": "頁面鎖定狀態",
|
||||||
|
"Paid": "已付款",
|
||||||
"Parameters": "參數設定",
|
"Parameters": "參數設定",
|
||||||
"Partial Dispense Success": "部分出貨成功",
|
"Partial Dispense Success": "部分出貨成功",
|
||||||
"Pass Code": "通行碼",
|
"Pass Code": "通行碼",
|
||||||
|
|||||||
@ -49,6 +49,7 @@
|
|||||||
inventoryLoading: false,
|
inventoryLoading: false,
|
||||||
startDate: '',
|
startDate: '',
|
||||||
endDate: '',
|
endDate: '',
|
||||||
|
selectedLevel: '',
|
||||||
tab: 'list',
|
tab: 'list',
|
||||||
viewMode: 'fleet',
|
viewMode: 'fleet',
|
||||||
selectedMachine: null,
|
selectedMachine: null,
|
||||||
@ -321,6 +322,7 @@
|
|||||||
let url = '/admin/machines/' + this.currentMachineId + '/logs-ajax?type=' + this.activeTab + '&page=' + page;
|
let url = '/admin/machines/' + this.currentMachineId + '/logs-ajax?type=' + this.activeTab + '&page=' + page;
|
||||||
if (this.startDate) url += '&start_date=' + this.startDate;
|
if (this.startDate) url += '&start_date=' + this.startDate;
|
||||||
if (this.endDate) url += '&end_date=' + this.endDate;
|
if (this.endDate) url += '&end_date=' + this.endDate;
|
||||||
|
if (this.selectedLevel) url += '&level=' + this.selectedLevel;
|
||||||
|
|
||||||
const res = await fetch(url);
|
const res = await fetch(url);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
@ -993,7 +995,7 @@
|
|||||||
|
|
||||||
<!-- Responsive Search within Panel -->
|
<!-- Responsive Search within Panel -->
|
||||||
<div class="mt-2 flex flex-col sm:flex-row sm:items-center gap-4 sm:gap-6">
|
<div class="mt-2 flex flex-col sm:flex-row sm:items-center gap-4 sm:gap-6">
|
||||||
<div class="grid grid-cols-1 sm:flex sm:items-center gap-3 sm:gap-4 flex-1">
|
<div class="grid grid-cols-1 sm:flex sm:flex-wrap sm:items-center gap-3 sm:gap-4 flex-1 min-w-0">
|
||||||
<div class="flex flex-col sm:flex-row sm:items-center gap-2 group">
|
<div class="flex flex-col sm:flex-row sm:items-center gap-2 group">
|
||||||
<label
|
<label
|
||||||
class="text-[11px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest whitespace-nowrap">{{
|
class="text-[11px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest whitespace-nowrap">{{
|
||||||
@ -1042,10 +1044,22 @@
|
|||||||
class="luxury-input py-2.5 pl-12 pr-4 w-full sm:w-52 text-sm font-bold tracking-tight cursor-pointer">
|
class="luxury-input py-2.5 pl-12 pr-4 w-full sm:w-52 text-sm font-bold tracking-tight cursor-pointer">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex flex-col sm:flex-row sm:items-center gap-2 group w-full sm:w-auto">
|
||||||
|
<label
|
||||||
|
class="text-[11px] font-black text-slate-400 dark:text-slate-500 uppercase tracking-widest whitespace-nowrap">{{
|
||||||
|
__('Level') }}</label>
|
||||||
|
<x-searchable-select id="log-level-select" name="level" class="w-full sm:w-44"
|
||||||
|
:placeholder="__('All Levels')" :has-search="false"
|
||||||
|
@change="selectedLevel = $event.target.value.trim(); fetchLogs(1)">
|
||||||
|
<option value="info" data-title="{{ __('Info') }}">{{ __('Info') }}</option>
|
||||||
|
<option value="warning" data-title="{{ __('Warning') }}">{{ __('Warning') }}</option>
|
||||||
|
<option value="error" data-title="{{ __('Error') }}">{{ __('Error') }}</option>
|
||||||
|
</x-searchable-select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-wrap items-center justify-start sm:justify-end gap-4 sm:gap-6">
|
<div class="flex flex-wrap items-center justify-start sm:justify-end gap-4 sm:gap-6 shrink-0">
|
||||||
<button @click="confirmResolve()"
|
<button @click="confirmResolve()"
|
||||||
class="text-[12px] font-bold text-rose-500 dark:text-rose-400 uppercase tracking-widest hover:text-rose-600 transition-colors flex items-center gap-1.5 px-3 py-1.5 rounded-xl hover:bg-rose-500/5 transition-all">
|
class="text-[12px] font-bold text-rose-500 dark:text-rose-400 uppercase tracking-widest hover:text-rose-600 transition-colors flex items-center gap-1.5 px-3 py-1.5 rounded-xl hover:bg-rose-500/5 transition-all whitespace-nowrap">
|
||||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||||
stroke-width="2.5">
|
stroke-width="2.5">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round"
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
@ -1053,8 +1067,10 @@
|
|||||||
</svg>
|
</svg>
|
||||||
{{ __('Clear Abnormal Status') }}
|
{{ __('Clear Abnormal Status') }}
|
||||||
</button>
|
</button>
|
||||||
<button @click="startDate = ''; endDate = ''; fetchLogs(1)"
|
<button @click="startDate = ''; endDate = ''; selectedLevel = '';
|
||||||
class="text-[12px] font-bold text-cyan-600 dark:text-cyan-400 uppercase tracking-widest hover:text-cyan-500 transition-colors flex items-center gap-1.5">
|
(() => { const s = document.getElementById('log-level-select'); const i = window.HSSelect?.getInstance(s); if (i) i.setValue(' '); })();
|
||||||
|
fetchLogs(1)"
|
||||||
|
class="text-[12px] font-bold text-cyan-600 dark:text-cyan-400 uppercase tracking-widest hover:text-cyan-500 transition-colors flex items-center gap-1.5 whitespace-nowrap">
|
||||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||||
stroke-width="2.5">
|
stroke-width="2.5">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round"
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
|||||||
@ -29,6 +29,31 @@
|
|||||||
</x-searchable-select>
|
</x-searchable-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{-- 付款狀態 --}}
|
||||||
|
<div class="w-full lg:w-44">
|
||||||
|
<x-searchable-select name="status" :placeholder="__('All Payment Statuses')" :selected="$filters['status']"
|
||||||
|
:has-search="false" @change="$el.closest('form').dispatchEvent(new Event('submit'))">
|
||||||
|
<option value="pending" {{ $filters['status']==='pending' ? 'selected' : '' }} data-title="{{ __('Pending') }}">{{ __('Pending') }}</option>
|
||||||
|
<option value="paid" {{ $filters['status']==='paid' ? 'selected' : '' }} data-title="{{ __('Paid') }}">{{ __('Paid') }}</option>
|
||||||
|
<option value="completed" {{ $filters['status']==='completed' ? 'selected' : '' }} data-title="{{ __('Completed') }}">{{ __('Completed') }}</option>
|
||||||
|
<option value="failed" {{ $filters['status']==='failed' ? 'selected' : '' }} data-title="{{ __('Failed') }}">{{ __('Failed') }}</option>
|
||||||
|
<option value="abandoned" {{ $filters['status']==='abandoned' ? 'selected' : '' }} data-title="{{ __('Unpaid') }}">{{ __('Unpaid') }}</option>
|
||||||
|
<option value="cancelled" {{ $filters['status']==='cancelled' ? 'selected' : '' }} data-title="{{ __('Cancelled') }}">{{ __('Cancelled') }}</option>
|
||||||
|
<option value="refunded" {{ $filters['status']==='refunded' ? 'selected' : '' }} data-title="{{ __('Refunded') }}">{{ __('Refunded') }}</option>
|
||||||
|
</x-searchable-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- 出貨狀態 --}}
|
||||||
|
<div class="w-full lg:w-44">
|
||||||
|
<x-searchable-select name="delivery_status" :placeholder="__('All Dispense Statuses')"
|
||||||
|
:selected="$filters['delivery_status']" :has-search="false"
|
||||||
|
@change="$el.closest('form').dispatchEvent(new Event('submit'))">
|
||||||
|
<option value="1" {{ (string)$filters['delivery_status']==='1' ? 'selected' : '' }} data-title="{{ __('Dispense Success') }}">{{ __('Dispense Success') }}</option>
|
||||||
|
<option value="2" {{ (string)$filters['delivery_status']==='2' ? 'selected' : '' }} data-title="{{ __('Partial Dispense Success') }}">{{ __('Partial Dispense Success') }}</option>
|
||||||
|
<option value="0" {{ (string)$filters['delivery_status']==='0' ? 'selected' : '' }} data-title="{{ __('Dispense Failed') }}">{{ __('Dispense Failed') }}</option>
|
||||||
|
</x-searchable-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- 開始時間 --}}
|
{{-- 開始時間 --}}
|
||||||
<div class="relative group w-full lg:w-56 lg:flex-none"
|
<div class="relative group w-full lg:w-56 lg:flex-none"
|
||||||
x-data="{ fp: null }"
|
x-data="{ fp: null }"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user