Skip to content

Commit

Permalink
Merge pull request #17071 from eileenmcnaughton/payment
Browse files Browse the repository at this point in the history
Refactor api3 Payment.Get API to support options + most fields in civicrm_financial_trxn
  • Loading branch information
mattwire authored Apr 27, 2020
2 parents a78a6c8 + d2aeabc commit 089e2d1
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 51 deletions.
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

0 comments on commit 089e2d1

Please sign in to comment.