diff --git a/src/price/AbstractPrice.php b/src/price/AbstractPrice.php index bba98577..0aefd2b4 100755 --- a/src/price/AbstractPrice.php +++ b/src/price/AbstractPrice.php @@ -53,7 +53,7 @@ abstract class AbstractPrice implements PriceInterface, ChargeModifier protected $plan; public function __construct( - $id, + $id, TypeInterface $type, TargetInterface $target, PlanInterface $plan = null @@ -137,10 +137,45 @@ public function calculateSum(QuantityInterface $quantity): ?Money public function jsonSerialize(): array { - $res = array_filter(get_object_vars($this)); - unset($res['plan']); + $data = [ + 'id' => $this->id, + 'class' => (new \ReflectionClass($this))->getShortName(), + 'type' => $this->getType()->getName(), + 'type_id' => $this->getType()->getId(), + 'object_id' => $this->getTarget()->getId(), + 'object' => [ + 'id' => $this->getTarget()->getId(), + 'name' => $this->getTarget()->getName(), + 'type' => $this->getTarget()->getType(), + ], + 'plan_id' => $this->getPlan()?->getId(), + ]; + + if ($this instanceof PriceWithSubpriceInterface) { + $data['subprice'] = $this->getSubprices()->values(); + } + + if ($this instanceof PriceWithRateInterface) { + $data['rate'] = $this->getRate(); + } + + if ($this instanceof PriceWithUnitInterface) { + $data['unit'] = $this->getUnit()->getName(); + } + + if ($this instanceof PriceWithCurrencyInterface) { + $data['currency'] = $this->getCurrency()->getCode(); + } + + if ($this instanceof PriceWithSumsInterface) { + $data['sums'] = $this->getSums()->values(); + } + + if ($this instanceof PriceWithQuantityInterface) { + $data['quantity'] = $this->getPrepaid()->getQuantity(); + } - return $res; + return $data; } /** diff --git a/src/price/EnumPrice.php b/src/price/EnumPrice.php index d7a5a5bc..a2eabb45 100644 --- a/src/price/EnumPrice.php +++ b/src/price/EnumPrice.php @@ -26,31 +26,22 @@ * * @author Andrii Vasyliev */ -class EnumPrice extends AbstractPrice +class EnumPrice extends AbstractPrice implements PriceWithSumsInterface, PriceWithCurrencyInterface, PriceWithUnitInterface { - /** - * @var UnitInterface - */ - protected $unit; + protected UnitInterface $unit; - /** - * @var Currency - */ - protected $currency; + protected Currency $currency; - /** - * @var array quantity => total sum for the quantity - */ - protected $sums; + protected Sums $sums; public function __construct( - $id, + $id, TypeInterface $type, TargetInterface $target, ?PlanInterface $plan, UnitInterface $unit, Currency $currency, - array $sums + Sums $sums, ) { parent::__construct($id, $type, $target, $plan); $this->unit = $unit; @@ -58,17 +49,17 @@ public function __construct( $this->sums = $sums; } - public function getUnit() + public function getUnit(): UnitInterface { return $this->unit; } - public function getCurrency() + public function getCurrency(): Currency { return $this->currency; } - public function getSums() + public function getSums(): Sums { return $this->sums; } @@ -80,7 +71,7 @@ public function calculateSum(QuantityInterface $quantity): ?Money { $usage = $this->calculateUsage($quantity)->getQuantity(); - foreach ($this->sums as $value => $price) { + foreach ($this->sums->values() as $value => $price) { if ((string) $value === (string) $usage) { return new Money($price, $this->currency); } diff --git a/src/price/HasMoney.php b/src/price/HasMoney.php new file mode 100644 index 00000000..e11b1ca1 --- /dev/null +++ b/src/price/HasMoney.php @@ -0,0 +1,21 @@ +price; + } + + public function getCurrency(): Currency + { + return $this->price->getCurrency(); + } +} diff --git a/src/price/HasQuantity.php b/src/price/HasQuantity.php new file mode 100644 index 00000000..f407eb42 --- /dev/null +++ b/src/price/HasQuantity.php @@ -0,0 +1,25 @@ +prepaid; + } + + public function getUnit(): UnitInterface + { + return $this->prepaid->getUnit(); + } +} diff --git a/src/price/PriceFactory.php b/src/price/PriceFactory.php index a771f685..02e794d8 100644 --- a/src/price/PriceFactory.php +++ b/src/price/PriceFactory.php @@ -77,9 +77,9 @@ public function findMethodForClass($class) throw new FailedCreatePriceException("unknown class: $class"); } - public function createEnumPrice(PriceCreationDto $dto) + public function createEnumPrice(PriceCreationDto $dto): EnumPrice { - return new EnumPrice($dto->id, $dto->type, $dto->target, $dto->plan, $dto->unit, $dto->currency, $dto->sums); + return new EnumPrice($dto->id, $dto->type, $dto->target, $dto->plan, $dto->unit, $dto->currency, new Sums($dto->sums)); } public function createRatePrice(PriceCreationDto $dto) diff --git a/src/price/PriceInvalidArgumentException.php b/src/price/PriceInvalidArgumentException.php new file mode 100644 index 00000000..309e5725 --- /dev/null +++ b/src/price/PriceInvalidArgumentException.php @@ -0,0 +1,9 @@ +thresholds = $thresholds; $this->price = $price; @@ -42,16 +44,6 @@ public function getThresholds(): ProgressivePriceThresholdList return $this->thresholds; } - public function getPrepaid(): QuantityInterface - { - return $this->prepaid; - } - - public function getPrice(): Money - { - return $this->price; - } - /** * @inheritDoc */ diff --git a/src/price/RatePrice.php b/src/price/RatePrice.php index 77a14e9e..71fff5f2 100644 --- a/src/price/RatePrice.php +++ b/src/price/RatePrice.php @@ -24,10 +24,9 @@ * * @author Andrii Vasyliev */ -class RatePrice extends AbstractPrice +class RatePrice extends AbstractPrice implements PriceWithRateInterface { - /** @var float */ - protected $rate; + protected float $rate; public function __construct( $id, diff --git a/src/price/SinglePrice.php b/src/price/SinglePrice.php index 6010eb7f..320f6ab2 100644 --- a/src/price/SinglePrice.php +++ b/src/price/SinglePrice.php @@ -27,21 +27,13 @@ * * @author Andrii Vasyliev */ -class SinglePrice extends AbstractPrice +class SinglePrice extends AbstractPrice implements PriceWithQuantityInterface, PriceWithMoneyInterface { - /** - * @var QuantityInterface prepaid quantity also implies Unit - * XXX cannot be null cause Unit is required - */ - protected $prepaid; - - /** - * @var Money - */ - protected $price; + use HasMoney; + use HasQuantity; public function __construct( - $id, + $id, TypeInterface $type, TargetInterface $target, PlanInterface $plan = null, @@ -53,16 +45,6 @@ public function __construct( $this->price = $price; } - public function getPrepaid() - { - return $this->prepaid; - } - - public function getPrice() - { - return $this->price; - } - /** * {@inheritdoc} */ diff --git a/src/price/Sums.php b/src/price/Sums.php new file mode 100644 index 00000000..2d10117a --- /dev/null +++ b/src/price/Sums.php @@ -0,0 +1,44 @@ + total sum for the quantity + */ + public function __construct(private ?array $values) + { + if (!empty($this->values)) { + $this->validate($this->values); + } + } + + private function validate(array $sums): void + { + if ($sums) { + foreach ($sums as $value) { + if (!is_numeric($value)) { + throw new PriceInvalidArgumentException('Invalid value for sums parameter'); + } + } + } + } + + public function values(): ?array + { + return $this->values; + } + + public function getMinSum(): int|string + { + return min($this->values); + } + + public function jsonSerialize(): ?array + { + return [ + 'values' => $this->values, + ]; + } +} diff --git a/src/price/SumsHydrator.php b/src/price/SumsHydrator.php new file mode 100644 index 00000000..6ce98fe9 --- /dev/null +++ b/src/price/SumsHydrator.php @@ -0,0 +1,27 @@ + $object->values(), + ]; + } +} diff --git a/tests/support/plan/CertificatePlan.php b/tests/support/plan/CertificatePlan.php index aa3b8513..278af07f 100644 --- a/tests/support/plan/CertificatePlan.php +++ b/tests/support/plan/CertificatePlan.php @@ -14,6 +14,7 @@ use hiqdev\php\billing\customer\Customer; use hiqdev\php\billing\plan\Plan; use hiqdev\php\billing\price\EnumPrice; +use hiqdev\php\billing\price\Sums; use hiqdev\php\billing\target\Target; use hiqdev\php\billing\type\Type; use hiqdev\php\units\Unit; @@ -110,9 +111,9 @@ public function getRawPrice($action) return $this->getRawPrices($action->getType(), $action->getTarget())[$years]; } - public function getRawPrices($type, $target) + public function getRawPrices($type, $target): Sums { - return $this->rawPrices[$this->getRawPriceKey($type, $target)]; + return new Sums($this->rawPrices[$this->getRawPriceKey($type, $target)]); } /** diff --git a/tests/unit/price/PriceFactoryTest.php b/tests/unit/price/PriceFactoryTest.php index 99bfdf10..b89a6bc0 100644 --- a/tests/unit/price/PriceFactoryTest.php +++ b/tests/unit/price/PriceFactoryTest.php @@ -57,7 +57,7 @@ public function testEnumPrice() $this->assertSame($this->enum, $price->getType()); $this->assertSame($this->target, $price->getTarget()); $this->assertSame($this->unit, $price->getUnit()); - $this->assertSame($this->sums, $price->getSums()); + $this->assertSame($this->sums, $price->getSums()->values()); $this->assertSame($this->price->getCurrency(), $price->getCurrency()); }