diff --git a/src/action/UsageInterval.php b/src/action/UsageInterval.php index 6b8693db..3251b8db 100644 --- a/src/action/UsageInterval.php +++ b/src/action/UsageInterval.php @@ -5,9 +5,10 @@ use DateInterval; use DateTimeImmutable; use InvalidArgumentException; +use JsonSerializable; /** @readonly */ -final class UsageInterval +final class UsageInterval implements JsonSerializable { /** @readonly */ private DateTimeImmutable $start; @@ -189,4 +190,9 @@ public function extend(self $other): self $newEnd, ); } + + public function jsonSerialize(): array + { + return array_filter(get_object_vars($this)); + } } diff --git a/src/bill/BillCreationDto.php b/src/bill/BillCreationDto.php index f93445f0..897ac8f2 100644 --- a/src/bill/BillCreationDto.php +++ b/src/bill/BillCreationDto.php @@ -36,4 +36,6 @@ class BillCreationDto public $charges; public $state; + + public $usageInterval; } diff --git a/src/bill/BillFactory.php b/src/bill/BillFactory.php index aa89afd3..0f1a7d38 100644 --- a/src/bill/BillFactory.php +++ b/src/bill/BillFactory.php @@ -10,6 +10,10 @@ namespace hiqdev\php\billing\bill; +use DateTimeImmutable; +use hiqdev\billing\hiapi\action\UsageIntervalHydrator; +use hiqdev\php\billing\action\UsageInterval; + /** * Default bill factory. * @@ -23,7 +27,7 @@ class BillFactory implements BillFactoryInterface */ public function create(BillCreationDto $dto) { - return new Bill( + $bill = new Bill( $dto->id, $dto->type, $dto->time, @@ -35,5 +39,21 @@ public function create(BillCreationDto $dto) $dto->charges ?: [], $dto->state ); + if (!empty($dto->usageInterval)) { + if ($dto->usageInterval instanceof UsageInterval) { + $interval = $dto->usageInterval; + } else { + $month = $dto->usageInterval['month']['date']; + $start = $dto->usageInterval['start']['date']; + $end = $dto->usageInterval['end']['date'];; + $interval = UsageInterval::withinMonth( + new DateTimeImmutable($month), + new DateTimeImmutable($start), + new DateTimeImmutable($end) + ); + } + $bill->setUsageInterval($interval); + } + return $bill; } } diff --git a/src/tools/Merger.php b/src/tools/Merger.php index ab61b843..693d3c9a 100644 --- a/src/tools/Merger.php +++ b/src/tools/Merger.php @@ -46,7 +46,7 @@ public function mergeBill(BillInterface $first, BillInterface $other): BillInter { $charges = $this->mergeCharges(array_merge($first->getCharges(), $other->getCharges())); - return new Bill( + $bill = new Bill( $this->mergeId($first, $other), $first->getType(), $first->getTime(), @@ -57,6 +57,8 @@ public function mergeBill(BillInterface $first, BillInterface $other): BillInter $first->getPlan(), $charges ); + $bill->setUsageInterval($first->getUsageInterval()); + return $bill; } /** diff --git a/tests/behat/bootstrap/BillingContext.php b/tests/behat/bootstrap/BillingContext.php index a94600d3..1e335e56 100644 --- a/tests/behat/bootstrap/BillingContext.php +++ b/tests/behat/bootstrap/BillingContext.php @@ -300,6 +300,36 @@ public function billWithTime($type, $sum, $currency, $quantity, $unit, $target, } } + /** + * @Given /bill interval +for (\S+) is +(\S+) (\S+) per (\S+) (\S+) for target (.+?) at (\S+) between (\S+) and (\S+)?$/ + */ + public function billInterval($type, $sum, $currency, $quantity, $unit, $target, $time, $since, $till) + { + $this->builder->flushEntitiesCacheByType('bill'); + + $quantity = $this->prepareQuantity($quantity); + $sum = $this->prepareSum($sum, $quantity); + $time = $this->prepareTime($time); + $bill = $this->findBill([ + 'type' => $type, + 'target' => $target, + 'sum' => "$sum $currency", + 'quantity' => "$quantity $unit", + 'time' => $time, + ]); + Assert::assertSame($type, $bill->getType()->getName(), "Bill type mismatch: expected $type, got {$bill->getType()->getName()}"); + Assert::assertSame($target, $bill->getTarget()->getFullName(), "Bill target mismatch: expected $target, got {$bill->getTarget()->getFullName()}"); + Assert::assertEquals(bcmul($sum, 100), $bill->getSum()->getAmount(), "Bill sum mismatch: expected $sum, got {$bill->getSum()->getAmount()}"); + Assert::assertSame($currency, $bill->getSum()->getCurrency()->getCode(), "Bill currency mismatch: expected $currency, got {$bill->getSum()->getCurrency()->getCode()}"); + Assert::assertEquals((float)$quantity, (float)$bill->getQuantity()->getQuantity(), "Bill quantity mismatch: expected $quantity, got {$bill->getQuantity()->getQuantity()}"); + Assert::assertEquals(strtolower($unit), strtolower($bill->getQuantity()->getUnit()->getName()), "Bill unit mismatch: expected $unit, got {$bill->getQuantity()->getUnit()->getName()}"); + Assert::assertEquals(new DateTimeImmutable($time), $bill->getTime(), "Bill time mismatch: expected $time, got {$bill->getTime()->format(DATE_ATOM)}"); + $billStart = $bill->getUsageInterval()->start(); + $billEnd = $bill->getUsageInterval()->end(); + Assert::assertEquals(new DateTimeImmutable($since), $billStart, "Bill since time mismatch: expected $since, got {$billStart->format(DATE_ATOM)}"); + Assert::assertEquals(new DateTimeImmutable($till), $billEnd, "Bill till time mismatch: expected $till, got {$billEnd->format(DATE_ATOM)}"); + } + public function findBill(array $params): BillInterface { $bills = $this->builder->findBills($params);