scopeToLocation($request, PosSale::owned($this->ownerRef($request))) ->with('lines') ->latest() ->paginate(25) ->withQueryString(); return view('pos.sales.index', compact('sales')); } public function show(Request $request, PosSale $sale): View { $this->authorizeOwner($request, $sale); $sale->load('lines', 'location'); $invoiceUrl = $sale->isPaid() ? $this->links->invoiceFromSale($sale) : null; return view('pos.sales.show', compact('sale', 'invoiceUrl')); } public function receipt(Request $request, PosSale $sale): View { $this->authorizeOwner($request, $sale); $sale->load('lines', 'location'); return view('pos.receipts.print', [ 'sale' => $sale, 'location' => $sale->location, 'autoprint' => $request->boolean('autoprint'), ]); } public function cancel(Request $request, PosSale $sale): RedirectResponse { $this->authorizeOwner($request, $sale); try { $this->sales->cancelSale($sale); } catch (RuntimeException $e) { return back()->with('error', $e->getMessage()); } return redirect()->route('pos.sales.show', $sale)->with('success', 'Sale cancelled.'); } public function emailReceipt(Request $request, PosSale $sale): RedirectResponse { $this->authorizeOwner($request, $sale); if (! $sale->isPaid()) { return back()->with('error', 'Only paid sales can be emailed as receipts.'); } $data = $request->validate([ 'email' => ['required', 'email', 'max:255'], ]); try { $result = $this->receiptEmail->send($sale, $data['email']); } catch (RuntimeException $e) { return back()->with('error', $e->getMessage()); } return back()->with('success', $result['message']); } public function destroy(Request $request, PosSale $sale): RedirectResponse { $this->authorizeOwner($request, $sale); try { $this->sales->deleteSale($sale); } catch (RuntimeException $e) { return back()->with('error', $e->getMessage()); } return redirect()->route('pos.sales.index')->with('success', 'Sale deleted.'); } public function callback(Request $request, PosSale $sale): RedirectResponse|View { $reference = trim((string) $request->query('reference', $sale->payment_reference ?? '')); if ($reference === '') { return $this->paymentReturn(route('pos.sales.show', $sale), error: 'Missing payment reference.'); } try { $sale = $this->sales->completePayCheckout($reference); } catch (RuntimeException $e) { return $this->paymentReturn(route('pos.sales.show', $sale), error: $e->getMessage()); } return $this->paymentReturn(route('pos.sales.show', $sale), success: 'Payment received.'); } private function paymentReturn(string $url, ?string $success = null, ?string $error = null): View { if ($success) { session()->flash('success', $success); } if ($error) { session()->flash('error', $error); } return view('pos.payment-return', [ 'redirect' => $url, ]); } }