3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
29 * Test APIv3 civicrm_contribute_* functions
31 * @package CiviCRM_APIv3
32 * @subpackage API_Contribution
35 class api_v3_OrderTest
extends CiviUnitTestCase
{
37 protected $_individualId;
38 protected $_financialTypeId = 1;
44 * @throws \CRM_Core_Exception
46 public function setUp() {
49 $this->_apiversion
= 3;
50 $this->_individualId
= $this->individualCreate();
54 * Clean up after each test.
56 * @throws \CRM_Core_Exception
58 public function tearDown() {
59 $this->quickCleanUpFinancialEntities();
60 $this->quickCleanup(['civicrm_uf_match']);
66 public function testGetOrder() {
67 $contribution = $this->addOrder(FALSE, 100);
70 'contribution_id' => $contribution['id'],
73 $order = $this->callAPIAndDocument('Order', 'get', $params, __FUNCTION__
, __FILE__
);
75 $this->assertEquals(1, $order['count']);
77 $contribution['id'] => [
78 'total_amount' => 100,
79 'contribution_id' => $contribution['id'],
80 'contribution_status' => 'Completed',
85 'entity_table' => 'civicrm_contribution',
86 'entity_id' => $contribution['id'],
87 'contribution_id' => $contribution['id'],
90 'financial_type_id' => 1,
92 $this->checkPaymentResult($order, $expectedResult, $lineItems);
93 $this->callAPISuccess('Contribution', 'Delete', [
94 'id' => $contribution['id'],
99 * Test Get Order api for participant contribution.
101 public function testGetOrderParticipant() {
102 $this->addOrder(FALSE, 100);
103 list($items, $contribution) = $this->createParticipantWithContribution();
106 'contribution_id' => $contribution['id'],
109 $order = $this->callAPISuccess('Order', 'get', $params);
111 $this->assertEquals(2, count($order['values'][$contribution['id']]['line_items']));
112 $this->callAPISuccess('Contribution', 'Delete', [
113 'id' => $contribution['id'],
118 * Function to assert db values.
120 public function checkPaymentResult($results, $expectedResult, $lineItems = NULL) {
121 foreach ($expectedResult[$results['id']] as $key => $value) {
122 $this->assertEquals($results['values'][$results['id']][$key], $value);
126 foreach ($lineItems as $key => $items) {
127 foreach ($items as $k => $item) {
128 $this->assertEquals($results['values'][$results['id']]['line_items'][$key][$k], $item);
137 * @param bool $isPriceSet
138 * @param float $amount
139 * @param array $extraParams
143 public function addOrder($isPriceSet, $amount = 300.00, $extraParams = []) {
145 'contact_id' => $this->_individualId
,
146 'receive_date' => '2010-01-20',
147 'total_amount' => $amount,
148 'financial_type_id' => $this->_financialTypeId
,
149 'contribution_status_id' => 1,
153 $priceFields = $this->createPriceSet();
154 foreach ($priceFields['values'] as $key => $priceField) {
155 $lineItems[1][$key] = [
156 'price_field_id' => $priceField['price_field_id'],
157 'price_field_value_id' => $priceField['id'],
158 'label' => $priceField['label'],
159 'field_title' => $priceField['label'],
161 'unit_price' => $priceField['amount'],
162 'line_total' => $priceField['amount'],
163 'financial_type_id' => $priceField['financial_type_id'],
166 $p['line_item'] = $lineItems;
168 $p = array_merge($extraParams, $p);
169 return $this->callAPISuccess('Contribution', 'create', $p);
173 * Test create order api
175 public function testAddOrder() {
176 $order = $this->addOrder(FALSE, 100);
178 'contribution_id' => $order['id'],
180 $order = $this->callAPISuccess('order', 'get', $params);
183 'total_amount' => 100,
184 'contribution_id' => $order['id'],
185 'contribution_status' => 'Completed',
190 'entity_table' => 'civicrm_contribution',
191 'entity_id' => $order['id'],
192 'contribution_id' => $order['id'],
195 'financial_type_id' => 1,
197 $this->checkPaymentResult($order, $expectedResult, $lineItems);
198 $this->callAPISuccess('Contribution', 'Delete', [
199 'id' => $order['id'],
204 * Test create order api for membership
206 * @throws \CRM_Core_Exception
208 public function testAddOrderForMembership() {
209 $membershipType = $this->membershipTypeCreate();
210 $membershipType1 = $this->membershipTypeCreate();
211 $membershipType = $membershipTypes = [$membershipType, $membershipType1];
213 'contact_id' => $this->_individualId
,
214 'receive_date' => '2010-01-20',
215 'financial_type_id' => 'Event Fee',
216 'contribution_status_id' => 'Pending',
218 $priceFields = $this->createPriceSet();
219 foreach ($priceFields['values'] as $key => $priceField) {
221 'price_field_id' => $priceField['price_field_id'],
222 'price_field_value_id' => $priceField['id'],
223 'label' => $priceField['label'],
224 'field_title' => $priceField['label'],
226 'unit_price' => $priceField['amount'],
227 'line_total' => $priceField['amount'],
228 'financial_type_id' => $priceField['financial_type_id'],
229 'entity_table' => 'civicrm_membership',
230 'membership_type_id' => array_pop($membershipType),
233 $p['line_items'][] = [
234 'line_item' => [array_pop($lineItems)],
236 'contact_id' => $this->_individualId
,
237 'membership_type_id' => array_pop($membershipTypes),
238 'join_date' => '2006-01-21',
239 'start_date' => '2006-01-21',
240 'end_date' => '2006-12-21',
241 'source' => 'Payment',
245 $order = $this->callAPIAndDocument('order', 'create', $p, __FUNCTION__
, __FILE__
);
247 'contribution_id' => $order['id'],
249 $order = $this->callAPISuccess('order', 'get', $params);
252 'total_amount' => 200,
253 'contribution_id' => $order['id'],
254 'contribution_status' => 'Pending Label**',
258 $this->checkPaymentResult($order, $expectedResult);
259 $this->callAPISuccessGetCount('MembershipPayment', $params, 1);
260 $this->callAPISuccess('Contribution', 'Delete', [
261 'id' => $order['id'],
263 $p['line_items'][] = [
264 'line_item' => [array_pop($lineItems)],
266 'contact_id' => $this->_individualId
,
267 'membership_type_id' => array_pop($membershipTypes),
268 'join_date' => '2006-01-21',
269 'start_date' => '2006-01-21',
270 'end_date' => '2006-12-21',
271 'source' => 'Payment',
273 'status_id' => 'Pending',
276 $p['total_amount'] = 300;
277 $order = $this->callAPISuccess('order', 'create', $p);
280 'total_amount' => 300,
281 'contribution_status' => 'Pending Label**',
285 $paymentMembership = [
286 'contribution_id' => $order['id'],
288 $order = $this->callAPISuccess('order', 'get', $paymentMembership);
289 $this->checkPaymentResult($order, $expectedResult);
290 $this->callAPISuccessGetCount('MembershipPayment', $paymentMembership, 2);
291 $this->callAPISuccess('Contribution', 'Delete', [
292 'id' => $order['id'],
297 * Test create order api for participant
299 * @throws \CRM_Core_Exception
301 public function testAddOrderForParticipant() {
302 $event = $this->eventCreate();
303 $this->_eventId
= $event['id'];
305 'contact_id' => $this->_individualId
,
306 'receive_date' => '2010-01-20',
307 'financial_type_id' => $this->_financialTypeId
,
308 'contribution_status_id' => 'Pending',
310 $priceFields = $this->createPriceSet();
311 foreach ($priceFields['values'] as $key => $priceField) {
313 'price_field_id' => $priceField['price_field_id'],
314 'price_field_value_id' => $priceField['id'],
315 'label' => $priceField['label'],
316 'field_title' => $priceField['label'],
318 'unit_price' => $priceField['amount'],
319 'line_total' => $priceField['amount'],
320 'financial_type_id' => $priceField['financial_type_id'],
321 'entity_table' => 'civicrm_participant',
324 $p['line_items'][] = [
325 'line_item' => $lineItems,
327 'contact_id' => $this->_individualId
,
328 'event_id' => $this->_eventId
,
330 'register_date' => '2007-07-21 00:00:00',
331 'source' => 'Online Event Registration: API Testing',
335 $order = $this->callAPIAndDocument('order', 'create', $p, __FUNCTION__
, __FILE__
, 'Create order for participant', 'CreateOrderParticipant');
336 $params = ['contribution_id' => $order['id']];
337 $order = $this->callAPISuccess('order', 'get', $params);
340 'total_amount' => 300,
341 'contribution_id' => $order['id'],
342 'contribution_status' => 'Pending Label**',
346 $this->checkPaymentResult($order, $expectedResult);
347 $paymentParticipant = $this->callAPISuccessGetSingle('ParticipantPayment', ['contribution_id' => $order['id']]);
348 $participant = $this->callAPISuccessGetSingle('Participant', ['participant_id' => $paymentParticipant['participant_id']]);
349 $this->assertEquals('Pending (incomplete transaction)', $participant['participant_status']);
350 $this->callAPISuccess('Contribution', 'Delete', [
351 'id' => $order['id'],
354 $p['line_items'][] = [
355 'line_item' => $lineItems,
357 'contact_id' => $this->individualCreate(),
358 'event_id' => $this->_eventId
,
360 'register_date' => '2007-07-21 00:00:00',
361 'source' => 'Online Event Registration: API Testing',
365 $order = $this->callAPISuccess('order', 'create', $p);
368 'total_amount' => 600,
369 'contribution_status' => 'Pending Label**',
373 $paymentParticipant = [
374 'contribution_id' => $order['id'],
376 $order = $this->callAPISuccess('order', 'get', $paymentParticipant);
377 $this->checkPaymentResult($order, $expectedResult);
378 $this->callAPISuccessGetCount('ParticipantPayment', $paymentParticipant, 2);
379 $this->callAPISuccess('Contribution', 'Delete', [
380 'id' => $order['id'],
385 * Test create order api with line items
387 public function testAddOrderWithLineItems() {
388 $order = $this->addOrder(TRUE);
390 'contribution_id' => $order['id'],
392 $order = $this->callAPISuccess('order', 'get', $params);
395 'total_amount' => 300,
396 'contribution_id' => $order['id'],
397 'contribution_status' => 'Completed',
402 'entity_table' => 'civicrm_contribution',
403 'entity_id' => $order['id'],
404 'contribution_id' => $order['id'],
409 'entity_table' => 'civicrm_contribution',
410 'entity_id' => $order['id'],
411 'contribution_id' => $order['id'],
415 $this->checkPaymentResult($order, $expectedResult, $items);
417 'entity_table' => 'civicrm_contribution',
418 'entity_id' => $order['id'],
420 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
421 $this->assertEquals($eft['values'][$eft['id']]['amount'], 300);
423 'entity_table' => 'civicrm_financial_item',
424 'financial_trxn_id' => $eft['values'][$eft['id']]['financial_trxn_id'],
426 $eft = $this->callAPISuccess('EntityFinancialTrxn', 'get', $params);
427 $amounts = [200, 100];
428 foreach ($eft['values'] as $value) {
429 $this->assertEquals($value['amount'], array_pop($amounts));
431 $this->callAPISuccess('Contribution', 'Delete', [
432 'id' => $order['id'],
437 * Test delete order api
439 public function testDeleteOrder() {
440 $order = $this->addOrder(FALSE, 100);
442 'contribution_id' => $order['id'],
445 $this->callAPISuccess('order', 'delete', $params);
446 $this->fail("Missed expected exception");
448 catch (Exception
$expected) {
449 $this->callAPISuccess('Contribution', 'create', [
450 'contribution_id' => $order['id'],
453 $this->callAPIAndDocument('order', 'delete', $params, __FUNCTION__
, __FILE__
);
454 $order = $this->callAPISuccess('order', 'get', $params);
455 $this->assertEquals(0, $order['count']);
460 * Test cancel order api
462 public function testCancelOrder() {
463 $contribution = $this->addOrder(FALSE, 100);
465 'contribution_id' => $contribution['id'],
467 $this->callAPIAndDocument('order', 'cancel', $params, __FUNCTION__
, __FILE__
);
468 $order = $this->callAPISuccess('Order', 'get', $params);
470 $contribution['id'] => [
471 'total_amount' => 100,
472 'contribution_id' => $contribution['id'],
473 'contribution_status' => 'Cancelled',
477 $this->checkPaymentResult($order, $expectedResult);
478 $this->callAPISuccess('Contribution', 'Delete', [
479 'id' => $contribution['id'],
484 * Test cancel order api
486 public function testCancelWithParticipant() {
487 $event = $this->eventCreate();
488 $this->_eventId
= $event['id'];
490 'id' => $this->_eventId
,
491 'financial_type_id' => 4,
494 $this->callAPISuccess('event', 'create', $eventParams);
495 $participantParams = [
496 'financial_type_id' => 4,
497 'event_id' => $this->_eventId
,
500 'fee_currency' => 'USD',
501 'contact_id' => $this->_individualId
,
503 $participant = $this->callAPISuccess('Participant', 'create', $participantParams);
505 'contribution_mode' => 'participant',
506 'participant_id' => $participant['id'],
508 $contribution = $this->addOrder(TRUE, 100, $extraParams);
509 $paymentParticipant = [
510 'participant_id' => $participant['id'],
511 'contribution_id' => $contribution['id'],
513 $this->callAPISuccess('ParticipantPayment', 'create', $paymentParticipant);
515 'contribution_id' => $contribution['id'],
517 $this->callAPISuccess('order', 'cancel', $params);
518 $order = $this->callAPISuccess('Order', 'get', $params);
520 $contribution['id'] => [
521 'total_amount' => 100,
522 'contribution_id' => $contribution['id'],
523 'contribution_status' => 'Cancelled',
527 $this->checkPaymentResult($order, $expectedResult);
528 $participantPayment = $this->callAPISuccess('ParticipantPayment', 'getsingle', $params);
529 $participant = $this->callAPISuccess('participant', 'get', ['id' => $participantPayment['participant_id']]);
530 $this->assertEquals($participant['values'][$participant['id']]['participant_status'], 'Cancelled');
531 $this->callAPISuccess('Contribution', 'Delete', [
532 'id' => $contribution['id'],
537 * Test an exception is thrown if line items do not add up to total_amount, no tax.
539 public function testCreateOrderIfTotalAmountDoesNotMatchLineItemsAmountsIfNoTaxSupplied() {
541 'contact_id' => $this->_individualId
,
542 'receive_date' => '2018-01-01',
543 'total_amount' => 50,
544 'financial_type_id' => $this->_financialTypeId
,
545 'contribution_status_id' => 'Pending',
550 'price_field_id' => 1,
551 'price_field_value_id' => 1,
553 'field_title' => 'Test 1',
557 'financial_type_id' => 1,
558 'entity_table' => 'civicrm_contribution',
565 $this->callAPIFailure('Order', 'create', $params, 'Line item total doesn\'t match with total amount');
569 * Test an exception is thrown if line items do not add up to total_amount, with tax.
571 public function testCreateOrderIfTotalAmountDoesNotMatchLineItemsAmountsIfTaxSupplied() {
573 'contact_id' => $this->_individualId
,
574 'receive_date' => '2018-01-01',
575 'total_amount' => 50,
576 'financial_type_id' => $this->_financialTypeId
,
577 'contribution_status_id' => 'Pending',
583 'price_field_id' => 1,
584 'price_field_value_id' => 1,
586 'field_title' => 'Test 1',
590 'financial_type_id' => 1,
591 'entity_table' => 'civicrm_contribution',
599 $this->callAPIFailure('Order', 'create', $params, 'Line item total doesn\'t match with total amount.');
602 public function testCreateOrderIfTotalAmountDoesMatchLineItemsAmountsAndTaxSupplied() {
604 'contact_id' => $this->_individualId
,
605 'receive_date' => '2018-01-01',
606 'total_amount' => 50,
607 'financial_type_id' => $this->_financialTypeId
,
608 'contribution_status_id' => 'Pending',
614 'price_field_id' => 1,
615 'price_field_value_id' => 1,
617 'field_title' => 'Test 1',
621 'financial_type_id' => 1,
622 'entity_table' => 'civicrm_contribution',
630 $order = $this->callAPISuccess('Order', 'create', $params);
631 $this->assertEquals(1, $order['count']);