Merge pull request #16469 from civicrm/5.22
[civicrm-core.git] / tests / phpunit / api / v3 / MembershipTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * Test APIv3 civicrm_membership functions
14 *
15 * @package CiviCRM_APIv3
16 * @subpackage API_Member
17 */
18
19 /**
20 * Class api_v3_MembershipTest
21 * @group headless
22 */
23 class api_v3_MembershipTest extends CiviUnitTestCase {
24 protected $_apiversion;
25 protected $_contactID;
26 protected $_membershipID;
27 protected $_membershipID2;
28 protected $_membershipID3;
29 protected $_membershipTypeID;
30 protected $_membershipTypeID2;
31 protected $_membershipStatusID;
32 protected $_entity;
33 protected $_params;
34
35 /**
36 * Set up for tests.
37 */
38 public function setUp() {
39 parent::setUp();
40 $this->_apiversion = 3;
41 $this->_contactID = $this->individualCreate();
42 $this->_membershipTypeID = $this->membershipTypeCreate(['member_of_contact_id' => $this->_contactID]);
43 $this->_membershipTypeID2 = $this->membershipTypeCreate([
44 'period_type' => 'fixed',
45 // Ie. 1 March.
46 'fixed_period_start_day' => '301',
47 // Ie. 11 Nov.
48 'fixed_period_rollover_day' => '1111',
49 'name' => 'Another one',
50 ]);
51 $this->_membershipStatusID = $this->membershipStatusCreate('test status');
52
53 CRM_Member_PseudoConstant::membershipType(NULL, TRUE);
54 CRM_Member_PseudoConstant::membershipStatus(NULL, NULL, 'name', TRUE);
55 CRM_Core_PseudoConstant::activityType(TRUE, TRUE, TRUE, 'name');
56
57 $this->_entity = 'Membership';
58 $this->_params = [
59 'contact_id' => $this->_contactID,
60 'membership_type_id' => $this->_membershipTypeID,
61 'join_date' => '2009-01-21',
62 'start_date' => '2009-01-21',
63 'end_date' => '2009-12-21',
64 'source' => 'Payment',
65 'is_override' => 1,
66 'status_id' => $this->_membershipStatusID,
67 ];
68 }
69
70 /**
71 * Clean up after tests.
72 *
73 * @throws \Exception
74 */
75 public function tearDown() {
76 $this->quickCleanUpFinancialEntities();
77 $this->quickCleanup(['civicrm_uf_match'], TRUE);
78 $this->contactDelete($this->_contactID);
79 parent::tearDown();
80 }
81
82 /**
83 * Test membership deletion.
84 */
85 public function testMembershipDelete() {
86 $membershipID = $this->contactMembershipCreate($this->_params);
87 $this->assertDBRowExist('CRM_Member_DAO_Membership', $membershipID);
88 $params = [
89 'id' => $membershipID,
90 ];
91 $this->callAPIAndDocument('membership', 'delete', $params, __FUNCTION__, __FILE__);
92 $this->assertDBRowNotExist('CRM_Member_DAO_Membership', $membershipID);
93 }
94
95 public function testMembershipDeleteEmpty() {
96 $this->callAPIFailure('membership', 'delete', []);
97 }
98
99 public function testMembershipDeleteInvalidID() {
100 $this->callAPIFailure('membership', 'delete', ['id' => 'blah']);
101 }
102
103 /**
104 * Test membership deletion and with the preserve contribution param.
105 */
106 public function testMembershipDeletePreserveContribution() {
107 //DELETE
108 $membershipID = $this->contactMembershipCreate($this->_params);
109 //DELETE
110 $this->assertDBRowExist('CRM_Member_DAO_Membership', $membershipID);
111 $ContributionCreate = $this->callAPISuccess('Contribution', 'create', [
112 'sequential' => 1,
113 'financial_type_id' => "Member Dues",
114 'total_amount' => 100,
115 'contact_id' => $this->_params['contact_id'],
116 ]);
117 $membershipPaymentCreate = $this->callAPISuccess('MembershipPayment', 'create', [
118 'sequential' => 1,
119 'contribution_id' => $ContributionCreate['values'][0]['id'],
120 'membership_id' => $membershipID,
121 ]);
122 $memParams = [
123 'id' => $membershipID,
124 'preserve_contribution' => 1,
125 ];
126 $contribParams = [
127 'id' => $ContributionCreate['values'][0]['id'],
128 ];
129 $this->callAPIAndDocument('membership', 'delete', $memParams, __FUNCTION__, __FILE__);
130 $this->assertDBRowNotExist('CRM_Member_DAO_Membership', $membershipID);
131 $this->assertDBRowExist('CRM_Contribute_DAO_Contribution', $ContributionCreate['values'][0]['id']);
132 $this->callAPISuccess('Contribution', 'delete', $contribParams);
133 $this->assertDBRowNotExist('CRM_Contribute_DAO_Contribution', $ContributionCreate['values'][0]['id']);
134 }
135
136 /**
137 * Test Activity creation on cancellation of membership contribution.
138 */
139 public function testActivityForCancelledContribution() {
140 $contactId = $this->createLoggedInUser();
141 $membershipID = $this->contactMembershipCreate($this->_params);
142 $this->assertDBRowExist('CRM_Member_DAO_Membership', $membershipID);
143
144 $ContributionCreate = $this->callAPISuccess('Contribution', 'create', [
145 'financial_type_id' => "Member Dues",
146 'total_amount' => 100,
147 'contact_id' => $this->_params['contact_id'],
148 ]);
149 $membershipPaymentCreate = $this->callAPISuccess('MembershipPayment', 'create', [
150 'sequential' => 1,
151 'contribution_id' => $ContributionCreate['id'],
152 'membership_id' => $membershipID,
153 ]);
154 $instruments = $this->callAPISuccess('contribution', 'getoptions', ['field' => 'payment_instrument_id']);
155 $this->paymentInstruments = $instruments['values'];
156
157 $form = new CRM_Contribute_Form_Contribution();
158 $form->_id = $ContributionCreate['id'];
159 $form->testSubmit([
160 'total_amount' => 100,
161 'financial_type_id' => 1,
162 'contact_id' => $contactId,
163 'payment_instrument_id' => array_search('Check', $this->paymentInstruments),
164 'contribution_status_id' => 3,
165 ],
166 CRM_Core_Action::UPDATE);
167
168 $activity = $this->callAPISuccess('Activity', 'get', [
169 'activity_type_id' => "Change Membership Status",
170 'source_record_id' => $membershipID,
171 ]);
172 $this->assertNotEmpty($activity['values']);
173 }
174
175 /**
176 * Test membership get.
177 */
178 public function testContactMembershipsGet() {
179 $this->_membershipID = $this->contactMembershipCreate($this->_params);
180 $this->callAPISuccess('membership', 'get', []);
181 $this->callAPISuccess('Membership', 'Delete', ['id' => $this->_membershipID]);
182 }
183
184 /**
185 * Test civicrm_membership_get with params not array.
186 *
187 * Gets treated as contact_id, memberships expected.
188 */
189 public function testGetWithParamsContactId() {
190 $this->_membershipID = $this->contactMembershipCreate($this->_params);
191 $params = [
192 'contact_id' => $this->_contactID,
193 ];
194 $membership = $this->callAPISuccess('membership', 'get', $params);
195
196 $result = $membership['values'][$this->_membershipID];
197 $this->callAPISuccess('Membership', 'Delete', [
198 'id' => $this->_membershipID,
199 ]);
200 $this->assertEquals($result['contact_id'], $this->_contactID);
201 $this->assertEquals($result['membership_type_id'], $this->_membershipTypeID);
202 $this->assertEquals($result['status_id'], $this->_membershipStatusID);
203 $this->assertEquals($result['join_date'], '2009-01-21');
204 $this->assertEquals($result['start_date'], '2009-01-21');
205 $this->assertEquals($result['end_date'], '2009-12-21');
206 $this->assertEquals($result['source'], 'Payment');
207 $this->assertEquals($result['is_override'], 1);
208 }
209
210 /**
211 * Test civicrm_membership_get with params not array.
212 *
213 * Gets treated as contact_id, memberships expected.
214 */
215 public function testGetInSyntax() {
216 $this->_membershipID = $this->contactMembershipCreate($this->_params);
217 $this->_membershipID2 = $this->contactMembershipCreate($this->_params);
218 $this->_membershipID3 = $this->contactMembershipCreate($this->_params);
219 $params = [
220 'id' => ['IN' => [$this->_membershipID, $this->_membershipID3]],
221 ];
222 $membership = $this->callAPISuccess('membership', 'get', $params);
223 $this->assertEquals(2, $membership['count']);
224 $this->assertEquals([$this->_membershipID, $this->_membershipID3], array_keys($membership['values']));
225 $params = [
226 'id' => ['NOT IN' => [$this->_membershipID, $this->_membershipID3]],
227 ];
228 $membership = $this->callAPISuccess('membership', 'get', $params);
229 $this->assertEquals(1, $membership['count']);
230 $this->assertEquals([$this->_membershipID2], array_keys($membership['values']));
231 }
232
233 /**
234 * Test civicrm_membership_get with params not array.
235 * Gets treated as contact_id, memberships expected.
236 */
237 public function testGetInSyntaxOnContactID() {
238 $this->_membershipID = $this->contactMembershipCreate($this->_params);
239 $contact2 = $this->individualCreate();
240 $contact3 = $this->individualCreate(['first_name' => 'Scout', 'last_name' => 'Canine']);
241 $this->_membershipID2 = $this->contactMembershipCreate(array_merge($this->_params, ['contact_id' => $contact2]));
242 $this->_membershipID3 = $this->contactMembershipCreate(array_merge($this->_params, ['contact_id' => $contact3]));
243 $params = [
244 'contact_id' => ['IN' => [$this->_contactID, $contact3]],
245 ];
246 $membership = $this->callAPISuccess('membership', 'get', $params);
247 $this->assertEquals(2, $membership['count']);
248 $this->assertEquals([$this->_membershipID, $this->_membershipID3], array_keys($membership['values']));
249 $params = [
250 'contact_id' => ['NOT IN' => [$this->_contactID, $contact3]],
251 ];
252 $membership = $this->callAPISuccess('membership', 'get', $params);
253 $this->assertEquals(1, $membership['count']);
254 $this->assertEquals([$this->_membershipID2], array_keys($membership['values']));
255 }
256
257 /**
258 * Test civicrm_membership_get with params not array.
259 *
260 * Gets treated as contact_id, memberships expected.
261 */
262 public function testGetWithParamsMemberShipTypeId() {
263 $this->callAPISuccess($this->_entity, 'create', $this->_params);
264 $params = [
265 'membership_type_id' => $this->_membershipTypeID,
266 ];
267 $membership = $this->callAPISuccess('membership', 'get', $params);
268 $this->callAPISuccess('Membership', 'Delete', [
269 'id' => $membership['id'],
270 ]);
271 $result = $membership['values'][$membership['id']];
272 $this->assertEquals($result['contact_id'], $this->_contactID);
273 $this->assertEquals($result['membership_type_id'], $this->_membershipTypeID);
274 $this->assertEquals($result['status_id'], $this->_membershipStatusID);
275 $this->assertEquals($result['join_date'], '2009-01-21');
276 $this->assertEquals($result['start_date'], '2009-01-21');
277 $this->assertEquals($result['end_date'], '2009-12-21');
278 $this->assertEquals($result['source'], 'Payment');
279 $this->assertEquals($result['is_override'], 1);
280 $this->assertEquals($result['id'], $membership['id']);
281 }
282
283 /**
284 * Test civicrm_membership_get with params not array.
285 * Gets treated as contact_id, memberships expected.
286 */
287 public function testGetWithParamsMemberShipTypeIdContactID() {
288 $params = $this->_params;
289 $this->callAPISuccess($this->_entity, 'create', $params);
290 $params['membership_type_id'] = $this->_membershipTypeID2;
291 $this->callAPISuccess($this->_entity, 'create', $params);
292 $this->callAPISuccessGetCount('membership', ['contact_id' => $this->_contactID], 2);
293 $params = [
294 'membership_type_id' => $this->_membershipTypeID,
295 'contact_id' => $this->_contactID,
296 ];
297 $result = $this->callAPISuccess('membership', 'getsingle', $params);
298 $this->assertEquals($result['contact_id'], $this->_contactID);
299 $this->assertEquals($result['membership_type_id'], $this->_membershipTypeID);
300
301 $params = [
302 'membership_type_id' => $this->_membershipTypeID2,
303 'contact_id' => $this->_contactID,
304 ];
305 $result = $this->callAPISuccess('membership', 'getsingle', $params);
306 $this->assertEquals($result['contact_id'], $this->_contactID);
307 $this->assertEquals($result['membership_type_id'], $this->_membershipTypeID2);
308 }
309
310 /**
311 * Check with complete array + custom field.
312 *
313 * Note that the test is written on purpose without any
314 * variables specific to participant so it can be replicated into other entities
315 * and / or moved to the automated test suite
316 */
317 public function testGetWithParamsMemberShipIdAndCustom() {
318 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
319
320 $params = $this->_params;
321 $params['custom_' . $ids['custom_field_id']] = "custom string";
322
323 $result = $this->callAPISuccess($this->_entity, 'create', $params);
324
325 $getParams = ['membership_type_id' => $params['membership_type_id']];
326 $check = $this->callAPIAndDocument($this->_entity, 'get', $getParams, __FUNCTION__, __FILE__);
327 $this->assertEquals("custom string", $check['values'][$result['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
328
329 $this->callAPISuccess('Membership', 'Delete', [
330 'id' => $result['id'],
331 ]);
332 }
333
334 /**
335 * Test civicrm_membership_get with proper params.
336 * Memberships expected.
337 */
338 public function testGet() {
339 $membershipID = $this->contactMembershipCreate($this->_params);
340 $params = [
341 'contact_id' => $this->_contactID,
342 ];
343
344 $membership = $this->callAPISuccess('membership', 'get', $params);
345 $result = $membership['values'][$membershipID];
346 $this->callAPISuccess('Membership', 'Delete', [
347 'id' => $membership['id'],
348 ]);
349 $this->assertEquals($result['join_date'], '2009-01-21');
350 $this->assertEquals($result['contact_id'], $this->_contactID);
351 $this->assertEquals($result['membership_type_id'], $this->_membershipTypeID);
352 $this->assertEquals($result['status_id'], $this->_membershipStatusID);
353
354 $this->assertEquals($result['start_date'], '2009-01-21');
355 $this->assertEquals($result['end_date'], '2009-12-21');
356 $this->assertEquals($result['source'], 'Payment');
357 $this->assertEquals($result['is_override'], 1);
358 }
359
360 /**
361 * Test civicrm_membership_get with proper params.
362 * Memberships expected.
363 */
364 public function testGetWithId() {
365 $membershipID = $this->contactMembershipCreate($this->_params);
366 $params = [
367 'contact_id' => $this->_contactID,
368 'id' => $this->_membershipID,
369 'return' => 'id',
370 ];
371 $result = $this->callAPISuccess('membership', 'get', $params);
372 $this->assertEquals($membershipID, $result['id']);
373 $params = [
374 'contact_id' => $this->_contactID,
375 'membership_id' => $this->_membershipID,
376 'return' => 'membership_id',
377 ];
378 $result = $this->callAPISuccess('membership', 'get', $params);
379 $this->assertEquals($membershipID, $result['id']);
380 }
381
382 /**
383 * Test civicrm_membership_get for only active.
384 * Memberships expected.
385 */
386 public function testGetOnlyActive() {
387 $description = "Demonstrates use of 'filter' active_only' param.";
388 $this->_membershipID = $this->contactMembershipCreate($this->_params);
389 $params = [
390 'contact_id' => $this->_contactID,
391 'active_only' => 1,
392 ];
393
394 $membership = $this->callAPISuccess('membership', 'get', $params);
395 $this->assertEquals($membership['values'][$this->_membershipID]['status_id'], $this->_membershipStatusID);
396 $this->assertEquals($membership['values'][$this->_membershipID]['contact_id'], $this->_contactID);
397 $params = [
398 'contact_id' => $this->_contactID,
399 'filters' => [
400 'is_current' => 1,
401 ],
402 ];
403
404 $membership = $this->callAPIAndDocument('membership', 'get', $params, __FUNCTION__, __FILE__, $description, 'FilterIsCurrent');
405 $this->assertEquals($membership['values'][$this->_membershipID]['status_id'], $this->_membershipStatusID);
406 $this->assertEquals($membership['values'][$this->_membershipID]['contact_id'], $this->_contactID);
407
408 $this->callAPISuccess('Membership', 'Delete', ['id' => $this->_membershipID]);
409 }
410
411 /**
412 * Test civicrm_membership_get for non exist contact.
413 * empty Memberships.
414 */
415 public function testGetNoContactExists() {
416 $params = [
417 'contact_id' => 55555,
418 ];
419
420 $membership = $this->callAPISuccess('membership', 'get', $params);
421 $this->assertEquals($membership['count'], 0);
422 }
423
424 /**
425 * Test civicrm_membership_get with relationship.
426 * get Memberships.
427 *
428 * @throws \CRM_Core_Exception
429 */
430 public function testGetWithRelationship() {
431 $membershipOrgId = $this->organizationCreate(NULL);
432 $memberContactId = $this->individualCreate();
433
434 $relTypeParams = [
435 'name_a_b' => 'Relation 1',
436 'name_b_a' => 'Relation 2',
437 'description' => 'Testing relationship type',
438 'contact_type_a' => 'Organization',
439 'contact_type_b' => 'Individual',
440 'is_reserved' => 1,
441 'is_active' => 1,
442 ];
443 $relTypeID = $this->relationshipTypeCreate($relTypeParams);
444
445 $params = [
446 'name' => 'test General',
447 'duration_unit' => 'year',
448 'duration_interval' => 1,
449 'period_type' => 'rolling',
450 'member_of_contact_id' => $membershipOrgId,
451 'domain_id' => 1,
452 'financial_type_id' => 1,
453 'relationship_type_id' => $relTypeID,
454 'relationship_direction' => 'b_a',
455 'is_active' => 1,
456 ];
457 $memType = $this->callAPISuccess('membership_type', 'create', $params);
458
459 $params = [
460 'contact_id' => $memberContactId,
461 'membership_type_id' => $memType['id'],
462 'join_date' => '2009-01-21',
463 'start_date' => '2009-01-21',
464 'end_date' => '2009-12-21',
465 'source' => 'Payment',
466 'is_override' => 1,
467 'status_id' => $this->_membershipStatusID,
468 ];
469 $membershipID = $this->contactMembershipCreate($params);
470
471 $params = [
472 'contact_id' => $memberContactId,
473 'membership_type_id' => $memType['id'],
474 ];
475
476 $result = $this->callAPISuccess('membership', 'get', $params);
477
478 $membership = $result['values'][$membershipID];
479 $this->assertEquals($this->_membershipStatusID, $membership['status_id']);
480 $this->callAPISuccess('Membership', 'Delete', [
481 'id' => $membership['id'],
482 ]);
483 $this->membershipTypeDelete(['id' => $memType['id']]);
484 $this->relationshipTypeDelete($relTypeID);
485 $this->contactDelete($membershipOrgId);
486 $this->contactDelete($memberContactId);
487 }
488
489 /**
490 * Test civicrm_membership_create with relationships.
491 * create/get Memberships.
492 *
493 * Test suite for CRM-14758: API ( contact, create ) does not always create related membership
494 * and max_related property for Membership_Type and Membership entities
495 *
496 * @throws \CRM_Core_Exception
497 * @throws \CiviCRM_API3_Exception
498 */
499 public function testCreateWithRelationship() {
500 // Create membership type: inherited through employment, max_related = 2
501 $params = [
502 'name_a_b' => 'Employee of',
503 ];
504 $result = $this->callAPISuccess('relationship_type', 'get', $params);
505 $relationshipTypeId = $result['id'];
506 $membershipOrgId = $this->organizationCreate();
507 $params = [
508 'name' => 'Corporate Membership',
509 'duration_unit' => 'year',
510 'duration_interval' => 1,
511 'period_type' => 'rolling',
512 'member_of_contact_id' => $membershipOrgId,
513 'domain_id' => 1,
514 'financial_type_id' => 1,
515 'relationship_type_id' => $relationshipTypeId,
516 'relationship_direction' => 'b_a',
517 'max_related' => 2,
518 'is_active' => 1,
519 ];
520 $result = $this->callAPISuccess('membership_type', 'create', $params);
521 $membershipTypeId = $result['id'];
522
523 // Create employer and first employee
524 $employerId[0] = $this->organizationCreate([], 1);
525 $memberContactId[0] = $this->individualCreate(['employer_id' => $employerId[0]], 0);
526
527 // Create organization's membership
528 $params = [
529 'contact_id' => $employerId[0],
530 'membership_type_id' => $membershipTypeId,
531 'source' => 'Test suite',
532 'start_date' => date('Y-m-d'),
533 'end_date' => '+1 year',
534 ];
535 $OrganizationMembershipID = $this->contactMembershipCreate($params);
536
537 // Check that the employee inherited the membership
538 $params = [
539 'contact_id' => $memberContactId[0],
540 'membership_type_id' => $membershipTypeId,
541 ];
542
543 $result = $this->callAPISuccess('membership', 'get', $params);
544
545 $this->assertEquals(1, $result['count']);
546 $result = $result['values'][$result['id']];
547 $this->assertEquals($OrganizationMembershipID, $result['owner_membership_id']);
548
549 // Create second employee
550 $memberContactId[1] = $this->individualCreate(['employer_id' => $employerId[0]], 1);
551
552 // Check that the employee inherited the membership
553 $params = [
554 'contact_id' => $memberContactId[1],
555 'membership_type_id' => $membershipTypeId,
556 ];
557 $result = $this->callAPISuccess('membership', 'get', $params);
558 // If it fails here CRM-14758 is not fixed
559 $this->assertEquals(1, $result['count']);
560 $result = $result['values'][$result['id']];
561 $this->assertEquals($OrganizationMembershipID, $result['owner_membership_id']);
562
563 // Create third employee
564 $memberContactId[2] = $this->individualCreate(['employer_id' => $employerId[0]], 2);
565
566 // Check that employee does NOT inherit the membership (max_related = 2)
567 $params = [
568 'contact_id' => $memberContactId[2],
569 'membership_type_id' => $membershipTypeId,
570 ];
571 $result = $this->callAPISuccess('membership', 'get', $params);
572 $this->assertEquals(0, $result['count']);
573
574 // Increase max_related for the employer's membership
575 $params = [
576 'id' => $OrganizationMembershipID,
577 'max_related' => 3,
578 ];
579 $this->callAPISuccess('Membership', 'create', $params);
580
581 // Check that the employee inherited the membership
582 $params = [
583 'contact_id' => $memberContactId[2],
584 'membership_type_id' => $membershipTypeId,
585 ];
586 $result = $this->callAPISuccess('membership', 'get', $params);
587 $this->assertEquals(1, $result['count']);
588 $result = $result['values'][$result['id']];
589 $this->assertEquals($OrganizationMembershipID, $result['owner_membership_id']);
590
591 // First employee moves to a new job
592 $employerId[1] = $this->organizationCreate([], 2);
593 $params = [
594 'id' => $memberContactId[0],
595 'employer_id' => $employerId[1],
596 ];
597 $this->callAPISuccess('contact', 'create', $params);
598
599 // Check that employee does NO LONGER inherit the membership
600 $params = [
601 'contact_id' => $memberContactId[0],
602 'membership_type_id' => $membershipTypeId,
603 ];
604 $result = $this->callAPISuccess('membership', 'get', $params);
605 $this->assertEquals(0, $result['count']);
606
607 //Create pay_later membership for organization.
608 $employerId[2] = $this->organizationCreate([], 1);
609 $params = [
610 'contact_id' => $employerId[2],
611 'membership_type_id' => $membershipTypeId,
612 'source' => 'Test pay later suite',
613 'is_pay_later' => 1,
614 'status_id' => 5,
615 ];
616 $organizationMembershipID = $this->callAPISuccess('Membership', 'create', $params)['id'];
617
618 $memberContactId[3] = $this->individualCreate(['employer_id' => $employerId[2]], 0);
619 // Check that the employee inherited the membership
620 $params = [
621 'contact_id' => $memberContactId[3],
622 'membership_type_id' => $membershipTypeId,
623 ];
624 $result = $this->callAPISuccessGetSingle('membership', $params);
625 $this->assertEquals($organizationMembershipID, $result['owner_membership_id']);
626
627 // Set up params for enable/disable checks
628 $relationship1 = $this->callAPISuccess('relationship', 'get', ['contact_id_a' => $memberContactId[1]]);
629 $params = [
630 'contact_id' => $memberContactId[1],
631 'membership_type_id' => $membershipTypeId,
632 ];
633
634 // Deactivate relationship using create and assert membership is not inherited
635 $this->callAPISuccess('relationship', 'create', ['id' => $relationship1['id'], 'is_active' => 0]);
636 $result = $this->callAPISuccess('membership', 'get', $params);
637 $this->assertEquals(0, $result['count']);
638
639 // Re-enable relationship using create and assert membership is inherited
640 $this->callAPISuccess('relationship', 'create', ['id' => $relationship1['id'], 'is_active' => 1]);
641 $result = $this->callAPISuccess('membership', 'get', $params);
642 $this->assertEquals(1, $result['count']);
643
644 // Deactivate relationship using setvalue and assert membership is not inherited
645 $this->callAPISuccess('relationship', 'setvalue', ['id' => $relationship1['id'], 'field' => 'is_active', 'value' => 0]);
646 $result = $this->callAPISuccess('membership', 'get', $params);
647 $this->assertEquals(0, $result['count']);
648
649 // Re-enable relationship using setvalue and assert membership is inherited
650 $this->callAPISuccess('relationship', 'setvalue', ['id' => $relationship1['id'], 'field' => 'is_active', 'value' => 1]);
651 $result = $this->callAPISuccess('membership', 'get', $params);
652 $this->assertEquals(1, $result['count']);
653
654 // Delete relationship and assert membership is not inherited
655 $this->callAPISuccess('relationship', 'delete', ['id' => $relationship1['id']]);
656 $result = $this->callAPISuccess('membership', 'get', $params);
657 $this->assertEquals(0, $result['count']);
658
659 // Tear down - reverse of creation to be safe
660 $this->contactDelete($memberContactId[2]);
661 $this->contactDelete($memberContactId[1]);
662 $this->contactDelete($memberContactId[0]);
663 $this->contactDelete($employerId[1]);
664 $this->contactDelete($employerId[0]);
665 $this->membershipTypeDelete(['id' => $membershipTypeId]);
666 $this->contactDelete($membershipOrgId);
667 }
668
669 /**
670 * We are checking for no e-notices + only id & end_date returned
671 *
672 * @throws \CRM_Core_Exception
673 */
674 public function testMembershipGetWithReturn() {
675 $this->contactMembershipCreate($this->_params);
676 $result = $this->callAPISuccess('membership', 'get', ['return' => 'end_date']);
677 foreach ($result['values'] as $membership) {
678 $this->assertEquals(['id', 'end_date'], array_keys($membership));
679 }
680 }
681
682 ///////////////// civicrm_membership_create methods
683
684 /**
685 * Test civicrm_contact_memberships_create with empty params.
686 * Error expected.
687 */
688 public function testCreateWithEmptyParams() {
689 $params = [];
690 $this->callAPIFailure('membership', 'create', $params);
691 }
692
693 /**
694 * If is_overide is passed in status must also be passed in.
695 */
696 public function testCreateOverrideNoStatus() {
697 $params = $this->_params;
698 unset($params['status_id']);
699 $this->callAPIFailure('membership', 'create', $params);
700 }
701
702 public function testMembershipCreateMissingRequired() {
703 $params = [
704 'membership_type_id' => '1',
705 'join_date' => '2006-01-21',
706 'start_date' => '2006-01-21',
707 'end_date' => '2006-12-21',
708 'source' => 'Payment',
709 'status_id' => '2',
710 ];
711
712 $this->callAPIFailure('membership', 'create', $params);
713 }
714
715 public function testMembershipCreate() {
716 $params = [
717 'contact_id' => $this->_contactID,
718 'membership_type_id' => $this->_membershipTypeID,
719 'join_date' => '2006-01-21',
720 'start_date' => '2006-01-21',
721 'end_date' => '2006-12-21',
722 'source' => 'Payment',
723 'is_override' => 1,
724 'status_id' => $this->_membershipStatusID,
725 ];
726
727 $result = $this->callAPIAndDocument('membership', 'create', $params, __FUNCTION__, __FILE__);
728 $this->getAndCheck($params, $result['id'], $this->_entity);
729 $this->assertNotNull($result['id']);
730 $this->assertEquals($this->_contactID, $result['values'][$result['id']]['contact_id'], " in line " . __LINE__);
731 $this->assertEquals($result['id'], $result['values'][$result['id']]['id'], " in line " . __LINE__);
732 }
733
734 /**
735 * Check for useful message if contact doesn't exist
736 */
737 public function testMembershipCreateWithInvalidContact() {
738 $params = [
739 'contact_id' => 999,
740 'membership_type_id' => $this->_membershipTypeID,
741 'join_date' => '2006-01-21',
742 'start_date' => '2006-01-21',
743 'end_date' => '2006-12-21',
744 'source' => 'Payment',
745 'is_override' => 1,
746 'status_id' => $this->_membershipStatusID,
747 ];
748
749 $this->callAPIFailure('membership', 'create', $params,
750 'contact_id is not valid : 999'
751 );
752 }
753
754 public function testMembershipCreateWithInvalidStatus() {
755 $params = $this->_params;
756 $params['status_id'] = 999;
757 $this->callAPIFailure('membership', 'create', $params,
758 "'999' is not a valid option for field status_id"
759 );
760 }
761
762 public function testMembershipCreateWithInvalidType() {
763 $params = $this->_params;
764 $params['membership_type_id'] = 999;
765
766 $this->callAPIFailure('membership', 'create', $params,
767 "'999' is not a valid option for field membership_type_id"
768 );
769 }
770
771 /**
772 * Check with complete array + custom field
773 * Note that the test is written on purpose without any
774 * variables specific to participant so it can be replicated into other entities
775 * and / or moved to the automated test suite
776 */
777 public function testCreateWithCustom() {
778 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
779
780 $params = $this->_params;
781 $params['custom_' . $ids['custom_field_id']] = "custom string";
782
783 $result = $this->callAPIAndDocument($this->_entity, 'create', $params, __FUNCTION__, __FILE__, NULL, 'CreateWithCustomData');
784 $check = $this->callAPISuccess($this->_entity, 'get', [
785 'id' => $result['id'],
786 'contact_id' => $this->_contactID,
787 ]);
788 $this->assertEquals("custom string", $check['values'][$result['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
789 }
790
791 /**
792 * Search on custom field value.
793 */
794 public function testSearchWithCustomDataCRM16036() {
795 // Create a custom field on membership
796 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
797
798 // Create a new membership, but don't assign anything to the custom field.
799 $params = $this->_params;
800 $result = $this->callAPIAndDocument(
801 $this->_entity,
802 'create',
803 $params,
804 __FUNCTION__,
805 __FILE__,
806 NULL,
807 'SearchWithCustomData');
808
809 // search memberships with CRM-16036 as custom field value.
810 // Since we did not touch the custom field of any membership,
811 // this should not return any results.
812 $check = $this->callAPISuccess($this->_entity, 'get', [
813 'custom_' . $ids['custom_field_id'] => "CRM-16036",
814 ]);
815
816 // Cleanup.
817 $this->callAPISuccess($this->_entity, 'delete', [
818 'id' => $result['id'],
819 ]);
820
821 // Assert.
822 $this->assertEquals(0, $check['count']);
823 }
824
825 /**
826 * Test civicrm_contact_memberships_create with membership id (edit
827 * membership).
828 * success expected.
829 */
830 public function testMembershipCreateWithId() {
831 $membershipID = $this->contactMembershipCreate($this->_params);
832 $params = [
833 'id' => $membershipID,
834 'contact_id' => $this->_contactID,
835 'membership_type_id' => $this->_membershipTypeID,
836 'join_date' => '2006-01-21',
837 'start_date' => '2006-01-21',
838 'end_date' => '2006-12-21',
839 'source' => 'Payment',
840 'is_override' => 1,
841 'status_id' => $this->_membershipStatusID,
842 ];
843
844 $result = $this->callAPISuccess('membership', 'create', $params);
845
846 //Update Status and check activities created.
847 $updateStatus = [
848 'id' => $result['id'],
849 'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Member_BAO_Membership', 'status_id', 'Cancelled'),
850 ];
851 $this->callAPISuccess('Membership', 'create', $updateStatus);
852 $activities = CRM_Activity_BAO_Activity::getContactActivity($this->_contactID);
853 $this->assertEquals(2, count($activities));
854 $activityNames = array_flip(CRM_Utils_Array::collect('activity_name', $activities));
855 $this->assertArrayHasKey('Membership Signup', $activityNames);
856 $this->assertArrayHasKey('Change Membership Status', $activityNames);
857
858 $this->callAPISuccess('Membership', 'Delete', [
859 'id' => $result['id'],
860 ]);
861 $this->assertEquals($result['id'], $membershipID, "in line " . __LINE__);
862 }
863
864 /**
865 * Test civicrm_contact_memberships_create with membership id (edit
866 * membership).
867 * success expected.
868 */
869 public function testMembershipCreateUpdateWithIdNoContact() {
870 $membershipID = $this->contactMembershipCreate($this->_params);
871 $params = [
872 'id' => $membershipID,
873 'membership_type_id' => $this->_membershipTypeID,
874 'contact_id' => $this->_contactID,
875 'join_date' => '2006-01-21',
876 'start_date' => '2006-01-21',
877 'end_date' => '2006-12-21',
878 'source' => 'Payment',
879 'is_override' => 1,
880 'status_id' => $this->_membershipStatusID,
881 ];
882
883 $result = $this->callAPISuccess('membership', 'create', $params);
884 $this->callAPISuccess('Membership', 'Delete', [
885 'id' => $result['id'],
886 ]);
887
888 $this->assertEquals($result['id'], $membershipID, "in line " . __LINE__);
889 }
890
891 /**
892 * Test civicrm_contact_memberships_create with membership id (edit
893 * membership).
894 * success expected.
895 */
896 public function testMembershipCreateUpdateWithIdNoDates() {
897 $membershipID = $this->contactMembershipCreate($this->_params);
898 $params = [
899 'id' => $membershipID,
900 'contact_id' => $this->_contactID,
901 'membership_type_id' => $this->_membershipTypeID,
902 'source' => 'Payment',
903 'is_override' => 1,
904 'status_id' => $this->_membershipStatusID,
905 ];
906
907 $result = $this->callAPISuccess('membership', 'create', $params);
908 $this->callAPISuccess('Membership', 'Delete', [
909 'id' => $result['id'],
910 ]);
911 $this->assertEquals($result['id'], $membershipID, "in line " . __LINE__);
912 }
913
914 /**
915 * Test civicrm_contact_memberships_create with membership id (edit
916 * membership).
917 * success expected.
918 */
919 public function testMembershipCreateUpdateWithIdNoDatesNoType() {
920 $membershipID = $this->contactMembershipCreate($this->_params);
921 $params = [
922 'id' => $membershipID,
923 'source' => 'not much here',
924 'contact_id' => $this->_contactID,
925 'is_override' => 1,
926 'status_id' => $this->_membershipStatusID,
927 ];
928
929 $result = $this->callAPISuccess('membership', 'create', $params);
930 $this->callAPISuccess('Membership', 'Delete', [
931 'id' => $result['id'],
932 ]);
933 $this->assertEquals($result['id'], $membershipID, "in line " . __LINE__);
934 }
935
936 /**
937 * Test civicrm_contact_memberships_create with membership id (edit
938 * membership).
939 * success expected.
940 */
941 public function testMembershipCreateUpdateWithIDAndSource() {
942 $membershipID = $this->contactMembershipCreate($this->_params);
943 $params = [
944 'id' => $membershipID,
945 'source' => 'changed',
946 'contact_id' => $this->_contactID,
947 'status_id' => $this->_membershipStatusID,
948 'membership_type_id' => $this->_membershipTypeID,
949 'skipStatusCal' => 1,
950 ];
951 $result = $this->callAPISuccess('membership', 'create', $params);
952 $this->assertEquals($result['id'], $membershipID, "in line " . __LINE__);
953 $this->callAPISuccess('Membership', 'Delete', [
954 'id' => $result['id'],
955 ]);
956 }
957
958 /**
959 * Change custom field using update.
960 */
961 public function testUpdateWithCustom() {
962 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
963
964 $params = $this->_params;
965 $params['custom_' . $ids['custom_field_id']] = "custom string";
966 $result = $this->callAPIAndDocument($this->_entity, 'create', $params, __FUNCTION__, __FILE__, NULL, 'UpdateCustomData');
967 $result = $this->callAPISuccess($this->_entity, 'create', [
968 'id' => $result['id'],
969 'custom_' . $ids['custom_field_id'] => "new custom",
970 ]);
971 $check = $this->callAPISuccess($this->_entity, 'get', [
972 'id' => $result['id'],
973 'contact_id' => $this->_contactID,
974 ]);
975
976 $this->assertEquals("new custom", $check['values'][$result['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__);
977 $this->callAPISuccess('Membership', 'Delete', [
978 'id' => $check['id'],
979 ]);
980
981 $this->customFieldDelete($ids['custom_field_id']);
982 $this->customGroupDelete($ids['custom_group_id']);
983 }
984
985 /**
986 * per CRM-15746 check that the id can be altered in an update hook
987 */
988 public function testMembershipUpdateCreateHookCRM15746() {
989 $this->hookClass->setHook('civicrm_pre', [$this, 'hook_civicrm_pre_update_create_membership']);
990 $result = $this->callAPISuccess('membership', 'create', $this->_params);
991 $this->callAPISuccess('membership', 'create', ['id' => $result['id'], 'end_date' => '1 year ago']);
992 $this->callAPISuccessGetCount('membership', [], 2);
993 $this->hookClass->reset();
994 $this->callAPISuccess('membership', 'create', ['id' => $result['id'], 'end_date' => '1 year ago']);
995 $this->callAPISuccessGetCount('membership', [], 2);
996 }
997
998 /**
999 * Custom hook for update membership.
1000 *
1001 * @param string $op
1002 * @param object $objectName
1003 * @param int $id
1004 * @param array $params
1005 *
1006 * @throws \Exception
1007 */
1008 public function hook_civicrm_pre_update_create_membership($op, $objectName, $id, &$params) {
1009 if ($objectName == 'Membership' && $op == 'edit') {
1010 $existingMembership = $this->callAPISuccessGetSingle('membership', ['id' => $params['id']]);
1011 unset($params['id'], $params['membership_id']);
1012 $params['join_date'] = $params['membership_start_date'] = $params['start_date'] = date('Ymd000000', strtotime($existingMembership['start_date']));
1013 $params = array_merge($existingMembership, $params);
1014 $params['id'] = NULL;
1015 }
1016 }
1017
1018 /**
1019 * Test civicrm_contact_memberships_create Invalid membership data.
1020 * Error expected.
1021 */
1022 public function testMembershipCreateInvalidMemData() {
1023 //membership_contact_id as string
1024 $params = [
1025 'membership_contact_id' => 'Invalid',
1026 'membership_type_id' => $this->_membershipTypeID,
1027 'join_date' => '2011-01-21',
1028 'start_date' => '2010-01-21',
1029 'end_date' => '2008-12-21',
1030 'source' => 'Payment',
1031 'is_override' => 1,
1032 'status_id' => $this->_membershipStatusID,
1033 ];
1034
1035 $this->callAPIFailure('membership', 'create', $params);
1036
1037 //membership_contact_id which is no in contact table
1038 $params['membership_contact_id'] = 999;
1039 $this->callAPIFailure('membership', 'create', $params);
1040
1041 //invalid join date
1042 unset($params['membership_contact_id']);
1043 $params['join_date'] = "invalid";
1044 $this->callAPIFailure('Membership', 'Create', $params);
1045 }
1046
1047 /**
1048 * Test civicrm_contact_memberships_create with membership_contact_id
1049 * membership).
1050 * Success expected.
1051 */
1052 public function testMembershipCreateWithMemContact() {
1053 $params = [
1054 'membership_contact_id' => $this->_contactID,
1055 'membership_type_id' => $this->_membershipTypeID,
1056 'join_date' => '2011-01-21',
1057 'start_date' => '2010-01-21',
1058 'end_date' => '2008-12-21',
1059 'source' => 'Payment',
1060 'is_override' => 1,
1061 'status_id' => $this->_membershipStatusID,
1062 ];
1063
1064 $result = $this->callAPISuccess('membership', 'create', $params);
1065
1066 $this->callAPISuccess('Membership', 'Delete', [
1067 'id' => $result['id'],
1068 ]);
1069 }
1070
1071 /**
1072 * Test civicrm_contact_memberships_create with membership_contact_id
1073 * membership).
1074 * Success expected.
1075 */
1076 public function testMembershipCreateValidMembershipTypeString() {
1077 $params = [
1078 'membership_contact_id' => $this->_contactID,
1079 'membership_type_id' => 'General',
1080 'join_date' => '2011-01-21',
1081 'start_date' => '2010-01-21',
1082 'end_date' => '2008-12-21',
1083 'source' => 'Payment',
1084 'is_override' => 1,
1085 'status_id' => $this->_membershipStatusID,
1086 ];
1087
1088 $result = $this->callAPISuccess('membership', 'create', $params);
1089 $this->assertEquals($this->_membershipTypeID, $result['values'][$result['id']]['membership_type_id']);
1090 $this->callAPISuccess('Membership', 'Delete', [
1091 'id' => $result['id'],
1092 ]);
1093 }
1094
1095 /**
1096 * Test civicrm_contact_memberships_create with membership_contact_id
1097 * membership).
1098 * Success expected.
1099 */
1100 public function testMembershipCreateInValidMembershipTypeString() {
1101 $params = [
1102 'membership_contact_id' => $this->_contactID,
1103 'membership_type_id' => 'invalid',
1104 'join_date' => '2011-01-21',
1105 'start_date' => '2010-01-21',
1106 'end_date' => '2008-12-21',
1107 'source' => 'Payment',
1108 'is_override' => 1,
1109 'status_id' => $this->_membershipStatusID,
1110 ];
1111
1112 $this->callAPIFailure('membership', 'create', $params);
1113 }
1114
1115 /**
1116 * Test that if membership join date is not set it defaults to today.
1117 */
1118 public function testEmptyJoinDate() {
1119 unset($this->_params['join_date'], $this->_params['is_override']);
1120 $result = $this->callAPISuccess($this->_entity, 'create', $this->_params);
1121 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1122 $this->assertEquals(date('Y-m-d', strtotime('now')), $result['join_date']);
1123 $this->assertEquals('2009-01-21', $result['start_date']);
1124 $this->assertEquals('2009-12-21', $result['end_date']);
1125 }
1126
1127 /**
1128 * Test that if membership start date is not set it defaults to correct end date.
1129 * - fixed
1130 */
1131 public function testEmptyStartDateFixed() {
1132 unset($this->_params['start_date'], $this->_params['is_override']);
1133 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1134 $result = $this->callAPISuccess($this->_entity, 'create', $this->_params);
1135 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1136 $this->assertEquals('2009-01-21', $result['join_date']);
1137 $this->assertEquals('2008-03-01', $result['start_date']);
1138 $this->assertEquals('2009-12-21', $result['end_date']);
1139 }
1140
1141 /**
1142 * Test that if membership start date is not set it defaults to correct end date
1143 * - fixed
1144 */
1145 public function testEmptyStartEndDateFixedOneYear() {
1146 unset($this->_params['start_date'], $this->_params['is_override'], $this->_params['end_date']);
1147 $this->callAPISuccess('membership_type', 'create', ['id' => $this->_membershipTypeID2, 'duration_interval' => 1]);
1148 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1149 $result = $this->callAPISuccess($this->_entity, 'create', $this->_params);
1150 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1151 $this->assertEquals('2009-01-21', $result['join_date']);
1152 $this->assertEquals('2008-03-01', $result['start_date']);
1153 $this->assertEquals('2010-02-28', $result['end_date']);
1154 }
1155
1156 /**
1157 * Test that if membership start date is not set it defaults to correct end date for fixed multi year memberships.
1158 */
1159 public function testEmptyStartEndDateFixedMultiYear() {
1160 unset($this->_params['start_date'], $this->_params['is_override'], $this->_params['end_date']);
1161 $this->callAPISuccess('membership_type', 'create', ['id' => $this->_membershipTypeID2, 'duration_interval' => 5]);
1162 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1163 $result = $this->callAPISuccess($this->_entity, 'create', $this->_params);
1164 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1165 $this->assertEquals('2009-01-21', $result['join_date']);
1166 $this->assertEquals('2008-03-01', $result['start_date']);
1167 $this->assertEquals('2014-02-28', $result['end_date']);
1168 }
1169
1170 /**
1171 * CRM-18503 - Test membership join date is correctly set for fixed memberships.
1172 */
1173 public function testMembershipJoinDateFixed() {
1174 $memStatus = CRM_Member_PseudoConstant::membershipStatus();
1175 // Update the fixed membership type to 1 year duration.
1176 $this->callAPISuccess('membership_type', 'create', ['id' => $this->_membershipTypeID2, 'duration_interval' => 1]);
1177 $contactId = $this->createLoggedInUser();
1178 // Create membership with 'Pending' status.
1179 $params = [
1180 'contact_id' => $contactId,
1181 'membership_type_id' => $this->_membershipTypeID2,
1182 'source' => 'test membership',
1183 'is_pay_later' => 0,
1184 'status_id' => array_search('Pending', $memStatus),
1185 'skipStatusCal' => 1,
1186 'is_for_organization' => 1,
1187 ];
1188 // @todo stop passing empty $ids
1189 $ids = [];
1190 $membership = CRM_Member_BAO_Membership::create($params, $ids);
1191
1192 // Update membership to 'Completed' and check the dates.
1193 $memParams = [
1194 'id' => $membership->id,
1195 'contact_id' => $contactId,
1196 'is_test' => 0,
1197 'membership_type_id' => $this->_membershipTypeID2,
1198 'num_terms' => 1,
1199 'status_id' => array_search('New', $memStatus),
1200 ];
1201 $result = $this->callAPISuccess('Membership', 'create', $memParams);
1202
1203 // Extend duration interval if join_date exceeds the rollover period.
1204 $joinDate = date('Y-m-d');
1205 $year = date('Y');
1206 $startDate = date('Y-m-d', strtotime(date('Y-03-01')));
1207 $rollOver = TRUE;
1208 if (strtotime($startDate) > time()) {
1209 $rollOver = FALSE;
1210 $startDate = date('Y-m-d', strtotime(date('Y-03-01') . '- 1 year'));
1211 }
1212 $membershipTypeDetails = CRM_Member_BAO_MembershipType::getMembershipTypeDetails($this->_membershipTypeID2);
1213 $fixedPeriodRollover = CRM_Member_BAO_MembershipType::isDuringFixedAnnualRolloverPeriod($joinDate, $membershipTypeDetails, $year, $startDate);
1214 $y = 1;
1215 if ($fixedPeriodRollover && $rollOver) {
1216 $y += 1;
1217 }
1218
1219 $expectedDates = [
1220 'join_date' => date('Ymd'),
1221 'start_date' => str_replace('-', '', $startDate),
1222 'end_date' => date('Ymd', strtotime(date('Y-03-01') . "+ {$y} year - 1 day")),
1223 ];
1224 foreach ($result['values'] as $values) {
1225 foreach ($expectedDates as $date => $val) {
1226 $this->assertEquals($val, $values[$date], "Failed asserting {$date} values");
1227 }
1228 }
1229 }
1230
1231 /**
1232 * Test correct end and start dates are calculated for fixed multi year memberships.
1233 *
1234 * The empty start date is calculated to be the start_date (1 Jan prior to the join_date - so 1 Jan 15)
1235 *
1236 * In this set our start date is after the start day and before the rollover day so we don't get an extra year
1237 * and we end one day before the rollover day. Start day is 1 Jan so we end on 31 Dec
1238 * and we add on 4 years rather than 5 because we are not after the rollover day - so we calculate 31 Dec 2019
1239 */
1240 public function testFixedMultiYearDateSetTwoEmptyStartEndDate() {
1241 unset($this->_params['start_date'], $this->_params['is_override'], $this->_params['end_date']);
1242
1243 $this->callAPISuccess('membership_type', 'create', [
1244 'id' => $this->_membershipTypeID2,
1245 'duration_interval' => 5,
1246 // Ie 1 Jan.
1247 'fixed_period_start_day' => '101',
1248 // Ie. 1 Nov.
1249 'fixed_period_rollover_day' => '1101',
1250 ]);
1251 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1252 $dates = [
1253 'join_date' => '28-Jan 2015',
1254 ];
1255 $result = $this->callAPISuccess($this->_entity, 'create', array_merge($this->_params, $dates));
1256 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1257 $this->assertEquals('2015-01-28', $result['join_date']);
1258 $this->assertEquals('2015-01-01', $result['start_date']);
1259 $this->assertEquals('2019-12-31', $result['end_date']);
1260 }
1261
1262 /**
1263 * Test that correct end date is calculated for fixed multi year memberships and start date is not changed.
1264 *
1265 * In this set our start date is after the start day and before the rollover day so we don't get an extra year
1266 * and we end one day before the rollover day. Start day is 1 Jan so we end on 31 Dec
1267 * and we add on 4 years rather than 5 because we are not after the rollover day - so we calculate 31 Dec 2019
1268 */
1269 public function testFixedMultiYearDateSetTwoEmptyEndDate() {
1270 unset($this->_params['start_date'], $this->_params['is_override'], $this->_params['end_date']);
1271
1272 $this->callAPISuccess('membership_type', 'create', [
1273 'id' => $this->_membershipTypeID2,
1274 'duration_interval' => 5,
1275 // Ie 1 Jan.
1276 'fixed_period_start_day' => '101',
1277 // Ie. 1 Nov.
1278 'fixed_period_rollover_day' => '1101',
1279 ]);
1280 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1281 $dates = [
1282 'start_date' => '28-Jan 2015',
1283 'join_date' => '28-Jan 2015',
1284 ];
1285 $result = $this->callAPISuccess($this->_entity, 'create', array_merge($this->_params, $dates));
1286 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1287 $this->assertEquals('2015-01-28', $result['join_date']);
1288 $this->assertEquals('2015-01-28', $result['start_date']);
1289 $this->assertEquals('2019-12-31', $result['end_date']);
1290 }
1291
1292 /**
1293 * Test correct end and start dates are calculated for fixed multi year memberships.
1294 *
1295 * The empty start date is calculated to be the start_date (1 Jan prior to the join_date - so 1 Jan 15)
1296 *
1297 * In this set our start date is after the start day and before the rollover day so we don't get an extra year
1298 * and we end one day before the rollover day. Start day is 1 Jan so we end on 31 Dec
1299 * and we add on <1 years rather than > 1 because we are not after the rollover day - so we calculate 31 Dec 2015
1300 */
1301 public function testFixedSingleYearDateSetTwoEmptyStartEndDate() {
1302 unset($this->_params['start_date'], $this->_params['is_override'], $this->_params['end_date']);
1303
1304 $this->callAPISuccess('membership_type', 'create', [
1305 'id' => $this->_membershipTypeID2,
1306 'duration_interval' => 1,
1307 // Ie 1 Jan.
1308 'fixed_period_start_day' => '101',
1309 // Ie. 1 Nov.
1310 'fixed_period_rollover_day' => '1101',
1311 ]);
1312 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1313 $dates = [
1314 'join_date' => '28-Jan 2015',
1315 ];
1316 $result = $this->callAPISuccess($this->_entity, 'create', array_merge($this->_params, $dates));
1317 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1318 $this->assertEquals('2015-01-28', $result['join_date']);
1319 $this->assertEquals('2015-01-01', $result['start_date']);
1320 $this->assertEquals('2015-12-31', $result['end_date']);
1321 }
1322
1323 /**
1324 * Test correct end date for fixed single year memberships is calculated and start_date is not changed.
1325 *
1326 * In this set our start date is after the start day and before the rollover day so we don't get an extra year
1327 * and we end one day before the rollover day. Start day is 1 Jan so we end on 31 Dec
1328 * and we add on <1 years rather than > 1 because we are not after the rollover day - so we calculate 31 Dec 2015
1329 */
1330 public function testFixedSingleYearDateSetTwoEmptyEndDate() {
1331 unset($this->_params['start_date'], $this->_params['is_override'], $this->_params['end_date']);
1332
1333 $this->callAPISuccess('membership_type', 'create', [
1334 'id' => $this->_membershipTypeID2,
1335 'duration_interval' => 1,
1336 // Ie 1 Jan.
1337 'fixed_period_start_day' => '101',
1338 // Ie. 1 Nov.
1339 'fixed_period_rollover_day' => '1101',
1340 ]);
1341 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1342 $dates = [
1343 'start_date' => '28-Jan 2015',
1344 'join_date' => '28-Jan 2015',
1345 ];
1346 $result = $this->callAPISuccess($this->_entity, 'create', array_merge($this->_params, $dates));
1347 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1348 $this->assertEquals('2015-01-28', $result['join_date']);
1349 $this->assertEquals('2015-01-28', $result['start_date']);
1350 $this->assertEquals('2015-12-31', $result['end_date']);
1351 }
1352
1353 /**
1354 * Test that correct end date is calculated for fixed multi year memberships and start date is not changed.
1355 *
1356 * In this set our start date is after the start day and after the rollover day so we do get an extra year
1357 * and we end one day before the rollover day. Start day is 1 Nov so we end on 31 Oct
1358 * and we add on 1 year we are after the rollover day - so we calculate 31 Oct 2016
1359 */
1360 public function testFixedSingleYearDateSetThreeEmptyEndDate() {
1361 unset($this->_params['start_date'], $this->_params['is_override'], $this->_params['end_date']);
1362
1363 $this->callAPISuccess('membership_type', 'create', [
1364 'id' => $this->_membershipTypeID2,
1365 'duration_interval' => 1,
1366 // Ie. 1 Nov.
1367 'fixed_period_start_day' => '1101',
1368 // Ie 1 Jan.
1369 'fixed_period_rollover_day' => '101',
1370 ]);
1371 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1372 $dates = [
1373 'start_date' => '28-Jan 2015',
1374 'join_date' => '28-Jan 2015',
1375 ];
1376 $result = $this->callAPISuccess($this->_entity, 'create', array_merge($this->_params, $dates));
1377 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1378 $this->assertEquals('2015-01-28', $result['join_date']);
1379 $this->assertEquals('2015-01-28', $result['start_date']);
1380 $this->assertEquals('2016-10-31', $result['end_date']);
1381 }
1382
1383 /**
1384 * Test correct end and start dates are calculated for fixed multi year memberships.
1385 *
1386 * The empty start date is calculated to be the start_date (1 Nov prior to the join_date - so 1 Nov 14)
1387 *
1388 * In this set our start date is after the start day and after the rollover day so we do get an extra year
1389 * and we end one day before the rollover day. Start day is 1 Nov so we end on 31 Oct
1390 * and we add on 1 year we are after the rollover day - so we calculate 31 Oct 2016
1391 */
1392 public function testFixedSingleYearDateSetThreeEmptyStartEndDate() {
1393 unset($this->_params['start_date'], $this->_params['is_override'], $this->_params['end_date']);
1394
1395 $this->callAPISuccess('membership_type', 'create', [
1396 'id' => $this->_membershipTypeID2,
1397 'duration_interval' => 1,
1398 // Ie. 1 Nov.
1399 'fixed_period_start_day' => '1101',
1400 // Ie 1 Jan.
1401 'fixed_period_rollover_day' => '101',
1402 ]);
1403 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1404 $dates = [
1405 'join_date' => '28-Jan 2015',
1406 ];
1407 $result = $this->callAPISuccess($this->_entity, 'create', array_merge($this->_params, $dates));
1408 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1409 $this->assertEquals('2015-01-28', $result['join_date']);
1410 $this->assertEquals('2014-11-01', $result['start_date']);
1411 $this->assertEquals('2016-10-31', $result['end_date']);
1412 }
1413
1414 /**
1415 * Test that correct end date is calculated for fixed multi year memberships and start date is not changed.
1416 *
1417 * In this set our start date is after the start day and after the rollover day so we do get an extra year
1418 * and we end one day before the rollover day. Start day is 1 Nov so we end on 31 Oct
1419 * and we add on 5 years we are after the rollover day - so we calculate 31 Oct 2020
1420 */
1421 public function testFixedMultiYearDateSetThreeEmptyEndDate() {
1422 unset($this->_params['start_date'], $this->_params['is_override'], $this->_params['end_date']);
1423
1424 $this->callAPISuccess('membership_type', 'create', [
1425 'id' => $this->_membershipTypeID2,
1426 'duration_interval' => 5,
1427 // Ie. 1 Nov.
1428 'fixed_period_start_day' => '1101',
1429 // Ie 1 Jan.
1430 'fixed_period_rollover_day' => '101',
1431 ]);
1432 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1433 $dates = [
1434 'start_date' => '28-Jan 2015',
1435 'join_date' => '28-Jan 2015',
1436 ];
1437 $result = $this->callAPISuccess($this->_entity, 'create', array_merge($this->_params, $dates));
1438 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1439 $this->assertEquals('2015-01-28', $result['join_date']);
1440 $this->assertEquals('2015-01-28', $result['start_date']);
1441 $this->assertEquals('2020-10-31', $result['end_date']);
1442 }
1443
1444 /**
1445 * Test correct end and start dates are calculated for fixed multi year memberships.
1446 *
1447 * The empty start date is calculated to be the start_date (1 Nov prior to the join_date - so 1 Nov 14)
1448 *
1449 * The empty start date is calculated to be the start_date (1 Nov prior to the join_date - so 1 Nov 14)
1450 * In this set our join date is after the start day and after the rollover day so we do get an extra year
1451 * and we end one day before the rollover day. Start day is 1 Nov so we end on 31 Oct
1452 * and we add on 5 years we are after the rollover day - so we calculate 31 Oct 2020
1453 */
1454 public function testFixedMultiYearDateSetThreeEmptyStartEndDate() {
1455 unset($this->_params['start_date'], $this->_params['is_override'], $this->_params['end_date']);
1456
1457 $this->callAPISuccess('membership_type', 'create', [
1458 'id' => $this->_membershipTypeID2,
1459 'duration_interval' => 5,
1460 // Ie. 1 Nov.
1461 'fixed_period_start_day' => '1101',
1462 // Ie 1 Jan.
1463 'fixed_period_rollover_day' => '101',
1464 ]);
1465 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1466 $dates = [
1467 'join_date' => '28-Jan 2015',
1468 ];
1469 $result = $this->callAPISuccess($this->_entity, 'create', array_merge($this->_params, $dates));
1470 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1471 $this->assertEquals('2015-01-28', $result['join_date']);
1472 $this->assertEquals('2014-11-01', $result['start_date']);
1473 $this->assertEquals('2020-10-31', $result['end_date']);
1474 }
1475
1476 /**
1477 * Test that if membership start date is not set it defaults to correct end date for fixed single year memberships.
1478 */
1479 public function testEmptyStartDateRolling() {
1480 unset($this->_params['start_date'], $this->_params['is_override']);
1481 $result = $this->callAPISuccess($this->_entity, 'create', $this->_params);
1482 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1483 $this->assertEquals('2009-01-21', $result['join_date']);
1484 $this->assertEquals('2009-01-21', $result['start_date']);
1485 $this->assertEquals('2009-12-21', $result['end_date']);
1486 }
1487
1488 /**
1489 * Test that if membership end date is not set it defaults to correct end date.
1490 * - rolling
1491 */
1492 public function testEmptyEndDateFixed() {
1493 unset($this->_params['start_date'], $this->_params['is_override'], $this->_params['end_date']);
1494 $this->_params['membership_type_id'] = $this->_membershipTypeID2;
1495 $result = $this->callAPISuccess($this->_entity, 'create', $this->_params);
1496 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1497 $this->assertEquals('2009-01-21', $result['join_date']);
1498 $this->assertEquals('2008-03-01', $result['start_date']);
1499 $this->assertEquals('2010-02-28', $result['end_date']);
1500 }
1501
1502 /**
1503 * Test that if membership end date is not set it defaults to correct end date.
1504 * - rolling
1505 */
1506 public function testEmptyEndDateRolling() {
1507 unset($this->_params['is_override'], $this->_params['end_date']);
1508 $this->_params['membership_type_id'] = $this->_membershipTypeID;
1509 $result = $this->callAPISuccess($this->_entity, 'create', $this->_params);
1510 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1511 $this->assertEquals('2009-01-21', $result['join_date']);
1512 $this->assertEquals('2009-01-21', $result['start_date']);
1513 $this->assertEquals('2010-01-20', $result['end_date']);
1514 }
1515
1516 /**
1517 * Test that if dates are set they not over-ridden if id is passed in
1518 */
1519 public function testMembershipDatesNotOverridden() {
1520 $result = $this->callAPISuccess($this->_entity, 'create', $this->_params);
1521 unset($this->_params['end_date'], $this->_params['start_date']);
1522 $this->_params['id'] = $result['id'];
1523 $this->callAPISuccess($this->_entity, 'create', $this->_params);
1524 $result = $this->callAPISuccess($this->_entity, 'getsingle', ['id' => $result['id']]);
1525 $this->assertEquals('2009-01-21', $result['join_date']);
1526 $this->assertEquals('2009-01-21', $result['start_date']);
1527 $this->assertEquals('2009-12-21', $result['end_date']);
1528
1529 }
1530
1531 /**
1532 * Test that all membership types are returned when getoptions is called.
1533 *
1534 * This test locks in current behaviour where types for all domains are returned. It should possibly be domain
1535 * specific but that should only be done in conjunction with adding a hook to allow that to be altered as the
1536 * multisite use case expects the master domain to be able to see all sites.
1537 *
1538 * See CRM-17075.
1539 */
1540 public function testGetOptionsMembershipTypeID() {
1541 $options = $this->callAPISuccess('Membership', 'getoptions', ['field' => 'membership_type_id']);
1542 $this->assertEquals('Another one', array_pop($options['values']));
1543 $this->assertEquals('General', array_pop($options['values']));
1544 $this->assertEquals(NULL, array_pop($options['values']));
1545 }
1546
1547 }