CRM-19594 further fix on creating correct line items for memberships
[civicrm-core.git] / tests / phpunit / api / v3 / ContributionPageTest.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
81621fee 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
fa938177 6 | Copyright CiviCRM LLC (c) 2004-2016 |
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 );
fc928539 118 $getResult = $this->callAPIAndDocument($this->_entity, 'get', $getParams, __FUNCTION__, __FILE__);
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
2f59d010 316 /**
317 * Test submit with a membership block in place.
318 */
319 public function testSubmitMembershipBlockNotSeparatePaymentWithEmail() {
320 $mut = new CiviMailUtils($this, TRUE);
321 $this->setUpMembershipContributionPage();
322 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
323
324 $submitParams = array(
325 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
326 'id' => (int) $this->_ids['contribution_page'],
327 'amount' => 10,
328 'billing_first_name' => 'Billy',
329 'billing_middle_name' => 'Goat',
330 'billing_last_name' => 'Gruff',
331 'selectMembership' => $this->_ids['membership_type'],
332 'email-Primary' => 'billy-goat@the-bridge.net',
9daadfce 333 'payment_processor_id' => $this->_paymentProcessor['id'],
334 'credit_card_number' => '4111111111111111',
335 'credit_card_type' => 'Visa',
336 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
337 'cvv2' => 123,
2f59d010 338 );
339
340 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
341 $contribution = $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
342 $this->callAPISuccess('membership_payment', 'getsingle', array('contribution_id' => $contribution['id']));
343 $mut->checkMailLog(array(
344 'Membership Type: General',
345 ));
346 $mut->stop();
347 $mut->clearMessages();
348 }
349
350 /**
351 * Test submit with a membership block in place.
352 */
353 public function testSubmitMembershipBlockNotSeparatePaymentZeroDollarsWithEmail() {
354 $mut = new CiviMailUtils($this, TRUE);
355 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 0)));
356 $this->setUpMembershipContributionPage();
357 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
358
359 $submitParams = array(
360 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
361 'id' => (int) $this->_ids['contribution_page'],
362 'amount' => 0,
363 'billing_first_name' => 'Billy',
364 'billing_middle_name' => 'Goat',
365 'billing_last_name' => 'Gruffier',
366 'selectMembership' => $this->_ids['membership_type'],
367 'email-Primary' => 'billy-goat@the-new-bridge.net',
368 );
369
370 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
371 $contribution = $this->callAPISuccess('contribution', 'getsingle', array('contribution_page_id' => $this->_ids['contribution_page']));
372 $this->callAPISuccess('membership_payment', 'getsingle', array('contribution_id' => $contribution['id']));
373 $mut->checkMailLog(array(
374 'Membership Type: General',
375 'Gruffier',
376 ),
377 array(
378 'Amount',
379 )
380 );
381 $mut->stop();
9daadfce 382 $mut->clearMessages(999);
2f59d010 383 }
384
f9342903 385 /**
eceb18cc 386 * Test submit with a membership block in place.
f9342903
EM
387 */
388 public function testSubmitMembershipBlockIsSeparatePayment() {
389 $this->setUpMembershipContributionPage(TRUE);
9daadfce 390 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 2)));
f9342903 391 $submitParams = array(
3e28c791 392 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
f9342903
EM
393 'id' => (int) $this->_ids['contribution_page'],
394 'amount' => 10,
395 'billing_first_name' => 'Billy',
396 'billing_middle_name' => 'Goat',
397 'billing_last_name' => 'Gruff',
398 'selectMembership' => $this->_ids['membership_type'],
399 );
400
a828d7b8 401 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
f9342903
EM
402 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
403 $this->assertCount(2, $contributions['values']);
417c6834 404 $this->callAPISuccessGetCount('LineItem', array(), 2);
f9342903
EM
405 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
406 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
407 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
408 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
409 }
f64a217a 410
2f59d010 411 /**
412 * Test submit with a membership block in place.
413 */
414 public function testSubmitMembershipBlockIsSeparatePaymentWithEmail() {
415 $mut = new CiviMailUtils($this, TRUE);
416 $this->setUpMembershipContributionPage(TRUE);
417 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
418
419 $submitParams = array(
420 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
421 'id' => (int) $this->_ids['contribution_page'],
422 'amount' => 10,
423 'billing_first_name' => 'Billy',
424 'billing_middle_name' => 'Goat',
425 'billing_last_name' => 'Gruff',
426 'selectMembership' => $this->_ids['membership_type'],
427 'email-Primary' => 'billy-goat@the-bridge.net',
9daadfce 428 'payment_processor_id' => $this->_paymentProcessor['id'],
429 'credit_card_number' => '4111111111111111',
430 'credit_card_type' => 'Visa',
431 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
432 'cvv2' => 123,
2f59d010 433 );
434
435 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
436 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
437 $this->assertCount(2, $contributions['values']);
438 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
439 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
440 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
441 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
9daadfce 442 $mut->checkAllMailLog(array(
443 '$ 2.00',
2f59d010 444 'Membership Fee',
445 ));
446 $mut->stop();
9daadfce 447 $mut->clearMessages(999);
2f59d010 448 }
449
450 /**
451 * Test submit with a membership block in place.
452 */
453 public function testSubmitMembershipBlockIsSeparatePaymentZeroDollarsPayLaterWithEmail() {
454 $mut = new CiviMailUtils($this, TRUE);
455 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 0)));
456 $this->setUpMembershipContributionPage(TRUE);
457 $this->addProfile('supporter_profile', $this->_ids['contribution_page']);
458
459 $submitParams = array(
460 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
461 'id' => (int) $this->_ids['contribution_page'],
462 'amount' => 0,
463 'billing_first_name' => 'Billy',
464 'billing_middle_name' => 'Goat',
465 'billing_last_name' => 'Gruffalo',
466 'selectMembership' => $this->_ids['membership_type'],
467 'payment_processor_id' => 0,
468 'email-Primary' => 'gruffalo@the-bridge.net',
469 );
470
471 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
472 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
473 $this->assertCount(2, $contributions['values']);
474 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
475 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
476 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
477 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
478 $mut->checkMailLog(array(
479 'Gruffalo',
480 'General Membership: $ 0.00',
481 'Membership Fee',
482 ));
483 $mut->stop();
484 $mut->clearMessages();
485 }
486
797c4f88 487 /**
eceb18cc 488 * Test submit with a membership block in place.
797c4f88
EM
489 */
490 public function testSubmitMembershipBlockTwoTypesIsSeparatePayment() {
491 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 6)));
492 $this->_ids['membership_type'][] = $this->membershipTypeCreate(array('name' => 'Student', 'minimum_fee' => 50));
493 $this->setUpMembershipContributionPage(TRUE);
494 $submitParams = array(
495 'price_' . $this->_ids['price_field'][0] => $this->_ids['price_field_value'][1],
496 'id' => (int) $this->_ids['contribution_page'],
497 'amount' => 10,
498 'billing_first_name' => 'Billy',
499 'billing_middle_name' => 'Goat',
500 'billing_last_name' => 'Gruff',
501 'selectMembership' => $this->_ids['membership_type'][1],
502 );
503
a828d7b8 504 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
6c6e6187 505 $contributions = $this->callAPISuccess('contribution', 'get', array('contribution_page_id' => $this->_ids['contribution_page']));
797c4f88
EM
506 $this->assertCount(2, $contributions['values']);
507 $ids = array_keys($contributions['values']);
508 $this->assertEquals('10.00', $contributions['values'][$ids[0]]['total_amount']);
509 $this->assertEquals('50.00', $contributions['values'][$ids[1]]['total_amount']);
510 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
511 $this->assertArrayHasKey($membershipPayment['contribution_id'], $contributions['values']);
512 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
513 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
514 }
515
8ca611b7 516 /**
eceb18cc 517 * Test submit with a membership block in place.
329f3f66
EM
518 *
519 * We are expecting a separate payment for the membership vs the contribution.
8ca611b7 520 */
329f3f66 521 public function testSubmitMembershipBlockIsSeparatePaymentPaymentProcessorNow() {
8ca611b7 522 $this->setUpMembershipContributionPage(TRUE);
0193ebdb 523 $processor = Civi\Payment\System::singleton()->getById($this->_paymentProcessor['id']);
524 $processor->setDoDirectPaymentResult(array('fee_amount' => .72));
8ca611b7
EM
525 $submitParams = array(
526 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
527 'id' => (int) $this->_ids['contribution_page'],
528 'amount' => 10,
529 'billing_first_name' => 'Billy',
530 'billing_middle_name' => 'Goat',
531 'billing_last_name' => 'Gruff',
532 'selectMembership' => $this->_ids['membership_type'],
7bc789a5 533 'payment_processor_id' => $this->_paymentProcessor['id'],
8ca611b7
EM
534 'credit_card_number' => '4111111111111111',
535 'credit_card_type' => 'Visa',
5896d037 536 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
8ca611b7
EM
537 'cvv2' => 123,
538 );
05990684 539
a828d7b8 540 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
5896d037 541 $contributions = $this->callAPISuccess('contribution', 'get', array(
92915c55
TO
542 'contribution_page_id' => $this->_ids['contribution_page'],
543 'contribution_status_id' => 1,
544 ));
8ca611b7
EM
545 $this->assertCount(2, $contributions['values']);
546 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
547 $this->assertTrue(in_array($membershipPayment['contribution_id'], array_keys($contributions['values'])));
548 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
549 $this->assertEquals($membership['contact_id'], $contributions['values'][$membershipPayment['contribution_id']]['contact_id']);
0193ebdb 550 foreach ($contributions['values'] as $contribution) {
551 $this->assertEquals(.72, $contribution['fee_amount']);
552 $this->assertEquals($contribution['total_amount'] - .72, $contribution['net_amount']);
553 }
8ca611b7 554 }
f8fe0df6 555
5961bd47
EM
556 /**
557 * Test that when a transaction fails the pending contribution remains.
558 *
559 * An activity should also be created. CRM-16417.
560 */
561 public function testSubmitPaymentProcessorFailure() {
562 $this->setUpContributionPage();
563 $this->setupPaymentProcessor();
564 $this->createLoggedInUser();
565 $priceFieldID = reset($this->_ids['price_field']);
566 $priceFieldValueID = reset($this->_ids['price_field_value']);
567 $submitParams = array(
568 'price_' . $priceFieldID => $priceFieldValueID,
569 'id' => (int) $this->_ids['contribution_page'],
570 'amount' => 10,
571 'payment_processor_id' => 1,
572 'credit_card_number' => '4111111111111111',
573 'credit_card_type' => 'Visa',
574 'credit_card_exp_date' => array('M' => 9, 'Y' => 2008),
575 'cvv2' => 123,
576 );
577
578 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
579 $contribution = $this->callAPISuccessGetSingle('contribution', array(
580 'contribution_page_id' => $this->_ids['contribution_page'],
581 'contribution_status_id' => 2,
582 ));
583
584 $this->callAPISuccessGetSingle('activity', array(
585 'source_record_id' => $contribution['id'],
586 'activity_type_id' => 'Failed Payment',
587 ));
588
5961bd47
EM
589 }
590
f8fe0df6 591 /**
dd1b539a 592 * Test submit recurring membership with immediate confirmation (IATS style).
593 *
e6fa4056 594 * - we process 2 membership transactions against with a recurring contribution against a contribution page with an immediate
1fee3ad2 595 * processor (IATS style - denoted by returning trxn_id)
e6fa4056
EM
596 * - the first creates a new membership, completed contribution, in progress recurring. Check these
597 * - create another - end date should be extended
f8fe0df6 598 */
8bef2e38 599 public function testSubmitMembershipPriceSetPaymentPaymentProcessorRecurInstantPayment() {
f8fe0df6 600 $this->params['is_recur'] = 1;
f8fe0df6 601 $this->params['recur_frequency_unit'] = 'month';
602 $this->setUpMembershipContributionPage();
7c85dc65 603 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
8bef2e38 604 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success'));
f69a9ac3 605 $processor = $dummyPP->getPaymentProcessor();
f8fe0df6 606
607 $submitParams = array(
608 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
609 'id' => (int) $this->_ids['contribution_page'],
610 'amount' => 10,
611 'billing_first_name' => 'Billy',
612 'billing_middle_name' => 'Goat',
613 'billing_last_name' => 'Gruff',
614 'email' => 'billy@goat.gruff',
615 'selectMembership' => $this->_ids['membership_type'],
579a1fb7 616 'payment_processor_id' => 1,
f8fe0df6 617 'credit_card_number' => '4111111111111111',
618 'credit_card_type' => 'Visa',
5896d037 619 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
f8fe0df6 620 'cvv2' => 123,
621 'is_recur' => 1,
622 'frequency_interval' => 1,
623 'frequency_unit' => 'month',
624 );
625
a828d7b8 626 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
5896d037 627 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
92915c55
TO
628 'contribution_page_id' => $this->_ids['contribution_page'],
629 'contribution_status_id' => 1,
630 ));
f69a9ac3 631 $this->assertEquals($processor['payment_instrument_id'], $contribution['payment_instrument_id']);
0739d6cf 632
633 $this->assertEquals('create_first_success', $contribution['trxn_id']);
f8fe0df6 634 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
635 $this->assertEquals($membershipPayment['contribution_id'], $contribution['id']);
636 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
637 $this->assertEquals($membership['contact_id'], $contribution['contact_id']);
638 $this->assertEquals(1, $membership['status_id']);
639 $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
356bfcaf 640
641 $this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $contribution['id'], 'entity_id' => $membership['id']));
f8fe0df6 642 //renew it with processor setting completed - should extend membership
643 $submitParams['contact_id'] = $contribution['contact_id'];
8bef2e38 644 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_second_success'));
f8fe0df6 645 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
5896d037 646 $this->callAPISuccess('contribution', 'getsingle', array(
92915c55
TO
647 'id' => array('NOT IN' => array($contribution['id'])),
648 'contribution_page_id' => $this->_ids['contribution_page'],
649 'contribution_status_id' => 1,
650 ));
f8fe0df6 651 $renewedMembership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
652 $this->assertEquals(date('Y-m-d', strtotime('+ 1 year', strtotime($membership['end_date']))), $renewedMembership['end_date']);
653 $recurringContribution = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
f69a9ac3 654 $this->assertEquals($processor['payment_instrument_id'], $recurringContribution['payment_instrument_id']);
91259407 655 $this->assertEquals(5, $recurringContribution['contribution_status_id']);
f8fe0df6 656 }
657
13a16f43 658 /**
659 * Test submit recurring membership with immediate confirmation (IATS style).
660 *
661 * - we process 2 membership transactions against with a recurring contribution against a contribution page with an immediate
662 * processor (IATS style - denoted by returning trxn_id)
663 * - the first creates a new membership, completed contribution, in progress recurring. Check these
664 * - create another - end date should be extended
665 */
666 public function testSubmitMembershipComplexPriceSetPaymentPaymentProcessorRecurInstantPayment() {
667 $this->params['is_recur'] = 1;
668 $this->params['recur_frequency_unit'] = 'month';
669 // Add a membership so membership & contribution are not both 1.
670 $preExistingMembershipID = $this->contactMembershipCreate(array('contact_id' => $this->contactIds[0]));
671 $this->setUpMembershipContributionPage();
672 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
673 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success'));
674 $processor = $dummyPP->getPaymentProcessor();
675
676 $submitParams = array(
677 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
678 'price_' . $this->_ids['price_field']['cont'] => 88,
679 'id' => (int) $this->_ids['contribution_page'],
680 'amount' => 10,
681 'billing_first_name' => 'Billy',
682 'billing_middle_name' => 'Goat',
683 'billing_last_name' => 'Gruff',
684 'email' => 'billy@goat.gruff',
685 'selectMembership' => $this->_ids['membership_type'],
686 'payment_processor_id' => 1,
687 'credit_card_number' => '4111111111111111',
688 'credit_card_type' => 'Visa',
689 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
690 'cvv2' => 123,
691 'is_recur' => 1,
692 'frequency_interval' => 1,
693 'frequency_unit' => 'month',
694 );
695
696 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
697 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
698 'contribution_page_id' => $this->_ids['contribution_page'],
699 'contribution_status_id' => 1,
700 ));
701 $this->assertEquals($processor['payment_instrument_id'], $contribution['payment_instrument_id']);
702
703 $this->assertEquals('create_first_success', $contribution['trxn_id']);
704 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
705 $this->assertEquals($membershipPayment['contribution_id'], $contribution['id']);
706 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
707 $this->assertEquals($membership['contact_id'], $contribution['contact_id']);
708 $this->assertEquals(1, $membership['status_id']);
709 $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
710
711 $lines = $this->callAPISuccess('line_item', 'get', array('sequential' => 1, 'contribution_id' => $contribution['id']));
712 $this->assertEquals(2, $lines['count']);
713 $this->assertEquals('civicrm_membership', $lines['values'][0]['entity_table']);
714 $this->assertEquals($preExistingMembershipID + 1, $lines['values'][0]['entity_id']);
715 $this->assertEquals('civicrm_contribution', $lines['values'][1]['entity_table']);
716 $this->assertEquals($contribution['id'], $lines['values'][1]['entity_id']);
717 $this->callAPISuccessGetSingle('MembershipPayment', array('contribution_id' => $contribution['id'], 'membership_id' => $preExistingMembershipID + 1));
718
719 //renew it with processor setting completed - should extend membership
720 $submitParams['contact_id'] = $contribution['contact_id'];
721 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_second_success'));
722 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
723 $renewContribution = $this->callAPISuccess('contribution', 'getsingle', array(
724 'id' => array('NOT IN' => array($contribution['id'])),
725 'contribution_page_id' => $this->_ids['contribution_page'],
726 'contribution_status_id' => 1,
727 ));
728 $lines = $this->callAPISuccess('line_item', 'get', array('sequential' => 1, 'contribution_id' => $renewContribution['id']));
729 $this->assertEquals(2, $lines['count']);
730 $this->assertEquals('civicrm_membership', $lines['values'][0]['entity_table']);
731 $this->assertEquals($preExistingMembershipID + 1, $lines['values'][0]['entity_id']);
732 $this->assertEquals('civicrm_contribution', $lines['values'][1]['entity_table']);
733 $this->assertEquals($renewContribution['id'], $lines['values'][1]['entity_id']);
734
735 $renewedMembership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
736 $this->assertEquals(date('Y-m-d', strtotime('+ 1 year', strtotime($membership['end_date']))), $renewedMembership['end_date']);
737 $recurringContribution = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
738 $this->assertEquals($processor['payment_instrument_id'], $recurringContribution['payment_instrument_id']);
739 $this->assertEquals(5, $recurringContribution['contribution_status_id']);
740 }
741
449f4c90 742 /**
743 * Test submit recurring membership with immediate confirmation (IATS style).
744 *
745 * - we process 2 membership transactions against with a recurring contribution against a contribution page with an immediate
746 * processor (IATS style - denoted by returning trxn_id)
747 * - the first creates a new membership, completed contribution, in progress recurring. Check these
748 * - create another - end date should be extended
749 */
750 public function testSubmitMembershipPriceSetPaymentPaymentProcessorSeparatePaymentRecurInstantPayment() {
751
752 $this->setUpMembershipContributionPage(TRUE);
753 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
754 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success'));
755
756 $submitParams = array(
757 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
758 'id' => (int) $this->_ids['contribution_page'],
759 'amount' => 10,
760 'billing_first_name' => 'Billy',
761 'billing_middle_name' => 'Goat',
762 'billing_last_name' => 'Gruff',
763 'email' => 'billy@goat.gruff',
764 'selectMembership' => $this->_ids['membership_type'],
765 'payment_processor_id' => 1,
766 'credit_card_number' => '4111111111111111',
767 'credit_card_type' => 'Visa',
768 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
769 'cvv2' => 123,
770 'is_recur' => 1,
771 'auto_renew' => TRUE,
772 'frequency_interval' => 1,
773 'frequency_unit' => 'month',
774 );
775
776 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
777 $contribution = $this->callAPISuccess('contribution', 'get', array(
778 'contribution_page_id' => $this->_ids['contribution_page'],
779 'contribution_status_id' => 1,
780 ));
781
782 $this->assertEquals(2, $contribution['count']);
783 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
784 $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
785 $this->assertNotEmpty($contribution['values'][$membershipPayment['contribution_id']]['contribution_recur_id']);
786 $this->callAPISuccess('contribution_recur', 'getsingle', array());
787 }
788
f8fe0df6 789 /**
e6fa4056
EM
790 * Test submit recurring membership with delayed confirmation (Authorize.net style)
791 * - we process 2 membership transactions against with a recurring contribution against a contribution page with a delayed
792 * processor (Authorize.net style - denoted by NOT returning trxn_id)
793 * - the first creates a pending membership, pending contribution, penging recurring. Check these
794 * - complete the transaction
795 * - create another - end date should NOT be extended
f8fe0df6 796 */
797 public function testSubmitMembershipPriceSetPaymentPaymentProcessorRecurDelayed() {
798 $this->params['is_recur'] = 1;
f8fe0df6 799 $this->params['recur_frequency_unit'] = 'month';
800 $this->setUpMembershipContributionPage();
ab30e033 801 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
b5eacf76 802 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 2));
356bfcaf 803 $this->membershipTypeCreate(array('name' => 'Student'));
804
805 // Add a contribution & a couple of memberships so the id will not be 1 & will differ from membership id.
806 // This saves us from 'accidental success'.
51f8c59c 807 $this->contributionCreate(array('contact_id' => $this->contactIds[0]));
356bfcaf 808 $this->contactMembershipCreate(array('contact_id' => $this->contactIds[0]));
809 $this->contactMembershipCreate(array('contact_id' => $this->contactIds[0], 'membership_type_id' => 'Student'));
f8fe0df6 810
811 $submitParams = array(
812 'price_' . $this->_ids['price_field'][0] => reset($this->_ids['price_field_value']),
813 'id' => (int) $this->_ids['contribution_page'],
814 'amount' => 10,
815 'billing_first_name' => 'Billy',
816 'billing_middle_name' => 'Goat',
817 'billing_last_name' => 'Gruff',
818 'email' => 'billy@goat.gruff',
819 'selectMembership' => $this->_ids['membership_type'],
579a1fb7 820 'payment_processor_id' => 1,
f8fe0df6 821 'credit_card_number' => '4111111111111111',
822 'credit_card_type' => 'Visa',
5896d037 823 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
f8fe0df6 824 'cvv2' => 123,
e6fa4056
EM
825 'is_recur' => 1,
826 'frequency_interval' => 1,
827 'frequency_unit' => 'month',
f8fe0df6 828 );
829
a828d7b8 830 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
5896d037 831 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
92915c55
TO
832 'contribution_page_id' => $this->_ids['contribution_page'],
833 'contribution_status_id' => 2,
834 ));
356bfcaf 835
f8fe0df6 836 $membershipPayment = $this->callAPISuccess('membership_payment', 'getsingle', array());
837 $this->assertEquals($membershipPayment['contribution_id'], $contribution['id']);
838 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
839 $this->assertEquals($membership['contact_id'], $contribution['contact_id']);
e6fa4056 840 $this->assertEquals(5, $membership['status_id']);
51f8c59c 841
842 $line = $this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $contribution['id']));
843 $this->assertEquals('civicrm_membership', $line['entity_table']);
844 $this->assertEquals($membership['id'], $line['entity_id']);
845
5896d037 846 $this->callAPISuccess('contribution', 'completetransaction', array(
92915c55
TO
847 'id' => $contribution['id'],
848 'trxn_id' => 'ipn_called',
b396c447 849 'payment_processor_id' => $this->_paymentProcessor['id'],
92915c55 850 ));
51f8c59c 851 $line = $this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $contribution['id']));
852 $this->assertEquals('civicrm_membership', $line['entity_table']);
853 $this->assertEquals($membership['id'], $line['entity_id']);
854
e6fa4056 855 $membership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
f8fe0df6 856 //renew it with processor setting completed - should extend membership
857 $submitParams = array_merge($submitParams, array(
5896d037
TO
858 'contact_id' => $contribution['contact_id'],
859 'is_recur' => 1,
860 'frequency_interval' => 1,
861 'frequency_unit' => 'month',
862 )
f8fe0df6 863 );
51f8c59c 864
b5eacf76 865 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 2));
f8fe0df6 866 $this->callAPISuccess('contribution_page', 'submit', $submitParams);
6c6e6187 867 $newContribution = $this->callAPISuccess('contribution', 'getsingle', array(
5896d037 868 'id' => array(
21dfd5f5 869 'NOT IN' => array($contribution['id']),
5896d037
TO
870 ),
871 'contribution_page_id' => $this->_ids['contribution_page'],
21dfd5f5 872 'contribution_status_id' => 2,
5896d037 873 )
f8fe0df6 874 );
51f8c59c 875 $line = $this->callAPISuccess('line_item', 'getsingle', array('contribution_id' => $newContribution['id']));
876 $this->assertEquals('civicrm_membership', $line['entity_table']);
877 $this->assertEquals($membership['id'], $line['entity_id']);
e6fa4056 878
f8fe0df6 879 $renewedMembership = $this->callAPISuccessGetSingle('membership', array('id' => $membershipPayment['membership_id']));
880 //no renewal as the date hasn't changed
881 $this->assertEquals($membership['end_date'], $renewedMembership['end_date']);
e6fa4056
EM
882 $recurringContribution = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $newContribution['contribution_recur_id']));
883 $this->assertEquals(2, $recurringContribution['contribution_status_id']);
f8fe0df6 884 }
885
f9342903 886 /**
eceb18cc 887 * Set up membership contribution page.
f9342903
EM
888 * @param bool $isSeparatePayment
889 */
00be9182 890 public function setUpMembershipContributionPage($isSeparatePayment = FALSE) {
f9342903 891 $this->setUpMembershipBlockPriceSet();
a380f4a0 892 $this->setupPaymentProcessor();
f9342903
EM
893 $this->setUpContributionPage();
894
895 $this->callAPISuccess('membership_block', 'create', array(
896 'entity_id' => $this->_ids['contribution_page'],
897 'entity_table' => 'civicrm_contribution_page',
898 'is_required' => TRUE,
899 'is_active' => TRUE,
900 'is_separate_payment' => $isSeparatePayment,
901 'membership_type_default' => $this->_ids['membership_type'],
902 ));
f64a217a
EM
903 }
904
dccd9f4f
ERL
905 /**
906 * Set up pledge block.
907 */
908 public function setUpPledgeBlock() {
909 $params = array(
910 'entity_table' => 'civicrm_contribution_page',
911 'entity_id' => $this->_ids['contribution_page'],
912 'pledge_frequency_unit' => 'week',
913 'is_pledge_interval' => 0,
914 'pledge_start_date' => json_encode(array('calendar_date' => date('Ymd', strtotime("+1 month")))),
915 );
916 $pledgeBlock = CRM_Pledge_BAO_PledgeBlock::create($params);
917 $this->_ids['pledge_block_id'] = $pledgeBlock->id;
918 }
919
f9342903 920 /**
dd1b539a 921 * The default data set does not include a complete default membership price set - not quite sure why.
922 *
f9342903
EM
923 * This function ensures it exists & populates $this->_ids with it's data
924 */
00be9182 925 public function setUpMembershipBlockPriceSet() {
5896d037 926 $this->_ids['price_set'][] = $this->callAPISuccess('price_set', 'getvalue', array(
92915c55
TO
927 'name' => 'default_membership_type_amount',
928 'return' => 'id',
929 ));
f9342903 930 if (empty($this->_ids['membership_type'])) {
3e28c791 931 $this->_ids['membership_type'] = array($this->membershipTypeCreate(array('minimum_fee' => 2)));
f9342903 932 }
3e28c791
EM
933 $priceField = $this->callAPISuccess('price_field', 'create', array(
934 'price_set_id' => reset($this->_ids['price_set']),
935 'name' => 'membership_amount',
936 'label' => 'Membership Amount',
937 'html_type' => 'Radio',
938 'sequential' => 1,
939 ));
940 $this->_ids['price_field'][] = $priceField['id'];
dd1b539a 941
3e28c791
EM
942 foreach ($this->_ids['membership_type'] as $membershipTypeID) {
943 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
f9342903
EM
944 'name' => 'membership_amount',
945 'label' => 'Membership Amount',
3e28c791 946 'amount' => 1,
43dbd988 947 'financial_type_id' => 'Donation',
3e28c791
EM
948 'format.only_id' => TRUE,
949 'membership_type_id' => $membershipTypeID,
950 'price_field_id' => $priceField['id'],
f9342903 951 ));
840e3907 952 $this->_ids['price_field_value'][] = $priceFieldValue;
f9342903 953 }
13a16f43 954 $priceField = $this->callAPISuccess('price_field', 'create', array(
955 'price_set_id' => reset($this->_ids['price_set']),
956 'name' => 'Contribution',
957 'label' => 'Contribution',
958 'html_type' => 'Text',
959 'sequential' => 1,
960 'is_enter_qty' => 1,
961 ));
962 $this->_ids['price_field']['cont'] = $priceField['id'];
963 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
964 'name' => 'contribution',
965 'label' => 'Give me money',
966 'amount' => 88,
967 'financial_type_id' => 'Donation',
968 'format.only_id' => TRUE,
969 'price_field_id' => $priceField['id'],
970 ));
971 $this->_ids['price_field_value'][] = $priceFieldValue;
f9342903 972 }
3e28c791 973
2f59d010 974 /**
975 * Add text field other amount to the price set.
976 */
977 public function addOtherAmountFieldToMembershipPriceSet() {
978 $this->_ids['price_field']['other_amount'] = $this->callAPISuccess('price_field', 'create', array(
979 'price_set_id' => reset($this->_ids['price_set']),
980 'name' => 'other_amount',
981 'label' => 'Other Amount',
982 'html_type' => 'Text',
983 'format.only_id' => TRUE,
984 'sequential' => 1,
985 ));
986 $this->_ids['price_field_value']['other_amount'] = $this->callAPISuccess('price_field_value', 'create', array(
987 'financial_type_id' => 'Donation',
988 'format.only_id' => TRUE,
989 'label' => 'Other Amount',
990 'amount' => 1,
991 'price_field_id' => $this->_ids['price_field']['other_amount'],
992 ));
993 }
994
f64a217a 995 /**
eceb18cc 996 * Help function to set up contribution page with some defaults.
f64a217a 997 */
00be9182 998 public function setUpContributionPage() {
f64a217a
EM
999 $contributionPageResult = $this->callAPISuccess($this->_entity, 'create', $this->params);
1000 if (empty($this->_ids['price_set'])) {
1001 $priceSet = $this->callAPISuccess('price_set', 'create', $this->_priceSetParams);
1002 $this->_ids['price_set'][] = $priceSet['id'];
1003 }
1004 $priceSetID = reset($this->_ids['price_set']);
5896d037 1005 CRM_Price_BAO_PriceSet::addTo('civicrm_contribution_page', $contributionPageResult['id'], $priceSetID);
f9342903
EM
1006
1007 if (empty($this->_ids['price_field'])) {
1008 $priceField = $this->callAPISuccess('price_field', 'create', array(
1009 'price_set_id' => $priceSetID,
1010 'label' => 'Goat Breed',
1011 'html_type' => 'Radio',
1012 ));
1013 $this->_ids['price_field'] = array($priceField['id']);
1014 }
1015 if (empty($this->_ids['price_field_value'])) {
1016 $this->callAPISuccess('price_field_value', 'create', array(
1017 'price_set_id' => $priceSetID,
1018 'price_field_id' => $priceField['id'],
1019 'label' => 'Long Haired Goat',
43dbd988 1020 'financial_type_id' => 'Donation',
f9342903 1021 'amount' => 20,
3300bf67 1022 'financial_type_id' => 'Donation',
05465712 1023 'non_deductible_amount' => 15,
f9342903
EM
1024 )
1025 );
1026 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', array(
1027 'price_set_id' => $priceSetID,
1028 'price_field_id' => $priceField['id'],
1029 'label' => 'Shoe-eating Goat',
43dbd988 1030 'financial_type_id' => 'Donation',
f9342903 1031 'amount' => 10,
3300bf67 1032 'financial_type_id' => 'Donation',
05465712 1033 'non_deductible_amount' => 5,
f9342903
EM
1034 )
1035 );
1036 $this->_ids['price_field_value'] = array($priceFieldValue['id']);
1037 }
f64a217a 1038 $this->_ids['contribution_page'] = $contributionPageResult['id'];
be26f3e0
EM
1039 }
1040
6a488035 1041 public static function setUpBeforeClass() {
6c6e6187 1042 // put stuff here that should happen before all tests in this unit
6a488035
TO
1043 }
1044
5896d037 1045 public static function tearDownAfterClass() {
6a488035
TO
1046 $tablesToTruncate = array(
1047 'civicrm_contact',
1048 'civicrm_financial_type',
1049 'civicrm_contribution',
1050 'civicrm_contribution_page',
1051 );
1052 $unitTest = new CiviUnitTestCase();
1053 $unitTest->quickCleanup($tablesToTruncate);
1054 }
96025800 1055
a380f4a0
EM
1056 /**
1057 * Create a payment processor instance.
1058 */
1059 protected function setupPaymentProcessor() {
1060 $this->params['payment_processor_id'] = $this->_ids['payment_processor'] = $this->paymentProcessorCreate(array(
1061 'payment_processor_type_id' => 'Dummy',
1062 'class_name' => 'Payment_Dummy',
1063 'billing_mode' => 1,
1064 ));
1065 $this->_paymentProcessor = $this->callAPISuccess('payment_processor', 'getsingle', array('id' => $this->params['payment_processor_id']));
1066 }
1067
dccd9f4f
ERL
1068 /**
1069 * Test submit recurring pledge.
1070 *
1071 * - 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.
1072 */
1073 public function testSubmitPledgePaymentPaymentProcessorRecurFuturePayment() {
1074 $this->params['adjust_recur_start_date'] = TRUE;
1075 $this->params['is_pay_later'] = FALSE;
1076 $this->setUpContributionPage();
1077 $this->setUpPledgeBlock();
1078 $this->setupPaymentProcessor();
1079 $dummyPP = Civi\Payment\System::singleton()->getByProcessor($this->_paymentProcessor);
1080 $dummyPP->setDoDirectPaymentResult(array('payment_status_id' => 1, 'trxn_id' => 'create_first_success'));
1081
1082 $submitParams = array(
1083 'id' => (int) $this->_ids['contribution_page'],
1084 'amount' => 100,
1085 'billing_first_name' => 'Billy',
1086 'billing_middle_name' => 'Goat',
1087 'billing_last_name' => 'Gruff',
1088 'email' => 'billy@goat.gruff',
1089 'payment_processor_id' => 1,
1090 'credit_card_number' => '4111111111111111',
1091 'credit_card_type' => 'Visa',
1092 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
1093 'cvv2' => 123,
1094 'pledge_frequency_interval' => 1,
1095 'pledge_frequency_unit' => 'week',
1096 'pledge_installments' => 3,
1097 'is_pledge' => TRUE,
1098 'pledge_block_id' => (int) $this->_ids['pledge_block_id'],
1099 );
1100
1101 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
1102
1103 // Check if contribution created.
1104 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
1105 'contribution_page_id' => $this->_ids['contribution_page'],
1106 'contribution_status_id' => 'Completed', // Will be pending when actual payment processor is used (dummy processor does not support future payments).
1107 ));
1108
1109 $this->assertEquals('create_first_success', $contribution['trxn_id']);
1110
1111 // Check if pledge created.
1112 $pledge = $this->callAPISuccess('pledge', 'getsingle', array());
1113 $this->assertEquals(date('Ymd', strtotime($pledge['pledge_start_date'])), date('Ymd', strtotime("+1 month")));
1114 $this->assertEquals($pledge['pledge_amount'], 300.00);
1115
1116 // Check if pledge payments created.
1117 $params = array(
1118 'pledge_id' => $pledge['id'],
1119 );
1120 $pledgePayment = $this->callAPISuccess('pledge_payment', 'get', $params);
1121 $this->assertEquals($pledgePayment['count'], 3);
1122 $this->assertEquals(date('Ymd', strtotime($pledgePayment['values'][1]['scheduled_date'])), date('Ymd', strtotime("+1 month")));
1123 $this->assertEquals($pledgePayment['values'][1]['scheduled_amount'], 100.00);
1124 $this->assertEquals($pledgePayment['values'][1]['status_id'], 1); // Will be pending when actual payment processor is used (dummy processor does not support future payments).
1125
1126 // Check contribution recur record.
1127 $recur = $this->callAPISuccess('contribution_recur', 'getsingle', array('id' => $contribution['contribution_recur_id']));
1128 $this->assertEquals(date('Ymd', strtotime($recur['start_date'])), date('Ymd', strtotime("+1 month")));
1129 $this->assertEquals($recur['amount'], 100.00);
1130 $this->assertEquals($recur['contribution_status_id'], 5); // In progress status.
1131 }
1132
603577b2
E
1133 /**
1134 * Test submit pledge payment.
1135 *
1136 * - test submitting a pledge payment using contribution form.
1137 */
1138 public function testSubmitPledgePayment() {
1139 $this->testSubmitPledgePaymentPaymentProcessorRecurFuturePayment();
1140 $pledge = $this->callAPISuccess('pledge', 'getsingle', array());
1141 $params = array(
1142 'pledge_id' => $pledge['id'],
1143 );
1144 $submitParams = array(
1145 'id' => (int) $pledge['pledge_contribution_page_id'],
1146 'pledge_amount' => array(2 => 1),
1147 'billing_first_name' => 'Billy',
1148 'billing_middle_name' => 'Goat',
1149 'billing_last_name' => 'Gruff',
1150 'email' => 'billy@goat.gruff',
1151 'payment_processor_id' => 1,
1152 'credit_card_number' => '4111111111111111',
1153 'credit_card_type' => 'Visa',
1154 'credit_card_exp_date' => array('M' => 9, 'Y' => 2040),
1155 'cvv2' => 123,
1156 'pledge_id' => $pledge['id'],
1157 'cid' => $pledge['contact_id'],
1158 'contact_id' => $pledge['contact_id'],
1159 'amount' => 100.00,
1160 'is_pledge' => TRUE,
1161 'pledge_block_id' => $this->_ids['pledge_block_id'],
1162 );
1163 $pledgePayment = $this->callAPISuccess('pledge_payment', 'get', $params);
1164 $this->assertEquals($pledgePayment['values'][2]['status_id'], 2);
1165
1166 $this->callAPIAndDocument('contribution_page', 'submit', $submitParams, __FUNCTION__, __FILE__, 'submit contribution page', NULL);
1167
1168 // Check if contribution created.
1169 $contribution = $this->callAPISuccess('contribution', 'getsingle', array(
1170 'contribution_page_id' => $pledge['pledge_contribution_page_id'],
1171 'contribution_status_id' => 'Completed',
1172 'contact_id' => $pledge['contact_id'],
1173 'contribution_recur_id' => array('IS NULL' => 1),
1174 ));
1175
1176 $this->assertEquals(100.00, $contribution['total_amount']);
1177 $pledgePayment = $this->callAPISuccess('pledge_payment', 'get', $params);
1178 $this->assertEquals($pledgePayment['values'][2]['status_id'], 1, "This pledge payment should have been completed");
1179 $this->assertEquals($pledgePayment['values'][2]['contribution_id'], $contribution['id']);
1180 }
1181
6a488035 1182}