Merge pull request #8119 from eileenmcnaughton/CRM-18303
[civicrm-core.git] / tests / phpunit / api / v3 / ContributionTest.php
index 927ee6d853f2a8a262e238f8dcbc27e6b7acbf76..7d482022300fb6cc3c9b5bf24805aec6bba61f18 100644 (file)
@@ -3,7 +3,7 @@
  +--------------------------------------------------------------------+
  | CiviCRM version 4.7                                                |
  +--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2015                                |
+ | Copyright CiviCRM LLC (c) 2004-2016                                |
  +--------------------------------------------------------------------+
  | This file is a part of CiviCRM.                                    |
  |                                                                    |
  +--------------------------------------------------------------------+
  */
 
-require_once 'CiviTest/CiviUnitTestCase.php';
-require_once 'CiviTest/CiviMailUtils.php';
-
-
 /**
  *  Test APIv3 civicrm_contribute_* functions
  *
  * @package CiviCRM_APIv3
  * @subpackage API_Contribution
+ * @group headless
  */
 class api_v3_ContributionTest extends CiviUnitTestCase {
 
@@ -70,6 +67,11 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
    */
   protected $_eventID;
 
+  /**
+   * @var CiviMailUtils
+   */
+  protected $mut;
+
   /**
    * Setup function.
    */
@@ -1071,6 +1073,108 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     )));
   }
 
+  /**
+   * Refund a contribution for a financial type with a contra account.
+   *
+   * CRM-17951 the contra account is a financial account with a relationship to a
+   * financial type. It is not always configured but should be reflected
+   * in the financial_trxn & financial_item table if it is.
+   */
+  public function testCreateUpdateChargebackContributionDefaultAccount() {
+    $contribution = $this->callAPISuccess('Contribution', 'create', $this->_params);
+    $this->callAPISuccess('Contribution', 'create', array(
+      'id' => $contribution['id'],
+      'contribution_status_id' => 'Chargeback',
+    ));
+    $this->callAPISuccessGetSingle('Contribution', array('contribution_status_id' => 'Chargeback'));
+
+    $lineItems = $this->callAPISuccessGetSingle('LineItem', array(
+      'contribution_id' => $contribution['id'],
+      'api.FinancialItem.getsingle' => array('amount' => array('<' => 0)),
+    ));
+    $this->assertEquals(1, $lineItems['api.FinancialItem.getsingle']['financial_account_id']);
+    $this->callAPISuccessGetSingle('FinancialTrxn', array(
+      'total_amount' => -100,
+      'status_id' => 'Chargeback',
+      'to_financial_account_id' => 6,
+    ));
+  }
+
+  /**
+   * Refund a contribution for a financial type with a contra account.
+   *
+   * CRM-17951 the contra account is a financial account with a relationship to a
+   * financial type. It is not always configured but should be reflected
+   * in the financial_trxn & financial_item table if it is.
+   */
+  public function testCreateUpdateChargebackContributionCustomAccount() {
+    $financialAccount = $this->callAPISuccess('FinancialAccount', 'create', array(
+      'name' => 'Chargeback Account',
+      'is_active' => TRUE,
+    ));
+
+    $entityFinancialAccount = $this->callAPISuccess('EntityFinancialAccount', 'create', array(
+      'entity_id' => $this->_financialTypeId,
+      'entity_table' => 'civicrm_financial_type',
+      'account_relationship' => 'Chargeback Account is',
+      'financial_account_id' => 'Chargeback Account',
+    ));
+
+    $contribution = $this->callAPISuccess('Contribution', 'create', $this->_params);
+    $this->callAPISuccess('Contribution', 'create', array(
+      'id' => $contribution['id'],
+      'contribution_status_id' => 'Chargeback',
+    ));
+    $this->callAPISuccessGetSingle('Contribution', array('contribution_status_id' => 'Chargeback'));
+
+    $lineItems = $this->callAPISuccessGetSingle('LineItem', array(
+      'contribution_id' => $contribution['id'],
+      'api.FinancialItem.getsingle' => array('amount' => array('<' => 0)),
+    ));
+    $this->assertEquals($financialAccount['id'], $lineItems['api.FinancialItem.getsingle']['financial_account_id']);
+
+    $this->callAPISuccess('Contribution', 'delete', array('id' => $contribution['id']));
+    $this->callAPISuccess('EntityFinancialAccount', 'delete', array('id' => $entityFinancialAccount['id']));
+    $this->callAPISuccess('FinancialAccount', 'delete', array('id' => $financialAccount['id']));
+  }
+
+  /**
+   * Refund a contribution for a financial type with a contra account.
+   *
+   * CRM-17951 the contra account is a financial account with a relationship to a
+   * financial type. It is not always configured but should be reflected
+   * in the financial_trxn & financial_item table if it is.
+   */
+  public function testCreateUpdateRefundContributionConfiguredContraAccount() {
+    $financialAccount = $this->callAPISuccess('FinancialAccount', 'create', array(
+      'name' => 'Refund Account',
+      'is_active' => TRUE,
+    ));
+
+    $entityFinancialAccount = $this->callAPISuccess('EntityFinancialAccount', 'create', array(
+      'entity_id' => $this->_financialTypeId,
+      'entity_table' => 'civicrm_financial_type',
+      'account_relationship' => 'Credit/Contra Revenue Account is',
+      'financial_account_id' => 'Refund Account',
+    ));
+
+    $contribution = $this->callAPISuccess('Contribution', 'create', $this->_params);
+    $this->callAPISuccess('Contribution', 'create', array(
+      'id' => $contribution['id'],
+      'contribution_status_id' => 'Refunded',
+    ));
+
+    $lineItems = $this->callAPISuccessGetSingle('LineItem', array(
+      'contribution_id' => $contribution['id'],
+      'api.FinancialItem.getsingle' => array('amount' => array('<' => 0)),
+    ));
+    $this->assertEquals($financialAccount['id'], $lineItems['api.FinancialItem.getsingle']['financial_account_id']);
+
+    $this->callAPISuccess('Contribution', 'delete', array('id' => $contribution['id']));
+    $this->callAPISuccess('EntityFinancialAccount', 'delete', array('id' => $entityFinancialAccount['id']));
+    $this->callAPISuccess('FinancialAccount', 'delete', array('id' => $financialAccount['id']));
+  }
+
   /**
    * Function tests that trxn_id is set when passed in.
    *
@@ -1473,19 +1577,30 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
    */
   public function testCompleteTransaction() {
     $mut = new CiviMailUtils($this, TRUE);
+    $this->swapMessageTemplateForTestTemplate();
     $this->createLoggedInUser();
     $params = array_merge($this->_params, array('contribution_status_id' => 2));
     $contribution = $this->callAPISuccess('contribution', 'create', $params);
     $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']);
+    $contribution = $this->callAPISuccess('contribution', 'getsingle', array('id' => $contribution['id']));
+    $this->assertEquals('SSF', $contribution['contribution_source']);
+    $this->assertEquals('Completed', $contribution['contribution_status']);
+    $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($contribution['receipt_date'])));
     $mut->checkMailLog(array(
-      'Receipt - Contribution',
-      'Please print this confirmation for your records.',
+      'email:::anthony_anderson@civicrm.org',
+      'is_monetary:::1',
+      'amount:::100.00',
+      'currency:::USD',
+      'receive_date:::' . date('Ymd', strtotime($contribution['receive_date'])),
+      'receipt_date:::' . date('Ymd'),
+      'contributeMode:::notify',
+      'title:::Contribution',
+      'displayName:::Mr. Anthony Anderson II',
     ));
     $mut->stop();
