176 lines
5.2 KiB
PHP
176 lines
5.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Fo;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Fo\Orders\PickTimeSlotRequest;
|
|
use App\Http\Requests\Fo\Orders\ValidateSummaryRequest;
|
|
use App\Models\Order;
|
|
use App\Services\MapUrlService;
|
|
use Domain\Enums\OrderTunnelStep;
|
|
use Domain\Exceptions\OrderTunnel\OrderLimitExceededException;
|
|
use Domain\Exceptions\OrderTunnel\WeeklyLimitExceededException;
|
|
use Domain\Ports\Repositories\ShopRepository;
|
|
use Domain\Services\BasketService;
|
|
use Domain\Services\OrderTunnelService;
|
|
use Illuminate\Contracts\View\View;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Infrastructure\Adapters\Services\AppCustomerAuthService;
|
|
|
|
class TunnelController extends Controller
|
|
{
|
|
public function __construct(
|
|
private readonly AppCustomerAuthService $authService,
|
|
private readonly BasketService $basketService,
|
|
private readonly OrderTunnelService $orderTunnelService,
|
|
private readonly MapUrlService $mapUrlService,
|
|
private readonly ShopRepository $shopRepository,
|
|
) {
|
|
}
|
|
|
|
// * -- STEP 1 -- *
|
|
|
|
public function basketSummary(BasketService $basketService): View
|
|
{
|
|
$this->authorize('canReviewBasketSummary', OrderTunnelStep::class);
|
|
|
|
$step = OrderTunnelStep::REVIEW;
|
|
$basket = $basketService->getBasket();
|
|
|
|
return view('fo.tunnel.basket-summary', compact(
|
|
'step',
|
|
'basket'
|
|
));
|
|
}
|
|
|
|
public function basketSummarySubmit(ValidateSummaryRequest $request): RedirectResponse
|
|
{
|
|
$this->authorize('canReviewBasketSummary', OrderTunnelStep::class);
|
|
|
|
$customer = $this->authService->getCustomerAsMandatory();
|
|
$basket = $this->basketService->getBasket();
|
|
|
|
$this->orderTunnelService->initializeFromBasket(
|
|
$basket,
|
|
$customer->getId()
|
|
);
|
|
|
|
return to_route('fo.sales.pick-time-slot');
|
|
}
|
|
|
|
// * -- STEP 2 -- *
|
|
|
|
public function pickTimeSlot(): View
|
|
{
|
|
$this->authorize('canPickTimeSlot', OrderTunnelStep::class);
|
|
|
|
$customer = $this->authService->getCustomerAsMandatory();
|
|
$shop = $this->orderTunnelService->getShopForCustomer($customer->getId());
|
|
$timeSlots = $this->orderTunnelService->getAvailableTimeSlots($shop);
|
|
$step = OrderTunnelStep::BOOKING;
|
|
|
|
$mapUrl = $this->mapUrlService->generateUrl($shop);
|
|
|
|
return view('fo.tunnel.pick-time-slot', compact(
|
|
'step',
|
|
'shop',
|
|
'mapUrl',
|
|
'timeSlots'
|
|
));
|
|
}
|
|
|
|
public function pickTimeSlotSubmit(PickTimeSlotRequest $request): RedirectResponse
|
|
{
|
|
$this->authorize('canPickTimeSlot', OrderTunnelStep::class);
|
|
|
|
$customer = $this->authService->getCustomerAsMandatory();
|
|
$builder = $this->orderTunnelService->getBuilderFromBasketOrFail();
|
|
|
|
$shop = $this->orderTunnelService->getShopForCustomer($customer->getId());
|
|
$timeSlots = $this->orderTunnelService->getAvailableTimeSlots($shop);
|
|
|
|
$matchedSlot = $this->orderTunnelService->applyTimeSlot(
|
|
$builder,
|
|
$shop,
|
|
$request->getTimeslot(),
|
|
$timeSlots
|
|
);
|
|
|
|
if ($matchedSlot === null) {
|
|
return back()->withErrors([
|
|
'timeslot' => trans('Invalid or unavailable time slot'),
|
|
])->withInput();
|
|
}
|
|
|
|
return to_route('fo.sales.confirmation');
|
|
}
|
|
|
|
// * -- STEP 3 -- *
|
|
|
|
public function confirmation(): View
|
|
{
|
|
$this->authorize('canFinalizeOrder', OrderTunnelStep::class);
|
|
|
|
$step = OrderTunnelStep::CONFIRMATION;
|
|
$builder = $this->orderTunnelService->getBuilderCompletedOrFail();
|
|
$basket = $builder->getBasket();
|
|
|
|
$shop = $this->shopRepository->find($builder->getShopId());
|
|
|
|
if (! $shop) {
|
|
abort(404, 'Shop not found');
|
|
}
|
|
|
|
return view('fo.tunnel.confirmation', compact(
|
|
'step',
|
|
'basket',
|
|
'builder',
|
|
'shop'
|
|
));
|
|
}
|
|
|
|
public function confirmationSubmit(Request $request): RedirectResponse
|
|
{
|
|
$this->authorize('canFinalizeOrder', OrderTunnelStep::class);
|
|
|
|
$request->validate([
|
|
'ok_cgv' => ['accepted'],
|
|
]);
|
|
|
|
$builder = $this->orderTunnelService->getBuilderCompletedOrFail();
|
|
|
|
try {
|
|
$order = $this->orderTunnelService->finalizeOrder($builder);
|
|
} catch (WeeklyLimitExceededException | OrderLimitExceededException $e) {
|
|
return back()->with('message', $e->getMessage());
|
|
}
|
|
|
|
return to_route('fo.sales.confirmation.show-confirmed', $order->reference->value);
|
|
}
|
|
|
|
// * -- CONFIRMATION -- *
|
|
|
|
public function confirmed(Order $order): View
|
|
{
|
|
$this->authorize('viewOwn', $order);
|
|
|
|
$step = OrderTunnelStep::CONFIRMATION;
|
|
$shop = $order->shop;
|
|
|
|
if (! $shop) {
|
|
throw new \UnexpectedValueException('Shop not found for order ' . $order->getId());
|
|
}
|
|
|
|
$mapUrl = $this->mapUrlService->generateUrl($shop);
|
|
|
|
return view('fo.tunnel.confirmed', compact(
|
|
'step',
|
|
'order',
|
|
'shop',
|
|
'mapUrl'
|
|
));
|
|
}
|
|
}
|