(NFC) (dev/core#878) Simplify copyright header (Civi/*)
[civicrm-core.git] / tests / phpunit / api / v3 / PaymentTest.php
CommitLineData
b7f554fe
E
1<?php
2/*
3 +--------------------------------------------------------------------+
2fe49090 4 | CiviCRM version 5 |
b7f554fe 5 +--------------------------------------------------------------------+
f299f7db 6 | Copyright CiviCRM LLC (c) 2004-2020 |
b7f554fe
E
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
b7f554fe
E
28/**
29 * Test APIv3 civicrm_contribute_* functions
30 *
31 * @package CiviCRM_APIv3
32 * @subpackage API_Contribution
acb109b7 33 * @group headless
b7f554fe
E
34 */
35class api_v3_PaymentTest extends CiviUnitTestCase {
36
b7f554fe 37 protected $_individualId;
d3b3ad06 38
b7f554fe 39 protected $_financialTypeId = 1;
d3b3ad06 40
b7f554fe
E
41 /**
42 * Setup function.
3d4f6f65 43 *
44 * @throws \CRM_Core_Exception
b7f554fe
E
45 */
46 public function setUp() {
47 parent::setUp();
48
49 $this->_apiversion = 3;
50 $this->_individualId = $this->individualCreate();
d3b3ad06 51 CRM_Core_Config::singleton()->userPermissionClass->permissions = [];
b7f554fe
E
52 }
53
54 /**
55 * Clean up after each test.
fda18dc3 56 *
57 * @throws \Exception
b7f554fe
E
58 */
59 public function tearDown() {
60 $this->quickCleanUpFinancialEntities();
d3b3ad06 61 $this->quickCleanup(['civicrm_uf_match']);
eba13f6d 62 unset(CRM_Core_Config::singleton()->userPermissionClass->permissions);
fda18dc3 63 parent::tearDown();
b7f554fe
E
64 }
65
66 /**
52873538 67 * Test Get Payment api.
3d4f6f65 68 *
69 * @throws \CRM_Core_Exception
b7f554fe
E
70 */
71 public function testGetPayment() {
d3b3ad06 72 $p = [
b7f554fe
E
73 'contact_id' => $this->_individualId,
74 'receive_date' => '2010-01-20',
75 'total_amount' => 100.00,
76 'financial_type_id' => $this->_financialTypeId,
77 'trxn_id' => 23456,
78 'contribution_status_id' => 1,
d3b3ad06 79 ];
b7f554fe
E
80 $contribution = $this->callAPISuccess('contribution', 'create', $p);
81
d3b3ad06 82 $params = [
b7f554fe 83 'contribution_id' => $contribution['id'],
979748a2 84 'check_permissions' => TRUE,
d3b3ad06 85 ];
86 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'administer CiviCRM'];
eba13f6d 87 $payment = $this->callAPIFailure('payment', 'get', $params, 'API permission check failed for Payment/get call; insufficient permission: require access CiviCRM and access CiviContribute');
b7f554fe 88
979748a2 89 array_push(CRM_Core_Config::singleton()->userPermissionClass->permissions, 'access CiviContribute');
c60d3584 90 $payment = $this->callAPISuccess('payment', 'get', $params);
b7f554fe 91
979748a2 92 $payment = $this->callAPIAndDocument('payment', 'get', $params, __FUNCTION__, __FILE__);
b7f554fe 93 $this->assertEquals(1, $payment['count']);
979748a2 94
d3b3ad06 95 $expectedResult = [
96 $contribution['id'] => [
c60d3584
PN
97 'total_amount' => 100,
98 'trxn_id' => 23456,
99 'trxn_date' => '2010-01-20 00:00:00',
100 'contribution_id' => $contribution['id'],
101 'is_payment' => 1,
d3b3ad06 102 ],
103 ];
a44499b4 104 $this->checkPaymentResult($payment, $expectedResult);
d3b3ad06 105 $this->callAPISuccess('Contribution', 'Delete', [
b7f554fe 106 'id' => $contribution['id'],
d3b3ad06 107 ]);
3d4f6f65 108 $this->validateAllPayments();
b7f554fe
E
109 }
110
6045f2b7
JP
111 /**
112 * Retrieve Payment using trxn_id.
3d4f6f65 113 *
114 * @throws \CRM_Core_Exception
6045f2b7
JP
115 */
116 public function testGetPaymentWithTrxnID() {
117 $this->_individualId2 = $this->individualCreate();
118 $params1 = [
119 'contact_id' => $this->_individualId,
120 'trxn_id' => 111111,
121 'total_amount' => 10,
122 ];
123 $contributionID1 = $this->contributionCreate($params1);
124
125 $params2 = [
126 'contact_id' => $this->_individualId2,
127 'trxn_id' => 222222,
128 'total_amount' => 20,
129 ];
130 $contributionID2 = $this->contributionCreate($params2);
131
132 $paymentParams = ['trxn_id' => 111111];
133 $payment = $this->callAPISuccess('payment', 'get', $paymentParams);
134 $expectedResult = [
135 $payment['id'] => [
136 'total_amount' => 10,
137 'trxn_id' => 111111,
138 'status_id' => 1,
139 'is_payment' => 1,
140 'contribution_id' => $contributionID1,
141 ],
142 ];
143 $this->checkPaymentResult($payment, $expectedResult);
144
145 $paymentParams = ['trxn_id' => 222222];
146 $payment = $this->callAPISuccess('payment', 'get', $paymentParams);
147 $expectedResult = [
148 $payment['id'] => [
149 'total_amount' => 20,
150 'trxn_id' => 222222,
151 'status_id' => 1,
152 'is_payment' => 1,
153 'contribution_id' => $contributionID2,
154 ],
155 ];
156 $this->checkPaymentResult($payment, $expectedResult);
3d4f6f65 157 $this->validateAllPayments();
6045f2b7
JP
158 }
159
a79d2ec2 160 /**
161 * Test email receipt for partial payment.
3d4f6f65 162 *
163 * @throws \CRM_Core_Exception
a79d2ec2 164 */
165 public function testPaymentEmailReceipt() {
166 $mut = new CiviMailUtils($this);
5266bd48 167 $contribution = $this->createPartiallyPaidParticipantOrder();
0fad34a0 168 $event = $this->callAPISuccess('Event', 'get', []);
169 $this->addLocationToEvent($event['id']);
b5a442ed 170 $params = [
a79d2ec2 171 'contribution_id' => $contribution['id'],
172 'total_amount' => 50,
434546ac 173 'check_number' => '345',
174 'trxn_date' => '2018-08-13 17:57:56',
b5a442ed 175 ];
a79d2ec2 176 $payment = $this->callAPISuccess('payment', 'create', $params);
177 $this->checkPaymentResult($payment, [
178 $payment['id'] => [
179 'from_financial_account_id' => 7,
180 'to_financial_account_id' => 6,
181 'total_amount' => 50,
182 'status_id' => 1,
183 'is_payment' => 1,
184 ],
185 ]);
186
187 $this->callAPISuccess('Payment', 'sendconfirmation', ['id' => $payment['id']]);
694cfde6 188 $mut->assertSubjects(['Payment Receipt - Annual CiviCRM meet - Mr. Anthony Anderson II']);
d3b3ad06 189 $mut->checkMailLog([
44a2f017 190 'From: "FIXME" <info@EXAMPLE.ORG>',
1e477c5b 191 'Dear Anthony,',
1f6479af 192 'Total Fee: $ 300.00',
a79d2ec2 193 'This Payment Amount: $ 50.00',
39b959db
SL
194 //150 was paid in the 1st payment.
195 'Balance Owed: $ 100.00',
a79d2ec2 196 'Event Information and Location',
434546ac 197 'Paid By: Check',
198 'Check Number: 345',
199 'Transaction Date: August 13th, 2018 5:57 PM',
0fad34a0 200 'event place',
201 'streety street',
d3b3ad06 202 ]);
a79d2ec2 203 $mut->stop();
a7b9128b 204 $mut->clearMessages();
3d4f6f65 205 $this->validateAllPayments();
a79d2ec2 206 }
207
00ef9b01 208 /**
209 * Test email receipt for partial payment.
1e0f58c7 210 *
211 * @throws \CRM_Core_Exception
00ef9b01 212 */
213 public function testPaymentEmailReceiptFullyPaid() {
214 $mut = new CiviMailUtils($this);
44a2f017 215 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviContribute', 'edit contributions', 'access CiviCRM'];
5266bd48 216 $contribution = $this->createPartiallyPaidParticipantOrder();
00ef9b01 217
218 $params = [
219 'contribution_id' => $contribution['id'],
220 'total_amount' => 150,
221 ];
222 $payment = $this->callAPISuccess('payment', 'create', $params);
223
44a2f017 224 // Here we set the email to an invalid email & use check_permissions, domain email should be used.
225 $email = $this->callAPISuccess('Email', 'create', ['contact_id' => 1, 'email' => 'bob@example.com']);
226 $this->callAPISuccess('Payment', 'sendconfirmation', ['id' => $payment['id'], 'from' => $email['id'], 'check_permissions' => 1]);
694cfde6 227 $mut->assertSubjects(['Payment Receipt - Annual CiviCRM meet - Mr. Anthony Anderson II', 'Registration Confirmation - Annual CiviCRM meet - Mr. Anthony Anderson II']);
d3b3ad06 228 $mut->checkMailLog([
44a2f017 229 'From: "FIXME" <info@EXAMPLE.ORG>',
1e477c5b 230 'Dear Anthony,',
84060348 231 'Below you will find a receipt for this payment.',
1f6479af 232 'Total Fee: $ 300.00',
00ef9b01 233 'This Payment Amount: $ 150.00',
234 'Balance Owed: $ 0.00',
12ff7379 235 'Thank you for completing this payment.',
d3b3ad06 236 ]);
00ef9b01 237 $mut->stop();
238 $mut->clearMessages();
3d4f6f65 239 $this->validateAllPayments();
00ef9b01 240 }
241
b5a442ed 242 /**
243 * Test email receipt for partial payment.
a7b9128b 244 *
245 * @dataProvider getThousandSeparators
246 *
247 * @param string $thousandSeparator
3d4f6f65 248 *
249 * @throws \CRM_Core_Exception
b5a442ed 250 */
a7b9128b 251 public function testRefundEmailReceipt($thousandSeparator) {
252 $this->setCurrencySeparators($thousandSeparator);
253 $decimalSeparator = ($thousandSeparator === ',' ? '.' : ',');
b5a442ed 254 $mut = new CiviMailUtils($this);
5266bd48 255 $contribution = $this->createPartiallyPaidParticipantOrder();
b5a442ed 256 $this->callAPISuccess('payment', 'create', [
257 'contribution_id' => $contribution['id'],
258 'total_amount' => 50,
259 'check_number' => '345',
260 'trxn_date' => '2018-08-13 17:57:56',
261 ]);
262
263 $payment = $this->callAPISuccess('payment', 'create', [
264 'contribution_id' => $contribution['id'],
265 'total_amount' => -30,
266 'trxn_date' => '2018-11-13 12:01:56',
52746f6a 267 'sequential' => TRUE,
268 ])['values'][0];
b5a442ed 269
52746f6a 270 $expected = [
271 'from_financial_account_id' => 7,
272 'to_financial_account_id' => 6,
273 'total_amount' => -30,
2561fc11 274 'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Core_BAO_FinancialTrxn', 'status_id', 'Refunded'),
52746f6a 275 'is_payment' => 1,
276 ];
277 foreach ($expected as $key => $value) {
278 $this->assertEquals($expected[$key], $payment[$key], 'mismatch on key ' . $key);
279 }
b5a442ed 280
281 $this->callAPISuccess('Payment', 'sendconfirmation', ['id' => $payment['id']]);
694cfde6 282 $mut->assertSubjects(['Refund Notification - Annual CiviCRM meet - Mr. Anthony Anderson II']);
d3b3ad06 283 $mut->checkMailLog([
1e477c5b 284 'Dear Anthony,',
00ef9b01 285 'A refund has been issued based on changes in your registration selections.',
1f6479af 286 'Total Fee: $ 300' . $decimalSeparator . '00',
a7b9128b 287 'Refund Amount: $ -30' . $decimalSeparator . '00',
b5a442ed 288 'Event Information and Location',
289 'Paid By: Check',
290 'Transaction Date: November 13th, 2018 12:01 PM',
1f6479af 291 'Total Paid: $ 170' . $decimalSeparator . '00',
d3b3ad06 292 ]);
b5a442ed 293 $mut->stop();
a7b9128b 294 $mut->clearMessages();
3d4f6f65 295 $this->validateAllPayments();
b5a442ed 296 }
297
5266bd48 298 /**
299 * Test adding a payment to a pending multi-line order.
300 *
301 * @throws \CRM_Core_Exception
302 */
303 public function testCreatePaymentPendingOrderNoLineItems() {
304 $order = $this->createPendingParticipantOrder();
305 $this->callAPISuccess('Payment', 'create', [
306 'order_id' => $order['id'],
307 'total_amount' => 50,
308 ]);
3d4f6f65 309 $this->validateAllPayments();
5266bd48 310 }
311
cc9f2882 312 /**
313 * Test that Payment.create does not fail if the line items are missing.
314 *
315 * In the original spec it was anticipated that financial items would not be created
316 * for pending contributions in some circumstances. We've backed away from this and
317 * I mostly could not find a way to do it through the UI. But I did seem to once &
318 * I want to be sure that if they ARE missing no fatal occurs so this tests
319 * that in an artificial way.
320 *
321 * @throws \CRM_Core_Exception
322 */
323 public function testAddPaymentMissingFinancialItems() {
324 $contribution = $this->callAPISuccess('Contribution', 'create', [
325 'total_amount' => 50,
326 'financial_type_id' => 'Donation',
327 'contact_id' => $this->individualCreate(),
328 'contribution_status_id' => 'Pending',
329 ]);
330 CRM_Core_DAO::executeQuery('DELETE FROM civicrm_financial_item');
331 $this->callAPISuccess('Payment', 'create', ['contribution_id' => $contribution['id'], 'payment_instrument_id' => 'Check', 'total_amount' => 5]);
332 $this->validateAllPayments();
333 }
334
5266bd48 335 /**
336 * Add participant with contribution
337 *
338 * @return array
339 *
340 * @throws \CRM_Core_Exception
341 */
342 protected function createPendingParticipantOrder() {
343 return $this->callAPISuccess('Order', 'create', $this->getParticipantOrderParams());
344 }
345
52873538
PN
346 /**
347 * Test create payment api with no line item in params
f3e6da5e 348 *
349 * @throws \CRM_Core_Exception
52873538 350 */
b7f554fe 351 public function testCreatePaymentNoLineItems() {
5266bd48 352 $contribution = $this->createPartiallyPaidParticipantOrder();
f5ec2569 353
b7f554fe 354 //Create partial payment
d3b3ad06 355 $params = [
b7f554fe 356 'contribution_id' => $contribution['id'],
52e3bed0 357 'total_amount' => 50,
d3b3ad06 358 ];
8ed3f575 359 $payment = $this->callAPIAndDocument('payment', 'create', $params, __FUNCTION__, __FILE__);
5049eefc 360 $this->checkPaymentIsValid($payment['id'], $contribution['id']);
b7f554fe 361
d3b3ad06 362 $params = [
577daeaa
PN
363 'entity_table' => 'civicrm_financial_item',
364 'financial_trxn_id' => $payment['id'],
d3b3ad06 365 ];
577daeaa 366 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
d3b3ad06 367 $amounts = [33.33, 16.67];
577daeaa
PN
368 foreach ($eft['values'] as $value) {
369 $this->assertEquals($value['amount'], array_pop($amounts));
370 }
371
b7f554fe 372 // Now create payment to complete total amount of contribution
d3b3ad06 373 $params = [
b7f554fe 374 'contribution_id' => $contribution['id'],
52e3bed0 375 'total_amount' => 100,
d3b3ad06 376 ];
c60d3584 377 $payment = $this->callAPISuccess('payment', 'create', $params);
d3b3ad06 378 $expectedResult = [
379 $payment['id'] => [
c60d3584
PN
380 'from_financial_account_id' => 7,
381 'to_financial_account_id' => 6,
382 'total_amount' => 100,
383 'status_id' => 1,
384 'is_payment' => 1,
d3b3ad06 385 ],
386 ];
52e3bed0 387 $this->checkPaymentResult($payment, $expectedResult);
d3b3ad06 388 $params = [
577daeaa
PN
389 'entity_table' => 'civicrm_financial_item',
390 'financial_trxn_id' => $payment['id'],
d3b3ad06 391 ];
577daeaa 392 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
d3b3ad06 393 $amounts = [66.67, 33.33];
577daeaa
PN
394 foreach ($eft['values'] as $value) {
395 $this->assertEquals($value['amount'], array_pop($amounts));
396 }
b7f554fe 397 // Check contribution for completed status
d3b3ad06 398 $contribution = $this->callAPISuccess('contribution', 'get', ['id' => $contribution['id']]);
b7f554fe
E
399
400 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status'], 'Completed');
52e3bed0 401 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 300.00);
d3b3ad06 402 $paymentParticipant = [
577daeaa 403 'contribution_id' => $contribution['id'],
d3b3ad06 404 ];
577daeaa 405 $participantPayment = $this->callAPISuccess('ParticipantPayment', 'getsingle', $paymentParticipant);
d3b3ad06 406 $participant = $this->callAPISuccess('participant', 'get', ['id' => $participantPayment['participant_id']]);
577daeaa 407 $this->assertEquals($participant['values'][$participant['id']]['participant_status'], 'Registered');
d3b3ad06 408 $this->callAPISuccess('Contribution', 'Delete', [
b7f554fe 409 'id' => $contribution['id'],
d3b3ad06 410 ]);
3d4f6f65 411 $this->validateAllPayments();
b7f554fe 412 }
f5ec2569 413
52e3bed0
PN
414 /**
415 * Function to assert db values
a494d7a3 416 *
417 * @throws \CRM_Core_Exception
52e3bed0
PN
418 */
419 public function checkPaymentResult($payment, $expectedResult) {
a494d7a3 420 $refreshedPayment = $this->callAPISuccessGetSingle('Payment', ['financial_trxn_id' => $payment['id']]);
c60d3584 421 foreach ($expectedResult[$payment['id']] as $key => $value) {
a494d7a3 422 $this->assertEquals($refreshedPayment[$key], $value, 'mismatch on ' . $key); $this->assertEquals($refreshedPayment[$key], $value, 'mismatch on ' . $key);
52e3bed0 423 }
52e3bed0
PN
424 }
425
52873538
PN
426 /**
427 * Test create payment api with line item in params
5049eefc 428 *
429 * @throws \CRM_Core_Exception
52873538 430 */
b7f554fe 431 public function testCreatePaymentLineItems() {
5266bd48 432 $contribution = $this->createPartiallyPaidParticipantOrder();
5049eefc 433 $lineItems = $this->callAPISuccess('LineItem', 'get', ['contribution_id' => $contribution['id']])['values'];
b7f554fe 434
5049eefc 435 // Create partial payment by passing line item array is params.
d3b3ad06 436 $params = [
b7f554fe 437 'contribution_id' => $contribution['id'],
d1f27fcf 438 'total_amount' => 50,
d3b3ad06 439 ];
440 $amounts = [40, 10];
5049eefc 441 foreach ($lineItems as $id => $ignore) {
d3b3ad06 442 $params['line_item'][] = [$id => array_pop($amounts)];
d1f27fcf 443 }
5049eefc 444 $payment = $this->callAPIAndDocument('Payment', 'create', $params, __FUNCTION__, __FILE__, 'Payment with line item', 'CreatePaymentWithLineItems');
445 $this->checkPaymentIsValid($payment['id'], $contribution['id']);
d1f27fcf 446
d3b3ad06 447 $params = [
d1f27fcf
PN
448 'entity_table' => 'civicrm_financial_item',
449 'financial_trxn_id' => $payment['id'],
5049eefc 450 'return' => ['entity_id.entity_id', 'amount'],
d3b3ad06 451 ];
5049eefc 452 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params)['values'];
453 $this->assertCount(2, $eft);
d3b3ad06 454 $amounts = [40, 10];
5049eefc 455 foreach ($eft as $value) {
d1f27fcf
PN
456 $this->assertEquals($value['amount'], array_pop($amounts));
457 }
b7f554fe
E
458
459 // Now create payment to complete total amount of contribution
d3b3ad06 460 $params = [
b7f554fe 461 'contribution_id' => $contribution['id'],
d1f27fcf 462 'total_amount' => 100,
d3b3ad06 463 ];
464 $amounts = [80, 20];
5049eefc 465 foreach ($lineItems as $id => $ignore) {
d3b3ad06 466 $params['line_item'][] = [$id => array_pop($amounts)];
d1f27fcf 467 }
5049eefc 468 $payment = $this->callAPISuccess('Payment', 'create', $params);
d3b3ad06 469 $expectedResult = [
470 $payment['id'] => [
c60d3584
PN
471 'from_financial_account_id' => 7,
472 'to_financial_account_id' => 6,
473 'total_amount' => 100,
474 'status_id' => 1,
475 'is_payment' => 1,
d3b3ad06 476 ],
477 ];
d1f27fcf 478 $this->checkPaymentResult($payment, $expectedResult);
d3b3ad06 479 $params = [
d1f27fcf
PN
480 'entity_table' => 'civicrm_financial_item',
481 'financial_trxn_id' => $payment['id'],
d3b3ad06 482 ];
5049eefc 483 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params)['values'];
484 $this->assertCount(2, $eft);
d3b3ad06 485 $amounts = [80, 20];
5049eefc 486 foreach ($eft as $value) {
d1f27fcf
PN
487 $this->assertEquals($value['amount'], array_pop($amounts));
488 }
b7f554fe 489 // Check contribution for completed status
5049eefc 490 $contribution = $this->callAPISuccess('Contribution', 'get', ['id' => $contribution['id']]);
b7f554fe
E
491
492 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status'], 'Completed');
d1f27fcf 493 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 300.00);
d3b3ad06 494 $paymentParticipant = [
d1f27fcf 495 'contribution_id' => $contribution['id'],
d3b3ad06 496 ];
d1f27fcf 497 $participantPayment = $this->callAPISuccess('ParticipantPayment', 'getsingle', $paymentParticipant);
d3b3ad06 498 $participant = $this->callAPISuccess('participant', 'get', ['id' => $participantPayment['participant_id']]);
d1f27fcf 499 $this->assertEquals($participant['values'][$participant['id']]['participant_status'], 'Registered');
3d4f6f65 500 $this->validateAllPayments();
b7f554fe
E
501 }
502
db62fd2b
PN
503 /**
504 * Test cancel payment api
5049eefc 505 *
506 * @throws \CRM_Core_Exception
2fabb298 507 */
db62fd2b 508 public function testCancelPayment() {
d3b3ad06 509 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['administer CiviCRM', 'access CiviContribute'];
5266bd48 510 $contribution = $this->createPartiallyPaidParticipantOrder();
db62fd2b 511
d3b3ad06 512 $params = [
db62fd2b 513 'contribution_id' => $contribution['id'],
d3b3ad06 514 ];
db62fd2b 515
979748a2 516 $payment = $this->callAPISuccess('payment', 'get', $params);
db62fd2b
PN
517 $this->assertEquals(1, $payment['count']);
518
d3b3ad06 519 $cancelParams = [
db62fd2b 520 'id' => $payment['id'],
979748a2 521 'check_permissions' => TRUE,
d3b3ad06 522 ];
4f94e3fa 523 $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');
979748a2 524
eba13f6d 525 array_push(CRM_Core_Config::singleton()->userPermissionClass->permissions, 'access CiviCRM', 'edit contributions');
979748a2 526
8ed3f575 527 $this->callAPIAndDocument('payment', 'cancel', $cancelParams, __FUNCTION__, __FILE__);
db62fd2b 528
c60d3584 529 $payment = $this->callAPISuccess('payment', 'get', $params);
db62fd2b 530 $this->assertEquals(2, $payment['count']);
d3b3ad06 531 $amounts = [-150.00, 150.00];
2fabb298 532 foreach ($payment['values'] as $value) {
db62fd2b
PN
533 $this->assertEquals($value['total_amount'], array_pop($amounts), 'Mismatch total amount');
534 }
535
d3b3ad06 536 $this->callAPISuccess('Contribution', 'Delete', [
db62fd2b 537 'id' => $contribution['id'],
d3b3ad06 538 ]);
3d4f6f65 539 $this->validateAllPayments();
db62fd2b
PN
540 }
541
ee1f482b
PN
542 /**
543 * Test delete payment api
3d4f6f65 544 *
545 * @throws \CRM_Core_Exception
ee1f482b
PN
546 */
547 public function testDeletePayment() {
d3b3ad06 548 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['administer CiviCRM', 'access CiviContribute'];
5266bd48 549 $contribution = $this->createPartiallyPaidParticipantOrder();
ee1f482b 550
d3b3ad06 551 $params = [
ee1f482b 552 'contribution_id' => $contribution['id'],
d3b3ad06 553 ];
ee1f482b 554
c60d3584 555 $payment = $this->callAPISuccess('payment', 'get', $params);
ee1f482b
PN
556 $this->assertEquals(1, $payment['count']);
557
d3b3ad06 558 $deleteParams = [
ee1f482b 559 'id' => $payment['id'],
979748a2 560 'check_permissions' => TRUE,
d3b3ad06 561 ];
4f94e3fa 562 $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');
979748a2 563
eba13f6d 564 array_push(CRM_Core_Config::singleton()->userPermissionClass->permissions, 'access CiviCRM', 'delete in CiviContribute');
8ed3f575 565 $this->callAPIAndDocument('payment', 'delete', $deleteParams, __FUNCTION__, __FILE__);
ee1f482b 566
c60d3584 567 $payment = $this->callAPISuccess('payment', 'get', $params);
ee1f482b
PN
568 $this->assertEquals(0, $payment['count']);
569
d3b3ad06 570 $this->callAPISuccess('Contribution', 'Delete', [
ee1f482b 571 'id' => $contribution['id'],
d3b3ad06 572 ]);
ee1f482b
PN
573 }
574
4cdb5e2f 575 /**
36057c8d 576 * Test update payment api.
577 *
578 * 1) create a contribution for $300 with a partial payment of $150
579 * - this results in 2 financial transactions. The accounts receivable transaction is linked
580 * via entity_financial_trxns to the 2 line items. The $150 payment is not linked to the line items
581 * so the line items are fully allocated even though they are only half paid.
582 *
583 * 2) add a payment of $50 -
584 * This payment transaction IS linked to the line items so $350 of the $300 in line items is allocated
585 * but $200 is paid
586 *
587 * 3) update that payment to be $100
588 * This results in a negative and a positive payment ($50 & $100) - the negative payment results in
589 * financial_items but the positive payment does not.
590 *
591 * The final result is we have
592 * - 1 partly paid contribution of $300
593 * - payment financial_trxns totalling $250
594 * - 1 Accounts receivable financial_trxn totalling $300
595 * - 2 financial items totalling $300 linked to the Accounts receivable financial_trxn
596 * - 6 entries in the civicrm_entity_financial_trxn linked to line items - totalling $450.
597 * - 5 entries in the civicrm_entity_financial_trxn linked to contributions - totalling $550.
6aa56ee2 598 *
599 * @throws \CRM_Core_Exception
4cdb5e2f
PN
600 */
601 public function testUpdatePayment() {
d3b3ad06 602 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['administer CiviCRM', 'access CiviContribute', 'edit contributions'];
5266bd48 603 $contribution = $this->createPartiallyPaidParticipantOrder();
4cdb5e2f
PN
604
605 //Create partial payment by passing line item array is params
d3b3ad06 606 $params = [
4cdb5e2f
PN
607 'contribution_id' => $contribution['id'],
608 'total_amount' => 50,
d3b3ad06 609 ];
4cdb5e2f 610
c60d3584 611 $payment = $this->callAPISuccess('payment', 'create', $params);
d3b3ad06 612 $expectedResult = [
613 $payment['id'] => [
c60d3584
PN
614 'from_financial_account_id' => 7,
615 'to_financial_account_id' => 6,
616 'total_amount' => 50,
617 'status_id' => 1,
618 'is_payment' => 1,
d3b3ad06 619 ],
620 ];
4cdb5e2f
PN
621 $this->checkPaymentResult($payment, $expectedResult);
622
d3b3ad06 623 $params = [
4cdb5e2f
PN
624 'entity_table' => 'civicrm_financial_item',
625 'financial_trxn_id' => $payment['id'],
d3b3ad06 626 ];
4cdb5e2f 627 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
d3b3ad06 628 $amounts = [33.33, 16.67];
4cdb5e2f
PN
629 foreach ($eft['values'] as $value) {
630 $this->assertEquals($value['amount'], array_pop($amounts));
631 }
632
633 // update the amount for payment
d3b3ad06 634 $params = [
4cdb5e2f
PN
635 'contribution_id' => $contribution['id'],
636 'total_amount' => 100,
637 'id' => $payment['id'],
979748a2 638 'check_permissions' => TRUE,
d3b3ad06 639 ];
36057c8d 640 // @todo - move this permissions test to it's own test - it just confuses here.
641 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['administer CiviCRM', 'access CiviContribute'];
642 $this->callAPIFailure('payment', 'create', $params, 'API permission check failed for Payment/create call; insufficient permission: require access CiviCRM and access CiviContribute and edit contributions');
979748a2 643
36057c8d 644 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['administer CiviCRM', 'access CiviContribute', 'access CiviCRM', 'edit contributions'];
8ed3f575 645 $payment = $this->callAPIAndDocument('payment', 'create', $params, __FUNCTION__, __FILE__, 'Update Payment', 'UpdatePayment');
4cdb5e2f 646
6ac768e7 647 $this->validateAllPayments();
2a84219e 648 // Check for proportional cancelled payment against lineitems.
d3b3ad06 649 $minParams = [
2a84219e
E
650 'entity_table' => 'civicrm_financial_item',
651 'financial_trxn_id' => $payment['id'] - 1,
d3b3ad06 652 ];
2a84219e 653
df29ccff 654 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $minParams)['values'];
655 $this->assertCount(2, $eft);
d3b3ad06 656 $amounts = [-33.33, -16.67];
2a84219e 657
df29ccff 658 foreach ($eft as $value) {
2a84219e
E
659 $this->assertEquals($value['amount'], array_pop($amounts));
660 }
661
662 // Check for proportional updated payment against lineitems.
d3b3ad06 663 $params = [
4cdb5e2f
PN
664 'entity_table' => 'civicrm_financial_item',
665 'financial_trxn_id' => $payment['id'],
d3b3ad06 666 ];
df29ccff 667 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params)['values'];
d3b3ad06 668 $amounts = [66.67, 33.33];
df29ccff 669 foreach ($eft as $value) {
4cdb5e2f
PN
670 $this->assertEquals($value['amount'], array_pop($amounts));
671 }
36057c8d 672 $items = $this->callAPISuccess('FinancialItem', 'get', [])['values'];
673 $this->assertCount(2, $items);
674 $itemSum = 0;
675 foreach ($items as $item) {
676 $this->assertEquals('civicrm_line_item', $item['entity_table']);
677 $itemSum += $item['amount'];
678 }
679 $this->assertEquals(300, $itemSum);
4cdb5e2f 680
d3b3ad06 681 $params = [
4cdb5e2f 682 'contribution_id' => $contribution['id'],
d3b3ad06 683 ];
c60d3584 684 $payment = $this->callAPISuccess('payment', 'get', $params);
d3b3ad06 685 $amounts = [100.00, -50.00, 50.00, 150.00];
4cdb5e2f
PN
686 foreach ($payment['values'] as $value) {
687 $amount = array_pop($amounts);
688 $this->assertEquals($value['total_amount'], $amount, 'Mismatch total amount');
689
690 // Check entity financial trxn created properly
d3b3ad06 691 $params = [
4cdb5e2f
PN
692 'entity_id' => $contribution['id'],
693 'entity_table' => 'civicrm_contribution',
694 'financial_trxn_id' => $value['id'],
d3b3ad06 695 ];
4cdb5e2f
PN
696 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
697 $this->assertEquals($eft['values'][$eft['id']]['amount'], $amount);
698 }
699
d3b3ad06 700 $this->callAPISuccess('Contribution', 'Delete', [
4cdb5e2f 701 'id' => $contribution['id'],
d3b3ad06 702 ]);
3d4f6f65 703 $this->validateAllPayments();
4cdb5e2f
PN
704 }
705
c60d3584
PN
706 /**
707 * Test create payment api for paylater contribution
3d4f6f65 708 *
709 * @throws \CRM_Core_Exception
c60d3584
PN
710 */
711 public function testCreatePaymentPayLater() {
712 $this->createLoggedInUser();
a494d7a3 713 $processorID = $this->paymentProcessorCreate();
d3b3ad06 714 $contributionParams = [
c60d3584
PN
715 'total_amount' => 100,
716 'currency' => 'USD',
717 'contact_id' => $this->_individualId,
718 'financial_type_id' => 1,
719 'contribution_status_id' => 2,
720 'is_pay_later' => 1,
d3b3ad06 721 ];
c60d3584 722 $contribution = $this->callAPISuccess('Contribution', 'create', $contributionParams);
8ed3f575 723 //add payment for pay later transaction
d3b3ad06 724 $params = [
c60d3584
PN
725 'contribution_id' => $contribution['id'],
726 'total_amount' => 100,
a494d7a3 727 'card_type_id' => 'Visa',
728 'pan_truncation' => '1234',
729 'trxn_result_code' => 'Startling success',
730 'payment_instrument_id' => $processorID,
731 'trxn_id' => 1234,
d3b3ad06 732 ];
c60d3584 733 $payment = $this->callAPISuccess('Payment', 'create', $params);
d3b3ad06 734 $expectedResult = [
735 $payment['id'] => [
c60d3584
PN
736 'from_financial_account_id' => 7,
737 'to_financial_account_id' => 6,
738 'total_amount' => 100,
739 'status_id' => 1,
740 'is_payment' => 1,
a494d7a3 741 'card_type_id' => 1,
742 'pan_truncation' => '1234',
743 'trxn_result_code' => 'Startling success',
744 'trxn_id' => 1234,
745 'payment_instrument_id' => 1,
d3b3ad06 746 ],
747 ];
c60d3584
PN
748 $this->checkPaymentResult($payment, $expectedResult);
749 // Check entity financial trxn created properly
d3b3ad06 750 $params = [
c60d3584
PN
751 'entity_id' => $contribution['id'],
752 'entity_table' => 'civicrm_contribution',
753 'financial_trxn_id' => $payment['id'],
d3b3ad06 754 ];
c60d3584
PN
755 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
756 $this->assertEquals($eft['values'][$eft['id']]['amount'], 100);
d3b3ad06 757 $params = [
c60d3584
PN
758 'entity_table' => 'civicrm_financial_item',
759 'financial_trxn_id' => $payment['id'],
d3b3ad06 760 ];
c60d3584
PN
761 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
762 $this->assertEquals($eft['values'][$eft['id']]['amount'], 100);
763 // Check contribution for completed status
d3b3ad06 764 $contribution = $this->callAPISuccess('contribution', 'get', ['id' => $contribution['id']]);
c60d3584
PN
765 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status'], 'Completed');
766 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 100.00);
d3b3ad06 767 $this->callAPISuccess('Contribution', 'Delete', [
c60d3584 768 'id' => $contribution['id'],
d3b3ad06 769 ]);
3d4f6f65 770 $this->validateAllPayments();
c60d3584
PN
771 }
772
d5b39a17 773 /**
8d54448e 774 * Test create payment api for pay later contribution with partial payment.
775 *
16b0233c 776 * https://lab.civicrm.org/dev/financial/issues/69
3d4f6f65 777 * @throws \CRM_Core_Exception
16b0233c 778 */
779 public function testCreatePaymentIncompletePaymentPartialPayment() {
780 $contributionParams = [
781 'total_amount' => 100,
782 'currency' => 'USD',
783 'contact_id' => $this->_individualId,
784 'financial_type_id' => 1,
785 'contribution_status_id' => 2,
786 ];
787 $contribution = $this->callAPISuccess('Contribution', 'create', $contributionParams);
788 $this->callAPISuccess('Payment', 'create', [
789 'contribution_id' => $contribution['id'],
790 'total_amount' => 50,
791 'payment_instrument_id' => 'Cash',
792 ]);
793 $payments = $this->callAPISuccess('Payment', 'get', ['contribution_id' => $contribution['id']])['values'];
794 $this->assertCount(1, $payments);
3d4f6f65 795 $this->validateAllPayments();
16b0233c 796 }
797
798 /**
799 * Test create payment api for pay later contribution with partial payment.
6cc6cb8c 800 *
801 * @throws \CRM_Core_Exception
d5b39a17
PN
802 */
803 public function testCreatePaymentPayLaterPartialPayment() {
804 $this->createLoggedInUser();
d3b3ad06 805 $contributionParams = [
d5b39a17
PN
806 'total_amount' => 100,
807 'currency' => 'USD',
808 'contact_id' => $this->_individualId,
809 'financial_type_id' => 1,
810 'contribution_status_id' => 2,
811 'is_pay_later' => 1,
d3b3ad06 812 ];
6cc6cb8c 813 $contribution = $this->callAPISuccess('Order', 'create', $contributionParams);
d5b39a17 814 //Create partial payment
d3b3ad06 815 $params = [
d5b39a17
PN
816 'contribution_id' => $contribution['id'],
817 'total_amount' => 60,
d3b3ad06 818 ];
d5b39a17 819 $payment = $this->callAPISuccess('Payment', 'create', $params);
d3b3ad06 820 $expectedResult = [
821 $payment['id'] => [
d5b39a17
PN
822 'total_amount' => 60,
823 'status_id' => 1,
824 'is_payment' => 1,
d3b3ad06 825 ],
826 ];
d5b39a17
PN
827 $this->checkPaymentResult($payment, $expectedResult);
828 // Check entity financial trxn created properly
d3b3ad06 829 $params = [
d5b39a17
PN
830 'entity_id' => $contribution['id'],
831 'entity_table' => 'civicrm_contribution',
832 'financial_trxn_id' => $payment['id'],
d3b3ad06 833 ];
d5b39a17
PN
834 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
835 $this->assertEquals($eft['values'][$eft['id']]['amount'], 60);
d3b3ad06 836 $params = [
d5b39a17
PN
837 'entity_table' => 'civicrm_financial_item',
838 'financial_trxn_id' => $payment['id'],
d3b3ad06 839 ];
d5b39a17
PN
840 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
841 $this->assertEquals($eft['values'][$eft['id']]['amount'], 60);
d3b3ad06 842 $contribution = $this->callAPISuccess('contribution', 'get', ['id' => $contribution['id']]);
d5b39a17
PN
843 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status'], 'Partially paid');
844 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 100.00);
845 //Create full payment
d3b3ad06 846 $params = [
d5b39a17
PN
847 'contribution_id' => $contribution['id'],
848 'total_amount' => 40,
d3b3ad06 849 ];
0a201857 850 // Rename the 'completed' status label first to check that we are not using the labels!
851 $this->callAPISuccess('OptionValue', 'get', ['name' => 'Completed', 'option_group_id' => 'contribution_status', 'api.OptionValue.create' => ['label' => 'Unicorn']]);
d5b39a17 852 $payment = $this->callAPISuccess('Payment', 'create', $params);
d3b3ad06 853 $expectedResult = [
854 $payment['id'] => [
d5b39a17
PN
855 'from_financial_account_id' => 7,
856 'to_financial_account_id' => 6,
857 'total_amount' => 40,
858 'status_id' => 1,
859 'is_payment' => 1,
d3b3ad06 860 ],
861 ];
d5b39a17
PN
862 $this->checkPaymentResult($payment, $expectedResult);
863 // Check entity financial trxn created properly
d3b3ad06 864 $params = [
d5b39a17
PN
865 'entity_id' => $contribution['id'],
866 'entity_table' => 'civicrm_contribution',
867 'financial_trxn_id' => $payment['id'],
d3b3ad06 868 ];
d5b39a17
PN
869 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
870 $this->assertEquals($eft['values'][$eft['id']]['amount'], 40);
d3b3ad06 871 $params = [
d5b39a17
PN
872 'entity_table' => 'civicrm_financial_item',
873 'financial_trxn_id' => $payment['id'],
d3b3ad06 874 ];
d5b39a17
PN
875 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
876 $this->assertEquals($eft['values'][$eft['id']]['amount'], 40);
877 // Check contribution for completed status
d3b3ad06 878 $contribution = $this->callAPISuccess('contribution', 'get', ['id' => $contribution['id']]);
0a201857 879 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status'], 'Unicorn');
d5b39a17 880 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 100.00);
d3b3ad06 881 $this->callAPISuccess('Contribution', 'Delete', [
d5b39a17 882 'id' => $contribution['id'],
d3b3ad06 883 ]);
0a201857 884 $this->callAPISuccess('OptionValue', 'get', ['name' => 'Completed', 'option_group_id' => 'contribution_status', 'api.OptionValue.create' => ['label' => 'Completed']]);
8d54448e 885 $this->callAPISuccessGetCount('Activity', ['target_contact_id' => $this->_individualId, 'activity_type_id' => 'Payment'], 2);
3d4f6f65 886 $this->validateAllPayments();
d5b39a17
PN
887 }
888
6cc6cb8c 889 /**
890 * Test that Payment.create uses the to_account of the payment processor.
891 *
892 * @throws \CiviCRM_API3_Exception
893 * @throws \CRM_Core_Exception
894 */
895 public function testPaymentWithProcessorWithOddFinancialAccount() {
896 $processor = $this->dummyProcessorCreate(['financial_account_id' => 'Deposit Bank Account', 'payment_instrument_id' => 'Cash']);
897 $processor2 = $this->dummyProcessorCreate(['financial_account_id' => 'Payment Processor Account', 'name' => 'p2', 'payment_instrument_id' => 'EFT']);
898 $contributionParams = [
899 'total_amount' => 100,
900 'currency' => 'USD',
901 'contact_id' => $this->_individualId,
902 'financial_type_id' => 1,
903 'contribution_status_id' => 'Pending',
904 ];
905 $order = $this->callAPISuccess('Order', 'create', $contributionParams);
906 $this->callAPISuccess('Payment', 'create', ['payment_processor_id' => $processor->getID(), 'total_amount' => 6, 'contribution_id' => $order['id']]);
907 $this->callAPISuccess('Payment', 'create', ['payment_processor_id' => $processor2->getID(), 'total_amount' => 15, 'contribution_id' => $order['id']]);
908 $payments = $this->callAPISuccess('Payment', 'get', ['sequential' => 1, 'contribution_id' => $order['id']])['values'];
909 $this->assertEquals('Deposit Bank Account', CRM_Core_PseudoConstant::getName('CRM_Core_BAO_FinancialTrxn', 'to_financial_account_id', $payments[0]['to_financial_account_id']));
910 $this->assertEquals('Payment Processor Account', CRM_Core_PseudoConstant::getName('CRM_Core_BAO_FinancialTrxn', 'to_financial_account_id', $payments[1]['to_financial_account_id']));
911 $this->assertEquals('Accounts Receivable', CRM_Core_PseudoConstant::getName('CRM_Core_BAO_FinancialTrxn', 'from_financial_account_id', $payments[0]['from_financial_account_id']));
912 $this->assertEquals('Accounts Receivable', CRM_Core_PseudoConstant::getName('CRM_Core_BAO_FinancialTrxn', 'from_financial_account_id', $payments[1]['from_financial_account_id']));
913 $this->assertEquals('Cash', CRM_Core_PseudoConstant::getName('CRM_Core_BAO_FinancialTrxn', 'payment_instrument_id', $payments[0]['payment_instrument_id']));
914 $this->assertEquals('EFT', CRM_Core_PseudoConstant::getName('CRM_Core_BAO_FinancialTrxn', 'payment_instrument_id', $payments[1]['payment_instrument_id']));
915 // $order = $this->callAPISuccessGetSingle('Order', ['id' => $processor->getID()]);
916 // $this->assertEquals('Cash', CRM_Core_PseudoConstant::getName('CRM_Core_BAO_FinancialTrxn', 'payment_instrument_id', $order['payment_instrument_id']));
917 }
918
0fad34a0 919 /**
920 * Add a location to our event.
921 *
922 * @param int $eventID
6cc6cb8c 923 *
924 * @throws \CRM_Core_Exception
0fad34a0 925 */
926 protected function addLocationToEvent($eventID) {
927 $addressParams = [
928 'name' => 'event place',
929 'street_address' => 'streety street',
930 'location_type_id' => 1,
931 'is_primary' => 1,
932 ];
933 // api requires contact_id - perhaps incorrectly but use add to get past that.
934 $address = CRM_Core_BAO_Address::add($addressParams);
935
936 $location = $this->callAPISuccess('LocBlock', 'create', ['address_id' => $address->id]);
937 $this->callAPISuccess('Event', 'create', [
938 'id' => $eventID,
939 'loc_block_id' => $location['id'],
940 'is_show_location' => TRUE,
941 ]);
3d4f6f65 942 $this->validateAllPayments();
0fad34a0 943 }
944
5049eefc 945 /**
946 * Check the created payment is valid.
947 *
948 * This is probably over-testing really since we are repetitively checking a basic function...
949 *
950 * @param int $paymentID
951 * @param int $contributionID
952 * @param int $amount
953 *
954 * @throws \CRM_Core_Exception
955 */
956 protected function checkPaymentIsValid($paymentID, $contributionID, $amount = 50) {
957 $payment = $this->callAPISuccess('Payment', 'getsingle', ['financial_trxn_id' => $paymentID]);
958 $this->assertEquals(7, $payment['from_financial_account_id']);
959 $this->assertEquals(6, $payment['to_financial_account_id']);
960 $this->assertEquals(1, $payment['status_id']);
961 $this->assertEquals(1, $payment['is_payment']);
962 $this->assertEquals($amount, $payment['total_amount']);
963
964 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', [
965 'entity_id' => $contributionID,
966 'entity_table' => 'civicrm_contribution',
967 'financial_trxn_id' => $payment['id'],
968 ]);
969
970 $this->assertEquals($eft['values'][$eft['id']]['amount'], $amount);
3d4f6f65 971 $this->validateAllPayments();
5049eefc 972 }
973
b7f554fe 974}