CRM-18341 Pledges not being completed by completeTransaction
authoreileenmcnaugton <eileen@fuzion.co.nz>
Fri, 1 Apr 2016 04:24:12 +0000 (17:24 +1300)
committereileenmcnaugton <eileen@fuzion.co.nz>
Sun, 10 Apr 2016 20:56:08 +0000 (08:56 +1200)
CRM/Contribute/BAO/Contribution.php
CRM/Contribute/BAO/ContributionRecur.php
tests/phpunit/CiviTest/CiviUnitTestCase.php
tests/phpunit/api/v3/ContributionTest.php
xml/schema/Pledge/Pledge.xml
xml/schema/Pledge/PledgePayment.xml

index 3459480dd82db366b3ef1d4a0c4f2727b64fccc2..2e967673f99b04cf685b7f5e73eeaf3a82019ed0 100644 (file)
@@ -4353,6 +4353,7 @@ WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']})
     $participant = CRM_Utils_Array::value('participant', $objects);
     $memberships = CRM_Utils_Array::value('membership', $objects);
     $recurContrib = CRM_Utils_Array::value('contributionRecur', $objects);
+    $recurringContributionID = (empty($recurContrib->id)) ? NULL : $recurContrib->id;
     $event = CRM_Utils_Array::value('event', $objects);
 
     $completedContributionStatusID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed');
@@ -4363,8 +4364,8 @@ WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']})
     ), array_intersect_key($input, array_fill_keys($inputContributionWhiteList, 1)
     ));
 
-    if (!empty($recurContrib->id)) {
-      $contributionParams['contribution_recur_id'] = $recurContrib->id;
+    if ($recurringContributionID) {
+      $contributionParams['contribution_recur_id'] = $recurringContributionID;
     }
     $changeDate = CRM_Utils_Array::value('trxn_date', $input, date('YmdHis'));
 
@@ -4389,7 +4390,7 @@ WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']})
         // Figure out what we gain from this.
         CRM_Contribute_BAO_ContributionPage::setValues($contribution->contribution_page_id, $values);
       }
