Merge pull request #12178 from jitendrapurohit/membership-4
[civicrm-core.git] / tests / phpunit / api / v3 / ReportTemplateTest.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
2fe49090 4 | CiviCRM version 5 |
6a488035 5 +--------------------------------------------------------------------+
8c9251b3 6 | Copyright CiviCRM LLC (c) 2004-2018 |
6a488035
TO
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 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035 27
6a488035
TO
28/**
29 * Test APIv3 civicrm_report_instance_* functions
30 *
6c6e6187
TO
31 * @package CiviCRM_APIv3
32 * @subpackage API_Report
acb109b7 33 * @group headless
6a488035 34 */
6a488035 35class api_v3_ReportTemplateTest extends CiviUnitTestCase {
e2779f6e 36 protected $_apiversion = 3;
b7c9bc4c 37
2c6b4783 38 /**
39 * Our group reports use an alter so transaction cleanup won't work.
40 *
41 * @throws \Exception
42 */
43 public function tearDown() {
44 $this->quickCleanUpFinancialEntities();
0626851e 45 $this->quickCleanup(array('civicrm_group', 'civicrm_saved_search', 'civicrm_group_contact', 'civicrm_group_contact_cache', 'civicrm_group'));
2c6b4783 46 parent::tearDown();
6a488035
TO
47 }
48
6a488035 49 public function testReportTemplate() {
7fbb4198 50 $result = $this->callAPISuccess('ReportTemplate', 'create', array(
6a488035
TO
51 'label' => 'Example Form',
52 'description' => 'Longish description of the example form',
53 'class_name' => 'CRM_Report_Form_Examplez',
54 'report_url' => 'example/path',
55 'component' => 'CiviCase',
56 ));
1cbea43e 57 $this->assertAPISuccess($result);
ba4a1892 58 $this->assertEquals(1, $result['count']);
6a488035 59 $entityId = $result['id'];
ba4a1892
TM
60 $this->assertTrue(is_numeric($entityId));
61 $this->assertEquals(7, $result['values'][$entityId]['component_id']);
6a488035
TO
62 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value
63 WHERE name = "CRM_Report_Form_Examplez"
0201b57f 64 AND option_group_id IN (SELECT id from civicrm_option_group WHERE name = "report_template") ');
6a488035
TO
65 $this->assertDBQuery(1, 'SELECT is_active FROM civicrm_option_value
66 WHERE name = "CRM_Report_Form_Examplez"');
67
68 // change component to null
6c6e6187 69 $result = $this->callAPISuccess('ReportTemplate', 'create', array(
92915c55 70 'id' => $entityId,
6a488035
TO
71 'component' => '',
72 ));
1cbea43e 73 $this->assertAPISuccess($result);
ba4a1892 74 $this->assertEquals(1, $result['count']);
6a488035
TO
75 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value
76 WHERE name = "CRM_Report_Form_Examplez"
0201b57f 77 AND option_group_id IN (SELECT id from civicrm_option_group WHERE name = "report_template") ');
6a488035
TO
78 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value
79 WHERE name = "CRM_Report_Form_Examplez"
80 AND component_id IS NULL');
81
82 // deactivate
6c6e6187 83 $result = $this->callAPISuccess('ReportTemplate', 'create', array(
92915c55 84 'id' => $entityId,
6a488035
TO
85 'is_active' => 0,
86 ));
1cbea43e 87 $this->assertAPISuccess($result);
ba4a1892 88 $this->assertEquals(1, $result['count']);
6a488035
TO
89 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value
90 WHERE name = "CRM_Report_Form_Examplez"
0201b57f 91 AND option_group_id IN (SELECT id from civicrm_option_group WHERE name = "report_template") ');
6a488035
TO
92 $this->assertDBQuery(0, 'SELECT is_active FROM civicrm_option_value
93 WHERE name = "CRM_Report_Form_Examplez"');
94
95 // activate
6c6e6187 96 $result = $this->callAPISuccess('ReportTemplate', 'create', array(
92915c55 97 'id' => $entityId,
6a488035
TO
98 'is_active' => 1,
99 ));
1cbea43e 100 $this->assertAPISuccess($result);
ba4a1892 101 $this->assertEquals(1, $result['count']);
6a488035
TO
102 $this->assertDBQuery(1, 'SELECT count(*) FROM civicrm_option_value
103 WHERE name = "CRM_Report_Form_Examplez"
0201b57f 104 AND option_group_id IN (SELECT id from civicrm_option_group WHERE name = "report_template") ');
6a488035
TO
105 $this->assertDBQuery(1, 'SELECT is_active FROM civicrm_option_value
106 WHERE name = "CRM_Report_Form_Examplez"');
107
92915c55
TO
108 $result = $this->callAPISuccess('ReportTemplate', 'delete', array(
109 'id' => $entityId,
6a488035 110 ));
1cbea43e 111 $this->assertAPISuccess($result);
ba4a1892 112 $this->assertEquals(1, $result['count']);
6a488035
TO
113 $this->assertDBQuery(0, 'SELECT count(*) FROM civicrm_option_value
114 WHERE name = "CRM_Report_Form_Examplez"
115 ');
116 }
e2779f6e
E
117
118 /**
fe482240 119 * Test getrows on contact summary report.
e2779f6e 120 */
00be9182 121 public function testReportTemplateGetRowsContactSummary() {
5c49fee0 122 $description = "Retrieve rows from a report template (optionally providing the instance_id).";
fee15d2a 123 $result = $this->callAPIAndDocument('report_template', 'getrows', array(
e2779f6e 124 'report_id' => 'contact/summary',
21dfd5f5 125 'options' => array('metadata' => array('labels', 'title')),
0626851e 126 ), __FUNCTION__, __FILE__, $description, 'Getrows');
781d91c8 127 $this->assertEquals('Contact Name', $result['metadata']['labels']['civicrm_contact_sort_name']);
e2779f6e
E
128
129 //the second part of this test has been commented out because it relied on the db being reset to
130 // it's base state
131 //wasn't able to get that to work consistently
132 // however, when the db is in the base state the tests do pass
133 // and because the test covers 'all' contacts we can't create our own & assume the others don't exist
134 /*
135 $this->assertEquals(2, $result['count']);
136 $this->assertEquals('Default Organization', $result[0]['civicrm_contact_sort_name']);
137 $this->assertEquals('Second Domain', $result[1]['civicrm_contact_sort_name']);
138 $this->assertEquals('15 Main St', $result[1]['civicrm_address_street_address']);
e70a7fc0 139 */
e2779f6e
E
140 }
141
142 /**
63dc1f23 143 * Test api to get rows from reports.
fe482240 144 *
e2779f6e 145 * @dataProvider getReportTemplates
fe482240 146 *
1e1fdcf6 147 * @param $reportID
fe482240 148 *
1e1fdcf6 149 * @throws \PHPUnit_Framework_IncompleteTestError
e2779f6e 150 */
00be9182 151 public function testReportTemplateGetRowsAllReports($reportID) {
63dc1f23 152 //$reportID = 'logging/contact/summary';
22e263ad 153 if (stristr($reportID, 'has existing issues')) {
e2779f6e
E
154 $this->markTestIncomplete($reportID);
155 }
63dc1f23 156 if (substr($reportID, 0, '7') === 'logging') {
157 Civi::settings()->set('logging', 1);
158 }
159
fe482240 160 $this->callAPISuccess('report_template', 'getrows', array(
92915c55 161 'report_id' => $reportID,
e2779f6e 162 ));
63dc1f23 163 if (substr($reportID, 0, '7') === 'logging') {
164 Civi::settings()->set('logging', 0);
165 }
e2779f6e
E
166 }
167
f2f65d33 168 /**
169 * Test logging report when a custom data table has a table removed by hook.
170 *
171 * Here we are checking that no fatal is triggered.
172 */
173 public function testLoggingReportWithHookRemovalOfCustomDataTable() {
174 Civi::settings()->set('logging', 1);
175 $group1 = $this->customGroupCreate();
176 $group2 = $this->customGroupCreate(['name' => 'second_one', 'title' => 'second one', 'table_name' => 'civicrm_value_second_one']);
177 $this->customFieldCreate(array('custom_group_id' => $group1['id'], 'label' => 'field one'));
178 $this->customFieldCreate(array('custom_group_id' => $group2['id'], 'label' => 'field two'));
179 $this->hookClass->setHook('civicrm_alterLogTables', array($this, 'alterLogTablesRemoveCustom'));
180
181 $this->callAPISuccess('report_template', 'getrows', array(
182 'report_id' => 'logging/contact/summary',
183 ));
184 Civi::settings()->set('logging', 0);
185 $this->customGroupDelete($group1['id']);
186 $this->customGroupDelete($group2['id']);
187 }
188
189 /**
190 * Remove one log table from the logging spec.
191 *
192 * @param array $logTableSpec
193 */
194 public function alterLogTablesRemoveCustom(&$logTableSpec) {
195 unset($logTableSpec['civicrm_value_second_one']);
e2779f6e
E
196 }
197
6c8223f6 198 /**
199 * Test api to get rows from reports with ACLs enabled.
200 *
201 * Checking for lack of fatal error at the moment.
202 *
203 * @dataProvider getReportTemplates
204 *
205 * @param $reportID
206 *
207 * @throws \PHPUnit_Framework_IncompleteTestError
208 */
209 public function testReportTemplateGetRowsAllReportsACL($reportID) {
210 if (stristr($reportID, 'has existing issues')) {
211 $this->markTestIncomplete($reportID);
212 }
213 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
214 $this->callAPISuccess('report_template', 'getrows', array(
215 'report_id' => $reportID,
216 ));
217 }
218
e2779f6e 219 /**
fe482240
EM
220 * Test get statistics.
221 *
e2779f6e 222 * @dataProvider getReportTemplates
fe482240 223 *
1e1fdcf6 224 * @param $reportID
fe482240 225 *
1e1fdcf6 226 * @throws \PHPUnit_Framework_IncompleteTestError
e2779f6e 227 */
00be9182 228 public function testReportTemplateGetStatisticsAllReports($reportID) {
22e263ad 229 if (stristr($reportID, 'has existing issues')) {
e2779f6e
E
230 $this->markTestIncomplete($reportID);
231 }
22e263ad 232 if (in_array($reportID, array('contribute/softcredit', 'contribute/bookkeeping'))) {
e2779f6e
E
233 $this->markTestIncomplete($reportID . " has non enotices when calling statistics fn");
234 }
5c49fee0 235 $description = "Get Statistics from a report (note there isn't much data to get in the test DB).";
fee15d2a 236 $result = $this->callAPIAndDocument('report_template', 'getstatistics', array(
e2779f6e 237 'report_id' => $reportID,
fee15d2a 238 ), __FUNCTION__, __FILE__, $description, 'Getstatistics', 'getstatistics');
e2779f6e
E
239 }
240
241 /**
fe482240
EM
242 * Data provider function for getting all templates.
243 *
244 * Note that the function needs to
e2779f6e
E
245 * be static so cannot use $this->callAPISuccess
246 */
247 public static function getReportTemplates() {
248 $reportsToSkip = array(
92915c55 249 'activity' => 'does not respect function signature on from clause',
92915c55 250 'event/income' => 'I do no understand why but error is Call to undefined method CRM_Report_Form_Event_Income::from() in CRM/Report/Form.php on line 2120',
92915c55 251 'contribute/history' => 'Declaration of CRM_Report_Form_Contribute_History::buildRows() should be compatible with CRM_Report_Form::buildRows($sql, &$rows)',
cb5aba81 252 'activitySummary' => 'We use temp tables for the main query generation and name are dynamic. These names are not available in stats() when called directly.',
e2779f6e
E
253 );
254
255 $reports = civicrm_api3('report_template', 'get', array('return' => 'value', 'options' => array('limit' => 500)));
256 foreach ($reports['values'] as $report) {
22e263ad 257 if (empty($reportsToSkip[$report['value']])) {
e2779f6e
E
258 $reportTemplates[] = array($report['value']);
259 }
260 else {
86bfa4f6 261 $reportTemplates[] = array($report['value'] . " has existing issues : " . $reportsToSkip[$report['value']]);
e2779f6e
E
262 }
263 }
264
e2779f6e
E
265 return $reportTemplates;
266 }
96025800 267
2c6b4783 268 /**
269 * Get contribution templates that work with basic filter tests.
270 *
271 * These templates require minimal data config.
272 */
273 public static function getContributionReportTemplates() {
eae0f0d9 274 return array(array('contribute/summary'), array('contribute/detail'), array('contribute/repeat'), array('topDonor' => 'contribute/topDonor'));
275 }
276
277 /**
278 * Get contribution templates that work with basic filter tests.
279 *
280 * These templates require minimal data config.
281 */
282 public static function getMembershipReportTemplates() {
283 return array(array('member/detail'));
284 }
285
286 public static function getMembershipAndContributionReportTemplatesForGroupTests() {
287 $templates = array_merge(self::getContributionReportTemplates(), self::getMembershipReportTemplates());
288 foreach ($templates as $key => $value) {
289 if (array_key_exists('topDonor', $value)) {
290 // Report is not standard enough to test here.
291 unset($templates[$key]);
292 }
293
294 }
295 return $templates;
2c6b4783 296 }
297
c160fde8 298 /**
299 * Test Lybunt report to check basic inclusion of a contact who gave in the year before the chosen year.
300 */
301 public function testLybuntReportWithData() {
302 $inInd = $this->individualCreate();
303 $outInd = $this->individualCreate();
304 $this->contributionCreate(array('contact_id' => $inInd, 'receive_date' => '2014-03-01'));
305 $this->contributionCreate(array('contact_id' => $outInd, 'receive_date' => '2015-03-01', 'trxn_id' => NULL, 'invoice_id' => NULL));
306 $rows = $this->callAPISuccess('report_template', 'getrows', array(
307 'report_id' => 'contribute/lybunt',
308 'yid_value' => 2015,
309 'yid_op' => 'calendar',
310 'options' => array('metadata' => array('sql')),
311 ));
312 $this->assertEquals(1, $rows['count'], "Report failed - the sql used to generate the results was " . print_r($rows['metadata']['sql'], TRUE));
313 }
314
33072bc7 315 /**
316 * Test Lybunt report applies ACLs.
317 */
318 public function testLybuntReportWithDataAndACLFilter() {
319 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('administer CiviCRM');
320 $inInd = $this->individualCreate();
321 $outInd = $this->individualCreate();
322 $this->contributionCreate(array('contact_id' => $inInd, 'receive_date' => '2014-03-01'));
323 $this->contributionCreate(array('contact_id' => $outInd, 'receive_date' => '2015-03-01', 'trxn_id' => NULL, 'invoice_id' => NULL));
324 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereHookNoResults'));
325 $params = array(
326 'report_id' => 'contribute/lybunt',
327 'yid_value' => 2015,
328 'yid_op' => 'calendar',
329 'options' => array('metadata' => array('sql')),
330 'check_permissions' => 1,
331 );
332
333 $rows = $this->callAPISuccess('report_template', 'getrows', $params);
334 $this->assertEquals(0, $rows['count'], "Report failed - the sql used to generate the results was " . print_r($rows['metadata']['sql'], TRUE));
335
336 CRM_Utils_Hook::singleton()->reset();
337 }
338
c160fde8 339 /**
340 * Test Lybunt report to check basic inclusion of a contact who gave in the year before the chosen year.
341 */
342 public function testLybuntReportWithFYData() {
343 $inInd = $this->individualCreate();
344 $outInd = $this->individualCreate();
345 $this->contributionCreate(array('contact_id' => $inInd, 'receive_date' => '2014-10-01'));
346 $this->contributionCreate(array('contact_id' => $outInd, 'receive_date' => '2015-03-01', 'trxn_id' => NULL, 'invoice_id' => NULL));
347 $this->callAPISuccess('Setting', 'create', array('fiscalYearStart' => array('M' => 7, 'd' => 1)));
348 $rows = $this->callAPISuccess('report_template', 'getrows', array(
349 'report_id' => 'contribute/lybunt',
350 'yid_value' => 2015,
351 'yid_op' => 'fiscal',
352 'options' => array('metadata' => array('sql')),
353 'order_bys' => array(
354 array(
355 'column' => 'first_name',
356 'order' => 'ASC',
357 ),
358 ),
359 ));
360
361 $this->assertEquals(2, $rows['count'], "Report failed - the sql used to generate the results was " . print_r($rows['metadata']['sql'], TRUE));
15d9e604 362
363 $this->assertContains('DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci
364 SELECT SQL_CALC_FOUND_ROWS contact_civireport.id as cid FROM civicrm_contact contact_civireport INNER JOIN civicrm_contribution contribution_civireport USE index (received_date) ON contribution_civireport.contact_id = contact_civireport.id
365 AND contribution_civireport.is_test = 0
366 AND contribution_civireport.receive_date BETWEEN \'20140701000000\' AND \'20150630235959\'
367
368 LEFT JOIN civicrm_contribution cont_exclude ON cont_exclude.contact_id = contact_civireport.id
369 AND cont_exclude.receive_date BETWEEN \'2015-7-1\' AND \'20160630235959\' WHERE cont_exclude.id IS NULL AND 1 AND ( contribution_civireport.contribution_status_id IN (1) )
370 GROUP BY contact_civireport.id', $rows['metadata']['sql'][0]);
c160fde8 371 }
372
3fd9a92a 373 /**
374 * Test Lybunt report to check basic inclusion of a contact who gave in the year before the chosen year.
375 */
376 public function testLybuntReportWithFYDataOrderByLastYearAmount() {
377 $inInd = $this->individualCreate();
378 $outInd = $this->individualCreate();
379 $this->contributionCreate(array('contact_id' => $inInd, 'receive_date' => '2014-10-01'));
380 $this->contributionCreate(array('contact_id' => $outInd, 'receive_date' => '2015-03-01', 'trxn_id' => NULL, 'invoice_id' => NULL));
381 $this->callAPISuccess('Setting', 'create', array('fiscalYearStart' => array('M' => 7, 'd' => 1)));
382 $rows = $this->callAPISuccess('report_template', 'getrows', array(
383 'report_id' => 'contribute/lybunt',
384 'yid_value' => 2015,
385 'yid_op' => 'fiscal',
386 'options' => array('metadata' => array('sql')),
387 'fields' => array('first_name'),
388 'order_bys' => array(
389 array(
390 'column' => 'last_year_total_amount',
391 'order' => 'ASC',
392 ),
393 ),
394 ));
395
396 $this->assertEquals(2, $rows['count'], "Report failed - the sql used to generate the results was " . print_r($rows['metadata']['sql'], TRUE));
397 }
398
2c6b4783 399 /**
400 * Test the group filter works on the contribution summary (with a smart group).
eae0f0d9 401 *
402 * @dataProvider getMembershipAndContributionReportTemplatesForGroupTests
403 *
404 * @param string $template
405 * Name of the template to test.
2c6b4783 406 */
eae0f0d9 407 public function testContributionSummaryWithSmartGroupFilter($template) {
2c6b4783 408 $groupID = $this->setUpPopulatedSmartGroup();
409 $rows = $this->callAPISuccess('report_template', 'getrows', array(
eae0f0d9 410 'report_id' => $template,
2c6b4783 411 'gid_value' => $groupID,
412 'gid_op' => 'in',
413 'options' => array('metadata' => array('sql')),
414 ));
eae0f0d9 415 $this->assertNumberOfContactsInResult(3, $rows, $template);
416 if ($template === 'contribute/summary') {
417 $this->assertEquals(3, $rows['values'][0]['civicrm_contribution_total_amount_count']);
418 }
2c6b4783 419 }
420
421 /**
eae0f0d9 422 * Test the group filter works on the contribution summary.
423 *
424 * @dataProvider getMembershipAndContributionReportTemplatesForGroupTests
2c6b4783 425 */
eae0f0d9 426 public function testContributionSummaryWithNotINSmartGroupFilter($template) {
2c6b4783 427 $groupID = $this->setUpPopulatedSmartGroup();
428 $rows = $this->callAPISuccess('report_template', 'getrows', array(
429 'report_id' => 'contribute/summary',
430 'gid_value' => $groupID,
43c1fa19 431 'gid_op' => 'notin',
2c6b4783 432 'options' => array('metadata' => array('sql')),
433 ));
434 $this->assertEquals(2, $rows['values'][0]['civicrm_contribution_total_amount_count']);
e6bab5ea 435 }
2c6b4783 436
e6bab5ea 437 /**
438 * Test the group filter works on the contribution summary.
439 */
440 public function testContributionDetailSoftCredits() {
441 $contactID = $this->individualCreate();
442 $contactID2 = $this->individualCreate();
443 $this->contributionCreate(['contact_id' => $contactID, 'api.ContributionSoft.create' => ['amount' => 5, 'contact_id' => $contactID2]]);
444 $template = 'contribute/detail';
445 $rows = $this->callAPISuccess('report_template', 'getrows', array(
446 'report_id' => $template,
447 'contribution_or_soft_value' => 'contributions_only',
448 'fields' => ['soft_credits' => 1, 'contribution_or_soft' => 1, 'sort_name' => 1],
449 'options' => array('metadata' => array('sql')),
450 ));
451 $this->assertEquals(
452 "<a href='/index.php?q=civicrm/contact/view&amp;reset=1&amp;cid=" . $contactID2 . "'>Anderson, Anthony</a> $ 5.00",
453 $rows['values'][0]['civicrm_contribution_soft_credits']
454 );
2c6b4783 455 }
456
457 /**
eae0f0d9 458 * Test the group filter works on the various reports.
2c6b4783 459 *
eae0f0d9 460 * @dataProvider getMembershipAndContributionReportTemplatesForGroupTests
2c6b4783 461 *
462 * @param string $template
463 * Report template unique identifier.
464 */
eae0f0d9 465 public function testReportsWithNonSmartGroupFilter($template) {
2c6b4783 466 $groupID = $this->setUpPopulatedGroup();
467 $rows = $this->callAPISuccess('report_template', 'getrows', array(
468 'report_id' => $template,
469 'gid_value' => array($groupID),
470 'gid_op' => 'in',
471 'options' => array('metadata' => array('sql')),
472 ));
473 $this->assertNumberOfContactsInResult(1, $rows, $template);
474 }
475
476 /**
477 * Assert the included results match the expected.
478 *
479 * There may or may not be a group by in play so the assertion varies a little.
480 *
481 * @param int $numberExpected
482 * @param array $rows
483 * Rows returned from the report.
484 * @param string $template
485 */
486 protected function assertNumberOfContactsInResult($numberExpected, $rows, $template) {
487 if (isset($rows['values'][0]['civicrm_contribution_total_amount_count'])) {
488 $this->assertEquals($numberExpected, $rows['values'][0]['civicrm_contribution_total_amount_count'], 'wrong row count in ' . $template);
489 }
490 else {
491 $this->assertEquals($numberExpected, count($rows['values']), 'wrong row count in ' . $template);
492 }
493 }
494
495 /**
496 * Test the group filter works on the contribution summary when 2 groups are involved.
497 */
498 public function testContributionSummaryWithTwoGroups() {
499 $groupID = $this->setUpPopulatedGroup();
500 $groupID2 = $this->setUpPopulatedSmartGroup();
501 $rows = $this->callAPISuccess('report_template', 'getrows', array(
502 'report_id' => 'contribute/summary',
503 'gid_value' => array($groupID, $groupID2),
504 'gid_op' => 'in',
505 'options' => array('metadata' => array('sql')),
506 ));
507 $this->assertEquals(4, $rows['values'][0]['civicrm_contribution_total_amount_count']);
508 }
509
27367f58 510 /**
511 * CRM-20640: Test the group filter works on the contribution summary when a single contact in 2 groups.
512 */
513 public function testContributionSummaryWithSingleContactsInTwoGroups() {
514 list($groupID1, $individualID) = $this->setUpPopulatedGroup(TRUE);
515 // create second group and add the individual to it.
516 $groupID2 = $this->groupCreate(array('name' => uniqid(), 'title' => uniqid()));
517 $this->callAPISuccess('GroupContact', 'create', array(
518 'group_id' => $groupID2,
519 'contact_id' => $individualID,
520 'status' => 'Added',
521 ));
522
523 $rows = $this->callAPISuccess('report_template', 'getrows', array(
524 'report_id' => 'contribute/summary',
525 'gid_value' => array($groupID1, $groupID2),
526 'gid_op' => 'in',
527 'options' => array('metadata' => array('sql')),
528 ));
529 $this->assertEquals(1, $rows['count']);
530 }
531
2c6b4783 532 /**
533 * Test the group filter works on the contribution summary when 2 groups are involved.
534 */
535 public function testContributionSummaryWithTwoGroupsWithIntersection() {
536 $groups = $this->setUpIntersectingGroups();
537
538 $rows = $this->callAPISuccess('report_template', 'getrows', array(
539 'report_id' => 'contribute/summary',
540 'gid_value' => $groups,
541 'gid_op' => 'in',
542 'options' => array('metadata' => array('sql')),
543 ));
544 $this->assertEquals(7, $rows['values'][0]['civicrm_contribution_total_amount_count']);
545 }
546
547 /**
548 * Set up a smart group for testing.
549 *
550 * The smart group includes all Households by filter. In addition an individual
551 * is created and hard-added and an individual is created that is not added.
552 *
553 * One household is hard-added as well as being in the filter.
554 *
555 * This gives us a range of scenarios for testing contacts are included only once
556 * whenever they are hard-added or in the criteria.
557 *
558 * @return int
559 */
560 public function setUpPopulatedSmartGroup() {
561 $household1ID = $this->householdCreate();
562 $individual1ID = $this->individualCreate();
563 $householdID = $this->householdCreate();
564 $individualID = $this->individualCreate();
565 $individualIDRemoved = $this->individualCreate();
566 $groupID = $this->smartGroupCreate(array(), array('name' => uniqid(), 'title' => uniqid()));
567 $this->callAPISuccess('GroupContact', 'create', array(
568 'group_id' => $groupID,
569 'contact_id' => $individualIDRemoved,
570 'status' => 'Removed',
571 ));
572 $this->callAPISuccess('GroupContact', 'create', array(
573 'group_id' => $groupID,
574 'contact_id' => $individualID,
575 'status' => 'Added',
576 ));
577 $this->callAPISuccess('GroupContact', 'create', array(
578 'group_id' => $groupID,
579 'contact_id' => $householdID,
580 'status' => 'Added',
581 ));
582 foreach (array($household1ID, $individual1ID, $householdID, $individualID, $individualIDRemoved) as $contactID) {
583 $this->contributionCreate(array('contact_id' => $contactID, 'invoice_id' => '', 'trxn_id' => ''));
eae0f0d9 584 $this->contactMembershipCreate(array('contact_id' => $contactID));
2c6b4783 585 }
586
587 // Refresh the cache for test purposes. It would be better to alter to alter the GroupContact add function to add contacts to the cache.
0626851e 588 CRM_Contact_BAO_GroupContactCache::clearGroupContactCache($groupID);
2c6b4783 589 return $groupID;
590 }
591
592 /**
eae0f0d9 593 * Set up a static group for testing.
2c6b4783 594 *
eae0f0d9 595 * An individual is created and hard-added and an individual is created that is not added.
2c6b4783 596 *
597 * This gives us a range of scenarios for testing contacts are included only once
598 * whenever they are hard-added or in the criteria.
599 *
27367f58 600 * @param bool $returnAddedContact
601 *
2c6b4783 602 * @return int
603 */
27367f58 604 public function setUpPopulatedGroup($returnAddedContact = FALSE) {
2c6b4783 605 $individual1ID = $this->individualCreate();
606 $individualID = $this->individualCreate();
607 $individualIDRemoved = $this->individualCreate();
608 $groupID = $this->groupCreate(array('name' => uniqid(), 'title' => uniqid()));
609 $this->callAPISuccess('GroupContact', 'create', array(
610 'group_id' => $groupID,
611 'contact_id' => $individualIDRemoved,
612 'status' => 'Removed',
613 ));
614 $this->callAPISuccess('GroupContact', 'create', array(
615 'group_id' => $groupID,
616 'contact_id' => $individualID,
617 'status' => 'Added',
618 ));
619
620 foreach (array($individual1ID, $individualID, $individualIDRemoved) as $contactID) {
621 $this->contributionCreate(array('contact_id' => $contactID, 'invoice_id' => '', 'trxn_id' => ''));
eae0f0d9 622 $this->contactMembershipCreate(array('contact_id' => $contactID));
2c6b4783 623 }
624
625 // Refresh the cache for test purposes. It would be better to alter to alter the GroupContact add function to add contacts to the cache.
0626851e 626 CRM_Contact_BAO_GroupContactCache::clearGroupContactCache($groupID);
27367f58 627
628 if ($returnAddedContact) {
629 return array($groupID, $individualID);
630 }
631
2c6b4783 632 return $groupID;
633 }
634
635 /**
636 * @return array
637 */
638 public function setUpIntersectingGroups() {
639 $groupID = $this->setUpPopulatedGroup();
640 $groupID2 = $this->setUpPopulatedSmartGroup();
641 $addedToBothIndividualID = $this->individualCreate();
642 $removedFromBothIndividualID = $this->individualCreate();
643 $addedToSmartGroupRemovedFromOtherIndividualID = $this->individualCreate();
644 $removedFromSmartGroupAddedToOtherIndividualID = $this->individualCreate();
645 $this->callAPISuccess('GroupContact', 'create', array(
646 'group_id' => $groupID,
647 'contact_id' => $addedToBothIndividualID,
648 'status' => 'Added',
649 ));
650 $this->callAPISuccess('GroupContact', 'create', array(
651 'group_id' => $groupID2,
652 'contact_id' => $addedToBothIndividualID,
653 'status' => 'Added',
654 ));
655 $this->callAPISuccess('GroupContact', 'create', array(
656 'group_id' => $groupID,
657 'contact_id' => $removedFromBothIndividualID,
658 'status' => 'Removed',
659 ));
660 $this->callAPISuccess('GroupContact', 'create', array(
661 'group_id' => $groupID2,
662 'contact_id' => $removedFromBothIndividualID,
663 'status' => 'Removed',
664 ));
665 $this->callAPISuccess('GroupContact', 'create', array(
666 'group_id' => $groupID2,
667 'contact_id' => $addedToSmartGroupRemovedFromOtherIndividualID,
668 'status' => 'Added',
669 ));
670 $this->callAPISuccess('GroupContact', 'create', array(
671 'group_id' => $groupID,
672 'contact_id' => $addedToSmartGroupRemovedFromOtherIndividualID,
673 'status' => 'Removed',
674 ));
675 $this->callAPISuccess('GroupContact', 'create', array(
676 'group_id' => $groupID,
677 'contact_id' => $removedFromSmartGroupAddedToOtherIndividualID,
678 'status' => 'Added',
679 ));
680 $this->callAPISuccess('GroupContact', 'create', array(
681 'group_id' => $groupID2,
682 'contact_id' => $removedFromSmartGroupAddedToOtherIndividualID,
683 'status' => 'Removed',
684 ));
685
686 foreach (array(
687 $addedToBothIndividualID,
688 $removedFromBothIndividualID,
689 $addedToSmartGroupRemovedFromOtherIndividualID,
690 $removedFromSmartGroupAddedToOtherIndividualID,
691 ) as $contactID) {
692 $this->contributionCreate(array(
693 'contact_id' => $contactID,
694 'invoice_id' => '',
695 'trxn_id' => '',
696 ));
697 }
698 return array($groupID, $groupID2);
699 }
700
45f8590c
PN
701 /**
702 * Test Deferred Revenue Report.
703 */
704 public function testDeferredRevenueReport() {
705 $indv1 = $this->individualCreate();
706 $indv2 = $this->individualCreate();
707 $params = array(
708 'contribution_invoice_settings' => array(
709 'deferred_revenue_enabled' => '1',
710 ),
711 );
712 $this->callAPISuccess('Setting', 'create', $params);
713 $this->contributionCreate(
714 array(
715 'contact_id' => $indv1,
716 'receive_date' => '2016-10-01',
717 'revenue_recognition_date' => date('Y-m-t', strtotime(date('ymd') . '+3 month')),
718 'financial_type_id' => 2,
719 )
720 );
721 $this->contributionCreate(
722 array(
723 'contact_id' => $indv1,
724 'revenue_recognition_date' => date('Y-m-t', strtotime(date('ymd') . '+22 month')),
725 'financial_type_id' => 4,
726 'trxn_id' => NULL,
727 'invoice_id' => NULL,
728 )
729 );
730 $this->contributionCreate(
731 array(
732 'contact_id' => $indv2,
733 'revenue_recognition_date' => date('Y-m-t', strtotime(date('ymd') . '+1 month')),
734 'financial_type_id' => 4,
735 'trxn_id' => NULL,
736 'invoice_id' => NULL,
737 )
738 );
739 $this->contributionCreate(
740 array(
741 'contact_id' => $indv2,
742 'receive_date' => '2016-03-01',
743 'revenue_recognition_date' => date('Y-m-t', strtotime(date('ymd') . '+4 month')),
744 'financial_type_id' => 2,
745 'trxn_id' => NULL,
746 'invoice_id' => NULL,
747 )
748 );
749 $rows = $this->callAPISuccess('report_template', 'getrows', array(
750 'report_id' => 'contribute/deferredrevenue',
751 ));
752 $this->assertEquals(2, $rows['count'], "Report failed to get row count");
753 $count = array(2, 1);
754 foreach ($rows['values'] as $row) {
755 $this->assertEquals(array_pop($count), count($row['rows']), "Report failed to get row count");
756 }
757 }
758
6a488035 759}