ldc-boutique-cnc-sable/app/Http/Requests/Fo/Orders/PickTimeSlotRequest.php

95 lines
3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Requests\Fo\Orders;
use App\Actions\Orders\ApplyPickTimeSlotInput;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Domain\Exceptions\OrderTunnel\WeeklyLimitExceededException;
use Domain\Ports\Repositories\ShopperRepository;
use Domain\Services\BasketService;
use Domain\Services\OrderTunnelService;
use Illuminate\Foundation\Http\FormRequest;
use Infrastructure\Adapters\Services\AppCustomerAuthService;
class PickTimeSlotRequest extends FormRequest
{
public function __construct(
private readonly AppCustomerAuthService $authService,
private readonly BasketService $basketService,
private readonly ShopperRepository $shopperRepository,
private readonly OrderTunnelService $orderTunnelService
) {
}
public function toApplyPickTimeSlotInput(): ApplyPickTimeSlotInput
{
$customer = $this->authService->getCustomerAsMandatory();
return new ApplyPickTimeSlotInput(
shopperId: $customer->getId(),
timeslot: $this->getTimeslot(),
);
}
public function authorize(): bool
{
return $this->authService->check();
}
#[\Override]
protected function prepareForValidation(): void
{
$this->merge([
'basketTotal' => $this->basketService
->getBasket()
->totalTaxIncluded()
->getAmount(),
]);
}
public function getTimeslot(): CarbonInterface
{
return CarbonImmutable::createFromFormat(
'Y-m-d',
$this->string('timeslot')->value()
)?->startOfDay() ?? throw new \InvalidArgumentException('Invalid timeslot format');
}
/** @return array<string,mixed> */
public function rules(): array
{
return [
'timeslot' => ['required', 'string', 'date_format:Y-m-d'],
'basketTotal' => [
function (string $_, mixed $__, \Closure $fail) {
try {
$customer = $this->authService->getCustomerAsMandatory();
$shopper = $this->shopperRepository->getByIdOrFail($customer->getId());
$atDate = $this->getTimeslot();
$basket = $this->basketService->getBasket();
$this->orderTunnelService->assertBasketWeeklyAmountWithinLimitFor(
shopper: $shopper,
withBasket: $basket,
atDate: $atDate
);
} catch (WeeklyLimitExceededException) {
$fail(trans('You will reach the maximum weekly order limit with this basket.'));
}
},
],
];
}
/** @return array<string,string> */
#[\Override]
public function attributes(): array
{
return [
'timeslot' => trans('validation.custom.attributes.timeslot'),
];
}
}