orderBy('last_heartbeat_at', 'desc')->orderBy('id', 'desc')->get(); $selectedMachine = null; $history = RemoteCommand::where('command_type', '!=', 'reload_stock')->with(['machine', 'user'])->latest()->limit(50)->get(); if ($request->has('machine_id')) { $selectedMachine = Machine::with(['slots.product', 'commands' => function($query) { $query->where('command_type', '!=', 'reload_stock') ->latest() ->limit(10); }])->find($request->machine_id); } if ($request->ajax()) { return response()->json([ 'success' => true, 'machine' => $selectedMachine, 'commands' => $selectedMachine ? $selectedMachine->commands : [] ]); } return view('admin.remote.index', [ 'machines' => $machines, 'selectedMachine' => $selectedMachine, 'history' => $history, 'title' => __('Remote Command Center'), 'subtitle' => __('Execute maintenance and operational commands remotely') ]); } /** * 儲存遠端指令 */ public function storeCommand(Request $request) { $validated = $request->validate([ 'machine_id' => 'required|exists:machines,id', 'command_type' => 'required|string|in:reboot,reboot_card,checkout,lock,unlock,change,dispense', 'amount' => 'nullable|integer|min:0', 'slot_no' => 'nullable|string', 'note' => 'nullable|string|max:255', ]); $payload = []; if ($validated['command_type'] === 'change') { $payload['amount'] = $validated['amount']; } elseif ($validated['command_type'] === 'dispense') { $payload['slot_no'] = $validated['slot_no']; } // 指令去重:將同機台、同類型的 pending 指令標記為「已取代」 RemoteCommand::where('machine_id', $validated['machine_id']) ->where('command_type', $validated['command_type']) ->where('status', 'pending') ->update([ 'status' => 'superseded', 'note' => __('Superseded by new command'), 'executed_at' => now(), ]); RemoteCommand::create([ 'machine_id' => $validated['machine_id'], 'user_id' => auth()->id(), 'command_type' => $validated['command_type'], 'payload' => $payload, 'status' => 'pending', 'note' => $validated['note'] ?? null, ]); session()->flash('success', __('Command has been queued successfully.')); if ($request->expectsJson()) { return response()->json([ 'success' => true, 'message' => __('Command has been queued successfully.') ]); } return redirect()->back(); } /** * 機台庫存管理 (現有功能保留) */ public function stock(Request $request) { $machines = Machine::withCount([ 'slots as slots_count', 'slots as low_stock_count' => function ($query) { $query->where('stock', '<=', 5); }, 'slots as expiring_soon_count' => function ($query) { $query->whereNotNull('expiry_date') ->where('expiry_date', '<=', now()->addDays(7)) ->where('expiry_date', '>=', now()->startOfDay()); } ])->orderBy('last_heartbeat_at', 'desc')->orderBy('id', 'desc')->get(); $history = RemoteCommand::where('command_type', 'reload_stock')->with(['machine', 'user'])->latest()->limit(50)->get(); $selectedMachine = null; if ($request->has('machine_id')) { $selectedMachine = Machine::with(['slots.product', 'commands' => function($query) { $query->where('command_type', 'reload_stock') ->latest() ->limit(50); }])->find($request->machine_id); } return view('admin.remote.stock', [ 'machines' => $machines, 'selectedMachine' => $selectedMachine, 'history' => $history, 'title' => __('Stock & Expiry Management'), 'subtitle' => __('Real-time monitoring and adjustment of cargo lane inventory and expiration dates') ]); } }