3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
29 * Include parent class definition
33 * Test Contribution Search form filters
37 class CRM_Contribute_Form_SearchTest
extends CiviUnitTestCase
{
39 protected $_individual;
40 protected $_tablesToTruncate = ['civicrm_contribution', 'civicrm_line_item'];
42 public function setUp() {
44 $this->_individual
= $this->individualCreate();
47 public function tearDown() {
51 * CRM-19325: Test CRM_Contribute_Form_Search batch filters
53 public function testBatchFilter() {
54 $this->quickCleanup($this->_tablesToTruncate
);
55 $contactID1 = $this->individualCreate([], 1);
56 $contactID2 = $this->individualCreate([], 2);
57 $batchTitle = CRM_Batch_BAO_Batch
::generateBatchName();
60 $batch = $this->callAPISuccess('Batch', 'create', [
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,
67 'type_id' => array_search('Contribution', CRM_Batch_BAO_Batch
::buildOptions('type_id')),
69 $batchID = $batch['id'];
72 'primary_profiles' => [1 => NULL, 2 => NULL, 3 => NULL],
73 'primary_contact_id' => [
79 'financial_type' => 1,
81 'receive_date' => '2013-07-24',
82 'receive_date_time' => NULL,
83 'payment_instrument' => 1,
84 'check_number' => NULL,
85 'contribution_status_id' => 1,
88 'financial_type' => 1,
90 'receive_date' => '2014-07-24',
91 'receive_date_time' => NULL,
92 'payment_instrument' => 1,
93 'check_number' => NULL,
94 'contribution_status_id' => 1,
97 'actualBatchTotal' => 100,
100 // create random contribution to check IS NULL filter more precisely
101 $nonBatchContri = $this->callAPISuccess('Contribution', 'create', [
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
,
111 $nonBatchContriID = $nonBatchContri['id'];
113 // process batch entries
114 $form = new CRM_Batch_Form_Entry();
115 $form->setBatchID($batchID);
116 $form->testProcessContribution($batchEntry);
118 // fetch created contributions
119 $entities = $this->callAPISuccess('EntityBatch', 'get', array('batch_id' => $batchID));
121 foreach ($entities['values'] as $value) {
122 $ids[] = $value['entity_id'];
124 list($batchContriID1, $batchContriID2) = $ids;
127 // Case 1: Search for ONLY those contributions which are created from batch
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',
134 // Case 2: Search for ONLY those contributions which are NOT created from batch
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',
141 // Case 3: Search for ONLY those contributions which are created from batch ID - $batchID
143 'form_value' => array('contribution_batch_id' => $batchID),
144 'expected_count' => 2,
145 'expected_contribution' => array($batchContriID1, $batchContriID2),
146 'expected_qill' => 'Batch Name = ' . $batchTitle,
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) = $query->query();
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'];
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);
171 * CRM-20286: Test CRM_Contribute_Form_Search Card type filters
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,
187 'to_financial_account_id' => 1,
189 'contribution_id' => $Contribution1['id'],
190 'payment_instrument_id' => 1,
192 'total_amount' => 100,
194 CRM_Core_BAO_FinancialTrxn
::create($params);
195 $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,
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,
214 'to_financial_account_id' => 1,
216 'contribution_id' => $Contribution3['id'],
217 'payment_instrument_id' => 1,
219 'total_amount' => 200,
221 CRM_Core_BAO_FinancialTrxn
::create($params);
224 // Case 1: Search for ONLY those contributions which have card type
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',
231 // Case 2: Search for ONLY those contributions which have Card Type as Visa
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',
238 // Case 3: Search for ONLY those contributions which have Card Type as Amex
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',
245 // Case 4: Search for ONLY those contributions which have Card Type as Visa or MasterCard
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',
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) = $query->query();
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'];
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);
276 * CRM-20391: Test CRM_Contribute_Form_Search Card Number filters
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,
292 'to_financial_account_id' => 1,
294 'contribution_id' => $Contribution1['id'],
295 'payment_instrument_id' => 1,
297 'total_amount' => 100,
298 'pan_truncation' => 1234,
300 CRM_Core_BAO_FinancialTrxn
::create($params);
301 $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,
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,
320 'to_financial_account_id' => 1,
322 'contribution_id' => $Contribution3['id'],
323 'payment_instrument_id' => 1,
325 'total_amount' => 200,
326 'pan_truncation' => 5678,
328 CRM_Core_BAO_FinancialTrxn
::create($params);
331 // Case 1: Search for ONLY those contributions which have card number
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',
338 // Case 2: Search for ONLY those contributions which have Card Number as 1234
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%',
345 // Case 3: Search for ONLY those contributions which have Card Number as 8888
347 'form_value' => array('financial_trxn_pan_truncation' => 8888),
348 'expected_count' => 0,
349 'expected_contribution' => array(),
350 'expected_qill' => 'Card Number Like %8888%',
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) = $query->query();
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'];
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);
376 * Test CRM_Contribute_Form_Search Recurring Contribution Status Id filters
378 public function testContributionRecurStatusFilter() {
379 $this->quickCleanup($this->_tablesToTruncate
);
380 $contactID1 = $this->individualCreate([], 1);
381 $contactID2 = $this->individualCreate([], 2);
382 // "In Progress" recurring contribution for contactID1
383 $ContributionRecur1 = $this->callAPISuccess('ContributionRecur', 'create', [
385 'contact_id' => $contactID1,
386 'frequency_interval' => 1,
387 'frequency_unit' => "month",
390 'payment_instrument_id' => 1,
391 'contribution_status_id' => 5,
392 'financial_type_id' => "Donation",
394 $Contribution1 = $this->callAPISuccess('Contribution', 'create', [
395 'financial_type_id' => 'Donation',
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'],
405 'to_financial_account_id' => 1,
407 'contribution_id' => $Contribution1['id'],
408 'payment_instrument_id' => 1,
410 'total_amount' => 11,
412 CRM_Core_BAO_FinancialTrxn
::create($params);
413 // "Completed" recurring contribution for contactID2
414 $ContributionRecur2 = $this->callAPISuccess('ContributionRecur', 'create', [
416 'contact_id' => $contactID2,
417 'frequency_interval' => 1,
418 'frequency_unit' => "month",
421 'payment_instrument_id' => 1,
422 'contribution_status_id' => 1,
423 'financial_type_id' => "Donation",
425 $Contribution2 = $this->callAPISuccess('Contribution', 'create', [
426 'financial_type_id' => 'Donation',
427 'total_amount' => 22,
428 'receive_date' => date('Ymd'),
429 'receive_date_time' => NULL,
430 'payment_instrument' => 1,
431 'contribution_status_id' => 1,
432 'contact_id' => $contactID2,
433 'contribution_recur_id' => $ContributionRecur2['id'],
436 'to_financial_account_id' => 1,
438 'contribution_id' => $Contribution2['id'],
439 'payment_instrument_id' => 1,
441 'total_amount' => 22,
443 CRM_Core_BAO_FinancialTrxn
::create($params);
446 // Case 1: Search for ONLY those recurring contributions with status "In Progress"
448 'form_value' => ['contribution_recur_contribution_status_id' => 5],
449 'expected_count' => 1,
450 'expected_contact' => [$contactID1],
451 'expected_qill' => "Recurring Contribution Status = 'In Progress'",
453 // Case 2: Search for ONLY those recurring contributions with status "Completed"
455 'form_value' => ['contribution_recur_contribution_status_id' => 1],
456 'expected_count' => 1,
457 'expected_contact' => [$contactID2],
458 'expected_qill' => "Recurring Contribution Status = 'Completed'",
460 // Case 3: Search for ONLY those recurring contributions with status "Cancelled"
462 'form_value' => ['contribution_recur_contribution_status_id' => 3],
463 'expected_count' => 0,
464 'expected_contact' => [],
465 'expected_qill' => "Recurring Contribution Status = 'Cancelled'",
469 foreach ($useCases as $case) {
470 $fv = $case['form_value'];
471 $query = new CRM_Contact_BAO_Query(CRM_Contact_BAO_Query
::convertFormValues($fv));
472 list($select, $from, $where, $having) = $query->query();
474 // get and assert contribution count
475 $contacts = CRM_Core_DAO
::executeQuery(sprintf('SELECT DISTINCT contact_a.id %s %s AND contact_a.id IS NOT NULL', $from, $where))->fetchAll();
476 foreach ($contacts as $key => $value) {
477 $contacts[$key] = $value['id'];
479 // assert the contribution count
480 $this->assertEquals($case['expected_count'], count($contacts));
481 // assert the contribution IDs
482 $this->checkArrayEquals($case['expected_contact'], $contacts);
483 // get and assert qill string
484 $qill = trim(implode($query->getOperator(), CRM_Utils_Array
::value(0, $query->qill())));
485 $this->assertEquals($case['expected_qill'], $qill);
490 * CRM-21343: Test CRM_Contribute_Form_Search Cancelled filters
492 public function testCancelledFilter() {
493 $this->quickCleanup($this->_tablesToTruncate
);
494 $contactID1 = $this->individualCreate([], 1);
495 $contactID2 = $this->individualCreate([], 2);
496 $Contribution1 = $this->callAPISuccess('Contribution', 'create', [
497 'financial_type_id' => 1,
498 'total_amount' => 100,
499 'receive_date' => date('Ymd'),
500 'receive_date_time' => NULL,
501 'payment_instrument' => 1,
502 'contribution_status_id' => 3,
503 'cancel_date' => date('Ymd'),
504 'cancel_reason' => 'Insufficient funds',
505 'contact_id' => $contactID1,
507 $this->callAPISuccess('Contribution', 'create', [
508 'financial_type_id' => 1,
509 'total_amount' => 150,
510 'receive_date' => date('Ymd', strtotime(date('Y-m-d') . ' - 1 days')),
511 'receive_date_time' => NULL,
512 'payment_instrument' => 1,
513 'contribution_status_id' => 3,
514 'cancel_date' => date('Ymd', strtotime(date('Y-m-d') . ' - 1 days')),
515 'cancel_reason' => 'Insufficient funds',
516 'contact_id' => $contactID2,
518 $Contribution3 = $this->callAPISuccess('Contribution', 'create', [
519 'financial_type_id' => 1,
520 'total_amount' => 200,
521 'receive_date' => date('Ymd'),
522 'receive_date_time' => NULL,
523 'payment_instrument' => 1,
524 'contribution_status_id' => 3,
525 'cancel_date' => date('Ymd'),
526 'cancel_reason' => 'Invalid Credit Card Number',
527 'contact_id' => $contactID1,
531 // Case 1: Search for Cancelled Date
533 'form_value' => ['cancel_date' => date('Y-m-d')],
534 'expected_count' => 2,
535 'expected_contribution' => [$Contribution1['id'], $Contribution3['id']],
536 'expected_qill' => "Cancel Date Like '%" . date('Y-m-d') . "%'",
538 // Case 2: Search for Cancelled Reason
540 'form_value' => ['cancel_reason' => 'Invalid Credit Card Number'],
541 'expected_count' => 1,
542 'expected_contribution' => [$Contribution3['id']],
543 'expected_qill' => "Cancellation / Refund Reason Like '%Invalid Credit Card Number%'",
545 // Case 3: Search for Cancelled Date and Cancelled Reason
547 'form_value' => ['cancel_date' => date('Y-m-d'), 'cancel_reason' => 'Insufficient funds'],
548 'expected_count' => 1,
549 'expected_contribution' => [$Contribution1['id']],
550 'expected_qill' => "Cancel Date Like '%" . date('Y-m-d') . "%'ANDCancellation / Refund Reason Like '%Insufficient funds%'",
554 foreach ($useCases as $case) {
555 $fv = $case['form_value'];
556 CRM_Contact_BAO_Query
::processSpecialFormValue($fv, ['cancel_date', 'cancel_reason']);
557 $query = new CRM_Contact_BAO_Query(CRM_Contact_BAO_Query
::convertFormValues($fv));
558 list($select, $from, $where) = $query->query();
560 // get and assert contribution count
561 $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();
562 foreach ($contributions as $key => $value) {
563 $contributions[$key] = $value['id'];
565 // assert the contribution count
566 $this->assertEquals($case['expected_count'], count($contributions));
567 // assert the contribution IDs
568 $this->checkArrayEquals($case['expected_contribution'], $contributions);
569 // get and assert qill string
570 $qill = trim(implode($query->getOperator(), CRM_Utils_Array
::value(0, $query->qill())));
571 $this->assertEquals($case['expected_qill'], $qill);