Commit | Line | Data |
---|---|---|
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 | */ |
35 | class 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 | } |