Commit | Line | Data |
---|---|---|
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 | 35 | class 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&reset=1&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 | } |