Merge pull request #17945 from colemanw/commentCleanup
[civicrm-core.git] / tests / phpunit / api / v3 / JobProcessMembershipTest.php
CommitLineData
57aa6fb6
CCPA
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 * Specific tests for the `process_membership` job.
14 *
15 * @link https://github.com/civicrm/civicrm-core/pull/16298
16 * @package CiviCRM_APIv3
17 * @subpackage API_Job
18 *
19 * @copyright CiviCRM LLC https://civicrm.org/licensing
20 */
21
22/**
23 * Class api_v3_JobProcessMembershipTest
24 * @group headless
25 */
26class api_v3_JobProcessMembershipTest extends CiviUnitTestCase {
27 protected $_apiversion = 3;
28
29 public $DBResetRequired = FALSE;
30 public $_entity = 'Job';
31
32 /**
33 * Caches membership status names in a key, value array
34 *
35 * @var array
36 */
37 public $_statuses;
38
39 /**
40 * Caches membership types in a key, value array
41 *
42 * @var array
43 */
44 public $_types;
45
46 /**
47 * Caches some reference dates
48 *
49 * @var string
50 */
51 public $_yesterday;
52
53 /**
54 * @var string
55 */
56 public $_today;
57
58 /**
59 * @var string
60 */
61 public $_tomorrow;
62
63 public function setUp() {
64 parent::setUp();
65 $this->loadReferenceDates();
66 $this->loadMembershipStatuses();
67 $this->loadMembershipTypes();
68 }
69
70 public function loadMembershipStatuses() {
71 $statuses = civicrm_api3('MembershipStatus', 'get', ['options' => ['limit' => 0]])['values'];
72 $this->_statuses = array_map(
73 function($status) {
74 return $status['name'];
75 },
76 $statuses
77 );
78 }
79
80 public function loadMembershipTypes() {
81 $this->membershipTypeCreate(['name' => 'General']);
82 $this->membershipTypeCreate(['name' => 'Old']);
83 $types = civicrm_api3('MembershipType', 'get', ['options' => ['limit' => 0]])['values'];
84 $this->_types = array_map(
85 function($type) {
86 return $type['name'];
87 },
88 $types
89 );
90 }
91
92 public function loadReferenceDates() {
93 $this->_yesterday = date('Y-m-d', time() - 60 * 60 * 24);
94 $this->_today = date('Y-m-d');
95 $this->_tomorrow = date('Y-m-d', time() + 60 * 60 * 24);
96 }
97
98 public function tearDown() {
99 parent::tearDown();
100
101 // For each case, the `old` membershipt type must start as
102 // active, so we can assign it (we'll disabled it after
103 // assigning it)
104 $this->callAPISuccess('MembershipType', 'create', [
105 'id' => array_search('Old', $this->_types),
106 'is_active' => TRUE,
107 ]);
108 }
109
110 /**
111 * Creates a membership that is expired but that should be ignored
112 * by the process as it is in `deceased` status.
113 */
114 public function createDeceasedMembershipThatShouldBeExpired() {
115 $contactId = $this->individualCreate(['is_deceased' => FALSE]);
116 $membershipId = $this->contactMembershipCreate([
117 'contact_id' => $contactId,
118 'start_date' => $this->_yesterday,
119 'end_date' => $this->_yesterday,
120 ]);
121
122 $this->callAPISuccess('Membership', 'create', [
123 'id' => $membershipId,
124 'status_id' => array_search('Deceased', $this->_statuses),
125 ]);
126
127 return $membershipId;
128 }
129
130 /**
131 * Creates a test membership in `grace` status that should be
132 * in `current` status but that won't be updated unless the process
133 * is explicitly told not to exclude tests.
134 */
135 public function createTestMembershipThatShouldBeCurrent() {
136 $contactId = $this->individualCreate();
137 $membershipId = $this->contactMembershipCreate([
138 'contact_id' => $contactId,
139 'start_date' => $this->_yesterday,
140 'end_date' => $this->_tomorrow,
141 'is_test' => TRUE,
142 ]);
143
144 $this->callAPISuccess('Membership', 'create', [
145 'id' => $membershipId,
146 'status_id' => array_search('Grace', $this->_statuses),
147 ]);
148
149 return $membershipId;
150 }
151
152 /**
153 * Creates a grace membership that should be in `current` status
154 * that should be fixed even when the process is executed with
155 * the default parameters.
156 */
157 public function createGraceMembershipThatShouldBeCurrent() {
158 $contactId = $this->individualCreate();
159 $membershipId = $this->contactMembershipCreate([
160 'contact_id' => $contactId,
161 'start_date' => $this->_yesterday,
162 'end_date' => $this->_tomorrow,
163 ]);
164
165 $this->callAPISuccess('Membership', 'create', [
166 'id' => $membershipId,
167 'status_id' => array_search('Grace', $this->_statuses),
168 ]);
169
170 return $membershipId;
171 }
172
173 /**
174 * Creates a pending membership that should be in `current` status
175 * that won't be fixed unless the process is executed
176 * with an explicit `exclude_membership_status_ids` list that
177 * doesn't include it.
178 */
179 public function createPendingMembershipThatShouldBeCurrent() {
180 $contactId = $this->individualCreate();
181 $membershipId = $this->contactMembershipCreate([
182 'contact_id' => $contactId,
183 'start_date' => $this->_yesterday,
184 'end_date' => $this->_tomorrow,
185 ]);
186
187 $this->callAPISuccess('Membership', 'create', [
188 'id' => $membershipId,
189 'status_id' => array_search('Pending', $this->_statuses),
190 ]);
191
192 return $membershipId;
193 }
194
195 /**
196 * Creates a membership that uses an inactive membership type
197 * and should be in `current` status.
198 */
199 public function createOldMembershipThatShouldBeCurrent() {
200 $contactId = $this->individualCreate();
201 $membershipId = $this->contactMembershipCreate([
202 'contact_id' => $contactId,
203 'start_date' => $this->_yesterday,
204 'end_date' => $this->_tomorrow,
205 'membership_type_id' => array_search('Old', $this->_types),
206 ]);
207
208 $this->callAPISuccess('Membership', 'create', [
209 'id' => $membershipId,
210 'status_id' => array_search('Grace', $this->_statuses),
211 ]);
212
213 $this->callAPISuccess('MembershipType', 'create', [
214 'id' => array_search('Old', $this->_types),
215 'is_active' => FALSE,
216 ]);
217
218 return $membershipId;
219 }
220
221 /**
222 * Returns the name of the status of a membership given its id.
223 */
224 public function getMembershipStatus($membershipId) {
225 $membership = $this->callAPISuccess('Membership', 'getsingle', ['id' => $membershipId]);
226 $statusId = $membership['status_id'];
227 return $this->_statuses[$statusId];
228 }
229
230 /**
231 * Test that by default test memberships are excluded.
232 */
233 public function testByDefaultTestsAreExcluded() {
234 $testId = $this->createTestMembershipThatShouldBeCurrent();
235
236 $this->callAPISuccess('job', 'process_membership', []);
237
238 $this->assertEquals('Grace', $this->getMembershipStatus($testId));
239 }
240
241 /**
242 * Test that by default memberships of inactive types are excluded.
243 */
244 public function testByDefaultInactiveAreExcluded() {
245 $oldId = $this->createOldMembershipThatShouldBeCurrent();
246
247 $this->callAPISuccess('job', 'process_membership', []);
248
249 $this->assertEquals('Grace', $this->getMembershipStatus($oldId));
250 }
251
252 /**
253 * Test that by default grace memberships are considered.
254 */
255 public function testByDefaultGraceIsConsidered() {
256 $graceId = $this->createGraceMembershipThatShouldBeCurrent();
257
258 $this->callAPISuccess('job', 'process_membership', []);
259
260 $this->assertEquals('Current', $this->getMembershipStatus($graceId));
261 }
262
263 /**
264 * Test that by default pending memberships are excluded.
265 *
266 * The pending status is still excluded as it's in the
267 * exclude_membership_status_ids list by default.
268 */
269 public function testByDefaultPendingIsExcluded() {
270 $pendingId = $this->createPendingMembershipThatShouldBeCurrent();
271
272 $this->callAPISuccess('job', 'process_membership', []);
273
274 $this->assertEquals('Pending', $this->getMembershipStatus($pendingId));
275 }
276
277 /**
278 * Test that by default memberships of type deceased are excluded.
279 */
280 public function testByDefaultDeceasedIsExcluded() {
281 $deceasedId = $this->createDeceasedMembershipThatShouldBeExpired();
282
283 $this->callAPISuccess('job', 'process_membership', []);
284
285 $this->assertEquals('Deceased', $this->getMembershipStatus($deceasedId));
286 }
287
288 /**
289 * Test that when including test memberships,
290 * pending memberships are excluded.
291 *
292 * The pending status is still excluded as it's in the
293 * exclude_membership_status_ids list by default.
294 */
295 public function testIncludingTestMembershipsExcludesPending() {
296 $pendingId = $this->createPendingMembershipThatShouldBeCurrent();
297
298 $this->callAPISuccess('job', 'process_membership', [
299 'exclude_test_memberships' => FALSE,
300 ]);
301
302 $this->assertEquals('Pending', $this->getMembershipStatus($pendingId));
303 }
304
305 /**
306 * Test that when including test memberships,
307 * grace memberships are considered.
308 */
309 public function testIncludingTestMembershipsConsidersGrace() {
310 $graceId = $this->createGraceMembershipThatShouldBeCurrent();
311
312 $this->callAPISuccess('job', 'process_membership', [
313 'exclude_test_memberships' => FALSE,
314 ]);
315
316 $this->assertEquals('Current', $this->getMembershipStatus($graceId));
317 }
318
319 /**
320 * Test that when including test memberships,
321 * memberships of inactive types are still ignored.
322 */
323 public function testIncludingTestMembershipsIgnoresInactive() {
324 $oldId = $this->createOldMembershipThatShouldBeCurrent();
325
326 $this->callAPISuccess('job', 'process_membership', [
327 'exclude_test_memberships' => FALSE,
328 ]);
329
330 $this->assertEquals('Grace', $this->getMembershipStatus($oldId));
331 }
332
333 /**
334 * Test that when including test memberships,
335 * acually includes test memberships.
336 */
337 public function testIncludingTestMembershipsActuallyIncludesThem() {
338 $testId = $this->createTestMembershipThatShouldBeCurrent();
339
340 $this->callAPISuccess('job', 'process_membership', [
341 'exclude_test_memberships' => FALSE,
342 ]);
343
344 $this->assertEquals('Current', $this->getMembershipStatus($testId));
345 }
346
347 /**
348 * Test that when including test memberships,
349 * memberships of type deceased are still ignored.
350 */
351 public function testIncludingTestMembershipsStillIgnoresDeceased() {
352 $deceasedId = $this->createDeceasedMembershipThatShouldBeExpired();
353
354 $this->callAPISuccess('job', 'process_membership', [
355 'exclude_test_memberships' => FALSE,
356 ]);
357
358 $this->assertEquals('Deceased', $this->getMembershipStatus($deceasedId));
359 }
360
361 /**
362 * Test that when including inactive membership types,
363 * pending memberships are considered.
364 *
365 * The pending status is still excluded as it's in the
366 * exclude_membership_status_ids list by default.
367 */
368 public function testIncludingInactiveMembershipTypesStillExcludesPending() {
369 $pendingId = $this->createPendingMembershipThatShouldBeCurrent();
370
371 $this->callAPISuccess('job', 'process_membership', [
372 'only_active_membership_types' => FALSE,
373 ]);
374
375 $this->assertEquals('Pending', $this->getMembershipStatus($pendingId));
376 }
377
378 /**
379 * Test that when including inactive membership types,
380 * grace memberships are considered.
381 */
382 public function testIncludingInactiveMembershipTypesConsidersGrace() {
383 $graceId = $this->createGraceMembershipThatShouldBeCurrent();
384
385 $this->callAPISuccess('job', 'process_membership', [
386 'only_active_membership_types' => FALSE,
387 ]);
388
389 $this->assertEquals('Current', $this->getMembershipStatus($graceId));
390 }
391
392 /**
393 * Test that when including inactive membership types,
394 * memberships of disabled membership types are considered.
395 */
396 public function testIncludingInactiveMembershipTypesConsidersInactive() {
397 $oldId = $this->createOldMembershipThatShouldBeCurrent();
398
399 $this->callAPISuccess('job', 'process_membership', [
400 'only_active_membership_types' => FALSE,
401 ]);
402
403 $this->assertEquals('Current', $this->getMembershipStatus($oldId));
404 }
405
406 /**
407 * Test that when including inactive membership types,
408 * test memberships are still ignored.
409 */
410 public function testIncludingInactiveMembershipTypesStillIgnoresTests() {
411 $testId = $this->createTestMembershipThatShouldBeCurrent();
412
413 $this->callAPISuccess('job', 'process_membership', [
414 'only_active_membership_types' => FALSE,
415 ]);
416
417 $this->assertEquals('Grace', $this->getMembershipStatus($testId));
418 }
419
420 /**
421 * Test that when including inactive membership types,
422 * memberships of type deceased are still ignored.
423 */
424 public function testMembershipTypeDeceasedIsExcluded() {
425 $deceasedId = $this->createDeceasedMembershipThatShouldBeExpired();
426
427 $this->callAPISuccess('job', 'process_membership', [
428 'only_active_membership_types' => FALSE,
429 ]);
430
431 $this->assertEquals('Deceased', $this->getMembershipStatus($deceasedId));
432 }
433
434 /**
435 * Test that when explicitly setting the status ids to exclude,
436 * memberships in deceased status are still ignored.
437 */
438 public function testSpecifyingTheStatusIdsToExcludeStillExcludesDeceased() {
439 $deceasedId = $this->createDeceasedMembershipThatShouldBeExpired();
440
441 $this->callAPISuccess('job', 'process_membership', [
442 'exclude_membership_status_ids' => [
443 array_search('Cancelled', $this->_statuses),
444 ],
445 ]);
446
447 $this->assertEquals('Deceased', $this->getMembershipStatus($deceasedId));
448 }
449
450 /**
451 * Test that when explicitly setting the status ids to exclude,
452 * test memberships are still ignored.
453 */
454 public function testSpecifyingTheStatusIdsToExcludeStillExcludesTests() {
455 $testId = $this->createTestMembershipThatShouldBeCurrent();
456
457 $this->callAPISuccess('job', 'process_membership', [
458 'exclude_membership_status_ids' => [
459 array_search('Cancelled', $this->_statuses),
460 ],
461 ]);
462
463 $this->assertEquals('Grace', $this->getMembershipStatus($testId));
464 }
465
466 /**
467 * Test that when explicitly setting the status ids to exclude,
468 * memberships of disabled membership types are still ignored.
469 */
470 public function testSpecifyingTheStatusIdsToExcludeStillExcludesInactive() {
471 $oldId = $this->createOldMembershipThatShouldBeCurrent();
472
473 $this->callAPISuccess('job', 'process_membership', [
474 'exclude_membership_status_ids' => [
475 array_search('Cancelled', $this->_statuses),
476 ],
477 ]);
478
479 $this->assertEquals('Grace', $this->getMembershipStatus($oldId));
480 }
481
482 /**
483 * Test that when explicitly setting the status ids to exclude,
484 * grace memberships are considered by default.
485 */
486 public function testSpecifyingTheStatusIdsToExcludeGraceIsIncludedByDefault() {
487 $graceId = $this->createGraceMembershipThatShouldBeCurrent();
488
489 $this->callAPISuccess('job', 'process_membership', [
490 'exclude_membership_status_ids' => [
491 array_search('Cancelled', $this->_statuses),
492 ],
493 ]);
494
495 $this->assertEquals('Current', $this->getMembershipStatus($graceId));
496 }
497
498 /**
499 * Test that when explicitly setting the status ids to exclude,
500 * if the specified list doesn't include pending, then pending
501 * memberships are considered.
502 */
503 public function testSpecifyingTheStatusIdsToExcludePendingIsExcludedByDefault() {
504 $pendingId = $this->createPendingMembershipThatShouldBeCurrent();
505
506 $this->callAPISuccess('job', 'process_membership', [
507 'exclude_membership_status_ids' => [
508 array_search('Cancelled', $this->_statuses),
509 ],
510 ]);
511
512 $this->assertEquals('Current', $this->getMembershipStatus($pendingId));
513 }
514
515}