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