+    $this->revertTemplateToReservedTemplate();
   }
 
   /**
@@ -1514,22 +1629,7 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
    * Test repeat contribution successfully creates line items.
    */
   public function testRepeatTransaction() {
-    $paymentProcessorID = $this->paymentProcessorCreate();
-    $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', array(
-      'contact_id' => $this->_individualId,
-      'installments' => '12',
-      'frequency_interval' => '1',
-      'amount' => '500',
-      'contribution_status_id' => 1,
-      'start_date' => '2012-01-01 00:00:00',
-      'currency' => 'USD',
-      'frequency_unit' => 'month',
-      'payment_processor_id' => $paymentProcessorID,
-    ));
-    $originalContribution = $this->callAPISuccess('contribution', 'create', array_merge(
-      $this->_params,
-      array('contribution_recur_id' => $contributionRecur['id']))
-    );
+    $originalContribution = $this->setUpRepeatTransaction();
 
     $this->callAPISuccess('contribution', 'repeattransaction', array(
       'original_contribution_id' => $originalContribution['id'],
@@ -1564,6 +1664,35 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     $this->quickCleanUpFinancialEntities();
   }
 
+  /**
+   * Test repeat contribution successfully creates line items.
+   */
+  public function testRepeatTransactionIsTest() {
+    $this->_params['is_test'] = 1;
+    $originalContribution = $this->setUpRepeatTransaction(array('is_test' => 1));
+
+    $this->callAPISuccess('contribution', 'repeattransaction', array(
+      'original_contribution_id' => $originalContribution['id'],
+      'contribution_status_id' => 'Completed',
+      'trxn_id' => uniqid(),
+    ));
+    $this->callAPISuccessGetCount('Contribution', array('contribution_test' => 1), 2);
+  }
+
+  /**
+   * Test repeat contribution passed in status.
+   */
+  public function testRepeatTransactionPassedInStatus() {
+    $originalContribution = $this->setUpRepeatTransaction();
+
+    $this->callAPISuccess('contribution', 'repeattransaction', array(
+      'original_contribution_id' => $originalContribution['id'],
+      'contribution_status_id' => 'Pending',
+      'trxn_id' => uniqid(),
+    ));
+    $this->callAPISuccessGetCount('Contribution', array('contribution_status_id' => 2), 1);
+  }
+
   /**
    * Test repeat contribution accepts recur_id instead of original_contribution_id.
    */
@@ -1877,6 +2006,64 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     $mut->stop();
   }
 
