From 6be1d5cde23cdcac0bd47efbc5108c0c6d5c7614 Mon Sep 17 00:00:00 2001 From: Bojan Zivanovic Date: Thu, 27 Apr 2017 13:32:42 -0400 Subject: [PATCH] Issue #2873394 by bojanz: Make taxes functional --- .../cart/tests/src/Kernel/CartManagerTest.php | 4 +- modules/order/src/Entity/Order.php | 8 +- .../tax/config/schema/commerce_tax.schema.yml | 2 +- .../tax/src/Event/CustomerProfileEvent.php | 10 +- .../Plugin/Commerce/TaxType/TaxTypeBase.php | 4 +- .../tests/src/Kernel/OrderIntegrationTest.php | 141 ++++++++++++++++++ 6 files changed, 157 insertions(+), 12 deletions(-) create mode 100644 modules/tax/tests/src/Kernel/OrderIntegrationTest.php diff --git a/modules/cart/tests/src/Kernel/CartManagerTest.php b/modules/cart/tests/src/Kernel/CartManagerTest.php index 94d104a4de..b530578e3c 100644 --- a/modules/cart/tests/src/Kernel/CartManagerTest.php +++ b/modules/cart/tests/src/Kernel/CartManagerTest.php @@ -117,7 +117,7 @@ public function testCartManager() { $order_item1 = $this->cartManager->addEntity($cart, $this->variation1); $order_item1 = $this->reloadEntity($order_item1); - $this->assertEquals([$order_item1], $cart->getItems()); + $this->assertNotEmpty($cart->hasItem($order_item1)); $this->assertEquals(1, $order_item1->getQuantity()); $this->assertEquals(new Price('1.00', 'USD'), $cart->getTotalPrice()); @@ -145,7 +145,7 @@ public function testCartManager() { } /** - * Tests that order items without purchaseable entity do not cause crashes. + * Tests that order items without purchasable entities do not cause crashes. */ public function testAddOrderItem() { $this->installCommerceCart(); diff --git a/modules/order/src/Entity/Order.php b/modules/order/src/Entity/Order.php index d991962e51..60504f117d 100644 --- a/modules/order/src/Entity/Order.php +++ b/modules/order/src/Entity/Order.php @@ -485,6 +485,13 @@ public function preSave(EntityStorageInterface $storage) { } } + // Ensure that $order_item->getOrder() works, for the order refresh + // process. The actual reference will be saved in postSave(). + foreach ($this->getItems() as $order_item) { + if ($order_item->order_id->isEmpty()) { + $order_item->order_id = $this; + } + } // Maintain the completed timestamp. $state = $this->getState()->value; $original_state = isset($this->original) ? $this->original->getState()->value : ''; @@ -493,7 +500,6 @@ public function preSave(EntityStorageInterface $storage) { $this->setCompletedTime(\Drupal::time()->getRequestTime()); } } - // Refresh draft orders on every save. if ($this->getState()->value == 'draft' && empty($this->getRefreshState())) { $this->setRefreshState(self::REFRESH_ON_SAVE); diff --git a/modules/tax/config/schema/commerce_tax.schema.yml b/modules/tax/config/schema/commerce_tax.schema.yml index d1ef9d08eb..8540cfc0e1 100644 --- a/modules/tax/config/schema/commerce_tax.schema.yml +++ b/modules/tax/config/schema/commerce_tax.schema.yml @@ -54,7 +54,7 @@ commerce_tax.commerce_tax_type.plugin.custom: type: label label: 'Label' amount: - type: float + type: string label: 'Amount' territories: type: sequence diff --git a/modules/tax/src/Event/CustomerProfileEvent.php b/modules/tax/src/Event/CustomerProfileEvent.php index f361d4409c..24e5ca1201 100644 --- a/modules/tax/src/Event/CustomerProfileEvent.php +++ b/modules/tax/src/Event/CustomerProfileEvent.php @@ -31,11 +31,11 @@ class CustomerProfileEvent extends Event { * Constructs a new CustomerProfileEvent. * * @param \Drupal\profile\Entity\ProfileInterface $customer_profile - * The customer profile. + * The initially selected customer profile. * @param \Drupal\commerce_order\Entity\OrderItemInterface $order_item - * The removed order item. + * The order item. */ - public function __construct(ProfileInterface $customer_profile, OrderItemInterface $order_item) { + public function __construct(ProfileInterface $customer_profile = NULL, OrderItemInterface $order_item) { $this->customerProfile = $customer_profile; $this->orderItem = $order_item; } @@ -43,8 +43,8 @@ public function __construct(ProfileInterface $customer_profile, OrderItemInterfa /** * Gets the customer profile. * - * @return \Drupal\profile\Entity\ProfileInterface - * The customer profile. + * @return \Drupal\profile\Entity\ProfileInterface|null + * The customer profile, or NULL if not yet known. */ public function getCustomerProfile() { return $this->customerProfile; diff --git a/modules/tax/src/Plugin/Commerce/TaxType/TaxTypeBase.php b/modules/tax/src/Plugin/Commerce/TaxType/TaxTypeBase.php index 4cee09714e..12e8b4307c 100644 --- a/modules/tax/src/Plugin/Commerce/TaxType/TaxTypeBase.php +++ b/modules/tax/src/Plugin/Commerce/TaxType/TaxTypeBase.php @@ -217,9 +217,6 @@ protected function getTaxableType(OrderItemInterface $order_item) { */ protected function resolveCustomerProfile(OrderItemInterface $order_item) { $order = $order_item->getOrder(); - if (!$order) { - return; - } $store = $order->getStore(); $prices_include_tax = $store->get('prices_include_tax')->value; $customer_profile = $order->getBillingProfile(); @@ -232,6 +229,7 @@ protected function resolveCustomerProfile(OrderItemInterface $order_item) { // better to show the store's default tax than nothing. $profile_storage = $this->entityTypeManager->getStorage('profile'); $customer_profile = $profile_storage->create([ + 'type' => 'customer', 'uid' => $order->getCustomerId(), 'address' => $store->getAddress(), ]); diff --git a/modules/tax/tests/src/Kernel/OrderIntegrationTest.php b/modules/tax/tests/src/Kernel/OrderIntegrationTest.php new file mode 100644 index 0000000000..dd4946e017 --- /dev/null +++ b/modules/tax/tests/src/Kernel/OrderIntegrationTest.php @@ -0,0 +1,141 @@ +installEntitySchema('profile'); + $this->installEntitySchema('commerce_order'); + $this->installEntitySchema('commerce_order_item'); + $this->installConfig(['commerce_order']); + $user = $this->createUser(['mail' => $this->randomString() . '@example.com']); + + $this->store->set('prices_include_tax', TRUE); + $this->store->save(); + + // The default store is US-WI, so imagine that the US has VAT. + TaxType::create([ + 'id' => 'us_vat', + 'label' => 'US VAT', + 'plugin' => 'custom', + 'configuration' => [ + 'display_inclusive' => TRUE, + 'rates' => [ + [ + 'id' => 'standard', + 'label' => 'Standard', + 'amount' => '0.2', + ], + ], + 'territories' => [ + ['country_code' => 'US', 'administrative_area' => 'WI'], + ['country_code' => 'US', 'administrative_area' => 'SC'], + ], + ], + ])->save(); + OrderItemType::create([ + 'id' => 'test', + 'label' => 'Test', + 'orderType' => 'default', + ])->save(); + $order = Order::create([ + 'type' => 'default', + 'store_id' => $this->store->id(), + 'state' => 'draft', + 'mail' => $user->getEmail(), + 'uid' => $user->id(), + 'ip_address' => '127.0.0.1', + 'order_number' => '6', + ]); + $order->save(); + $this->order = $this->reloadEntity($order); + } + + /** + * Tests that the store address is used as a default for new orders. + */ + public function testDefaultProfile() { + $order_item = OrderItem::create([ + 'type' => 'test', + 'quantity' => '1', + 'unit_price' => new Price('12.00', 'USD'), + ]); + $order_item->save(); + $this->order->addItem($order_item); + $this->order->save(); + $adjustments = $this->order->collectAdjustments(); + $adjustment = reset($adjustments); + $this->assertCount(1, $adjustments); + $this->assertEquals(new Price('2.00', 'USD'), $adjustment->getAmount()); + $this->assertEquals('us_vat|default|standard', $adjustment->getSourceId()); + } + + /** + * Tests the usage of default billing profile. + */ + public function testBillingProfile() { + $profile = Profile::create([ + 'type' => 'customer', + 'address' => [ + 'country_code' => 'US', + 'administrative_area' => 'SC', + ], + ]); + $profile->save(); + $order_item = OrderItem::create([ + 'type' => 'test', + 'quantity' => '1', + 'unit_price' => new Price('12.00', 'USD'), + ]); + $order_item->save(); + $this->order->addItem($order_item); + $this->order->setBillingProfile($profile); + $this->order->save(); + $adjustments = $this->order->collectAdjustments(); + $adjustment = reset($adjustments); + $this->assertCount(1, $adjustments); + $this->assertEquals(new Price('2.00', 'USD'), $adjustment->getAmount()); + $this->assertEquals('us_vat|default|standard', $adjustment->getSourceId()); + } + +}