95 lines
3 KiB
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'),
|
|
];
|
|
}
|
|
}
|