Files
ladill-pos/app/Http/Controllers/Pos/SaleController.php
T
isaaccladandCursor 9d7dac6c24
Deploy Ladill POS / deploy (push) Successful in 1m58s
Add multi-branch POS with team roles and branch-scoped cashiers.
Pro and Business users can manage branches, invite cashiers with branch assignment, and switch registers; sales and register flows respect acting location.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-08 06:05:30 +00:00

104 lines
3.0 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 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,
) {}
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 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
{
$reference = trim((string) $request->query('reference', $sale->payment_reference ?? ''));
if ($reference === '') {
return redirect()->route('pos.sales.show', $sale)->with('error', 'Missing payment reference.');
}
try {
$sale = $this->sales->completePayCheckout($reference);
} catch (RuntimeException $e) {
return redirect()->route('pos.sales.show', $sale)->with('error', $e->getMessage());
}
return redirect()
->route('pos.sales.show', $sale)
->with('success', 'Payment received.');
}
}