Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support chaining Payment.create from Order api #15548

Merged
merged 1 commit into from
Oct 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Civi/Test/Api3TestTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -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([
Expand Down
15 changes: 13 additions & 2 deletions api/v3/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions api/v3/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
13 changes: 13 additions & 0 deletions tests/phpunit/api/v3/OrderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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']));
}

}