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