CRM-17718 update repeattransaction to permit the financial_type_id to be passed in
authoreileenmcnaughton <eileen@fuzion.co.nz>
Wed, 16 Dec 2015 17:04:19 +0000 (17:04 +0000)
committereileen <emcnaughton@wikimedia.org>
Wed, 23 Dec 2015 20:44:05 +0000 (09:44 +1300)
CRM/Contribute/BAO/Contribution.php
CRM/Contribute/BAO/ContributionRecur.php
api/v3/Contribution.php
tests/phpunit/api/v3/ContributionTest.php

index 2e64f674edebf45ff5a0df21fd20973a3fdb4e36..3fc2f4ca4bddcd6f1fab3fa04fef75603ebf00d2 100644 (file)
@@ -2052,7 +2052,13 @@ LEFT JOIN  civicrm_contribution contribution ON ( componentPayment.contribution_
 
       $contributionParams['skipLineItem'] = TRUE;
       $contributionParams['status_id'] = 'Pending';
-      $contributionParams['financial_type_id'] = $templateContribution['financial_type_id'];
+      if (isset($contributionParams['financial_type_id'])) {
+        // Give precedence to passed in type.
+        $contribution->financial_type_id = $contributionParams['financial_type_id'];
+      }
+      else {
+        $contributionParams['financial_type_id'] = $templateContribution['financial_type_id'];
+      }
       $contributionParams['contact_id'] = $templateContribution['contact_id'];
       $contributionParams['source'] = empty($templateContribution['source']) ? ts('Recurring contribution') : $templateContribution['source'];
       $createContribution = civicrm_api3('Contribution', 'create', $contributionParams);
@@ -4169,6 +4175,20 @@ WHERE con.id = {$contributionId}
     }
   }
 
