Merge pull request #15734 from seamuslee001/remove_activity_option_join_custom_search
[civicrm-core.git] / tests / phpunit / api / v3 / PledgeTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 * Test class for Pledge API - civicrm_pledge_*
14 *
15 * @package CiviCRM_APIv3
16 * @group headless
17 */
18 class api_v3_PledgeTest extends CiviUnitTestCase {
19
20 protected $_individualId;
21 protected $_pledge;
22 protected $_params;
23 protected $_entity;
24 protected $scheduled_date;
25
26 /**
27 * @throws \CRM_Core_Exception
28 */
29 public function setUp() {
30 $this->_apiversion = 3;
31 parent::setUp();
32 $this->quickCleanup(['civicrm_pledge', 'civicrm_pledge_payment']);
33 //need to set scheduled payment in advance we are running test @ midnight & it becomes unexpectedly overdue
34 //due to timezone issues
35 $this->scheduled_date = date('Ymd', mktime(0, 0, 0, date("m"), date("d") + 2, date("y")));
36 $this->_entity = 'Pledge';
37 $this->_individualId = $this->individualCreate();
38 $this->_params = [
39 'contact_id' => $this->_individualId,
40 'pledge_create_date' => date('Ymd'),
41 'start_date' => date('Ymd'),
42 'scheduled_date' => $this->scheduled_date,
43 'amount' => 100.00,
44 'pledge_status_id' => '2',
45 'pledge_financial_type_id' => '1',
46 'pledge_original_installment_amount' => 20,
47 'frequency_interval' => 5,
48 'frequency_unit' => 'year',
49 'frequency_day' => 15,
50 'installments' => 5,
51 'sequential' => 1,
52 ];
53 }
54
55 public function tearDown() {
56 $this->contactDelete($this->_individualId);
57 }
58
59 /**
60 * Check with complete array + custom field.
61 *
62 * Note that the test is written on purpose without any
63 * variables specific to participant so it can be replicated into other entities
64 * and / or moved to the automated test suite
65 */
66 public function testCreateWithCustom() {
67 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
68
69 $params = $this->_params;
70 $params['custom_' . $ids['custom_field_id']] = "custom string";
71
72 $result = $this->callAPISuccess($this->_entity, 'create', $params);
73 $this->assertAPISuccess($result, " testCreateWithCustom ");
74 $this->assertAPISuccess($result);
75 $getParams = ['id' => $result['id'], 'return.custom_' . $ids['custom_field_id'] => 1];
76 $check = $this->callAPISuccess($this->_entity, 'get', $getParams);
77 $this->callAPISuccess('pledge', 'delete', ['id' => $check['id']]);
78 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
79
80 $this->customFieldDelete($ids['custom_field_id']);
81 $this->customGroupDelete($ids['custom_group_id']);
82 }
83
84 /**
85 * Test getfields function for pledge.
86 */
87 public function testGetfieldsPledge() {
88 $result = $this->callAPISuccess('pledge', 'getfields', ['action' => 'get']);
89 $this->assertEquals(1, $result['values']['next_pay_date']['api.return']);
90 }
91
92 /**
93 * Test get pledge api.
94 */
95 public function testGetPledge() {
96
97 $this->_pledge = $this->callAPISuccess('pledge', 'create', $this->_params);
98 $params = [
99 'pledge_id' => $this->_pledge['id'],
100 ];
101 $result = $this->callAPIAndDocument('pledge', 'get', $params, __FUNCTION__, __FILE__);
102 $pledge = $result['values'][$this->_pledge['id']];
103 $this->assertEquals($this->_individualId, $pledge['contact_id']);
104 $this->assertEquals($this->_pledge['id'], $pledge['pledge_id']);
105 $this->assertEquals(date('Y-m-d') . ' 00:00:00', $pledge['pledge_create_date']);
106 $this->assertEquals(100.00, $pledge['pledge_amount']);
107 $this->assertEquals('Pending Label**', $pledge['pledge_status']);
108 $this->assertEquals(5, $pledge['pledge_frequency_interval']);
109 $this->assertEquals('year', $pledge['pledge_frequency_unit']);
110 $this->assertEquals(date('Y-m-d', strtotime($this->scheduled_date)) . ' 00:00:00', $pledge['pledge_next_pay_date']);
111 $this->assertEquals($pledge['pledge_next_pay_amount'], 20.00);
112
113 $params2 = [
114 'pledge_id' => $this->_pledge['id'],
115 ];
116 $pledge = $this->callAPISuccess('pledge', 'delete', $params2);
117 }
118
119 /**
120 * Test 'return.pledge_financial_type' => 1 works.
121 */
122 public function testGetPledgeWithReturn() {
123
124 $this->_pledge = $this->callAPISuccess('pledge', 'create', $this->_params);
125 $params = [
126 'pledge_id' => $this->_pledge['id'],
127 'return.pledge_financial_type' => 1,
128 ];
129 $result = $this->callAPISuccess('pledge', 'get', $params);
130 $pledge = $result['values'][$this->_pledge['id']];
131 $this->callAPISuccess('pledge', 'delete', $pledge);
132 $this->assertEquals('Donation', $pledge['pledge_financial_type']);
133 }
134
135 /**
136 * Test 'return.pledge_contribution_type' => 1 works.
137 *
138 * This is for legacy compatibility
139 */
140 public function testGetPledgeWithReturnLegacy() {
141
142 $this->_pledge = $this->callAPISuccess('pledge', 'create', $this->_params);
143 $params = [
144 'pledge_id' => $this->_pledge['id'],
145 'return.pledge_financial_type' => 1,
146 ];
147 $result = $this->callAPISuccess('pledge', 'get', $params);
148 $pledge = $result['values'][$this->_pledge['id']];
149 $this->callAPISuccess('pledge', 'delete', $pledge);
150 $this->assertEquals('Donation', $pledge['pledge_financial_type']);
151 }
152
153 /**
154 * Test date legacy date filters like pledge_start_date_high.
155 */
156 public function testPledgeGetReturnFilters() {
157 $this->callAPISuccess('pledge', 'create', $this->_params);
158
159 $overdueParams = [
160 'scheduled_date' => 'first saturday of march last year',
161 'start_date' => 'first saturday of march last year',
162 ];
163 $oldPledge = $this->callAPISuccess('pledge', 'create', array_merge($this->_params, $overdueParams));
164
165 $pledgeGetParams = [];
166 $allPledges = $this->callAPISuccess('pledge', 'getcount', $pledgeGetParams);
167
168 $this->assertEquals(2, $allPledges, 'Check we have 2 pledges to place with in line ' . __LINE__);
169 $pledgeGetParams['pledge_start_date_high'] = date('YmdHis', strtotime('2 days ago'));
170 $earlyPledge = $this->callAPIAndDocument('pledge', 'get', $pledgeGetParams, __FUNCTION__, __FILE__, "demonstrates high date filter", "GetFilterHighDate");
171 $this->assertEquals(1, $earlyPledge['count'], ' check only one returned with start date filter in line ' . __LINE__);
172 $this->assertEquals($oldPledge['id'], $earlyPledge['id'], ' check correct pledge returned ' . __LINE__);
173 }
174
175 /**
176 * Create 2 pledges - see if we can get by status id.
177 */
178 public function testGetOverduePledge() {
179 $overdueParams = [
180 'scheduled_date' => 'first saturday of march last year',
181 'start_date' => 'first saturday of march last year',
182 ];
183 $this->_pledge = $this->callAPISuccess('pledge', 'create', array_merge($this->_params, $overdueParams));
184
185 $result = $this->callAPISuccess('pledge', 'get', ['status_id' => 'Overdue']);
186 $emptyResult = $this->callAPISuccess('pledge', 'get', [
187 'pledge_status_id' => '1',
188 ]);
189 $pledge = $result['values'][$this->_pledge['id']];
190 $this->callAPISuccess('pledge', 'delete', $pledge);
191 $this->assertEquals(1, $result['count']);
192 $this->assertEquals(0, $emptyResult['count']);
193 }
194
195 /**
196 * Test pledge_status option group
197 */
198 public function testOptionGroupForPledgeStatus() {
199 $pledgeOg = $this->callAPISuccess('OptionGroup', 'get', [
200 'name' => "pledge_status",
201 ]);
202 $this->assertEquals(1, $pledgeOg['count']);
203
204 $pledgeOv = $this->callAPISuccess('OptionValue', 'get', [
205 'sequential' => 1,
206 'option_group_id' => "pledge_status",
207 ]);
208 $this->assertEquals(5, $pledgeOv['count']);
209 $pledgeStatus = CRM_Utils_Array::collect('name', $pledgeOv['values']);
210 $expected = ['Completed', 'Pending', 'Cancelled', 'In Progress', 'Overdue'];
211 $this->assertEquals($expected, $pledgeStatus);
212 }
213
214 /**
215 * Create 2 pledges - see if we can get by status id.
216 */
217 public function testSortParamPledge() {
218 $pledge1 = $this->callAPISuccess('pledge', 'create', $this->_params);
219 $overdueParams = [
220 'scheduled_date' => 'first saturday of march last year',
221 'start_date' => 'first saturday of march last year',
222 'create_date' => 'first saturday of march last year',
223 ];
224 $pledge2 = $this->callAPISuccess('pledge', 'create', array_merge($this->_params, $overdueParams));
225 $params = [
226 'pledge_is_test' => 0,
227 'rowCount' => 1,
228 ];
229 $result = $this->callAPISuccess('pledge', 'get', $params);
230
231 $resultSortedAsc = $this->callAPISuccess('pledge', 'get', [
232 'rowCount' => 1,
233 'sort' => 'start_date ASC',
234 ]);
235 $resultSortedDesc = $this->callAPISuccess('pledge', 'get', [
236 'rowCount' => 1,
237 'sort' => 'start_date DESC',
238 ]);
239
240 $this->assertEquals($pledge1['id'], $result['id'], 'pledge get gets first created pledge in line ' . __LINE__);
241 $this->assertEquals($pledge2['id'], $resultSortedAsc['id'], 'Ascending pledge sort works');
242 $this->assertEquals($pledge1['id'], $resultSortedDesc['id'], 'Decending pledge sort works');
243 $this->callAPISuccess('pledge', 'delete', ['id' => $pledge1['id']]);
244 $this->callAPISuccess('pledge', 'delete', ['id' => $pledge2['id']]);
245 }
246
247 public function testCreatePledge() {
248
249 $result = $this->callAPIAndDocument('pledge', 'create', $this->_params, __FUNCTION__, __FILE__);
250 $this->assertEquals($result['values'][0]['amount'], 100.00);
251 $this->assertEquals($result['values'][0]['installments'], 5);
252 $this->assertEquals($result['values'][0]['frequency_unit'], 'year');
253 $this->assertEquals($result['values'][0]['frequency_interval'], 5);
254 $this->assertEquals($result['values'][0]['frequency_day'], 15);
255 $this->assertEquals($result['values'][0]['original_installment_amount'], 20);
256 $this->assertEquals($result['values'][0]['status_id'], 2);
257 $this->assertEquals($result['values'][0]['create_date'], date('Ymd') . '000000');
258 $this->assertEquals($result['values'][0]['start_date'], date('Ymd') . '000000');
259 $this->assertAPISuccess($result);
260 $payments = $this->callAPISuccess('PledgePayment', 'Get', ['pledge_id' => $result['id'], 'sequential' => 1]);
261 $this->assertAPISuccess($payments);
262 $this->assertEquals($payments['count'], 5);
263 $shouldBeDate = CRM_Utils_Date::format(CRM_Utils_Date::intervalAdd('year', 5 * 4, $this->scheduled_date), "-");
264 $this->assertEquals(substr($shouldBeDate, 0, 10), substr($payments['values'][4]['scheduled_date'], 0, 10));
265
266 $pledgeID = ['id' => $result['id']];
267 $pledge = $this->callAPISuccess('pledge', 'delete', $pledgeID);
268 }
269
270 /**
271 * Test that pledge with weekly schedule calculates dates correctly.
272 */
273 public function testCreatePledgeWeeklySchedule() {
274 $params = [
275 'scheduled_date' => '20110510',
276 'frequency_unit' => 'week',
277 'frequency_day' => 3,
278 'frequency_interval' => 2,
279 ];
280 $params = array_merge($this->_params, $params);
281 $pledge = $this->callAPISuccess('Pledge', 'Create', $params);
282 //ensure that correct number of payments created & last payment has the right date
283 $payments = $this->callAPISuccess('PledgePayment', 'Get', [
284 'pledge_id' => $pledge['id'],
285 'sequential' => 1,
286 ]);
287 $this->assertEquals($payments['count'], 5);
288 $this->assertEquals('2011-07-06 00:00:00', $payments['values'][4]['scheduled_date']);
289
290 $this->callAPISuccess('pledge', 'delete', ['pledge_id' => $pledge['id']]);
291 }
292
293 /**
294 * Test that pledge with weekly schedule calculates dates correctly.
295 */
296 public function testCreatePledgeMontlySchedule() {
297 $params = [
298 'scheduled_date' => '20110510',
299 'frequency_unit' => 'Month',
300 'frequency_day' => 3,
301 'frequency_interval' => 2,
302 ];
303 $params = array_merge($this->_params, $params);
304 $apiResult = $this->callAPISuccess('pledge', 'create', $params);
305 }
306
307 /**
308 * Test creation of pledge with only one payment.
309 *
310 * Pledge status id left empty as it is not a required field
311 * http://issues.civicrm.org/jira/browse/CRM-8551
312 */
313 public function testCreatePledgeSinglePayment() {
314 $params = [
315 'scheduled_date' => '20110510',
316 'frequency_unit' => 'week',
317 'frequency_day' => 3,
318 'frequency_interval' => 2,
319 'installments' => 1,
320 ];
321
322 $params = array_merge($this->_params, $params);
323 unset($params['pledge_status_id']);
324 $pledge = $this->callAPISuccess('Pledge', 'Create', $params);
325 //ensure that correct number of payments created & last payment has the right date
326 $payments = $this->callAPISuccess('PledgePayment', 'Get', [
327 'pledge_id' => $pledge['id'],
328 'sequential' => 1,
329 ]);
330 $this->assertEquals(1, $payments['count']);
331 $this->assertEquals(2, $payments['values'][0]['status_id']);
332 $pledgeID = ['id' => $pledge['id']];
333 $pledge = $this->callAPISuccess('pledge', 'delete', $pledgeID);
334 }
335
336 /**
337 * Test that using original_installment_amount rather than pledge_original_installment_amount works.
338 *
339 * Pledge field behaviour is a bit random & so pledge has come to try to handle both unique & non -unique fields.
340 */
341 public function testCreatePledgeWithNonUnique() {
342 $params = $this->_params;
343 $params['original_installment_amount'] = $params['pledge_original_installment_amount'];
344
345 unset($params['pledge_original_installment_amount']);
346 $result = $this->callAPISuccess('pledge', 'create', $params);
347 $pledgeDetails = $this->callAPISuccess('Pledge', 'Get', ['id' => $result['id'], 'sequential' => 1]);
348 $pledge = $pledgeDetails['values'][0];
349 $this->assertEquals(100.00, $pledge['pledge_amount']);
350 $this->assertEquals('year', $pledge['pledge_frequency_unit']);
351 $this->assertEquals(5, $pledge['pledge_frequency_interval']);
352 $this->assertEquals(20, $pledge['pledge_next_pay_amount']);
353
354 $pledgeID = ['id' => $result['id']];
355 $pledge = $this->callAPISuccess('pledge', 'delete', $pledgeID);
356 }
357
358 /**
359 * Test cancelling a pledge.
360 */
361 public function testCreateCancelPledge() {
362
363 $result = $this->callAPISuccess('pledge', 'create', $this->_params);
364 $this->assertEquals(2, $result['values'][0]['status_id']);
365 $cancelParams = [
366 'sequential' => 1,
367 'id' => $result['id'],
368 'pledge_status_id' => 3,
369 ];
370 $result = $this->callAPISuccess('pledge', 'create', $cancelParams);
371 $this->assertEquals(3, $result['values'][0]['status_id']);
372 $pledgeID = ['id' => $result['id']];
373 $this->callAPISuccess('pledge', 'delete', $pledgeID);
374 }
375
376 /**
377 * Test that status is set to pending.
378 */
379 public function testCreatePledgeNoStatus() {
380
381 $params = $this->_params;
382 unset($params['status_id']);
383 unset($params['pledge_status_id']);
384 $result = $this->callAPISuccess('pledge', 'create', $params);
385 $this->assertAPISuccess($result);
386 $this->assertEquals(2, $result['values'][0]['status_id']);
387 $pledgeID = ['pledge_id' => $result['id']];
388 $pledge = $this->callAPISuccess('pledge', 'delete', $pledgeID);
389 }
390
391 /**
392 * Update Pledge.
393 */
394 public function testCreateUpdatePledge() {
395 // we test 'sequential' param here too
396 $pledgeID = $this->pledgeCreate(['contact_id' => $this->_individualId]);
397 $old_params = [
398 'id' => $pledgeID,
399 'sequential' => 1,
400 ];
401 $original = $this->callAPISuccess('pledge', 'get', $old_params);
402 //Make sure it came back
403 $this->assertEquals($original['values'][0]['pledge_id'], $pledgeID);
404 //set up list of old params, verify
405 $old_contact_id = $original['values'][0]['contact_id'];
406 $old_frequency_unit = $original['values'][0]['pledge_frequency_unit'];
407 $old_frequency_interval = $original['values'][0]['pledge_frequency_interval'];
408 $old_status_id = $original['values'][0]['pledge_status'];
409
410 //check against values in CiviUnitTestCase::createPledge()
411 $this->assertEquals($old_contact_id, $this->_individualId);
412 $this->assertEquals($old_frequency_unit, 'year');
413 $this->assertEquals($old_frequency_interval, 5);
414 $this->assertEquals($old_status_id, 'Pending Label**');
415 $params = [
416 'id' => $pledgeID,
417 'contact_id' => $this->_individualId,
418 'pledge_status_id' => 3,
419 'amount' => 100,
420 'financial_type_id' => 1,
421 'start_date' => date('Ymd'),
422 'installments' => 10,
423 ];
424
425 $pledge = $this->callAPISuccess('pledge', 'create', $params);
426 $new_params = [
427 'id' => $pledge['id'],
428 ];
429 $pledge = $this->callAPISuccess('pledge', 'get', $new_params);
430 $this->assertEquals($pledge['values'][$pledgeID]['contact_id'], $this->_individualId);
431 $this->assertEquals($pledge['values'][$pledgeID]['pledge_status'], 'Cancelled');
432 $pledge = $this->callAPISuccess('pledge', 'delete', $new_params);
433 }
434
435 /**
436 * Here we ensure we are maintaining our 'contract' & supporting previously working syntax.
437 *
438 * ie contribution_type_id.
439 *
440 * We test 'sequential' param here too.
441 */
442 public function testCreateUpdatePledgeLegacy() {
443 $pledgeID = $this->pledgeCreate(['contact_id' => $this->_individualId]);
444 $old_params = [
445 'id' => $pledgeID,
446 'sequential' => 1,
447 ];
448 $original = $this->callAPISuccess('pledge', 'get', $old_params);
449 // Make sure it came back.
450 $this->assertEquals($original['values'][0]['pledge_id'], $pledgeID);
451 // Set up list of old params, verify.
452 $old_contact_id = $original['values'][0]['contact_id'];
453 $old_frequency_unit = $original['values'][0]['pledge_frequency_unit'];
454 $old_frequency_interval = $original['values'][0]['pledge_frequency_interval'];
455 $old_status_id = $original['values'][0]['pledge_status'];
456
457 // Check against values in CiviUnitTestCase::createPledge().
458 $this->assertEquals($old_contact_id, $this->_individualId);
459 $this->assertEquals($old_frequency_unit, 'year');
460 $this->assertEquals($old_frequency_interval, 5);
461 $this->assertEquals($old_status_id, 'Pending Label**');
462 $params = [
463 'id' => $pledgeID,
464 'contact_id' => $this->_individualId,
465 'pledge_status_id' => 3,
466 'amount' => 100,
467 'contribution_type_id' => 1,
468 'start_date' => date('Ymd'),
469 'installments' => 10,
470 ];
471
472 $pledge = $this->callAPISuccess('pledge', 'create', $params);
473 $new_params = [
474 'id' => $pledge['id'],
475 ];
476 $pledge = $this->callAPISuccess('pledge', 'get', $new_params);
477 $this->assertEquals($pledge['values'][$pledgeID]['contact_id'], $this->_individualId);
478 $this->assertEquals($pledge['values'][$pledgeID]['pledge_status'], 'Cancelled');
479 $this->callAPISuccess('pledge', 'delete', $new_params);
480 }
481
482 /**
483 * Failure test for delete without id.
484 */
485 public function testDeleteEmptyParamsPledge() {
486 $this->callAPIFailure('pledge', 'delete', [], 'Mandatory key(s) missing from params array: id');
487 }
488
489 /**
490 * Failure test for invalid pledge id.
491 */
492 public function testDeleteWrongParamPledge() {
493 $params = [
494 'pledge_source' => 'SSF',
495 ];
496 $this->callAPIFailure('pledge', 'delete', $params, 'Mandatory key(s) missing from params array: id');
497 }
498
499 /**
500 * Legacy support for pledge_id.
501 */
502 public function testDeletePledge() {
503
504 $pledgeID = $this->pledgeCreate(['contact_id' => $this->_individualId]);
505 $params = [
506 'pledge_id' => $pledgeID,
507 ];
508 $this->callAPIAndDocument('pledge', 'delete', $params, __FUNCTION__, __FILE__);
509 }
510
511 /**
512 * Standard is to accept id.
513 */
514 public function testDeletePledgeUseID() {
515
516 $pledgeID = $this->pledgeCreate(['contact_id' => $this->_individualId]);
517 $params = [
518 'id' => $pledgeID,
519 ];
520 $this->callAPIAndDocument('pledge', 'delete', $params, __FUNCTION__, __FILE__);
521 }
522
523 /**
524 * Test to make sure empty get returns nothing.
525 *
526 * Note that the function gives incorrect results if no pledges exist as it does a
527 * contact search instead - test only checks that the get finds the one existing
528 */
529 public function testGetEmpty() {
530 $this->callAPISuccess('pledge', 'create', $this->_params);
531 $result = $this->callAPISuccess('pledge', 'get', []);
532 $this->assertAPISuccess($result, "This test is failing because it's acting like a contact get when no params set. Not sure the fix");
533 $this->assertEquals(1, $result['count']);
534 $pledgeID = ['id' => $result['id']];
535 $this->callAPISuccess('pledge', 'delete', $pledgeID);
536 }
537
538 }