ownerRef($request)) ->with('category') ->orderBy('name') ->paginate(30) ->withQueryString(); return view('pos.products.index', compact('products')); } public function create(Request $request): View { return view('pos.products.create', [ 'product' => new PosProduct([ 'currency' => config('pos.default_currency', 'GHS'), 'is_active' => true, ]), 'selectedGroups' => [], ...$this->formOptions($request), ]); } public function store(Request $request): RedirectResponse { $product = PosProduct::create([ ...$this->validated($request), 'owner_ref' => $this->ownerRef($request), ]); $product->modifierGroups()->sync($this->groupIds($request)); return redirect()->route('pos.products.index')->with('success', 'Product added.'); } public function edit(Request $request, PosProduct $product): View { $this->authorizeOwner($request, $product); return view('pos.products.edit', [ 'product' => $product, 'selectedGroups' => $product->modifierGroups()->pluck('pos_modifier_groups.id')->all(), ...$this->formOptions($request), ]); } public function update(Request $request, PosProduct $product): RedirectResponse { $this->authorizeOwner($request, $product); $product->update($this->validated($request)); $product->modifierGroups()->sync($this->groupIds($request)); return redirect()->route('pos.products.index')->with('success', 'Product updated.'); } public function destroy(Request $request, PosProduct $product): RedirectResponse { $this->authorizeOwner($request, $product); $product->delete(); return redirect()->route('pos.products.index')->with('success', 'Product removed.'); } /** @return array */ private function formOptions(Request $request): array { $owner = $this->ownerRef($request); return [ 'restaurant' => PosLocation::owned($owner)->where('service_style', PosLocation::STYLE_RESTAURANT)->exists(), 'categories' => PosCategory::owned($owner)->orderBy('name')->get(), 'stations' => PosStation::owned($owner)->orderBy('name')->get(), 'modifierGroups' => PosModifierGroup::owned($owner)->orderBy('name')->get(), ]; } /** @return list */ private function groupIds(Request $request): array { $owner = $this->ownerRef($request); $ids = array_map('intval', (array) $request->input('modifier_group_ids', [])); return PosModifierGroup::owned($owner)->whereIn('id', $ids)->pluck('id')->all(); } /** @return array */ private function validated(Request $request): array { $owner = $this->ownerRef($request); $data = $request->validate([ 'name' => ['required', 'string', 'max:200'], 'sku' => ['nullable', 'string', 'max:80'], 'price' => ['required', 'numeric', 'min:0.01'], 'currency' => ['nullable', 'string', 'size:3'], 'is_active' => ['sometimes', 'boolean'], 'category_id' => ['nullable', 'integer'], 'station_id' => ['nullable', 'integer'], 'course' => ['nullable', 'in:'.implode(',', array_keys(PosSaleLine::COURSES))], ]); $categoryId = ($data['category_id'] ?? null) && PosCategory::owned($owner)->whereKey($data['category_id'])->exists() ? (int) $data['category_id'] : null; $stationId = ($data['station_id'] ?? null) && PosStation::owned($owner)->whereKey($data['station_id'])->exists() ? (int) $data['station_id'] : null; return [ 'name' => $data['name'], 'sku' => $data['sku'] ?? null, 'price_minor' => (int) round(((float) $data['price']) * 100), 'currency' => strtoupper($data['currency'] ?? config('pos.default_currency', 'GHS')), 'is_active' => $request->boolean('is_active', true), 'category_id' => $categoryId, 'station_id' => $stationId, 'course' => $data['course'] ?? null, ]; } }