+  /**
+   * Is there only one line item attached to the contribution.
+   *
+   * @param int $id
+   *   Contribution ID.
+   *
+   * @return bool
+   * @throws \CiviCRM_API3_Exception
+   */
+  public static function isSingleLineItem($id) {
+    $lineItemCount = civicrm_api3('LineItem', 'getcount', array('id' => $id));
+    return ($lineItemCount == 1);
+  }
+
   /**
    * Complete an order.
    *
@@ -4206,6 +4226,9 @@ WHERE con.id = {$contributionId}
       'campaign_id',
       'receive_date',
     );
+    if (self::isSingleLineItem($primaryContributionID)) {
+      $inputContributionWhiteList[] = 'financial_type_id';
+    }
 
     $contributionParams = array_merge(array(
       'contribution_status_id' => 'Completed',
index a5e5add641ea5de1c47677171901d33019749936..b5a94192c47b39f8ed58d972436d434449ba6eb9 100644 (file)
@@ -590,6 +590,10 @@ INNER JOIN civicrm_contribution       con ON ( con.id = mp.contribution_id )
     $lineItems = CRM_Price_BAO_LineItem::getLineItemsByContributionID($originalContributionID);
     if (count($lineItems) == 1) {
       foreach ($lineItems as $index => $lineItem) {
+        if (isset($contribution->financial_type_id)) {
+          // CRM-17718 allow for possibility of changed financial type ID having been set prior to calling this.
+          $lineItems[$index]['financial_type_id'] = $contribution->financial_type_id;
+        }
         if ($lineItem['line_total'] != $contribution->total_amount) {
           // We are dealing with a changed amount! Per CRM-16397 we can work out what to do with these
           // if there is only one line item, and the UI should prevent this situation for those with more than one.
index 27d6bf3aa1417096d7b1abb26673b0c2a4e60871..ef1efa9973148326acb0674e701ad37f4a8eb493 100644 (file)
@@ -559,7 +559,7 @@ function civicrm_api3_contribution_repeattransaction(&$params) {
     $contribution->contribution_status_id = $params['contribution_status_id'];
     $contribution->receive_date = $params['receive_date'];
 
-    $passThroughParams = array('trxn_id', 'total_amount', 'campaign_id', 'fee_amount');
+    $passThroughParams = array('trxn_id', 'total_amount', 'campaign_id', 'fee_amount', 'financial_type_id');
     $input = array_intersect_key($params, array_fill_keys($passThroughParams, NULL));
 
     $params = _ipn_process_transaction($params, $contribution, $input, $ids, $original_contribution);
@@ -670,6 +670,16 @@ function _civicrm_api3_contribution_repeattransaction_spec(&$params) {
       'labelColumn' => 'title',
     ),
   );
+  $params['financial_type_id'] = array(
+    'title' => 'Financial ID (ignored if more than one line item)',
+    'name' => 'financial_type_id',
+    'type' => CRM_Utils_Type::T_INT,
+    'pseudoconstant' => array(
+      'table' => 'civicrm_financial_type',
+      'keyColumn' => 'id',
+      'labelColumn' => 'name',
+    ),
+  );
   $params['payment_processor_id'] = array(
     'description' => ts('Payment processor ID, will be loaded from contribution_recur if not provided'),
     'title' => 'Payment processor ID',
index c8e5ea3b91c9f4054093b62168629e7d9cd20c33..565cd20689ef70dc0b3d99994578141ac7277690 100644 (file)
@@ -1550,6 +1550,57 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     $this->assertEquals($expectedLineItem, $lineItem2['values'][0]);
   }
 
+  /**
+   * CRM-17718 test appropriate action if financial type has changed for single line items.
+   */
+  public function testRepeatTransactionPassedInFinancialType() {
+    $originalContribution = $this->setUpRecurringContribution();
+
+    $this->callAPISuccess('contribution', 'repeattransaction', array(
+      'original_contribution_id' => $originalContribution['id'],
+      'contribution_status_id' => 'Completed',
+      'trxn_id' => uniqid(),
+      'financial_type_id' => 2,
+    ));
+    $lineItemParams = array(
+      'entity_id' => $originalContribution['id'],
+      'sequential' => 1,
+      'return' => array(
+        'entity_table',
+        'qty',
+        'unit_price',
+        'line_total',
+        'label',
+        'financial_type_id',
+        'deductible_amount',
+        'price_field_value_id',
+        'price_field_id',
+      ),
+    );
+
+    $this->callAPISuccessGetSingle('contribution', array(
+      'total_amount' => 100,
+      'financial_type_id' => 2,
+    ));
+    $lineItem1 = $this->callAPISuccess('line_item', 'get', array_merge($lineItemParams, array(
+      'entity_id' => $originalContribution['id'],
+    )));
+    $expectedLineItem = array_merge(
+      $lineItem1['values'][0], array(
+        'line_total' => '100.00',
+        'unit_price' => '100.00',
+        'financial_type_id' => 2,
+      )
+    );
+
+    $lineItem2 = $this->callAPISuccess('line_item', 'get', array_merge($lineItemParams, array(
+      'entity_id' => $originalContribution['id'] + 1,
+    )));
+    unset($expectedLineItem['id'], $expectedLineItem['entity_id']);
+    unset($lineItem2['values'][0]['id'], $lineItem2['values'][0]['entity_id']);
+    $this->assertEquals($expectedLineItem, $lineItem2['values'][0]);
+  }
+
   /**
    * CRM-16397 test appropriate action if campaign has been passed in.
    */
@@ -2301,4 +2352,34 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     }
   }
 
+  /**
+   * Set up the basic recurring contribution for tests.
+   *
+   * @param array $generalParams
+   *   Parameters that can be merged into the recurring AND the contribution.
+   *   (potentially add extra params if later we only want to merge to one).
+   *
+   * @return array|int
+   */
+  protected function setUpRecurringContribution($generalParams = array()) {
+    $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', array_merge(array(
+      'contact_id' => $this->_individualId,
+      'installments' => '12',
+      'frequency_interval' => '1',
+      'amount' => '100',
+      'contribution_status_id' => 1,
+      'start_date' => '2012-01-01 00:00:00',
+      'currency' => 'USD',
+      'frequency_unit' => 'month',
+      'payment_processor_id' => $this->paymentProcessorID,
+    ), $generalParams));
+    $originalContribution = $this->callAPISuccess('contribution', 'create', array_merge(
+      $this->_params,
+      array(
+        'contribution_recur_id' => $contributionRecur['id'],
+      ), $generalParams)
+    );
+    return $originalContribution;
+  }
+
 }