Merge branch '5.11' of https://github.com/civicrm/civicrm-core
[civicrm-core.git] / tests / phpunit / api / v3 / PledgePaymentTest.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
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_PledgePaymentTest extends CiviUnitTestCase {
35
36 /**
37 * Assume empty database with just civicrm_data.
38 */
39 protected $_individualId;
40 protected $_pledgeID;
41 protected $_apiversion = 3;
42 protected $_contributionID;
43 protected $_financialTypeId = 1;
44 protected $_entity = 'PledgePayment';
45 public $DBResetRequired = TRUE;
46
47 public function setUp() {
48 parent::setUp();
49 $this->_individualId = $this->individualCreate();
50 $this->_pledgeID = $this->pledgeCreate(array('contact_id' => $this->_individualId));
51 $this->_contributionID = $this->contributionCreate(array('contact_id' => $this->_individualId));
52 }
53
54 public function tearDown() {
55 $tablesToTruncate = array(
56 'civicrm_contribution',
57 'civicrm_contact',
58 'civicrm_pledge',
59 'civicrm_pledge_payment',
60 'civicrm_line_item',
61 );
62
63 $this->quickCleanup($tablesToTruncate);
64 }
65
66 public function testGetPledgePayment() {
67 $params = array();
68 $result = $this->callAPIAndDocument('pledge_payment', 'get', $params, __FUNCTION__, __FILE__);
69 $this->assertEquals(5, $result['count'], " in line " . __LINE__);
70 }
71
72 /**
73 * Test that passing in a single variable works.
74 */
75 public function testGetSinglePledgePayment() {
76 $createparams = array(
77 'contact_id' => $this->_individualId,
78 'pledge_id' => $this->_pledgeID,
79 'contribution_id' => $this->_contributionID,
80 'status_id' => 1,
81 );
82 $createResult = $this->callAPISuccess('pledge_payment', 'create', $createparams);
83 $params = array(
84 'contribution_id' => $this->_contributionID,
85 );
86 $result = $this->callAPISuccess('pledge_payment', 'get', $params);
87 $this->assertEquals(1, $result['count'], " in line " . __LINE__);
88 }
89
90 /**
91 * Test process_pledge job log.
92 */
93 public function testProcessPledgeJob() {
94 $pledgeStatuses = CRM_Core_OptionGroup::values('pledge_status',
95 FALSE, FALSE, FALSE, NULL, 'name'
96 );
97 //Make first payment.
98 $paymentParams = array(
99 'contact_id' => $this->_individualId,
100 'pledge_id' => $this->_pledgeID,
101 'contribution_id' => $this->_contributionID,
102 'scheduled_date' => date('Ymd', strtotime("-1 days")),
103 'status_id' => array_search('Pending', $pledgeStatuses),
104 );
105 $firstPayment = $this->callAPISuccess('pledge_payment', 'create', $paymentParams);
106 //Status should be 'Pending' after first incomplete payment.
107 $checkStatus = $this->callAPISuccess('pledge', 'getsingle', array(
108 'id' => $this->_pledgeID,
109 'return' => 'pledge_status',
110 ));
111 $this->assertEquals('Pending', $checkStatus['pledge_status']);
112
113 //Execute process_pledge job log.
114 $result = $this->callAPISuccess('Job', 'process_pledge', array());
115 $this->assertEquals("Checking if status update is needed for Pledge Id: {$this->_pledgeID} (current status is Pending)\n\r- status updated to: Overdue\n\r1 records updated.", $result['values']);
116
117 //Status should be 'Overdue' after processing.
118 $statusAfterProcessing = $this->callAPISuccess('pledge', 'getsingle', array(
119 'id' => $this->_pledgeID,
120 'return' => 'pledge_status',
121 ));
122 $this->assertEquals('Overdue', $statusAfterProcessing['pledge_status']);
123 }
124
125 /**
126 * Test status of pledge on payments and cancellation.
127 */
128 public function testPledgeStatus() {
129 //Status should initially be Pending.
130 $checkStatus = $this->callAPISuccess('pledge', 'getsingle', array(
131 'id' => $this->_pledgeID,
132 'return' => 'pledge_status',
133 ));
134 $this->assertEquals('Pending', $checkStatus['pledge_status']);
135
136 //Make first payment.
137 $paymentParams = array(
138 'contact_id' => $this->_individualId,
139 'pledge_id' => $this->_pledgeID,
140 'contribution_id' => $this->_contributionID,
141 'status_id' => 1,
142 );
143 $firstPayment = $this->callAPISuccess('pledge_payment', 'create', $paymentParams);
144
145 //Status should be 'In Progress' after first payment.
146 $checkStatus = $this->callAPISuccess('pledge', 'getsingle', array(
147 'id' => $this->_pledgeID,
148 'return' => 'pledge_status',
149 ));
150 $this->assertEquals('In Progress', $checkStatus['pledge_status']);
151
152 //Cancel the Pledge.
153 $paymentStatusTypes = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
154 $updateParams = array(
155 'id' => $this->_pledgeID,
156 'status_id' => array_search('Cancelled', $paymentStatusTypes),
157 );
158 $this->callAPISuccess('pledge', 'create', $updateParams);
159
160 //Status should be calculated as Cancelled.
161 $pledgeStatus = CRM_Pledge_BAO_PledgePayment::calculatePledgeStatus($this->_pledgeID);
162 $this->assertEquals('Cancelled', $paymentStatusTypes[$pledgeStatus]);
163
164 //Already completed payments should not be cancelled.
165 $checkPaymentStatus = $this->callAPISuccess('pledge_payment', 'getsingle', array(
166 'id' => $firstPayment['id'],
167 'return' => 'status_id',
168 ));
169 $this->assertEquals(array_search('Completed', $paymentStatusTypes), $checkPaymentStatus['status_id']);
170 }
171
172
173 /**
174 * Test that passing in a single variable works:: status_id
175 */
176 public function testGetSinglePledgePaymentByStatusID() {
177 $createparams = array(
178 'contact_id' => $this->_individualId,
179 'pledge_id' => $this->_pledgeID,
180 'contribution_id' => $this->_contributionID,
181 'status_id' => 1,
182 );
183 $createResult = $this->callAPISuccess('pledge_payment', 'create', $createparams);
184 $params = array(
185 'status_id' => 1,
186 );
187
188 $result = $this->callAPISuccess('pledge_payment', 'get', $params);
189 $this->assertEquals(1, $result['count'], " in line " . __LINE__);
190 }
191
192 /**
193 * Test that creating a payment will add the contribution ID.
194 */
195 public function testCreatePledgePayment() {
196 //check that 5 pledge payments exist at the start
197 $beforeAdd = $this->callAPISuccess('pledge_payment', 'get', array());
198 $this->assertEquals(5, $beforeAdd['count'], " in line " . __LINE__);
199
200 //test the pledge_payment_create function
201 $params = array(
202 'contact_id' => $this->_individualId,
203 'pledge_id' => $this->_pledgeID,
204 'contribution_id' => $this->_contributionID,
205 'status_id' => 1,
206 'actual_amount' => 20,
207 );
208 $result = $this->callAPIAndDocument('pledge_payment', 'create', $params, __FUNCTION__, __FILE__);
209
210 //check existing updated not new one created - 'create' means add contribution_id in this context
211 $afterAdd = $this->callAPISuccess('pledge_payment', 'get', array());
212 $this->assertEquals(5, $afterAdd['count'], " in line " . __LINE__);
213
214 //get the created payment & check it out
215 $getParams['id'] = $result['id'];
216 $getIndPayment = $this->callAPISuccess('pledge_payment', 'get', $getParams);
217 $this->assertEquals(1, $getIndPayment['count'], " in line " . __LINE__);
218 $this->assertEquals(20, $getIndPayment['values'][$result['id']]['actual_amount'], " in line " . __LINE__);
219
220 //create a second pledge payment - need a contribution first &can't use the CiviUnitTest case function as invoice is hard-coded
221 $contributionParams = array(
222 'total_amount' => 20,
223 'contact_id' => $this->_individualId,
224 'financial_type_id' => $this->_financialTypeId,
225 );
226 $contribution = $this->callAPISuccess('contribution', 'create', $contributionParams);
227 $params['contribution_id'] = $contribution['id'];
228
229 $resultCont2 = $this->callAPISuccess('pledge_payment', 'create', $params);
230 //make sure original is untouched & has not been updated
231 $this->assertGreaterThan($result['id'], $resultCont2['id'], " in line " . __LINE__);
232 $getIndPaymentAgain = $this->callAPISuccess('pledge_payment', 'get', $getParams);
233 $this->assertEquals(1, $getIndPaymentAgain['count'], " in line " . __LINE__);
234 $this->assertEquals($this->_contributionID, $getIndPaymentAgain['values'][$result['id']]['contribution_id'], " in line " . __LINE__);
235 }
236
237 /**
238 * Test checks behaviour when more payments are created than should be possible.
239 */
240 public function testCreatePledgePaymentAllCreated() {
241 $params = array(
242 'pledge_id' => $this->_pledgeID,
243 'status_id' => 1,
244 );
245 // create one more pledge than there are spaces for
246 $i = 0;
247 while ($i <= 5) {
248 $contributionParams = array(
249 'total_amount' => 20,
250 'contact_id' => $this->_individualId,
251 'financial_type_id' => $this->_financialTypeId,
252 );
253 $contribution = $this->callAPISuccess('contribution', 'create', $contributionParams);
254
255 $params['contribution_id'] = $contribution['id'];
256
257 $resultCont2 = civicrm_api('pledge_payment', 'create', $params + array('version' => $this->_apiversion));
258 $i++;
259 }
260 // check that only 5 exist & we got an error setting the 6th
261 $result = $this->callAPISuccess('PledgePayment', 'Get', array(
262 'pledge_id' => $this->_pledgeID,
263 ));
264 // the last one above should result in an error
265 $this->assertEquals("There are no unmatched payment on this pledge. Pass in the pledge_payment id to specify one or 'option.create_new' to create one", $resultCont2['error_message']);
266 $this->assertEquals(5, $result['count']);
267
268 $params['option.create_new'] = 1;
269 $params['scheduled_amount'] = 20;
270 $params['scheduled_date'] = '20131212';
271 $resultcreatenew = $this->callAPISuccess('pledge_payment', 'create', $params);
272 $result = $this->callAPISuccess('PledgePayment', 'Get', array(
273 'pledge_id' => $this->_pledgeID,
274 ));
275
276 $this->assertEquals(6, $result['count']);
277 }
278
279 /**
280 * Test that creating a payment adds the contribution ID where only one pledge payment is in schedule.
281 */
282 public function testCreatePledgePaymentWhereOnlyOnePayment() {
283 $pledgeParams = array(
284 'contact_id' => $this->_individualId,
285 'pledge_create_date' => date('Ymd'),
286 'start_date' => date('Ymd'),
287 'scheduled_date' => 'first day 2015',
288 'pledge_amount' => 100.00,
289 'pledge_status_id' => '2',
290 'pledge_financial_type_id' => '1',
291 'pledge_original_installment_amount' => 20,
292 'frequency_interval' => 5,
293 'frequency_unit' => 'year',
294 'frequency_day' => 15,
295 'installments' => 1,
296 'sequential' => 1,
297 );
298
299 $contributionID = $this->contributionCreate(array(
300 'contact_id' => $this->_individualId,
301 'financial_type_id' => $this->_financialTypeId,
302 'invoice_id' => 45,
303 'trxn_id' => 45,
304 ));
305 $pledge = $this->callAPISuccess('Pledge', 'Create', $pledgeParams);
306
307 //test the pledge_payment_create function
308 $params = array(
309 'contact_id' => $this->_individualId,
310 'pledge_id' => $pledge['id'],
311 'contribution_id' => $contributionID,
312 'status_id' => 1,
313 'actual_amount' => 20,
314 );
315 $result = $this->callAPISuccess('pledge_payment', 'create', $params);
316
317 //check existing updated not new one created - 'create' means add contribution_id in this context
318 $afterAdd = $this->callAPISuccess('pledge_payment', 'get', array(
319 'contribution_id' => $contributionID,
320 ));
321 $this->assertEquals(1, $afterAdd['count'], " in line " . __LINE__);
322 }
323
324 public function testUpdatePledgePayment() {
325 $params = array(
326 'pledge_id' => $this->_pledgeID,
327 'contribution_id' => $this->_contributionID,
328 'status_id' => 2,
329 'actual_amount' => 20,
330 );
331 $result = $this->callAPISuccess('pledge_payment', 'create', $params);
332 $updateparams = array(
333 'id' => $result['id'],
334 'status_id' => 1,
335 );
336
337 $result = $this->callAPIAndDocument('pledge_payment', 'update', $updateparams, __FUNCTION__, __FILE__);
338 $this->getAndCheck(array_merge($params, $updateparams), $result['id'], $this->_entity);
339 }
340
341 public function testDeletePledgePayment() {
342 $params = array(
343 'contact_id' => $this->_individualId,
344 'pledge_id' => $this->_pledgeID,
345 'contribution_id' => $this->_contributionID,
346 'status_id' => 1,
347 'sequential' => 1,
348 'actual_amount' => 20,
349 );
350 $pledgePayment = $this->callAPISuccess('pledge_payment', 'create', $params);
351
352 $deleteParams = array(
353 'id' => $pledgePayment['id'],
354 );
355 $result = $this->callAPIAndDocument('pledge_payment', 'delete', $deleteParams, __FUNCTION__, __FILE__);
356 }
357
358 public function testGetFields() {
359 $result = $this->callAPISuccess('PledgePayment', 'GetFields', array());
360 $this->assertType('array', $result);
361 }
362
363 }