Deploy Ladill POS / deploy (push) Successful in 31s
Send real receipt emails from the customer display and sale page, store branch promo content for the idle screen, and fold selected tips into totals.
139 lines
4.1 KiB
PHP
139 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Pos;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Controllers\Pos\Concerns\ScopesToAccount;
|
|
use App\Models\PosSale;
|
|
use App\Services\CrossApp\CrossAppLinkService;
|
|
use App\Services\Pos\PosSaleService;
|
|
use App\Services\Pos\ReceiptEmailService;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\View\View;
|
|
use RuntimeException;
|
|
|
|
class SaleController extends Controller
|
|
{
|
|
use ScopesToAccount;
|
|
|
|
public function __construct(
|
|
private PosSaleService $sales,
|
|
private CrossAppLinkService $links,
|
|
private ReceiptEmailService $receiptEmail,
|
|
) {}
|
|
|
|
public function index(Request $request): View
|
|
{
|
|
$sales = $this->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,
|
|
]);
|
|
}
|
|
}
|