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