From 0efa8efeff7359b3206dea1c9a0dbd29eec01444 Mon Sep 17 00:00:00 2001 From: eileen Date: Tue, 2 Jul 2013 15:59:08 +1200 Subject: [PATCH] CRM-12984 add contribution.completetransaction api --- CRM/Core/DAO/permissions.php | 3 + api/v3/Contribution.php | 50 ++++++++++++++ tests/phpunit/api/v3/ContributionTest.php | 82 +++++++++++++++++++++-- 3 files changed, 130 insertions(+), 5 deletions(-) diff --git a/CRM/Core/DAO/permissions.php b/CRM/Core/DAO/permissions.php index 5112e0274f..81dcd55ea5 100644 --- a/CRM/Core/DAO/permissions.php +++ b/CRM/Core/DAO/permissions.php @@ -149,6 +149,9 @@ function _civicrm_api3_permissions($entity, $action, &$params) { 'access CiviContribute', 'delete in CiviContribute', ), + 'completetransaction' => array( + 'edit contributions', + ), 'default' => array( 'access CiviCRM', 'access CiviContribute', diff --git a/api/v3/Contribution.php b/api/v3/Contribution.php index 0d77401415..09542ddf2a 100644 --- a/api/v3/Contribution.php +++ b/api/v3/Contribution.php @@ -389,3 +389,53 @@ function _civicrm_api3_contribution_sendconfirmation_spec(&$params) { ); } + +/** + * Complete an existing (pending) transaction, updating related entities (participant, membership, pledge etc) + * and taking any complete actions from the contribution page (e.g. send receipt) + * + * @todo - most of this should live in the BAO layer but as we want it to be an addition + * to 4.3 which is already stable we should add it to the api layer & re-factor into the BAO layer later + * + * @param array $params input parameters + * {@getfields Contribution_completetransaction} + * @return array Api result array + * @static void + * @access public + * + */ +function civicrm_api3_contribution_completetransaction(&$params) { + + $input = $ids = array(); + $contribution = new CRM_Contribute_BAO_Contribution(); + $contribution->id = $params['id']; + $contribution->find(TRUE); + if(!$contribution->id == $params['id']){ + throw new API_Exception('A valid contribution ID is required', 'invalid_data'); + } + try { + if(!$contribution->loadRelatedObjects($input, $ids, FALSE, TRUE)){ + throw new API_Exception('failed to load related objects'); + } + $objects = $contribution->_relatedObjects; + $objects['contribution'] = &$contribution; + $input['component'] = $contribution->_component; + $input['is_test'] = $contribution->is_test; + $input['trxn_id']= $contribution->trxn_id; + $input['amount'] = $contribution->total_amount; + if(isset($params['is_email_receipt'])){ + $input['is_email_receipt'] = $params['is_email_receipt']; + } + // @todo required for base ipn but problematic as api layer handles this + $transaction = new CRM_Core_Transaction(); + $ipn = new CRM_Core_Payment_BaseIPN(); + $ipn->completeTransaction($input, $ids, $objects, $transaction); + } + catch(Exception$e) { + throw new API_Exception('failed to load related objects' . $e->getMessage() . "\n" . $e->getTraceAsString()); + } +} + +function _civicrm_api3_contribution_completetransaction(&$params) { + +} diff --git a/tests/phpunit/api/v3/ContributionTest.php b/tests/phpunit/api/v3/ContributionTest.php index 12c30c5749..94a43dff00 100644 --- a/tests/phpunit/api/v3/ContributionTest.php +++ b/tests/phpunit/api/v3/ContributionTest.php @@ -949,8 +949,8 @@ class api_v3_ContributionTest extends CiviUnitTestCase { 'total_amount' => 100.00, 'financial_type_id' => $this->_contributionTypeId, 'payment_instrument_id' => 1, - 'contribution_status_id' => 2, - 'is_pay_later' => 1, + 'contribution_status_id' => 2, + 'is_pay_later' => 1, 'version' => $this->_apiversion, ); $contribution = civicrm_api('contribution', 'create', $contribParams); @@ -1013,10 +1013,10 @@ class api_v3_ContributionTest extends CiviUnitTestCase { $contribution = civicrm_api('contribution', 'update', $newParams); $this->_checkFinancialTrxn($contribution, 'refund'); $this->_checkFinancialItem($contribution['id'], 'refund'); - } + } /* - * Function tests invalid contribution status change + * Function tests invalid contribution status change */ function testCreateUpdateContributionInValidStatusChange() { $contribParams = array( @@ -1303,7 +1303,57 @@ class api_v3_ContributionTest extends CiviUnitTestCase { $this->contributionDelete($contribution1['id']); $this->contributionDelete($contribution2['id']); } - /* + /** + * Test completing a transaction via the API + * + * Note that we are creating a logged in user because email goes out from + * that person + */ + function testCompleteTransaction() { + $mut = new CiviMailUtils( $this, true ); + $this->createLoggedInUser(); + $params = array_merge($this->_params, array('contribution_status_id' => 1,)); + $contribution = $this->callAPISuccess('contribution','create', $params); + $apiResult = $this->callAPISuccess('contribution', 'completetransaction', array( + 'id' => $contribution['id'], + ) + ); + $contribution = $this->callAPISuccess('contribution', 'get', array('id' => $contribution['id'], 'sequential' => 1,)); + $this->assertEquals('Completed', $contribution['values'][0]['contribution_status']); + $mut->checkMailLog(array( + 'Receipt - Contribution', + 'Please print this confirmation for your records.', + )); + $mut->stop(); + } + + /** + * Test completing a transaction with an event via the API + * + * Note that we are creating a logged in user because email goes out from + * that person + */ + function testCompleteTransactionWithParticipantRecord() { + $mut = new CiviMailUtils( $this, true ); + $mut->clearMessages(); + $this->createLoggedInUser(); + $contributionID = $this->createPendingParticipantContribution(); + $apiResult = $this->callAPISuccess('contribution', 'completetransaction', array( + 'id' => $contributionID, + ) + ); + $participantStatus = $this->callAPISuccessGetValue('participant', array('id' => $this->ids['participant'], 'return' => 'participant_status_id')); + $this->assertEquals(1, $participantStatus); + $mut->checkMailLog(array( + 'Annual CiviCRM meet', + 'Event', + 'This letter is a confirmation that your registration has been received and your status has been updated to registered for the following', + )); + $mut->stop(); + + } + + /** * Test sending a mail via the API */ function testSendMail() { @@ -1426,6 +1476,28 @@ class api_v3_ContributionTest extends CiviUnitTestCase { } } + /** + * Create a pending contribution & linked pending participant record + * (along with an event) + */ + function createPendingParticipantContribution(){ + $event = $this->eventCreate(array('is_email_confirm' => 1, 'confirm_from_email' => 'test@civicrm.org',)); + $participantID = $this->participantCreate(array('event_id' => $event['id'], 'status_id' => 6)); + $this->ids['participant'] = $participantID; + $params = array_merge($this->_params, array('contribution_status_id' => 2, 'financial_type_id' => 'Event Fee')); + $contribution = $this->callAPISuccess('contribution','create', $params); + $this->callAPISuccess('participant_payment', 'create', array('contribution_id' => $contribution['id'], 'participant_id' => $participantID)); + $lineItem = $this->callAPISuccess('line_item', 'get', array( + 'entity_id' => $contribution['id'], + 'entity_table' => 'civicrm_contribution', + 'api.line_item.create' => array( + 'entity_id' => $participantID, + 'entity_table' => 'civicrm_participant', + ), + )); + return $contribution['id']; + } + function _getFinancialTrxnAmount($contId) { $query = "SELECT SUM( ft.total_amount ) AS total -- 2.25.1