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