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