CRM-18246 Lybunt group clause not being included in temp table due to order of operations
[civicrm-core.git] / CRM / Report / Form / Contribute / History.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
7e9e8871 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
e7112fa7 6 | Copyright CiviCRM LLC (c) 2004-2015 |
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
TO
27
28/**
29 *
30 * @package CRM
e7112fa7 31 * @copyright CiviCRM LLC (c) 2004-2015
6a488035
TO
32 * $Id$
33 *
34 */
35class CRM_Report_Form_Contribute_History extends CRM_Report_Form {
36 // Primary Contacts count limitCONSTROW_COUNT_LIMIT = 10;
37
38 protected $_addressField = FALSE;
39 protected $_emailField = FALSE;
40 protected $_phoneField = FALSE;
41 protected $_relationshipColumns = array();
42
70bea8e2 43 protected $_customGroupExtends = array(
44 'Contact',
45 'Individual',
7d793900 46 'Contribution',
70bea8e2 47 );
6a488035
TO
48
49 protected $_referenceYear = array(
50 'this_year' => '',
51 'other_year' => '',
52 );
53 protected $_yearStatisticsFrom = '';
54
55 protected $_yearStatisticsTo = '';
74cf4551 56
74cf4551 57 /**
74cf4551 58 */
00be9182 59 public function __construct() {
70bea8e2 60 $this->_autoIncludeIndexedFieldsAsOrderBys = 1;
6a488035 61 $yearsInPast = 4;
9d72cede
EM
62 $date = CRM_Core_SelectValues::date('custom', NULL, $yearsInPast, 0);
63 $count = $date['maxYear'];
64 $optionYear = array('' => ts('- select -'));
6a488035
TO
65
66 $this->_yearStatisticsFrom = $date['minYear'];
67 $this->_yearStatisticsTo = $date['maxYear'];
68
69 while ($date['minYear'] <= $count) {
70 $optionYear[$date['minYear']] = $date['minYear'];
71 $date['minYear']++;
72 }
73
74 $relationTypeOp = array();
75 $relationshipTypes = CRM_Core_PseudoConstant::relationshipType();
76 foreach ($relationshipTypes as $rid => $rtype) {
77 if ($rtype['label_a_b'] != $rtype['label_b_a']) {
78 $relationTypeOp[$rid] = "{$rtype['label_a_b']}/{$rtype['label_b_a']}";
79 }
80 else {
81 $relationTypeOp[$rid] = $rtype['label_a_b'];
82 }
83 }
84
85 $this->_columns = array(
c301f76e 86 'civicrm_contact' => array(
87 'dao' => 'CRM_Contact_DAO_Contact',
88 'fields' => array(
89 'sort_name' => array(
90 'title' => ts('Contact Name'),
91 'default' => TRUE,
92 'required' => TRUE,
93 'no_repeat' => TRUE,
6a488035 94 ),
70bea8e2 95 'first_name' => array(
96 'title' => ts('First Name'),
97 ),
98 'middle_name' => array(
99 'title' => ts('Middle Name'),
100 ),
101 'last_name' => array(
102 'title' => ts('Last Name'),
103 ),
c301f76e 104 'id' => array(
105 'no_display' => TRUE,
106 'default' => TRUE,
107 'required' => TRUE,
108 ),
70bea8e2 109 'gender_id' => array(
110 'title' => ts('Gender'),
111 ),
112 'birth_date' => array(
113 'title' => ts('Birth Date'),
114 ),
115 'age' => array(
116 'title' => ts('Age'),
117 'dbAlias' => 'TIMESTAMPDIFF(YEAR, contact_civireport.birth_date, CURDATE())',
118 ),
c301f76e 119 'contact_type' => array(
120 'title' => ts('Contact Type'),
121 ),
122 'contact_sub_type' => array(
123 'title' => ts('Contact Subtype'),
30f85891 124 ),
6a488035 125 ),
c301f76e 126 'grouping' => 'contact-fields',
70bea8e2 127 'order_bys' => array(
128 'sort_name' => array(
129 'title' => ts('Last Name, First Name'),
130 'default' => '1',
131 'default_weight' => '0',
132 'default_order' => 'ASC',
133 ),
134 'first_name' => array(
135 'name' => 'first_name',
136 'title' => ts('First Name'),
137 ),
138 'gender_id' => array(
139 'name' => 'gender_id',
140 'title' => ts('Gender'),
141 ),
142 'birth_date' => array(
143 'name' => 'birth_date',
144 'title' => ts('Birth Date'),
145 ),
146 'contact_type' => array(
147 'title' => ts('Contact Type'),
148 ),
149 'contact_sub_type' => array(
150 'title' => ts('Contact Subtype'),
151 ),
152 ),
c301f76e 153 'filters' => array(
154 'sort_name' => array('title' => ts('Contact Name')),
155 'id' => array(
156 'title' => ts('Contact ID'),
157 'no_display' => TRUE,
6a488035 158 ),
70bea8e2 159 'gender_id' => array(
160 'title' => ts('Gender'),
161 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
162 'options' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'),
163 ),
164 'birth_date' => array(
165 'title' => ts('Birth Date'),
166 'operatorType' => CRM_Report_Form::OP_DATE,
167 ),
168 'contact_type' => array(
169 'title' => ts('Contact Type'),
170 ),
171 'contact_sub_type' => array(
172 'title' => ts('Contact Subtype'),
173 ),
6a488035 174 ),
c301f76e 175 ),
176 'civicrm_email' => array(
177 'dao' => 'CRM_Core_DAO_Email',
178 'fields' => array(
179 'email' => array(
180 'title' => ts('Email'),
181 'no_repeat' => TRUE,
6a488035
TO
182 ),
183 ),
c301f76e 184 'grouping' => 'contact-fields',
185 ),
186 'civicrm_phone' => array(
187 'dao' => 'CRM_Core_DAO_Phone',
188 'fields' => array(
189 'phone' => array(
190 'title' => ts('Phone'),
191 'no_repeat' => TRUE,
6a488035 192 ),
c301f76e 193 ),
194 'grouping' => 'contact-fields',
195 ),
196 ) + $this->addAddressFields(FALSE, FALSE, FALSE, array()) + array(
197 'civicrm_relationship' => array(
198 'dao' => 'CRM_Contact_DAO_Relationship',
199 'fields' => array(
200 'relationship_type_id' => array(
201 'title' => ts('Relationship Type'),
202 'default' => TRUE,
6a488035 203 ),
c301f76e 204 'contact_id_a' => array('no_display' => TRUE),
205 'contact_id_b' => array('no_display' => TRUE),
6a488035 206 ),
c301f76e 207 'filters' => array(
208 'relationship_type_id' => array(
209 'title' => ts('Relationship Type'),
210 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
211 'options' => $relationTypeOp,
212 'type' => CRM_Utils_Type::T_STRING,
6a488035 213 ),
c301f76e 214 ),
215 ),
216 ) + array(
217 'civicrm_contribution' => array(
218 'dao' => 'CRM_Contribute_DAO_Contribution',
219 'fields' => array(
220 'total_amount' => array(
221 'title' => ts('Amount Statistics'),
222 'default' => TRUE,
223 'required' => TRUE,
224 'no_display' => TRUE,
225 'statistics' => array('sum' => ts('Aggregate Amount')),
226 ),
227 'receive_date' => array(
228 'required' => TRUE,
229 'default' => TRUE,
230 'no_display' => TRUE,
6a488035
TO
231 ),
232 ),
c301f76e 233 'grouping' => 'contri-fields',
234 'filters' => array(
235 'this_year' => array(
236 'title' => ts('This Year'),
237 'operatorType' => CRM_Report_Form::OP_SELECT,
238 'options' => $optionYear,
239 'default' => '',
240 ),
241 'other_year' => array(
242 'title' => ts('Other Years'),
243 'operatorType' => CRM_Report_Form::OP_SELECT,
244 'options' => $optionYear,
245 'default' => '',
246 ),
247 'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
248 'contribution_status_id' => array(
249 'title' => ts('Contribution Status'),
250 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
251 'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
252 'default' => array(1),
253 ),
254 'financial_type_id' => array(
255 'title' => ts('Financial Type'),
8ee006e7 256 'type' => CRM_Utils_Type::T_INT,
c301f76e 257 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
258 'options' => CRM_Contribute_PseudoConstant::financialType(),
259 ),
260 'total_amount' => array(
261 'title' => ts('Contribution Amount'),
262 ),
263 'total_sum' => array(
264 'title' => ts('Aggregate Amount'),
265 'type' => CRM_Report_Form::OP_INT,
266 'dbAlias' => 'civicrm_contribution_total_amount_sum',
267 'having' => TRUE,
268 ),
269 ),
270 ),
271 );
6a488035 272
9d72cede
EM
273 $this->_columns['civicrm_contribution']['fields']['civicrm_upto_' .
274 $this->_yearStatisticsFrom] = array(
275 'title' => ts('Up To %1 Donation', array(1 => $this->_yearStatisticsFrom)),
6a488035
TO
276 'default' => TRUE,
277 'type' => CRM_Utils_Type::T_MONEY,
278 'is_statistics' => TRUE,
279 );
280
281 $yearConter = $this->_yearStatisticsFrom;
282 $yearConter++;
283 while ($yearConter <= $this->_yearStatisticsTo) {
9d72cede
EM
284 $this->_columns['civicrm_contribution']['fields'][$yearConter] = array(
285 'title' => ts('%1 Donation', array(1 => $yearConter)),
6a488035
TO
286 'default' => TRUE,
287 'type' => CRM_Utils_Type::T_MONEY,
288 'is_statistics' => TRUE,
289 );
290 $yearConter++;
291 }
292
9d72cede
EM
293 $this->_columns['civicrm_contribution']['fields']['aggregate_amount'] = array(
294 'title' => ts('Aggregate Amount'),
6a488035
TO
295 'type' => CRM_Utils_Type::T_MONEY,
296 'is_statistics' => TRUE,
297 );
298
16e2e80c 299 $this->_groupFilter = TRUE;
6a488035
TO
300 $this->_tagFilter = TRUE;
301 parent::__construct();
302 }
303
00be9182 304 public function preProcess() {
6a488035
TO
305 parent::preProcess();
306 }
307
00be9182 308 public function select() {
6a488035
TO
309 $select = array();
310 $this->_columnHeaders = array();
311
312 foreach ($this->_columns as $tableName => $table) {
313 if (array_key_exists('fields', $table)) {
314 foreach ($table['fields'] as $fieldName => $field) {
315
9d72cede
EM
316 if (!empty($field['required']) ||
317 !empty($this->_params['fields'][$fieldName])
318 ) {
6a488035
TO
319 if ($tableName == 'civicrm_address') {
320 $this->_addressField = TRUE;
321 }
322 if ($tableName == 'civicrm_email') {
323 $this->_emailField = TRUE;
324 }
325 if ($tableName == 'civicrm_phone') {
326 $this->_phoneField = TRUE;
327 }
328 if ($tableName == 'civicrm_relationship') {
329 $this->_relationshipColumns["{$tableName}_{$fieldName}"] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
330 $this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
331 $this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
332 continue;
333 }
334
a7488080 335 if (!empty($field['is_statistics'])) {
6a488035
TO
336 $this->_columnHeaders[$fieldName]['type'] = $field['type'];
337 $this->_columnHeaders[$fieldName]['title'] = $field['title'];
338 continue;
339 }
2f4c2f5d 340 elseif ($fieldName == 'receive_date') {
9d72cede
EM
341 if ((CRM_Utils_Array::value('this_year_op', $this->_params) ==
342 'fiscal' && !empty($this->_params['this_year_value'])) ||
343 (CRM_Utils_Array::value('other_year_op', $this->_params ==
344 'fiscal') && !empty($this->_params['other_year_value']))
345 ) {
346 $select[] = self::fiscalYearOffset($field['dbAlias']) .
347 " as {$tableName}_{$fieldName}";
348 }
349 else {
350 $select[] = " YEAR(" . $field['dbAlias'] . ")" .
351 " as {$tableName}_{$fieldName}";
352 }
6a488035 353 }
f480d851
DG
354 elseif ($fieldName == 'total_amount') {
355 $select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}";
356 }
6a488035
TO
357 else {
358 $select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
359 $this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
360 $this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
361 }
a7488080 362 if (!empty($field['no_display'])) {
6a488035
TO
363 $this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = TRUE;
364 }
365 }
366 }
367 }
368 }
369
370 $this->_select = "SELECT " . implode(', ', $select) . " ";
371 }
372
00be9182 373 public function from() {
6a488035
TO
374 $this->_from = "
375 FROM civicrm_contact {$this->_aliases['civicrm_contact']}
2f4c2f5d 376 INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
6a488035
TO
377 ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_contribution']}.contact_id AND
378 {$this->_aliases['civicrm_contribution']}.is_test = 0 ";
379
380 if ($this->_emailField) {
2f4c2f5d 381 $this->_from .= " LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
382 ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
6a488035
TO
383 {$this->_aliases['civicrm_email']}.is_primary = 1) ";
384 }
385
386 if ($this->_phoneField) {
2f4c2f5d 387 $this->_from .= " LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
388 ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
6a488035
TO
389 {$this->_aliases['civicrm_phone']}.is_primary = 1) ";
390 }
391
392 $relContacAlias = 'contact_relationship';
2f4c2f5d 393 $this->_relationshipFrom = " INNER JOIN civicrm_relationship {$this->_aliases['civicrm_relationship']}
6a488035
TO
394 ON (({$this->_aliases['civicrm_relationship']}.contact_id_a = {$relContacAlias}.id OR {$this->_aliases['civicrm_relationship']}.contact_id_b = {$relContacAlias}.id ) AND {$this->_aliases['civicrm_relationship']}.is_active = 1) ";
395
396 if ($this->_addressField) {
397 $this->_from .= "
2f4c2f5d 398 LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
399 ON {$this->_aliases['civicrm_contact']}.id =
400 {$this->_aliases['civicrm_address']}.contact_id AND
6a488035
TO
401 {$this->_aliases['civicrm_address']}.is_primary = 1\n";
402 }
403 }
404
00be9182 405 public function where() {
6a488035
TO
406 $whereClauses = $havingClauses = $relationshipWhere = array();
407 $this->_relationshipWhere = '';
408 $this->_statusClause = '';
409
410 foreach ($this->_columns as $tableName => $table) {
411 if (array_key_exists('filters', $table)) {
412 foreach ($table['filters'] as $fieldName => $field) {
413 $clause = NULL;
414 if ($fieldName == 'this_year' || $fieldName == 'other_year') {
415 continue;
9d72cede 416 }
84178120 417 elseif (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE
9d72cede 418 ) {
6a488035 419 $relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
9d72cede
EM
420 $from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
421 $to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
6a488035
TO
422
423 $clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
424 }
425 else {
426 $op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
427 if ($op) {
428 $clause = $this->whereClause($field,
429 $op,
430 CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
431 CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
432 CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
433 );
434 }
435 }
436
437 if (!empty($clause)) {
438 if ($tableName == 'civicrm_relationship') {
439 $relationshipWhere[] = $clause;
440 continue;
441 }
442
443 if ($fieldName == 'contribution_status_id') {
444 $this->_statusClause = " AND " . $clause;
445 }
446
a7488080 447 if (!empty($field['having'])) {
6a488035
TO
448 $havingClauses[] = $clause;
449 }
450 else {
451 $whereClauses[] = $clause;
452 }
453 }
454 }
455 }
456 }
457
458 if (empty($whereClauses)) {
459 $this->_where = "WHERE ( 1 ) ";
460 $this->_having = "";
461 }
462 else {
463 $this->_where = "WHERE " . implode(' AND ', $whereClauses);
464 }
465
466 if ($this->_aclWhere) {
467 $this->_where .= " AND {$this->_aclWhere} ";
468 }
469
470 if (!empty($havingClauses)) {
471 // use this clause to construct group by clause.
472 $this->_having = "HAVING " . implode(' AND ', $havingClauses);
473 }
474
475 if (!empty($relationshipWhere)) {
9d72cede
EM
476 $this->_relationshipWhere = ' AND ' .
477 implode(' AND ', $relationshipWhere);
6a488035
TO
478 }
479 }
480
00be9182 481 public function groupBy() {
6a488035
TO
482 $this->_groupBy = "GROUP BY {$this->_aliases['civicrm_contribution']}.contact_id, YEAR({$this->_aliases['civicrm_contribution']}.receive_date)";
483 }
484
74cf4551 485 /**
ab432335 486 * Override to set limit to 10.
decced8b 487 *
74cf4551 488 * @param int $rowCount
decced8b 489 *
ab432335 490 * @return array
74cf4551 491 */
00be9182 492 public function limit($rowCount = self::ROW_COUNT_LIMIT) {
ab432335 493 return parent::limit($rowCount);
6a488035
TO
494 }
495
74cf4551 496 /**
ab432335
EM
497 * Override to set pager with limit is 10.
498 *
74cf4551
EM
499 * @param int $rowCount
500 */
00be9182 501 public function setPager($rowCount = self::ROW_COUNT_LIMIT) {
6a488035
TO
502 parent::setPager($rowCount);
503 }
504
74cf4551
EM
505 /**
506 * @param $rows
507 *
508 * @return array
509 */
00be9182 510 public function statistics(&$rows) {
6a488035
TO
511 $statistics = parent::statistics($rows);
512 $count = 0;
513 foreach ($rows as $rownum => $row) {
514 if (is_numeric($rownum)) {
515 $count++;
516 }
517 }
9d72cede
EM
518 $statistics['counts']['rowCount'] = array(
519 'title' => ts('Primary Contact(s) Listed'),
6a488035
TO
520 'value' => $count,
521 );
522
523 if ($this->_rowsFound && ($this->_rowsFound > $count)) {
9d72cede
EM
524 $statistics['counts']['rowsFound'] = array(
525 'title' => ts('Total Primary Contact(s)'),
6a488035
TO
526 'value' => $this->_rowsFound,
527 );
528 }
529
530 return $statistics;
531 }
532
74cf4551
EM
533 /**
534 * @param $fields
535 * @param $files
536 * @param $self
537 *
538 * @return array
539 */
00be9182 540 public static function formRule($fields, $files, $self) {
6a488035 541 $errors = array();
9d72cede
EM
542 if (!empty($fields['this_year_value']) &&
543 !empty($fields['other_year_value']) &&
6a488035
TO
544 ($fields['this_year_value'] == $fields['other_year_value'])
545 ) {
546 $errors['other_year_value'] = ts("Value for filters 'This Year' and 'Other Years' can not be same.");
547 }
548 return $errors;
549 }
550
00be9182 551 public function postProcess() {
6a488035
TO
552 // get ready with post process params
553 $this->beginPostProcess();
554 $this->fixReportParams();
555
556 $this->buildACLClause($this->_aliases['civicrm_contact']);
557 $this->select();
558 $this->where();
559 $this->from();
7e597787 560 $this->customDataFrom();
6a488035
TO
561 $this->groupBy();
562
97fa836c 563 $sql = NULL;
6a488035
TO
564 $rows = array();
565
566 // build array of result based on column headers. This method also allows
567 // modifying column headers before using it to build result set i.e $rows.
97fa836c 568 $this->buildRows($sql, $rows);
6a488035
TO
569
570 // format result set.
571 $this->formatDisplay($rows, FALSE);
572
573 // assign variables to templates
574 $this->doTemplateAssignment($rows);
575
576 // do print / pdf / instance stuff if needed
577 $this->endPostProcess($rows);
578 }
579
00be9182 580 public function fixReportParams() {
a7488080 581 if (!empty($this->_params['this_year_value'])) {
6a488035
TO
582 $this->_referenceYear['this_year'] = $this->_params['this_year_value'];
583 }
a7488080 584 if (!empty($this->_params['other_year_value'])) {
6a488035
TO
585 $this->_referenceYear['other_year'] = $this->_params['other_year_value'];
586 }
587 }
588
74cf4551 589 /**
645ee340 590 * @param $sql
74cf4551
EM
591 * @param $rows
592 */
00be9182 593 public function buildRows($sql, &$rows) {
6a488035
TO
594 $contactIds = array();
595
596 $addWhere = '';
597
a7488080 598 if (!empty($this->_referenceYear['other_year'])) {
9d72cede
EM
599 (CRM_Utils_Array::value('other_year_op', $this->_params) ==
600 'calendar') ? $other_receive_date = 'YEAR (contri.receive_date)' : $other_receive_date = self::fiscalYearOffset('contri.receive_date');
601 $addWhere .= " AND {$this->_aliases['civicrm_contact']}.id NOT IN ( SELECT DISTINCT cont.id FROM civicrm_contact cont, civicrm_contribution contri WHERE cont.id = contri.contact_id AND {$other_receive_date} = {$this->_referenceYear['other_year']} AND contri.is_test = 0 ) ";
6a488035 602 }
a7488080 603 if (!empty($this->_referenceYear['this_year'])) {
9d72cede
EM
604 (CRM_Utils_Array::value('this_year_op', $this->_params) ==
605 'calendar') ? $receive_date = 'YEAR (contri.receive_date)' : $receive_date = self::fiscalYearOffset('contri.receive_date');
606 $addWhere .= " AND {$this->_aliases['civicrm_contact']}.id IN ( SELECT DISTINCT cont.id FROM civicrm_contact cont, civicrm_contribution contri WHERE cont.id = contri.contact_id AND {$receive_date} = {$this->_referenceYear['this_year']} AND contri.is_test = 0 ) ";
2f4c2f5d 607 }
6a488035
TO
608 $this->limit();
609 $getContacts = "SELECT SQL_CALC_FOUND_ROWS {$this->_aliases['civicrm_contact']}.id as cid, SUM({$this->_aliases['civicrm_contribution']}.total_amount) as civicrm_contribution_total_amount_sum {$this->_from} {$this->_where} {$addWhere} GROUP BY {$this->_aliases['civicrm_contact']}.id {$this->_having} {$this->_limit}";
2f4c2f5d 610
6a488035
TO
611 $dao = CRM_Core_DAO::executeQuery($getContacts);
612
613 while ($dao->fetch()) {
614 $contactIds[] = $dao->cid;
615 }
616 $dao->free();
617 $this->setPager();
618
619 $relationshipRows = array();
620 if (empty($contactIds)) {
621 return;
622 }
623
624 $primaryContributions = $this->buildContributionRows($contactIds);
625
626 list($relationshipRows, $relatedContactIds) = $this->buildRelationshipRows($contactIds);
627
628 if (empty($relatedContactIds)) {
629 $rows = $primaryContributions;
630 return;
631 }
632
633 $relatedContributions = $this->buildContributionRows($relatedContactIds);
634
9d72cede 635 $summaryYears = array();
6a488035 636 $summaryYears[] = "civicrm_upto_{$this->_yearStatisticsFrom}";
9d72cede 637 $yearConter = $this->_yearStatisticsFrom;
6a488035
TO
638 $yearConter++;
639 while ($yearConter <= $this->_yearStatisticsTo) {
640 $summaryYears[] = $yearConter;
641 $yearConter++;
642 }
643 $summaryYears[] = 'aggregate_amount';
644
645 foreach ($primaryContributions as $cid => $primaryRow) {
646 $row = $primaryRow;
647 if (!isset($relationshipRows[$cid])) {
648 $rows[$cid] = $row;
649 continue;
650 }
651 $total = array();
652 $total['civicrm_contact_sort_name'] = ts('Total');
653 foreach ($summaryYears as $year) {
654 $total[$year] = CRM_Utils_Array::value($year, $primaryRow, 0);
655 }
656
657 $relatedContact = FALSE;
658 $rows[$cid] = $row;
659 foreach ($relationshipRows[$cid] as $relcid => $relRow) {
660 if (!isset($relatedContributions[$relcid])) {
661 continue;
662 }
663 $relatedContact = TRUE;
664 $relatedRow = $relatedContributions[$relcid];
665 foreach ($summaryYears as $year) {
666 $total[$year] += CRM_Utils_Array::value($year, $relatedRow, 0);
667 }
668
669 foreach (array_keys($this->_relationshipColumns) as $col) {
a7488080 670 if (!empty($relRow[$col])) {
6a488035
TO
671 $relatedRow[$col] = $relRow[$col];
672 }
673 }
674 $rows["{$cid}_{$relcid}"] = $relatedRow;
675 }
676 if ($relatedContact) {
677 $rows["{$cid}_total"] = $total;
678 $rows["{$cid}_bank"] = array('civicrm_contact_sort_name' => '&nbsp;');
679 }
680 }
681 }
682
74cf4551
EM
683 /**
684 * @param $contactIds
685 *
686 * @return array
687 */
00be9182 688 public function buildContributionRows($contactIds) {
6a488035
TO
689 $rows = array();
690 if (empty($contactIds)) {
691 return $rows;
692 }
693
c301f76e 694 $sqlContribution = "{$this->_select} {$this->_from} WHERE {$this->_aliases['civicrm_contact']}.id IN (" .
9d72cede
EM
695 implode(',', $contactIds) .
696 ") AND {$this->_aliases['civicrm_contribution']}.is_test = 0 {$this->_statusClause} {$this->_groupBy} ";
6a488035 697
9d72cede 698 $dao = CRM_Core_DAO::executeQuery($sqlContribution);
6a488035 699 $contributionSum = 0;
9d72cede 700 $yearcal = array();
6a488035
TO
701 while ($dao->fetch()) {
702 if (!$dao->civicrm_contact_id) {
703 continue;
704 }
705
706 foreach ($this->_columnHeaders as $key => $value) {
707 if (property_exists($dao, $key)) {
708 $rows[$dao->civicrm_contact_id][$key] = $dao->$key;
709 }
710 }
711 if ($dao->civicrm_contribution_receive_date) {
9d72cede
EM
712 if ($dao->civicrm_contribution_receive_date >
713 $this->_yearStatisticsFrom
714 ) {
6a488035
TO
715 $rows[$dao->civicrm_contact_id][$dao->civicrm_contribution_receive_date] = $dao->civicrm_contribution_total_amount;
716 }
717 else {
718 if (!isset($rows[$dao->civicrm_contact_id]["civicrm_upto_{$this->_yearStatisticsFrom}"])) {
719 $rows[$dao->civicrm_contact_id]["civicrm_upto_{$this->_yearStatisticsFrom}"] = 0;
720 }
721
722 $rows[$dao->civicrm_contact_id]["civicrm_upto_{$this->_yearStatisticsFrom}"] += $dao->civicrm_contribution_total_amount;
723 }
724 }
725
726 if (!isset($rows[$dao->civicrm_contact_id]['aggregate_amount'])) {
727 $rows[$dao->civicrm_contact_id]['aggregate_amount'] = 0;
728 }
729 $rows[$dao->civicrm_contact_id]['aggregate_amount'] += $dao->civicrm_contribution_total_amount;
730 }
731 $dao->free();
732 return $rows;
733 }
734
74cf4551
EM
735 /**
736 * @param $contactIds
737 *
738 * @return array
739 */
00be9182 740 public function buildRelationshipRows($contactIds) {
6a488035
TO
741 $relationshipRows = $relatedContactIds = array();
742 if (empty($contactIds)) {
743 return array($relationshipRows, $relatedContactIds);
744 }
745
746 $relContactAlias = 'contact_relationship';
747 $addRelSelect = '';
748 if (!empty($this->_relationshipColumns)) {
749 $addRelSelect = ', ' . implode(', ', $this->_relationshipColumns);
750 }
c301f76e 751 $sqlRelationship = "SELECT {$this->_aliases['civicrm_relationship']}.relationship_type_id as relationship_type_id, {$this->_aliases['civicrm_relationship']}.contact_id_a as contact_id_a, {$this->_aliases['civicrm_relationship']}.contact_id_b as contact_id_b {$addRelSelect} FROM civicrm_contact {$relContactAlias} {$this->_relationshipFrom} WHERE {$relContactAlias}.id IN (" .
9d72cede
EM
752 implode(',', $contactIds) .
753 ") AND {$this->_aliases['civicrm_relationship']}.is_active = 1 {$this->_relationshipWhere} GROUP BY {$this->_aliases['civicrm_relationship']}.contact_id_a, {$this->_aliases['civicrm_relationship']}.contact_id_b";
6a488035
TO
754 $relationshipTypes = CRM_Core_PseudoConstant::relationshipType();
755
756 $dao = CRM_Core_DAO::executeQuery($sqlRelationship);
757 while ($dao->fetch()) {
758 $row = array();
759 foreach (array_keys($this->_relationshipColumns) as $rel_column) {
760 $row[$rel_column] = $dao->$rel_column;
761 }
762 if (in_array($dao->contact_id_a, $contactIds)) {
763 $row['civicrm_relationship_relationship_type_id'] = $relationshipTypes[$dao->relationship_type_id]['label_a_b'];
764 $row['civicrm_relationship_contact_id'] = $dao->contact_id_b;
765 $relationshipRows[$dao->contact_id_a][$dao->contact_id_b] = $row;
766 $relatedContactIds[$dao->contact_id_b] = $dao->contact_id_b;
767 }
768 if (in_array($dao->contact_id_b, $contactIds)) {
769 $row['civicrm_relationship_contact_id'] = $dao->contact_id_a;
770 $row['civicrm_relationship_relationship_type_id'] = $relationshipTypes[$dao->relationship_type_id]['label_b_a'];
771 $relationshipRows[$dao->contact_id_b][$dao->contact_id_a] = $row;
772 $relatedContactIds[$dao->contact_id_a] = $dao->contact_id_a;
773 }
774 }
775 $dao->free();
776 return array($relationshipRows, $relatedContactIds);
777 }
2f4c2f5d 778
74cf4551 779 /**
4f1f1f2a 780 * Override "This Year" $op options
74cf4551
EM
781 * @param string $type
782 * @param null $fieldName
783 *
784 * @return array
785 */
00be9182 786 public function getOperationPair($type = "string", $fieldName = NULL) {
0b0b778f 787 if ($fieldName == 'this_year' || $fieldName == 'other_year') {
9d72cede
EM
788 return array(
789 'calendar' => ts('Is Calendar Year'),
21dfd5f5 790 'fiscal' => ts('Fiscal Year Starting'),
9d72cede 791 );
0b0b778f 792 }
793 return parent::getOperationPair($type, $fieldName);
6a488035 794 }
2f4c2f5d 795
74cf4551 796 /**
ced9bfed
EM
797 * Alter display of rows.
798 *
799 * Iterate through the rows retrieved via SQL and make changes for display purposes,
800 * such as rendering contacts as links.
801 *
802 * @param array $rows
803 * Rows generated by SQL, with an array for each row.
74cf4551 804 */
00be9182 805 public function alterDisplay(&$rows) {
6a488035
TO
806 if (empty($rows)) {
807 return;
808 }
809
6a488035
TO
810 $last_primary = NULL;
811 foreach ($rows as $rowNum => $row) {
6e68fe2a 812 //handle gender
813 if (array_key_exists('civicrm_contact_gender_id', $row)) {
814 if ($value = $row['civicrm_contact_gender_id']) {
815 $gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
816 $row['civicrm_contact_gender_id'] = $rows[$rowNum]['civicrm_contact_gender_id'] = $gender[$value];
817 }
818 $entryFound = TRUE;
819 }
820
6a488035
TO
821 // Highlight primary contact and amount row
822 if (is_numeric($rowNum) ||
823 ($last_primary && ($rowNum == "{$last_primary}_total"))
824 ) {
825 if (is_numeric($rowNum)) {
826 $last_primary = $rowNum;
827 }
828 foreach ($row as $key => $value) {
829 if ($key == 'civicrm_contact_id') {
830 continue;
831 }
832 if (empty($value)) {
833 $row[$key] = '';
834 continue;
835 }
836
837 if ($last_primary && ($rowNum == "{$last_primary}_total")) {
838 $value = CRM_Utils_Money::format($value, ' ');
839 }
840 $row[$key] = '<strong>' . $value . '</strong>';
841 }
842 $rows[$rowNum] = $row;
843 }
844
845 // Convert Display name into link
9d72cede
EM
846 if (!empty($row['civicrm_contact_sort_name']) &&
847 !empty($row['civicrm_contact_id'])
848 ) {
6a488035
TO
849 $url = CRM_Report_Utils_Report::getNextUrl('contribute/detail',
850 'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'],
851 $this->_absoluteUrl, $this->_id
852 );
853 $rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
854 $rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contribution Details for this Contact.");
855 }
70bea8e2 856
70bea8e2 857 // display birthday in the configured custom format
858 if (array_key_exists('civicrm_contact_birth_date', $row)) {
859 $birthDate = $row['civicrm_contact_birth_date'];
860 if ($birthDate) {
861 $rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
862 }
863 $entryFound = TRUE;
864 }
865
6a488035
TO
866 }
867 }
96025800 868
9d72cede 869}