-      elseif ($recurContrib && $recurContrib->id) {
+      elseif ($recurContrib && $recurringContributionID) {
         $values['amount'] = $recurContrib->amount;
         $values['financial_type_id'] = $objects['contributionType']->id;
         $values['title'] = $source = ts('Offline Recurring Contribution');
@@ -4398,7 +4399,7 @@ WHERE eft.financial_trxn_id IN ({$trxnId}, {$baseTrxnId['financialTrxnId']})
         $values['receipt_from_email'] = $domainValues[1];
       }
 
-      if ($recurContrib && $recurContrib->id && !isset($input['is_email_receipt'])) {
+      if ($recurContrib && $recurringContributionID && !isset($input['is_email_receipt'])) {
         //CRM-13273 - is_email_receipt setting on recurring contribution should take precedence over contribution page setting
         // but CRM-16124 if $input['is_email_receipt'] is set then that should not be overridden.
         $values['is_email_receipt'] = $recurContrib->is_email_receipt;
@@ -4551,7 +4552,8 @@ LIMIT 1;";
     CRM_Core_Error::debug_log_message("Contribution record updated successfully");
     $transaction->commit();
 
-    CRM_Contribute_BAO_ContributionRecur::updateRecurLinkedPledge($contribution);
+    CRM_Contribute_BAO_ContributionRecur::updateRecurLinkedPledge($contribution->id, $recurringContributionID,
+      $input['contribution_status_id'], $input['total_amount']);
 
     // create an activity record
     if ($input['component'] == 'contribute') {
index 7478d39c52cd9ad24b3a9bb015b1fb5f108050e3..da44e17b04b6dd45e25a359ae32237f1f92fdd74 100644 (file)
@@ -692,13 +692,18 @@ INNER JOIN civicrm_contribution       con ON ( con.id = mp.contribution_id )
    * The pledge payment record should already exist & will need to be updated with the new contribution ID.
    * If not the contribution will also need to be linked to the pledge
    *
-   * @param CRM_Contribute_BAO_Contribution $contribution
+   * @param int $contributionID
+   * @param int $contributionRecurID
+   * @param int $contributionStatusID
+   * @param float $contributionAmount
+   *
+   * @throws \CiviCRM_API3_Exception
    */
-  public static function updateRecurLinkedPledge($contribution) {
+  public static function updateRecurLinkedPledge($contributionID, $contributionRecurID, $contributionStatusID, $contributionAmount) {
     $returnProperties = array('id', 'pledge_id');
     $paymentDetails = $paymentIDs = array();
 
-    if (CRM_Core_DAO::commonRetrieveAll('CRM_Pledge_DAO_PledgePayment', 'contribution_id', $contribution->id,
+    if (CRM_Core_DAO::commonRetrieveAll('CRM_Pledge_DAO_PledgePayment', 'contribution_id', $contributionID,
       $paymentDetails, $returnProperties
     )
     ) {
@@ -710,12 +715,12 @@ INNER JOIN civicrm_contribution       con ON ( con.id = mp.contribution_id )
     else {
       //payment is not already linked - if it is linked with a pledge we need to create a link.
       // return if it is not recurring contribution
-      if (!$contribution->contribution_recur_id) {
+      if (!$contributionRecurID) {
         return;
       }
 
       $relatedContributions = new CRM_Contribute_DAO_Contribution();
-      $relatedContributions->contribution_recur_id = $contribution->contribution_recur_id;
+      $relatedContributions->contribution_recur_id = $contributionRecurID;
       $relatedContributions->find();
 
       while ($relatedContributions->fetch()) {
@@ -740,18 +745,18 @@ INNER JOIN civicrm_contribution       con ON ( con.id = mp.contribution_id )
         // return now so we don't create a core error & roll back
         return;
       }
-      $paymentDetails['contribution_id'] = $contribution->id;
-      $paymentDetails['status_id'] = $contribution->contribution_status_id;
-      $paymentDetails['actual_amount'] = $contribution->total_amount;
+      $paymentDetails['contribution_id'] = $contributionID;
+      $paymentDetails['status_id'] = $contributionStatusID;
+      $paymentDetails['actual_amount'] = $contributionAmount;
 
       // put contribution against it
-      $payment = CRM_Pledge_BAO_PledgePayment::add($paymentDetails);
-      $paymentIDs[] = $payment->id;
+      $payment = civicrm_api3('PledgePayment', 'create', $paymentDetails);
+      $paymentIDs[] = $payment['id'];
     }
 
     // update pledge and corresponding payment statuses
-    CRM_Pledge_BAO_PledgePayment::updatePledgePaymentStatus($pledgeId, $paymentIDs, $contribution->contribution_status_id,
-      NULL, $contribution->total_amount
+    CRM_Pledge_BAO_PledgePayment::updatePledgePaymentStatus($pledgeId, $paymentIDs, $contributionStatusID,
+      NULL, $contributionAmount
     );
   }
 
index dd1a107c461f30ee857cbae9be41c88dd8747a42..68bd30ab7a2803fe4b50332794b3d738577fb78a 100644 (file)
@@ -2498,6 +2498,7 @@ AND    ( TABLE_NAME LIKE 'civicrm_value_%' )
       'civicrm_participant',
       'civicrm_participant_payment',
       'civicrm_pledge',
+      'civicrm_pledge_payment',
       'civicrm_price_set_entity',
       'civicrm_price_field_value',
       'civicrm_price_field',
index d536229bd8dbc36e1582b108a064b056722160cd..3ec831da6e8da46f30dda358286cb7a520d40790 100644 (file)
@@ -2027,6 +2027,38 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     $this->assertEquals(date('Y-m-d 00:00:00', strtotime('+1 month')), $contributionRecur['next_sched_contribution_date']);
   }
 
+  /**
+   * Test completing a pledge with the completeTransaction api..
+   *
+   * Note that we are creating a logged in user because email goes out from
+   * that person.
+   */
+  public function testCompleteTransactionUpdatePledgePayment() {
+    $mut = new CiviMailUtils($this, TRUE);
+    $mut->clearMessages();
+    $this->createLoggedInUser();
+    $contributionID = $this->createPendingPledgeContribution();
+    $this->callAPISuccess('contribution', 'completetransaction', array(
+      'id' => $contributionID,
+      'trxn_date' => '1 Feb 2013',
+    ));
+    $pledge = $this->callAPISuccessGetSingle('Pledge', array(
+      'id' => $this->_ids['pledge'],
+    ));
+    $this->assertEquals('Completed', $pledge['pledge_status']);
+
+    $status = $this->callAPISuccessGetValue('PledgePayment', array(
+      'pledge_id' => $this->_ids['pledge'],
+      'return' => 'status_id',
+    ));
+    $this->assertEquals(1, $status);
+    $mut->checkMailLog(array(
+      '$ 500.00',
+      'May 11th, 2012 12:00 AM',
+    ));
+    $mut->stop();
+  }
+
   /**
    * Test completing a transaction with an event via the API.
    *
@@ -2307,6 +2339,33 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     }
   }
 
+  /**
+   * Create a pending contribution & linked pending pledge record.
+   */
+  public function createPendingPledgeContribution() {
+
+    $pledgeID = $this->pledgeCreate(array('contact_id' => $this->_individualId, 'installments' => 1, 'amount' => 500));
+    $this->_ids['pledge'] = $pledgeID;
+    $contribution = $this->callAPISuccess('contribution', 'create', array_merge($this->_params, array(
+      'contribution_status_id' => 'Pending',
+       'total_amount' => 500,
+      ))
+    );
+    $paymentID = $this->callAPISuccessGetValue('PledgePayment', array(
+      'options' => array('limit' => 1),
+      'return' => 'id',
+    ));
+    $this->callAPISuccess('PledgePayment', 'create', array(
+      'id' => $paymentID,
+      'contribution_id' =>
+      $contribution['id'],
+      'status_id' => 'Pending',
+      'scheduled_amount' => 500,
+    ));
+
+    return $contribution['id'];
+  }
+
   /**
    * Create a pending contribution & linked pending participant record (along with an event).
    */
index e407d86c70e903757bcff3625fa79c068d4cb05a..56b61580d482c93b9ee31ed0323bd15e653e4394 100644 (file)
     <import>true</import>
     <export>false</export>
     <type>int unsigned</type>
+    <pseudoconstant>
+      <optionGroupName>contribution_status</optionGroupName>
+    </pseudoconstant>
     <comment>Implicit foreign key to civicrm_option_values in the contribution_status option group.</comment>
     <add>2.1</add>
   </field>
index 7a79f476f6ab823a35987e77b4578b1104456478..c646bb5aa9752ef54f127024a827922d7251ebf1 100644 (file)
     <export>false</export>
     <type>int unsigned</type>
     <add>2.1</add>
+    <pseudoconstant>
+      <optionGroupName>contribution_status</optionGroupName>
+    </pseudoconstant>
   </field>
   <index>
     <name>index_status</name>