CRM-16259, changes for pending status for adding payments and added unit test
authorPradeep Nayak <pradpnayak@gmail.com>
Wed, 27 Jan 2016 22:32:27 +0000 (04:02 +0530)
committerPradeep Nayak <pradpnayak@gmail.com>
Wed, 17 Feb 2016 12:33:28 +0000 (18:03 +0530)
CRM-16259#

----------------------------------------
* CRM-16259: Create Payment API
  https://issues.civicrm.org/jira/browse/CRM-16259

Conflicts:

tests/phpunit/api/v3/PaymentTest.php

api/v3/Payment.php
tests/phpunit/api/v3/PaymentTest.php

index 4de75452217b58aa2289f0ce75632260e74f8e68..ade66f0f22812472d5fe1184fb8d765bd50f2d25 100644 (file)
@@ -134,51 +134,72 @@ function civicrm_api3_payment_create(&$params) {
   }
   // Get contribution
   $contribution = civicrm_api3('Contribution', 'getsingle', array('id' => $params['contribution_id']));
-  if ($contribution['contribution_status'] != 'Partially paid') {
-    throw new API_Exception('Please select a contribution which has a partial payment');
+  $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
+  if ($contributionStatus[$contribution['contribution_status_id']] != 'Partially paid'
+    && !($contributionStatus[$contribution['contribution_status_id']] = 'Pending' && $contribution['is_pay_later'] == TRUE)
+  ) {
+    throw new API_Exception('Please select a contribution which has a partial or pending payment');
   }
   else {
-    $trxn = CRM_Contribute_BAO_Contribution::recordPartialPayment($contribution, $params);
-    $paid = CRM_Core_BAO_FinancialTrxn::getTotalPayments($params['contribution_id']);
-    $total = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution', $params['contribution_id'], 'total_amount');
-    $cmp = bccomp($total, $paid, 5);
-    if ($cmp == 0 || $cmp == -1) {// If paid amount is greater or equal to total amount
-      civicrm_api3('Contribution', 'completetransaction', array('id' => $contribution['id']));
+    // Check if pending contribution
+    $fullyPaidPayLater = FALSE;
+    if ($contributionStatus[$contribution['contribution_status_id']] == 'Pending') {
+      $cmp = bccomp($contribution['total_amount'], $params['total_amount'], 5);
+      // Total payment amount is the whole amount paid against pending contribution
+      if ($cmp == 0 || $cmp == -1) {
+        civicrm_api3('Contribution', 'completetransaction', array('id' => $contribution['id']));
+        // Get the trxn
+        $trxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contribution['id'], 'DESC');
+        $ftParams = array('id' => $trxnId['financialTrxnId']);
+        $trxn = CRM_Core_BAO_FinancialTrxn::retrieve($ftParams, CRM_Core_DAO::$_nullArray);
+        $fullyPaidPayLater = TRUE;
+      }
+      else {
+        civicrm_api3('Contribution', 'create', 
+          array(
+           'id' => $contribution['id'],
+           'contribution_status_id' => array_search('Partially paid', $contributionStatus),
+          )
+        );
+      }
     }
-  }
-  if (CRM_Utils_Array::value('line_item', $params) && !empty($trxn)) {
-    foreach ($params['line_item'] as $values) {
-      foreach ($values as $id => $amount) {
-        $p = array('id' => $id);
-        $check = CRM_Price_BAO_LineItem::retrieve($p, $defaults);
-        if (empty($check)) {
-          throw new API_Exception('Please specify a valid Line Item.');
+    if (!$fullyPaidPayLater) {
+      $trxn = CRM_Core_BAO_FinancialTrxn::getPartialPaymentTrxn($contribution, $params);
+      if (CRM_Utils_Array::value('line_item', $params) && !empty($trxn)) {
+        foreach ($params['line_item'] as $values) {
+          foreach ($values as $id => $amount) {
+            $p = array('id' => $id);
+            $check = CRM_Price_BAO_LineItem::retrieve($p, $defaults);
+            if (empty($check)) {
+              throw new API_Exception('Please specify a valid Line Item.');
+            }
+            // get financial item
+            $sql = "SELECT fi.id
+              FROM civicrm_financial_item fi
+              INNER JOIN civicrm_line_item li ON li.id = fi.entity_id
+              WHERE li.contribution_id = %1 AND li.id = %2";
+            $sqlParams = array(
+              1 => array($params['contribution_id'], 'Integer'),
+              2 => array($id, 'Integer'),
+            );
+            $fid = CRM_Core_DAO::singleValueQuery($sql, $sqlParams);
+            // Record Entity Financial Trxn
+            $eftParams = array(
+              'entity_table' => 'civicrm_financial_item',
+              'financial_trxn_id' => $trxn->id,
+              'amount' => $amount,
+              'entity_id' => $fid,
+            );
+            civicrm_api3('EntityFinancialTrxn', 'create', $eftParams);
+          }
         }
-        // get financial item
-        $sql = "SELECT fi.id
-          FROM civicrm_financial_item fi
-          INNER JOIN civicrm_line_item li ON li.id = fi.entity_id
-          WHERE li.contribution_id = %1 AND li.id = %2";
-        $sqlParams = array(
-          1 => array($params['contribution_id'], 'Integer'),
-          2 => array($id, 'Integer'),
-        );
-        $fid = CRM_Core_DAO::singleValueQuery($sql, $sqlParams);
-        // Record Entity Financial Trxn
-        $eftParams = array(
-          'entity_table' => 'civicrm_financial_item',
-          'financial_trxn_id' => $trxn->id,
-          'amount' => $amount,
-          'entity_id' => $fid,
-        );
-        civicrm_api3('EntityFinancialTrxn', 'create', $eftParams);
+      }
+      elseif (!empty($trxn)) {
+        // Assign the lineitems proportionally
+        CRM_Contribute_BAO_Contribution::assignProportionalLineItems($params, $trxn, $contribution);
       }
     }
   }
-  elseif (!empty($trxn)) {
-    // Assign the lineitems proportionally
-    CRM_Contribute_BAO_Contribution::assignProportionalLineItems($params, $trxn, $contribution);
-  }
   $values = array();
   _civicrm_api3_object_to_array_unique_fields($trxn, $values[$trxn->id]);
   return civicrm_api3_create_success($values, $params, 'Payment', 'create', $trxn);
index 3ad33a73801cbd4b6d8bcc5b56692fc53645ae43..672e54eab75b7face8e9362aff7a3290fb601200 100644 (file)
@@ -84,16 +84,19 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
     $payment = $this->callAPIFailure('payment', 'get', $params, 'API permission check failed for Payment/get call; insufficient permission: require access CiviCRM and access CiviContribute');
 
     array_push(CRM_Core_Config::singleton()->userPermissionClass->permissions, 'access CiviContribute');
+    $payment = $this->callAPISuccess('payment', 'get', $params);
 
     $payment = $this->callAPIAndDocument('payment', 'get', $params, __FUNCTION__, __FILE__);
     $this->assertEquals(1, $payment['count']);
 
     $expectedResult = array(
-      'total_amount' => 100,
-      'trxn_id' => 23456,
-      'trxn_date' => '2010-01-20 00:00:00',
-      'contribution_id' => $contribution['id'],
-      'is_payment' => 1,
+      $contribution['id'] => array(
+        'total_amount' => 100,
+        'trxn_id' => 23456,
+        'trxn_date' => '2010-01-20 00:00:00',
+        'contribution_id' => $contribution['id'],
+        'is_payment' => 1,
+      ),
     );
     $this->checkPaymentResult($payment, $expectedResult);
     $this->callAPISuccess('Contribution', 'Delete', array(
@@ -112,13 +115,15 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
       'contribution_id' => $contribution['id'],
       'total_amount' => 50,
     );
-    $payment = $this->callAPIAndDocument('payment', 'create', $params, __FUNCTION__, __FILE__);
+    $payment = $this->callAPISuccess('payment', 'create', $params);
     $expectedResult = array(
-      'from_financial_account_id' => 7,
-      'to_financial_account_id' => 6,
-      'total_amount' => 50,
-      'status_id' => 1,
-      'is_payment' => 1,
+      $payment['id'] => array(
+        'from_financial_account_id' => 7,
+        'to_financial_account_id' => 6,
+        'total_amount' => 50,
+        'status_id' => 1,
+        'is_payment' => 1,
+      ),
     );
     $this->checkPaymentResult($payment, $expectedResult);
 
@@ -148,13 +153,15 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
       'contribution_id' => $contribution['id'],
       'total_amount' => 100,
     );
-    $payment = $this->callAPIAndDocument('payment', 'create', $params, __FUNCTION__, __FILE__);
+    $payment = $this->callAPISuccess('payment', 'create', $params);
     $expectedResult = array(
-      'from_financial_account_id' => 7,
-      'to_financial_account_id' => 6,
-      'total_amount' => 100,
-      'status_id' => 1,
-      'is_payment' => 1,
+      $payment['id'] => array(
+        'from_financial_account_id' => 7,
+        'to_financial_account_id' => 6,
+        'total_amount' => 100,
+        'status_id' => 1,
+        'is_payment' => 1,
+      ),
     );
     $this->checkPaymentResult($payment, $expectedResult);
     $params = array(
@@ -186,7 +193,7 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
    * Function to assert db values
    */
   public function checkPaymentResult($payment, $expectedResult) {
-    foreach ($expectedResult as $key => $value) {
+    foreach ($expectedResult[$payment['id']] as $key => $value) {
       $this->assertEquals($payment['values'][$payment['id']][$key], $value);
     }
   }
@@ -207,13 +214,15 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
     foreach ($lineItems['values'] as $id => $ignore) {
       $params['line_item'][] = array($id => array_pop($amounts));
     }
-    $payment = $this->callAPIAndDocument('payment', 'create', $params, __FUNCTION__, __FILE__);
+    $payment = $this->callAPISuccess('payment', 'create', $params);
     $expectedResult = array(
-      'from_financial_account_id' => 7,
-      'to_financial_account_id' => 6,
-      'total_amount' => 50,
-      'status_id' => 1,
-      'is_payment' => 1,
+      $payment['id'] => array(
+        'from_financial_account_id' => 7,
+        'to_financial_account_id' => 6,
+        'total_amount' => 50,
+        'status_id' => 1,
+        'is_payment' => 1,
+      ),
     );
     $this->checkPaymentResult($payment, $expectedResult);
 
@@ -247,13 +256,15 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
     foreach ($lineItems['values'] as $id => $ignore) {
       $params['line_item'][] = array($id => array_pop($amounts));
     }
-    $payment = $this->callAPIAndDocument('payment', 'create', $params, __FUNCTION__, __FILE__);
+    $payment = $this->callAPISuccess('payment', 'create', $params);
     $expectedResult = array(
-      'from_financial_account_id' => 7,
-      'to_financial_account_id' => 6,
-      'total_amount' => 100,
-      'status_id' => 1,
-      'is_payment' => 1,
+      $payment['id'] => array(
+        'from_financial_account_id' => 7,
+        'to_financial_account_id' => 6,
+        'total_amount' => 100,
+        'status_id' => 1,
+        'is_payment' => 1,
+      ),
     );
     $this->checkPaymentResult($payment, $expectedResult);
     $params = array(
@@ -303,9 +314,9 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
 
     array_push(CRM_Core_Config::singleton()->userPermissionClass->permissions, 'access CiviCRM', 'edit contributions');
 
-    $this->callAPIAndDocument('payment', 'cancel', $cancelParams, __FUNCTION__, __FILE__);
+    $this->callAPIAndDocument('payment', 'cancel', $cancelParams);
 
-    $payment = $this->callAPIAndDocument('payment', 'get', $params, __FUNCTION__, __FILE__);
+    $payment = $this->callAPISuccess('payment', 'get', $params);
     $this->assertEquals(2, $payment['count']);
     $amounts = array(-150.00, 150.00);
     foreach ($payment['values'] as $value) {
@@ -328,7 +339,7 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
       'contribution_id' => $contribution['id'],
     );
 
-    $payment = $this->callAPIAndDocument('payment', 'get', $params, __FUNCTION__, __FILE__);
+    $payment = $this->callAPISuccess('payment', 'get', $params);
     $this->assertEquals(1, $payment['count']);
 
     $deleteParams = array(
@@ -338,9 +349,9 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
     $payment = $this->callAPIFailure('payment', 'delete', $deleteParams, 'API permission check failed for Payment/get call; insufficient permission: require access CiviCRM and delete in CiviContribute');
 
     array_push(CRM_Core_Config::singleton()->userPermissionClass->permissions, 'access CiviCRM', 'delete in CiviContribute');
-    $this->callAPIAndDocument('payment', 'delete', $deleteParams, __FUNCTION__, __FILE__);
+    $this->callAPISuccess('payment', 'delete', $cancelParams);
 
-    $payment = $this->callAPIAndDocument('payment', 'get', $params, __FUNCTION__, __FILE__);
+    $payment = $this->callAPISuccess('payment', 'get', $params);
     $this->assertEquals(0, $payment['count']);
 
     $this->callAPISuccess('Contribution', 'Delete', array(
@@ -361,13 +372,15 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
       'total_amount' => 50,
     );
 
-    $payment = $this->callAPIAndDocument('payment', 'create', $params, __FUNCTION__, __FILE__);
+    $payment = $this->callAPISuccess('payment', 'create', $params);
     $expectedResult = array(
-      'from_financial_account_id' => 7,
-      'to_financial_account_id' => 6,
-      'total_amount' => 50,
-      'status_id' => 1,
-      'is_payment' => 1,
+      $payment['id'] => array(
+        'from_financial_account_id' => 7,
+        'to_financial_account_id' => 6,
+        'total_amount' => 50,
+        'status_id' => 1,
+        'is_payment' => 1,
+      ),
     );
     $this->checkPaymentResult($payment, $expectedResult);
 
@@ -392,7 +405,7 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
     $payment = $this->callAPIFailure('payment', 'create', $params, 'API permission check failed for Payment/get call; insufficient permission: require access CiviCRM and edit contributions');
 
     array_push(CRM_Core_Config::singleton()->userPermissionClass->permissions, 'access CiviCRM', 'edit contributions');
-    $payment = $this->callAPIAndDocument('payment', 'create', $params, __FUNCTION__, __FILE__);
+    $payment = $this->callAPISuccess('payment', 'create', $params);
 
     $params = array(
       'entity_table' => 'civicrm_financial_item',
@@ -407,7 +420,7 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
     $params = array(
       'contribution_id' => $contribution['id'],
     );
-    $payment = $this->callAPIAndDocument('payment', 'get', $params, __FUNCTION__, __FILE__);
+    $payment = $this->callAPISuccess('payment', 'get', $params);
     $amounts = array(100.00, -50.00, 50.00, 150.00);
     foreach ($payment['values'] as $value) {
       $amount = array_pop($amounts);
@@ -428,4 +441,57 @@ class api_v3_PaymentTest extends CiviUnitTestCase {
     ));
   }
 
+  /**
+   * Test create payment api for paylater contribution
+   */
+  public function testCreatePaymentPayLater() {
+    $this->createLoggedInUser();
+    $contributionParams = array(
+      'total_amount' => 100,
+      'currency' => 'USD',
+      'contact_id' => $this->_individualId,
+      'financial_type_id' => 1,
+      'contribution_status_id' => 2,
+      'is_pay_later' => 1,
+    );
+    $contribution = $this->callAPISuccess('Contribution', 'create', $contributionParams);
+    //Create partial payment
+    $params = array(
+      'contribution_id' => $contribution['id'],
+      'total_amount' => 100,
+    );
+    $payment = $this->callAPISuccess('Payment', 'create', $params);
+    $expectedResult = array(
+      $payment['id'] => array(         
+        'from_financial_account_id' => 7,
+        'to_financial_account_id' => 6,
+        'total_amount' => 100,
+        'status_id' => 1,
+        'is_payment' => 1,
+      ),
+    );
+    $this->checkPaymentResult($payment, $expectedResult);
+    // Check entity financial trxn created properly
+    $params = array(
+      'entity_id' => $contribution['id'],
+      'entity_table' => 'civicrm_contribution',
+      'financial_trxn_id' => $payment['id'],
+    );
+    $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
+    $this->assertEquals($eft['values'][$eft['id']]['amount'], 100);
+    $params = array(
+      'entity_table' => 'civicrm_financial_item',
+      'financial_trxn_id' => $payment['id'],
+    );
+    $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
+    $this->assertEquals($eft['values'][$eft['id']]['amount'], 100);
+    // Check contribution for completed status
+    $contribution = $this->callAPISuccess('contribution', 'get', array('id' => $contribution['id']));
+    $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status'], 'Completed');
+    $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 100.00);
+    $this->callAPISuccess('Contribution', 'Delete', array(
+      'id' => $contribution['id'],
+    ));
+  }
+
 }