Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor api3 Payment.Get API to support options + most fields in civicrm_financial_trxn #17071

Merged
merged 1 commit into from
Apr 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 31 additions & 38 deletions api/v3/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}

/**
Expand Down Expand Up @@ -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'],
];

Expand Down Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions tests/phpunit/CRM/Contribute/Form/ContributionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,9 @@ public function testSubmitCreditCardFullyDeductible() {
* - 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();
Expand Down Expand Up @@ -517,6 +520,9 @@ public function testSubmitCreditCardInvalid() {

/**
* 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();
Expand Down
66 changes: 53 additions & 13 deletions tests/phpunit/api/v3/PaymentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ public function testGetPayment() {
'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']);
Expand All @@ -92,6 +92,51 @@ public function testGetPayment() {
$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.
*
Expand Down Expand Up @@ -516,7 +561,7 @@ public function testRefundPayment() {
'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".
Expand All @@ -543,7 +588,7 @@ public function testCancelPayment() {
'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');

Expand Down Expand Up @@ -575,24 +620,19 @@ public function testDeletePayment() {
'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']]);
}

/**
Expand Down