Shop, menu, and booking storefronts with OIDC SSO, Pay checkout, and merchant.ladill.com deployment workflow. Co-authored-by: Cursor <cursoragent@cursor.com>
101 lines
3.7 KiB
PHP
101 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Merchant;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\QrBooking;
|
|
use App\Models\QrCode;
|
|
use App\Models\QrSaleOrder;
|
|
use App\Services\Merchant\MerchantSaleService;
|
|
use App\Support\Qr\QrTypeCatalog;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Validation\Rule;
|
|
use Illuminate\View\View;
|
|
|
|
class OrdersController extends Controller
|
|
{
|
|
public function __construct(private MerchantSaleService $sales) {}
|
|
|
|
public function index(Request $request): View
|
|
{
|
|
$account = ladill_account();
|
|
$search = trim((string) $request->query('q', ''));
|
|
|
|
$qrIds = $account->qrCodes()
|
|
->whereIn('type', QrTypeCatalog::storefrontTypes())
|
|
->pluck('id');
|
|
|
|
$orders = QrSaleOrder::query()
|
|
->whereIn('qr_code_id', $qrIds)
|
|
->when($search !== '', function ($query) use ($search) {
|
|
$like = '%'.$search.'%';
|
|
$query->where(function ($inner) use ($like) {
|
|
$inner->where('customer_name', 'like', $like)
|
|
->orWhere('customer_email', 'like', $like)
|
|
->orWhere('payment_reference', 'like', $like)
|
|
->orWhereHas('qrCode', fn ($qr) => $qr->where('label', 'like', $like));
|
|
});
|
|
})
|
|
->with('qrCode')
|
|
->latest('created_at')
|
|
->paginate(15, ['*'], 'orders_page')
|
|
->withQueryString();
|
|
|
|
$bookings = QrBooking::query()
|
|
->whereIn('qr_code_id', $qrIds)
|
|
->whereIn('status', [QrBooking::STATUS_CONFIRMED, QrBooking::STATUS_PENDING])
|
|
->when($search !== '', function ($query) use ($search) {
|
|
$like = '%'.$search.'%';
|
|
$query->where(function ($inner) use ($like) {
|
|
$inner->where('customer_name', 'like', $like)
|
|
->orWhere('customer_email', 'like', $like)
|
|
->orWhere('service_name', 'like', $like)
|
|
->orWhereHas('qrCode', fn ($qr) => $qr->where('label', 'like', $like));
|
|
});
|
|
})
|
|
->with('qrCode')
|
|
->latest('starts_at')
|
|
->paginate(15, ['*'], 'bookings_page')
|
|
->withQueryString();
|
|
|
|
return view('merchant.orders', [
|
|
'orders' => $orders,
|
|
'bookings' => $bookings,
|
|
'search' => $search,
|
|
]);
|
|
}
|
|
|
|
public function updateStatus(Request $request, QrSaleOrder $order): RedirectResponse
|
|
{
|
|
abort_if($order->user_id !== ladill_account()->id, 403);
|
|
abort_if($order->status !== QrSaleOrder::STATUS_PAID, 422, 'Only paid orders can be updated.');
|
|
|
|
$validated = $request->validate([
|
|
'fulfillment_status' => ['required', Rule::in(array_keys(QrSaleOrder::FULFILLMENT_STATUSES))],
|
|
]);
|
|
|
|
$order->update(['fulfillment_status' => $validated['fulfillment_status']]);
|
|
$order->load('qrCode');
|
|
$this->sales->notifyStatusUpdated($order);
|
|
|
|
return back()->with('success', 'Order status updated.');
|
|
}
|
|
|
|
public function updateBookingStatus(Request $request, QrBooking $booking): RedirectResponse
|
|
{
|
|
abort_if($booking->user_id !== ladill_account()->id, 403);
|
|
abort_if($booking->status !== QrBooking::STATUS_CONFIRMED, 422);
|
|
|
|
$validated = $request->validate([
|
|
'fulfillment_status' => ['required', Rule::in(array_keys(QrBooking::FULFILLMENT_STATUSES))],
|
|
]);
|
|
|
|
$booking->update(['fulfillment_status' => $validated['fulfillment_status']]);
|
|
$booking->load('qrCode');
|
|
$this->sales->notifyBookingStatusUpdated($booking);
|
|
|
|
return back()->with('success', 'Booking status updated.');
|
|
}
|
|
}
|