Merge pull request #8525 from twomice/CRM-18251b
[civicrm-core.git] / tests / phpunit / CRM / Member / Form / MembershipRenewalTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2017 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 * File for the MembershipTest class
30 *
31 * (PHP 5)
32 *
33 * @author Walt Haas <walt@dharmatech.org> (801) 534-1262
34 */
35
36 /**
37 * Test CRM_Member_Form_Membership functions.
38 *
39 * @package CiviCRM
40 * @group headless
41 */
42 class CRM_Member_Form_MembershipRenewalTest extends CiviUnitTestCase {
43
44 /**
45 * Assume empty database with just civicrm_data.
46 */
47 protected $_individualId;
48 protected $_contribution;
49 protected $_financialTypeId = 1;
50 protected $_apiversion;
51 protected $_entity = 'Membership';
52 protected $_params;
53 protected $_ids = array();
54 protected $_paymentProcessorID;
55
56 /**
57 * Membership type ID for annual fixed membership.
58 *
59 * @var int
60 */
61 protected $membershipTypeAnnualFixedID;
62
63 /**
64 * Parameters to create payment processor.
65 *
66 * @var array
67 */
68 protected $_processorParams = array();
69
70 /**
71 * ID of created membership.
72 *
73 * @var int
74 */
75 protected $_membershipID;
76
77 /**
78 * Payment instrument mapping.
79 *
80 * @var array
81 */
82 protected $paymentInstruments = array();
83
84 /**
85 * Test setup for every test.
86 *
87 * Connect to the database, truncate the tables that will be used
88 * and redirect stdin to a temporary file.
89 */
90 public function setUp() {
91 $this->_apiversion = 3;
92 parent::setUp();
93
94 $this->_individualId = $this->individualCreate();
95 $this->_paymentProcessorID = $this->processorCreate();
96 // Insert test data.
97 $op = new PHPUnit_Extensions_Database_Operation_Insert();
98 $op->execute($this->_dbconn,
99 $this->createFlatXMLDataSet(
100 dirname(__FILE__) . '/dataset/data.xml'
101 )
102 );
103 $membershipTypeAnnualFixed = $this->callAPISuccess('membership_type', 'create', array(
104 'domain_id' => 1,
105 'name' => "AnnualFixed",
106 'member_of_contact_id' => 23,
107 'duration_unit' => "year",
108 'duration_interval' => 1,
109 'period_type' => "fixed",
110 'fixed_period_start_day' => "101",
111 'fixed_period_rollover_day' => "1231",
112 'relationship_type_id' => 20,
113 'financial_type_id' => 2,
114 ));
115 $this->membershipTypeAnnualFixedID = $membershipTypeAnnualFixed['id'];
116 $membership = $this->callAPISuccess('Membership', 'create', array(
117 'contact_id' => $this->_individualId,
118 'membership_type_id' => $this->membershipTypeAnnualFixedID,
119 ));
120 $this->_membershipID = $membership['id'];
121
122 $instruments = $this->callAPISuccess('contribution', 'getoptions', array('field' => 'payment_instrument_id'));
123 $this->paymentInstruments = $instruments['values'];
124 }
125
126 /**
127 * Clean up after each test.
128 */
129 public function tearDown() {
130 $this->quickCleanUpFinancialEntities();
131 $this->quickCleanup(
132 array(
133 'civicrm_relationship',
134 'civicrm_membership_type',
135 'civicrm_membership',
136 'civicrm_uf_match',
137 'civicrm_address',
138 )
139 );
140 $this->callAPISuccess('contact', 'delete', array('id' => 17, 'skip_undelete' => TRUE));
141 $this->callAPISuccess('contact', 'delete', array('id' => 23, 'skip_undelete' => TRUE));
142 $this->callAPISuccess('relationship_type', 'delete', array('id' => 20));
143 }
144
145 /**
146 * Test the submit function of the membership form.
147 */
148 public function testSubmit() {
149 $form = $this->getForm();
150 $this->createLoggedInUser();
151 $params = array(
152 'cid' => $this->_individualId,
153 'join_date' => date('m/d/Y', time()),
154 'start_date' => '',
155 'end_date' => '',
156 // This format reflects the 23 being the organisation & the 25 being the type.
157 'membership_type_id' => array(23, $this->membershipTypeAnnualFixedID),
158 'auto_renew' => '0',
159 'max_related' => '',
160 'num_terms' => '1',
161 'source' => '',
162 'total_amount' => '50.00',
163 //Member dues, see data.xml
164 'financial_type_id' => '2',
165 'soft_credit_type_id' => '',
166 'soft_credit_contact_id' => '',
167 'from_email_address' => '"Demonstrators Anonymous" <info@example.org>',
168 'receipt_text_signup' => 'Thank you text',
169 'payment_processor_id' => $this->_paymentProcessorID,
170 'credit_card_number' => '4111111111111111',
171 'cvv2' => '123',
172 'credit_card_exp_date' => array(
173 'M' => '9',
174 'Y' => '2024', // TODO: Future proof
175 ),
176 'credit_card_type' => 'Visa',
177 'billing_first_name' => 'Test',
178 'billing_middlename' => 'Last',
179 'billing_street_address-5' => '10 Test St',
180 'billing_city-5' => 'Test',
181 'billing_state_province_id-5' => '1003',
182 'billing_postal_code-5' => '90210',
183 'billing_country_id-5' => '1228',
184 );
185 $form->_contactID = $this->_individualId;
186
187 $form->testSubmit($params);
188 $membership = $this->callAPISuccessGetSingle('Membership', array('contact_id' => $this->_individualId));
189 $this->callAPISuccessGetCount('ContributionRecur', array('contact_id' => $this->_individualId), 0);
190 $contribution = $this->callAPISuccess('Contribution', 'get', array(
191 'contact_id' => $this->_individualId,
192 'is_test' => TRUE,
193 ));
194
195 $this->callAPISuccessGetCount('LineItem', array(
196 'entity_id' => $membership['id'],
197 'entity_table' => 'civicrm_membership',
198 'contribution_id' => $contribution['id'],
199 ), 1);
200 $this->_checkFinancialRecords(array(
201 'id' => $contribution['id'],
202 'total_amount' => 50,
203 'financial_account_id' => 2,
204 'payment_instrument_id' => $this->callAPISuccessGetValue('PaymentProcessor', array(
205 'id' => $this->_paymentProcessorID,
206 'return' => 'payment_instrument_id',
207 )),
208 ), 'online');
209 }
210
211 /**
212 * Test the submit function of the membership form.
213 */
214 public function testSubmitRecur() {
215 $form = $this->getForm();
216
217 $this->callAPISuccess('MembershipType', 'create', array(
218 'id' => $this->membershipTypeAnnualFixedID,
219 'duration_unit' => 'month',
220 'duration_interval' => 1,
221 'auto_renew' => TRUE,
222 ));
223 $form->preProcess();
224 $this->createLoggedInUser();
225 $params = array(
226 'cid' => $this->_individualId,
227 'price_set_id' => 0,
228 'join_date' => date('m/d/Y', time()),
229 'start_date' => '',
230 'end_date' => '',
231 'campaign_id' => '',
232 // This format reflects the 23 being the organisation & the 25 being the type.
233 'membership_type_id' => array(23, $this->membershipTypeAnnualFixedID),
234 'auto_renew' => '1',
235 'is_recur' => 1,
236 'max_related' => 0,
237 'num_terms' => '1',
238 'source' => '',
239 'total_amount' => '77.00',
240 //Member dues, see data.xml
241 'financial_type_id' => '2',
242 'soft_credit_type_id' => 11,
243 'soft_credit_contact_id' => '',
244 'from_email_address' => '"Demonstrators Anonymous" <info@example.org>',
245 'receipt_text' => 'Thank you text',
246 'payment_processor_id' => $this->_paymentProcessorID,
247 'credit_card_number' => '4111111111111111',
248 'cvv2' => '123',
249 'credit_card_exp_date' => array(
250 'M' => '9',
251 'Y' => '2019', // TODO: Future proof
252 ),
253 'credit_card_type' => 'Visa',
254 'billing_first_name' => 'Test',
255 'billing_middlename' => 'Last',
256 'billing_street_address-5' => '10 Test St',
257 'billing_city-5' => 'Test',
258 'billing_state_province_id-5' => '1003',
259 'billing_postal_code-5' => '90210',
260 'billing_country_id-5' => '1228',
261 'send_receipt' => 1,
262 );
263 $form->_mode = 'test';
264 $form->_contactID = $this->_individualId;
265
266 $form->testSubmit($params);
267 $membership = $this->callAPISuccessGetSingle('Membership', array('contact_id' => $this->_individualId));
268 $contributionRecur = $this->callAPISuccessGetSingle('ContributionRecur', array('contact_id' => $this->_individualId));
269 $this->assertEquals(1, $contributionRecur['is_email_receipt']);
270 $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($contributionRecur['modified_date'])));
271 $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($contributionRecur['modified_date'])));
272 $this->assertNotEmpty($contributionRecur['invoice_id']);
273 $this->assertEquals(CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id',
274 'Pending'), $contributionRecur['contribution_status_id']);
275 $this->assertEquals($this->callAPISuccessGetValue('PaymentProcessor', array(
276 'id' => $this->_paymentProcessorID,
277 'return' => 'payment_instrument_id',
278 )), $contributionRecur['payment_instrument_id']);
279
280 $contribution = $this->callAPISuccess('Contribution', 'getsingle', array(
281 'contact_id' => $this->_individualId,
282 'is_test' => TRUE,
283 ));
284
285 $this->assertEquals($this->callAPISuccessGetValue('PaymentProcessor', array(
286 'id' => $this->_paymentProcessorID,
287 'return' => 'payment_instrument_id',
288 )), $contribution['payment_instrument_id']);
289 $this->assertEquals($contributionRecur['id'], $contribution['contribution_recur_id']);
290
291 $this->callAPISuccessGetCount('LineItem', array(
292 'entity_id' => $membership['id'],
293 'entity_table' => 'civicrm_membership',
294 'contribution_id' => $contribution['id'],
295 ), 1);
296
297 $this->callAPISuccessGetSingle('address', array(
298 'contact_id' => $this->_individualId,
299 'street_address' => '10 Test St',
300 'postal_code' => 90210,
301 ));
302 }
303
304 /**
305 * Test the submit function of the membership form.
306 */
307 public function testSubmitRecurCompleteInstant() {
308 $form = $this->getForm();
309
310 $processor = Civi\Payment\System::singleton()->getById($this->_paymentProcessorID);
311 $processor->setDoDirectPaymentResult(array(
312 'payment_status_id' => 1,
313 'trxn_id' => 'kettles boil water',
314 'fee_amount' => .29,
315 ));
316
317 $this->callAPISuccess('MembershipType', 'create', array(
318 'id' => $this->membershipTypeAnnualFixedID,
319 'duration_unit' => 'month',
320 'duration_interval' => 1,
321 'auto_renew' => TRUE,
322 ));
323 $this->createLoggedInUser();
324 $form->preProcess();
325
326 $form->_contactID = $this->_individualId;
327 $params = $this->getBaseSubmitParams();
328 $form->_mode = 'test';
329
330 $form->testSubmit($params);
331 $membership = $this->callAPISuccessGetSingle('Membership', array('contact_id' => $this->_individualId));
332 $contributionRecur = $this->callAPISuccessGetSingle('ContributionRecur', array('contact_id' => $this->_individualId));
333 $this->assertEquals($contributionRecur['id'], $membership['contribution_recur_id']);
334 $this->assertEquals(0, $contributionRecur['is_email_receipt']);
335 $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($contributionRecur['modified_date'])));
336 $this->assertNotEmpty($contributionRecur['invoice_id']);
337 // @todo fix this part!
338 /*
339 $this->assertEquals(CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id',
340 'In Progress'), $contributionRecur['contribution_status_id']);
341 $this->assertNotEmpty($contributionRecur['next_sched_contribution_date']);
342 */
343 $paymentInstrumentID = $this->callAPISuccessGetValue('PaymentProcessor', array(
344 'id' => $this->_paymentProcessorID,
345 'return' => 'payment_instrument_id',
346 ));
347 $this->assertEquals($paymentInstrumentID, $contributionRecur['payment_instrument_id']);
348
349 $contribution = $this->callAPISuccess('Contribution', 'getsingle', array(
350 'contact_id' => $this->_individualId,
351 'is_test' => TRUE,
352 ));
353 $this->assertEquals($paymentInstrumentID, $contribution['payment_instrument_id']);
354
355 $this->assertEquals('kettles boil water', $contribution['trxn_id']);
356 $this->assertEquals(.29, $contribution['fee_amount']);
357 $this->assertEquals(78, $contribution['total_amount']);
358 $this->assertEquals(77.71, $contribution['net_amount']);
359
360 $this->callAPISuccessGetCount('LineItem', array(
361 'entity_id' => $membership['id'],
362 'entity_table' => 'civicrm_membership',
363 'contribution_id' => $contribution['id'],
364 ), 1);
365
366 }
367
368 /**
369 * Test the submit function of the membership form.
370 */
371 public function testSubmitPayLater() {
372 $form = $this->getForm(NULL);
373 $this->createLoggedInUser();
374 $originalMembership = $this->callAPISuccessGetSingle('membership', array());
375 $params = array(
376 'cid' => $this->_individualId,
377 'join_date' => date('m/d/Y', time()),
378 'start_date' => '',
379 'end_date' => '',
380 // This format reflects the 23 being the organisation & the 25 being the type.
381 'membership_type_id' => array(23, $this->membershipTypeAnnualFixedID),
382 'auto_renew' => '0',
383 'max_related' => '',
384 'num_terms' => '2',
385 'source' => '',
386 'total_amount' => '50.00',
387 //Member dues, see data.xml
388 'financial_type_id' => '2',
389 'soft_credit_type_id' => '',
390 'soft_credit_contact_id' => '',
391 'payment_instrument_id' => 4,
392 'from_email_address' => '"Demonstrators Anonymous" <info@example.org>',
393 'receipt_text_signup' => 'Thank you text',
394 'payment_processor_id' => $this->_paymentProcessorID,
395 'record_contribution' => TRUE,
396 'trxn_id' => 777,
397 'contribution_status_id' => 2,
398 );
399 $form->_contactID = $this->_individualId;
400
401 $form->testSubmit($params);
402 $membership = $this->callAPISuccessGetSingle('Membership', array('contact_id' => $this->_individualId));
403 $this->assertEquals(strtotime($membership['end_date']), strtotime($originalMembership['end_date']));
404 $contribution = $this->callAPISuccessGetSingle('Contribution', array(
405 'contact_id' => $this->_individualId,
406 'contribution_status_id' => 2,
407 'return' => array("tax_amount", "trxn_id"),
408 ));
409 $this->assertEquals($contribution['trxn_id'], 777);
410 $this->assertEquals($contribution['tax_amount'], NULL);
411
412 $this->callAPISuccessGetCount('LineItem', array(
413 'entity_id' => $membership['id'],
414 'entity_table' => 'civicrm_membership',
415 'contribution_id' => $contribution['id'],
416 ), 1);
417 }
418
419 /**
420 * Test the submit function of the membership form.
421 */
422 public function testSubmitPayLaterWithBilling() {
423 $form = $this->getForm(NULL);
424 $this->createLoggedInUser();
425 $originalMembership = $this->callAPISuccessGetSingle('membership', array());
426 $params = array(
427 'cid' => $this->_individualId,
428 'join_date' => date('m/d/Y', time()),
429 'start_date' => '',
430 'end_date' => '',
431 // This format reflects the 23 being the organisation & the 25 being the type.
432 'membership_type_id' => array(23, $this->membershipTypeAnnualFixedID),
433 'auto_renew' => '0',
434 'max_related' => '',
435 'num_terms' => '2',
436 'source' => '',
437 'total_amount' => '50.00',
438 //Member dues, see data.xml
439 'financial_type_id' => '2',
440 'soft_credit_type_id' => '',
441 'soft_credit_contact_id' => '',
442 'payment_instrument_id' => 4,
443 'from_email_address' => '"Demonstrators Anonymous" <info@example.org>',
444 'receipt_text_signup' => 'Thank you text',
445 'payment_processor_id' => $this->_paymentProcessorID,
446 'record_contribution' => TRUE,
447 'trxn_id' => 777,
448 'contribution_status_id' => 2,
449 'billing_first_name' => 'Test',
450 'billing_middlename' => 'Last',
451 'billing_street_address-5' => '10 Test St',
452 'billing_city-5' => 'Test',
453 'billing_state_province_id-5' => '1003',
454 'billing_postal_code-5' => '90210',
455 'billing_country_id-5' => '1228',
456 );
457 $form->_contactID = $this->_individualId;
458
459 $form->testSubmit($params);
460 $membership = $this->callAPISuccessGetSingle('Membership', array('contact_id' => $this->_individualId));
461 $this->assertEquals(strtotime($membership['end_date']), strtotime($originalMembership['end_date']));
462 $contribution = $this->callAPISuccessGetSingle('Contribution', array(
463 'contact_id' => $this->_individualId,
464 'contribution_status_id' => 2,
465 ));
466 $this->assertEquals($contribution['trxn_id'], 777);
467
468 $this->callAPISuccessGetCount('LineItem', array(
469 'entity_id' => $membership['id'],
470 'entity_table' => 'civicrm_membership',
471 'contribution_id' => $contribution['id'],
472 ), 1);
473 $this->callAPISuccessGetSingle('address', array(
474 'contact_id' => $this->_individualId,
475 'street_address' => '10 Test St',
476 'postal_code' => 90210,
477 ));
478 }
479
480 /**
481 * Test the submit function of the membership form.
482 */
483 public function testSubmitComplete() {
484 $form = $this->getForm(NULL);
485 $this->createLoggedInUser();
486 $originalMembership = $this->callAPISuccessGetSingle('membership', array());
487 $params = array(
488 'cid' => $this->_individualId,
489 'join_date' => date('m/d/Y', time()),
490 'start_date' => '',
491 'end_date' => '',
492 // This format reflects the 23 being the organisation & the 25 being the type.
493 'membership_type_id' => array(23, $this->membershipTypeAnnualFixedID),
494 'auto_renew' => '0',
495 'max_related' => '',
496 'num_terms' => '2',
497 'source' => '',
498 'total_amount' => '50.00',
499 //Member dues, see data.xml
500 'financial_type_id' => '2',
501 'soft_credit_type_id' => '',
502 'soft_credit_contact_id' => '',
503 'payment_instrument_id' => 4,
504 'from_email_address' => '"Demonstrators Anonymous" <info@example.org>',
505 'receipt_text_signup' => 'Thank you text',
506 'payment_processor_id' => $this->_paymentProcessorID,
507 'record_contribution' => TRUE,
508 'trxn_id' => 777,
509 'contribution_status_id' => 1,
510 'fee_amount' => .5,
511 );
512 $form->_contactID = $this->_individualId;
513
514 $form->testSubmit($params);
515 $membership = $this->callAPISuccessGetSingle('Membership', array('contact_id' => $this->_individualId));
516 $this->assertEquals(strtotime($membership['end_date']), strtotime('+ 2 years',
517 strtotime($originalMembership['end_date'])));
518 $contribution = $this->callAPISuccessGetSingle('Contribution', array(
519 'contact_id' => $this->_individualId,
520 'contribution_status_id' => 1,
521 ));
522
523 $this->assertEquals($contribution['trxn_id'], 777);
524 $this->assertEquals(.5, $contribution['fee_amount']);
525 $this->callAPISuccessGetCount('LineItem', array(
526 'entity_id' => $membership['id'],
527 'entity_table' => 'civicrm_membership',
528 'contribution_id' => $contribution['id'],
529 ), 1);
530 }
531
532 /**
533 * Get a membership form object.
534 *
535 * We need to instantiate the form to run preprocess, which means we have to trick it about the request method.
536 *
537 * @param string $mode
538 *
539 * @return \CRM_Member_Form_MembershipRenewal
540 */
541 protected function getForm($mode = 'test') {
542 $form = new CRM_Member_Form_MembershipRenewal();
543 $_SERVER['REQUEST_METHOD'] = 'GET';
544 $form->controller = new CRM_Core_Controller();
545 $form->_bltID = 5;
546 $form->_mode = $mode;
547 $form->_id = $this->_membershipID;
548 $form->preProcess();
549 return $form;
550 }
551
552 /**
553 * Get some re-usable parameters for the submit function.
554 *
555 * @return array
556 */
557 protected function getBaseSubmitParams() {
558 $params = array(
559 'cid' => $this->_individualId,
560 'price_set_id' => 0,
561 'join_date' => date('m/d/Y', time()),
562 'start_date' => '',
563 'end_date' => '',
564 'campaign_id' => '',
565 // This format reflects the 23 being the organisation & the 25 being the type.
566 'membership_type_id' => array(23, $this->membershipTypeAnnualFixedID),
567 'auto_renew' => '1',
568 'is_recur' => 1,
569 'max_related' => 0,
570 'num_terms' => '1',
571 'source' => '',
572 'total_amount' => '78.00',
573 'financial_type_id' => '2', //Member dues, see data.xml
574 'soft_credit_type_id' => 11,
575 'soft_credit_contact_id' => '',
576 'from_email_address' => '"Demonstrators Anonymous" <info@example.org>',
577 'receipt_text' => 'Thank you text',
578 'payment_processor_id' => $this->_paymentProcessorID,
579 'credit_card_number' => '4111111111111111',
580 'cvv2' => '123',
581 'credit_card_exp_date' => array(
582 'M' => '9',
583 'Y' => '2019', // TODO: Future proof
584 ),
585 'credit_card_type' => 'Visa',
586 'billing_first_name' => 'Test',
587 'billing_middlename' => 'Last',
588 'billing_street_address-5' => '10 Test St',
589 'billing_city-5' => 'Test',
590 'billing_state_province_id-5' => '1003',
591 'billing_postal_code-5' => '90210',
592 'billing_country_id-5' => '1228',
593 );
594 return $params;
595 }
596
597 }