From af3d767d098d175349815454281a6c1be3f9af09 Mon Sep 17 00:00:00 2001 From: Harings Rob Date: Tue, 21 Mar 2017 16:02:37 +0100 Subject: [PATCH 01/25] 2862339: Commit --- modules/payment/src/Event/PaymentEvent.php | 42 ++++++++++++ modules/payment/src/Event/PaymentEvents.php | 72 +++++++++++++++++++++ modules/payment/src/PaymentStorage.php | 9 ++- 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 modules/payment/src/Event/PaymentEvent.php create mode 100644 modules/payment/src/Event/PaymentEvents.php diff --git a/modules/payment/src/Event/PaymentEvent.php b/modules/payment/src/Event/PaymentEvent.php new file mode 100644 index 0000000000..36e5c90cc6 --- /dev/null +++ b/modules/payment/src/Event/PaymentEvent.php @@ -0,0 +1,42 @@ +payment = $payment; + } + + /** + * Gets the payment. + * + * @return \Drupal\commerce_payment\Entity\PaymentInterface + * Gets the payment. + */ + public function getOrder() { + return $this->payment; + } + +} diff --git a/modules/payment/src/Event/PaymentEvents.php b/modules/payment/src/Event/PaymentEvents.php new file mode 100644 index 0000000000..2a076b2bc3 --- /dev/null +++ b/modules/payment/src/Event/PaymentEvents.php @@ -0,0 +1,72 @@ +getPluginId(); } - return parent::doCreate($values); + $payment = parent::doCreate($values); + + // Notify other modules. + $event = new PaymentEvent($payment); + $this->eventDispatcher->dispatch('commerce_payment.commerce_payment.create', $event); + + return $payment; } } From a0554406d296773349edaecff0cfb56b30ff35cd Mon Sep 17 00:00:00 2001 From: Harings Rob Date: Tue, 21 Mar 2017 18:28:48 +0100 Subject: [PATCH 02/25] 2862339: Test --- .../payment_events_test.info.yml | 5 + .../payment_events_test.services.yml | 6 + .../src/EventSubscriber.php | 53 +++++++++ .../tests/src/Kernel/PaymentEventsTest.php | 107 ++++++++++++++++++ 4 files changed, 171 insertions(+) create mode 100644 modules/payment/tests/modules/payment_events_test/payment_events_test.info.yml create mode 100644 modules/payment/tests/modules/payment_events_test/payment_events_test.services.yml create mode 100644 modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php create mode 100644 modules/payment/tests/src/Kernel/PaymentEventsTest.php diff --git a/modules/payment/tests/modules/payment_events_test/payment_events_test.info.yml b/modules/payment/tests/modules/payment_events_test/payment_events_test.info.yml new file mode 100644 index 0000000000..95c6799f00 --- /dev/null +++ b/modules/payment/tests/modules/payment_events_test/payment_events_test.info.yml @@ -0,0 +1,5 @@ +name: 'Configuration events test' +type: module +package: Testing +version: VERSION +core: 8.x diff --git a/modules/payment/tests/modules/payment_events_test/payment_events_test.services.yml b/modules/payment/tests/modules/payment_events_test/payment_events_test.services.yml new file mode 100644 index 0000000000..a7df3aa96c --- /dev/null +++ b/modules/payment/tests/modules/payment_events_test/payment_events_test.services.yml @@ -0,0 +1,6 @@ +services: + payment_events_test.event_subscriber: + class: Drupal\payment_events_test\EventSubscriber + arguments: ['@state'] + tags: + - { name: event_subscriber } diff --git a/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php b/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php new file mode 100644 index 0000000000..32c5683bdf --- /dev/null +++ b/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php @@ -0,0 +1,53 @@ +state = $state; + } + + /** + * Reacts to payment event. + * + * @param \Drupal\commerce_payment\Event\PaymentEvent $event + * The payment event. + * @param $name + * The name of the event. + */ + public function paymentEvent(PaymentEvent $event, $name) { + $this->state->set('payment_events_test.event', [ + 'event_name' => $name, + ]); + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + $events[PaymentEvents::PAYMENT_LOAD][] = ['paymentEvent']; + $events[PaymentEvents::PAYMENT_CREATE][] = ['paymentEvent']; + return $events; + } + +} diff --git a/modules/payment/tests/src/Kernel/PaymentEventsTest.php b/modules/payment/tests/src/Kernel/PaymentEventsTest.php new file mode 100644 index 0000000000..468ea0f471 --- /dev/null +++ b/modules/payment/tests/src/Kernel/PaymentEventsTest.php @@ -0,0 +1,107 @@ +installEntitySchema('profile'); + $this->installEntitySchema('commerce_order'); + $this->installEntitySchema('commerce_order_item'); + $this->installEntitySchema('commerce_payment'); + $this->installEntitySchema('commerce_payment_method'); + $this->installConfig('commerce_order'); + $this->installConfig('commerce_payment'); + + // An order item type that doesn't need a purchasable entity, for simplicity. + OrderItemType::create([ + 'id' => 'test', + 'label' => 'Test', + 'orderType' => 'default', + ])->save(); + + $payment_gateway = PaymentGateway::create([ + 'id' => 'example', + 'label' => 'Example', + 'plugin' => 'example_onsite', + ]); + $payment_gateway->save(); + + $user = $this->createUser(); + + /** @var \Drupal\commerce_payment\Entity\PaymentMethodInterface $payment_method */ + $payment_method_active = PaymentMethod::create([ + 'type' => 'credit_card', + 'payment_gateway' => 'example', + // Thu, 16 Jan 2020. + 'expires' => '1579132800', + 'uid' => $user->id(), + ]); + $payment_method_active->save(); + } + + /** + * Tests the basic payment events. + */ + public function testPaymentEvents() { + // Create a dummy payment. + $payment = Payment::create([ + 'payment_gateway' => 'example', + 'payment_method' => 'credit_card', + 'remote_id' => '123456', + 'amount' => [ + 'number' => '39.99', + 'currency_code' => 'USD', + ], + 'state' => 'capture_completed', + 'test' => TRUE, + ]); + $payment->save(); + $payment = $this->reloadEntity($payment); + + // Check the create event. + $event_recorder = \Drupal::state()->get('payment_events_test.event', FALSE); + $this->assertEquals('commerce_payment.commerce_payment.create', $event_recorder['event_name']); + + // Reload the payment. + Payment::load($payment->id()); + + // Check the load event. + $event_recorder = \Drupal::state()->get('payment_events_test.event', FALSE); + $this->assertEquals('commerce_payment.commerce_payment.load', $event_recorder['event_name']); + } + +} From 350d1846a04980e57d140a188c08bdeacbc21187 Mon Sep 17 00:00:00 2001 From: Steve Oliver Date: Fri, 23 Sep 2016 13:35:53 -0700 Subject: [PATCH 03/25] Issue #2804227 Add total_paid field and Order::getBalance() and related methods. --- modules/order/src/Entity/Order.php | 50 +++++++++++++++++++++ modules/order/src/Entity/OrderInterface.php | 44 ++++++++++++++++++ modules/payment/src/Entity/Payment.php | 2 + 3 files changed, 96 insertions(+) diff --git a/modules/order/src/Entity/Order.php b/modules/order/src/Entity/Order.php index a9a1239fb4..573c9a0957 100644 --- a/modules/order/src/Entity/Order.php +++ b/modules/order/src/Entity/Order.php @@ -364,6 +364,49 @@ public function getTotalPrice() { } } + /** + * {@inheritdoc} + */ + public function addPayment(Price $amount) { + $this->setTotalPaid($this->getTotalPaid()->add($amount)); + return $this; + } + + /** + * {@inheritdoc} + */ + public function subtractPayment(Price $amount) { + $this->setTotalPaid($this->getTotalPaid()->subtract($amount)); + return $this; + } + + /** + * {@inheritdoc} + */ + public function getTotalPaid() { + if (!$this->get('total_paid')->isEmpty()) { + return $this->get('total_paid')->first()->toPrice(); + } + return new Price('0', $this->getStore()->getDefaultCurrencyCode()); + } + + /** + * {@inheritdoc} + */ + public function setTotalPaid(Price $amount) { + $this->set('total_paid', $amount); + } + + /** + * {@inheritdoc} + */ + public function getBalance() { + if ($this->getTotalPrice() && $this->getTotalPaid()) { + return $this->getTotalPrice()->subtract($this->getTotalPaid()); + } + return $this->getTotalPrice(); + } + /** * {@inheritdoc} */ @@ -623,6 +666,13 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setDisplayConfigurable('form', FALSE) ->setDisplayConfigurable('view', TRUE); + $fields['total_paid'] = BaseFieldDefinition::create('commerce_price') + ->setLabel(t('Total paid')) + ->setDescription(t('The total amount paid on the order.')) + ->setReadOnly(TRUE) + ->setDisplayConfigurable('form', FALSE) + ->setDisplayConfigurable('view', TRUE); + $fields['state'] = BaseFieldDefinition::create('state') ->setLabel(t('State')) ->setDescription(t('The order state.')) diff --git a/modules/order/src/Entity/OrderInterface.php b/modules/order/src/Entity/OrderInterface.php index 3fbf0ce7d8..fa54c866d8 100644 --- a/modules/order/src/Entity/OrderInterface.php +++ b/modules/order/src/Entity/OrderInterface.php @@ -3,6 +3,7 @@ namespace Drupal\commerce_order\Entity; use Drupal\commerce_order\EntityAdjustableInterface; +use Drupal\commerce_price\Price; use Drupal\commerce_store\Entity\StoreInterface; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityChangedInterface; @@ -262,6 +263,49 @@ public function recalculateTotalPrice(); */ public function getTotalPrice(); + /** + * Adds an amount to the order total paid. + * + * @param \Drupal\commerce_price\Price $amount + * The amount to add to the total paid. + * + * @return $this + */ + public function addPayment(Price $amount); + + /** + * Subtracts an amount from the order total paid. + * + * @param \Drupal\commerce_price\Price $amount + * The amount to subtract from the total paid. + * + * @return $this + */ + public function subtractPayment(Price $amount); + + /** + * Gets the total amount paid on the order. + * + * @return \Drupal\commerce_price\Price + * The order total paid amount. + */ + public function getTotalPaid(); + + /** + * Sets the total amount paid on the order. + * + * @param \Drupal\commerce_price\Price $amount + */ + public function setTotalPaid(Price $amount); + + /** + * Gets the remaining amount unpaid on the order. + * + * @return \Drupal\commerce_price\Price|null + * The total order amount minus the total paid, or NULL. + */ + public function getBalance(); + /** * Gets the order state. * diff --git a/modules/payment/src/Entity/Payment.php b/modules/payment/src/Entity/Payment.php index 91a5e659d7..dcf9e456d2 100644 --- a/modules/payment/src/Entity/Payment.php +++ b/modules/payment/src/Entity/Payment.php @@ -175,6 +175,7 @@ public function getAmount() { */ public function setAmount(Price $amount) { $this->set('amount', $amount); + $this->getOrder()->addPayment($amount); return $this; } @@ -192,6 +193,7 @@ public function getRefundedAmount() { */ public function setRefundedAmount(Price $refunded_amount) { $this->set('refunded_amount', $refunded_amount); + $this->getOrder()->subtractPayment($refunded_amount); return $this; } From 87508a3a31f8fc4d7fb1790d86b2adfe862635b4 Mon Sep 17 00:00:00 2001 From: Steve Oliver Date: Fri, 23 Sep 2016 16:37:41 -0700 Subject: [PATCH 04/25] Fix OrderInterface docblocks (thanks, phpcs). --- modules/order/src/Entity/OrderInterface.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/order/src/Entity/OrderInterface.php b/modules/order/src/Entity/OrderInterface.php index fa54c866d8..2519ca8114 100644 --- a/modules/order/src/Entity/OrderInterface.php +++ b/modules/order/src/Entity/OrderInterface.php @@ -267,7 +267,7 @@ public function getTotalPrice(); * Adds an amount to the order total paid. * * @param \Drupal\commerce_price\Price $amount - * The amount to add to the total paid. + * The amount to add to the total paid. * * @return $this */ @@ -277,7 +277,7 @@ public function addPayment(Price $amount); * Subtracts an amount from the order total paid. * * @param \Drupal\commerce_price\Price $amount - * The amount to subtract from the total paid. + * The amount to subtract from the total paid. * * @return $this */ @@ -295,6 +295,7 @@ public function getTotalPaid(); * Sets the total amount paid on the order. * * @param \Drupal\commerce_price\Price $amount + * The amount to set as the order total paid. */ public function setTotalPaid(Price $amount); From c31e6ce64aeb1fe9e9abed27363c518d4d6f81ed Mon Sep 17 00:00:00 2001 From: Steve Oliver Date: Mon, 17 Oct 2016 13:23:55 -0700 Subject: [PATCH 05/25] Add Order tests for ::getBalance, ::getTotalPaid, ::setTotalPaid, ::addPayment, ::subtractPayment. --- .../order/tests/src/Kernel/Entity/OrderTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/modules/order/tests/src/Kernel/Entity/OrderTest.php b/modules/order/tests/src/Kernel/Entity/OrderTest.php index ebdf2bdcb6..efb205512e 100644 --- a/modules/order/tests/src/Kernel/Entity/OrderTest.php +++ b/modules/order/tests/src/Kernel/Entity/OrderTest.php @@ -94,6 +94,11 @@ protected function setUp() { * @covers ::getSubtotalPrice * @covers ::recalculateTotalPrice * @covers ::getTotalPrice + * @covers ::getBalance + * @covers ::addPayment + * @covers ::subtractPayment + * @covers ::setTotalPaid + * @covers ::getTotalPaid * @covers ::getState * @covers ::getRefreshState * @covers ::setRefreshState @@ -178,6 +183,7 @@ public function testOrder() { $this->assertNotEmpty($order->hasItem($another_order_item)); $this->assertEquals(new Price('8.00', 'USD'), $order->getTotalPrice()); + $this->assertEquals(new Price('8.00', 'USD'), $order->getBalance()); $adjustments = []; $adjustments[] = new Adjustment([ 'type' => 'custom', @@ -199,6 +205,7 @@ public function testOrder() { $order->removeAdjustment($adjustments[0]); $this->assertEquals(new Price('8.00', 'USD'), $order->getSubtotalPrice()); $this->assertEquals(new Price('18.00', 'USD'), $order->getTotalPrice()); + $this->assertEquals(new Price('18.00', 'USD'), $order->getBalance()); $this->assertEquals([$adjustments[1]], $order->getAdjustments()); $order->setAdjustments($adjustments); $this->assertEquals($adjustments, $order->getAdjustments()); @@ -215,6 +222,14 @@ public function testOrder() { $this->assertEquals(new Price('27.00', 'USD'), $order->getTotalPrice()); $collected_adjustments = $order->collectAdjustments(); $this->assertEquals(new Price('10.00', 'USD'), $collected_adjustments[2]->getAmount()); + $order->addPayment(new Price('25.00', 'USD')); + $this->assertEquals(new Price('25.00', 'USD'), $order->getTotalPaid()); + $this->assertEquals(new Price('2.00', 'USD'), $order->getBalance()); + $order->subtractPayment(new Price('5.00', 'USD')); + $this->assertEquals(new Price('20.00', 'USD'), $order->getTotalPaid()); + $this->assertEquals(new Price('7.00', 'USD'), $order->getBalance()); + $order->setTotalPaid(new Price('27.00', 'USD')); + $this->assertEquals(new Price('0.00', 'USD'), $order->getBalance()); $this->assertEquals('completed', $order->getState()->value); From fa1b88d6799253337c362347b68e39c15bdda654 Mon Sep 17 00:00:00 2001 From: Steve Oliver Date: Tue, 7 Feb 2017 14:20:56 -0800 Subject: [PATCH 06/25] Add and subtract payments to and from order when saving and deleting payment entities. --- .../tests/src/Kernel/Entity/OrderTest.php | 42 +++++++++++++++++-- modules/payment/src/Entity/Payment.php | 23 +++++++++- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/modules/order/tests/src/Kernel/Entity/OrderTest.php b/modules/order/tests/src/Kernel/Entity/OrderTest.php index efb205512e..927617edf4 100644 --- a/modules/order/tests/src/Kernel/Entity/OrderTest.php +++ b/modules/order/tests/src/Kernel/Entity/OrderTest.php @@ -8,6 +8,8 @@ use Drupal\commerce_order\Entity\OrderItemType; use Drupal\commerce_price\Exception\CurrencyMismatchException; use Drupal\commerce_price\Price; +use Drupal\commerce_payment\Entity\Payment; +use Drupal\commerce_payment\Entity\PaymentGateway; use Drupal\profile\Entity\Profile; use Drupal\Tests\commerce\Kernel\CommerceKernelTestBase; @@ -36,6 +38,8 @@ class OrderTest extends CommerceKernelTestBase { 'entity_reference_revisions', 'profile', 'state_machine', + 'commerce_payment', + 'commerce_payment_example', 'commerce_product', 'commerce_order', ]; @@ -49,6 +53,7 @@ protected function setUp() { $this->installEntitySchema('profile'); $this->installEntitySchema('commerce_order'); $this->installEntitySchema('commerce_order_item'); + $this->installEntitySchema('commerce_payment'); $this->installConfig('commerce_order'); // An order item type that doesn't need a purchasable entity, for simplicity. @@ -58,6 +63,12 @@ protected function setUp() { 'orderType' => 'default', ])->save(); + PaymentGateway::create([ + 'id' => 'example', + 'label' => 'Example', + 'plugin' => 'example_onsite', + ])->save(); + $user = $this->createUser(); $this->user = $this->reloadEntity($user); } @@ -138,6 +149,7 @@ public function testOrder() { $order = Order::create([ 'type' => 'default', 'state' => 'completed', + 'store_id' => $this->store->id(), ]); $order->save(); @@ -220,16 +232,40 @@ public function testOrder() { ])); $order->addItem($another_order_item); $this->assertEquals(new Price('27.00', 'USD'), $order->getTotalPrice()); + $this->assertEquals(new Price('0', 'USD'), $order->getTotalPaid()); $collected_adjustments = $order->collectAdjustments(); $this->assertEquals(new Price('10.00', 'USD'), $collected_adjustments[2]->getAmount()); - $order->addPayment(new Price('25.00', 'USD')); + + // Test that payments update the order total paid and balance. + $order->save(); + $payment = Payment::create([ + 'order_id' => $order->id(), + 'amount' => new Price('25.00', 'USD'), + 'payment_gateway' => 'example', + ]); + $payment->save(); + $order = Order::load($order->id()); $this->assertEquals(new Price('25.00', 'USD'), $order->getTotalPaid()); $this->assertEquals(new Price('2.00', 'USD'), $order->getBalance()); - $order->subtractPayment(new Price('5.00', 'USD')); + $payment->setRefundedAmount(new Price('5.00', 'USD'))->save(); + $order = Order::load($order->id()); $this->assertEquals(new Price('20.00', 'USD'), $order->getTotalPaid()); $this->assertEquals(new Price('7.00', 'USD'), $order->getBalance()); - $order->setTotalPaid(new Price('27.00', 'USD')); + $payment->delete(); + $order = Order::load($order->id()); + $this->assertEquals(new Price('0.00', 'USD'), $order->getTotalPaid()); + $payment2 = Payment::create([ + 'order_id' => $order->id(), + 'amount' => new Price('27.00', 'USD'), + 'payment_gateway' => 'example', + ]); + $payment2->save(); + $order = Order::load($order->id()); $this->assertEquals(new Price('0.00', 'USD'), $order->getBalance()); + // Test that the total paid amount can be set explicitly on the order. + $order->setTotalPaid(new Price('0.00', 'USD')); + $order->save(); + $this->assertEquals(new Price('27.00', 'USD'), $order->getBalance()); $this->assertEquals('completed', $order->getState()->value); diff --git a/modules/payment/src/Entity/Payment.php b/modules/payment/src/Entity/Payment.php index dcf9e456d2..873c04eaf7 100644 --- a/modules/payment/src/Entity/Payment.php +++ b/modules/payment/src/Entity/Payment.php @@ -175,7 +175,6 @@ public function getAmount() { */ public function setAmount(Price $amount) { $this->set('amount', $amount); - $this->getOrder()->addPayment($amount); return $this; } @@ -193,7 +192,6 @@ public function getRefundedAmount() { */ public function setRefundedAmount(Price $refunded_amount) { $this->set('refunded_amount', $refunded_amount); - $this->getOrder()->subtractPayment($refunded_amount); return $this; } @@ -276,6 +274,27 @@ public function preSave(EntityStorageInterface $storage) { $refunded_amount = new Price('0', $this->getAmount()->getCurrencyCode()); $this->setRefundedAmount($refunded_amount); } + + // Add or subtract payments from order. + if ($this->isNew()) { + $this->getOrder()->addPayment($this->getAmount())->save(); + } + else { + $this->getOrder()->subtractPayment($this->getRefundedAmount())->save(); + } + } + + /** + * {@inheritdoc} + */ + public static function preDelete(EntityStorageInterface $storage, array $entities) { + parent::preDelete($storage, $entities); + + // Subtract each payment from order. + foreach ($entities as $payment) { + $net_payment = $payment->getAmount()->subtract($payment->getRefundedAmount()); + $payment->getOrder()->subtractPayment($net_payment)->save(); + } } /** From 11b2b7fd5f34324ed2d5c72025894367cf31fd05 Mon Sep 17 00:00:00 2001 From: Steve Oliver Date: Tue, 7 Feb 2017 16:31:47 -0800 Subject: [PATCH 07/25] Support multiple partial refunds. --- .../tests/src/Kernel/Entity/OrderTest.php | 59 +++++++++++++++++-- modules/payment/src/Entity/Payment.php | 4 +- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/modules/order/tests/src/Kernel/Entity/OrderTest.php b/modules/order/tests/src/Kernel/Entity/OrderTest.php index 927617edf4..a746a5e955 100644 --- a/modules/order/tests/src/Kernel/Entity/OrderTest.php +++ b/modules/order/tests/src/Kernel/Entity/OrderTest.php @@ -29,6 +29,11 @@ class OrderTest extends CommerceKernelTestBase { */ protected $user; + /** + * @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface; + */ + protected $payment_gateway; + /** * Modules to enable. * @@ -63,11 +68,13 @@ protected function setUp() { 'orderType' => 'default', ])->save(); - PaymentGateway::create([ + $payment_gateway = PaymentGateway::create([ 'id' => 'example', 'label' => 'Example', 'plugin' => 'example_onsite', - ])->save(); + ]); + $payment_gateway->save(); + $this->payment_gateway = $payment_gateway; $user = $this->createUser(); $this->user = $this->reloadEntity($user); @@ -231,10 +238,54 @@ public function testOrder() { 'amount' => new Price('5.00', 'USD'), ])); $order->addItem($another_order_item); - $this->assertEquals(new Price('27.00', 'USD'), $order->getTotalPrice()); - $this->assertEquals(new Price('0', 'USD'), $order->getTotalPaid()); $collected_adjustments = $order->collectAdjustments(); $this->assertEquals(new Price('10.00', 'USD'), $collected_adjustments[2]->getAmount()); + $this->assertEquals(new Price('27.00', 'USD'), $order->getTotalPrice()); + $this->assertEquals(new Price('27.00', 'USD'), $order->getBalance()); + + // Test that payments update the order total paid and balance. + $order->save(); + $payment = Payment::create([ + 'order_id' => $order->id(), + 'amount' => new Price('25.00', 'USD'), + 'payment_gateway' => 'example', + 'state' => 'capture_completed', + ]); + $payment->save(); + $order = Order::load($order->id()); + $this->assertEquals(new Price('2.00', 'USD'), $order->getBalance()); + $payment->setRefundedAmount(new Price('5.00', 'USD'))->save(); + $order = Order::load($order->id()); + $this->assertEquals(new Price('7.00', 'USD'), $order->getBalance()); + $payment->delete(); + $order = Order::load($order->id()); + $this->assertEquals(new Price('27.00', 'USD'), $order->getBalance()); + $payment2 = Payment::create([ + 'order_id' => $order->id(), + 'amount' => new Price('27.00', 'USD'), + 'payment_gateway' => 'example', + 'state' => 'capture_completed', + ]); + $payment2->save(); + $order = Order::load($order->id()); + $this->assertEquals(new Price('0.00', 'USD'), $order->getBalance()); + + // Test that payments can be partially refunded multiple times. + /** @var \Drupal\commerce_payment\Plugin\Commerce\PaymentGateway\SupportsRefundsInterface $payment_gateway_plugin */ + $payment_gateway_plugin = $this->payment_gateway->getPlugin(); + + $payment_gateway_plugin->refundPayment($payment2, new Price('17.00', 'USD')); + $order = Order::load($order->id()); + $this->assertEquals(new Price('17.00', 'USD'), $order->getBalance()); + + $payment_gateway_plugin->refundPayment($payment2, new Price('5.00', 'USD')); + $order = Order::load($order->id()); + $this->assertEquals(new Price('22.00', 'USD'), $order->getBalance()); + + // Test that the total paid amount can be set explicitly on the order. + $order->setTotalPaid(new Price('0.00', 'USD')); + $order->save(); + $this->assertEquals(new Price('27.00', 'USD'), $order->getBalance()); // Test that payments update the order total paid and balance. $order->save(); diff --git a/modules/payment/src/Entity/Payment.php b/modules/payment/src/Entity/Payment.php index 873c04eaf7..2949715c6d 100644 --- a/modules/payment/src/Entity/Payment.php +++ b/modules/payment/src/Entity/Payment.php @@ -280,7 +280,9 @@ public function preSave(EntityStorageInterface $storage) { $this->getOrder()->addPayment($this->getAmount())->save(); } else { - $this->getOrder()->subtractPayment($this->getRefundedAmount())->save(); + $original = $this->values['original']; + $net_refund = $this->getRefundedAmount()->subtract($original->getRefundedAmount()); + $this->getOrder()->subtractPayment($net_refund)->save(); } } From 7593adecc23bae0774888c541db8b1183a6cce80 Mon Sep 17 00:00:00 2001 From: Steve Oliver Date: Wed, 8 Feb 2017 09:16:06 -0800 Subject: [PATCH 08/25] Clean up Order entity test. --- .../tests/src/Kernel/Entity/OrderTest.php | 36 +++++-------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/modules/order/tests/src/Kernel/Entity/OrderTest.php b/modules/order/tests/src/Kernel/Entity/OrderTest.php index a746a5e955..3fba039bfb 100644 --- a/modules/order/tests/src/Kernel/Entity/OrderTest.php +++ b/modules/order/tests/src/Kernel/Entity/OrderTest.php @@ -30,9 +30,11 @@ class OrderTest extends CommerceKernelTestBase { protected $user; /** - * @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface; + * The payment gateway plugin. + * + * @var \Drupal\commerce_payment\Plugin\Commerce\PaymentGateway\SupportsRefundsInterface */ - protected $payment_gateway; + protected $payment_gateway_plugin; /** * Modules to enable. @@ -74,7 +76,7 @@ protected function setUp() { 'plugin' => 'example_onsite', ]); $payment_gateway->save(); - $this->payment_gateway = $payment_gateway; + $this->payment_gateway_plugin = $payment_gateway->getPlugin(); $user = $this->createUser(); $this->user = $this->reloadEntity($user); @@ -254,7 +256,7 @@ public function testOrder() { $payment->save(); $order = Order::load($order->id()); $this->assertEquals(new Price('2.00', 'USD'), $order->getBalance()); - $payment->setRefundedAmount(new Price('5.00', 'USD'))->save(); + $this->payment_gateway_plugin->refundPayment($payment, new Price('5.00', 'USD')); $order = Order::load($order->id()); $this->assertEquals(new Price('7.00', 'USD'), $order->getBalance()); $payment->delete(); @@ -271,14 +273,10 @@ public function testOrder() { $this->assertEquals(new Price('0.00', 'USD'), $order->getBalance()); // Test that payments can be partially refunded multiple times. - /** @var \Drupal\commerce_payment\Plugin\Commerce\PaymentGateway\SupportsRefundsInterface $payment_gateway_plugin */ - $payment_gateway_plugin = $this->payment_gateway->getPlugin(); - - $payment_gateway_plugin->refundPayment($payment2, new Price('17.00', 'USD')); + $this->payment_gateway_plugin->refundPayment($payment2, new Price('17.00', 'USD')); $order = Order::load($order->id()); $this->assertEquals(new Price('17.00', 'USD'), $order->getBalance()); - - $payment_gateway_plugin->refundPayment($payment2, new Price('5.00', 'USD')); + $this->payment_gateway_plugin->refundPayment($payment2, new Price('5.00', 'USD')); $order = Order::load($order->id()); $this->assertEquals(new Price('22.00', 'USD'), $order->getBalance()); @@ -287,7 +285,7 @@ public function testOrder() { $order->save(); $this->assertEquals(new Price('27.00', 'USD'), $order->getBalance()); - // Test that payments update the order total paid and balance. + // Test that deleted payments update the order total paid and balance. $order->save(); $payment = Payment::create([ 'order_id' => $order->id(), @@ -298,25 +296,9 @@ public function testOrder() { $order = Order::load($order->id()); $this->assertEquals(new Price('25.00', 'USD'), $order->getTotalPaid()); $this->assertEquals(new Price('2.00', 'USD'), $order->getBalance()); - $payment->setRefundedAmount(new Price('5.00', 'USD'))->save(); - $order = Order::load($order->id()); - $this->assertEquals(new Price('20.00', 'USD'), $order->getTotalPaid()); - $this->assertEquals(new Price('7.00', 'USD'), $order->getBalance()); $payment->delete(); $order = Order::load($order->id()); $this->assertEquals(new Price('0.00', 'USD'), $order->getTotalPaid()); - $payment2 = Payment::create([ - 'order_id' => $order->id(), - 'amount' => new Price('27.00', 'USD'), - 'payment_gateway' => 'example', - ]); - $payment2->save(); - $order = Order::load($order->id()); - $this->assertEquals(new Price('0.00', 'USD'), $order->getBalance()); - // Test that the total paid amount can be set explicitly on the order. - $order->setTotalPaid(new Price('0.00', 'USD')); - $order->save(); - $this->assertEquals(new Price('27.00', 'USD'), $order->getBalance()); $this->assertEquals('completed', $order->getState()->value); From 913b912c2d62cfb61cd73a575a768daffc8428ad Mon Sep 17 00:00:00 2001 From: Steve Oliver Date: Wed, 12 Apr 2017 14:01:59 -0700 Subject: [PATCH 09/25] Use Price. --- modules/order/src/Entity/Order.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/order/src/Entity/Order.php b/modules/order/src/Entity/Order.php index 573c9a0957..44a0dbf8ab 100644 --- a/modules/order/src/Entity/Order.php +++ b/modules/order/src/Entity/Order.php @@ -3,6 +3,7 @@ namespace Drupal\commerce_order\Entity; use Drupal\commerce_order\Adjustment; +use Drupal\commerce_price\Price; use Drupal\commerce_store\Entity\StoreInterface; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityChangedTrait; From 14a37fdea1012bc02d86abb0d8c2616c805b85fd Mon Sep 17 00:00:00 2001 From: vasike Date: Mon, 4 Sep 2017 18:28:57 -0500 Subject: [PATCH 10/25] add update to add the total_paid field --- modules/order/commerce_order.post_update.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/modules/order/commerce_order.post_update.php b/modules/order/commerce_order.post_update.php index 335c6cf399..0be9b15dad 100644 --- a/modules/order/commerce_order.post_update.php +++ b/modules/order/commerce_order.post_update.php @@ -5,6 +5,8 @@ * Post update functions for Order. */ +use Drupal\Core\Field\BaseFieldDefinition; + /** * Revert Order views to fix broken Price fields. */ @@ -149,3 +151,18 @@ function commerce_order_post_update_5() { return $message; } + +/** + * Add 'total_paid' field to 'commerce_order' entities. + */ +function commerce_order_post_update_6() { + $storage_definition = BaseFieldDefinition::create('commerce_price') + ->setLabel(t('Total paid')) + ->setDescription(t('The total amount paid on the order.')) + ->setReadOnly(TRUE) + ->setDisplayConfigurable('form', FALSE) + ->setDisplayConfigurable('view', TRUE); + \Drupal::entityDefinitionUpdateManager() + ->installFieldStorageDefinition('total_paid', 'commerce_order', 'commerce_order', $storage_definition); + return t('The order total paid field was created.'); +} From f1678e15128252ce805cfd981b727b36a9c12cc6 Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Date: Thu, 7 Sep 2017 17:08:03 -0500 Subject: [PATCH 11/25] Update payment states to match new names --- modules/order/tests/src/Kernel/Entity/OrderTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/order/tests/src/Kernel/Entity/OrderTest.php b/modules/order/tests/src/Kernel/Entity/OrderTest.php index c5bf320c6f..8d7d8f34b2 100644 --- a/modules/order/tests/src/Kernel/Entity/OrderTest.php +++ b/modules/order/tests/src/Kernel/Entity/OrderTest.php @@ -260,7 +260,7 @@ public function testOrder() { 'order_id' => $order->id(), 'amount' => new Price('25.00', 'USD'), 'payment_gateway' => 'example', - 'state' => 'capture_completed', + 'state' => 'completed', ]); $payment->save(); $order = Order::load($order->id()); @@ -275,7 +275,7 @@ public function testOrder() { 'order_id' => $order->id(), 'amount' => new Price('27.00', 'USD'), 'payment_gateway' => 'example', - 'state' => 'capture_completed', + 'state' => 'completed', ]); $payment2->save(); $order = Order::load($order->id()); From 8dec773891b16e8a44017a25e8d54b83ede39341 Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Thu, 7 Sep 2017 23:31:37 -0400 Subject: [PATCH 12/25] Fix phpcs errors --- .../modules/payment_events_test/payment_events_test.info.yml | 1 - .../tests/modules/payment_events_test/src/EventSubscriber.php | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/payment/tests/modules/payment_events_test/payment_events_test.info.yml b/modules/payment/tests/modules/payment_events_test/payment_events_test.info.yml index 95c6799f00..604ef369cc 100644 --- a/modules/payment/tests/modules/payment_events_test/payment_events_test.info.yml +++ b/modules/payment/tests/modules/payment_events_test/payment_events_test.info.yml @@ -1,5 +1,4 @@ name: 'Configuration events test' type: module package: Testing -version: VERSION core: 8.x diff --git a/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php b/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php index 32c5683bdf..26c63fac35 100644 --- a/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php +++ b/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php @@ -2,7 +2,6 @@ namespace Drupal\payment_events_test; - use Drupal\commerce_payment\Event\PaymentEvent; use Drupal\commerce_payment\Event\PaymentEvents; use Drupal\Core\State\StateInterface; @@ -32,7 +31,7 @@ public function __construct(StateInterface $state) { * * @param \Drupal\commerce_payment\Event\PaymentEvent $event * The payment event. - * @param $name + * @param string $name * The name of the event. */ public function paymentEvent(PaymentEvent $event, $name) { From 857f08357264bd57d346a276f5f082637f1e6715 Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Thu, 7 Sep 2017 23:32:57 -0400 Subject: [PATCH 13/25] Correctly implement and test commerce_payment.load event --- modules/payment/src/PaymentStorage.php | 16 +++++++++++++++- .../tests/src/Kernel/PaymentEventsTest.php | 3 +-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/modules/payment/src/PaymentStorage.php b/modules/payment/src/PaymentStorage.php index 6ffb75b3e7..2ea73ec158 100644 --- a/modules/payment/src/PaymentStorage.php +++ b/modules/payment/src/PaymentStorage.php @@ -5,6 +5,7 @@ use Drupal\commerce\CommerceContentEntityStorage; use Drupal\commerce_order\Entity\OrderInterface; use Drupal\commerce_payment\Event\PaymentEvent; +use Drupal\commerce_payment\Event\PaymentEvents; use Drupal\Core\Entity\EntityStorageException; /** @@ -12,6 +13,19 @@ */ class PaymentStorage extends CommerceContentEntityStorage implements PaymentStorageInterface { + /** + * {@inheritdoc} + */ + public function load($id) { + $payment = parent::load($id); // TODO: Change the autogenerated stub + + // Notify other modules. + $event = new PaymentEvent($payment); + $this->eventDispatcher->dispatch(PaymentEvents::PAYMENT_LOAD, $event); + + return $payment; + } + /** * {@inheritdoc} */ @@ -58,7 +72,7 @@ protected function doCreate(array $values) { // Notify other modules. $event = new PaymentEvent($payment); - $this->eventDispatcher->dispatch('commerce_payment.commerce_payment.create', $event); + $this->eventDispatcher->dispatch(PaymentEvents::PAYMENT_CREATE, $event); return $payment; } diff --git a/modules/payment/tests/src/Kernel/PaymentEventsTest.php b/modules/payment/tests/src/Kernel/PaymentEventsTest.php index 468ea0f471..1a30ba013b 100644 --- a/modules/payment/tests/src/Kernel/PaymentEventsTest.php +++ b/modules/payment/tests/src/Kernel/PaymentEventsTest.php @@ -90,14 +90,13 @@ public function testPaymentEvents() { 'test' => TRUE, ]); $payment->save(); - $payment = $this->reloadEntity($payment); // Check the create event. $event_recorder = \Drupal::state()->get('payment_events_test.event', FALSE); $this->assertEquals('commerce_payment.commerce_payment.create', $event_recorder['event_name']); // Reload the payment. - Payment::load($payment->id()); + $this->reloadEntity($payment); // Check the load event. $event_recorder = \Drupal::state()->get('payment_events_test.event', FALSE); From 0db777ae127806b4c30c33d13bb14a8fdb3cdb6a Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Mon, 11 Sep 2017 01:28:00 -0400 Subject: [PATCH 14/25] Watch payment status before changing order balance --- modules/order/tests/src/Kernel/Entity/OrderTest.php | 9 ++++++++- modules/payment/src/Entity/Payment.php | 13 +++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/modules/order/tests/src/Kernel/Entity/OrderTest.php b/modules/order/tests/src/Kernel/Entity/OrderTest.php index 8d7d8f34b2..d21995e8a4 100644 --- a/modules/order/tests/src/Kernel/Entity/OrderTest.php +++ b/modules/order/tests/src/Kernel/Entity/OrderTest.php @@ -294,7 +294,7 @@ public function testOrder() { $order->save(); $this->assertEquals(new Price('27.00', 'USD'), $order->getBalance()); - // Test that deleted payments update the order total paid and balance. + // Test that payments only substract total when setting to completed. $order->save(); $payment = Payment::create([ 'order_id' => $order->id(), @@ -303,8 +303,15 @@ public function testOrder() { ]); $payment->save(); $order = Order::load($order->id()); + $this->assertEquals(new Price('0.00', 'USD'), $order->getTotalPaid()); + + $payment->setState('completed'); + $payment->save(); + $order = Order::load($order->id()); $this->assertEquals(new Price('25.00', 'USD'), $order->getTotalPaid()); $this->assertEquals(new Price('2.00', 'USD'), $order->getBalance()); + + // Test that deleted payments update the order total paid and balance. $payment->delete(); $order = Order::load($order->id()); $this->assertEquals(new Price('0.00', 'USD'), $order->getTotalPaid()); diff --git a/modules/payment/src/Entity/Payment.php b/modules/payment/src/Entity/Payment.php index 460d236e2c..cc77431ebb 100644 --- a/modules/payment/src/Entity/Payment.php +++ b/modules/payment/src/Entity/Payment.php @@ -291,7 +291,8 @@ public function preSave(EntityStorageInterface $storage) { $refunded_amount = new Price('0', $this->getAmount()->getCurrencyCode()); $this->setRefundedAmount($refunded_amount); } - // Maintain the authorized completed timestamps. + // Maintain the authorized completed timestamps while also maintaining the + // order balance. $state = $this->getState()->value; $original_state = isset($this->original) ? $this->original->getState()->value : ''; if ($state == 'authorized' && $original_state != 'authorized') { @@ -300,16 +301,12 @@ public function preSave(EntityStorageInterface $storage) { } } if ($state == 'completed' && $original_state != 'completed') { + $this->getOrder()->addPayment($this->getAmount())->save(); if (empty($this->getCompletedTime())) { $this->setCompletedTime(\Drupal::time()->getRequestTime()); } - } - - // Add or subtract payments from order. - if ($this->isNew()) { - $this->getOrder()->addPayment($this->getAmount())->save(); - } - else { + } else if (in_array($state, ['partially_refunded', 'refunded']) && + in_array($original_state, ['completed', 'partially_refunded'])) { $original = $this->values['original']; $net_refund = $this->getRefundedAmount()->subtract($original->getRefundedAmount()); $this->getOrder()->subtractPayment($net_refund)->save(); From 5395dc2f0afd00c21763068340a95aee5efbd116 Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Mon, 11 Sep 2017 08:40:22 -0400 Subject: [PATCH 15/25] Fix two coding standard errors --- modules/payment/src/Entity/Payment.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/payment/src/Entity/Payment.php b/modules/payment/src/Entity/Payment.php index cc77431ebb..89602ab812 100644 --- a/modules/payment/src/Entity/Payment.php +++ b/modules/payment/src/Entity/Payment.php @@ -305,7 +305,8 @@ public function preSave(EntityStorageInterface $storage) { if (empty($this->getCompletedTime())) { $this->setCompletedTime(\Drupal::time()->getRequestTime()); } - } else if (in_array($state, ['partially_refunded', 'refunded']) && + } + elseif (in_array($state, ['partially_refunded', 'refunded']) && in_array($original_state, ['completed', 'partially_refunded'])) { $original = $this->values['original']; $net_refund = $this->getRefundedAmount()->subtract($original->getRefundedAmount()); From f8ebaf9eb590d3efca58db70125cc9f8a875b1c0 Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Tue, 12 Sep 2017 00:16:03 -0400 Subject: [PATCH 16/25] Rename getOrder to getEntity. It it is not returning the order. --- modules/payment/src/Event/PaymentEvent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/payment/src/Event/PaymentEvent.php b/modules/payment/src/Event/PaymentEvent.php index 36e5c90cc6..fec57891ec 100644 --- a/modules/payment/src/Event/PaymentEvent.php +++ b/modules/payment/src/Event/PaymentEvent.php @@ -35,7 +35,7 @@ public function __construct(PaymentInterface $payment) { * @return \Drupal\commerce_payment\Entity\PaymentInterface * Gets the payment. */ - public function getOrder() { + public function getEntity() { return $this->payment; } From a50215b3f3cff565d8656d5e5bdfbd6a7a2975cc Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Tue, 12 Sep 2017 00:18:20 -0400 Subject: [PATCH 17/25] Implement CRUD events using the event annotation on the Payment Entity --- modules/payment/src/Entity/Payment.php | 1 + modules/payment/src/PaymentStorage.php | 13 ------------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/modules/payment/src/Entity/Payment.php b/modules/payment/src/Entity/Payment.php index 89602ab812..e2167660a2 100644 --- a/modules/payment/src/Entity/Payment.php +++ b/modules/payment/src/Entity/Payment.php @@ -25,6 +25,7 @@ * bundle_label = @Translation("Payment type"), * bundle_plugin_type = "commerce_payment_type", * handlers = { + * "event" = "Drupal\commerce_payment\Event\PaymentEvent", * "access" = "Drupal\commerce_payment\PaymentAccessControlHandler", * "list_builder" = "Drupal\commerce_payment\PaymentListBuilder", * "storage" = "Drupal\commerce_payment\PaymentStorage", diff --git a/modules/payment/src/PaymentStorage.php b/modules/payment/src/PaymentStorage.php index 2ea73ec158..6435a60812 100644 --- a/modules/payment/src/PaymentStorage.php +++ b/modules/payment/src/PaymentStorage.php @@ -13,19 +13,6 @@ */ class PaymentStorage extends CommerceContentEntityStorage implements PaymentStorageInterface { - /** - * {@inheritdoc} - */ - public function load($id) { - $payment = parent::load($id); // TODO: Change the autogenerated stub - - // Notify other modules. - $event = new PaymentEvent($payment); - $this->eventDispatcher->dispatch(PaymentEvents::PAYMENT_LOAD, $event); - - return $payment; - } - /** * {@inheritdoc} */ From df566da3fff18952cea89f27221c5fe5b1c72bbc Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Tue, 12 Sep 2017 00:23:03 -0400 Subject: [PATCH 18/25] Rename PaymentEvent::getOrder to getEntity because it returns the payment object --- modules/payment/src/Event/PaymentEvent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/payment/src/Event/PaymentEvent.php b/modules/payment/src/Event/PaymentEvent.php index 36e5c90cc6..fec57891ec 100644 --- a/modules/payment/src/Event/PaymentEvent.php +++ b/modules/payment/src/Event/PaymentEvent.php @@ -35,7 +35,7 @@ public function __construct(PaymentInterface $payment) { * @return \Drupal\commerce_payment\Entity\PaymentInterface * Gets the payment. */ - public function getOrder() { + public function getEntity() { return $this->payment; } From 6c56ec6d7f9fd6da46cdad991958b70cefcd121c Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Tue, 12 Sep 2017 00:23:19 -0400 Subject: [PATCH 19/25] Implement CRUD events using the event annotation on the Payment Entity --- modules/payment/src/Entity/Payment.php | 1 + modules/payment/src/PaymentStorage.php | 13 ------------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/modules/payment/src/Entity/Payment.php b/modules/payment/src/Entity/Payment.php index 01fbe95556..0fbf220bb2 100644 --- a/modules/payment/src/Entity/Payment.php +++ b/modules/payment/src/Entity/Payment.php @@ -25,6 +25,7 @@ * bundle_label = @Translation("Payment type"), * bundle_plugin_type = "commerce_payment_type", * handlers = { + * "event" = "Drupal\commerce_payment\Event\PaymentEvent", * "access" = "Drupal\commerce_payment\PaymentAccessControlHandler", * "list_builder" = "Drupal\commerce_payment\PaymentListBuilder", * "storage" = "Drupal\commerce_payment\PaymentStorage", diff --git a/modules/payment/src/PaymentStorage.php b/modules/payment/src/PaymentStorage.php index 2ea73ec158..6435a60812 100644 --- a/modules/payment/src/PaymentStorage.php +++ b/modules/payment/src/PaymentStorage.php @@ -13,19 +13,6 @@ */ class PaymentStorage extends CommerceContentEntityStorage implements PaymentStorageInterface { - /** - * {@inheritdoc} - */ - public function load($id) { - $payment = parent::load($id); // TODO: Change the autogenerated stub - - // Notify other modules. - $event = new PaymentEvent($payment); - $this->eventDispatcher->dispatch(PaymentEvents::PAYMENT_LOAD, $event); - - return $payment; - } - /** * {@inheritdoc} */ From 4dd5cf3b83650610ed3de81ae2977d4684e6d2af Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Tue, 12 Sep 2017 11:57:41 -0500 Subject: [PATCH 20/25] Test also the getEntity method inside PaymentEvent --- .../tests/modules/payment_events_test/src/EventSubscriber.php | 1 + modules/payment/tests/src/Kernel/PaymentEventsTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php b/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php index 26c63fac35..916bee9cef 100644 --- a/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php +++ b/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php @@ -37,6 +37,7 @@ public function __construct(StateInterface $state) { public function paymentEvent(PaymentEvent $event, $name) { $this->state->set('payment_events_test.event', [ 'event_name' => $name, + 'event_entity' => $event->getEntity(), ]); } diff --git a/modules/payment/tests/src/Kernel/PaymentEventsTest.php b/modules/payment/tests/src/Kernel/PaymentEventsTest.php index 1a30ba013b..7f584004bd 100644 --- a/modules/payment/tests/src/Kernel/PaymentEventsTest.php +++ b/modules/payment/tests/src/Kernel/PaymentEventsTest.php @@ -94,6 +94,7 @@ public function testPaymentEvents() { // Check the create event. $event_recorder = \Drupal::state()->get('payment_events_test.event', FALSE); $this->assertEquals('commerce_payment.commerce_payment.create', $event_recorder['event_name']); + $this->assertEquals($payment->id(), $event_recorder['event_entity']->id()); // Reload the payment. $this->reloadEntity($payment); From 5343c0e877c065d5adc6cd5bae580cd9b8d80622 Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Tue, 12 Sep 2017 12:08:18 -0500 Subject: [PATCH 21/25] Test also the getEntity method inside PaymentEvent --- .../tests/modules/payment_events_test/src/EventSubscriber.php | 1 + modules/payment/tests/src/Kernel/PaymentEventsTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php b/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php index 26c63fac35..916bee9cef 100644 --- a/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php +++ b/modules/payment/tests/modules/payment_events_test/src/EventSubscriber.php @@ -37,6 +37,7 @@ public function __construct(StateInterface $state) { public function paymentEvent(PaymentEvent $event, $name) { $this->state->set('payment_events_test.event', [ 'event_name' => $name, + 'event_entity' => $event->getEntity(), ]); } diff --git a/modules/payment/tests/src/Kernel/PaymentEventsTest.php b/modules/payment/tests/src/Kernel/PaymentEventsTest.php index 1a30ba013b..7f584004bd 100644 --- a/modules/payment/tests/src/Kernel/PaymentEventsTest.php +++ b/modules/payment/tests/src/Kernel/PaymentEventsTest.php @@ -94,6 +94,7 @@ public function testPaymentEvents() { // Check the create event. $event_recorder = \Drupal::state()->get('payment_events_test.event', FALSE); $this->assertEquals('commerce_payment.commerce_payment.create', $event_recorder['event_name']); + $this->assertEquals($payment->id(), $event_recorder['event_entity']->id()); // Reload the payment. $this->reloadEntity($payment); From ce54df0b68a335e352010f84a50825bb64fac18a Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Tue, 12 Sep 2017 15:15:26 -0500 Subject: [PATCH 22/25] Issue #2856586 by haringsrob, jackbravo: extract event dispatching to a separate function --- modules/payment/src/PaymentStorage.php | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/modules/payment/src/PaymentStorage.php b/modules/payment/src/PaymentStorage.php index 6435a60812..69132bffa6 100644 --- a/modules/payment/src/PaymentStorage.php +++ b/modules/payment/src/PaymentStorage.php @@ -4,6 +4,7 @@ use Drupal\commerce\CommerceContentEntityStorage; use Drupal\commerce_order\Entity\OrderInterface; +use Drupal\commerce_payment\Entity\PaymentInterface; use Drupal\commerce_payment\Event\PaymentEvent; use Drupal\commerce_payment\Event\PaymentEvents; use Drupal\Core\Entity\EntityStorageException; @@ -57,11 +58,24 @@ protected function doCreate(array $values) { $payment = parent::doCreate($values); - // Notify other modules. - $event = new PaymentEvent($payment); - $this->eventDispatcher->dispatch(PaymentEvents::PAYMENT_CREATE, $event); + $this->dispatchPaymentEvent($payment, PaymentEvents::PAYMENT_CREATE); return $payment; } + /** + * Notifies other modules about payment events. + * + * @param \Drupal\commerce_payment\Entity\PaymentInterface $payment + * The payment. + * + * @param string $event_id + * The event identifier defined in + * \Drupal\commerce_payment\Event\PaymentEvents. + */ + public function dispatchPaymentEvent(PaymentInterface $payment, $event_id) { + $event = new PaymentEvent($payment); + $this->eventDispatcher->dispatch($event_id, $event); + } + } From 4f4bc6481f6e7c1b453caf3814dcd143776594ba Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Tue, 12 Sep 2017 15:59:53 -0500 Subject: [PATCH 23/25] Fix coding standard errors --- modules/payment/src/PaymentStorage.php | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/payment/src/PaymentStorage.php b/modules/payment/src/PaymentStorage.php index 69132bffa6..3af30cedf6 100644 --- a/modules/payment/src/PaymentStorage.php +++ b/modules/payment/src/PaymentStorage.php @@ -68,7 +68,6 @@ protected function doCreate(array $values) { * * @param \Drupal\commerce_payment\Entity\PaymentInterface $payment * The payment. - * * @param string $event_id * The event identifier defined in * \Drupal\commerce_payment\Event\PaymentEvents. From 15ee868c7f7f8bc6837de95388b741b770588500 Mon Sep 17 00:00:00 2001 From: Joaquin Bravo Contreras Date: Tue, 12 Sep 2017 16:41:12 -0500 Subject: [PATCH 24/25] Dispatch PAYMENT_ORDER_PAID_IN_FULL event when balance isZero on Payment::preSave --- modules/payment/src/Entity/Payment.php | 5 +++++ modules/payment/src/Event/PaymentEvents.php | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/modules/payment/src/Entity/Payment.php b/modules/payment/src/Entity/Payment.php index e2167660a2..71c359bbc5 100644 --- a/modules/payment/src/Entity/Payment.php +++ b/modules/payment/src/Entity/Payment.php @@ -2,6 +2,8 @@ namespace Drupal\commerce_payment\Entity; +use Drupal\commerce_payment\Event\PaymentEvents; +use Drupal\commerce_payment\PaymentStorage; use Drupal\commerce_price\Price; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityMalformedException; @@ -306,6 +308,9 @@ public function preSave(EntityStorageInterface $storage) { if (empty($this->getCompletedTime())) { $this->setCompletedTime(\Drupal::time()->getRequestTime()); } + if ($this->getOrder()->getBalance()->isZero() && $storage instanceof PaymentStorage) { + $storage->dispatchPaymentEvent($this, PaymentEvents::PAYMENT_ORDER_PAID_IN_FULL); + } } elseif (in_array($state, ['partially_refunded', 'refunded']) && in_array($original_state, ['completed', 'partially_refunded'])) { diff --git a/modules/payment/src/Event/PaymentEvents.php b/modules/payment/src/Event/PaymentEvents.php index 10f263946b..8da5b4bc9f 100644 --- a/modules/payment/src/Event/PaymentEvents.php +++ b/modules/payment/src/Event/PaymentEvents.php @@ -69,6 +69,15 @@ final class PaymentEvents { */ const PAYMENT_DELETE = 'commerce_payment.commerce_payment.delete'; + /** + * Name of the event fired after paying an order in full. + * + * @Event + * + * @see \Drupal\commerce_payment\Event\PaymentEvent + */ + const PAYMENT_ORDER_PAID_IN_FULL = 'commerce_payment.order_paid_in_full'; + /** * Name of the event fired when payment gateways are loaded for an order. * From 91c03f02bce66eafe624e7d552cf03defcb9686c Mon Sep 17 00:00:00 2001 From: steveoliver Date: Fri, 15 Sep 2017 14:03:04 -0500 Subject: [PATCH 25/25] remove the word 'remaining' -- it seems redundant --- modules/order/src/Entity/OrderInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/order/src/Entity/OrderInterface.php b/modules/order/src/Entity/OrderInterface.php index fe6f369883..98db0fbf5b 100644 --- a/modules/order/src/Entity/OrderInterface.php +++ b/modules/order/src/Entity/OrderInterface.php @@ -310,7 +310,7 @@ public function getTotalPaid(); public function setTotalPaid(Price $amount); /** - * Gets the remaining amount unpaid on the order. + * Gets the amount unpaid on the order. * * @return \Drupal\commerce_price\Price|null * The total order amount minus the total paid, or NULL.