ownerRef($request); $query = PosDevice::owned($owner)->with('location')->orderBy('name'); $this->scopeToLocation($request, $query); $devices = $query->paginate(25); $statsQuery = PosDevice::owned($owner); $this->scopeToLocation($request, $statsQuery); $heroStats = [ 'total' => (clone $statsQuery)->count(), 'online' => (clone $statsQuery) ->where('status', PosDevice::STATUS_ONLINE) ->where('last_online_at', '>=', now()->subMinutes(10)) ->count(), 'displays' => (clone $statsQuery) ->whereIn('type', ['customer_display', 'kitchen_display']) ->count(), ]; return view('pos.devices.index', [ 'devices' => $devices, 'deviceTypes' => config('pos.device_types', []), 'heroStats' => $heroStats, ]); } public function create(Request $request): View { return view('pos.devices.create', [ 'deviceTypes' => config('pos.device_types', []), 'hints' => config('pos.device_registration_hints', []), 'locations' => $this->locations($request), 'defaultLocationId' => $this->location($request)->id, ]); } public function store(Request $request): RedirectResponse { $types = array_keys(config('pos.device_types', [])); $owner = $this->ownerRef($request); $validated = $request->validate([ 'name' => ['required', 'string', 'max:255'], 'type' => ['required', 'string', Rule::in($types)], 'location_id' => ['nullable', 'integer'], ]); $locationId = $validated['location_id'] ?? null; if ($locationId) { $this->assertLocationOwned($request, (int) $locationId); } if (in_array($validated['type'], ['customer_display', 'kitchen_display'], true) && ! $locationId) { return back()->withInput()->with('error', 'Choose a branch for this display device.'); } $this->devices->register([ 'owner_ref' => $owner, 'name' => $validated['name'], 'type' => $validated['type'], 'location_id' => $locationId, ]); return redirect()->route('pos.devices.index')->with('success', 'Device registered.'); } public function edit(Request $request, PosDevice $device): View { $this->authorizeOwner($request, $device); return view('pos.devices.edit', [ 'device' => $device, 'deviceTypes' => config('pos.device_types', []), 'hints' => config('pos.device_registration_hints', []), 'locations' => $this->locations($request), 'openUrl' => $this->devices->openUrl($device), ]); } public function update(Request $request, PosDevice $device): RedirectResponse { $this->authorizeOwner($request, $device); $types = array_keys(config('pos.device_types', [])); $validated = $request->validate([ 'name' => ['required', 'string', 'max:255'], 'type' => ['required', 'string', Rule::in($types)], 'location_id' => ['nullable', 'integer'], 'status' => ['nullable', 'string', Rule::in([ PosDevice::STATUS_ONLINE, PosDevice::STATUS_OFFLINE, PosDevice::STATUS_MAINTENANCE, ])], ]); if (! empty($validated['location_id'])) { $this->assertLocationOwned($request, (int) $validated['location_id']); } $device->update([ 'name' => $validated['name'], 'type' => $validated['type'], 'location_id' => $validated['location_id'] ?: null, 'status' => $validated['status'] ?? $device->status, ]); return redirect()->route('pos.devices.index')->with('success', 'Device updated.'); } public function destroy(Request $request, PosDevice $device): RedirectResponse { $this->authorizeOwner($request, $device); $device->delete(); return redirect()->route('pos.devices.index')->with('success', 'Device removed.'); } public function regenerateToken(Request $request, PosDevice $device): RedirectResponse { $this->authorizeOwner($request, $device); $this->devices->regenerateToken($device); return back()->with('success', 'Device token regenerated. Re-open the device URL if needed.'); } /** @return \Illuminate\Support\Collection */ protected function locations(Request $request) { $query = PosLocation::owned($this->ownerRef($request))->orderBy('name'); $scope = $this->locationScope($request); if ($scope !== null) { $query->whereKey($scope); } return $query->get(); } protected function assertLocationOwned(Request $request, int $locationId): void { $exists = PosLocation::owned($this->ownerRef($request))->whereKey($locationId)->exists(); abort_unless($exists, 404); $scope = $this->locationScope($request); if ($scope !== null) { abort_unless($locationId === $scope, 404); } } }