Merge pull request #17139 from civicrm/5.25
[civicrm-core.git] / tests / phpunit / CRM / Member / BAO / MembershipTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * Class CRM_Member_BAO_MembershipTest
14 * @group headless
15 */
16 class CRM_Member_BAO_MembershipTest extends CiviUnitTestCase {
17
18 public function setUp() {
19 parent::setUp();
20
21 $this->_contactID = $this->organizationCreate();
22 $this->_membershipTypeID = $this->membershipTypeCreate(['member_of_contact_id' => $this->_contactID]);
23 // add a random number to avoid silly conflicts with old data
24 $this->_membershipStatusID = $this->membershipStatusCreate('test status' . rand(1, 1000));
25 }
26
27 /**
28 * Tears down the fixture, for example, closes a network connection.
29 * This method is called after a test is executed.
30 *
31 * @throws \CRM_Core_Exception
32 */
33 public function tearDown() {
34 $this->membershipTypeDelete(['id' => $this->_membershipTypeID]);
35 $this->membershipStatusDelete($this->_membershipStatusID);
36 $this->contactDelete($this->_contactID);
37
38 $this->_contactID = $this->_membershipStatusID = $this->_membershipTypeID = NULL;
39 $this->quickCleanUpFinancialEntities();
40 $this->restoreMembershipTypes();
41 parent::tearDown();
42 }
43
44 /**
45 * Create membership type using given organization id.
46 *
47 * @param $organizationId
48 * @param bool $withRelationship
49 *
50 * @return array|int
51 * @throws \CRM_Core_Exception
52 */
53 private function createMembershipType($organizationId, $withRelationship = FALSE) {
54 $membershipType = $this->callAPISuccess('MembershipType', 'create', [
55 //Default domain ID
56 'domain_id' => 1,
57 'member_of_contact_id' => $organizationId,
58 'financial_type_id' => "Member Dues",
59 'duration_unit' => "year",
60 'duration_interval' => 1,
61 'period_type' => "rolling",
62 'name' => 'Organiation Membership Type',
63 'relationship_type_id' => ($withRelationship) ? 5 : NULL,
64 'relationship_direction' => ($withRelationship) ? 'b_a' : NULL,
65 ]);
66 return $membershipType["values"][$membershipType["id"]];
67 }
68
69 /**
70 * Get count of related memberships by parent membership id.
71 * @param $membershipId
72 * @return array|int
73 */
74 private function getRelatedMembershipsCount($membershipId) {
75 return $this->callAPISuccess("Membership", "getcount", [
76 'owner_membership_id' => $membershipId,
77 ]);
78 }
79
80 /**
81 * Test to delete related membership when type of parent memebrship is changed which does not have relation type associated.
82 * @throws CRM_Core_Exception
83 */
84 public function testDeleteRelatedMembershipsOnParentTypeChanged() {
85
86 $contactId = $this->individualCreate();
87 $membershipOrganizationId = $this->organizationCreate();
88 $organizationId = $this->organizationCreate();
89
90 // Create relationship between organization and individual contact
91 $this->callAPISuccess('Relationship', 'create', [
92 // Employer of relationship
93 'relationship_type_id' => 5,
94 'contact_id_a' => $contactId,
95 'contact_id_b' => $organizationId,
96 'is_active' => 1,
97 ]);
98
99 // Create two membership types one with relationship and one without.
100 $membershipTypeWithRelationship = $this->createMembershipType($membershipOrganizationId, TRUE);
101 $membershipTypeWithoutRelationship = $this->createMembershipType($membershipOrganizationId);
102
103 // Creating membership of organisation
104 $membership = $this->callAPISuccess("Membership", "create", [
105 'membership_type_id' => $membershipTypeWithRelationship["id"],
106 'contact_id' => $organizationId,
107 'status_id' => $this->_membershipStatusID,
108 ]);
109
110 $membership = $membership['values'][$membership["id"]];
111
112 // Check count of related memberships. It should be one for individual contact.
113 $relatedMembershipsCount = $this->getRelatedMembershipsCount($membership["id"]);
114 $this->assertEquals(1, $relatedMembershipsCount, 'Related membership count should be 1.');
115
116 // Update membership by changing it's type. New membership type is without relationship.
117 $membership["membership_type_id"] = $membershipTypeWithoutRelationship["id"];
118 $updatedMembership = $this->callAPISuccess("Membership", "create", $membership);
119
120 // Check count of related memberships again. It should be zero as we changed the membership type.
121 $relatedMembershipsCount = $this->getRelatedMembershipsCount($membership["id"]);
122 $this->assertEquals(0, $relatedMembershipsCount, 'Related membership count should be 0.');
123
124 // Clean up: Delete membership
125 $this->membershipDelete($membership["id"]);
126 }
127
128 public function testCreate() {
129
130 list($contactId, $membershipId) = $this->setupMembership();
131
132 // Now call create() to modify an existing Membership
133 $params = [
134 'id' => $membershipId,
135 'contact_id' => $contactId,
136 'membership_type_id' => $this->_membershipTypeID,
137 'join_date' => date('Ymd', strtotime('2006-01-21')),
138 'start_date' => date('Ymd', strtotime('2006-01-21')),
139 'end_date' => date('Ymd', strtotime('2006-12-21')),
140 'source' => 'Payment',
141 'is_override' => 1,
142 'status_id' => $this->_membershipStatusID,
143 ];
144 CRM_Member_BAO_Membership::create($params);
145
146 $membershipTypeId = $this->assertDBNotNull('CRM_Member_BAO_Membership', $contactId,
147 'membership_type_id', 'contact_id',
148 'Database check on updated membership record.'
149 );
150 $this->assertEquals($membershipTypeId, $this->_membershipTypeID, 'Verify membership type id is fetched.');
151
152 $this->membershipDelete($membershipId);
153 $this->contactDelete($contactId);
154 }
155
156 public function testGetValues() {
157 // $this->markTestSkipped( 'causes mysterious exit, needs fixing!' );
158 // Calculate membership dates based on the current date
159 $now = time();
160 $year_from_now = $now + (365 * 24 * 60 * 60);
161 $last_month = $now - (30 * 24 * 60 * 60);
162 $year_from_last_month = $last_month + (365 * 24 * 60 * 60);
163
164 $contactId = $this->individualCreate();
165
166 $params = [
167 'contact_id' => $contactId,
168 'membership_type_id' => $this->_membershipTypeID,
169 'join_date' => date('Ymd'),
170 'start_date' => date('Ymd'),
171 'end_date' => date('Ymd', $year_from_now),
172 'source' => 'Payment',
173 'is_override' => 1,
174 'status_id' => $this->_membershipStatusID,
175 ];
176
177 CRM_Member_BAO_Membership::create($params);
178
179 $membershipId1 = $this->assertDBNotNull('CRM_Member_BAO_Membership', $contactId, 'id',
180 'contact_id', 'Database check for created membership.'
181 );
182
183 $params = [
184 'contact_id' => $contactId,
185 'membership_type_id' => $this->_membershipTypeID,
186 'join_date' => date('Ymd', $last_month),
187 'start_date' => date('Ymd', $last_month),
188 'end_date' => date('Ymd', $year_from_last_month),
189 'source' => 'Source123',
190 'is_override' => 0,
191 'status_id' => $this->_membershipStatusID,
192 ];
193
194 CRM_Member_BAO_Membership::create($params);
195
196 $membershipId2 = $this->assertDBNotNull('CRM_Member_BAO_Membership', 'source123', 'id',
197 'source', 'Database check for created membership.'
198 );
199
200 $membership = ['contact_id' => $contactId];
201 $membershipValues = [];
202 CRM_Member_BAO_Membership::getValues($membership, $membershipValues, TRUE);
203
204 $this->assertEquals($membershipValues[$membershipId1]['membership_id'], $membershipId1, 'Verify membership record 1 is fetched.');
205
206 $this->assertEquals($membershipValues[$membershipId2]['membership_id'], $membershipId2, 'Verify membership record 2 is fetched.');
207
208 $this->membershipDelete($membershipId1);
209 $this->membershipDelete($membershipId2);
210 $this->contactDelete($contactId);
211 }
212
213 public function testRetrieve() {
214 list($contactId, $membershipId) = $this->setupMembership();
215 $params = ['id' => $membershipId];
216 $values = [];
217 CRM_Member_BAO_Membership::retrieve($params, $values);
218 $this->assertEquals($values['id'], $membershipId, 'Verify membership record is retrieved.');
219
220 $this->membershipDelete($membershipId);
221 $this->contactDelete($contactId);
222 }
223
224 public function testActiveMembers() {
225 $contactId = $this->individualCreate();
226
227 $params = [
228 'contact_id' => $contactId,
229 'membership_type_id' => $this->_membershipTypeID,
230 'join_date' => date('Ymd', strtotime('2006-01-21')),
231 'start_date' => date('Ymd', strtotime('2006-01-21')),
232 'end_date' => date('Ymd', strtotime('2006-12-21')),
233 'source' => 'Payment',
234 'is_override' => 1,
235 'status_id' => $this->_membershipStatusID,
236 ];
237
238 CRM_Member_BAO_Membership::create($params);
239
240 $membershipId1 = $this->assertDBNotNull('CRM_Member_BAO_Membership', $contactId, 'id',
241 'contact_id', 'Database check for created membership.'
242 );
243
244 $params = ['id' => $membershipId1];
245 $values1 = [];
246 CRM_Member_BAO_Membership::retrieve($params, $values1);
247 $membership = [$membershipId1 => $values1];
248
249 $params = [
250 'contact_id' => $contactId,
251 'membership_type_id' => $this->_membershipTypeID,
252 'join_date' => date('Ymd', strtotime('2006-01-21')),
253 'start_date' => date('Ymd', strtotime('2006-01-21')),
254 'end_date' => date('Ymd', strtotime('2006-12-21')),
255 'source' => 'PaySource',
256 'is_override' => 1,
257 'status_id' => $this->_membershipStatusID,
258 ];
259
260 CRM_Member_BAO_Membership::create($params);
261
262 $membershipId2 = $this->assertDBNotNull('CRM_Member_BAO_Membership', 'PaySource', 'id',
263 'source', 'Database check for created membership.'
264 );
265
266 $params = ['id' => $membershipId2];
267 $values2 = [];
268 CRM_Member_BAO_Membership::retrieve($params, $values2);
269 $membership[$membershipId2] = $values2;
270
271 $activeMembers = CRM_Member_BAO_Membership::activeMembers($membership);
272 $inActiveMembers = CRM_Member_BAO_Membership::activeMembers($membership, 'inactive');
273
274 $this->assertEquals($activeMembers[$membershipId1]['id'], $membership[$membershipId1]['id'], 'Verify active membership record is retrieved.');
275 $this->assertEquals($activeMembers[$membershipId2]['id'], $membership[$membershipId2]['id'], 'Verify active membership record is retrieved.');
276
277 $this->assertEquals(0, count($inActiveMembers), 'Verify No inactive membership record is retrieved.');
278
279 $this->membershipDelete($membershipId1);
280 $this->membershipDelete($membershipId2);
281 $this->contactDelete($contactId);
282 }
283
284 public function testDeleteMembership() {
285 list($contactId, $membershipId) = $this->setupMembership();
286 CRM_Member_BAO_Membership::del($membershipId);
287
288 $this->assertDBNull('CRM_Member_BAO_Membership', $contactId, 'id',
289 'contact_id', 'Database check for deleted membership.'
290 );
291 $this->assertDBNull('CRM_Price_BAO_LineItem', $membershipId, 'id',
292 'entity_id', 'Database check for deleted line item.'
293 );
294 $this->contactDelete($contactId);
295 }
296
297 public function testGetContactMembership() {
298 list($contactId, $membershipId) = $this->setupMembership();
299
300 $membership = CRM_Member_BAO_Membership::getContactMembership($contactId, $this->_membershipTypeID, FALSE);
301
302 $this->assertEquals($membership['id'], $membershipId, 'Verify membership record is retrieved.');
303
304 $this->membershipDelete($membershipId);
305 $this->contactDelete($contactId);
306 }
307
308 /**
309 * Get the contribution.
310 * page id from the membership record
311 */
312 public function testgetContributionPageId() {
313 list($contactId, $membershipId) = $this->setupMembership();
314 $membership[$membershipId]['renewPageId'] = CRM_Member_BAO_Membership::getContributionPageId($membershipId);
315
316 $this->membershipDelete($membershipId);
317 $this->contactDelete($contactId);
318 }
319
320 /**
321 * Get membership joins/renewals
322 * for a specified membership
323 * type.
324 */
325 public function testgetMembershipStarts() {
326 list($contactId, $membershipId) = $this->setupMembership();
327 $yearStart = date('Y') . '0101';
328 $currentDate = date('Ymd');
329 CRM_Member_BAO_Membership::getMembershipStarts($this->_membershipTypeID, $yearStart, $currentDate);
330
331 $this->membershipDelete($membershipId);
332 $this->contactDelete($contactId);
333 }
334
335 /**
336 * Get a count of membership for a specified membership type,
337 * optionally for a specified date.
338 */
339 public function testGetMembershipCount() {
340 list($contactId, $membershipId) = $this->setupMembership();
341 $currentDate = date('Ymd');
342 $test = 0;
343 CRM_Member_BAO_Membership::getMembershipCount($this->_membershipTypeID, $currentDate, $test);
344
345 $this->membershipDelete($membershipId);
346 $this->contactDelete($contactId);
347 }
348
349 /**
350 * Checkup sort name function.
351 */
352 public function testSortName() {
353 $contactId = $this->individualCreate();
354
355 $params = [
356 'contact_id' => $contactId,
357 'membership_type_id' => $this->_membershipTypeID,
358 'join_date' => '2006-01-21',
359 'start_date' => '2006-01-21',
360 'end_date' => '2006-12-21',
361 'source' => 'Payment',
362 'is_override' => 1,
363 'status_id' => $this->_membershipStatusID,
364 ];
365
366 $membership = $this->callAPISuccess('Membership', 'create', $params);
367
368 $this->assertEquals('Anderson, Anthony', CRM_Member_BAO_Membership::sortName($membership['id']));
369
370 $this->membershipDelete($membership['id']);
371 $this->contactDelete($contactId);
372 }
373
374 /**
375 * Delete related memberships.
376 */
377 public function testdeleteRelatedMemberships() {
378 list($contactId, $membershipId) = $this->setupMembership();
379
380 CRM_Member_BAO_Membership::deleteRelatedMemberships($membershipId);
381
382 $this->membershipDelete($membershipId);
383 $this->contactDelete($contactId);
384 }
385
386 /**
387 * Renew membership with change in membership type.
388 *
389 * @fixme Note that this test fails when today is August 29 2019 (and maybe other years?):
390 * Verify correct end date is calculated after membership renewal
391 * Failed asserting that two strings are equal.
392 * Expected-'2021-03-01'
393 * Actual+'2021-02-28'
394 * /home/jenkins/bknix-dfl/build/core-15165-73etc/web/sites/all/modules/civicrm/tests/phpunit/CRM/Member/BAO/MembershipTest.php:609
395 */
396 public function testRenewMembership() {
397 $contactId = $this->individualCreate();
398 $joinDate = $startDate = date("Ymd", strtotime(date("Ymd") . " -6 month"));
399 $endDate = date("Ymd", strtotime($joinDate . " +1 year -1 day"));
400 $params = [
401 'contact_id' => $contactId,
402 'membership_type_id' => $this->_membershipTypeID,
403 'join_date' => $joinDate,
404 'start_date' => $startDate,
405 'end_date' => $endDate,
406 'source' => 'Payment',
407 'is_override' => 1,
408 'status_id' => $this->_membershipStatusID,
409 ];
410
411 $membership = CRM_Member_BAO_Membership::create($params);
412 $membershipId = $this->assertDBNotNull('CRM_Member_BAO_Membership', $contactId, 'id',
413 'contact_id', 'Database check for created membership.'
414 );
415
416 $this->assertDBNotNull('CRM_Member_BAO_MembershipLog',
417 $membership->id,
418 'id',
419 'membership_id',
420 'Database checked on membershiplog record.'
421 );
422
423 // this is a test and we dont want qfKey generation / validation
424 // easier to suppress it, than change core code
425 $config = CRM_Core_Config::singleton();
426 $config->keyDisable = TRUE;
427
428 $isTestMembership = 0;
429 list($MembershipRenew) = CRM_Member_BAO_Membership::processMembership(
430 $contactId,
431 $this->_membershipTypeID,
432 $isTestMembership,
433 NULL,
434 NULL,
435 NULL,
436 1,
437 FALSE,
438 NULL,
439 NULL,
440 FALSE,
441 NULL,
442 NULL
443 );
444 $endDate = date("Y-m-d", strtotime($membership->end_date . " +1 year"));
445
446 $this->assertDBNotNull('CRM_Member_BAO_MembershipLog',
447 $MembershipRenew->id,
448 'id',
449 'membership_id',
450 'Database checked on membershiplog record.'
451 );
452 $this->assertEquals($this->_membershipTypeID, $MembershipRenew->membership_type_id, 'Verify membership type is changed during renewal.');
453 $this->assertEquals($endDate, $MembershipRenew->end_date, 'Verify correct end date is calculated after membership renewal');
454
455 $this->membershipDelete($membershipId);
456 $this->contactDelete($contactId);
457 }
458
459 /**
460 * Renew stale membership.
461 *
462 * @throws \CRM_Core_Exception
463 * @throws \CiviCRM_API3_Exception
464 */
465 public function testStaleMembership() {
466 $statusId = 3;
467 $contactId = $this->individualCreate();
468 $joinDate = $startDate = date("Ymd", strtotime(date("Ymd") . " -1 year -15 days"));
469 $endDate = date('Ymd', strtotime($joinDate . " +1 year -1 day"));
470 $params = [
471 'contact_id' => $contactId,
472 'membership_type_id' => $this->_membershipTypeID,
473 'join_date' => $joinDate,
474 'start_date' => $startDate,
475 'end_date' => $endDate,
476 'source' => 'Payment',
477 'status_id' => $statusId,
478 ];
479
480 $membership = CRM_Member_BAO_Membership::create($params);
481
482 $membershipId = $this->assertDBNotNull('CRM_Member_BAO_Membership', $contactId, 'id',
483 'contact_id', 'Database check for created membership.'
484 );
485
486 $this->assertEquals($membership->status_id, $statusId, 'Verify correct status id is calculated.');
487 $this->assertEquals($membership->membership_type_id, $this->_membershipTypeID,
488 'Verify correct membership type id.'
489 );
490
491 //verify all dates.
492 $dates = [
493 'startDate' => 'start_date',
494 'joinDate' => 'join_date',
495 'endDate' => 'end_date',
496 ];
497
498 foreach ($dates as $date => $dbDate) {
499 $this->assertEquals($membership->$dbDate, $$date,
500 "Verify correct {$date} is present."
501 );
502 }
503
504 $this->assertDBNotNull('CRM_Member_BAO_MembershipLog',
505 $membership->id,
506 'id',
507 'membership_id',
508 'Database checked on membership log record.'
509 );
510
511 list($MembershipRenew) = CRM_Member_BAO_Membership::processMembership(
512 $contactId,
513 $this->_membershipTypeID,
514 FALSE,
515 FALSE,
516 NULL,
517 NULL,
518 NULL,
519 1,
520 NULL,
521 NULL,
522 NULL,
523 FALSE,
524 NULL
525 );
526
527 $this->assertDBNotNull('CRM_Member_BAO_MembershipLog',
528 $MembershipRenew->id,
529 'id',
530 'membership_id',
531 'Database checked on membership log record.'
532 );
533
534 $this->membershipDelete($membershipId);
535 $this->contactDelete($contactId);
536 }
537
538 public function testUpdateAllMembershipStatusConvertExpiredOverriddenStatusToNormal() {
539 $params = [
540 'contact_id' => $this->individualCreate(),
541 'membership_type_id' => $this->_membershipTypeID,
542 'join_date' => date('Ymd', time()),
543 'start_date' => date('Ymd', time()),
544 'end_date' => date('Ymd', strtotime('+1 year')),
545 'source' => 'Payment',
546 'is_override' => 1,
547 'status_override_end_date' => date('Ymd', strtotime('-1 day')),
548 'status_id' => $this->_membershipStatusID,
549 ];
550
551 $createdMembership = CRM_Member_BAO_Membership::create($params);
552
553 CRM_Member_BAO_Membership::updateAllMembershipStatus();
554
555 $membershipAfterProcess = civicrm_api3('Membership', 'get', [
556 'sequential' => 1,
557 'id' => $createdMembership->id,
558 'return' => ['id', 'is_override', 'status_override_end_date'],
559 ])['values'][0];
560
561 $this->assertEquals($createdMembership->id, $membershipAfterProcess['id']);
562 $this->assertArrayNotHasKey('is_override', $membershipAfterProcess);
563 $this->assertArrayNotHasKey('status_override_end_date', $membershipAfterProcess);
564 }
565
566 public function testUpdateAllMembershipStatusHandleOverriddenWithEndOverrideDateEqualTodayAsExpired() {
567 $params = [
568 'contact_id' => $this->individualCreate(),
569 'membership_type_id' => $this->_membershipTypeID,
570 'join_date' => date('Ymd', time()),
571 'start_date' => date('Ymd', time()),
572 'end_date' => date('Ymd', strtotime('+1 year')),
573 'source' => 'Payment',
574 'is_override' => 1,
575 'status_override_end_date' => date('Ymd', time()),
576 'status_id' => $this->_membershipStatusID,
577 ];
578
579 $createdMembership = CRM_Member_BAO_Membership::create($params);
580
581 CRM_Member_BAO_Membership::updateAllMembershipStatus();
582
583 $membershipAfterProcess = civicrm_api3('Membership', 'get', [
584 'sequential' => 1,
585 'id' => $createdMembership->id,
586 'return' => ['id', 'is_override', 'status_override_end_date'],
587 ])['values'][0];
588
589 $this->assertEquals($createdMembership->id, $membershipAfterProcess['id']);
590 $this->assertArrayNotHasKey('is_override', $membershipAfterProcess);
591 $this->assertArrayNotHasKey('status_override_end_date', $membershipAfterProcess);
592 }
593
594 public function testUpdateAllMembershipStatusDoesNotConvertOverridenMembershipWithoutEndOverrideDateToNormal() {
595 $params = [
596 'contact_id' => $this->individualCreate(),
597 'membership_type_id' => $this->_membershipTypeID,
598 'join_date' => date('Ymd', time()),
599 'start_date' => date('Ymd', time()),
600 'end_date' => date('Ymd', strtotime('+1 year')),
601 'source' => 'Payment',
602 'is_override' => 1,
603 'status_id' => $this->_membershipStatusID,
604 ];
605
606 $createdMembership = CRM_Member_BAO_Membership::create($params);
607
608 CRM_Member_BAO_Membership::updateAllMembershipStatus();
609
610 $membershipAfterProcess = civicrm_api3('Membership', 'get', [
611 'sequential' => 1,
612 'id' => $createdMembership->id,
613 'return' => ['id', 'is_override', 'status_override_end_date'],
614 ])['values'][0];
615
616 $this->assertEquals($createdMembership->id, $membershipAfterProcess['id']);
617 $this->assertEquals(1, $membershipAfterProcess['is_override']);
618 }
619
620 /**
621 * @throws \CRM_Core_Exception
622 */
623 public function testMembershipPaymentForSingleContributionMultipleMembership() {
624 $membershipTypeID1 = $this->membershipTypeCreate(['name' => 'Parent']);
625 $membershipTypeID2 = $this->membershipTypeCreate(['name' => 'Child']);
626 $financialTypeId = $this->getFinancialTypeId('Member Dues');
627 $priceSet = $this->callAPISuccess('price_set', 'create', [
628 'is_quick_config' => 0,
629 'extends' => 'CiviMember',
630 'financial_type_id' => $financialTypeId,
631 'title' => 'Family Membership',
632 ]);
633 $priceSetID = $priceSet['id'];
634 $priceField = $this->callAPISuccess('price_field', 'create', [
635 'price_set_id' => $priceSetID,
636 'label' => 'Memberships',
637 'html_type' => 'Radio',
638 ]);
639 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', [
640 'price_set_id' => $priceSetID,
641 'price_field_id' => $priceField['id'],
642 'label' => 'Parent',
643 'amount' => 100,
644 'financial_type_id' => $financialTypeId,
645 'membership_type_id' => $membershipTypeID1,
646 'membership_num_terms' => 1,
647 ]);
648 $priceFieldValueId = [1 => $priceFieldValue['id']];
649 $priceFieldValue = $this->callAPISuccess('price_field_value', 'create', [
650 'price_set_id' => $priceSetID,
651 'price_field_id' => $priceField['id'],
652 'label' => 'Child',
653 'amount' => 50,
654 'financial_type_id' => $financialTypeId,
655 'membership_type_id' => $membershipTypeID2,
656 'membership_num_terms' => 1,
657 ]);
658 $priceFieldValueId[2] = $priceFieldValue['id'];
659 $parentContactId = $this->individualCreate();
660 $contributionRecur = $this->callAPISuccess('contribution_recur', 'create', [
661 'contact_id' => $parentContactId,
662 'amount' => 150,
663 'frequency_unit' => 'day',
664 'frequency_interval' => 1,
665 'installments' => 2,
666 'start_date' => 'yesterday',
667 'create_date' => 'yesterday',
668 'modified_date' => 'yesterday',
669 'cancel_date' => NULL,
670 'end_date' => '+ 2 weeks',
671 'processor_id' => '643411460836',
672 'trxn_id' => 'e0d0808e26f3e661c6c18eb7c039d363',
673 'invoice_id' => 'e0d0808e26f3e661c6c18eb7c039d363',
674 'contribution_status_id' => 'In Progress',
675 'cycle_day' => 1,
676 'next_sched_contribution_date' => '+ 1 week',
677 'auto_renew' => 0,
678 'currency' => 'USD',
679 'payment_processor_id' => $this->paymentProcessorCreate(),
680 'financial_type_id' => $financialTypeId,
681 'payment_instrument_id' => 'Credit Card',
682 ]);
683
684 $params[] = [
685 'contact_id' => $this->individualCreate(),
686 'membership_type_id' => $membershipTypeID2,
687 'contribution_recur_id' => $contributionRecur['id'],
688 'join_date' => date('Ymd', time()),
689 'start_date' => date('Ymd', time()),
690 'end_date' => date('Ymd', strtotime('+1 year')),
691 'source' => 'Payment',
692 ];
693 $params[] = [
694 'contact_id' => $this->individualCreate(),
695 'membership_type_id' => $membershipTypeID2,
696 'contribution_recur_id' => $contributionRecur['id'],
697 'join_date' => date('Ymd', time()),
698 'start_date' => date('Ymd', time()),
699 'end_date' => date('Ymd', strtotime('+1 year')),
700 'source' => 'Payment',
701 ];
702
703 foreach ($params as $key => $param) {
704 $this->callAPISuccess('membership', 'create', $param);
705 }
706
707 $contribution = $this->callAPISuccess('Order', 'create', [
708 'total_amount' => 150,
709 'contribution_recur_id' => $contributionRecur['id'],
710 'currency' => 'USD',
711 'contact_id' => $parentContactId,
712 'financial_type_id' => $financialTypeId,
713 'contribution_status_id' => 'Pending',
714 'is_recur' => TRUE,
715 'api.Payment.create' => ['total_amount' => 150],
716 'line_items' => [
717 [
718 'line_item' => [
719 0 => [
720 'price_field_id' => $priceField['id'],
721 'price_field_value_id' => $priceFieldValueId[1],
722 'label' => 'Parent',
723 'membership_type_id' => $membershipTypeID1,
724 'qty' => 1,
725 'unit_price' => 100,
726 'line_total' => 100,
727 'financial_type_id' => $financialTypeId,
728 'entity_table' => 'civicrm_membership',
729 ],
730 1 => [
731 'price_field_id' => $priceField['id'],
732 'price_field_value_id' => $priceFieldValueId[2],
733 'label' => 'Child',
734 'qty' => 1,
735 'unit_price' => 50,
736 'line_total' => 50,
737 'membership_type_id' => $membershipTypeID2,
738 'financial_type_id' => $financialTypeId,
739 'entity_table' => 'civicrm_membership',
740 ],
741 ],
742 ],
743 ],
744 ]);
745 $params[] = [
746 'contact_id' => $parentContactId,
747 'membership_type_id' => $membershipTypeID1,
748 'contribution_recur_id' => $contributionRecur['id'],
749 'join_date' => date('Ymd', time()),
750 'start_date' => date('Ymd', time()),
751 'end_date' => date('Ymd', strtotime('+1 year')),
752 'skipLineItem' => TRUE,
753 'source' => 'Payment',
754 ];
755
756 $this->callAPISuccess('contribution', 'repeattransaction', [
757 'original_contribution_id' => $contribution['id'],
758 'contribution_status_id' => 'Completed',
759 ]);
760 $this->callAPISuccessGetCount('Contribution', [], 2);
761 // @todo this fails depending on what tests it is run with due some bad stuff in Membership.create
762 // It needs to be addressed but might involve the switch to ORDER. Membership BAO does bad line item stuff.
763 // $this->callAPISuccessGetCount('LineItem', [], 6);
764 $this->membershipTypeDelete(['id' => $membershipTypeID1]);
765 $this->membershipTypeDelete(['id' => $membershipTypeID2]);
766 $this->validateAllPayments();
767 $this->validateAllContributions();
768 }
769
770 /**
771 * Test the buildMembershipTypeValues function.
772 *
773 * @throws \CiviCRM_API3_Exception
774 */
775 public function testBuildMembershipTypeValues() {
776 $this->restoreMembershipTypes();
777 $form = new CRM_Core_Form();
778 $values = CRM_Member_BAO_Membership::buildMembershipTypeValues($form);
779 $this->assertEquals([
780 'id' => '1',
781 'minimum_fee' => '100.000000000',
782 'name' => 'General',
783 'is_active' => '1',
784 'description' => 'Regular annual membership.',
785 'financial_type_id' => '2',
786 'auto_renew' => '0',
787 'member_of_contact_id' => $values[1]['member_of_contact_id'],
788 'relationship_type_id' => [7],
789 'relationship_direction' => ['b_a'],
790 'max_related' => NULL,
791 'duration_unit' => 'year',
792 'duration_interval' => '2',
793 'domain_id' => '1',
794 'period_type' => 'rolling',
795 'visibility' => 'Public',
796 'weight' => '1',
797 'tax_rate' => 0.0,
798 'minimum_fee_with_tax' => 100.0,
799 ], $values[1]);
800 }
801
802 /**
803 * @return array
804 * @throws \CRM_Core_Exception
805 * @throws \CiviCRM_API3_Exception
806 */
807 protected function setupMembership(): array {
808 $contactId = $this->individualCreate();
809
810 $params = [
811 'contact_id' => $contactId,
812 'membership_type_id' => $this->_membershipTypeID,
813 'join_date' => date('Ymd', strtotime('2006-01-21')),
814 'start_date' => date('Ymd', strtotime('2006-01-21')),
815 'end_date' => date('Ymd', strtotime('2006-12-21')),
816 'source' => 'Payment',
817 'is_override' => 1,
818 'status_id' => $this->_membershipStatusID,
819 ];
820
821 CRM_Member_BAO_Membership::create($params);
822
823 $membershipId = $this->assertDBNotNull('CRM_Member_BAO_Membership', $contactId, 'id',
824 'contact_id', 'Database check for created membership.'
825 );
826 return [$contactId, $membershipId];
827 }
828
829 }