Merge pull request #15142 from eileenmcnaughton/pradeep2
[civicrm-core.git] / tests / phpunit / api / v3 / PaymentTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
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
28 /**
29 * Test APIv3 civicrm_contribute_* functions
30 *
31 * @package CiviCRM_APIv3
32 * @subpackage API_Contribution
33 * @group headless
34 */
35 class api_v3_PaymentTest extends CiviUnitTestCase {
36
37 protected $_individualId;
38
39 protected $_financialTypeId = 1;
40
41 protected $_apiversion;
42
43 public $debug = 0;
44
45 /**
46 * Setup function.
47 */
48 public function setUp() {
49 parent::setUp();
50
51 $this->_apiversion = 3;
52 $this->_individualId = $this->individualCreate();
53 CRM_Core_Config::singleton()->userPermissionClass->permissions = [];
54 }
55
56 /**
57 * Clean up after each test.
58 *
59 * @throws \Exception
60 */
61 public function tearDown() {
62 $this->quickCleanUpFinancialEntities();
63 $this->quickCleanup(['civicrm_uf_match']);
64 unset(CRM_Core_Config::singleton()->userPermissionClass->permissions);
65 parent::tearDown();
66 }
67
68 /**
69 * Test Get Payment api.
70 */
71 public function testGetPayment() {
72 $p = [
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,
79 ];
80 $contribution = $this->callAPISuccess('contribution', 'create', $p);
81
82 $params = [
83 'contribution_id' => $contribution['id'],
84 'check_permissions' => TRUE,
85 ];
86 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['access CiviCRM', 'administer CiviCRM'];
87 $payment = $this->callAPIFailure('payment', 'get', $params, 'API permission check failed for Payment/get call; insufficient permission: require access CiviCRM and access CiviContribute');
88
89 array_push(CRM_Core_Config::singleton()->userPermissionClass->permissions, 'access CiviContribute');
90 $payment = $this->callAPISuccess('payment', 'get', $params);
91
92 $payment = $this->callAPIAndDocument('payment', 'get', $params, __FUNCTION__, __FILE__);
93 $this->assertEquals(1, $payment['count']);
94
95 $expectedResult = [
96 $contribution['id'] => [
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,
102 ],
103 ];
104 $this->checkPaymentResult($payment, $expectedResult);
105 $this->callAPISuccess('Contribution', 'Delete', [
106 'id' => $contribution['id'],
107 ]);
108 }
109
110 /**
111 * Test email receipt for partial payment.
112 */
113 public function testPaymentEmailReceipt() {
114 $mut = new CiviMailUtils($this);
115 list($lineItems, $contribution) = $this->createParticipantWithContribution();
116 $event = $this->callAPISuccess('Event', 'get', []);
117 $this->addLocationToEvent($event['id']);
118 $params = [
119 'contribution_id' => $contribution['id'],
120 'total_amount' => 50,
121 'check_number' => '345',
122 'trxn_date' => '2018-08-13 17:57:56',
123 ];
124 $payment = $this->callAPISuccess('payment', 'create', $params);
125 $this->checkPaymentResult($payment, [
126 $payment['id'] => [
127 'from_financial_account_id' => 7,
128 'to_financial_account_id' => 6,
129 'total_amount' => 50,
130 'status_id' => 1,
131 'is_payment' => 1,
132 ],
133 ]);
134
135 $this->callAPISuccess('Payment', 'sendconfirmation', ['id' => $payment['id']]);
136 $mut->assertSubjects(['Payment Receipt - Annual CiviCRM meet']);
137 $mut->checkMailLog([
138 'Dear Anthony,',
139 'Total Fees: $ 300.00',
140 'This Payment Amount: $ 50.00',
141 //150 was paid in the 1st payment.
142 'Balance Owed: $ 100.00',
143 'Event Information and Location',
144 'Paid By: Check',
145 'Check Number: 345',
146 'Transaction Date: August 13th, 2018 5:57 PM',
147 'event place',
148 'streety street',
149 ]);
150 $mut->stop();
151 $mut->clearMessages();
152 }
153
154 /**
155 * Test email receipt for partial payment.
156 *
157 * @throws \CRM_Core_Exception
158 */
159 public function testPaymentEmailReceiptFullyPaid() {
160 $mut = new CiviMailUtils($this);
161 list($lineItems, $contribution) = $this->createParticipantWithContribution();
162
163 $params = [
164 'contribution_id' => $contribution['id'],
165 'total_amount' => 150,
166 ];
167 $payment = $this->callAPISuccess('payment', 'create', $params);
168
169 $this->callAPISuccess('Payment', 'sendconfirmation', ['id' => $payment['id']]);
170 $mut->assertSubjects(['Payment Receipt - Annual CiviCRM meet', 'Registration Confirmation - Annual CiviCRM meet']);
171 $mut->checkMailLog([
172 'Dear Anthony,',
173 'A payment has been received.',
174 'Total Fees: $ 300.00',
175 'This Payment Amount: $ 150.00',
176 'Balance Owed: $ 0.00',
177 'Thank you for completing payment.',
178 ]);
179 $mut->stop();
180 $mut->clearMessages();
181 }
182
183 /**
184 * Test email receipt for partial payment.
185 *
186 * @dataProvider getThousandSeparators
187 *
188 * @param string $thousandSeparator
189 */
190 public function testRefundEmailReceipt($thousandSeparator) {
191 $this->setCurrencySeparators($thousandSeparator);
192 $decimalSeparator = ($thousandSeparator === ',' ? '.' : ',');
193 $mut = new CiviMailUtils($this);
194 list($lineItems, $contribution) = $this->createParticipantWithContribution();
195 $this->callAPISuccess('payment', 'create', [
196 'contribution_id' => $contribution['id'],
197 'total_amount' => 50,
198 'check_number' => '345',
199 'trxn_date' => '2018-08-13 17:57:56',
200 ]);
201
202 $payment = $this->callAPISuccess('payment', 'create', [
203 'contribution_id' => $contribution['id'],
204 'total_amount' => -30,
205 'trxn_date' => '2018-11-13 12:01:56',
206 'sequential' => TRUE,
207 ])['values'][0];
208
209 $expected = [
210 'from_financial_account_id' => 7,
211 'to_financial_account_id' => 6,
212 'total_amount' => -30,
213 'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Core_BAO_FinancialTrxn', 'status_id', 'Refunded'),
214 'is_payment' => 1,
215 ];
216 foreach ($expected as $key => $value) {
217 $this->assertEquals($expected[$key], $payment[$key], 'mismatch on key ' . $key);
218 }
219
220 $this->callAPISuccess('Payment', 'sendconfirmation', ['id' => $payment['id']]);
221 $mut->assertSubjects(['Refund Notification - Annual CiviCRM meet']);
222 $mut->checkMailLog([
223 'Dear Anthony,',
224 'A refund has been issued based on changes in your registration selections.',
225 'Total Fees: $ 300' . $decimalSeparator . '00',
226 'Refund Amount: $ -30' . $decimalSeparator . '00',
227 'Event Information and Location',
228 'Paid By: Check',
229 'Transaction Date: November 13th, 2018 12:01 PM',
230 'You Paid: $ 170' . $decimalSeparator . '00',
231 ]);
232 $mut->stop();
233 $mut->clearMessages();
234 }
235
236 /**
237 * Test create payment api with no line item in params
238 */
239 public function testCreatePaymentNoLineItems() {
240 list($lineItems, $contribution) = $this->createParticipantWithContribution();
241
242 //Create partial payment
243 $params = [
244 'contribution_id' => $contribution['id'],
245 'total_amount' => 50,
246 ];
247 $payment = $this->callAPIAndDocument('payment', 'create', $params, __FUNCTION__, __FILE__);
248 $expectedResult = [
249 $payment['id'] => [
250 'from_financial_account_id' => 7,
251 'to_financial_account_id' => 6,
252 'total_amount' => 50,
253 'status_id' => 1,
254 'is_payment' => 1,
255 ],
256 ];
257 $this->checkPaymentResult($payment, $expectedResult);
258
259 // Check entity financial trxn created properly
260 $params = [
261 'entity_id' => $contribution['id'],
262 'entity_table' => 'civicrm_contribution',
263 'financial_trxn_id' => $payment['id'],
264 ];
265
266 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
267
268 $this->assertEquals($eft['values'][$eft['id']]['amount'], 50);
269
270 $params = [
271 'entity_table' => 'civicrm_financial_item',
272 'financial_trxn_id' => $payment['id'],
273 ];
274 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
275 $amounts = [33.33, 16.67];
276 foreach ($eft['values'] as $value) {
277 $this->assertEquals($value['amount'], array_pop($amounts));
278 }
279
280 // Now create payment to complete total amount of contribution
281 $params = [
282 'contribution_id' => $contribution['id'],
283 'total_amount' => 100,
284 ];
285 $payment = $this->callAPISuccess('payment', 'create', $params);
286 $expectedResult = [
287 $payment['id'] => [
288 'from_financial_account_id' => 7,
289 'to_financial_account_id' => 6,
290 'total_amount' => 100,
291 'status_id' => 1,
292 'is_payment' => 1,
293 ],
294 ];
295 $this->checkPaymentResult($payment, $expectedResult);
296 $params = [
297 'entity_table' => 'civicrm_financial_item',
298 'financial_trxn_id' => $payment['id'],
299 ];
300 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
301 $amounts = [66.67, 33.33];
302 foreach ($eft['values'] as $value) {
303 $this->assertEquals($value['amount'], array_pop($amounts));
304 }
305 // Check contribution for completed status
306 $contribution = $this->callAPISuccess('contribution', 'get', ['id' => $contribution['id']]);
307
308 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status'], 'Completed');
309 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 300.00);
310 $paymentParticipant = [
311 'contribution_id' => $contribution['id'],
312 ];
313 $participantPayment = $this->callAPISuccess('ParticipantPayment', 'getsingle', $paymentParticipant);
314 $participant = $this->callAPISuccess('participant', 'get', ['id' => $participantPayment['participant_id']]);
315 $this->assertEquals($participant['values'][$participant['id']]['participant_status'], 'Registered');
316 $this->callAPISuccess('Contribution', 'Delete', [
317 'id' => $contribution['id'],
318 ]);
319 }
320
321 /**
322 * Function to assert db values
323 */
324 public function checkPaymentResult($payment, $expectedResult) {
325 foreach ($expectedResult[$payment['id']] as $key => $value) {
326 $this->assertEquals($payment['values'][$payment['id']][$key], $value, 'mismatch on ' . $key);
327 }
328 }
329
330 /**
331 * Test create payment api with line item in params
332 */
333 public function testCreatePaymentLineItems() {
334 list($lineItems, $contribution) = $this->createParticipantWithContribution();
335 $lineItems = $this->callAPISuccess('LineItem', 'get', ['contribution_id' => $contribution['id']]);
336
337 //Create partial payment by passing line item array is params
338 $params = [
339 'contribution_id' => $contribution['id'],
340 'total_amount' => 50,
341 ];
342 $amounts = [40, 10];
343 foreach ($lineItems['values'] as $id => $ignore) {
344 $params['line_item'][] = [$id => array_pop($amounts)];
345 }
346 $payment = $this->callAPIAndDocument('payment', 'create', $params, __FUNCTION__, __FILE__, 'Payment with line item', 'CreatePaymentWithLineItems');
347 $expectedResult = [
348 $payment['id'] => [
349 'from_financial_account_id' => 7,
350 'to_financial_account_id' => 6,
351 'total_amount' => 50,
352 'status_id' => 1,
353 'is_payment' => 1,
354 ],
355 ];
356 $this->checkPaymentResult($payment, $expectedResult);
357
358 // Check entity financial trxn created properly
359 $params = [
360 'entity_id' => $contribution['id'],
361 'entity_table' => 'civicrm_contribution',
362 'financial_trxn_id' => $payment['id'],
363 ];
364
365 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
366
367 $this->assertEquals($eft['values'][$eft['id']]['amount'], 50);
368
369 $params = [
370 'entity_table' => 'civicrm_financial_item',
371 'financial_trxn_id' => $payment['id'],
372 ];
373 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
374 $amounts = [40, 10];
375 foreach ($eft['values'] as $value) {
376 $this->assertEquals($value['amount'], array_pop($amounts));
377 }
378
379 // Now create payment to complete total amount of contribution
380 $params = [
381 'contribution_id' => $contribution['id'],
382 'total_amount' => 100,
383 ];
384 $amounts = [80, 20];
385 foreach ($lineItems['values'] as $id => $ignore) {
386 $params['line_item'][] = [$id => array_pop($amounts)];
387 }
388 $payment = $this->callAPISuccess('payment', 'create', $params);
389 $expectedResult = [
390 $payment['id'] => [
391 'from_financial_account_id' => 7,
392 'to_financial_account_id' => 6,
393 'total_amount' => 100,
394 'status_id' => 1,
395 'is_payment' => 1,
396 ],
397 ];
398 $this->checkPaymentResult($payment, $expectedResult);
399 $params = [
400 'entity_table' => 'civicrm_financial_item',
401 'financial_trxn_id' => $payment['id'],
402 ];
403 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
404 $amounts = [80, 20];
405 foreach ($eft['values'] as $value) {
406 $this->assertEquals($value['amount'], array_pop($amounts));
407 }
408 // Check contribution for completed status
409 $contribution = $this->callAPISuccess('contribution', 'get', ['id' => $contribution['id']]);
410
411 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status'], 'Completed');
412 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 300.00);
413 $paymentParticipant = [
414 'contribution_id' => $contribution['id'],
415 ];
416 $participantPayment = $this->callAPISuccess('ParticipantPayment', 'getsingle', $paymentParticipant);
417 $participant = $this->callAPISuccess('participant', 'get', ['id' => $participantPayment['participant_id']]);
418 $this->assertEquals($participant['values'][$participant['id']]['participant_status'], 'Registered');
419 $this->callAPISuccess('Contribution', 'Delete', [
420 'id' => $contribution['id'],
421 ]);
422 }
423
424 /**
425 * Test cancel payment api
426 */
427 public function testCancelPayment() {
428 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['administer CiviCRM', 'access CiviContribute'];
429 list($lineItems, $contribution) = $this->createParticipantWithContribution();
430
431 $params = [
432 'contribution_id' => $contribution['id'],
433 ];
434
435 $payment = $this->callAPISuccess('payment', 'get', $params);
436 $this->assertEquals(1, $payment['count']);
437
438 $cancelParams = [
439 'id' => $payment['id'],
440 'check_permissions' => TRUE,
441 ];
442 $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');
443
444 array_push(CRM_Core_Config::singleton()->userPermissionClass->permissions, 'access CiviCRM', 'edit contributions');
445
446 $this->callAPIAndDocument('payment', 'cancel', $cancelParams, __FUNCTION__, __FILE__);
447
448 $payment = $this->callAPISuccess('payment', 'get', $params);
449 $this->assertEquals(2, $payment['count']);
450 $amounts = [-150.00, 150.00];
451 foreach ($payment['values'] as $value) {
452 $this->assertEquals($value['total_amount'], array_pop($amounts), 'Mismatch total amount');
453 }
454
455 $this->callAPISuccess('Contribution', 'Delete', [
456 'id' => $contribution['id'],
457 ]);
458 }
459
460 /**
461 * Test delete payment api
462 */
463 public function testDeletePayment() {
464 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['administer CiviCRM', 'access CiviContribute'];
465 list($lineItems, $contribution) = $this->createParticipantWithContribution();
466
467 $params = [
468 'contribution_id' => $contribution['id'],
469 ];
470
471 $payment = $this->callAPISuccess('payment', 'get', $params);
472 $this->assertEquals(1, $payment['count']);
473
474 $deleteParams = [
475 'id' => $payment['id'],
476 'check_permissions' => TRUE,
477 ];
478 $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');
479
480 array_push(CRM_Core_Config::singleton()->userPermissionClass->permissions, 'access CiviCRM', 'delete in CiviContribute');
481 $this->callAPIAndDocument('payment', 'delete', $deleteParams, __FUNCTION__, __FILE__);
482
483 $payment = $this->callAPISuccess('payment', 'get', $params);
484 $this->assertEquals(0, $payment['count']);
485
486 $this->callAPISuccess('Contribution', 'Delete', [
487 'id' => $contribution['id'],
488 ]);
489 }
490
491 /**
492 * Test update payment api.
493 *
494 * 1) create a contribution for $300 with a partial payment of $150
495 * - this results in 2 financial transactions. The accounts receivable transaction is linked
496 * via entity_financial_trxns to the 2 line items. The $150 payment is not linked to the line items
497 * so the line items are fully allocated even though they are only half paid.
498 *
499 * 2) add a payment of $50 -
500 * This payment transaction IS linked to the line items so $350 of the $300 in line items is allocated
501 * but $200 is paid
502 *
503 * 3) update that payment to be $100
504 * This results in a negative and a positive payment ($50 & $100) - the negative payment results in
505 * financial_items but the positive payment does not.
506 *
507 * The final result is we have
508 * - 1 partly paid contribution of $300
509 * - payment financial_trxns totalling $250
510 * - 1 Accounts receivable financial_trxn totalling $300
511 * - 2 financial items totalling $300 linked to the Accounts receivable financial_trxn
512 * - 6 entries in the civicrm_entity_financial_trxn linked to line items - totalling $450.
513 * - 5 entries in the civicrm_entity_financial_trxn linked to contributions - totalling $550.
514 */
515 public function testUpdatePayment() {
516 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['administer CiviCRM', 'access CiviContribute', 'edit contributions'];
517 list($lineItems, $contribution) = $this->createParticipantWithContribution();
518
519 //Create partial payment by passing line item array is params
520 $params = [
521 'contribution_id' => $contribution['id'],
522 'total_amount' => 50,
523 ];
524
525 $payment = $this->callAPISuccess('payment', 'create', $params);
526 $expectedResult = [
527 $payment['id'] => [
528 'from_financial_account_id' => 7,
529 'to_financial_account_id' => 6,
530 'total_amount' => 50,
531 'status_id' => 1,
532 'is_payment' => 1,
533 ],
534 ];
535 $this->checkPaymentResult($payment, $expectedResult);
536
537 $params = [
538 'entity_table' => 'civicrm_financial_item',
539 'financial_trxn_id' => $payment['id'],
540 ];
541 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
542 $amounts = [33.33, 16.67];
543 foreach ($eft['values'] as $value) {
544 $this->assertEquals($value['amount'], array_pop($amounts));
545 }
546
547 // update the amount for payment
548 $params = [
549 'contribution_id' => $contribution['id'],
550 'total_amount' => 100,
551 'id' => $payment['id'],
552 'check_permissions' => TRUE,
553 ];
554 // @todo - move this permissions test to it's own test - it just confuses here.
555 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['administer CiviCRM', 'access CiviContribute'];
556 $this->callAPIFailure('payment', 'create', $params, 'API permission check failed for Payment/create call; insufficient permission: require access CiviCRM and access CiviContribute and edit contributions');
557
558 CRM_Core_Config::singleton()->userPermissionClass->permissions = ['administer CiviCRM', 'access CiviContribute', 'access CiviCRM', 'edit contributions'];
559 $payment = $this->callAPIAndDocument('payment', 'create', $params, __FUNCTION__, __FILE__, 'Update Payment', 'UpdatePayment');
560
561 // Check for proportional cancelled payment against lineitems.
562 $minParams = [
563 'entity_table' => 'civicrm_financial_item',
564 'financial_trxn_id' => $payment['id'] - 1,
565 ];
566
567 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $minParams);
568 $amounts = [-33.33, -16.67];
569
570 foreach ($eft['values'] as $value) {
571 $this->assertEquals($value['amount'], array_pop($amounts));
572 }
573
574 // Check for proportional updated payment against lineitems.
575 $params = [
576 'entity_table' => 'civicrm_financial_item',
577 'financial_trxn_id' => $payment['id'],
578 ];
579 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
580 $amounts = [66.67, 33.33];
581 foreach ($eft['values'] as $value) {
582 $this->assertEquals($value['amount'], array_pop($amounts));
583 }
584 $items = $this->callAPISuccess('FinancialItem', 'get', [])['values'];
585 $this->assertCount(2, $items);
586 $itemSum = 0;
587 foreach ($items as $item) {
588 $this->assertEquals('civicrm_line_item', $item['entity_table']);
589 $itemSum += $item['amount'];
590 }
591 $this->assertEquals(300, $itemSum);
592
593 $params = [
594 'contribution_id' => $contribution['id'],
595 ];
596 $payment = $this->callAPISuccess('payment', 'get', $params);
597 $amounts = [100.00, -50.00, 50.00, 150.00];
598 foreach ($payment['values'] as $value) {
599 $amount = array_pop($amounts);
600 $this->assertEquals($value['total_amount'], $amount, 'Mismatch total amount');
601
602 // Check entity financial trxn created properly
603 $params = [
604 'entity_id' => $contribution['id'],
605 'entity_table' => 'civicrm_contribution',
606 'financial_trxn_id' => $value['id'],
607 ];
608 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
609 $this->assertEquals($eft['values'][$eft['id']]['amount'], $amount);
610 }
611
612 $this->callAPISuccess('Contribution', 'Delete', [
613 'id' => $contribution['id'],
614 ]);
615 }
616
617 /**
618 * Test create payment api for paylater contribution
619 */
620 public function testCreatePaymentPayLater() {
621 $this->createLoggedInUser();
622 $contributionParams = [
623 'total_amount' => 100,
624 'currency' => 'USD',
625 'contact_id' => $this->_individualId,
626 'financial_type_id' => 1,
627 'contribution_status_id' => 2,
628 'is_pay_later' => 1,
629 ];
630 $contribution = $this->callAPISuccess('Contribution', 'create', $contributionParams);
631 //add payment for pay later transaction
632 $params = [
633 'contribution_id' => $contribution['id'],
634 'total_amount' => 100,
635 ];
636 $payment = $this->callAPISuccess('Payment', 'create', $params);
637 $expectedResult = [
638 $payment['id'] => [
639 'from_financial_account_id' => 7,
640 'to_financial_account_id' => 6,
641 'total_amount' => 100,
642 'status_id' => 1,
643 'is_payment' => 1,
644 ],
645 ];
646 $this->checkPaymentResult($payment, $expectedResult);
647 // Check entity financial trxn created properly
648 $params = [
649 'entity_id' => $contribution['id'],
650 'entity_table' => 'civicrm_contribution',
651 'financial_trxn_id' => $payment['id'],
652 ];
653 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
654 $this->assertEquals($eft['values'][$eft['id']]['amount'], 100);
655 $params = [
656 'entity_table' => 'civicrm_financial_item',
657 'financial_trxn_id' => $payment['id'],
658 ];
659 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
660 $this->assertEquals($eft['values'][$eft['id']]['amount'], 100);
661 // Check contribution for completed status
662 $contribution = $this->callAPISuccess('contribution', 'get', ['id' => $contribution['id']]);
663 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status'], 'Completed');
664 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 100.00);
665 $this->callAPISuccess('Contribution', 'Delete', [
666 'id' => $contribution['id'],
667 ]);
668 }
669
670 /**
671 * Test create payment api for pay later contribution with partial payment.
672 *
673 * @throws \Exception
674 */
675 public function testCreatePaymentPayLaterPartialPayment() {
676 $this->createLoggedInUser();
677 $contributionParams = [
678 'total_amount' => 100,
679 'currency' => 'USD',
680 'contact_id' => $this->_individualId,
681 'financial_type_id' => 1,
682 'contribution_status_id' => 2,
683 'is_pay_later' => 1,
684 ];
685 $contribution = $this->callAPISuccess('Contribution', 'create', $contributionParams);
686 //Create partial payment
687 $params = [
688 'contribution_id' => $contribution['id'],
689 'total_amount' => 60,
690 ];
691 $payment = $this->callAPISuccess('Payment', 'create', $params);
692 $expectedResult = [
693 $payment['id'] => [
694 'total_amount' => 60,
695 'status_id' => 1,
696 'is_payment' => 1,
697 ],
698 ];
699 $this->checkPaymentResult($payment, $expectedResult);
700 // Check entity financial trxn created properly
701 $params = [
702 'entity_id' => $contribution['id'],
703 'entity_table' => 'civicrm_contribution',
704 'financial_trxn_id' => $payment['id'],
705 ];
706 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
707 $this->assertEquals($eft['values'][$eft['id']]['amount'], 60);
708 $params = [
709 'entity_table' => 'civicrm_financial_item',
710 'financial_trxn_id' => $payment['id'],
711 ];
712 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
713 $this->assertEquals($eft['values'][$eft['id']]['amount'], 60);
714 $contribution = $this->callAPISuccess('contribution', 'get', ['id' => $contribution['id']]);
715 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status'], 'Partially paid');
716 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 100.00);
717 //Create full payment
718 $params = [
719 'contribution_id' => $contribution['id'],
720 'total_amount' => 40,
721 ];
722 // Rename the 'completed' status label first to check that we are not using the labels!
723 $this->callAPISuccess('OptionValue', 'get', ['name' => 'Completed', 'option_group_id' => 'contribution_status', 'api.OptionValue.create' => ['label' => 'Unicorn']]);
724 $payment = $this->callAPISuccess('Payment', 'create', $params);
725 $expectedResult = [
726 $payment['id'] => [
727 'from_financial_account_id' => 7,
728 'to_financial_account_id' => 6,
729 'total_amount' => 40,
730 'status_id' => 1,
731 'is_payment' => 1,
732 ],
733 ];
734 $this->checkPaymentResult($payment, $expectedResult);
735 // Check entity financial trxn created properly
736 $params = [
737 'entity_id' => $contribution['id'],
738 'entity_table' => 'civicrm_contribution',
739 'financial_trxn_id' => $payment['id'],
740 ];
741 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
742 $this->assertEquals($eft['values'][$eft['id']]['amount'], 40);
743 $params = [
744 'entity_table' => 'civicrm_financial_item',
745 'financial_trxn_id' => $payment['id'],
746 ];
747 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
748 $this->assertEquals($eft['values'][$eft['id']]['amount'], 40);
749 // Check contribution for completed status
750 $contribution = $this->callAPISuccess('contribution', 'get', ['id' => $contribution['id']]);
751 $this->assertEquals($contribution['values'][$contribution['id']]['contribution_status'], 'Unicorn');
752 $this->assertEquals($contribution['values'][$contribution['id']]['total_amount'], 100.00);
753 $this->callAPISuccess('Contribution', 'Delete', [
754 'id' => $contribution['id'],
755 ]);
756 $this->callAPISuccess('OptionValue', 'get', ['name' => 'Completed', 'option_group_id' => 'contribution_status', 'api.OptionValue.create' => ['label' => 'Completed']]);
757 $this->callAPISuccessGetCount('Activity', ['target_contact_id' => $this->_individualId, 'activity_type_id' => 'Payment'], 2);
758 }
759
760 /**
761 * Add a location to our event.
762 *
763 * @param int $eventID
764 */
765 protected function addLocationToEvent($eventID) {
766 $addressParams = [
767 'name' => 'event place',
768 'street_address' => 'streety street',
769 'location_type_id' => 1,
770 'is_primary' => 1,
771 ];
772 // api requires contact_id - perhaps incorrectly but use add to get past that.
773 $address = CRM_Core_BAO_Address::add($addressParams);
774
775 $location = $this->callAPISuccess('LocBlock', 'create', ['address_id' => $address->id]);
776 $this->callAPISuccess('Event', 'create', [
777 'id' => $eventID,
778 'loc_block_id' => $location['id'],
779 'is_show_location' => TRUE,
780 ]);
781 }
782
783 }