80 lines
2.9 KiB
PHP
80 lines
2.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Domain\Models\ValueObjects\RequestedCoupon;
|
|
|
|
use Domain\Models\ValueObjects\Coupon\CouponValidity;
|
|
use Domain\Models\ValueObjects\Coupon\CouponValidityInformation;
|
|
use Domain\Models\ValueObjects\CouponName;
|
|
use Domain\Models\ValueObjects\GS1;
|
|
use Domain\Models\ValueObjects\IncoCode;
|
|
use Domain\Models\ValueObjects\MoneyAmount;
|
|
use Domain\Models\ValueObjects\Period;
|
|
use Domain\Models\ValueObjects\PrintRules;
|
|
use Domain\Models\ValueObjects\ProcessingCode;
|
|
use Domain\Models\ValueObjects\WarningThresholdQuantity;
|
|
use Shared\Enums\Country;
|
|
|
|
final readonly class RequestedCoupon
|
|
{
|
|
private const int DEFAULT_WARNING_THRESHOLD_QUANTITY = 100;
|
|
private const int MIN_FACE_VALUE_IN_CENTS = 1;
|
|
private const int MAX_FACE_VALUE_IN_CENTS = 300;
|
|
|
|
public WarningThresholdQuantity $warningThresholdQuantity;
|
|
|
|
/**
|
|
* @param array<CouponValidityInformation> $couponValidityInformation
|
|
* @param array<IncoCode> $products
|
|
*/
|
|
public function __construct(
|
|
public CouponName $name,
|
|
public RequestedCouponQuantity $quantity,
|
|
public Period $diffusion,
|
|
public MoneyAmount $moneyAmount,
|
|
public ProcessingCode $processingCode,
|
|
public CouponValidity $couponValidity,
|
|
public array $couponValidityInformation,
|
|
public array $products = [],
|
|
public ?PrintRules $printRules = null,
|
|
public ?GS1 $gs1 = null,
|
|
?WarningThresholdQuantity $warningThresholdQuantity = null,
|
|
) {
|
|
$money = $this->moneyAmount->value;
|
|
|
|
foreach ($this->couponValidityInformation as $validityInformation) {
|
|
if (!$validityInformation instanceof CouponValidityInformation) {
|
|
throw new \DomainException('Coupon validity information must be CouponValidityInformation instances.');
|
|
}
|
|
}
|
|
|
|
if ($money->value < self::MIN_FACE_VALUE_IN_CENTS || $money->value > self::MAX_FACE_VALUE_IN_CENTS) {
|
|
throw new \DomainException(sprintf(
|
|
'Coupon face value must be between 0.01€ and 3.00€, %s given.',
|
|
$money,
|
|
));
|
|
}
|
|
|
|
if (!$this->hasValidityInformationFor(Country::FRANCE)) {
|
|
throw new \DomainException('A coupon requires validity information for France.');
|
|
}
|
|
|
|
if ($this->gs1 instanceof GS1 && !$this->hasValidityInformationFor(Country::BENELUX)) {
|
|
throw new \DomainException('A GS1 coupon requires validity information for Benelux.');
|
|
}
|
|
|
|
$this->warningThresholdQuantity = $warningThresholdQuantity ?? new WarningThresholdQuantity(self::DEFAULT_WARNING_THRESHOLD_QUANTITY);
|
|
}
|
|
|
|
private function hasValidityInformationFor(Country $country): bool
|
|
{
|
|
foreach ($this->couponValidityInformation as $validityInformation) {
|
|
if ($validityInformation->forLocale === $country) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|