From e2887a3c6f6a4747e9bfd7027e55f2e9d182d28c Mon Sep 17 00:00:00 2001 From: eileen Date: Sat, 19 Oct 2019 15:30:51 +1300 Subject: [PATCH] Support chaining Payment.create from Order api --- Civi/Test/Api3TestTrait.php | 2 ++ api/v3/Order.php | 15 +++++++++++++-- api/v3/Payment.php | 3 +++ tests/phpunit/api/v3/OrderTest.php | 13 +++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Civi/Test/Api3TestTrait.php b/Civi/Test/Api3TestTrait.php index e853f5249b14..bc8b0b9125d9 100644 --- a/Civi/Test/Api3TestTrait.php +++ b/Civi/Test/Api3TestTrait.php @@ -147,6 +147,8 @@ public function callAPIFailure($entity, $action, $params, $expectedErrorMessage * better or worse ) * * @return array|int + * + * @throws \CRM_Core_Exception */ public function callAPISuccess($entity, $action, $params = [], $checkAgainst = NULL) { $params = array_merge([ diff --git a/api/v3/Order.php b/api/v3/Order.php index a54104e598ef..baa491c359a1 100644 --- a/api/v3/Order.php +++ b/api/v3/Order.php @@ -92,8 +92,9 @@ function civicrm_api3_order_create($params) { $entityIds = []; $contributionStatus = CRM_Utils_Array::value('contribution_status_id', $params); if ($contributionStatus !== 'Pending' && 'Pending' !== CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $contributionStatus)) { - CRM_Core_Error::deprecatedFunctionWarning('Creating a Order with a status other than pending is deprecated. Currently empty defaults to "Completed" so as a transition not passing in "Pending" is deprecated'); + CRM_Core_Error::deprecatedFunctionWarning("Creating a Order with a status other than pending is deprecated. Currently empty defaults to 'Completed' so as a transition not passing in 'Pending' is deprecated. You can chain payment creation e.g civicrm_api3('Order', 'create', ['blah' => 'blah', 'contribution_status_id' => 'Pending', 'api.Payment.create => ['total_amount' => 5]]"); } + if (!empty($params['line_items']) && is_array($params['line_items'])) { $priceSetID = NULL; CRM_Contribute_BAO_Contribution::checkLineItems($params); @@ -131,7 +132,17 @@ function civicrm_api3_order_create($params) { $params['line_item'][$priceSetID] = array_merge($params['line_item'][$priceSetID], $lineItems['line_item']); } } - $contribution = civicrm_api3('Contribution', 'create', $params); + $contributionParams = $params; + foreach ($contributionParams as $key => $value) { + // Unset chained keys so the code does not attempt to do this chaining twice. + // e.g if calling 'api.Payment.create' We want to finish creating the order first. + // it would probably be better to have a full whitelist of contributionParams + if (substr($key, 0, 3) === 'api') { + unset($contributionParams[$key]); + } + } + + $contribution = civicrm_api3('Contribution', 'create', $contributionParams); // add payments if ($entity && !empty($contribution['id'])) { foreach ($entityIds as $entityId) { diff --git a/api/v3/Payment.php b/api/v3/Payment.php index cdbfbc98c20e..a89350cf12a9 100644 --- a/api/v3/Payment.php +++ b/api/v3/Payment.php @@ -161,6 +161,9 @@ function _civicrm_api3_payment_create_spec(&$params) { 'api.required' => 1, 'title' => ts('Contribution ID'), 'type' => CRM_Utils_Type::T_INT, + // We accept order_id as an alias so that we can chain like + // civicrm_api3('Order', 'create', ['blah' => 'blah', 'contribution_status_id' => 'Pending', 'api.Payment.create => ['total_amount' => 5]] + 'api.aliases' => ['order_id'], ], 'total_amount' => [ 'api.required' => 1, diff --git a/tests/phpunit/api/v3/OrderTest.php b/tests/phpunit/api/v3/OrderTest.php index e72aa26490d4..3633f70d8b8f 100644 --- a/tests/phpunit/api/v3/OrderTest.php +++ b/tests/phpunit/api/v3/OrderTest.php @@ -631,4 +631,17 @@ public function testCreateOrderIfTotalAmountDoesMatchLineItemsAmountsAndTaxSuppl $this->assertEquals(1, $order['count']); } + /** + * Test that a contribution can be added in pending mode with a chained payment. + * + * We have just deprecated creating an order with a status other than pending. It makes + * sense to support adding a payment straight away by chaining. + * + * @throws \CRM_Core_Exception + */ + public function testCreateWithChainedPayment() { + $contributionID = $this->callAPISuccess('Order', 'create', ['contact_id' => $this->_individualId, 'total_amount' => 5, 'financial_type_id' => 2, 'contribution_status_id' => 'Pending', 'api.Payment.create' => ['total_amount' => 5]])['id']; + $this->assertEquals('Completed', $this->callAPISuccessGetValue('Contribution', ['id' => $contributionID, 'return' => 'contribution_status'])); + } + }