Merge pull request #9617 from totten/master-19824
[civicrm-core.git] / CRM / Report / Form / Pledge / Summary.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
7e9e8871 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
0f03f337 6 | Copyright CiviCRM LLC (c) 2004-2017 |
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
0f03f337 31 * @copyright CiviCRM LLC (c) 2004-2017
6a488035
TO
32 * $Id$
33 *
34 */
35class CRM_Report_Form_Pledge_Summary extends CRM_Report_Form {
36
37 protected $_summary = NULL;
38 protected $_totalPaid = FALSE;
39 protected $_customGroupExtends = array('Pledge', 'Individual');
40 protected $_customGroupGroupBy = TRUE;
41 protected $_addressField = FALSE;
42 protected $_emailField = FALSE;
43
74cf4551 44 /**
1728e9a0 45 * This report has not been optimised for group filtering.
46 *
47 * The functionality for group filtering has been improved but not
48 * all reports have been adjusted to take care of it. This report has not
49 * and will run an inefficient query until fixed.
50 *
51 * CRM-19170
52 *
53 * @var bool
74cf4551 54 */
1728e9a0 55 protected $groupFilterNotOptimised = TRUE;
56
74cf4551 57 /**
73b448bf 58 * Class constructor.
74cf4551 59 */
00be9182 60 public function __construct() {
6a488035 61 $this->_columns = array(
c301f76e 62 'civicrm_contact' => array(
63 'dao' => 'CRM_Contact_DAO_Contact',
64 'fields' => array(
65 'sort_name' => array(
66 'title' => ts('Contact Name'),
67 'no_repeat' => TRUE,
6a488035 68 ),
c301f76e 69 'postal_greeting_display' => array('title' => ts('Postal Greeting')),
70 'id' => array(
71 'no_display' => TRUE,
72 'required' => TRUE,
6a488035
TO
73 ),
74 ),
c301f76e 75 'grouping' => 'contact-fields',
76 'group_bys' => array(
77 'id' => array('title' => ts('Contact ID')),
78 'sort_name' => array(
79 'title' => ts('Contact Name'),
6a488035
TO
80 ),
81 ),
c301f76e 82 ),
83 'civicrm_email' => array(
84 'dao' => 'CRM_Core_DAO_Email',
85 'fields' => array(
86 'email' => array(
87 'no_repeat' => TRUE,
88 'title' => ts('email'),
6a488035 89 ),
c301f76e 90 ),
91 'grouping' => 'contact-fields',
92 ),
93 'civicrm_pledge' => array(
94 'dao' => 'CRM_Pledge_DAO_Pledge',
95 'fields' => array(
96 'id' => array(
97 'no_display' => TRUE,
98 'required' => FALSE,
6a488035 99 ),
9e335308 100 'financial_type_id' => array(
101 'title' => ts('Financial Type'),
102 ),
c301f76e 103 'currency' => array(
104 'required' => TRUE,
105 'no_display' => TRUE,
106 ),
107 'amount' => array(
108 'title' => ts('Pledge Amount'),
109 'required' => TRUE,
110 'type' => CRM_Utils_Type::T_MONEY,
111 'statistics' => array(
112 'sum' => ts('Aggregate Amount Pledged'),
113 'count' => ts('Pledges'),
114 'avg' => ts('Average'),
9d72cede 115 ),
6a488035 116 ),
c301f76e 117 'frequency_unit' => array(
118 'title' => ts('Frequency Unit'),
119 ),
120 'installments' => array(
121 'title' => ts('Installments'),
122 ),
123 'pledge_create_date' => array(
124 'title' => ts('Pledge Made Date'),
125 ),
126 'start_date' => array(
127 'title' => ts('Pledge Start Date'),
128 'type' => CRM_Utils_Type::T_DATE,
129 ),
130 'end_date' => array(
131 'title' => ts('Pledge End Date'),
132 'type' => CRM_Utils_Type::T_DATE,
133 ),
134 'status_id' => array(
135 'title' => ts('Pledge Status'),
136 ),
6a488035 137 ),
c301f76e 138 'filters' => array(
139 'pledge_create_date' => array(
ccc29f8e 140 'title' => ts('Pledge Made Date'),
c301f76e 141 'operatorType' => CRM_Report_Form::OP_DATE,
142 ),
143 'pledge_amount' => array(
144 'title' => ts('Pledged Amount'),
145 'operatorType' => CRM_Report_Form::OP_INT,
146 ),
147 'currency' => array(
ccc29f8e 148 'title' => ts('Currency'),
c301f76e 149 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
150 'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
151 'default' => NULL,
152 'type' => CRM_Utils_Type::T_STRING,
153 ),
154 'sid' => array(
155 'name' => 'status_id',
156 'title' => ts('Pledge Status'),
525ae77a 157 'type' => CRM_Utils_Type::T_INT,
c301f76e 158 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
159 'options' => CRM_Core_OptionGroup::values('contribution_status'),
160 ),
9e335308 161 'financial_type_id' => array(
162 'title' => ts('Financial Type'),
525ae77a 163 'type' => CRM_Utils_Type::T_INT,
9e335308 164 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
165 'options' => CRM_Contribute_PseudoConstant::financialType(),
166 ),
c301f76e 167 ),
168 'group_bys' => array(
169 'pledge_create_date' => array(
170 'frequency' => TRUE,
171 'default' => TRUE,
172 'chart' => TRUE,
173 ),
174 'frequency_unit' => array(
175 'title' => ts('Frequency Unit'),
176 ),
177 'status_id' => array(
178 'title' => ts('Pledge Status'),
179 ),
a00ead4d
BC
180 'financial_type_id' => array(
181 'title' => ts('Financial Type'),
182 ),
c301f76e 183 ),
184 ),
185 'civicrm_pledge_payment' => array(
186 'dao' => 'CRM_Pledge_DAO_PledgePayment',
187 'fields' => array(
188 'total_paid' => array(
189 'title' => ts('Total Amount Paid'),
190 'type' => CRM_Utils_Type::T_STRING,
191 'dbAlias' => 'sum(pledge_payment_civireport.actual_amount)',
9d72cede 192 ),
6a488035 193 ),
c301f76e 194 ),
195 ) + $this->addAddressFields();
6a488035 196
16e2e80c 197 $this->_groupFilter = TRUE;
6a488035 198 $this->_tagFilter = TRUE;
9bf1940a 199 $this->_currencyColumn = 'civicrm_pledge_currency';
6a488035
TO
200 parent::__construct();
201 }
202
00be9182 203 public function preProcess() {
6a488035
TO
204 parent::preProcess();
205 }
206
00be9182 207 public function select() {
6a488035
TO
208 parent::select();
209 }
210
00be9182 211 public function from() {
6a488035
TO
212 $this->_from = "
213 FROM civicrm_pledge {$this->_aliases['civicrm_pledge']}
2f4c2f5d 214 LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
215 ON ({$this->_aliases['civicrm_contact']}.id =
6a488035
TO
216 {$this->_aliases['civicrm_pledge']}.contact_id )
217 {$this->_aclFrom} ";
218
219 // include address field if address column is to be included
220 if ($this->_addressField) {
221 $this->_from .= "
2f4c2f5d 222 LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
223 ON ({$this->_aliases['civicrm_contact']}.id =
6a488035
TO
224 {$this->_aliases['civicrm_address']}.contact_id) AND
225 {$this->_aliases['civicrm_address']}.is_primary = 1\n";
226 }
227
228 // include email field if email column is to be included
229 if ($this->_emailField) {
230 $this->_from .= "
2f4c2f5d 231 LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
232 ON ({$this->_aliases['civicrm_contact']}.id =
233 {$this->_aliases['civicrm_email']}.contact_id) AND
6a488035
TO
234 {$this->_aliases['civicrm_email']}.is_primary = 1\n";
235 }
236
9d72cede 237 if (!empty($this->_params['fields']['total_paid'])) {
6a488035
TO
238 $this->_from .= "
239 LEFT JOIN civicrm_pledge_payment {$this->_aliases['civicrm_pledge_payment']} ON
240 {$this->_aliases['civicrm_pledge']}.id = {$this->_aliases['civicrm_pledge_payment']}.pledge_id
241 AND {$this->_aliases['civicrm_pledge_payment']}.status_id = 1
242 ";
243 }
244 }
245
00be9182 246 public function groupBy() {
6a488035
TO
247 $this->_groupBy = "";
248 $append = FALSE;
249
250 if (is_array($this->_params['group_bys']) &&
251 !empty($this->_params['group_bys'])
252 ) {
253 foreach ($this->_columns as $tableName => $table) {
254 if (array_key_exists('group_bys', $table)) {
255 foreach ($table['group_bys'] as $fieldName => $field) {
a7488080
CW
256 if (!empty($this->_params['group_bys'][$fieldName])) {
257 if (!empty($field['chart'])) {
6a488035
TO
258 $this->assign('chartSupported', TRUE);
259 }
260
9d72cede
EM
261 if (!empty($table['group_bys'][$fieldName]['frequency']) &&
262 !empty($this->_params['group_bys_freq'][$fieldName])
263 ) {
6a488035
TO
264
265 $append = "YEAR({$field['dbAlias']}),";
266 if (in_array(strtolower($this->_params['group_bys_freq'][$fieldName]),
9d72cede
EM
267 array('year')
268 )) {
6a488035
TO
269 $append = '';
270 }
271 $this->_groupBy[] = "$append {$this->_params['group_bys_freq'][$fieldName]}({$field['dbAlias']})";
272 $append = TRUE;
273 }
274 else {
275 $this->_groupBy[] = $field['dbAlias'];
276 }
277 }
278 }
279 }
280 }
281
282 if (!empty($this->_statFields) &&
9d72cede
EM
283 (($append && count($this->_groupBy) <= 1) || (!$append)) &&
284 !$this->_having
6a488035
TO
285 ) {
286 $this->_rollup = " WITH ROLLUP";
287 }
d1641c51 288 $groupBy = $this->_groupBy;
289 $this->_groupBy = "GROUP BY " . implode(', ', $this->_groupBy);
6a488035
TO
290 }
291 else {
d1641c51 292 $groupBy = "{$this->_aliases['civicrm_contact']}.id";
293 $this->_groupBy = "GROUP BY {$groupBy}";
6a488035 294 }
36d2f4d5 295 $this->_select = CRM_Contact_BAO_Query::appendAnyValueToSelect($this->_selectClauses, $groupBy);
d1641c51 296 $this->_groupBy .= " {$this->_rollup}";
6a488035
TO
297 }
298
74cf4551
EM
299 /**
300 * @param $rows
301 *
302 * @return array
303 */
00be9182 304 public function statistics(&$rows) {
6a488035
TO
305 $statistics = parent::statistics($rows);
306
307 if (!$this->_having) {
308 $select = "
309 SELECT COUNT({$this->_aliases['civicrm_pledge']}.amount ) as count,
310 SUM({$this->_aliases['civicrm_pledge']}.amount ) as amount,
311 ROUND(AVG({$this->_aliases['civicrm_pledge']}.amount), 2) as avg
312 ";
313
314 $sql = "{$select} {$this->_from} {$this->_where}";
9bf1940a 315
6a488035
TO
316 $dao = CRM_Core_DAO::executeQuery($sql);
317
318 if ($dao->fetch()) {
319 $statistics['count']['amount'] = array(
320 'value' => $dao->amount,
ccc29f8e 321 'title' => ts('Total Pledged'),
6a488035
TO
322 'type' => CRM_Utils_Type::T_MONEY,
323 );
324 $statistics['count']['count '] = array(
325 'value' => $dao->count,
ccc29f8e 326 'title' => ts('Total No Pledges'),
6a488035
TO
327 );
328 $statistics['count']['avg '] = array(
329 'value' => $dao->avg,
ccc29f8e 330 'title' => ts('Average'),
6a488035
TO
331 'type' => CRM_Utils_Type::T_MONEY,
332 );
333 }
334 }
335 return $statistics;
336 }
337
00be9182 338 public function where() {
6a488035
TO
339 $clauses = array();
340 foreach ($this->_columns as $tableName => $table) {
341 if (array_key_exists('filters', $table)) {
342 foreach ($table['filters'] as $fieldName => $field) {
343 $clause = NULL;
344 if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
345 $relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
9d72cede
EM
346 $from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
347 $to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
6a488035
TO
348
349 if ($relative || $from || $to) {
350 $clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
351 }
352 }
353 else {
354 $op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
355 if ($op) {
356 $clause = $this->whereClause($field,
357 $op,
358 CRM_Utils_Array::value("{$fieldName}_value",
359 $this->_params
360 ),
361 CRM_Utils_Array::value("{$fieldName}_min",
362 $this->_params
363 ),
364 CRM_Utils_Array::value("{$fieldName}_max",
365 $this->_params
366 )
367 );
368 }
369 }
370
371 if (!empty($clause)) {
372 $clauses[] = $clause;
373 }
374 }
375 }
376 }
377 if (empty($clauses)) {
378 $this->_where = "WHERE ({$this->_aliases['civicrm_pledge']}.is_test=0 ) ";
379 }
380 else {
2f4c2f5d 381 $this->_where = "WHERE ({$this->_aliases['civicrm_pledge']}.is_test=0 ) AND
6a488035
TO
382 " . implode(' AND ', $clauses);
383 }
384
385 if ($this->_aclWhere) {
386 $this->_where .= " AND {$this->_aclWhere} ";
387 }
388 }
389
00be9182 390 public function postProcess() {
6a488035
TO
391 parent::postProcess();
392 }
393
74cf4551 394 /**
ced9bfed
EM
395 * Alter display of rows.
396 *
397 * Iterate through the rows retrieved via SQL and make changes for display purposes,
398 * such as rendering contacts as links.
399 *
400 * @param array $rows
401 * Rows generated by SQL, with an array for each row.
74cf4551 402 */
00be9182 403 public function alterDisplay(&$rows) {
9d72cede
EM
404 $entryFound = FALSE;
405 $checkList = array();
6a488035 406 $display_flag = $prev_cid = $cid = 0;
6a488035
TO
407 foreach ($rows as $rowNum => $row) {
408
409 // convert display name to links
410 if (array_key_exists('civicrm_contact_sort_name', $row) &&
411 array_key_exists('civicrm_contact_id', $row)
412 ) {
413 $url = CRM_Utils_System::url("civicrm/contact/view",
414 'reset=1&cid=' . $row['civicrm_contact_id'],
415 $this->_absoluteUrl
416 );
417 $rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
418 $rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact Summary for this Contact.");
419 $entryFound = TRUE;
420 }
421
9e335308 422 if (array_key_exists('civicrm_pledge_financial_type_id', $row)) {
423 if ($value = $row['civicrm_pledge_financial_type_id']) {
424 $rows[$rowNum]['civicrm_pledge_financial_type_id'] = CRM_Contribute_PseudoConstant::financialType($value, FALSE);
425 }
426 $entryFound = TRUE;
427 }
428
6a488035
TO
429 //handle status id
430 if (array_key_exists('civicrm_pledge_status_id', $row)) {
431 if ($value = $row['civicrm_pledge_status_id']) {
432 $rows[$rowNum]['civicrm_pledge_status_id'] = CRM_Contribute_PseudoConstant::contributionStatus($value);
433 }
434 $entryFound = TRUE;
435 }
436
437 $entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'pledge/summary', 'List all pledge(s) for this ') ? TRUE : $entryFound;
438
439 // skip looking further in rows, if first row itself doesn't
440 // have the column we need
441 if (!$entryFound) {
442 break;
443 }
444 }
445 }
96025800 446
6a488035 447}