CRM-12984 add contribution.completetransaction api
authoreileen <eileen@fuzion.co.nz>
Tue, 2 Jul 2013 03:59:08 +0000 (15:59 +1200)
committereileen <eileen@fuzion.co.nz>
Tue, 2 Jul 2013 03:59:08 +0000 (15:59 +1200)
CRM/Core/DAO/permissions.php
api/v3/Contribution.php
tests/phpunit/api/v3/ContributionTest.php

index 5112e0274ffba78ad7090509566abdafab41712f..81dcd55ea56a3d9738fa4e291d641afcde862df2 100644 (file)
@@ -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',
index 0d774014158b61f893a2720119d306173d4c4b94..09542ddf2a082b75045e9089255800149a11cb68 100644 (file)
@@ -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) {
+
+}
index 12c30c5749ae0da5c55ef512f29655a74b4772ee..94a43dff00ed7335f8b0f64b644100f0d8b1d58c 100644 (file)
@@ -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