CRM-20413 fix to setting wrong payment_instrument_id, by passing responsibility to...
[civicrm-core.git] / tests / phpunit / api / v3 / ContributionPageTest.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
81621fee 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
15a4309a 6 | Copyright CiviCRM LLC (c) 2004-2017 |
6a488035
TO
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035 27
6a488035
TO
28/**
29 * Test APIv3 civicrm_contribute_recur* functions
30 *
6c6e6187
TO
31 * @package CiviCRM_APIv3
32 * @subpackage API_Contribution
acb109b7 33 * @group headless
6a488035 34 */
6a488035
TO
35class api_v3_ContributionPageTest extends CiviUnitTestCase {
36 protected $_apiversion = 3;
37 protected $testAmount = 34567;
38 protected $params;
39 protected $id = 0;
40 protected $contactIds = array();
41 protected $_entity = 'contribution_page';
6c6e6187 42 protected $contribution_result = NULL;
f64a217a 43 protected $_priceSetParams = array();
f8fe0df6 44 /**
eceb18cc 45 * Payment processor details.
f8fe0df6 46 * @var array
47 */
48 protected $_paymentProcessor = array();
f64a217a
EM
49
50 /**
51 * @var array
16b10e64
CW
52 * - contribution_page
53 * - price_set
54 * - price_field
55 * - price_field_value
f64a217a
EM
56 */
57 protected $_ids = array();
58
b7c9bc4c 59
6a488035 60 public $DBResetRequired = TRUE;
5896d037 61
6a488035
TO
62 public function setUp() {
63 parent::setUp();
64 $this->contactIds[] = $this->individualCreate();
65 $this->params = array(
6a488035
TO
66 'title' => "Test Contribution Page",
67 'financial_type_id' => 1,
68 'currency' => 'NZD',
69 'goal_amount' => $this->testAmount,
6cdac50b 70 'is_pay_later' => 1,
f64a217a 71 'is_monetary' => TRUE,
dd1b539a 72 'is_email_receipt' => TRUE,
73 'receipt_from_email' => 'yourconscience@donate.com',
74 'receipt_from_name' => 'Ego Freud',
f64a217a
EM
75 );
76
77 $this->_priceSetParams = array(
78 'is_quick_config' => 1,
79 'extends' => 'CiviContribute',
80 'financial_type_id' => 'Donation',
21dfd5f5 81 'title' => 'my Page',
6a488035
TO
82 );
83 }
84
00be9182 85 public function tearDown() {
6a488035 86 foreach ($this->contactIds as $id) {
fc928539 87 $this->callAPISuccess('contact', 'delete', array('id' => $id));
611c7ece 88 }
f9342903 89 $this->quickCleanUpFinancialEntities();
6a488035
TO
90 }
91
92 public function testCreateContributionPage() {
fc928539 93 $result = $this->callAPIAndDocument($this->_entity, 'create', $this->params, __FUNCTION__, __FILE__);
94 $this->assertEquals(1, $result['count']);
95 $this->assertNotNull($result['values'][$result['id']]['id']);
6a488035
TO
96 $this->getAndCheck($this->params, $result['id'], $this->_entity);
97 }
98
99 public function testGetBasicContributionPage() {
fc928539 100 $createResult = $this->callAPISuccess($this->_entity, 'create', $this->params);
6a488035 101 $this->id = $createResult['id'];
6a488035 102 $getParams = array(
6a488035
TO
103 'currency' => 'NZD',
104 'financial_type_id' => 1,
105 );
fc928539 106 $getResult = $this->callAPIAndDocument($this->_entity, 'get', $getParams, __FUNCTION__, __FILE__);
107 $this->assertEquals(1, $getResult['count']);
6a488035
TO
108 }
109
110 public function testGetContributionPageByAmount() {
fc928539 111 $createResult = $this->callAPISuccess($this->_entity, 'create', $this->params);
6a488035 112 $this->id = $createResult['id'];
6a488035 113 $getParams = array(
5896d037 114 'amount' => '' . $this->testAmount, // 3456
6a488035
TO
115 'currency' => 'NZD',
116 'financial_type_id' => 1,
117 );
5be22f39 118 $getResult = $this->callAPISuccess($this->_entity, 'get', $getParams);
fc928539 119 $this->assertEquals(1, $getResult['count']);
6a488035
TO
120 }
121
122 public function testDeleteContributionPage() {
fc928539 123 $createResult = $this->callAPISuccess($this->_entity, 'create', $this->params);
124 $deleteParams = array('id' => $createResult['id']);
611c7ece 125 $this->callAPIAndDocument($this->_entity, 'delete', $deleteParams, __FUNCTION__, __FILE__);
fc928539 126 $checkDeleted = $this->callAPISuccess($this->_entity, 'get', array());
127 $this->assertEquals(0, $checkDeleted['count']);
6a488035
TO
128 }
129
130 public function testGetFieldsContributionPage() {
fc928539 131 $result = $this->callAPISuccess($this->_entity, 'getfields', array('action' => 'create'));
6a488035
TO
132 $this->assertEquals(12, $result['values']['start_date']['type']);
133 }
134
be26f3e0 135
d58b453e 136 /**
eceb18cc 137 * Test form submission with basic price set.
d58b453e 138 */
be26f3e0 139 public function testSubmit() {
f64a217a
EM
140 $this->setUpContributionPage();
141 $priceFieldID = reset($this->_ids['price_field']);
142 $priceFieldValueID = reset($this->_ids['price_field_value']);
143 $submitParams = array(
144 'price_' . $priceFieldID => $priceFieldValueID,
145 'id' => (int) $this->_ids['contribution_page'],
21dfd5f5 146 'amount' => 10,
be26f3e0
EM
147 );
148
f64a217a 149 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
05465712 150 $contribution = $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
151 //assert non-deductible amount
152 $this->assertEquals(5.00, $contribution['non_deductible_amount']);
f64a217a 153 }
5896d037 154
870156d6 155 /**
156 * Test form submission with billing first & last name where the contact does NOT
157 * otherwise have one.
158 */
159 public function testSubmitNewBillingNameData() {
160 $this->setUpContributionPage();
161 $contact = $this->callAPISuccess('Contact', 'create', array('contact_type' => 'Individual', 'email' => 'wonderwoman@amazon.com'));
162 $priceFieldID = reset($this->_ids['price_field']);
163 $priceFieldValueID = reset($this->_ids['price_field_value']);
164 $submitParams = array(
165 'price_' . $priceFieldID => $priceFieldValueID,
166 'id' => (int) $this->_ids['contribution_page'],
167 'amount' => 10,
168 'billing_first_name' => 'Wonder',
169 'billing_last_name' => 'Woman',
170 'contactID' => $contact['id'],
171 'email' => 'wonderwoman@amazon.com',
172 );
173
174 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
175 $contact = $this->callAPISuccess('Contact', 'get', array(
176 'id' => $contact['id'],
177 'return' => array(
178 'first_name',
179 'last_name',
180 'sort_name',
181 'display_name',
182 ),
183 ));
184 $this->assertEquals(array(
185 'first_name' => 'Wonder',
186 'last_name' => 'Woman',
187 'display_name' => 'Wonder Woman',
188 'sort_name' => 'Woman, Wonder',
189 'id' => $contact['id'],
190 'contact_id' => $contact['id'],
191 ), $contact['values'][$contact['id']]);
192
193 }
194
195 /**
196 * Test form submission with billing first & last name where the contact does
197 * otherwise have one and should not be overwritten.
198 */
199 public function testSubmitNewBillingNameDoNotOverwrite() {
200 $this->setUpContributionPage();
201 $contact = $this->callAPISuccess('Contact', 'create', array(
202 'contact_type' => 'Individual',
203 'email' => 'wonderwoman@amazon.com',
204 'first_name' => 'Super',
205 'last_name' => 'Boy',
206 ));
207 $priceFieldID = reset($this->_ids['price_field']);
208 $priceFieldValueID = reset($this->_ids['price_field_value']);
209 $submitParams = array(
210 'price_' . $priceFieldID => $priceFieldValueID,
211 'id' => (int) $this->_ids['contribution_page'],
212 'amount' => 10,
213 'billing_first_name' => 'Wonder',
214 'billing_last_name' => 'Woman',
215 'contactID' => $contact['id'],
216 'email' => 'wonderwoman@amazon.com',
217 );
218
219 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
220 $contact = $this->callAPISuccess('Contact', 'get', array(
221 'id' => $contact['id'],
222 'return' => array(
223 'first_name',
224 'last_name',
225 'sort_name',
226 'display_name',
227 ),
228 ));
229 $this->assertEquals(array(
230 'first_name' => 'Super',
231 'last_name' => 'Boy',
232 'display_name' => 'Super Boy',
233 'sort_name' => 'Boy, Super',
234 'id' => $contact['id'],
235 'contact_id' => $contact['id'],
236 ), $contact['values'][$contact['id']]);
237
238 }
239
7bc789a5 240 /**
241 * Test process with instant payment when more than one configured for the page.
242 *
243 * CRM-16923
244 */
245 public function testSubmitRecurMultiProcessorInstantPayment() {
246 $this->setUpContributionPage();
247 $this->setupPaymentProcessor();
d27635dc 248 $paymentProcessor2ID = $this->paymentProcessorCreate(array(
7bc789a5 249 'payment_processor_type_id' => 'Dummy',
250 'name' => 'processor 2',
251 'class_name' => 'Payment_Dummy',
252 'billing_mode' => 1,
253 ));
254 $dummyPP = Civi\Payment\System::singleton()->getById($paymentProcessor2ID);
70cc8754 255 $dummyPP->setDoDirectPaymentResult(array(
256 'payment_status_id' => 1,
257 'trxn_id' => 'create_first_success',
258 'fee_amount' => .85,
259 ));
f69a9ac3 260 $processor = $dummyPP->getPaymentProcessor();
7bc789a5 261 $this->callAPISuccess('ContributionPage', 'create', array(
d27635dc 262 'id' => $this->_ids['contribution_page'],
263 'payment_processor' => array($paymentProcessor2ID, $this->_ids['payment_processor']),
7bc789a5 264 ));
265
266 $priceFieldID = reset($this->_ids['price_field']);
267 $priceFieldValueID = reset($this->_ids['price_field_value']);
268 $submitParams = array(
269 'price_' . $priceFieldID => $priceFieldValueID,
270 'id' => (int) $this->_ids['contribution_page'],
271 'amount' => 10,
272 'is_recur' => 1,
273 'frequency_interval' => 1,
274 'frequency_unit' => 'month',
275 'payment_processor_id' => $paymentProcessor2ID,
276 );
277
278 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
70cc8754 279 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
7bc789a5 280 'contribution_page_id' => $this->_ids['contribution_page'],
281 'contribution_status_id' => 1,
282 ));
70cc8754 283 $this->assertEquals('create_first_success', $contribution['trxn_id']);
284 $this->assertEquals(10, $contribution['total_amount']);
285 $this->assertEquals(.85, $contribution['fee_amount']);
286 $this->assertEquals(9.15, $contribution['net_amount']);
bf722049 287 $this->_checkFinancialRecords(array(
288 'id' => $contribution['id'],
289 'total_amount' => $contribution['total_amount'],
f69a9ac3 290 'payment_instrument_id' => $processor['payment_instrument_id'],
bf722049 291 ), 'online');
7bc789a5 292 }
70cc8754 293
f64a217a 294 /**
eceb18cc 295 * Test submit with a membership block in place.
f64a217a 296 */
f9342903
EM
297 public function testSubmitMembershipBlockNotSeparatePayment() {
298 $this->setUpMembershipContributionPage();
f64a217a 299 $submitParams = array(
3e28c791 300 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
f9342903 301 'id' => (int) $this->_ids['contribution_page'],
f64a217a
EM
302 'amount' => 10,
303 'billing_first_name' => 'Billy',
304 'billing_middle_name' => 'Goat',
305 'billing_last_name' => 'Gruff',
306 'selectMembership' => $this->_ids['membership_type'],
307
308 );
309
a828d7b8 310 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
f9342903 311 $contribution = $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
840e3907 312 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array('contribution_id' => $contribution['id']));
313 $this->callAPISuccessGetSingle('LineItem', array('contribution_id' => $contribution['id'], 'entity_id' => $membershipPayment['id']));
f9342903
EM
314 }
315
e04004fa 316 /**
317 * Test submit with a membership block in place works with renewal.
318 */
319 public function testSubmitMembershipBlockNotSeparatePaymentProcessorInstantRenew() {
320 $this->setUpMembershipContributionPage();
321 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
322 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1));
323 $submitParams = array(
324 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
325 'id' => (int) $this->_ids['contribution_page'],
326 'amount' => 10,
327 'billing_first_name' => 'Billy',
328 'billing_middle_name' => 'Goat',
329 'billing_last_name' => 'Gruff',
330 'selectMembership' => $this->_ids['membership_type'],
331 'payment_processor_id' => 1,
332 'credit_card_number' => '4111111111111111',
333 'credit_card_type' => 'Visa',
334 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
335 'cvv2' => 123,
336 );
337
338 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
339 $contribution = $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
340 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array('contribution_id' => $contribution['id']));
341 $this->callAPISuccessGetCount('LineItem', array(
342 'entity_table' => 'civicrm_membership',
343 'entity_id' => $membershipPayment['id'],
344 ), 1);
345
346 $submitParams['contact_id'] = $contribution['contact_id'];
347
348 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
349 $this->callAPISuccessGetCount('LineItem', array(
350 'entity_table' => 'civicrm_membership',
351 'entity_id' => $membershipPayment['id'],
352 ), 2);
353 $membership = $this->callAPISuccessGetSingle('Membership', array(
354 'id' => $membershipPayment['membership_id'],
355 'return' => array('end_date', 'join_date', 'start_date'),
356 ));
357 $this->assertEquals(date('Y-m-d'), $membership['start_date']);
358 $this->assertEquals(date('Y-m-d'), $membership['join_date']);
359 $this->assertEquals(date('Y-m-d', strtotime('+ 2 year - 1 day')), $membership['end_date']);
360 }
361
2f59d010 362 /**
363 * Test submit with a membership block in place.
364 */
365 public function testSubmitMembershipBlockNotSeparatePaymentWithEmail() {
366 $mut = new CiviMailUtils($this, TRUE);
367 $this->setUpMembershipContributionPage();
368 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
369
370 $submitParams = array(
371 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
372 'id' => (int) $this->_ids['contribution_page'],
373 'amount' => 10,
374 'billing_first_name' => 'Billy',
375 'billing_middle_name' => 'Goat',
376 'billing_last_name' => 'Gruff',
377 'selectMembership' => $this->_ids['membership_type'],
378 'email-Primary' => 'billy-goat@the-bridge.net',
9daadfce 379 'payment_processor_id' => $this->_paymentProcessor['id'],
380 'credit_card_number' => '4111111111111111',
381 'credit_card_type' => 'Visa',
382 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
383 'cvv2' => 123,
2f59d010 384 );
385
5be22f39 386 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
2f59d010 387 $contribution = $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
388 $this->callAPISuccess('membership_payment', 'getsingle', array('contribution_id' => $contribution['id']));
389 $mut->checkMailLog(array(
390 'Membership Type: General',
391 ));
392 $mut->stop();
393 $mut->clearMessages();
394 }
395
396 /**
397 * Test submit with a membership block in place.
398 */
399 public function testSubmitMembershipBlockNotSeparatePaymentZeroDollarsWithEmail() {
400 $mut = new CiviMailUtils($this, TRUE);
401 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 0)));
402 $this->setUpMembershipContributionPage();
403 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
404
405 $submitParams = array(
406 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
407 'id' => (int) $this->_ids['contribution_page'],
408 'amount' => 0,
409 'billing_first_name' => 'Billy',
410 'billing_middle_name' => 'Goat',
411 'billing_last_name' => 'Gruffier',
412 'selectMembership' => $this->_ids['membership_type'],
413 'email-Primary' => 'billy-goat@the-new-bridge.net',
18135422 414 'payment_processor_id' => $this->params['payment_processor_id'],
2f59d010 415 );
416
5be22f39 417 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
2f59d010 418 $contribution = $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
419 $this->callAPISuccess('membership_payment', 'getsingle', array('contribution_id' => $contribution['id']));
e2e2be86
JP
420 //Assert only one mail is being sent.
421 $msgs = $mut->getAllMessages();
422 $this->assertCount(1, $msgs);
423
2f59d010 424 $mut->checkMailLog(array(
425 'Membership Type: General',
426 'Gruffier',
427 ),
428 array(
429 'Amount',
430 )
431 );
432 $mut->stop();
9daadfce 433 $mut->clearMessages(999);
2f59d010 434 }
435
f9342903 436 /**
eceb18cc 437 * Test submit with a membership block in place.
f9342903
EM
438 */
439 public function testSubmitMembershipBlockIsSeparatePayment() {
440 $this->setUpMembershipContributionPage(TRUE);
9daadfce 441 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 2)));
f9342903 442 $submitParams = array(
3e28c791 443 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
f9342903
EM
444 'id' => (int) $this->_ids['contribution_page'],
445 'amount' => 10,
446 'billing_first_name' => 'Billy',
447 'billing_middle_name' => 'Goat',
448 'billing_last_name' => 'Gruff',
449 'selectMembership' => $this->_ids['membership_type'],
450 );
451
5be22f39 452 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
f9342903
EM
453 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
454 $this->assertCount(2, $contributions['values']);
8e8d287f 455 $lines = $this->callAPISuccess('LineItem', 'get', array('sequential' => 1));
456 $this->assertEquals(10, $lines['values'][0]['line_total']);
f9342903
EM
457 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
458 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
459 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
460 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
461 }
f64a217a 462
2f59d010 463 /**
464 * Test submit with a membership block in place.
465 */
466 public function testSubmitMembershipBlockIsSeparatePaymentWithEmail() {
467 $mut = new CiviMailUtils($this, TRUE);
468 $this->setUpMembershipContributionPage(TRUE);
469 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
470
471 $submitParams = array(
472 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
473 'id' => (int) $this->_ids['contribution_page'],
474 'amount' => 10,
475 'billing_first_name' => 'Billy',
476 'billing_middle_name' => 'Goat',
477 'billing_last_name' => 'Gruff',
478 'selectMembership' => $this->_ids['membership_type'],
479 'email-Primary' => 'billy-goat@the-bridge.net',
9daadfce 480 'payment_processor_id' => $this->_paymentProcessor['id'],
481 'credit_card_number' => '4111111111111111',
482 'credit_card_type' => 'Visa',
483 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
484 'cvv2' => 123,
2f59d010 485 );
486
5be22f39 487 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
2f59d010 488 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
489 $this->assertCount(2, $contributions['values']);
490 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
491 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
492 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
493 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
de6a9861
JM
494 // We should have two separate email messages, each with their own amount
495 // line and no total line.
496 $mut->checkAllMailLog(
497 array(
498 'Amount: $ 2.00',
499 'Amount: $ 10.00',
500 'Membership Fee',
501 ),
502 array(
c2ce0c2a 503 'Total: $',
461ae02f 504 )
de6a9861 505 );
2f59d010 506 $mut->stop();
9daadfce 507 $mut->clearMessages(999);
2f59d010 508 }
509
510 /**
511 * Test submit with a membership block in place.
512 */
513 public function testSubmitMembershipBlockIsSeparatePaymentZeroDollarsPayLaterWithEmail() {
514 $mut = new CiviMailUtils($this, TRUE);
515 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 0)));
516 $this->setUpMembershipContributionPage(TRUE);
517 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
518
519 $submitParams = array(
520 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
521 'id' => (int) $this->_ids['contribution_page'],
522 'amount' => 0,
523 'billing_first_name' => 'Billy',
524 'billing_middle_name' => 'Goat',
525 'billing_last_name' => 'Gruffalo',
526 'selectMembership' => $this->_ids['membership_type'],
527 'payment_processor_id' => 0,
528 'email-Primary' => 'gruffalo@the-bridge.net',
529 );
530
531 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
532 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
533 $this->assertCount(2, $contributions['values']);
534 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
535 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
536 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
537 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
538 $mut->checkMailLog(array(
539 'Gruffalo',
540 'General Membership: $ 0.00',
541 'Membership Fee',
542 ));
543 $mut->stop();
544 $mut->clearMessages();
545 }
546
797c4f88 547 /**
eceb18cc 548 * Test submit with a membership block in place.
797c4f88
EM
549 */
550 public function testSubmitMembershipBlockTwoTypesIsSeparatePayment() {
551 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 6)));
552 $this->_ids['membership_type'][] = $this->membershipTypeCreate(array('name' => 'Student', 'minimum_fee' => 50));
553 $this->setUpMembershipContributionPage(TRUE);
554 $submitParams = array(
555 'price_' . $this->_ids['price_field'][0] => $this->_ids['price_field_value'][1],
556 'id' => (int) $this->_ids['contribution_page'],
557 'amount' => 10,
558 'billing_first_name' => 'Billy',
559 'billing_middle_name' => 'Goat',
560 'billing_last_name' => 'Gruff',
561 'selectMembership' => $this->_ids['membership_type'][1],
562 );
563
a828d7b8 564 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
6c6e6187 565 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
797c4f88
EM
566 $this->assertCount(2, $contributions['values']);
567 $ids = array_keys($contributions['values']);
568 $this->assertEquals('10.00', $contributions['values'][$ids[0]]['total_amount']);
569 $this->assertEquals('50.00', $contributions['values'][$ids[1]]['total_amount']);
570 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
571 $this->assertArrayHasKey($membershipPayment['contribution_id'], $contributions['values']);
572 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
573 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
574 }
575
8ca611b7 576 /**
eceb18cc 577 * Test submit with a membership block in place.
329f3f66
EM
578 *
579 * We are expecting a separate payment for the membership vs the contribution.
8ca611b7 580 */
329f3f66 581 public function testSubmitMembershipBlockIsSeparatePaymentPaymentProcessorNow() {
58d8c7e2 582 $mut = new CiviMailUtils($this, TRUE);
8ca611b7 583 $this->setUpMembershipContributionPage(TRUE);
0193ebdb 584 $processor = Civi\Payment\System::singleton()->getById($this->_paymentProcessor['id']);
585 $processor->setDoDirectPaymentResult(array('fee_amount' => .72));
8ca611b7
EM
586 $submitParams = array(
587 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
588 'id' => (int) $this->_ids['contribution_page'],
589 'amount' => 10,
590 'billing_first_name' => 'Billy',
591 'billing_middle_name' => 'Goat',
592 'billing_last_name' => 'Gruff',
58d8c7e2 593 'email-Primary' => 'henry@8th.king',
8ca611b7 594 'selectMembership' => $this->_ids['membership_type'],
7bc789a5 595 'payment_processor_id' => $this->_paymentProcessor['id'],
8ca611b7
EM
596 'credit_card_number' => '4111111111111111',
597 'credit_card_type' => 'Visa',
5896d037 598 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
8ca611b7
EM
599 'cvv2' => 123,
600 );
05990684 601
a828d7b8 602 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
5896d037 603 $contributions = $this->callAPISuccess('contribution', 'get', array(
92915c55
TO
604 'contribution_page_id' => $this->_ids['contribution_page'],
605 'contribution_status_id' => 1,
606 ));
8ca611b7
EM
607 $this->assertCount(2, $contributions['values']);
608 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
609 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
610 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
611 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
f2bca231 612 $lineItem = $this->callAPISuccessGetSingle('LineItem', array('entity_table' => 'civicrm_membership'));
613 $this->assertEquals($lineItem['entity_id'], $membership['id']);
614 $this->assertEquals($lineItem['contribution_id'], $membershipPayment['contribution_id']);
615 $this->assertEquals($lineItem['qty'], 1);
616 $this->assertEquals($lineItem['unit_price'], 2);
617 $this->assertEquals($lineItem['line_total'], 2);
0193ebdb 618 foreach ($contributions['values'] as $contribution) {
619 $this->assertEquals(.72, $contribution['fee_amount']);
620 $this->assertEquals($contribution['total_amount'] - .72, $contribution['net_amount']);
621 }
58d8c7e2 622 // The total string is currently absent & it seems worse with - although at some point
623 // it may have been intended
624 $mut->checkAllMailLog(array('$ 2.00', 'Contribution Amount', '$ 10.00'), array('Total:'));
625 $mut->stop();
626 $mut->clearMessages();
8ca611b7 627 }
f8fe0df6 628
5961bd47
EM
629 /**
630 * Test that when a transaction fails the pending contribution remains.
631 *
632 * An activity should also be created. CRM-16417.
633 */
634 public function testSubmitPaymentProcessorFailure() {
635 $this->setUpContributionPage();
636 $this->setupPaymentProcessor();
637 $this->createLoggedInUser();
638 $priceFieldID = reset($this->_ids['price_field']);
639 $priceFieldValueID = reset($this->_ids['price_field_value']);
640 $submitParams = array(
641 'price_' . $priceFieldID => $priceFieldValueID,
642 'id' => (int) $this->_ids['contribution_page'],
643 'amount' => 10,
644 'payment_processor_id' => 1,
645 'credit_card_number' => '4111111111111111',
646 'credit_card_type' => 'Visa',
647 'credit_card_exp_date' => array('M' => 9, 'Y' => 2008),
648 'cvv2' => 123,
649 );
650
651 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
652 $contribution = $this->callAPISuccessGetSingle('contribution', array(
653 'contribution_page_id' => $this->_ids['contribution_page'],
382c5680 654 'contribution_status_id' => 'Failed',
5961bd47
EM
655 ));
656
657 $this->callAPISuccessGetSingle('activity', array(
658 'source_record_id' => $contribution['id'],
659 'activity_type_id' => 'Failed Payment',
660 ));
661
5961bd47
EM
662 }
663
f8fe0df6 664 /**
dd1b539a 665 * Test submit recurring membership with immediate confirmation (IATS style).
666 *
e6fa4056 667 * - we process 2 membership transactions against with a recurring contribution against a contribution page with an immediate
1fee3ad2 668 * processor (IATS style - denoted by returning trxn_id)
e6fa4056
EM
669 * - the first creates a new membership, completed contribution, in progress recurring. Check these
670 * - create another - end date should be extended
f8fe0df6 671 */
8bef2e38 672 public function testSubmitMembershipPriceSetPaymentPaymentProcessorRecurInstantPayment() {
f8fe0df6 673 $this->params['is_recur'] = 1;
f8fe0df6 674 $this->params['recur_frequency_unit'] = 'month';
675 $this->setUpMembershipContributionPage();
7c85dc65 676 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
8bef2e38 677 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success'));
f69a9ac3 678 $processor = $dummyPP->getPaymentProcessor();
f8fe0df6 679
680 $submitParams = array(
681 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
682 'id' => (int) $this->_ids['contribution_page'],
683 'amount' => 10,
684 'billing_first_name' => 'Billy',
685 'billing_middle_name' => 'Goat',
686 'billing_last_name' => 'Gruff',
687 'email' => 'billy@goat.gruff',
688 'selectMembership' => $this->_ids['membership_type'],
579a1fb7 689 'payment_processor_id' => 1,
f8fe0df6 690 'credit_card_number' => '4111111111111111',
691 'credit_card_type' => 'Visa',
5896d037 692 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
f8fe0df6 693 'cvv2' => 123,
694 'is_recur' => 1,
695 'frequency_interval' => 1,
696 'frequency_unit' => 'month',
697 );
698
a828d7b8 699 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
5896d037 700 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
92915c55
TO
701 'contribution_page_id' => $this->_ids['contribution_page'],
702 'contribution_status_id' => 1,
703 ));
f69a9ac3 704 $this->assertEquals($processor['payment_instrument_id'], $contribution['payment_instrument_id']);
0739d6cf 705
706 $this->assertEquals('create_first_success', $contribution['trxn_id']);
f8fe0df6 707 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
708 $this->assertEquals($membershipPayment['contribution_id'], $contribution['id']);
709 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
710 $this->assertEquals($membership['contact_id'], $contribution['contact_id']);
711 $this->assertEquals(1, $membership['status_id']);
712 $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
356bfcaf 713
714 $this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $contribution['id'], 'entity_id' => $membership['id']));
f8fe0df6 715 //renew it with processor setting completed - should extend membership
716 $submitParams['contact_id'] = $contribution['contact_id'];
8bef2e38 717 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_second_success'));
f8fe0df6 718 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
5896d037 719 $this->callAPISuccess('contribution', 'getsingle', array(
92915c55
TO
720 'id' => array('NOT IN' => array($contribution['id'])),
721 'contribution_page_id' => $this->_ids['contribution_page'],
722 'contribution_status_id' => 1,
723 ));
f8fe0df6 724 $renewedMembership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
725 $this->assertEquals(date('Y-m-d', strtotime('+ 1 year', strtotime($membership['end_date']))), $renewedMembership['end_date']);
726 $recurringContribution = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
f69a9ac3 727 $this->assertEquals($processor['payment_instrument_id'], $recurringContribution['payment_instrument_id']);
91259407 728 $this->assertEquals(5, $recurringContribution['contribution_status_id']);
f8fe0df6 729 }
730
13a16f43 731 /**
732 * Test submit recurring membership with immediate confirmation (IATS style).
733 *
734 * - we process 2 membership transactions against with a recurring contribution against a contribution page with an immediate
735 * processor (IATS style - denoted by returning trxn_id)
736 * - the first creates a new membership, completed contribution, in progress recurring. Check these
737 * - create another - end date should be extended
738 */
65e172a3 739 public function testSubmitMembershipComplexNonPriceSetPaymentPaymentProcessorRecurInstantPayment() {
13a16f43 740 $this->params['is_recur'] = 1;
741 $this->params['recur_frequency_unit'] = 'month';
742 // Add a membership so membership & contribution are not both 1.
743 $preExistingMembershipID = $this->contactMembershipCreate(array('contact_id' => $this->contactIds[0]));
744 $this->setUpMembershipContributionPage();
745 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
746 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success'));
747 $processor = $dummyPP->getPaymentProcessor();
748
749 $submitParams = array(
750 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
751 'price_' . $this->_ids['price_field']['cont'] => 88,
752 'id' => (int) $this->_ids['contribution_page'],
753 'amount' => 10,
754 'billing_first_name' => 'Billy',
755 'billing_middle_name' => 'Goat',
756 'billing_last_name' => 'Gruff',
757 'email' => 'billy@goat.gruff',
758 'selectMembership' => $this->_ids['membership_type'],
759 'payment_processor_id' => 1,
760 'credit_card_number' => '4111111111111111',
761 'credit_card_type' => 'Visa',
762 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
763 'cvv2' => 123,
764 'is_recur' => 1,
765 'frequency_interval' => 1,
766 'frequency_unit' => 'month',
767 );
768
769 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
770 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
771 'contribution_page_id' => $this->_ids['contribution_page'],
772 'contribution_status_id' => 1,
773 ));
774 $this->assertEquals($processor['payment_instrument_id'], $contribution['payment_instrument_id']);
775
776 $this->assertEquals('create_first_success', $contribution['trxn_id']);
777 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
778 $this->assertEquals($membershipPayment['contribution_id'], $contribution['id']);
779 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
780 $this->assertEquals($membership['contact_id'], $contribution['contact_id']);
781 $this->assertEquals(1, $membership['status_id']);
782 $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
783
784 $lines = $this->callAPISuccess('line_item', 'get', array('sequential' => 1, 'contribution_id' => $contribution['id']));
785 $this->assertEquals(2, $lines['count']);
786 $this->assertEquals('civicrm_membership', $lines['values'][0]['entity_table']);
787 $this->assertEquals($preExistingMembershipID + 1, $lines['values'][0]['entity_id']);
788 $this->assertEquals('civicrm_contribution', $lines['values'][1]['entity_table']);
789 $this->assertEquals($contribution['id'], $lines['values'][1]['entity_id']);
790 $this->callAPISuccessGetSingle('MembershipPayment', array('contribution_id' => $contribution['id'], 'membership_id' => $preExistingMembershipID + 1));
791
792 //renew it with processor setting completed - should extend membership
793 $submitParams['contact_id'] = $contribution['contact_id'];
794 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_second_success'));
795 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
796 $renewContribution = $this->callAPISuccess('contribution', 'getsingle', array(
797 'id' => array('NOT IN' => array($contribution['id'])),
798 'contribution_page_id' => $this->_ids['contribution_page'],
799 'contribution_status_id' => 1,
800 ));
801 $lines = $this->callAPISuccess('line_item', 'get', array('sequential' => 1, 'contribution_id' => $renewContribution['id']));
802 $this->assertEquals(2, $lines['count']);
803 $this->assertEquals('civicrm_membership', $lines['values'][0]['entity_table']);
804 $this->assertEquals($preExistingMembershipID + 1, $lines['values'][0]['entity_id']);
805 $this->assertEquals('civicrm_contribution', $lines['values'][1]['entity_table']);
806 $this->assertEquals($renewContribution['id'], $lines['values'][1]['entity_id']);
807
808 $renewedMembership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
809 $this->assertEquals(date('Y-m-d', strtotime('+ 1 year', strtotime($membership['end_date']))), $renewedMembership['end_date']);
810 $recurringContribution = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
811 $this->assertEquals($processor['payment_instrument_id'], $recurringContribution['payment_instrument_id']);
812 $this->assertEquals(5, $recurringContribution['contribution_status_id']);
813 }
814
65e172a3 815 /**
816 * Test submit recurring membership with immediate confirmation (IATS style).
817 *
818 * - we process 2 membership transactions against with a recurring contribution against a contribution page with an immediate
819 * processor (IATS style - denoted by returning trxn_id)
820 * - the first creates a new membership, completed contribution, in progress recurring. Check these
821 * - create another - end date should be extended
822 */
823 public function testSubmitMembershipComplexPriceSetPaymentPaymentProcessorRecurInstantPayment() {
824 $this->params['is_recur'] = 1;
825 $this->params['recur_frequency_unit'] = 'month';
826 // Add a membership so membership & contribution are not both 1.
827 $preExistingMembershipID = $this->contactMembershipCreate(array('contact_id' => $this->contactIds[0]));
828 $this->createPriceSetWithPage();
829 $this->addSecondOrganizationMembershipToPriceSet();
830 $this->setupPaymentProcessor();
831
832 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
833 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success'));
834 $processor = $dummyPP->getPaymentProcessor();
835
836 $submitParams = array(
837 'price_' . $this->_ids['price_field'][0] => $this->_ids['price_field_value']['cont'],
838 'price_' . $this->_ids['price_field']['org1'] => $this->_ids['price_field_value']['org1'],
839 'price_' . $this->_ids['price_field']['org2'] => $this->_ids['price_field_value']['org2'],
840 'id' => (int) $this->_ids['contribution_page'],
841 'amount' => 10,
842 'billing_first_name' => 'Billy',
843 'billing_middle_name' => 'Goat',
844 'billing_last_name' => 'Gruff',
845 'email' => 'billy@goat.gruff',
846 'selectMembership' => NULL,
847 'payment_processor_id' => 1,
848 'credit_card_number' => '4111111111111111',
849 'credit_card_type' => 'Visa',
850 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
851 'cvv2' => 123,
852 'frequency_interval' => 1,
853 'frequency_unit' => 'month',
854 );
855
856 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
857 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
858 'contribution_page_id' => $this->_ids['contribution_page'],
859 'contribution_status_id' => 1,
860 ));
861 $this->assertEquals($processor['payment_instrument_id'], $contribution['payment_instrument_id']);
862
863 $this->assertEquals('create_first_success', $contribution['trxn_id']);
864 $membershipPayments = $this->callAPISuccess('membership_payment', 'get', array(
865 'sequential' => 1,
866 'contribution_id' => $contribution['id'],
867 ));
868 $this->assertEquals(2, $membershipPayments['count']);
869 $lines = $this->callAPISuccess('line_item', 'get', array('sequential' => 1, 'contribution_id' => $contribution['id']));
870 $this->assertEquals(3, $lines['count']);
871 $this->assertEquals('civicrm_membership', $lines['values'][0]['entity_table']);
872 $this->assertEquals($preExistingMembershipID + 1, $lines['values'][0]['entity_id']);
873 $this->assertEquals('civicrm_contribution', $lines['values'][1]['entity_table']);
874 $this->assertEquals($contribution['id'], $lines['values'][1]['entity_id']);
875 $this->assertEquals('civicrm_membership', $lines['values'][2]['entity_table']);
876 $this->assertEquals($preExistingMembershipID + 2, $lines['values'][2]['entity_id']);
877
878 $this->callAPISuccessGetSingle('MembershipPayment', array('contribution_id' => $contribution['id'], 'membership_id' => $preExistingMembershipID + 1));
879 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $preExistingMembershipID + 1));
880
881 //renew it with processor setting completed - should extend membership
882 $submitParams['contact_id'] = $contribution['contact_id'];
883 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_second_success'));
884 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
885 $renewContribution = $this->callAPISuccess('contribution', 'getsingle', array(
886 'id' => array('NOT IN' => array($contribution['id'])),
887 'contribution_page_id' => $this->_ids['contribution_page'],
888 'contribution_status_id' => 1,
889 ));
890 $lines = $this->callAPISuccess('line_item', 'get', array('sequential' => 1, 'contribution_id' => $renewContribution['id']));
891 $this->assertEquals(3, $lines['count']);
892 $this->assertEquals('civicrm_membership', $lines['values'][0]['entity_table']);
893 $this->assertEquals($preExistingMembershipID + 1, $lines['values'][0]['entity_id']);
894 $this->assertEquals('civicrm_contribution', $lines['values'][1]['entity_table']);
895 $this->assertEquals($renewContribution['id'], $lines['values'][1]['entity_id']);
896
897 $renewedMembership = $this->callAPISuccessGetSingle('membership', array('id' => $preExistingMembershipID + 1));
898 $this->assertEquals(date('Y-m-d', strtotime('+ 1 year', strtotime($membership['end_date']))), $renewedMembership['end_date']);
899 }
900
901 /**
902 * Extend the price set with a second organisation's membership.
903 */
904 public function addSecondOrganizationMembershipToPriceSet() {
905 $organization2ID = $this->organizationCreate();
906 $membershipTypes = $this->callAPISuccess('MembershipType', 'get', array());
907 $this->_ids['membership_type'] = array_keys($membershipTypes['values']);
908 $this->_ids['membership_type']['org2'] = $this->membershipTypeCreate(array('contact_id' => $organization2ID, 'name' => 'Org 2'));
909 $priceField = $this->callAPISuccess('PriceField', 'create', array(
910 'price_set_id' => $this->_ids['price_set'],
911 'html_type' => 'Radio',
912 'name' => 'Org1 Price',
913 'label' => 'Org1Price',
914 ));
915 $this->_ids['price_field']['org1'] = $priceField['id'];
916
917 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
918 'name' => 'org1 amount',
919 'label' => 'org 1 Amount',
920 'amount' => 2,
921 'financial_type_id' => 'Member Dues',
922 'format.only_id' => TRUE,
923 'membership_type_id' => reset($this->_ids['membership_type']),
924 'price_field_id' => $priceField['id'],
925 ));
926 $this->_ids['price_field_value']['org1'] = $priceFieldValue;
927
928 $priceField = $this->callAPISuccess('PriceField', 'create', array(
929 'price_set_id' => $this->_ids['price_set'],
930 'html_type' => 'Radio',
931 'name' => 'Org2 Price',
932 'label' => 'Org2Price',
933 ));
934 $this->_ids['price_field']['org2'] = $priceField['id'];
935
936 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
937 'name' => 'org2 amount',
938 'label' => 'org 2 Amount',
939 'amount' => 200,
940 'financial_type_id' => 'Member Dues',
941 'format.only_id' => TRUE,
942 'membership_type_id' => $this->_ids['membership_type']['org2'],
943 'price_field_id' => $priceField['id'],
944 ));
945 $this->_ids['price_field_value']['org2'] = $priceFieldValue;
946
947 }
948
449f4c90 949 /**
950 * Test submit recurring membership with immediate confirmation (IATS style).
951 *
952 * - we process 2 membership transactions against with a recurring contribution against a contribution page with an immediate
953 * processor (IATS style - denoted by returning trxn_id)
954 * - the first creates a new membership, completed contribution, in progress recurring. Check these
955 * - create another - end date should be extended
956 */
957 public function testSubmitMembershipPriceSetPaymentPaymentProcessorSeparatePaymentRecurInstantPayment() {
958
959 $this->setUpMembershipContributionPage(TRUE);
960 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
961 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success'));
962
963 $submitParams = array(
964 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
965 'id' => (int) $this->_ids['contribution_page'],
966 'amount' => 10,
967 'billing_first_name' => 'Billy',
968 'billing_middle_name' => 'Goat',
969 'billing_last_name' => 'Gruff',
970 'email' => 'billy@goat.gruff',
971 'selectMembership' => $this->_ids['membership_type'],
972 'payment_processor_id' => 1,
973 'credit_card_number' => '4111111111111111',
974 'credit_card_type' => 'Visa',
975 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
976 'cvv2' => 123,
977 'is_recur' => 1,
978 'auto_renew' => TRUE,
979 'frequency_interval' => 1,
980 'frequency_unit' => 'month',
981 );
982
983 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
984 $contribution = $this->callAPISuccess('contribution', 'get', array(
985 'contribution_page_id' => $this->_ids['contribution_page'],
986 'contribution_status_id' => 1,
987 ));
988
989 $this->assertEquals(2, $contribution['count']);
990 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
991 $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
992 $this->assertNotEmpty($contribution['values'][$membershipPayment['contribution_id']]['contribution_recur_id']);
993 $this->callAPISuccess('contribution_recur', 'getsingle', array());
994 }
995
f8fe0df6 996 /**
e6fa4056
EM
997 * Test submit recurring membership with delayed confirmation (Authorize.net style)
998 * - we process 2 membership transactions against with a recurring contribution against a contribution page with a delayed
999 * processor (Authorize.net style - denoted by NOT returning trxn_id)
1000 * - the first creates a pending membership, pending contribution, penging recurring. Check these
1001 * - complete the transaction
1002 * - create another - end date should NOT be extended
f8fe0df6 1003 */
1004 public function testSubmitMembershipPriceSetPaymentPaymentProcessorRecurDelayed() {
1005 $this->params['is_recur'] = 1;
f8fe0df6 1006 $this->params['recur_frequency_unit'] = 'month';
1007 $this->setUpMembershipContributionPage();
ab30e033 1008 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
b5eacf76 1009 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 2));
356bfcaf 1010 $this->membershipTypeCreate(array('name' => 'Student'));
1011
1012 // Add a contribution & a couple of memberships so the id will not be 1 & will differ from membership id.
1013 // This saves us from 'accidental success'.
51f8c59c 1014 $this->contributionCreate(array('contact_id' => $this->contactIds[0]));
356bfcaf 1015 $this->contactMembershipCreate(array('contact_id' => $this->contactIds[0]));
1016 $this->contactMembershipCreate(array('contact_id' => $this->contactIds[0], 'membership_type_id' => 'Student'));
f8fe0df6 1017
1018 $submitParams = array(
1019 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
1020 'id' => (int) $this->_ids['contribution_page'],
1021 'amount' => 10,
1022 'billing_first_name' => 'Billy',
1023 'billing_middle_name' => 'Goat',
1024 'billing_last_name' => 'Gruff',
1025 'email' => 'billy@goat.gruff',
1026 'selectMembership' => $this->_ids['membership_type'],
579a1fb7 1027 'payment_processor_id' => 1,
f8fe0df6 1028 'credit_card_number' => '4111111111111111',
1029 'credit_card_type' => 'Visa',
5896d037 1030 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
f8fe0df6 1031 'cvv2' => 123,
e6fa4056
EM
1032 'is_recur' => 1,
1033 'frequency_interval' => 1,
1034 'frequency_unit' => 'month',
f8fe0df6 1035 );
1036
a828d7b8 1037 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
5896d037 1038 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
92915c55
TO
1039 'contribution_page_id' => $this->_ids['contribution_page'],
1040 'contribution_status_id' => 2,
1041 ));
356bfcaf 1042
f8fe0df6 1043 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
1044 $this->assertEquals($membershipPayment['contribution_id'], $contribution['id']);
1045 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
1046 $this->assertEquals($membership['contact_id'], $contribution['contact_id']);
e6fa4056 1047 $this->assertEquals(5, $membership['status_id']);
51f8c59c 1048
1049 $line = $this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $contribution['id']));
1050 $this->assertEquals('civicrm_membership', $line['entity_table']);
1051 $this->assertEquals($membership['id'], $line['entity_id']);
1052
5896d037 1053 $this->callAPISuccess('contribution', 'completetransaction', array(
92915c55
TO
1054 'id' => $contribution['id'],
1055 'trxn_id' => 'ipn_called',
b396c447 1056 'payment_processor_id' => $this->_paymentProcessor['id'],
92915c55 1057 ));
51f8c59c 1058 $line = $this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $contribution['id']));
1059 $this->assertEquals('civicrm_membership', $line['entity_table']);
1060 $this->assertEquals($membership['id'], $line['entity_id']);
1061
e6fa4056 1062 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
f8fe0df6 1063 //renew it with processor setting completed - should extend membership
1064 $submitParams = array_merge($submitParams, array(
5896d037
TO
1065 'contact_id' => $contribution['contact_id'],
1066 'is_recur' => 1,
1067 'frequency_interval' => 1,
1068 'frequency_unit' => 'month',
1069 )
f8fe0df6 1070 );
51f8c59c 1071
b5eacf76 1072 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 2));
f8fe0df6 1073 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
6c6e6187 1074 $newContribution = $this->callAPISuccess('contribution', 'getsingle', array(
5896d037 1075 'id' => array(
21dfd5f5 1076 'NOT IN' => array($contribution['id']),
5896d037
TO
1077 ),
1078 'contribution_page_id' => $this->_ids['contribution_page'],
21dfd5f5 1079 'contribution_status_id' => 2,
5896d037 1080 )
f8fe0df6 1081 );
51f8c59c 1082 $line = $this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $newContribution['id']));
1083 $this->assertEquals('civicrm_membership', $line['entity_table']);
1084 $this->assertEquals($membership['id'], $line['entity_id']);
e6fa4056 1085
f8fe0df6 1086 $renewedMembership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
1087 //no renewal as the date hasn't changed
1088 $this->assertEquals($membership['end_date'], $renewedMembership['end_date']);
e6fa4056
EM
1089 $recurringContribution = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $newContribution['contribution_recur_id']));
1090 $this->assertEquals(2, $recurringContribution['contribution_status_id']);
f8fe0df6 1091 }
1092
f9342903 1093 /**
eceb18cc 1094 * Set up membership contribution page.
f9342903
EM
1095 * @param bool $isSeparatePayment
1096 */
00be9182 1097 public function setUpMembershipContributionPage($isSeparatePayment = FALSE) {
f9342903 1098 $this->setUpMembershipBlockPriceSet();
a380f4a0 1099 $this->setupPaymentProcessor();
f9342903
EM
1100 $this->setUpContributionPage();
1101
1102 $this->callAPISuccess('membership_block', 'create', array(
1103 'entity_id' => $this->_ids['contribution_page'],
1104 'entity_table' => 'civicrm_contribution_page',
1105 'is_required' => TRUE,
1106 'is_active' => TRUE,
1107 'is_separate_payment' => $isSeparatePayment,
1108 'membership_type_default' => $this->_ids['membership_type'],
1109 ));
f64a217a
EM
1110 }
1111
dccd9f4f
ERL
1112 /**
1113 * Set up pledge block.
1114 */
1115 public function setUpPledgeBlock() {
1116 $params = array(
1117 'entity_table' => 'civicrm_contribution_page',
1118 'entity_id' => $this->_ids['contribution_page'],
1119 'pledge_frequency_unit' => 'week',
1120 'is_pledge_interval' => 0,
1121 'pledge_start_date' => json_encode(array('calendar_date' => date('Ymd', strtotime("+1 month")))),
1122 );
1123 $pledgeBlock = CRM_Pledge_BAO_PledgeBlock::create($params);
1124 $this->_ids['pledge_block_id'] = $pledgeBlock->id;
1125 }
1126
f9342903 1127 /**
dd1b539a 1128 * The default data set does not include a complete default membership price set - not quite sure why.
1129 *
f9342903
EM
1130 * This function ensures it exists & populates $this->_ids with it's data
1131 */
00be9182 1132 public function setUpMembershipBlockPriceSet() {
5896d037 1133 $this->_ids['price_set'][] = $this->callAPISuccess('price_set', 'getvalue', array(
92915c55
TO
1134 'name' => 'default_membership_type_amount',
1135 'return' => 'id',
1136 ));
f9342903 1137 if (empty($this->_ids['membership_type'])) {
3e28c791 1138 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 2)));
f9342903 1139 }
3e28c791
EM
1140 $priceField = $this->callAPISuccess('price_field', 'create', array(
1141 'price_set_id' => reset($this->_ids['price_set']),
1142 'name' => 'membership_amount',
1143 'label' => 'Membership Amount',
1144 'html_type' => 'Radio',
1145 'sequential' => 1,
1146 ));
1147 $this->_ids['price_field'][] = $priceField['id'];
dd1b539a 1148
3e28c791
EM
1149 foreach ($this->_ids['membership_type'] as $membershipTypeID) {
1150 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
f9342903
EM
1151 'name' => 'membership_amount',
1152 'label' => 'Membership Amount',
65e172a3 1153 'amount' => 2,
43dbd988 1154 'financial_type_id' => 'Donation',
3e28c791
EM
1155 'format.only_id' => TRUE,
1156 'membership_type_id' => $membershipTypeID,
1157 'price_field_id' => $priceField['id'],
f9342903 1158 ));
840e3907 1159 $this->_ids['price_field_value'][] = $priceFieldValue;
f9342903 1160 }
65e172a3 1161 if (!empty($this->_ids['membership_type']['org2'])) {
1162 $priceField = $this->callAPISuccess('price_field', 'create', array(
1163 'price_set_id' => reset($this->_ids['price_set']),
1164 'name' => 'membership_org2',
1165 'label' => 'Membership Org2',
1166 'html_type' => 'Checkbox',
1167 'sequential' => 1,
1168 ));
1169 $this->_ids['price_field']['org2'] = $priceField['id'];
1170
1171 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
1172 'name' => 'membership_org2',
1173 'label' => 'Membership org 2',
1174 'amount' => 55,
1175 'financial_type_id' => 'Member Dues',
1176 'format.only_id' => TRUE,
1177 'membership_type_id' => $this->_ids['membership_type']['org2'],
1178 'price_field_id' => $priceField['id'],
1179 ));
1180 $this->_ids['price_field_value']['org2'] = $priceFieldValue;
1181 }
13a16f43 1182 $priceField = $this->callAPISuccess('price_field', 'create', array(
1183 'price_set_id' => reset($this->_ids['price_set']),
1184 'name' => 'Contribution',
1185 'label' => 'Contribution',
1186 'html_type' => 'Text',
1187 'sequential' => 1,
1188 'is_enter_qty' => 1,
1189 ));
1190 $this->_ids['price_field']['cont'] = $priceField['id'];
1191 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
1192 'name' => 'contribution',
1193 'label' => 'Give me money',
1194 'amount' => 88,
1195 'financial_type_id' => 'Donation',
1196 'format.only_id' => TRUE,
1197 'price_field_id' => $priceField['id'],
1198 ));
1199 $this->_ids['price_field_value'][] = $priceFieldValue;
f9342903 1200 }
3e28c791 1201
2f59d010 1202 /**
1203 * Add text field other amount to the price set.
1204 */
1205 public function addOtherAmountFieldToMembershipPriceSet() {
1206 $this->_ids['price_field']['other_amount'] = $this->callAPISuccess('price_field', 'create', array(
1207 'price_set_id' => reset($this->_ids['price_set']),
1208 'name' => 'other_amount',
1209 'label' => 'Other Amount',
1210 'html_type' => 'Text',
1211 'format.only_id' => TRUE,
1212 'sequential' => 1,
1213 ));
1214 $this->_ids['price_field_value']['other_amount'] = $this->callAPISuccess('price_field_value', 'create', array(
1215 'financial_type_id' => 'Donation',
1216 'format.only_id' => TRUE,
1217 'label' => 'Other Amount',
1218 'amount' => 1,
1219 'price_field_id' => $this->_ids['price_field']['other_amount'],
1220 ));
1221 }
1222
f64a217a 1223 /**
eceb18cc 1224 * Help function to set up contribution page with some defaults.
f64a217a 1225 */
00be9182 1226 public function setUpContributionPage() {
f64a217a
EM
1227 $contributionPageResult = $this->callAPISuccess($this->_entity, 'create', $this->params);
1228 if (empty($this->_ids['price_set'])) {
1229 $priceSet = $this->callAPISuccess('price_set', 'create', $this->_priceSetParams);
1230 $this->_ids['price_set'][] = $priceSet['id'];
1231 }
1232 $priceSetID = reset($this->_ids['price_set']);
5896d037 1233 CRM_Price_BAO_PriceSet::addTo('civicrm_contribution_page', $contributionPageResult['id'], $priceSetID);
f9342903
EM
1234
1235 if (empty($this->_ids['price_field'])) {
1236 $priceField = $this->callAPISuccess('price_field', 'create', array(
1237 'price_set_id' => $priceSetID,
1238 'label' => 'Goat Breed',
1239 'html_type' => 'Radio',
1240 ));
1241 $this->_ids['price_field'] = array($priceField['id']);
1242 }
1243 if (empty($this->_ids['price_field_value'])) {
1244 $this->callAPISuccess('price_field_value', 'create', array(
1245 'price_set_id' => $priceSetID,
1246 'price_field_id' => $priceField['id'],
1247 'label' => 'Long Haired Goat',
43dbd988 1248 'financial_type_id' => 'Donation',
f9342903 1249 'amount' => 20,
05465712 1250 'non_deductible_amount' => 15,
f9342903
EM
1251 )
1252 );
1253 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
1254 'price_set_id' => $priceSetID,
1255 'price_field_id' => $priceField['id'],
1256 'label' => 'Shoe-eating Goat',
43dbd988 1257 'financial_type_id' => 'Donation',
f9342903 1258 'amount' => 10,
05465712 1259 'non_deductible_amount' => 5,
f9342903
EM
1260 )
1261 );
1262 $this->_ids['price_field_value'] = array($priceFieldValue['id']);
1263 }
f64a217a 1264 $this->_ids['contribution_page'] = $contributionPageResult['id'];
be26f3e0
EM
1265 }
1266
6a488035 1267 public static function setUpBeforeClass() {
6c6e6187 1268 // put stuff here that should happen before all tests in this unit
6a488035
TO
1269 }
1270
5896d037 1271 public static function tearDownAfterClass() {
6a488035
TO
1272 $tablesToTruncate = array(
1273 'civicrm_contact',
1274 'civicrm_financial_type',
1275 'civicrm_contribution',
1276 'civicrm_contribution_page',
1277 );
1278 $unitTest = new CiviUnitTestCase();
1279 $unitTest->quickCleanup($tablesToTruncate);
1280 }
96025800 1281
a380f4a0
EM
1282 /**
1283 * Create a payment processor instance.
1284 */
1285 protected function setupPaymentProcessor() {
1286 $this->params['payment_processor_id'] = $this->_ids['payment_processor'] = $this->paymentProcessorCreate(array(
1287 'payment_processor_type_id' => 'Dummy',
1288 'class_name' => 'Payment_Dummy',
1289 'billing_mode' => 1,
1290 ));
1291 $this->_paymentProcessor = $this->callAPISuccess('payment_processor', 'getsingle', array('id' => $this->params['payment_processor_id']));
1292 }
1293
dccd9f4f
ERL
1294 /**
1295 * Test submit recurring pledge.
1296 *
1297 * - we process 1 pledge with a future start date. A recur contribution and the pledge should be created with first payment date in the future.
1298 */
1299 public function testSubmitPledgePaymentPaymentProcessorRecurFuturePayment() {
1300 $this->params['adjust_recur_start_date'] = TRUE;
1301 $this->params['is_pay_later'] = FALSE;
1302 $this->setUpContributionPage();
1303 $this->setUpPledgeBlock();
1304 $this->setupPaymentProcessor();
1305 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
1306 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success'));
1307
1308 $submitParams = array(
1309 'id' => (int) $this->_ids['contribution_page'],
1310 'amount' => 100,
1311 'billing_first_name' => 'Billy',
1312 'billing_middle_name' => 'Goat',
1313 'billing_last_name' => 'Gruff',
1314 'email' => 'billy@goat.gruff',
1315 'payment_processor_id' => 1,
1316 'credit_card_number' => '4111111111111111',
1317 'credit_card_type' => 'Visa',
1318 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
1319 'cvv2' => 123,
1320 'pledge_frequency_interval' => 1,
1321 'pledge_frequency_unit' => 'week',
1322 'pledge_installments' => 3,
1323 'is_pledge' => TRUE,
1324 'pledge_block_id' => (int) $this->_ids['pledge_block_id'],
1325 );
1326
1327 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
1328
1329 // Check if contribution created.
1330 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
1331 'contribution_page_id' => $this->_ids['contribution_page'],
1332 'contribution_status_id' => 'Completed', // Will be pending when actual payment processor is used (dummy processor does not support future payments).
1333 ));
1334
1335 $this->assertEquals('create_first_success', $contribution['trxn_id']);
1336
1337 // Check if pledge created.
1338 $pledge = $this->callAPISuccess('pledge', 'getsingle', array());
1339 $this->assertEquals(date('Ymd', strtotime($pledge['pledge_start_date'])), date('Ymd', strtotime("+1 month")));
1340 $this->assertEquals($pledge['pledge_amount'], 300.00);
1341
1342 // Check if pledge payments created.
1343 $params = array(
1344 'pledge_id' => $pledge['id'],
1345 );
1346 $pledgePayment = $this->callAPISuccess('pledge_payment', 'get', $params);
1347 $this->assertEquals($pledgePayment['count'], 3);
1348 $this->assertEquals(date('Ymd', strtotime($pledgePayment['values'][1]['scheduled_date'])), date('Ymd', strtotime("+1 month")));
1349 $this->assertEquals($pledgePayment['values'][1]['scheduled_amount'], 100.00);
1350 $this->assertEquals($pledgePayment['values'][1]['status_id'], 1); // Will be pending when actual payment processor is used (dummy processor does not support future payments).
1351
1352 // Check contribution recur record.
1353 $recur = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
1354 $this->assertEquals(date('Ymd', strtotime($recur['start_date'])), date('Ymd', strtotime("+1 month")));
1355 $this->assertEquals($recur['amount'], 100.00);
1356 $this->assertEquals($recur['contribution_status_id'], 5); // In progress status.
1357 }
1358
603577b2
E
1359 /**
1360 * Test submit pledge payment.
1361 *
1362 * - test submitting a pledge payment using contribution form.
1363 */
1364 public function testSubmitPledgePayment() {
1365 $this->testSubmitPledgePaymentPaymentProcessorRecurFuturePayment();
1366 $pledge = $this->callAPISuccess('pledge', 'getsingle', array());
1367 $params = array(
1368 'pledge_id' => $pledge['id'],
1369 );
1370 $submitParams = array(
1371 'id' => (int) $pledge['pledge_contribution_page_id'],
1372 'pledge_amount' => array(2 => 1),
1373 'billing_first_name' => 'Billy',
1374 'billing_middle_name' => 'Goat',
1375 'billing_last_name' => 'Gruff',
1376 'email' => 'billy@goat.gruff',
1377 'payment_processor_id' => 1,
1378 'credit_card_number' => '4111111111111111',
1379 'credit_card_type' => 'Visa',
1380 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
1381 'cvv2' => 123,
1382 'pledge_id' => $pledge['id'],
1383 'cid' => $pledge['contact_id'],
1384 'contact_id' => $pledge['contact_id'],
1385 'amount' => 100.00,
1386 'is_pledge' => TRUE,
1387 'pledge_block_id' => $this->_ids['pledge_block_id'],
1388 );
1389 $pledgePayment = $this->callAPISuccess('pledge_payment', 'get', $params);
1390 $this->assertEquals($pledgePayment['values'][2]['status_id'], 2);
1391
1392 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
1393
1394 // Check if contribution created.
1395 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
1396 'contribution_page_id' => $pledge['pledge_contribution_page_id'],
1397 'contribution_status_id' => 'Completed',
1398 'contact_id' => $pledge['contact_id'],
1399 'contribution_recur_id' => array('IS NULL' => 1),
1400 ));
1401
1402 $this->assertEquals(100.00, $contribution['total_amount']);
1403 $pledgePayment = $this->callAPISuccess('pledge_payment', 'get', $params);
1404 $this->assertEquals($pledgePayment['values'][2]['status_id'], 1, "This pledge payment should have been completed");
1405 $this->assertEquals($pledgePayment['values'][2]['contribution_id'], $contribution['id']);
1406 }
1407
a93e9452
PN
1408 /**
1409 * Test form submission with multiple option price set.
1410 */
1411 public function testSubmitContributionPageWithPriceSet() {
1412 $this->_priceSetParams['is_quick_config'] = 0;
1413 $this->setUpContributionPage();
1414 $submitParams = array(
1415 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
1416 'id' => (int) $this->_ids['contribution_page'],
1417 'amount' => 80,
1418 'first_name' => 'Billy',
1419 'last_name' => 'Gruff',
1420 'email' => 'billy@goat.gruff',
1421 'is_pay_later' => TRUE,
1422 );
1423 $this->addPriceFields($submitParams);
1424
1425 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
1426 $contribution = $this->callAPISuccessGetSingle('contribution', array(
1427 'contribution_page_id' => $this->_ids['contribution_page'],
1428 'contribution_status_id' => 2,
1429 ));
1430 $this->callAPISuccessGetCount(
1431 'LineItem',
1432 array(
1433 'contribution_id' => $contribution['id'],
1434 ),
1435 3
1436 );
1437 }
1438
1439 /**
1440 * Function to add additional price fields to priceset.
1441 * @param array $params
1442 */
1443 public function addPriceFields(&$params) {
1444 $priceSetID = reset($this->_ids['price_set']);
1445 $priceField = $this->callAPISuccess('price_field', 'create', array(
1446 'price_set_id' => $priceSetID,
1447 'label' => 'Chicken Breed',
1448 'html_type' => 'CheckBox',
1449 ));
1450 $priceFieldValue1 = $this->callAPISuccess('price_field_value', 'create', array(
1451 'price_set_id' => $priceSetID,
1452 'price_field_id' => $priceField['id'],
1453 'label' => 'Shoe-eating chicken -1',
1454 'financial_type_id' => 'Donation',
1455 'amount' => 30,
1456 ));
1457 $priceFieldValue2 = $this->callAPISuccess('price_field_value', 'create', array(
1458 'price_set_id' => $priceSetID,
1459 'price_field_id' => $priceField['id'],
1460 'label' => 'Shoe-eating chicken -2',
1461 'financial_type_id' => 'Donation',
1462 'amount' => 40,
1463 ));
1464 $params['price_' . $priceField['id']] = array(
1465 $priceFieldValue1['id'] => 1,
1466 $priceFieldValue2['id'] => 1,
1467 );
1468 }
1469
57d395bb
K
1470 /**
1471 * Test Tax Amount is calculated properly when using PriceSet with Field Type = Text/Numeric Quantity
1472 */
1473 public function testSubmitContributionPageWithPriceSetQuantity() {
1474 $this->_priceSetParams['is_quick_config'] = 0;
1475 $this->enableTaxAndInvoicing();
1476 $financialType = $this->createFinancialType();
1477 $financialTypeId = $financialType['id'];
1478 // This function sets the Tax Rate at 10% - it currently has no way to pass Tax Rate into it - so let's work with 10%
1479 $financialAccount = $this->relationForFinancialTypeWithFinancialAccount($financialType['id'], 5);
1480
1481 $this->setUpContributionPage();
1482 $submitParams = array(
1483 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
1484 'id' => (int) $this->_ids['contribution_page'],
1485 'first_name' => 'J',
1486 'last_name' => 'T',
1487 'email' => 'JT@ohcanada.ca',
1488 'is_pay_later' => TRUE,
1489 );
1490
1491 // Create PriceSet/PriceField
1492 $priceSetID = reset($this->_ids['price_set']);
1493 $priceField = $this->callAPISuccess('price_field', 'create', array(
1494 'price_set_id' => $priceSetID,
1495 'label' => 'Printing Rights',
1496 'html_type' => 'Text',
1497 ));
1498 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
1499 'price_set_id' => $priceSetID,
1500 'price_field_id' => $priceField['id'],
1501 'label' => 'Printing Rights',
1502 'financial_type_id' => $financialTypeId,
1503 'amount' => '16.95',
1504 ));
1505 $priceFieldId = $priceField['id'];
1506
1507 // Set quantity for our test
1508 $submitParams['price_' . $priceFieldId] = 180;
1509
1510 // contribution_page submit requires amount and tax_amount - and that's ok we're not testing that - we're testing at the LineItem level
1511 $submitParams['amount'] = 180 * 16.95;
1512 // This is the correct Tax Amount - use it later to compare to what the CiviCRM Core came up with at the LineItem level
1513 $submitParams['tax_amount'] = 180 * 16.95 * 0.10;
1514
1515 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
1516 $contribution = $this->callAPISuccessGetSingle('contribution', array(
1517 'contribution_page_id' => $this->_ids['contribution_page'],
1518 ));
1519
1520 // Retrieve the lineItem that belongs to the Printing Rights and check the tax_amount CiviCRM Core calculated for it
1521 $lineItem = $this->callAPISuccess('LineItem', 'get', array(
1522 'contribution_id' => $contribution['id'],
1523 'label' => 'Printing Rights',
1524 ));
1525 $lineItemId = $lineItem['id'];
1526 $lineItem_TaxAmount = round($lineItem['values'][$lineItemId]['tax_amount'], 2);
1527
1528 // Compare this to what it should be!
1529 $this->assertEquals($lineItem_TaxAmount, round($submitParams['tax_amount'], 2), 'Wrong Sales Tax Amount is calculated and stored.');
1530 }
1531
6a488035 1532}