+
+  /**
+   * Complete the transaction using the template with all the possible.
+   */
+  public function testCompleteTransactionWithTestTemplate() {
+    $this->swapMessageTemplateForTestTemplate();
+    $contribution = $this->setUpForCompleteTransaction();
+    $this->callAPISuccess('contribution', 'completetransaction', array(
+      'id' => $contribution['id'],
+      'trxn_date' => date('2011-04-09'),
+      'trxn_id' => 'kazam',
+    ));
+    $receive_date = $this->callAPISuccess('Contribution', 'getvalue', array('id' => $contribution['id'], 'return' => 'receive_date'));
+    $this->mut->checkMailLog(array(
+      'email:::anthony_anderson@civicrm.org',
+      'is_monetary:::1',
+      'amount:::100.00',
+      'currency:::USD',
+      'receive_date:::' . date('Ymd', strtotime($receive_date)),
+      'receipt_date:::' . date('Ymd'),
+      'contributeMode:::notify',
+      'title:::Contribution',
+      'displayName:::Mr. Anthony Anderson II',
+      'trxn_id:::kazam',
+      'contactID:::' . $this->_params['contact_id'],
+      'contributionID:::' . $contribution['id'],
+      'financialTypeId:::1',
+      'financialTypeName:::Donation',
+    ));
+    $this->mut->stop();
+    $this->revertTemplateToReservedTemplate();
+  }
+
+  /**
+   * Complete the transaction using the template with all the possible.
+   */
+  public function testCompleteTransactionContributionPageFromAddress() {
+    $contributionPage = $this->callAPISuccess('ContributionPage', 'create', array(
+      'receipt_from_name' => 'Mickey Mouse',
+      'receipt_from_email' => 'mickey@mouse.com',
+      'title' => "Test Contribution Page",
+      'financial_type_id' => 1,
+      'currency' => 'NZD',
+      'goal_amount' => 50,
+      'is_pay_later' => 1,
+      'is_monetary' => TRUE,
+      'is_email_receipt' => TRUE,
+    ));
+    $this->_params['contribution_page_id'] = $contributionPage['id'];
+    $contribution = $this->setUpForCompleteTransaction();
+    $this->callAPISuccess('contribution', 'completetransaction', array('id' => $contribution['id']));
+    $this->mut->checkMailLog(array(
+      'mickey@mouse.com',
+      'Mickey Mouse <',
+    ));
+    $this->mut->stop();
+  }
+
   /**
    * Test completing first transaction in a recurring series.
    *
@@ -1911,6 +2098,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.
    *
@@ -2191,6 +2410,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).
    */
@@ -2319,9 +2565,14 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
   }
 
   /**
+   * Check financial transaction.
+   *
+   * @todo break this down into sensible functions - most calls to it only use a few lines out of the big if.
+   *
    * @param array $contribution
    * @param string $context
    * @param int $instrumentId
+   * @param array $extraParams
    */
   public function _checkFinancialTrxn($contribution, $context, $instrumentId = NULL, $extraParams = array()) {
     $trxnParams = array(
@@ -2546,4 +2797,44 @@ class api_v3_ContributionTest extends CiviUnitTestCase {
     return $originalContribution;
   }
 
+  /**
+   * Set up a repeat transaction.
+   *
+   * @param array $recurParams
+   *
+   * @return array
+   */
+  protected function setUpRepeatTransaction($recurParams = array()) {
+    $paymentProcessorID = $this->paymentProcessorCreate();
+    $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', array_merge(array(
+      'contact_id' => $this->_individualId,
+      'installments' => '12',
+      'frequency_interval' => '1',
+      'amount' => '500',
+      'contribution_status_id' => 1,
+      'start_date' => '2012-01-01 00:00:00',
+      'currency' => 'USD',
+      'frequency_unit' => 'month',
+      'payment_processor_id' => $paymentProcessorID,
+    ), $recurParams));
+    $originalContribution = $this->callAPISuccess('contribution', 'create', array_merge(
+      $this->_params,
+      array('contribution_recur_id' => $contributionRecur['id']))
+    );
+    return $originalContribution;
+  }
+
+  /**
+   * Common set up routine.
+   *
+   * @return array
+   */
+  protected function setUpForCompleteTransaction() {
+    $this->mut = new CiviMailUtils($this, TRUE);
+    $this->createLoggedInUser();
+    $params = array_merge($this->_params, array('contribution_status_id' => 2, 'receipt_date' => 'now'));
+    $contribution = $this->callAPISuccess('contribution', 'create', $params);
+    return $contribution;
+  }
+
 }