9bbf4dda1a11634267dcd86167c2e39f5417bdd4
[civicrm-core.git] / tests / phpunit / CRM / Contribute / Form / SearchTest.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 * Include parent class definition
30 */
31
32 /**
33 * Test Contribution Search form filters
34 *
35 * @package CiviCRM
36 */
37 class CRM_Contribute_Form_SearchTest extends CiviUnitTestCase {
38
39 protected $_individual;
40 protected $_tablesToTruncate = array('civicrm_contribution', 'civicrm_line_item');
41
42 public function setUp() {
43 parent::setUp();
44 $this->_individual = $this->individualCreate();
45 }
46
47 public function tearDown() {
48 }
49
50 /**
51 * CRM-19325: Test CRM_Contribute_Form_Search batch filters
52 */
53 public function testBatchFilter() {
54 $this->quickCleanup($this->_tablesToTruncate);
55 $contactID1 = $this->individualCreate(array(), 1);
56 $contactID2 = $this->individualCreate(array(), 2);
57 $batchTitle = CRM_Batch_BAO_Batch::generateBatchName();
58
59 // create batch
60 $batch = $this->callAPISuccess('Batch', 'create', array(
61 'created_id' => $this->_individual,
62 'created_date' => CRM_Utils_Date::processDate(date("Y-m-d"), date("H:i:s")),
63 'status_id' => CRM_Core_Pseudoconstant::getKey('CRM_Batch_BAO_Batch', 'status_id', 'Data Entry'),
64 'title' => $batchTitle,
65 'item_count' => 2,
66 'total' => 100,
67 'type_id' => array_search('Contribution', CRM_Batch_BAO_Batch::buildOptions('type_id')),
68 ));
69 $batchID = $batch['id'];
70
71 $batchEntry = array(
72 'primary_profiles' => array(1 => NULL, 2 => NULL, 3 => NULL),
73 'primary_contact_id' => array(
74 1 => $contactID1,
75 2 => $contactID2,
76 ),
77 'field' => array(
78 1 => array(
79 'financial_type' => 1,
80 'total_amount' => 70,
81 'receive_date' => '2013-07-24',
82 'receive_date_time' => NULL,
83 'payment_instrument' => 1,
84 'check_number' => NULL,
85 'contribution_status_id' => 1,
86 ),
87 2 => array(
88 'financial_type' => 1,
89 'total_amount' => 30,
90 'receive_date' => '2014-07-24',
91 'receive_date_time' => NULL,
92 'payment_instrument' => 1,
93 'check_number' => NULL,
94 'contribution_status_id' => 1,
95 ),
96 ),
97 'actualBatchTotal' => 100,
98 );
99
100 // create random contribution to check IS NULL filter more precisely
101 $nonBatchContri = $this->callAPISuccess('Contribution', 'create', array(
102 'financial_type_id' => 1,
103 'total_amount' => 123,
104 'receive_date' => '2014-07-24',
105 'receive_date_time' => NULL,
106 'payment_instrument' => 1,
107 'check_number' => NULL,
108 'contribution_status_id' => 1,
109 'contact_id' => $this->_individual,
110 ));
111 $nonBatchContriID = $nonBatchContri['id'];
112
113 // process batch entries
114 $form = new CRM_Batch_Form_Entry();
115 $form->setBatchID($batchID);
116 $form->testProcessContribution($batchEntry);
117
118 // fetch created contributions
119 $entities = $this->callAPISuccess('EntityBatch', 'get', array('batch_id' => $batchID));
120 $ids = array();
121 foreach ($entities['values'] as $value) {
122 $ids[] = $value['entity_id'];
123 }
124 list($batchContriID1, $batchContriID2) = $ids;
125
126 $useCases = array(
127 // Case 1: Search for ONLY those contributions which are created from batch
128 array(
129 'form_value' => array('contribution_batch_id' => 'IS NOT NULL'),
130 'expected_count' => 2,
131 'expected_contribution' => array($batchContriID1, $batchContriID2),
132 'expected_qill' => 'Batch Name Not Null',
133 ),
134 // Case 2: Search for ONLY those contributions which are NOT created from batch
135 array(
136 'form_value' => array('contribution_batch_id' => 'IS NULL'),
137 'expected_count' => 1,
138 'expected_contribution' => array($nonBatchContriID),
139 'expected_qill' => 'Batch Name Is Null',
140 ),
141 // Case 3: Search for ONLY those contributions which are created from batch ID - $batchID
142 array(
143 'form_value' => array('contribution_batch_id' => $batchID),
144 'expected_count' => 2,
145 'expected_contribution' => array($batchContriID1, $batchContriID2),
146 'expected_qill' => 'Batch Name = ' . $batchTitle,
147 ),
148 );
149 foreach ($useCases as $case) {
150 $fv = $case['form_value'];
151 CRM_Contact_BAO_Query::processSpecialFormValue($fv, array('contribution_batch_id'));
152 $query = new CRM_Contact_BAO_Query(CRM_Contact_BAO_Query::convertFormValues($fv));
153 list($select, $from, $where, $having) = $query->query();
154
155 // get and assert contribution count
156 $contributions = CRM_Core_DAO::executeQuery(sprintf('SELECT DISTINCT civicrm_contribution.id %s %s AND civicrm_contribution.id IS NOT NULL', $from, $where))->fetchAll();
157 foreach ($contributions as $key => $value) {
158 $contributions[$key] = $value['id'];
159 }
160 // assert the contribution count
161 $this->assertEquals($case['expected_count'], count($contributions));
162 // assert the contribution IDs
163 $this->checkArrayEquals($case['expected_contribution'], $contributions);
164 // get and assert qill string
165 $qill = trim(implode($query->getOperator(), CRM_Utils_Array::value(0, $query->qill())));
166 $this->assertEquals($case['expected_qill'], $qill);
167 }
168 }
169
170 /**
171 * CRM-20286: Test CRM_Contribute_Form_Search Card type filters
172 */
173 public function testCardTypeFilter() {
174 $this->quickCleanup($this->_tablesToTruncate);
175 $contactID1 = $this->individualCreate(array(), 1);
176 $contactID2 = $this->individualCreate(array(), 2);
177 $Contribution1 = $this->callAPISuccess('Contribution', 'create', array(
178 'financial_type_id' => 1,
179 'total_amount' => 100,
180 'receive_date' => date('Ymd'),
181 'receive_date_time' => NULL,
182 'payment_instrument' => 1,
183 'contribution_status_id' => 1,
184 'contact_id' => $contactID1,
185 ));
186 $params = array(
187 'to_financial_account_id' => 1,
188 'status_id' => 1,
189 'contribution_id' => $Contribution1['id'],
190 'payment_instrument_id' => 1,
191 'card_type_id' => 1,
192 'total_amount' => 100,
193 );
194 CRM_Core_BAO_FinancialTrxn::create($params);
195 $Contribution2 = $this->callAPISuccess('Contribution', 'create', array(
196 'financial_type_id' => 1,
197 'total_amount' => 150,
198 'receive_date' => date('Ymd'),
199 'receive_date_time' => NULL,
200 'payment_instrument' => 1,
201 'contribution_status_id' => 1,
202 'contact_id' => $contactID1,
203 ));
204 $Contribution3 = $this->callAPISuccess('Contribution', 'create', array(
205 'financial_type_id' => 1,
206 'total_amount' => 200,
207 'receive_date' => date('Ymd'),
208 'receive_date_time' => NULL,
209 'payment_instrument' => 1,
210 'contribution_status_id' => 1,
211 'contact_id' => $contactID2,
212 ));
213 $params = array(
214 'to_financial_account_id' => 1,
215 'status_id' => 1,
216 'contribution_id' => $Contribution3['id'],
217 'payment_instrument_id' => 1,
218 'card_type_id' => 2,
219 'total_amount' => 200,
220 );
221 CRM_Core_BAO_FinancialTrxn::create($params);
222
223 $useCases = array(
224 // Case 1: Search for ONLY those contributions which have card type
225 array(
226 'form_value' => array('financial_trxn_card_type_id' => 'IS NOT NULL'),
227 'expected_count' => 2,
228 'expected_contribution' => array($Contribution1['id'], $Contribution3['id']),
229 'expected_qill' => 'Card Type Not Null',
230 ),
231 // Case 2: Search for ONLY those contributions which have Card Type as Visa
232 array(
233 'form_value' => array('financial_trxn_card_type_id' => array(1)),
234 'expected_count' => 1,
235 'expected_contribution' => array($Contribution1['id']),
236 'expected_qill' => 'Card Type In Visa',
237 ),
238 // Case 3: Search for ONLY those contributions which have Card Type as Amex
239 array(
240 'form_value' => array('financial_trxn_card_type_id' => array(3)),
241 'expected_count' => 0,
242 'expected_contribution' => array(),
243 'expected_qill' => 'Card Type In Amex',
244 ),
245 // Case 4: Search for ONLY those contributions which have Card Type as Visa or MasterCard
246 array(
247 'form_value' => array('financial_trxn_card_type_id' => array(1, 2)),
248 'expected_count' => 2,
249 'expected_contribution' => array($Contribution1['id'], $Contribution3['id']),
250 'expected_qill' => 'Card Type In Visa, MasterCard',
251 ),
252 );
253
254 foreach ($useCases as $case) {
255 $fv = $case['form_value'];
256 CRM_Contact_BAO_Query::processSpecialFormValue($fv, array('financial_trxn_card_type_id'));
257 $query = new CRM_Contact_BAO_Query(CRM_Contact_BAO_Query::convertFormValues($fv));
258 list($select, $from, $where, $having) = $query->query();
259
260 // get and assert contribution count
261 $contributions = CRM_Core_DAO::executeQuery(sprintf('SELECT DISTINCT civicrm_contribution.id %s %s AND civicrm_contribution.id IS NOT NULL', $from, $where))->fetchAll();
262 foreach ($contributions as $key => $value) {
263 $contributions[$key] = $value['id'];
264 }
265 // assert the contribution count
266 //$this->assertEquals($case['expected_count'], count($contributions));
267 // assert the contribution IDs
268 $this->checkArrayEquals($case['expected_contribution'], $contributions);
269 // get and assert qill string
270 $qill = trim(implode($query->getOperator(), CRM_Utils_Array::value(0, $query->qill())));
271 $this->assertEquals($case['expected_qill'], $qill);
272 }
273 }
274
275 /**
276 * CRM-20391: Test CRM_Contribute_Form_Search Card Number filters
277 */
278 public function testCardNumberFilter() {
279 $this->quickCleanup($this->_tablesToTruncate);
280 $contactID1 = $this->individualCreate(array(), 1);
281 $contactID2 = $this->individualCreate(array(), 2);
282 $Contribution1 = $this->callAPISuccess('Contribution', 'create', array(
283 'financial_type_id' => 1,
284 'total_amount' => 100,
285 'receive_date' => date('Ymd'),
286 'receive_date_time' => NULL,
287 'payment_instrument' => 1,
288 'contribution_status_id' => 1,
289 'contact_id' => $contactID1,
290 ));
291 $params = array(
292 'to_financial_account_id' => 1,
293 'status_id' => 1,
294 'contribution_id' => $Contribution1['id'],
295 'payment_instrument_id' => 1,
296 'card_type_id' => 1,
297 'total_amount' => 100,
298 'pan_truncation' => 1234,
299 );
300 CRM_Core_BAO_FinancialTrxn::create($params);
301 $Contribution2 = $this->callAPISuccess('Contribution', 'create', array(
302 'financial_type_id' => 1,
303 'total_amount' => 150,
304 'receive_date' => date('Ymd'),
305 'receive_date_time' => NULL,
306 'payment_instrument' => 1,
307 'contribution_status_id' => 1,
308 'contact_id' => $contactID1,
309 ));
310 $Contribution3 = $this->callAPISuccess('Contribution', 'create', array(
311 'financial_type_id' => 1,
312 'total_amount' => 200,
313 'receive_date' => date('Ymd'),
314 'receive_date_time' => NULL,
315 'payment_instrument' => 1,
316 'contribution_status_id' => 1,
317 'contact_id' => $contactID2,
318 ));
319 $params = array(
320 'to_financial_account_id' => 1,
321 'status_id' => 1,
322 'contribution_id' => $Contribution3['id'],
323 'payment_instrument_id' => 1,
324 'card_type_id' => 2,
325 'total_amount' => 200,
326 'pan_truncation' => 5678,
327 );
328 CRM_Core_BAO_FinancialTrxn::create($params);
329
330 $useCases = array(
331 // Case 1: Search for ONLY those contributions which have card number
332 array(
333 'form_value' => array('financial_trxn_pan_truncation' => 'IS NOT NULL'),
334 'expected_count' => 2,
335 'expected_contribution' => array($Contribution1['id'], $Contribution3['id']),
336 'expected_qill' => 'Card Number Not Null',
337 ),
338 // Case 2: Search for ONLY those contributions which have Card Number as 1234
339 array(
340 'form_value' => array('financial_trxn_pan_truncation' => 1234),
341 'expected_count' => 1,
342 'expected_contribution' => array($Contribution1['id']),
343 'expected_qill' => 'Card Number Like %1234%',
344 ),
345 // Case 3: Search for ONLY those contributions which have Card Number as 8888
346 array(
347 'form_value' => array('financial_trxn_pan_truncation' => 8888),
348 'expected_count' => 0,
349 'expected_contribution' => array(),
350 'expected_qill' => 'Card Number Like %8888%',
351 ),
352 );
353
354 foreach ($useCases as $case) {
355 $fv = $case['form_value'];
356 CRM_Contact_BAO_Query::processSpecialFormValue($fv, array('financial_trxn_pan_truncation'));
357 $query = new CRM_Contact_BAO_Query(CRM_Contact_BAO_Query::convertFormValues($fv));
358 list($select, $from, $where, $having) = $query->query();
359
360 // get and assert contribution count
361 $contributions = CRM_Core_DAO::executeQuery(sprintf('SELECT DISTINCT civicrm_contribution.id %s %s AND civicrm_contribution.id IS NOT NULL', $from, $where))->fetchAll();
362 foreach ($contributions as $key => $value) {
363 $contributions[$key] = $value['id'];
364 }
365 // assert the contribution count
366 $this->assertEquals($case['expected_count'], count($contributions));
367 // assert the contribution IDs
368 $this->checkArrayEquals($case['expected_contribution'], $contributions);
369 // get and assert qill string
370 $qill = trim(implode($query->getOperator(), CRM_Utils_Array::value(0, $query->qill())));
371 $this->assertEquals($case['expected_qill'], $qill);
372 }
373 }
374
375 /**
376 * Test CRM_Contribute_Form_Search Recurring Contribution Status Id filters
377 */
378 public function testContributionRecurStatusFilter() {
379 $this->quickCleanup($this->_tablesToTruncate);
380 $contactID1 = $this->individualCreate(array(), 1);
381 $contactID2 = $this->individualCreate(array(), 2);
382 // "In Progress" recurring contribution for contactID1
383 $ContributionRecur1 = $this->callAPISuccess('ContributionRecur', 'create', array(
384 'sequential' => 1,
385 'contact_id' => $contactID1,
386 'frequency_interval' => 1,
387 'frequency_unit' => "month",
388 'amount' => 11,
389 'currency' => "CAD",
390 'payment_instrument_id' => 1,
391 'contribution_status_id' => 5,
392 'financial_type_id' => "Donation",
393 ));
394 $Contribution1 = $this->callAPISuccess('Contribution', 'create', array(
395 'financial_type_id' => 1,
396 'total_amount' => 11,
397 'receive_date' => date('Ymd'),
398 'receive_date_time' => NULL,
399 'payment_instrument_id' => 1,
400 'contribution_status_id' => 1,
401 'contact_id' => $contactID1,
402 'contribution_recur_id' => $ContributionRecur1['id'],
403 'financial_type_id' => "Donation",
404 ));
405 $params = array(
406 'to_financial_account_id' => 1,
407 'status_id' => 1,
408 'contribution_id' => $Contribution1['id'],
409 'payment_instrument_id' => 1,
410 'card_type_id' => 1,
411 'total_amount' => 11,
412 );
413 CRM_Core_BAO_FinancialTrxn::create($params);
414 // "Completed" recurring contribution for contactID2
415 $ContributionRecur2 = $this->callAPISuccess('ContributionRecur', 'create', array(
416 'sequential' => 1,
417 'contact_id' => $contactID2,
418 'frequency_interval' => 1,
419 'frequency_unit' => "month",
420 'amount' => 22,
421 'currency' => "CAD",
422 'payment_instrument_id' => 1,
423 'contribution_status_id' => 1,
424 'financial_type_id' => "Donation",
425 ));
426 $Contribution2 = $this->callAPISuccess('Contribution', 'create', array(
427 'financial_type_id' => 1,
428 'total_amount' => 22,
429 'receive_date' => date('Ymd'),
430 'receive_date_time' => NULL,
431 'payment_instrument' => 1,
432 'contribution_status_id' => 1,
433 'contact_id' => $contactID2,
434 'contribution_recur_id' => $ContributionRecur2['id'],
435 'financial_type_id' => "Donation",
436 ));
437 $params = array(
438 'to_financial_account_id' => 1,
439 'status_id' => 1,
440 'contribution_id' => $Contribution2['id'],
441 'payment_instrument_id' => 1,
442 'card_type_id' => 1,
443 'total_amount' => 22,
444 );
445 CRM_Core_BAO_FinancialTrxn::create($params);
446
447 $useCases = array(
448 // Case 1: Search for ONLY those recurring contributions with status "In Progress"
449 array(
450 'form_value' => array('contribution_recur_contribution_status_id' => 5),
451 'expected_count' => 1,
452 'expected_contact' => array($contactID1),
453 'expected_qill' => "Recurring Contribution Status = 'In Progress'",
454 ),
455 // Case 2: Search for ONLY those recurring contributions with status "Completed"
456 array(
457 'form_value' => array('contribution_recur_contribution_status_id' => 1),
458 'expected_count' => 1,
459 'expected_contact' => array($contactID2),
460 'expected_qill' => "Recurring Contribution Status = 'Completed'",
461 ),
462 // Case 3: Search for ONLY those recurring contributions with status "Cancelled"
463 array(
464 'form_value' => array('contribution_recur_contribution_status_id' => 3),
465 'expected_count' => 0,
466 'expected_contact' => array(),
467 'expected_qill' => "Recurring Contribution Status = 'Cancelled'",
468 ),
469 );
470
471 foreach ($useCases as $case) {
472 $fv = $case['form_value'];
473 $query = new CRM_Contact_BAO_Query(CRM_Contact_BAO_Query::convertFormValues($fv));
474 list($select, $from, $where, $having) = $query->query();
475
476 // get and assert contribution count
477 $contacts = CRM_Core_DAO::executeQuery(sprintf('SELECT DISTINCT contact_a.id %s %s AND contact_a.id IS NOT NULL', $from, $where))->fetchAll();
478 foreach ($contacts as $key => $value) {
479 $contacts[$key] = $value['id'];
480 }
481 // assert the contribution count
482 $this->assertEquals($case['expected_count'], count($contacts));
483 // assert the contribution IDs
484 $this->checkArrayEquals($case['expected_contact'], $contacts);
485 // get and assert qill string
486 $qill = trim(implode($query->getOperator(), CRM_Utils_Array::value(0, $query->qill())));
487 $this->assertEquals($case['expected_qill'], $qill);
488 }
489 }
490
491 /**
492 * CRM-21343: Test CRM_Contribute_Form_Search Cancelled filters
493 */
494 public function testCancelledFilter() {
495 $this->quickCleanup($this->_tablesToTruncate);
496 $contactID1 = $this->individualCreate(array(), 1);
497 $contactID2 = $this->individualCreate(array(), 2);
498 $Contribution1 = $this->callAPISuccess('Contribution', 'create', array(
499 'financial_type_id' => 1,
500 'total_amount' => 100,
501 'receive_date' => date('Ymd'),
502 'receive_date_time' => NULL,
503 'payment_instrument' => 1,
504 'contribution_status_id' => 3,
505 'cancel_date' => date('Ymd'),
506 'cancel_reason' => 'Insufficient funds',
507 'contact_id' => $contactID1,
508 ));
509 $Contribution2 = $this->callAPISuccess('Contribution', 'create', array(
510 'financial_type_id' => 1,
511 'total_amount' => 150,
512 'receive_date' => date('Ymd', strtotime(date('Y-m-d') . ' - 1 days')),
513 'receive_date_time' => NULL,
514 'payment_instrument' => 1,
515 'contribution_status_id' => 3,
516 'cancel_date' => date('Ymd', strtotime(date('Y-m-d') . ' - 1 days')),
517 'cancel_reason' => 'Insufficient funds',
518 'contact_id' => $contactID2,
519 ));
520 $Contribution3 = $this->callAPISuccess('Contribution', 'create', array(
521 'financial_type_id' => 1,
522 'total_amount' => 200,
523 'receive_date' => date('Ymd'),
524 'receive_date_time' => NULL,
525 'payment_instrument' => 1,
526 'contribution_status_id' => 3,
527 'cancel_date' => date('Ymd'),
528 'cancel_reason' => 'Invalid Credit Card Number',
529 'contact_id' => $contactID1,
530 ));
531
532 $useCases = array(
533 // Case 1: Search for Cancelled Date
534 array(
535 'form_value' => array('cancel_date' => date('Y-m-d')),
536 'expected_count' => 2,
537 'expected_contribution' => array($Contribution1['id'], $Contribution3['id']),
538 'expected_qill' => "Cancel Date Like '%" . date('Y-m-d') . "%'",
539 ),
540 // Case 2: Search for Cancelled Reason
541 array(
542 'form_value' => array('cancel_reason' => 'Invalid Credit Card Number'),
543 'expected_count' => 1,
544 'expected_contribution' => array($Contribution3['id']),
545 'expected_qill' => "Cancellation / Refund Reason Like '%Invalid Credit Card Number%'",
546 ),
547 // Case 3: Search for Cancelled Date and Cancelled Reason
548 array(
549 'form_value' => array('cancel_date' => date('Y-m-d'), 'cancel_reason' => 'Insufficient funds'),
550 'expected_count' => 1,
551 'expected_contribution' => array($Contribution1['id']),
552 'expected_qill' => "Cancel Date Like '%" . date('Y-m-d') . "%'ANDCancellation / Refund Reason Like '%Insufficient funds%'",
553 ),
554 );
555
556 foreach ($useCases as $case) {
557 $fv = $case['form_value'];
558 CRM_Contact_BAO_Query::processSpecialFormValue($fv, array('cancel_date', 'cancel_reason'));
559 $query = new CRM_Contact_BAO_Query(CRM_Contact_BAO_Query::convertFormValues($fv));
560 list($select, $from, $where, $having) = $query->query();
561
562 // get and assert contribution count
563 $contributions = CRM_Core_DAO::executeQuery(sprintf('SELECT DISTINCT civicrm_contribution.id %s %s AND civicrm_contribution.id IS NOT NULL AND civicrm_contribution.contribution_status_id = 3', $from, $where))->fetchAll();
564 foreach ($contributions as $key => $value) {
565 $contributions[$key] = $value['id'];
566 }
567 // assert the contribution count
568 $this->assertEquals($case['expected_count'], count($contributions));
569 // assert the contribution IDs
570 $this->checkArrayEquals($case['expected_contribution'], $contributions);
571 // get and assert qill string
572 $qill = trim(implode($query->getOperator(), CRM_Utils_Array::value(0, $query->qill())));
573 $this->assertEquals($case['expected_qill'], $qill);
574 }
575 }
576
577 }