From 49a76efdf8d4b5d6c5fff68e6c94b3e159b56fac Mon Sep 17 00:00:00 2001 From: Krzysztof Grzelak Date: Fri, 23 Jan 2026 06:43:21 +0100 Subject: [PATCH] add tax, product type and metadata fields to CartItem --- src/Payment/Domain/Enum/ItemType.php | 14 +++ src/Payment/Domain/Enum/ProductType.php | 13 ++ src/Payment/Domain/ValueObject/CartItem.php | 26 ++++ .../Unit/Domain/ValueObject/CartItemTest.php | 116 ++++++++++++++++++ 4 files changed, 169 insertions(+) create mode 100644 src/Payment/Domain/Enum/ItemType.php create mode 100644 src/Payment/Domain/Enum/ProductType.php diff --git a/src/Payment/Domain/Enum/ItemType.php b/src/Payment/Domain/Enum/ItemType.php new file mode 100644 index 0000000..70cca70 --- /dev/null +++ b/src/Payment/Domain/Enum/ItemType.php @@ -0,0 +1,14 @@ + $this->name, 'quantity' => $this->quantity, 'unitPrice' => $this->unitPrice, + 'type' => $this->type?->value, + 'productType' => $this->productType?->value, + 'sku' => $this->sku, + 'taxRate' => $this->taxRate, + 'taxAmount' => $this->taxAmount, + 'url' => $this->url, + 'imageUrl' => $this->imageUrl, + 'totalAmount' => $this->totalAmount, ], static fn ($value) => null !== $value); } } diff --git a/tests/Unit/Domain/ValueObject/CartItemTest.php b/tests/Unit/Domain/ValueObject/CartItemTest.php index 5c50922..d2f3350 100644 --- a/tests/Unit/Domain/ValueObject/CartItemTest.php +++ b/tests/Unit/Domain/ValueObject/CartItemTest.php @@ -4,6 +4,8 @@ namespace Paymentic\Tests\Unit\Domain\ValueObject; +use Paymentic\Sdk\Payment\Domain\Enum\ItemType; +use Paymentic\Sdk\Payment\Domain\Enum\ProductType; use Paymentic\Sdk\Payment\Domain\ValueObject\CartItem; use Paymentic\Sdk\Shared\Exception\InvalidValueException; use PHPUnit\Framework\Attributes\Test; @@ -18,11 +20,27 @@ public function createsWithAllFields(): void name: 'Product Name', quantity: 2, unitPrice: '49.99', + type: ItemType::PRODUCT, + productType: ProductType::PHYSICAL, + sku: 'SKU-123', + taxRate: '23', + taxAmount: '11.50', + url: 'https://example.com/product', + imageUrl: 'https://example.com/image.jpg', + totalAmount: '99.98', ); $this->assertSame('Product Name', $item->name); $this->assertSame(2, $item->quantity); $this->assertSame('49.99', $item->unitPrice); + $this->assertSame(ItemType::PRODUCT, $item->type); + $this->assertSame(ProductType::PHYSICAL, $item->productType); + $this->assertSame('SKU-123', $item->sku); + $this->assertSame('23', $item->taxRate); + $this->assertSame('11.50', $item->taxAmount); + $this->assertSame('https://example.com/product', $item->url); + $this->assertSame('https://example.com/image.jpg', $item->imageUrl); + $this->assertSame('99.98', $item->totalAmount); } #[Test] @@ -33,6 +51,14 @@ public function createsWithNoFields(): void $this->assertNull($item->name); $this->assertNull($item->quantity); $this->assertNull($item->unitPrice); + $this->assertNull($item->type); + $this->assertNull($item->productType); + $this->assertNull($item->sku); + $this->assertNull($item->taxRate); + $this->assertNull($item->taxAmount); + $this->assertNull($item->url); + $this->assertNull($item->imageUrl); + $this->assertNull($item->totalAmount); } #[Test] @@ -42,6 +68,14 @@ public function convertsToArrayWithAllFields(): void name: 'Test Product', quantity: 3, unitPrice: '19.99', + type: ItemType::SHIPPING, + productType: ProductType::DIGITAL, + sku: 'SKU-456', + taxRate: '8', + taxAmount: '1.60', + url: 'https://example.com/item', + imageUrl: 'https://example.com/item.png', + totalAmount: '21.59', ); $array = $item->toArray(); @@ -50,6 +84,14 @@ public function convertsToArrayWithAllFields(): void 'name' => 'Test Product', 'quantity' => 3, 'unitPrice' => '19.99', + 'type' => 'SHIPPING', + 'productType' => 'DIGITAL', + 'sku' => 'SKU-456', + 'taxRate' => '8', + 'taxAmount' => '1.60', + 'url' => 'https://example.com/item', + 'imageUrl' => 'https://example.com/item.png', + 'totalAmount' => '21.59', ], $array); } @@ -116,4 +158,78 @@ public function acceptsValidUnitPrice(): void $this->assertSame('0.00', $item->unitPrice); } + + #[Test] + public function throwsExceptionForInvalidTaxAmount(): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage('Amount must be a positive numeric string, got: "invalid"'); + + new CartItem(taxAmount: 'invalid'); + } + + #[Test] + public function throwsExceptionForNegativeTaxAmount(): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage('Amount must be a positive numeric string, got: "-5.00"'); + + new CartItem(taxAmount: '-5.00'); + } + + #[Test] + public function throwsExceptionForInvalidTotalAmount(): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage('Amount must be a positive numeric string, got: "abc"'); + + new CartItem(totalAmount: 'abc'); + } + + #[Test] + public function throwsExceptionForNegativeTotalAmount(): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage('Amount must be a positive numeric string, got: "-100.00"'); + + new CartItem(totalAmount: '-100.00'); + } + + #[Test] + public function acceptsAllItemTypes(): void + { + $types = [ItemType::PRODUCT, ItemType::SHIPPING, ItemType::DISCOUNT, ItemType::SURCHARGE, ItemType::GIFT_CARD]; + + foreach ($types as $type) { + $item = new CartItem(type: $type); + $this->assertSame($type, $item->type); + } + } + + #[Test] + public function acceptsAllProductTypes(): void + { + $types = [ProductType::PHYSICAL, ProductType::DIGITAL, ProductType::SERVICE, ProductType::VIRTUAL]; + + foreach ($types as $type) { + $item = new CartItem(productType: $type); + $this->assertSame($type, $item->productType); + } + } + + #[Test] + public function acceptsValidTaxAmount(): void + { + $item = new CartItem(taxAmount: '0.00'); + + $this->assertSame('0.00', $item->taxAmount); + } + + #[Test] + public function acceptsValidTotalAmount(): void + { + $item = new CartItem(totalAmount: '150.50'); + + $this->assertSame('150.50', $item->totalAmount); + } }