3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
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 +--------------------------------------------------------------------+
12 use Civi\Api4\MembershipType
;
13 use Civi\Api4\Relationship
;
14 use Civi\Api4\RelationshipType
;
17 * Test APIv3 civicrm_membership functions
19 * @package CiviCRM_APIv3
20 * @subpackage API_Member
24 * Class api_v3_MembershipTest
27 class api_v3_MembershipTest
extends CiviUnitTestCase
{
29 use CRMTraits_Financial_OrderTrait
;
31 protected $_contactID;
32 protected $_membershipID;
33 protected $_membershipID2;
34 protected $_membershipID3;
35 protected $_membershipTypeID;
36 protected $_membershipTypeID2;
37 protected $_membershipStatusID;
44 public function setUp() {
46 $this->_contactID
= $this->individualCreate();
47 $this->_membershipTypeID
= $this->membershipTypeCreate(['member_of_contact_id' => $this->_contactID
]);
48 $this->_membershipTypeID2
= $this->membershipTypeCreate([
49 'period_type' => 'fixed',
51 'fixed_period_start_day' => '301',
53 'fixed_period_rollover_day' => '1111',
54 'name' => 'Another one',
56 $this->_membershipStatusID
= $this->membershipStatusCreate('test status');
58 CRM_Member_PseudoConstant
::membershipStatus(NULL, NULL, 'name', TRUE);
59 CRM_Core_PseudoConstant
::activityType(TRUE, TRUE, TRUE, 'name');
61 $this->_entity
= 'Membership';
63 'contact_id' => $this->_contactID
,
64 'membership_type_id' => $this->_membershipTypeID
,
65 'join_date' => '2009-01-21',
66 'start_date' => '2009-01-21',
67 'end_date' => '2009-12-21',
68 'source' => 'Payment',
70 'status_id' => $this->_membershipStatusID
,
75 * Clean up after tests.
79 public function tearDown() {
80 $this->quickCleanUpFinancialEntities();
81 $this->quickCleanup(['civicrm_uf_match'], TRUE);
82 $this->contactDelete($this->_contactID
);
87 * Test membership deletion.
89 public function testMembershipDelete() {
90 $membershipID = $this->contactMembershipCreate($this->_params
);
91 $this->assertDBRowExist('CRM_Member_DAO_Membership', $membershipID);
93 'id' => $membershipID,
95 $this->callAPIAndDocument('membership', 'delete', $params, __FUNCTION__
, __FILE__
);
96 $this->assertDBRowNotExist('CRM_Member_DAO_Membership', $membershipID);
99 public function testMembershipDeleteEmpty() {
100 $this->callAPIFailure('membership', 'delete', []);
103 public function testMembershipDeleteInvalidID() {
104 $this->callAPIFailure('membership', 'delete', ['id' => 'blah']);
108 * Test membership deletion and with the preserve contribution param.
110 public function testMembershipDeletePreserveContribution() {
112 $membershipID = $this->contactMembershipCreate($this->_params
);
114 $this->assertDBRowExist('CRM_Member_DAO_Membership', $membershipID);
115 $ContributionCreate = $this->callAPISuccess('Contribution', 'create', [
117 'financial_type_id' => "Member Dues",
118 'total_amount' => 100,
119 'contact_id' => $this->_params
['contact_id'],
121 $this->callAPISuccess('MembershipPayment', 'create', [
123 'contribution_id' => $ContributionCreate['values'][0]['id'],
124 'membership_id' => $membershipID,
127 'id' => $membershipID,
128 'preserve_contribution' => 1,
131 'id' => $ContributionCreate['values'][0]['id'],
133 $this->callAPIAndDocument('membership', 'delete', $memParams, __FUNCTION__
, __FILE__
);
134 $this->assertDBRowNotExist('CRM_Member_DAO_Membership', $membershipID);
135 $this->assertDBRowExist('CRM_Contribute_DAO_Contribution', $ContributionCreate['values'][0]['id']);
136 $this->callAPISuccess('Contribution', 'delete', $contribParams);
137 $this->assertDBRowNotExist('CRM_Contribute_DAO_Contribution', $ContributionCreate['values'][0]['id']);
141 * Test Activity creation on cancellation of membership contribution.
143 public function testActivityForCancelledContribution() {
144 $contactId = $this->createLoggedInUser();
145 $membershipID = $this->contactMembershipCreate($this->_params
);
147 $ContributionCreate = $this->callAPISuccess('Contribution', 'create', [
148 'financial_type_id' => 'Member Dues',
149 'total_amount' => 100,
150 'contact_id' => $this->_params
['contact_id'],
152 $this->callAPISuccess('MembershipPayment', 'create', [
154 'contribution_id' => $ContributionCreate['id'],
155 'membership_id' => $membershipID,
158 $form = new CRM_Contribute_Form_Contribution();
159 $form->_id
= $ContributionCreate['id'];
161 'total_amount' => 100,
162 'financial_type_id' => 1,
163 'contact_id' => $contactId,
164 'payment_instrument_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
165 'contribution_status_id' => 3,
167 CRM_Core_Action
::UPDATE
);
169 $this->callAPISuccessGetSingle('Activity', [
170 'activity_type_id' => 'Membership Signup',
171 'source_record_id' => $membershipID,
172 'subject' => 'General - Payment - Status: test status',
174 $this->callAPISuccessGetSingle('Activity', [
175 'activity_type_id' => 'Change Membership Status',
176 'source_record_id' => $membershipID,
181 * Test Multiple Membership Status for same contribution id.
183 public function testMultipleMembershipsContribution() {
185 $memStatus = CRM_Member_PseudoConstant
::membershipStatus();
186 // Pending Membership Status
187 $pendingMembershipId = array_search('Pending', $memStatus);
188 // New Membership Status
189 $newMembershipId = array_search('test status', $memStatus);
192 'membership_type_id' => $this->_membershipTypeID
,
193 'source' => 'Webform Payment',
194 'status_id' => $pendingMembershipId,
196 'skipStatusCal' => 1,
200 $contactId1 = $this->individualCreate();
201 $membershipParam['contact_id'] = $contactId1;
202 $membershipID1 = $this->contactMembershipCreate($membershipParam);
204 // Pending Payment Status
205 $ContributionCreate = $this->callAPISuccess('Contribution', 'create', [
206 'financial_type_id' => '1',
207 'total_amount' => 100,
208 'contact_id' => $contactId1,
209 'payment_instrument_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
210 'contribution_status_id' => 2,
212 'receive_date' => date('Ymd'),
214 $this->callAPISuccess('MembershipPayment', 'create', [
216 'contribution_id' => $ContributionCreate['id'],
217 'membership_id' => $membershipID1,
221 $contactId2 = $this->individualCreate();
222 $membershipParam['contact_id'] = $contactId2;
223 $membershipID2 = $this->contactMembershipCreate($membershipParam);
224 $this->callAPISuccess('MembershipPayment', 'create', [
226 'contribution_id' => $ContributionCreate['id'],
227 'membership_id' => $membershipID2,
231 $contactId3 = $this->individualCreate();
232 $membershipParam['contact_id'] = $contactId3;
233 $membershipID3 = $this->contactMembershipCreate($membershipParam);
234 $this->callAPISuccess('MembershipPayment', 'create', [
236 'contribution_id' => $ContributionCreate['id'],
237 'membership_id' => $membershipID3,
240 // Change Payment Status to Completed
241 $form = new CRM_Contribute_Form_Contribution();
242 $form->_id
= $ContributionCreate['id'];
243 $params = ['id' => $ContributionCreate['id']];
245 CRM_Contribute_BAO_Contribution
::getValues($params, $values, $ids);
246 $form->_values
= $values;
248 'total_amount' => 100,
249 'financial_type_id' => '1',
250 'contact_id' => $contactId1,
251 'payment_instrument_id' => CRM_Core_PseudoConstant
::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
252 'contribution_status_id' => 1,
254 CRM_Core_Action
::UPDATE
);
256 // check for Membership 1
257 $params = ['id' => $membershipID1];
258 $membership1 = $this->callAPISuccess('membership', 'get', $params);
259 $result1 = $membership1['values'][$membershipID1];
260 $this->assertEquals($result1['contact_id'], $contactId1);
261 $this->assertEquals($result1['status_id'], $newMembershipId);
263 // check for Membership 2
264 $params = ['id' => $membershipID2];
265 $membership2 = $this->callAPISuccess('membership', 'get', $params);
266 $result2 = $membership2['values'][$membershipID2];
267 $this->assertEquals($result2['contact_id'], $contactId2);
268 $this->assertEquals($result2['status_id'], $newMembershipId);
270 // check for Membership 3
271 $params = ['id' => $membershipID3];
272 $membership3 = $this->callAPISuccess('membership', 'get', $params);
273 $result3 = $membership3['values'][$membershipID3];
274 $this->assertEquals($result3['contact_id'], $contactId3);
275 $this->assertEquals($result3['status_id'], $newMembershipId);
279 * Test membership get.
281 public function testContactMembershipsGet() {
282 $this->_membershipID
= $this->contactMembershipCreate($this->_params
);
283 $this->callAPISuccess('membership', 'get', []);
284 $this->callAPISuccess('Membership', 'Delete', ['id' => $this->_membershipID
]);
288 * Test civicrm_membership_get with params not array.
290 * Gets treated as contact_id, memberships expected.
292 public function testGetWithParamsContactId() {
293 $this->_membershipID
= $this->contactMembershipCreate($this->_params
);
295 'contact_id' => $this->_contactID
,
297 $membership = $this->callAPISuccess('membership', 'get', $params);
299 $result = $membership['values'][$this->_membershipID
];
300 $this->callAPISuccess('Membership', 'Delete', [
301 'id' => $this->_membershipID
,
303 $this->assertEquals($result['contact_id'], $this->_contactID
);
304 $this->assertEquals($result['membership_type_id'], $this->_membershipTypeID
);
305 $this->assertEquals($result['status_id'], $this->_membershipStatusID
);
306 $this->assertEquals($result['join_date'], '2009-01-21');
307 $this->assertEquals($result['start_date'], '2009-01-21');
308 $this->assertEquals($result['end_date'], '2009-12-21');
309 $this->assertEquals($result['source'], 'Payment');
310 $this->assertEquals($result['is_override'], 1);
314 * Test civicrm_membership_get with params not array.
316 * Gets treated as contact_id, memberships expected.
318 public function testGetInSyntax() {
319 $this->_membershipID
= $this->contactMembershipCreate($this->_params
);
320 $this->_membershipID2
= $this->contactMembershipCreate($this->_params
);
321 $this->_membershipID3
= $this->contactMembershipCreate($this->_params
);
323 'id' => ['IN' => [$this->_membershipID
, $this->_membershipID3
]],
325 $membership = $this->callAPISuccess('membership', 'get', $params);
326 $this->assertEquals(2, $membership['count']);
327 $this->assertEquals([$this->_membershipID
, $this->_membershipID3
], array_keys($membership['values']));
329 'id' => ['NOT IN' => [$this->_membershipID
, $this->_membershipID3
]],
331 $membership = $this->callAPISuccess('membership', 'get', $params);
332 $this->assertEquals(1, $membership['count']);
333 $this->assertEquals([$this->_membershipID2
], array_keys($membership['values']));
337 * Test civicrm_membership_get with params not array.
338 * Gets treated as contact_id, memberships expected.
340 public function testGetInSyntaxOnContactID() {
341 $this->_membershipID
= $this->contactMembershipCreate($this->_params
);
342 $contact2 = $this->individualCreate();
343 $contact3 = $this->individualCreate(['first_name' => 'Scout', 'last_name' => 'Canine']);
344 $this->_membershipID2
= $this->contactMembershipCreate(array_merge($this->_params
, ['contact_id' => $contact2]));
345 $this->_membershipID3
= $this->contactMembershipCreate(array_merge($this->_params
, ['contact_id' => $contact3]));
347 'contact_id' => ['IN' => [$this->_contactID
, $contact3]],
349 $membership = $this->callAPISuccess('membership', 'get', $params);
350 $this->assertEquals(2, $membership['count']);
351 $this->assertEquals([$this->_membershipID
, $this->_membershipID3
], array_keys($membership['values']));
353 'contact_id' => ['NOT IN' => [$this->_contactID
, $contact3]],
355 $membership = $this->callAPISuccess('membership', 'get', $params);
356 $this->assertEquals(1, $membership['count']);
357 $this->assertEquals([$this->_membershipID2
], array_keys($membership['values']));
361 * Test civicrm_membership_get with params not array.
363 * Gets treated as contact_id, memberships expected.
365 public function testGetWithParamsMemberShipTypeId() {
366 $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
368 'membership_type_id' => $this->_membershipTypeID
,
370 $membership = $this->callAPISuccess('membership', 'get', $params);
371 $this->callAPISuccess('Membership', 'Delete', [
372 'id' => $membership['id'],
374 $result = $membership['values'][$membership['id']];
375 $this->assertEquals($result['contact_id'], $this->_contactID
);
376 $this->assertEquals($result['membership_type_id'], $this->_membershipTypeID
);
377 $this->assertEquals($result['status_id'], $this->_membershipStatusID
);
378 $this->assertEquals($result['join_date'], '2009-01-21');
379 $this->assertEquals($result['start_date'], '2009-01-21');
380 $this->assertEquals($result['end_date'], '2009-12-21');
381 $this->assertEquals($result['source'], 'Payment');
382 $this->assertEquals($result['is_override'], 1);
383 $this->assertEquals($result['id'], $membership['id']);
387 * Test civicrm_membership_get with params not array.
388 * Gets treated as contact_id, memberships expected.
390 public function testGetWithParamsMemberShipTypeIdContactID() {
391 $params = $this->_params
;
392 $this->callAPISuccess($this->_entity
, 'create', $params);
393 $params['membership_type_id'] = $this->_membershipTypeID2
;
394 $this->callAPISuccess($this->_entity
, 'create', $params);
395 $this->callAPISuccessGetCount('membership', ['contact_id' => $this->_contactID
], 2);
397 'membership_type_id' => $this->_membershipTypeID
,
398 'contact_id' => $this->_contactID
,
400 $result = $this->callAPISuccess('membership', 'getsingle', $params);
401 $this->assertEquals($result['contact_id'], $this->_contactID
);
402 $this->assertEquals($result['membership_type_id'], $this->_membershipTypeID
);
405 'membership_type_id' => $this->_membershipTypeID2
,
406 'contact_id' => $this->_contactID
,
408 $result = $this->callAPISuccess('membership', 'getsingle', $params);
409 $this->assertEquals($result['contact_id'], $this->_contactID
);
410 $this->assertEquals($result['membership_type_id'], $this->_membershipTypeID2
);
414 * Check with complete array + custom field.
416 * Note that the test is written on purpose without any
417 * variables specific to participant so it can be replicated into other entities
418 * and / or moved to the automated test suite
420 public function testGetWithParamsMemberShipIdAndCustom() {
421 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
423 $params = $this->_params
;
424 $params['custom_' . $ids['custom_field_id']] = "custom string";
426 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
428 $getParams = ['membership_type_id' => $params['membership_type_id']];
429 $check = $this->callAPIAndDocument($this->_entity
, 'get', $getParams, __FUNCTION__
, __FILE__
);
430 $this->assertEquals("custom string", $check['values'][$result['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__
);
432 $this->callAPISuccess('Membership', 'Delete', [
433 'id' => $result['id'],
438 * Test civicrm_membership_get with proper params.
439 * Memberships expected.
441 public function testGet() {
442 $membershipID = $this->contactMembershipCreate($this->_params
);
444 'contact_id' => $this->_contactID
,
447 $membership = $this->callAPISuccess('membership', 'get', $params);
448 $result = $membership['values'][$membershipID];
449 $this->callAPISuccess('Membership', 'Delete', [
450 'id' => $membership['id'],
452 $this->assertEquals($result['join_date'], '2009-01-21');
453 $this->assertEquals($result['contact_id'], $this->_contactID
);
454 $this->assertEquals($result['membership_type_id'], $this->_membershipTypeID
);
455 $this->assertEquals($result['status_id'], $this->_membershipStatusID
);
457 $this->assertEquals($result['start_date'], '2009-01-21');
458 $this->assertEquals($result['end_date'], '2009-12-21');
459 $this->assertEquals($result['source'], 'Payment');
460 $this->assertEquals($result['is_override'], 1);
464 * Test civicrm_membership_get with proper params.
465 * Memberships expected.
467 public function testGetWithId() {
468 $membershipID = $this->contactMembershipCreate($this->_params
);
470 'contact_id' => $this->_contactID
,
471 'id' => $this->_membershipID
,
474 $result = $this->callAPISuccess('membership', 'get', $params);
475 $this->assertEquals($membershipID, $result['id']);
477 'contact_id' => $this->_contactID
,
478 'membership_id' => $this->_membershipID
,
479 'return' => 'membership_id',
481 $result = $this->callAPISuccess('membership', 'get', $params);
482 $this->assertEquals($membershipID, $result['id']);
486 * Test civicrm_membership_get for only active.
487 * Memberships expected.
489 public function testGetOnlyActive() {
490 $description = "Demonstrates use of 'filter' active_only' param.";
491 $this->_membershipID
= $this->contactMembershipCreate($this->_params
);
493 'contact_id' => $this->_contactID
,
497 $membership = $this->callAPISuccess('membership', 'get', $params);
498 $this->assertEquals($membership['values'][$this->_membershipID
]['status_id'], $this->_membershipStatusID
);
499 $this->assertEquals($membership['values'][$this->_membershipID
]['contact_id'], $this->_contactID
);
501 'contact_id' => $this->_contactID
,
507 $membership = $this->callAPIAndDocument('membership', 'get', $params, __FUNCTION__
, __FILE__
, $description, 'FilterIsCurrent');
508 $this->assertEquals($membership['values'][$this->_membershipID
]['status_id'], $this->_membershipStatusID
);
509 $this->assertEquals($membership['values'][$this->_membershipID
]['contact_id'], $this->_contactID
);
511 $this->callAPISuccess('Membership', 'Delete', ['id' => $this->_membershipID
]);
515 * Test civicrm_membership_get for non exist contact.
518 public function testGetNoContactExists() {
520 'contact_id' => 55555,
523 $membership = $this->callAPISuccess('membership', 'get', $params);
524 $this->assertEquals($membership['count'], 0);
528 * Test civicrm_membership_get with relationship.
531 * @throws \CRM_Core_Exception
533 public function testGetWithRelationship() {
534 $membershipOrgId = $this->organizationCreate(NULL);
535 $memberContactId = $this->individualCreate();
538 'name_a_b' => 'Relation 1',
539 'name_b_a' => 'Relation 2',
540 'description' => 'Testing relationship type',
541 'contact_type_a' => 'Organization',
542 'contact_type_b' => 'Individual',
546 $relTypeID = $this->relationshipTypeCreate($relTypeParams);
549 'name' => 'test General',
550 'duration_unit' => 'year',
551 'duration_interval' => 1,
552 'period_type' => 'rolling',
553 'member_of_contact_id' => $membershipOrgId,
555 'financial_type_id' => 1,
556 'relationship_type_id' => $relTypeID,
557 'relationship_direction' => 'b_a',
560 $memType = $this->callAPISuccess('membership_type', 'create', $params);
563 'contact_id' => $memberContactId,
564 'membership_type_id' => $memType['id'],
565 'join_date' => '2009-01-21',
566 'start_date' => '2009-01-21',
567 'end_date' => '2009-12-21',
568 'source' => 'Payment',
570 'status_id' => $this->_membershipStatusID
,
572 $membershipID = $this->contactMembershipCreate($params);
575 'contact_id' => $memberContactId,
576 'membership_type_id' => $memType['id'],
579 $result = $this->callAPISuccess('membership', 'get', $params);
581 $membership = $result['values'][$membershipID];
582 $this->assertEquals($this->_membershipStatusID
, $membership['status_id']);
583 $this->callAPISuccess('Membership', 'Delete', [
584 'id' => $membership['id'],
586 $this->membershipTypeDelete(['id' => $memType['id']]);
587 $this->relationshipTypeDelete($relTypeID);
588 $this->contactDelete($membershipOrgId);
589 $this->contactDelete($memberContactId);
593 * Test civicrm_membership_create with relationships.
594 * create/get Memberships.
596 * Test suite for CRM-14758: API ( contact, create ) does not always create related membership
597 * and max_related property for Membership_Type and Membership entities
599 * @throws \CRM_Core_Exception
601 public function testCreateWithRelationship() {
602 // Create membership type: inherited through employment, max_related = 2
604 'name_a_b' => 'Employee of',
606 $result = $this->callAPISuccess('relationship_type', 'get', $params);
607 $relationshipTypeId = $result['id'];
608 $membershipOrgId = $this->organizationCreate();
610 'name' => 'Corporate Membership',
611 'duration_unit' => 'year',
612 'duration_interval' => 1,
613 'period_type' => 'rolling',
614 'member_of_contact_id' => $membershipOrgId,
616 'financial_type_id' => 1,
617 'relationship_type_id' => $relationshipTypeId,
618 'relationship_direction' => 'b_a',
622 $result = $this->callAPISuccess('membership_type', 'create', $params);
623 $membershipTypeId = $result['id'];
625 // Create employer and first employee
626 $employerId[0] = $this->organizationCreate([], 1);
627 $memberContactId[0] = $this->individualCreate(['employer_id' => $employerId[0]], 0);
629 // Create organization's membership
631 'contact_id' => $employerId[0],
632 'membership_type_id' => $membershipTypeId,
633 'source' => 'Test suite',
634 'start_date' => date('Y-m-d'),
635 'end_date' => '+1 year',
637 $OrganizationMembershipID = $this->contactMembershipCreate($params);
639 // Check that the employee inherited the membership
641 'contact_id' => $memberContactId[0],
642 'membership_type_id' => $membershipTypeId,
645 $result = $this->callAPISuccess('membership', 'get', $params);
647 $this->assertEquals(1, $result['count']);
648 $result = $result['values'][$result['id']];
649 $this->assertEquals($OrganizationMembershipID, $result['owner_membership_id']);
651 // Create second employee
652 $memberContactId[1] = $this->individualCreate(['employer_id' => $employerId[0]], 1);
654 // Check that the employee inherited the membership
656 'contact_id' => $memberContactId[1],
657 'membership_type_id' => $membershipTypeId,
659 $result = $this->callAPISuccess('membership', 'get', $params);
660 // If it fails here CRM-14758 is not fixed
661 $this->assertEquals(1, $result['count']);
662 $result = $result['values'][$result['id']];
663 $this->assertEquals($OrganizationMembershipID, $result['owner_membership_id']);
665 // Create third employee
666 $memberContactId[2] = $this->individualCreate(['employer_id' => $employerId[0]], 2);
668 // Check that employee does NOT inherit the membership (max_related = 2)
670 'contact_id' => $memberContactId[2],
671 'membership_type_id' => $membershipTypeId,
673 $result = $this->callAPISuccess('membership', 'get', $params);
674 $this->assertEquals(0, $result['count']);
676 // Increase max_related for the employer's membership
678 'id' => $OrganizationMembershipID,
681 $this->callAPISuccess('Membership', 'create', $params);
683 // Check that the employee inherited the membership
685 'contact_id' => $memberContactId[2],
686 'membership_type_id' => $membershipTypeId,
688 $result = $this->callAPISuccess('membership', 'get', $params);
689 $this->assertEquals(1, $result['count']);
690 $result = $result['values'][$result['id']];
691 $this->assertEquals($OrganizationMembershipID, $result['owner_membership_id']);
693 // First employee moves to a new job
694 $employerId[1] = $this->organizationCreate([], 2);
696 'id' => $memberContactId[0],
697 'employer_id' => $employerId[1],
699 $this->callAPISuccess('contact', 'create', $params);
701 // Check that employee does NO LONGER inherit the membership
703 'contact_id' => $memberContactId[0],
704 'membership_type_id' => $membershipTypeId,
706 $result = $this->callAPISuccess('membership', 'get', $params);
707 $this->assertEquals(0, $result['count']);
709 //Create pay_later membership for organization.
710 $employerId[2] = $this->organizationCreate([], 1);
712 'contact_id' => $employerId[2],
713 'membership_type_id' => $membershipTypeId,
714 'source' => 'Test pay later suite',
718 $organizationMembershipID = $this->callAPISuccess('Membership', 'create', $params)['id'];
720 $memberContactId[3] = $this->individualCreate(['employer_id' => $employerId[2]], 0);
721 // Check that the employee inherited the membership
723 'contact_id' => $memberContactId[3],
724 'membership_type_id' => $membershipTypeId,
726 $result = $this->callAPISuccessGetSingle('membership', $params);
727 $this->assertEquals($organizationMembershipID, $result['owner_membership_id']);
729 // Set up params for enable/disable checks
730 $relationship1 = $this->callAPISuccess('relationship', 'get', ['contact_id_a' => $memberContactId[1]]);
732 'contact_id' => $memberContactId[1],
733 'membership_type_id' => $membershipTypeId,
736 // Deactivate relationship using create and assert membership is not inherited
737 $this->callAPISuccess('relationship', 'create', ['id' => $relationship1['id'], 'is_active' => 0]);
738 $result = $this->callAPISuccess('membership', 'get', $params);
739 $this->assertEquals(0, $result['count']);
741 // Re-enable relationship using create and assert membership is inherited
742 $this->callAPISuccess('relationship', 'create', ['id' => $relationship1['id'], 'is_active' => 1]);
743 $result = $this->callAPISuccess('membership', 'get', $params);
744 $this->assertEquals(1, $result['count']);
746 // Deactivate relationship using setvalue and assert membership is not inherited
747 $this->callAPISuccess('relationship', 'setvalue', ['id' => $relationship1['id'], 'field' => 'is_active', 'value' => 0]);
748 $result = $this->callAPISuccess('membership', 'get', $params);
749 $this->assertEquals(0, $result['count']);
751 // Re-enable relationship using setvalue and assert membership is inherited
752 $this->callAPISuccess('relationship', 'setvalue', ['id' => $relationship1['id'], 'field' => 'is_active', 'value' => 1]);
753 $result = $this->callAPISuccess('membership', 'get', $params);
754 $this->assertEquals(1, $result['count']);
756 // Delete relationship and assert membership is not inherited
757 $this->callAPISuccess('relationship', 'delete', ['id' => $relationship1['id']]);
758 $result = $this->callAPISuccess('membership', 'get', $params);
759 $this->assertEquals(0, $result['count']);
761 // Tear down - reverse of creation to be safe
762 $this->contactDelete($memberContactId[2]);
763 $this->contactDelete($memberContactId[1]);
764 $this->contactDelete($memberContactId[0]);
765 $this->contactDelete($employerId[1]);
766 $this->contactDelete($employerId[0]);
767 $this->membershipTypeDelete(['id' => $membershipTypeId]);
768 $this->contactDelete($membershipOrgId);
772 * Test that loops are not created when adding spouse relationships.
774 * This add a test for https://issues.civicrm.org/jira/browse/CRM-4213 in the hope of removing
775 * the buggy fix for that without a resurgence.
777 * @throws \API_Exception
778 * @throws \CRM_Core_Exception
779 * @throws \Civi\API\Exception\UnauthorizedException
781 public function testCreateWithSpouseRelationship() {
782 $relationshipTypeID = RelationshipType
::get()->addSelect('id')->addWhere('name_a_b', '=', 'Spouse of')->execute()->first()['id'];
783 MembershipType
::update()->setValues([
784 'relationship_direction' => ['b_a', 'a_b'],
785 'relationship_type_id' => [$relationshipTypeID, $relationshipTypeID],
787 ->addWhere('name', '=', 'General')
788 ->execute()->first()['id'];
790 $spouse1ID = $this->individualCreate(['first_name' => 'him']);
791 $spouse2ID = $this->individualCreate(['first_name' => 'her']);
792 $spouse3ID = $this->individualCreate(['first_name' => 'they']);
793 $spouse4ID = $this->individualCreate(['first_name' => 'them']);
794 Relationship
::create()->setValues([
795 'contact_id_a' => $spouse1ID,
796 'contact_id_b' => $spouse2ID,
797 'relationship_type_id' => $relationshipTypeID,
800 $this->contactMembershipCreate([
801 'contact_id' => $spouse1ID,
802 'start_date' => date('Y-m-d'),
803 'end_date' => '+1 year',
806 $this->callAPISuccessGetSingle('Membership', [
807 'contact_id' => $spouse2ID,
808 'membership_type_id' => 'General',
811 $this->callAPISuccessGetSingle('Membership', [
812 'contact_id' => $spouse1ID,
813 'membership_type_id' => 'General',
815 // Add another Spouse
816 Relationship
::create()->setValues([
817 'contact_id_a' => $spouse3ID,
818 'contact_id_b' => $spouse1ID,
819 'relationship_type_id' => $relationshipTypeID,
821 $this->callAPISuccessGetSingle('Membership', [
822 'contact_id' => $spouse3ID,
823 'membership_type_id' => 'General',
825 $this->callAPISuccessGetCount('Membership', [], 3);
826 Relationship
::create()->setValues([
827 'contact_id_a' => $spouse1ID,
828 'contact_id_b' => $spouse4ID,
829 'relationship_type_id' => $relationshipTypeID,
832 $this->callAPISuccessGetSingle('Membership', [
833 'contact_id' => $spouse4ID,
834 'membership_type_id' => 'General',
837 $this->callAPISuccessGetCount('Membership', [], 4);
841 * We are checking for no e-notices + only id & end_date returned
843 * @throws \CRM_Core_Exception
845 public function testMembershipGetWithReturn() {
846 $this->contactMembershipCreate($this->_params
);
847 $result = $this->callAPISuccess('membership', 'get', ['return' => 'end_date']);
848 foreach ($result['values'] as $membership) {
849 $this->assertEquals(['id', 'end_date'], array_keys($membership));
853 ///////////////// civicrm_membership_create methods
856 * Test civicrm_contact_memberships_create with empty params.
859 public function testCreateWithEmptyParams() {
861 $this->callAPIFailure('membership', 'create', $params);
865 * If is_overide is passed in status must also be passed in.
867 public function testCreateOverrideNoStatus() {
868 $params = $this->_params
;
869 unset($params['status_id']);
870 $this->callAPIFailure('membership', 'create', $params);
873 public function testMembershipCreateMissingRequired() {
875 'membership_type_id' => '1',
876 'join_date' => '2006-01-21',
877 'start_date' => '2006-01-21',
878 'end_date' => '2006-12-21',
879 'source' => 'Payment',
883 $this->callAPIFailure('membership', 'create', $params);
886 public function testMembershipCreate() {
888 'contact_id' => $this->_contactID
,
889 'membership_type_id' => $this->_membershipTypeID
,
890 'join_date' => '2006-01-21',
891 'start_date' => '2006-01-21',
892 'end_date' => '2006-12-21',
893 'source' => 'Payment',
895 'status_id' => $this->_membershipStatusID
,
898 $result = $this->callAPIAndDocument('membership', 'create', $params, __FUNCTION__
, __FILE__
);
899 $this->getAndCheck($params, $result['id'], $this->_entity
);
900 $this->assertNotNull($result['id']);
901 $this->assertEquals($this->_contactID
, $result['values'][$result['id']]['contact_id'], " in line " . __LINE__
);
902 $this->assertEquals($result['id'], $result['values'][$result['id']]['id'], " in line " . __LINE__
);
906 * Check for useful message if contact doesn't exist
908 public function testMembershipCreateWithInvalidContact() {
911 'membership_type_id' => $this->_membershipTypeID
,
912 'join_date' => '2006-01-21',
913 'start_date' => '2006-01-21',
914 'end_date' => '2006-12-21',
915 'source' => 'Payment',
917 'status_id' => $this->_membershipStatusID
,
920 $this->callAPIFailure('membership', 'create', $params,
921 'contact_id is not valid : 999'
925 public function testMembershipCreateWithInvalidStatus() {
926 $params = $this->_params
;
927 $params['status_id'] = 999;
928 $this->callAPIFailure('membership', 'create', $params,
929 "'999' is not a valid option for field status_id"
933 public function testMembershipCreateWithInvalidType() {
934 $params = $this->_params
;
935 $params['membership_type_id'] = 999;
937 $this->callAPIFailure('membership', 'create', $params,
938 "'999' is not a valid option for field membership_type_id"
943 * Check with complete array + custom field
944 * Note that the test is written on purpose without any
945 * variables specific to participant so it can be replicated into other entities
946 * and / or moved to the automated test suite
948 public function testCreateWithCustom() {
949 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
951 $params = $this->_params
;
952 $params['custom_' . $ids['custom_field_id']] = "custom string";
954 $result = $this->callAPIAndDocument($this->_entity
, 'create', $params, __FUNCTION__
, __FILE__
, NULL, 'CreateWithCustomData');
955 $check = $this->callAPISuccess($this->_entity
, 'get', [
956 'id' => $result['id'],
957 'contact_id' => $this->_contactID
,
959 $this->assertEquals("custom string", $check['values'][$result['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__
);
963 * Search on custom field value.
965 public function testSearchWithCustomDataCRM16036() {
966 // Create a custom field on membership
967 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
969 // Create a new membership, but don't assign anything to the custom field.
970 $params = $this->_params
;
971 $result = $this->callAPIAndDocument(
978 'SearchWithCustomData');
980 // search memberships with CRM-16036 as custom field value.
981 // Since we did not touch the custom field of any membership,
982 // this should not return any results.
983 $check = $this->callAPISuccess($this->_entity
, 'get', [
984 'custom_' . $ids['custom_field_id'] => "CRM-16036",
988 $this->callAPISuccess($this->_entity
, 'delete', [
989 'id' => $result['id'],
993 $this->assertEquals(0, $check['count']);
997 * Test civicrm_contact_memberships_create with membership id (edit
1001 public function testMembershipCreateWithId() {
1002 $membershipID = $this->contactMembershipCreate($this->_params
);
1004 'id' => $membershipID,
1005 'contact_id' => $this->_contactID
,
1006 'membership_type_id' => $this->_membershipTypeID
,
1007 'join_date' => '2006-01-21',
1008 'start_date' => '2006-01-21',
1009 'end_date' => '2006-12-21',
1010 'source' => 'Payment',
1012 'status_id' => $this->_membershipStatusID
,
1015 $result = $this->callAPISuccess('membership', 'create', $params);
1017 //Update Status and check activities created.
1019 'id' => $result['id'],
1020 'status_id' => CRM_Core_PseudoConstant
::getKey('CRM_Member_BAO_Membership', 'status_id', 'Cancelled'),
1022 $this->callAPISuccess('Membership', 'create', $updateStatus);
1023 $activities = CRM_Activity_BAO_Activity
::getContactActivity($this->_contactID
);
1024 $this->assertEquals(2, count($activities));
1025 $activityNames = array_flip(CRM_Utils_Array
::collect('activity_name', $activities));
1026 $this->assertArrayHasKey('Membership Signup', $activityNames);
1027 $this->assertArrayHasKey('Change Membership Status', $activityNames);
1029 $this->callAPISuccess('Membership', 'Delete', [
1030 'id' => $result['id'],
1032 $this->assertEquals($result['id'], $membershipID, "in line " . __LINE__
);
1036 * Test civicrm_contact_memberships_create with membership id (edit
1040 public function testMembershipCreateUpdateWithIdNoContact() {
1041 $membershipID = $this->contactMembershipCreate($this->_params
);
1043 'id' => $membershipID,
1044 'membership_type_id' => $this->_membershipTypeID
,
1045 'contact_id' => $this->_contactID
,
1046 'join_date' => '2006-01-21',
1047 'start_date' => '2006-01-21',
1048 'end_date' => '2006-12-21',
1049 'source' => 'Payment',
1051 'status_id' => $this->_membershipStatusID
,
1054 $result = $this->callAPISuccess('membership', 'create', $params);
1055 $this->callAPISuccess('Membership', 'Delete', [
1056 'id' => $result['id'],
1059 $this->assertEquals($result['id'], $membershipID, "in line " . __LINE__
);
1063 * Test civicrm_contact_memberships_create with membership id (edit
1067 public function testMembershipCreateUpdateWithIdNoDates() {
1068 $membershipID = $this->contactMembershipCreate($this->_params
);
1070 'id' => $membershipID,
1071 'contact_id' => $this->_contactID
,
1072 'membership_type_id' => $this->_membershipTypeID
,
1073 'source' => 'Payment',
1075 'status_id' => $this->_membershipStatusID
,
1078 $result = $this->callAPISuccess('membership', 'create', $params);
1079 $this->callAPISuccess('Membership', 'Delete', [
1080 'id' => $result['id'],
1082 $this->assertEquals($result['id'], $membershipID, "in line " . __LINE__
);
1086 * Test civicrm_contact_memberships_create with membership id (edit
1090 public function testMembershipCreateUpdateWithIdNoDatesNoType() {
1091 $membershipID = $this->contactMembershipCreate($this->_params
);
1093 'id' => $membershipID,
1094 'source' => 'not much here',
1095 'contact_id' => $this->_contactID
,
1097 'status_id' => $this->_membershipStatusID
,
1100 $result = $this->callAPISuccess('membership', 'create', $params);
1101 $this->callAPISuccess('Membership', 'Delete', [
1102 'id' => $result['id'],
1104 $this->assertEquals($result['id'], $membershipID, "in line " . __LINE__
);
1108 * Test civicrm_contact_memberships_create with membership id (edit
1112 public function testMembershipCreateUpdateWithIDAndSource() {
1113 $membershipID = $this->contactMembershipCreate($this->_params
);
1115 'id' => $membershipID,
1116 'source' => 'changed',
1117 'contact_id' => $this->_contactID
,
1118 'status_id' => $this->_membershipStatusID
,
1119 'membership_type_id' => $this->_membershipTypeID
,
1120 'skipStatusCal' => 1,
1122 $result = $this->callAPISuccess('membership', 'create', $params);
1123 $this->assertEquals($result['id'], $membershipID, "in line " . __LINE__
);
1124 $this->callAPISuccess('Membership', 'Delete', [
1125 'id' => $result['id'],
1130 * Change custom field using update.
1132 public function testUpdateWithCustom() {
1133 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1135 $params = $this->_params
;
1136 $params['custom_' . $ids['custom_field_id']] = "custom string";
1137 $result = $this->callAPIAndDocument($this->_entity
, 'create', $params, __FUNCTION__
, __FILE__
, NULL, 'UpdateCustomData');
1138 $result = $this->callAPISuccess($this->_entity
, 'create', [
1139 'id' => $result['id'],
1140 'custom_' . $ids['custom_field_id'] => "new custom",
1142 $check = $this->callAPISuccess($this->_entity
, 'get', [
1143 'id' => $result['id'],
1144 'contact_id' => $this->_contactID
,
1147 $this->assertEquals("new custom", $check['values'][$result['id']]['custom_' . $ids['custom_field_id']], ' in line ' . __LINE__
);
1148 $this->callAPISuccess('Membership', 'Delete', [
1149 'id' => $check['id'],
1152 $this->customFieldDelete($ids['custom_field_id']);
1153 $this->customGroupDelete($ids['custom_group_id']);
1157 * per CRM-15746 check that the id can be altered in an update hook
1159 public function testMembershipUpdateCreateHookCRM15746() {
1160 $this->hookClass
->setHook('civicrm_pre', [$this, 'hook_civicrm_pre_update_create_membership']);
1161 $result = $this->callAPISuccess('membership', 'create', $this->_params
);
1162 $this->callAPISuccess('membership', 'create', ['id' => $result['id'], 'end_date' => '1 year ago']);
1163 $this->callAPISuccessGetCount('membership', [], 2);
1164 $this->hookClass
->reset();
1165 $this->callAPISuccess('membership', 'create', ['id' => $result['id'], 'end_date' => '1 year ago']);
1166 $this->callAPISuccessGetCount('membership', [], 2);
1170 * Custom hook for update membership.
1173 * @param object $objectName
1175 * @param array $params
1177 * @throws \Exception
1179 public function hook_civicrm_pre_update_create_membership($op, $objectName, $id, &$params) {
1180 if ($objectName === 'Membership' && $op === 'edit') {
1181 $existingMembership = $this->callAPISuccessGetSingle('membership', ['id' => $params['id']]);
1182 unset($params['id'], $params['membership_id']);
1183 $params['join_date'] = $params['membership_start_date'] = $params['start_date'] = date('Ymd000000', strtotime($existingMembership['start_date']));
1184 $params = array_merge($existingMembership, $params);
1185 $params['id'] = NULL;
1190 * Test civicrm_contact_memberships_create Invalid membership data.
1193 public function testMembershipCreateInvalidMemData() {
1194 //membership_contact_id as string
1196 'membership_contact_id' => 'Invalid',
1197 'membership_type_id' => $this->_membershipTypeID
,
1198 'join_date' => '2011-01-21',
1199 'start_date' => '2010-01-21',
1200 'end_date' => '2008-12-21',
1201 'source' => 'Payment',
1203 'status_id' => $this->_membershipStatusID
,
1206 $this->callAPIFailure('membership', 'create', $params);
1208 //membership_contact_id which is no in contact table
1209 $params['membership_contact_id'] = 999;
1210 $this->callAPIFailure('membership', 'create', $params);
1213 unset($params['membership_contact_id']);
1214 $params['join_date'] = "invalid";
1215 $this->callAPIFailure('Membership', 'Create', $params);
1219 * Test civicrm_contact_memberships_create with membership_contact_id
1223 public function testMembershipCreateWithMemContact() {
1225 'membership_contact_id' => $this->_contactID
,
1226 'membership_type_id' => $this->_membershipTypeID
,
1227 'join_date' => '2011-01-21',
1228 'start_date' => '2010-01-21',
1229 'end_date' => '2008-12-21',
1230 'source' => 'Payment',
1232 'status_id' => $this->_membershipStatusID
,
1235 $result = $this->callAPISuccess('membership', 'create', $params);
1237 $this->callAPISuccess('Membership', 'Delete', [
1238 'id' => $result['id'],
1243 * Test civicrm_contact_memberships_create with membership_contact_id
1247 public function testMembershipCreateValidMembershipTypeString() {
1249 'membership_contact_id' => $this->_contactID
,
1250 'membership_type_id' => 'General',
1251 'join_date' => '2011-01-21',
1252 'start_date' => '2010-01-21',
1253 'end_date' => '2008-12-21',
1254 'source' => 'Payment',
1256 'status_id' => $this->_membershipStatusID
,
1259 $result = $this->callAPISuccess('membership', 'create', $params);
1260 $this->assertEquals($this->_membershipTypeID
, $result['values'][$result['id']]['membership_type_id']);
1261 $this->callAPISuccess('Membership', 'Delete', [
1262 'id' => $result['id'],
1267 * Test civicrm_contact_memberships_create with membership_contact_id
1271 public function testMembershipCreateInValidMembershipTypeString() {
1273 'membership_contact_id' => $this->_contactID
,
1274 'membership_type_id' => 'invalid',
1275 'join_date' => '2011-01-21',
1276 'start_date' => '2010-01-21',
1277 'end_date' => '2008-12-21',
1278 'source' => 'Payment',
1280 'status_id' => $this->_membershipStatusID
,
1283 $this->callAPIFailure('membership', 'create', $params);
1287 * Test that if membership join date is not set it defaults to today.
1289 public function testEmptyJoinDate() {
1290 unset($this->_params
['join_date'], $this->_params
['is_override']);
1291 $result = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
1292 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1293 $this->assertEquals(date('Y-m-d', strtotime('now')), $result['join_date']);
1294 $this->assertEquals('2009-01-21', $result['start_date']);
1295 $this->assertEquals('2009-12-21', $result['end_date']);
1299 * Test that if membership start date is not set it defaults to correct end date.
1302 public function testEmptyStartDateFixed() {
1303 unset($this->_params
['start_date'], $this->_params
['is_override']);
1304 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1305 $result = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
1306 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1307 $this->assertEquals('2009-01-21', $result['join_date']);
1308 $this->assertEquals('2008-03-01', $result['start_date']);
1309 $this->assertEquals('2009-12-21', $result['end_date']);
1313 * Test that if membership start date is not set it defaults to correct end date
1316 public function testEmptyStartEndDateFixedOneYear() {
1317 unset($this->_params
['start_date'], $this->_params
['is_override'], $this->_params
['end_date']);
1318 $this->callAPISuccess('membership_type', 'create', ['id' => $this->_membershipTypeID2
, 'duration_interval' => 1]);
1319 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1320 $result = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
1321 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1322 $this->assertEquals('2009-01-21', $result['join_date']);
1323 $this->assertEquals('2008-03-01', $result['start_date']);
1324 $this->assertEquals('2010-02-28', $result['end_date']);
1328 * Test that if membership start date is not set it defaults to correct end date for fixed multi year memberships.
1330 public function testEmptyStartEndDateFixedMultiYear() {
1331 unset($this->_params
['start_date'], $this->_params
['is_override'], $this->_params
['end_date']);
1332 $this->callAPISuccess('membership_type', 'create', ['id' => $this->_membershipTypeID2
, 'duration_interval' => 5]);
1333 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1334 $result = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
1335 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1336 $this->assertEquals('2009-01-21', $result['join_date']);
1337 $this->assertEquals('2008-03-01', $result['start_date']);
1338 $this->assertEquals('2014-02-28', $result['end_date']);
1342 * CRM-18503 - Test membership join date is correctly set for fixed memberships.
1344 * @throws \CRM_Core_Exception
1346 public function testMembershipJoinDateFixed() {
1347 $memStatus = CRM_Member_PseudoConstant
::membershipStatus();
1348 // Update the fixed membership type to 1 year duration.
1349 $this->callAPISuccess('membership_type', 'create', ['id' => $this->_membershipTypeID2
, 'duration_interval' => 1]);
1350 $contactId = $this->createLoggedInUser();
1351 // Create membership with 'Pending' status.
1353 'contact_id' => $contactId,
1354 'membership_type_id' => $this->_membershipTypeID2
,
1355 'source' => 'test membership',
1356 'is_pay_later' => 0,
1357 'status_id' => array_search('Pending', $memStatus),
1358 'skipStatusCal' => 1,
1359 'is_for_organization' => 1,
1361 $membership = CRM_Member_BAO_Membership
::create($params);
1363 // Update membership to 'Completed' and check the dates.
1365 'id' => $membership->id
,
1366 'contact_id' => $contactId,
1368 'membership_type_id' => $this->_membershipTypeID2
,
1370 'status_id' => array_search('New', $memStatus),
1372 $result = $this->callAPISuccess('Membership', 'create', $memParams);
1374 // Extend duration interval if join_date exceeds the rollover period.
1375 $joinDate = date('Y-m-d');
1377 $startDate = date('Y-m-d', strtotime(date('Y-03-01')));
1379 if (strtotime($startDate) > time()) {
1381 $startDate = date('Y-m-d', strtotime(date('Y-03-01') . '- 1 year'));
1383 $membershipTypeDetails = CRM_Member_BAO_MembershipType
::getMembershipTypeDetails($this->_membershipTypeID2
);
1384 $fixedPeriodRollover = CRM_Member_BAO_MembershipType
::isDuringFixedAnnualRolloverPeriod($joinDate, $membershipTypeDetails, $year, $startDate);
1386 if ($fixedPeriodRollover && $rollOver) {
1391 'join_date' => date('Ymd'),
1392 'start_date' => str_replace('-', '', $startDate),
1393 'end_date' => date('Ymd', strtotime(date('Y-03-01') . "+ {$y} year - 1 day")),
1395 foreach ($result['values'] as $values) {
1396 foreach ($expectedDates as $date => $val) {
1397 $this->assertEquals($val, $values[$date], "Failed asserting {$date} values");
1403 * Test correct end and start dates are calculated for fixed multi year memberships.
1405 * The empty start date is calculated to be the start_date (1 Jan prior to the join_date - so 1 Jan 15)
1407 * In this set our start date is after the start day and before the rollover day so we don't get an extra year
1408 * and we end one day before the rollover day. Start day is 1 Jan so we end on 31 Dec
1409 * and we add on 4 years rather than 5 because we are not after the rollover day - so we calculate 31 Dec 2019
1411 public function testFixedMultiYearDateSetTwoEmptyStartEndDate() {
1412 unset($this->_params
['start_date'], $this->_params
['is_override'], $this->_params
['end_date']);
1414 $this->callAPISuccess('membership_type', 'create', [
1415 'id' => $this->_membershipTypeID2
,
1416 'duration_interval' => 5,
1418 'fixed_period_start_day' => '101',
1420 'fixed_period_rollover_day' => '1101',
1422 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1424 'join_date' => '28-Jan 2015',
1426 $result = $this->callAPISuccess($this->_entity
, 'create', array_merge($this->_params
, $dates));
1427 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1428 $this->assertEquals('2015-01-28', $result['join_date']);
1429 $this->assertEquals('2015-01-01', $result['start_date']);
1430 $this->assertEquals('2019-12-31', $result['end_date']);
1434 * Test that correct end date is calculated for fixed multi year memberships and start date is not changed.
1436 * In this set our start date is after the start day and before the rollover day so we don't get an extra year
1437 * and we end one day before the rollover day. Start day is 1 Jan so we end on 31 Dec
1438 * and we add on 4 years rather than 5 because we are not after the rollover day - so we calculate 31 Dec 2019
1440 public function testFixedMultiYearDateSetTwoEmptyEndDate() {
1441 unset($this->_params
['start_date'], $this->_params
['is_override'], $this->_params
['end_date']);
1443 $this->callAPISuccess('membership_type', 'create', [
1444 'id' => $this->_membershipTypeID2
,
1445 'duration_interval' => 5,
1447 'fixed_period_start_day' => '101',
1449 'fixed_period_rollover_day' => '1101',
1451 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1453 'start_date' => '28-Jan 2015',
1454 'join_date' => '28-Jan 2015',
1456 $result = $this->callAPISuccess($this->_entity
, 'create', array_merge($this->_params
, $dates));
1457 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1458 $this->assertEquals('2015-01-28', $result['join_date']);
1459 $this->assertEquals('2015-01-28', $result['start_date']);
1460 $this->assertEquals('2019-12-31', $result['end_date']);
1464 * Test correct end and start dates are calculated for fixed multi year memberships.
1466 * The empty start date is calculated to be the start_date (1 Jan prior to the join_date - so 1 Jan 15)
1468 * In this set our start date is after the start day and before the rollover day so we don't get an extra year
1469 * and we end one day before the rollover day. Start day is 1 Jan so we end on 31 Dec
1470 * and we add on <1 years rather than > 1 because we are not after the rollover day - so we calculate 31 Dec 2015
1472 public function testFixedSingleYearDateSetTwoEmptyStartEndDate() {
1473 unset($this->_params
['start_date'], $this->_params
['is_override'], $this->_params
['end_date']);
1475 $this->callAPISuccess('membership_type', 'create', [
1476 'id' => $this->_membershipTypeID2
,
1477 'duration_interval' => 1,
1479 'fixed_period_start_day' => '101',
1481 'fixed_period_rollover_day' => '1101',
1483 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1485 'join_date' => '28-Jan 2015',
1487 $result = $this->callAPISuccess($this->_entity
, 'create', array_merge($this->_params
, $dates));
1488 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1489 $this->assertEquals('2015-01-28', $result['join_date']);
1490 $this->assertEquals('2015-01-01', $result['start_date']);
1491 $this->assertEquals('2015-12-31', $result['end_date']);
1495 * Test correct end date for fixed single year memberships is calculated and start_date is not changed.
1497 * In this set our start date is after the start day and before the rollover day so we don't get an extra year
1498 * and we end one day before the rollover day. Start day is 1 Jan so we end on 31 Dec
1499 * and we add on <1 years rather than > 1 because we are not after the rollover day - so we calculate 31 Dec 2015
1501 public function testFixedSingleYearDateSetTwoEmptyEndDate() {
1502 unset($this->_params
['start_date'], $this->_params
['is_override'], $this->_params
['end_date']);
1504 $this->callAPISuccess('membership_type', 'create', [
1505 'id' => $this->_membershipTypeID2
,
1506 'duration_interval' => 1,
1508 'fixed_period_start_day' => '101',
1510 'fixed_period_rollover_day' => '1101',
1512 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1514 'start_date' => '28-Jan 2015',
1515 'join_date' => '28-Jan 2015',
1517 $result = $this->callAPISuccess($this->_entity
, 'create', array_merge($this->_params
, $dates));
1518 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1519 $this->assertEquals('2015-01-28', $result['join_date']);
1520 $this->assertEquals('2015-01-28', $result['start_date']);
1521 $this->assertEquals('2015-12-31', $result['end_date']);
1525 * Test that correct end date is calculated for fixed multi year memberships and start date is not changed.
1527 * In this set our start date is after the start day and after the rollover day so we do get an extra year
1528 * and we end one day before the rollover day. Start day is 1 Nov so we end on 31 Oct
1529 * and we add on 1 year we are after the rollover day - so we calculate 31 Oct 2016
1531 public function testFixedSingleYearDateSetThreeEmptyEndDate() {
1532 unset($this->_params
['start_date'], $this->_params
['is_override'], $this->_params
['end_date']);
1534 $this->callAPISuccess('membership_type', 'create', [
1535 'id' => $this->_membershipTypeID2
,
1536 'duration_interval' => 1,
1538 'fixed_period_start_day' => '1101',
1540 'fixed_period_rollover_day' => '101',
1542 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1544 'start_date' => '28-Jan 2015',
1545 'join_date' => '28-Jan 2015',
1547 $result = $this->callAPISuccess($this->_entity
, 'create', array_merge($this->_params
, $dates));
1548 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1549 $this->assertEquals('2015-01-28', $result['join_date']);
1550 $this->assertEquals('2015-01-28', $result['start_date']);
1551 $this->assertEquals('2016-10-31', $result['end_date']);
1555 * Test correct end and start dates are calculated for fixed multi year memberships.
1557 * The empty start date is calculated to be the start_date (1 Nov prior to the join_date - so 1 Nov 14)
1559 * In this set our start date is after the start day and after the rollover day so we do get an extra year
1560 * and we end one day before the rollover day. Start day is 1 Nov so we end on 31 Oct
1561 * and we add on 1 year we are after the rollover day - so we calculate 31 Oct 2016
1563 public function testFixedSingleYearDateSetThreeEmptyStartEndDate() {
1564 unset($this->_params
['start_date'], $this->_params
['is_override'], $this->_params
['end_date']);
1566 $this->callAPISuccess('membership_type', 'create', [
1567 'id' => $this->_membershipTypeID2
,
1568 'duration_interval' => 1,
1570 'fixed_period_start_day' => '1101',
1572 'fixed_period_rollover_day' => '101',
1574 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1576 'join_date' => '28-Jan 2015',
1578 $result = $this->callAPISuccess($this->_entity
, 'create', array_merge($this->_params
, $dates));
1579 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1580 $this->assertEquals('2015-01-28', $result['join_date']);
1581 $this->assertEquals('2014-11-01', $result['start_date']);
1582 $this->assertEquals('2016-10-31', $result['end_date']);
1586 * Test that correct end date is calculated for fixed multi year memberships and start date is not changed.
1588 * In this set our start date is after the start day and after the rollover day so we do get an extra year
1589 * and we end one day before the rollover day. Start day is 1 Nov so we end on 31 Oct
1590 * and we add on 5 years we are after the rollover day - so we calculate 31 Oct 2020
1592 public function testFixedMultiYearDateSetThreeEmptyEndDate() {
1593 unset($this->_params
['start_date'], $this->_params
['is_override'], $this->_params
['end_date']);
1595 $this->callAPISuccess('membership_type', 'create', [
1596 'id' => $this->_membershipTypeID2
,
1597 'duration_interval' => 5,
1599 'fixed_period_start_day' => '1101',
1601 'fixed_period_rollover_day' => '101',
1603 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1605 'start_date' => '28-Jan 2015',
1606 'join_date' => '28-Jan 2015',
1608 $result = $this->callAPISuccess($this->_entity
, 'create', array_merge($this->_params
, $dates));
1609 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1610 $this->assertEquals('2015-01-28', $result['join_date']);
1611 $this->assertEquals('2015-01-28', $result['start_date']);
1612 $this->assertEquals('2020-10-31', $result['end_date']);
1616 * Test correct end and start dates are calculated for fixed multi year memberships.
1618 * The empty start date is calculated to be the start_date (1 Nov prior to the join_date - so 1 Nov 14)
1620 * The empty start date is calculated to be the start_date (1 Nov prior to the join_date - so 1 Nov 14)
1621 * In this set our join date is after the start day and after the rollover day so we do get an extra year
1622 * and we end one day before the rollover day. Start day is 1 Nov so we end on 31 Oct
1623 * and we add on 5 years we are after the rollover day - so we calculate 31 Oct 2020
1625 public function testFixedMultiYearDateSetThreeEmptyStartEndDate() {
1626 unset($this->_params
['start_date'], $this->_params
['is_override'], $this->_params
['end_date']);
1628 $this->callAPISuccess('membership_type', 'create', [
1629 'id' => $this->_membershipTypeID2
,
1630 'duration_interval' => 5,
1632 'fixed_period_start_day' => '1101',
1634 'fixed_period_rollover_day' => '101',
1636 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1638 'join_date' => '28-Jan 2015',
1640 $result = $this->callAPISuccess($this->_entity
, 'create', array_merge($this->_params
, $dates));
1641 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1642 $this->assertEquals('2015-01-28', $result['join_date']);
1643 $this->assertEquals('2014-11-01', $result['start_date']);
1644 $this->assertEquals('2020-10-31', $result['end_date']);
1648 * Test that if membership start date is not set it defaults to correct end date for fixed single year memberships.
1650 public function testEmptyStartDateRolling() {
1651 unset($this->_params
['start_date'], $this->_params
['is_override']);
1652 $result = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
1653 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1654 $this->assertEquals('2009-01-21', $result['join_date']);
1655 $this->assertEquals('2009-01-21', $result['start_date']);
1656 $this->assertEquals('2009-12-21', $result['end_date']);
1660 * Test that if membership end date is not set it defaults to correct end date.
1663 public function testEmptyEndDateFixed() {
1664 unset($this->_params
['start_date'], $this->_params
['is_override'], $this->_params
['end_date']);
1665 $this->_params
['membership_type_id'] = $this->_membershipTypeID2
;
1666 $result = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
1667 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1668 $this->assertEquals('2009-01-21', $result['join_date']);
1669 $this->assertEquals('2008-03-01', $result['start_date']);
1670 $this->assertEquals('2010-02-28', $result['end_date']);
1674 * Test that if membership end date is not set it defaults to correct end date.
1677 public function testEmptyEndDateRolling() {
1678 unset($this->_params
['is_override'], $this->_params
['end_date']);
1679 $this->_params
['membership_type_id'] = $this->_membershipTypeID
;
1680 $result = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
1681 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1682 $this->assertEquals('2009-01-21', $result['join_date']);
1683 $this->assertEquals('2009-01-21', $result['start_date']);
1684 $this->assertEquals('2010-01-20', $result['end_date']);
1688 * Test that if dates are set they not over-ridden if id is passed in
1690 public function testMembershipDatesNotOverridden() {
1691 $result = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
1692 unset($this->_params
['end_date'], $this->_params
['start_date']);
1693 $this->_params
['id'] = $result['id'];
1694 $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
1695 $result = $this->callAPISuccess($this->_entity
, 'getsingle', ['id' => $result['id']]);
1696 $this->assertEquals('2009-01-21', $result['join_date']);
1697 $this->assertEquals('2009-01-21', $result['start_date']);
1698 $this->assertEquals('2009-12-21', $result['end_date']);
1703 * Test that a contribution linked to multiple memberships results in all being updated.
1705 * @throws \CRM_Core_Exception
1707 public function testMultipleMembershipContribution() {
1708 $this->createMultipleMembershipOrder();
1709 $this->callAPISuccess('Payment', 'create', [
1710 'contribution_id' => $this->ids
['Contribution'][0],
1711 'payment_instrument_id' => 'Check',
1712 'total_amount' => 400,
1714 $memberships = $this->callAPISuccess('membership', 'get')['values'];
1715 $this->assertCount(2, $memberships);
1719 * Test that all membership types are returned when getoptions is called.
1721 * This test locks in current behaviour where types for all domains are returned. It should possibly be domain
1722 * specific but that should only be done in conjunction with adding a hook to allow that to be altered as the
1723 * multisite use case expects the master domain to be able to see all sites.
1727 public function testGetOptionsMembershipTypeID() {
1728 $options = $this->callAPISuccess('Membership', 'getoptions', ['field' => 'membership_type_id']);
1729 $this->assertEquals('Another one', array_pop($options['values']));
1730 $this->assertEquals('General', array_pop($options['values']));
1731 $this->assertEquals(NULL, array_pop($options['values']));