From d2aeabca2d9734d6a96efcafb9a85555d5c55f2e Mon Sep 17 00:00:00 2001 From: Matthew Wire Date: Thu, 20 Feb 2020 17:15:37 +0000 Subject: [PATCH] Refactor api3 Payment.Get API to support options + most fields in civicrm_financial_trxn Unit test for PR#16603 Alternative for fix ups on Payment.get --- api/v3/Payment.php | 69 +++++++++---------- .../CRM/Contribute/Form/ContributionTest.php | 6 ++ tests/phpunit/api/v3/PaymentTest.php | 66 ++++++++++++++---- 3 files changed, 90 insertions(+), 51 deletions(-) diff --git a/api/v3/Payment.php b/api/v3/Payment.php index 3ab01d934c..b601cd684f 100644 --- a/api/v3/Payment.php +++ b/api/v3/Payment.php @@ -27,43 +27,40 @@ * @throws \CiviCRM_API3_Exception */ function civicrm_api3_payment_get($params) { - $financialTrxn = []; - $limit = ''; - if (isset($params['options']) && !empty($params['options']['limit'])) { - $limit = $params['options']['limit'] ?? NULL; - } - $params['options']['limit'] = 0; - if (isset($params['trxn_id'])) { - $params['financial_trxn_id.trxn_id'] = $params['trxn_id']; + $params['is_payment'] = TRUE; + $contributionID = $params['entity_id'] ?? NULL; + + // In order to support contribution id we need to do an extra lookup. + if ($contributionID) { + $eftParams = [ + 'entity_id' => $contributionID, + 'entity_table' => 'civicrm_contribution', + 'options' => ['limit' => 0], + 'financial_trxn_id.is_payment' => 1, + ]; + $eft = civicrm_api3('EntityFinancialTrxn', 'get', $eftParams)['values']; + if (empty($eft)) { + return civicrm_api3_create_success([], $params, 'Payment', 'get'); + } + foreach ($eft as $entityFinancialTrxn) { + $params['financial_trxn_id']['IN'][] = $entityFinancialTrxn['financial_trxn_id']; + } } - $eftParams = $params; - unset($eftParams['return']); - // @todo - why do we fetch EFT params at all? - $eft = civicrm_api3('EntityFinancialTrxn', 'get', $eftParams); - if (!empty($eft['values'])) { - $eftIds = []; - foreach ($eft['values'] as $efts) { - if (empty($efts['financial_trxn_id'])) { - continue; - } - $eftIds[] = $efts['financial_trxn_id']; - $map[$efts['financial_trxn_id']] = $efts['entity_id']; + + $financialTrxn = civicrm_api3('FinancialTrxn', 'get', array_merge($params, ['sequential' => FALSE]))['values']; + if ($contributionID) { + foreach ($financialTrxn as &$values) { + $values['contribution_id'] = $contributionID; } - if (!empty($eftIds)) { - $ftParams = [ - 'id' => ['IN' => $eftIds], - 'is_payment' => 1, - ]; - if ($limit) { - $ftParams['options']['limit'] = $limit; - } - $financialTrxn = civicrm_api3('FinancialTrxn', 'get', $ftParams); - foreach ($financialTrxn['values'] as &$values) { - $values['contribution_id'] = $map[$values['id']]; - } + } + elseif (!empty($financialTrxn)) { + $entityFinancialTrxns = civicrm_api3('EntityFinancialTrxn', 'get', ['financial_trxn_id' => ['IN' => array_keys($financialTrxn)], 'entity_table' => 'civicrm_contribution', 'options' => ['limit' => 0]])['values']; + foreach ($entityFinancialTrxns as $entityFinancialTrxn) { + $financialTrxn[$entityFinancialTrxn['financial_trxn_id']]['contribution_id'] = $entityFinancialTrxn['entity_id']; } } - return civicrm_api3_create_success(CRM_Utils_Array::value('values', $financialTrxn, []), $params, 'Payment', 'get'); + + return civicrm_api3_create_success($financialTrxn, $params, 'Payment', 'get'); } /** @@ -103,7 +100,7 @@ function civicrm_api3_payment_cancel($params) { $paymentParams = [ 'total_amount' => -$entity['amount'], 'contribution_id' => $entity['entity_id'], - 'trxn_date' => CRM_Utils_Array::value('trxn_date', $params, 'now'), + 'trxn_date' => $params['trxn_date'] ?? 'now', 'cancelled_payment_id' => $params['id'], ]; @@ -325,10 +322,6 @@ function _civicrm_api3_payment_get_spec(&$params) { 'title' => ts('Contribution ID'), 'type' => CRM_Utils_Type::T_INT, ], - 'entity_table' => [ - 'title' => ts('Entity Table'), - 'api.default' => 'civicrm_contribution', - ], 'entity_id' => [ 'title' => ts('Entity ID'), 'type' => CRM_Utils_Type::T_INT, diff --git a/tests/phpunit/CRM/Contribute/Form/ContributionTest.php b/tests/phpunit/CRM/Contribute/Form/ContributionTest.php index 17e2647bb0..d9dc29a178 100644 --- a/tests/phpunit/CRM/Contribute/Form/ContributionTest.php +++ b/tests/phpunit/CRM/Contribute/Form/ContributionTest.php @@ -479,6 +479,9 @@ class CRM_Contribute_Form_ContributionTest extends CiviUnitTestCase { * - 1 Contribution with status = Pending * - 1 Line item * - 1 civicrm_financial_item. This is linked to the line item and has a status of 3 + * + * @throws \CRM_Core_Exception + * @throws \CiviCRM_API3_Exception */ public function testSubmitCreditCardInvalid() { $form = new CRM_Contribute_Form_Contribution(); @@ -517,6 +520,9 @@ class CRM_Contribute_Form_ContributionTest extends CiviUnitTestCase { /** * Test the submit function creates a billing address if provided. + * + * @throws \CRM_Core_Exception + * @throws \CiviCRM_API3_Exception */ public function testSubmitCreditCardWithBillingAddress() { $form = new CRM_Contribute_Form_Contribution(); diff --git a/tests/phpunit/api/v3/PaymentTest.php b/tests/phpunit/api/v3/PaymentTest.php index e8bbc94e94..927e11bb16 100644 --- a/tests/phpunit/api/v3/PaymentTest.php +++ b/tests/phpunit/api/v3/PaymentTest.php @@ -68,10 +68,10 @@ class api_v3_PaymentTest extends CiviUnitTestCase { 'check_permissions' => TRUE, ]; CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'administer CiviCRM']; - $payment = $this->callAPIFailure('payment', 'get', $params, 'API permission check failed for Payment/get call; insufficient permission: require access CiviCRM and access CiviContribute'); + $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); + $this->callAPISuccess('payment', 'get', $params); $payment = $this->callAPIAndDocument('payment', 'get', $params, __FUNCTION__, __FILE__); $this->assertEquals(1, $payment['count']); @@ -92,6 +92,51 @@ class api_v3_PaymentTest extends CiviUnitTestCase { $this->validateAllPayments(); } + /** + * Test multiple payments for contribution and assert if option + * and is_payment returns the correct list of payments. + * + * @throws \CRM_Core_Exception + */ + public function testMultiplePaymentsForContribution() { + $params = [ + 'contact_id' => $this->_individualId, + 'total_amount' => 100, + 'contribution_status_id' => 'Pending', + ]; + $contributionID = $this->contributionCreate($params); + $paymentParams = [ + 'contribution_id' => $contributionID, + 'total_amount' => 20, + 'trxn_date' => date('Y-m-d'), + ]; + $this->callAPISuccess('payment', 'create', $paymentParams); + $paymentParams['total_amount'] = 30; + $this->callAPISuccess('payment', 'create', $paymentParams); + + $paymentParams['total_amount'] = 50; + $this->callAPISuccess('payment', 'create', $paymentParams); + + //check if contribution status is set to "Completed". + $contribution = $this->callAPISuccessGetSingle('Contribution', [ + 'id' => $contributionID, + ]); + $this->assertEquals('Completed', $contribution['contribution_status']); + + //Get Payment using options + $getParams = [ + 'sequential' => 1, + 'contribution_id' => $contributionID, + 'is_payment' => 1, + 'options' => ['limit' => 0, 'sort' => 'total_amount DESC'], + ]; + $payments = $this->callAPISuccess('Payment', 'get', $getParams); + $this->assertEquals(3, $payments['count']); + foreach ([50, 30, 20] as $key => $total_amount) { + $this->assertEquals($total_amount, $payments['values'][$key]['total_amount']); + } + } + /** * Retrieve Payment using trxn_id. * @@ -516,7 +561,7 @@ class api_v3_PaymentTest extends CiviUnitTestCase { 'total_amount' => -90, ]); $contribution = $this->callAPISuccessGetSingle('Contribution', [ - 'return' => ["contribution_status_id"], + 'return' => ['contribution_status_id'], 'id' => $contributionID, ]); //Assert if main contribution status is updated to "Refunded". @@ -543,7 +588,7 @@ class api_v3_PaymentTest extends CiviUnitTestCase { 'id' => $payment['id'], 'check_permissions' => TRUE, ]; - $payment = $this->callAPIFailure('payment', 'cancel', $cancelParams, 'API permission check failed for Payment/cancel call; insufficient permission: require access CiviCRM and access CiviContribute and edit contributions'); + $this->callAPIFailure('payment', 'cancel', $cancelParams, 'API permission check failed for Payment/cancel call; insufficient permission: require access CiviCRM and access CiviContribute and edit contributions'); array_push(CRM_Core_Config::singleton()->userPermissionClass->permissions, 'access CiviCRM', 'edit contributions'); @@ -575,24 +620,19 @@ class api_v3_PaymentTest extends CiviUnitTestCase { 'contribution_id' => $contribution['id'], ]; - $payment = $this->callAPISuccess('payment', 'get', $params); - $this->assertEquals(1, $payment['count']); + $payment = $this->callAPISuccessGetSingle('payment', $params); $deleteParams = [ 'id' => $payment['id'], 'check_permissions' => TRUE, ]; - $payment = $this->callAPIFailure('payment', 'delete', $deleteParams, 'API permission check failed for Payment/delete call; insufficient permission: require access CiviCRM and access CiviContribute and delete in CiviContribute'); + $this->callAPIFailure('payment', 'delete', $deleteParams, 'API permission check failed for Payment/delete call; insufficient permission: require access CiviCRM and access CiviContribute 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->callAPISuccessGetCount('payment', $params, 0); - $payment = $this->callAPISuccess('payment', 'get', $params); - $this->assertEquals(0, $payment['count']); - - $this->callAPISuccess('Contribution', 'Delete', [ - 'id' => $contribution['id'], - ]); + $this->callAPISuccess('Contribution', 'Delete', ['id' => $contribution['id']]); } /** -- 2.25.1