81 lines
2.4 KiB
PHP
81 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace App\Validator;
|
|
|
|
use App\Aggregate\AcceptOrderCommand;
|
|
use App\Contract\Order;
|
|
use App\Entity\Client;
|
|
use App\Service\ClientService;
|
|
use Symfony\Component\Validator\Constraint;
|
|
use Symfony\Component\Validator\ConstraintValidator;
|
|
use Symfony\Component\Validator\Exception\UnexpectedValueException;
|
|
|
|
class ValidOrderValidator extends ConstraintValidator
|
|
{
|
|
public function __construct(private readonly ClientService $clientService)
|
|
{
|
|
}
|
|
|
|
public function validate($value, Constraint $constraint)
|
|
{
|
|
if (!$value instanceof Order) {
|
|
throw new UnexpectedValueException($value, Order::class);
|
|
}
|
|
|
|
if (!$constraint instanceof ValidOrder) {
|
|
throw new UnexpectedValueException($constraint, ValidOrder::class);
|
|
}
|
|
|
|
$client = $this->getClient($value);
|
|
|
|
$this->checkClientBalance($client);
|
|
|
|
$this->checkMinimumProductCount($value, $constraint);
|
|
$this->checkMaximumWeight($value, $constraint);
|
|
}
|
|
|
|
private function checkMinimumProductCount(Order $value, ValidOrder $constraint): void
|
|
{
|
|
if (count($value->getProducts()) < $constraint->minProductCount) {
|
|
$this->context
|
|
->buildViolation('The number of products in order should be no less than {{ min }}')
|
|
->setParameter('{{ min }}', $constraint->minProductCount)
|
|
->atPath('products')
|
|
->addViolation();
|
|
}
|
|
}
|
|
|
|
private function checkMaximumWeight(Order $value, ValidOrder $constraint): void
|
|
{
|
|
if ($value->getTotalWeight() > $constraint->maxWeight) {
|
|
$this->context
|
|
->buildViolation('Total weight of products in order must not exceed {{ max }}kg')
|
|
->setParameter('{{ max }}', $constraint->maxWeight)
|
|
->atPath('products')
|
|
->addViolation();
|
|
}
|
|
}
|
|
|
|
private function getClient(Order $value)
|
|
{
|
|
$root = $this->context->getRoot();
|
|
|
|
if ($root instanceof AcceptOrderCommand) {
|
|
return $root->client;
|
|
}
|
|
|
|
return $this->clientService->getClient($value->getClientId());
|
|
}
|
|
|
|
private function checkClientBalance(Client $client): void
|
|
{
|
|
if ($client->getBalance() < 0) {
|
|
$this->context
|
|
->buildViolation('Total balance of the client is negative')
|
|
->atPath('clientId')
|
|
->addViolation();
|
|
}
|
|
}
|
|
|
|
}
|