CIVI-28 Added permission check for Contribution Summary Report
[civicrm-core.git] / CRM / Report / Form / Contribute / Detail.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_Detail extends CRM_Report_Form {
36 protected $_addressField = FALSE;
37
38 protected $_emailField = FALSE;
6a488035
TO
39
40 protected $_summary = NULL;
acb4ca2f 41 protected $_allBatches = NULL;
6a488035 42
e9b25936
E
43 protected $_softFrom = NULL;
44
70bea8e2 45 protected $_customGroupExtends = array(
46 'Contact',
47 'Individual',
7d793900 48 'Contribution',
70bea8e2 49 );
6a488035 50
74cf4551 51 /**
74cf4551 52 */
00be9182 53 public function __construct() {
70bea8e2 54 $this->_autoIncludeIndexedFieldsAsOrderBys = 1;
f813f78e 55 // Check if CiviCampaign is a) enabled and b) has active campaigns
6a488035
TO
56 $config = CRM_Core_Config::singleton();
57 $campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
58 if ($campaignEnabled) {
59 $getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
60 $this->activeCampaigns = $getCampaigns['campaigns'];
61 asort($this->activeCampaigns);
62 }
63 $this->_columns = array(
a1a2a83d
TO
64 'civicrm_contact' => array(
65 'dao' => 'CRM_Contact_DAO_Contact',
66 'fields' => array(
67 'sort_name' => array(
68 'title' => ts('Donor Name'),
69 'required' => TRUE,
6a488035 70 ),
a1a2a83d
TO
71 'first_name' => array(
72 'title' => ts('First Name'),
6a488035 73 ),
70bea8e2 74 'middle_name' => array(
75 'title' => ts('Middle Name'),
76 ),
a1a2a83d
TO
77 'last_name' => array(
78 'title' => ts('Last Name'),
79 ),
80 'id' => array(
81 'no_display' => TRUE,
82 'required' => TRUE,
83 ),
70bea8e2 84 'gender_id' => array(
85 'title' => ts('Gender'),
86 ),
87 'birth_date' => array(
88 'title' => ts('Birth Date'),
89 ),
90 'age' => array(
91 'title' => ts('Age'),
92 'dbAlias' => 'TIMESTAMPDIFF(YEAR, contact_civireport.birth_date, CURDATE())',
93 ),
a1a2a83d
TO
94 'contact_type' => array(
95 'title' => ts('Contact Type'),
96 ),
97 'contact_sub_type' => array(
98 'title' => ts('Contact Subtype'),
6a488035
TO
99 ),
100 ),
a1a2a83d
TO
101 'filters' => array(
102 'sort_name' => array(
103 'title' => ts('Donor Name'),
104 'operator' => 'like',
105 ),
106 'id' => array(
107 'title' => ts('Contact ID'),
108 'no_display' => TRUE,
109 'type' => CRM_Utils_Type::T_INT,
6a488035 110 ),
70bea8e2 111 'gender_id' => array(
112 'title' => ts('Gender'),
113 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
114 'options' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'),
115 ),
116 'birth_date' => array(
117 'title' => ts('Birth Date'),
118 'operatorType' => CRM_Report_Form::OP_DATE,
119 ),
120 'contact_type' => array(
121 'title' => ts('Contact Type'),
122 ),
123 'contact_sub_type' => array(
124 'title' => ts('Contact Subtype'),
125 ),
6a488035 126 ),
70bea8e2 127 'grouping' => 'contact-fields',
a1a2a83d
TO
128 'order_bys' => array(
129 'sort_name' => array(
130 'title' => ts('Last Name, First Name'),
131 'default' => '1',
132 'default_weight' => '0',
133 'default_order' => 'ASC',
a0e67d3c 134 ),
70bea8e2 135 'first_name' => array(
136 'name' => 'first_name',
137 'title' => ts('First Name'),
138 ),
139 'gender_id' => array(
140 'name' => 'gender_id',
141 'title' => ts('Gender'),
142 ),
143 'birth_date' => array(
144 'name' => 'birth_date',
145 'title' => ts('Birth Date'),
146 ),
147 'contact_type' => array(
148 'title' => ts('Contact Type'),
149 ),
150 'contact_sub_type' => array(
151 'title' => ts('Contact Subtype'),
152 ),
6a488035 153 ),
70bea8e2 154
a1a2a83d
TO
155 ),
156 'civicrm_email' => array(
157 'dao' => 'CRM_Core_DAO_Email',
158 'fields' => array(
159 'email' => array(
160 'title' => ts('Donor Email'),
161 'default' => TRUE,
1ebef749 162 ),
a1a2a83d
TO
163 ),
164 'grouping' => 'contact-fields',
165 ),
166 'civicrm_phone' => array(
167 'dao' => 'CRM_Core_DAO_Phone',
168 'fields' => array(
169 'phone' => array(
170 'title' => ts('Donor Phone'),
171 'default' => TRUE,
172 'no_repeat' => TRUE,
173 ),
174 ),
175 'grouping' => 'contact-fields',
176 ),
177 'civicrm_contribution' => array(
178 'dao' => 'CRM_Contribute_DAO_Contribution',
179 'fields' => array(
180 'contribution_id' => array(
181 'name' => 'id',
182 'no_display' => TRUE,
183 'required' => TRUE,
184 ),
185 'list_contri_id' => array(
186 'name' => 'id',
187 'title' => ts('Contribution ID'),
188 ),
189 'financial_type_id' => array(
190 'title' => ts('Financial Type'),
191 'default' => TRUE,
192 ),
193 'contribution_status_id' => array(
194 'title' => ts('Contribution Status'),
195 ),
196 'contribution_page_id' => array(
197 'title' => ts('Contribution Page'),
198 ),
199 'source' => array(
200 'title' => ts('Source'),
201 ),
202 'payment_instrument_id' => array(
203 'title' => ts('Payment Type'),
204 ),
205 'check_number' => array(
206 'title' => ts('Check Number'),
207 ),
208 'currency' => array(
209 'required' => TRUE,
210 'no_display' => TRUE,
211 ),
212 'trxn_id' => NULL,
213 'receive_date' => array('default' => TRUE),
214 'receipt_date' => NULL,
215 'total_amount' => array(
216 'title' => ts('Amount'),
217 'required' => TRUE,
218 'statistics' => array('sum' => ts('Amount')),
6a488035 219 ),
a1a2a83d
TO
220 'fee_amount' => NULL,
221 'net_amount' => NULL,
222 'contribution_or_soft' => array(
223 'title' => ts('Contribution OR Soft Credit?'),
224 'dbAlias' => "'Contribution'",
225 ),
226 'soft_credits' => array(
227 'title' => ts('Soft Credits'),
228 'dbAlias' => "NULL",
229 ),
230 'soft_credit_for' => array(
231 'title' => ts('Soft Credit For'),
232 'dbAlias' => "NULL",
6a488035 233 ),
6a488035 234 ),
a1a2a83d
TO
235 'filters' => array(
236 'contribution_or_soft' => array(
237 'title' => ts('Contribution OR Soft Credit?'),
238 'clause' => "(1)",
239 'operatorType' => CRM_Report_Form::OP_SELECT,
240 'type' => CRM_Utils_Type::T_STRING,
241 'options' => array(
242 'both' => ts('Both'),
243 'contributions_only' => ts('Contributions Only'),
244 'soft_credits_only' => ts('Soft Credits Only'),
9d72cede 245 ),
51fa20cb 246 ),
a1a2a83d
TO
247 'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
248 'currency' => array(
249 'title' => 'Currency',
250 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
251 'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
252 'default' => NULL,
253 'type' => CRM_Utils_Type::T_STRING,
254 ),
255 'financial_type_id' => array(
256 'title' => ts('Financial Type'),
257 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
258 'options' => CRM_Contribute_PseudoConstant::financialType(),
259 'type' => CRM_Utils_Type::T_INT,
260 ),
261 'contribution_page_id' => array(
262 'title' => ts('Contribution Page'),
263 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
264 'options' => CRM_Contribute_PseudoConstant::contributionPage(),
265 'type' => CRM_Utils_Type::T_INT,
266 ),
267 'payment_instrument_id' => array(
268 'title' => ts('Payment Type'),
269 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
270 'options' => CRM_Contribute_PseudoConstant::paymentInstrument(),
271 'type' => CRM_Utils_Type::T_INT,
272 ),
273 'contribution_status_id' => array(
274 'title' => ts('Contribution Status'),
275 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
276 'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
277 'default' => array(1),
278 'type' => CRM_Utils_Type::T_INT,
279 ),
280 'total_amount' => array('title' => ts('Contribution Amount')),
51fa20cb 281 ),
a1a2a83d
TO
282 'order_bys' => array(
283 'financial_type_id' => array('title' => ts('Financial Type')),
284 'contribution_status_id' => array('title' => ts('Contribution Status')),
536f0e02 285 'payment_instrument_id' => array('title' => ts('Payment Method')),
7bc6b5bb 286 'receive_date' => array('title' => ts('Date Received')),
a1a2a83d
TO
287 ),
288 'grouping' => 'contri-fields',
289 ),
290 'civicrm_contribution_soft' => array(
291 'dao' => 'CRM_Contribute_DAO_ContributionSoft',
292 'fields' => array(
293 'soft_credit_type_id' => array('title' => ts('Soft Credit Type')),
294 ),
295 'filters' => array(
296 'soft_credit_type_id' => array(
297 'title' => 'Soft Credit Type',
298 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
299 'options' => CRM_Core_OptionGroup::values('soft_credit_type'),
300 'default' => NULL,
301 'type' => CRM_Utils_Type::T_STRING,
6a488035
TO
302 ),
303 ),
a1a2a83d
TO
304 ),
305 'civicrm_contribution_ordinality' => array(
306 'dao' => 'CRM_Contribute_DAO_Contribution',
307 'alias' => 'cordinality',
308 'filters' => array(
309 'ordinality' => array(
310 'title' => ts('Contribution Ordinality'),
311 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
312 'options' => array(
313 0 => 'First by Contributor',
314 1 => 'Second or Later by Contributor',
315 ),
316 'type' => CRM_Utils_Type::T_INT,
6a488035 317 ),
a1a2a83d
TO
318 ),
319 ),
320 'civicrm_note' => array(
321 'dao' => 'CRM_Core_DAO_Note',
322 'fields' => array(
323 'contribution_note' => array(
324 'name' => 'note',
325 'title' => ts('Contribution Note'),
326 ),
327 ),
328 'filters' => array(
329 'note' => array(
330 'name' => 'note',
331 'title' => ts('Contribution Note'),
332 'operator' => 'like',
333 'type' => CRM_Utils_Type::T_STRING,
6a488035
TO
334 ),
335 ),
a1a2a83d
TO
336 ),
337 ) + $this->addAddressFields(FALSE);
6a488035 338
16e2e80c 339 $this->_groupFilter = TRUE;
6a488035 340 $this->_tagFilter = TRUE;
1c4d8c3e 341
6a488035 342 // Don't show Batch display column and filter unless batches are being used
acb4ca2f
DG
343 $this->_allBatches = CRM_Batch_BAO_Batch::getBatches();
344 if (!empty($this->_allBatches)) {
6a488035
TO
345 $this->_columns['civicrm_batch']['dao'] = 'CRM_Batch_DAO_Batch';
346 $this->_columns['civicrm_batch']['fields']['batch_id'] = array(
347 'name' => 'id',
1c4d8c3e 348 'title' => ts('Batch Name'),
6a488035
TO
349 );
350 $this->_columns['civicrm_batch']['filters']['bid'] = array(
351 'name' => 'id',
352 'title' => ts('Batch Name'),
353 'type' => CRM_Utils_Type::T_INT,
354 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
acb4ca2f 355 'options' => $this->_allBatches,
6a488035
TO
356 );
357 $this->_columns['civicrm_entity_batch']['dao'] = 'CRM_Batch_DAO_EntityBatch';
358 $this->_columns['civicrm_entity_batch']['fields']['entity_batch_id'] = array(
1c4d8c3e 359 'name' => 'batch_id',
6a488035
TO
360 'default' => TRUE,
361 'no_display' => TRUE,
362 );
363 }
364
9d72cede 365 // If we have active campaigns add those elements to both the fields and filters
6a488035
TO
366 if ($campaignEnabled && !empty($this->activeCampaigns)) {
367 $this->_columns['civicrm_contribution']['fields']['campaign_id'] = array(
368 'title' => ts('Campaign'),
369 'default' => 'false',
370 );
9d72cede
EM
371 $this->_columns['civicrm_contribution']['filters']['campaign_id'] = array(
372 'title' => ts('Campaign'),
6a488035
TO
373 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
374 'options' => $this->activeCampaigns,
375 );
376 $this->_columns['civicrm_contribution']['order_bys']['campaign_id'] = array('title' => ts('Campaign'));
377 }
7a961f19 378
379 $this->_currencyColumn = 'civicrm_contribution_currency';
6a488035
TO
380 parent::__construct();
381 }
382
00be9182 383 public function preProcess() {
6a488035
TO
384 parent::preProcess();
385 }
386
00be9182 387 public function select() {
6a488035 388 $this->_columnHeaders = array();
6a488035 389
f2947aea 390 parent::select();
8e3ad5e0
WA
391 //total_amount was affected by sum as it is considered as one of the stat field
392 //so it is been replaced with correct alias, CRM-13833
393 $this->_select = str_replace("sum({$this->_aliases['civicrm_contribution']}.total_amount)", "{$this->_aliases['civicrm_contribution']}.total_amount", $this->_select);
f2947aea
DS
394 }
395
00be9182 396 public function orderBy() {
f2947aea
DS
397 parent::orderBy();
398
399 // please note this will just add the order-by columns to select query, and not display in column-headers.
400 // This is a solution to not throw fatal errors when there is a column in order-by, not present in select/display columns.
401 foreach ($this->_orderByFields as $orderBy) {
9d72cede
EM
402 if (!array_key_exists($orderBy['name'], $this->_params['fields']) &&
403 empty($orderBy['section'])
404 ) {
f2947aea
DS
405 $this->_select .= ", {$orderBy['dbAlias']} as {$orderBy['tplField']}";
406 }
407 }
6a488035
TO
408 }
409
74cf4551
EM
410 /**
411 * @param bool $softcredit
412 */
00be9182 413 public function from($softcredit = FALSE) {
6a488035
TO
414 $this->_from = "
415 FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}
1c4d8c3e 416 INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
6a488035 417 ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_contribution']}.contact_id AND {$this->_aliases['civicrm_contribution']}.is_test = 0";
51fa20cb 418
9d72cede
EM
419 if (CRM_Utils_Array::value('contribution_or_soft_value', $this->_params) ==
420 'both'
421 ) {
51fa20cb 422 $this->_from .= "\n LEFT JOIN civicrm_contribution_soft contribution_soft_civireport
423 ON contribution_soft_civireport.contribution_id = {$this->_aliases['civicrm_contribution']}.id";
424 }
9d72cede
EM
425 elseif (CRM_Utils_Array::value('contribution_or_soft_value', $this->_params) ==
426 'soft_credits_only'
427 ) {
51fa20cb 428 $this->_from .= "\n INNER JOIN civicrm_contribution_soft contribution_soft_civireport
429 ON contribution_soft_civireport.contribution_id = {$this->_aliases['civicrm_contribution']}.id";
c548e07b 430 }
6a488035 431
70c41bce
DS
432 if ($softcredit) {
433 $this->_from = "
c548e07b 434 FROM civireport_contribution_detail_temp1 temp1_civireport
70c41bce 435 INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
c548e07b
DS
436 ON temp1_civireport.civicrm_contribution_contribution_id = {$this->_aliases['civicrm_contribution']}.id
437 INNER JOIN civicrm_contribution_soft contribution_soft_civireport
438 ON contribution_soft_civireport.contribution_id = {$this->_aliases['civicrm_contribution']}.id
33650a20
J
439 INNER JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
440 ON {$this->_aliases['civicrm_contact']}.id = contribution_soft_civireport.contact_id
441 {$this->_aclFrom}";
70c41bce
DS
442 }
443
6a488035
TO
444 if (!empty($this->_params['ordinality_value'])) {
445 $this->_from .= "
1c4d8c3e 446 INNER JOIN (SELECT c.id, IF(COUNT(oc.id) = 0, 0, 1) AS ordinality FROM civicrm_contribution c LEFT JOIN civicrm_contribution oc ON c.contact_id = oc.contact_id AND oc.receive_date < c.receive_date GROUP BY c.id) {$this->_aliases['civicrm_contribution_ordinality']}
6a488035
TO
447 ON {$this->_aliases['civicrm_contribution_ordinality']}.id = {$this->_aliases['civicrm_contribution']}.id";
448 }
449
850e4640 450 $this->addPhoneFromClause();
6a488035 451
9d72cede
EM
452 if ($this->_addressField OR
453 (!empty($this->_params['state_province_id_value']) OR
454 !empty($this->_params['country_id_value']))
455 ) {
6a488035 456 $this->_from .= "
1c4d8c3e
DL
457 LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
458 ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND
6a488035
TO
459 {$this->_aliases['civicrm_address']}.is_primary = 1\n";
460 }
461
462 if ($this->_emailField) {
1c4d8c3e
DL
463 $this->_from .= "
464 LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
465 ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
6a488035
TO
466 {$this->_aliases['civicrm_email']}.is_primary = 1\n";
467 }
6a488035 468 // include contribution note
9d72cede
EM
469 if (!empty($this->_params['fields']['contribution_note']) ||
470 !empty($this->_params['note_value'])
471 ) {
472 $this->_from .= "
6a488035
TO
473 LEFT JOIN civicrm_note {$this->_aliases['civicrm_note']}
474 ON ( {$this->_aliases['civicrm_note']}.entity_table = 'civicrm_contribution' AND
475 {$this->_aliases['civicrm_contribution']}.id = {$this->_aliases['civicrm_note']}.entity_id )";
476 }
477 //for contribution batches
acb4ca2f 478 if ($this->_allBatches &&
9d72cede
EM
479 (!empty($this->_params['fields']['batch_id']) ||
480 !empty($this->_params['bid_value']))
481 ) {
6a488035 482 $this->_from .= "
acb4ca2f
DG
483 LEFT JOIN civicrm_entity_financial_trxn tx ON (tx.entity_id = {$this->_aliases['civicrm_contribution']}.id AND
484 tx.entity_table = 'civicrm_contribution')
1c4d8c3e 485 LEFT JOIN civicrm_entity_batch {$this->_aliases['civicrm_entity_batch']}
acb4ca2f
DG
486 ON ({$this->_aliases['civicrm_entity_batch']}.entity_id = tx.financial_trxn_id AND
487 {$this->_aliases['civicrm_entity_batch']}.entity_table = 'civicrm_financial_trxn')
1c4d8c3e 488 LEFT JOIN civicrm_batch {$this->_aliases['civicrm_batch']}
6a488035
TO
489 ON {$this->_aliases['civicrm_batch']}.id = {$this->_aliases['civicrm_entity_batch']}.batch_id";
490 }
be78fc2d 491
6a488035
TO
492 }
493
00be9182 494 public function groupBy() {
6a488035
TO
495 $this->_groupBy = " GROUP BY {$this->_aliases['civicrm_contact']}.id, {$this->_aliases['civicrm_contribution']}.id ";
496 }
497
74cf4551
EM
498 /**
499 * @param $rows
500 *
501 * @return array
502 */
00be9182 503 public function statistics(&$rows) {
6a488035
TO
504 $statistics = parent::statistics($rows);
505
7a961f19 506 $totalAmount = $average = array();
507 $count = 0;
6a488035
TO
508 $select = "
509 SELECT COUNT({$this->_aliases['civicrm_contribution']}.total_amount ) as count,
510 SUM( {$this->_aliases['civicrm_contribution']}.total_amount ) as amount,
7a961f19 511 ROUND(AVG({$this->_aliases['civicrm_contribution']}.total_amount), 2) as avg,
512 {$this->_aliases['civicrm_contribution']}.currency as currency
6a488035
TO
513 ";
514
7a961f19 515 $group = "\nGROUP BY {$this->_aliases['civicrm_contribution']}.currency";
516 $sql = "{$select} {$this->_from} {$this->_where} {$group}";
6a488035
TO
517 $dao = CRM_Core_DAO::executeQuery($sql);
518
7a961f19 519 while ($dao->fetch()) {
6c552737 520 $totalAmount[] = CRM_Utils_Money::format($dao->amount, $dao->currency) . " (" .
9d72cede
EM
521 $dao->count . ")";
522 $average[] = CRM_Utils_Money::format($dao->avg, $dao->currency);
1c4d8c3e 523 $count += $dao->count;
6a488035 524 }
7a961f19 525 $statistics['counts']['amount'] = array(
be205937 526 'title' => ts('Total Amount (Contributions)'),
7a961f19 527 'value' => implode(', ', $totalAmount),
528 'type' => CRM_Utils_Type::T_STRING,
529 );
530 $statistics['counts']['count'] = array(
be205937 531 'title' => ts('Total Contributions'),
7a961f19 532 'value' => $count,
533 );
534 $statistics['counts']['avg'] = array(
535 'title' => ts('Average'),
536 'value' => implode(', ', $average),
537 'type' => CRM_Utils_Type::T_STRING,
538 );
6a488035 539
70c41bce 540 // Stats for soft credits
9d72cede
EM
541 if ($this->_softFrom &&
542 CRM_Utils_Array::value('contribution_or_soft_value', $this->_params) !=
543 'contributions_only'
544 ) {
c548e07b 545 $totalAmount = $average = array();
9d72cede 546 $count = 0;
c548e07b 547 $select = "
70c41bce
DS
548SELECT COUNT(contribution_soft_civireport.amount ) as count,
549 SUM(contribution_soft_civireport.amount ) as amount,
550 ROUND(AVG(contribution_soft_civireport.amount), 2) as avg,
551 {$this->_aliases['civicrm_contribution']}.currency as currency";
c548e07b 552 $sql = "
f813f78e 553{$select}
554{$this->_softFrom}
c548e07b
DS
555GROUP BY {$this->_aliases['civicrm_contribution']}.currency";
556 $dao = CRM_Core_DAO::executeQuery($sql);
557 while ($dao->fetch()) {
6c552737 558 $totalAmount[] = CRM_Utils_Money::format($dao->amount, $dao->currency) . " (" .
9d72cede
EM
559 $dao->count . ")";
560 $average[] = CRM_Utils_Money::format($dao->avg, $dao->currency);
c548e07b
DS
561 $count += $dao->count;
562 }
563 $statistics['counts']['softamount'] = array(
564 'title' => ts('Total Amount (Soft Credits)'),
565 'value' => implode(', ', $totalAmount),
566 'type' => CRM_Utils_Type::T_STRING,
567 );
568 $statistics['counts']['softcount'] = array(
569 'title' => ts('Total Soft Credits'),
570 'value' => $count,
571 );
572 $statistics['counts']['softavg'] = array(
573 'title' => ts('Average (Soft Credits)'),
574 'value' => implode(', ', $average),
575 'type' => CRM_Utils_Type::T_STRING,
576 );
70c41bce 577 }
70c41bce 578
6a488035
TO
579 return $statistics;
580 }
581
00be9182 582 public function postProcess() {
6a488035
TO
583 // get the acl clauses built before we assemble the query
584 $this->buildACLClause($this->_aliases['civicrm_contact']);
70c41bce
DS
585
586 $this->beginPostProcess();
f813f78e 587
9d72cede
EM
588 if (CRM_Utils_Array::value('contribution_or_soft_value', $this->_params) ==
589 'contributions_only' &&
590 !empty($this->_params['fields']['soft_credit_type_id'])
591 ) {
51fa20cb 592 unset($this->_params['fields']['soft_credit_type_id']);
593 if (!empty($this->_params['soft_credit_type_id_value'])) {
594 $this->_params['soft_credit_type_id_value'] = array();
595 }
596 }
597
70c41bce
DS
598 // 1. use main contribution query to build temp table 1
599 $sql = $this->buildQuery();
6c552737 600 $tempQuery = 'CREATE TEMPORARY TABLE civireport_contribution_detail_temp1 AS ' . $sql;
70c41bce
DS
601 CRM_Core_DAO::executeQuery($tempQuery);
602 $this->setPager();
603
c548e07b 604 // 2. customize main contribution query for soft credit, and build temp table 2 with soft credit contributions only
70c41bce 605 $this->from(TRUE);
be78fc2d
DL
606 // also include custom group from if included
607 // since this might be included in select
608 $this->customDataFrom();
609
70c41bce
DS
610 $select = str_ireplace('contribution_civireport.total_amount', 'contribution_soft_civireport.amount', $this->_select);
611 $select = str_ireplace("'Contribution' as", "'Soft Credit' as", $select);
612 // we inner join with temp1 to restrict soft contributions to those in temp1 table
51fa20cb 613 $sql = "{$select} {$this->_from} {$this->_where} {$this->_groupBy}";
6c552737 614 $tempQuery = 'CREATE TEMPORARY TABLE civireport_contribution_detail_temp2 AS ' . $sql;
70c41bce 615 CRM_Core_DAO::executeQuery($tempQuery);
9d72cede
EM
616 if (CRM_Utils_Array::value('contribution_or_soft_value', $this->_params) ==
617 'soft_credits_only'
618 ) {
c548e07b
DS
619 // revise pager : prev, next based on soft-credits only
620 $this->setPager();
f813f78e 621 }
70c41bce
DS
622
623 // copy _from for later use of stats calculation for soft credits, and reset $this->_from to main query
624 $this->_softFrom = $this->_from;
c93f6d83
DL
625
626 // simple reset of ->_from
627 $this->from();
be78fc2d
DL
628
629 // also include custom group from if included
630 // since this might be included in select
c93f6d83 631 $this->customDataFrom();
70c41bce 632
c548e07b 633 // 3. Decide where to populate temp3 table from
9d72cede
EM
634 if (CRM_Utils_Array::value('contribution_or_soft_value', $this->_params) ==
635 'contributions_only'
636 ) {
1ebef749 637 $tempQuery = "(SELECT * FROM civireport_contribution_detail_temp1)";
9d72cede 638 }
4c9b6178 639 elseif (CRM_Utils_Array::value('contribution_or_soft_value', $this->_params) ==
9d72cede
EM
640 'soft_credits_only'
641 ) {
1ebef749 642 $tempQuery = "(SELECT * FROM civireport_contribution_detail_temp2)";
9d72cede
EM
643 }
644 else {
c548e07b 645 $tempQuery = "
1ebef749 646(SELECT * FROM civireport_contribution_detail_temp1)
c548e07b 647UNION ALL
1ebef749 648(SELECT * FROM civireport_contribution_detail_temp2)";
c548e07b
DS
649 }
650
651 // 4. build temp table 3
1ebef749
DS
652 $sql = "CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 AS {$tempQuery}";
653 CRM_Core_DAO::executeQuery($sql);
654
655 // 5. Re-construct order-by to make sense for final query on temp3 table
656 $orderBy = '';
657 if (!empty($this->_orderByArray)) {
658 $aliases = array_flip($this->_aliases);
659 $orderClause = array();
660 foreach ($this->_orderByArray as $clause) {
661 list($alias, $rest) = explode('.', $clause);
662 $orderClause[] = $aliases[$alias] . "_" . $rest;
663 }
84178120 664 $orderBy = (!empty($orderClause)) ? "ORDER BY " . implode(', ', $orderClause) : '';
70c41bce
DS
665 }
666
1ebef749 667 // 6. show result set from temp table 3
70c41bce 668 $rows = array();
9d72cede 669 $sql = "SELECT * FROM civireport_contribution_detail_temp3 {$orderBy}";
70c41bce
DS
670 $this->buildRows($sql, $rows);
671
672 // format result set.
673 $this->formatDisplay($rows, FALSE);
674
675 // assign variables to templates
676 $this->doTemplateAssignment($rows);
677
678 // do print / pdf / instance stuff if needed
679 $this->endPostProcess($rows);
6a488035
TO
680 }
681
74cf4551 682 /**
ced9bfed
EM
683 * Alter display of rows.
684 *
685 * Iterate through the rows retrieved via SQL and make changes for display purposes,
686 * such as rendering contacts as links.
687 *
688 * @param array $rows
689 * Rows generated by SQL, with an array for each row.
74cf4551 690 */
00be9182 691 public function alterDisplay(&$rows) {
9d72cede
EM
692 $checkList = array();
693 $entryFound = FALSE;
694 $display_flag = $prev_cid = $cid = 0;
695 $contributionTypes = CRM_Contribute_PseudoConstant::financialType();
6a488035
TO
696 $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus();
697 $paymentInstruments = CRM_Contribute_PseudoConstant::paymentInstrument();
9d72cede 698 $contributionPages = CRM_Contribute_PseudoConstant::contributionPage();
6a488035
TO
699
700 foreach ($rows as $rowNum => $row) {
701 if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
702 // don't repeat contact details if its same as the previous row
703 if (array_key_exists('civicrm_contact_id', $row)) {
704 if ($cid = $row['civicrm_contact_id']) {
705 if ($rowNum == 0) {
706 $prev_cid = $cid;
707 }
708 else {
709 if ($prev_cid == $cid) {
710 $display_flag = 1;
711 $prev_cid = $cid;
712 }
713 else {
714 $display_flag = 0;
715 $prev_cid = $cid;
716 }
717 }
718
719 if ($display_flag) {
720 foreach ($row as $colName => $colVal) {
721 // Hide repeats in no-repeat columns, but not if the field's a section header
9d72cede
EM
722 if (in_array($colName, $this->_noRepeats) &&
723 !array_key_exists($colName, $this->_sections)
724 ) {
6a488035
TO
725 unset($rows[$rowNum][$colName]);
726 }
727 }
728 }
729 $entryFound = TRUE;
730 }
731 }
732 }
733
9d72cede
EM
734 if (CRM_Utils_Array::value('civicrm_contribution_contribution_or_soft', $rows[$rowNum]) ==
735 'Contribution'
736 ) {
8e3ad5e0
WA
737 unset($rows[$rowNum]['civicrm_contribution_soft_soft_credit_type_id']);
738 }
6a488035
TO
739
740 // convert donor sort name to link
9d72cede
EM
741 if (array_key_exists('civicrm_contact_sort_name', $row) &&
742 !empty($rows[$rowNum]['civicrm_contact_sort_name']) &&
6a488035
TO
743 array_key_exists('civicrm_contact_id', $row)
744 ) {
745 $url = CRM_Utils_System::url("civicrm/contact/view",
746 'reset=1&cid=' . $row['civicrm_contact_id'],
747 $this->_absoluteUrl
748 );
749 $rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
750 $rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact Summary for this Contact.");
751 }
752
6a488035
TO
753 if ($value = CRM_Utils_Array::value('civicrm_contribution_financial_type_id', $row)) {
754 $rows[$rowNum]['civicrm_contribution_financial_type_id'] = $contributionTypes[$value];
755 $entryFound = TRUE;
756 }
757 if ($value = CRM_Utils_Array::value('civicrm_contribution_contribution_status_id', $row)) {
758 $rows[$rowNum]['civicrm_contribution_contribution_status_id'] = $contributionStatus[$value];
759 $entryFound = TRUE;
760 }
0d0e945a
DG
761 if ($value = CRM_Utils_Array::value('civicrm_contribution_contribution_page_id', $row)) {
762 $rows[$rowNum]['civicrm_contribution_contribution_page_id'] = $contributionPages[$value];
763 $entryFound = TRUE;
764 }
6a488035
TO
765 if ($value = CRM_Utils_Array::value('civicrm_contribution_payment_instrument_id', $row)) {
766 $rows[$rowNum]['civicrm_contribution_payment_instrument_id'] = $paymentInstruments[$value];
767 $entryFound = TRUE;
768 }
6a488035
TO
769 if (array_key_exists('civicrm_batch_batch_id', $row)) {
770 if ($value = $row['civicrm_batch_batch_id']) {
771 $rows[$rowNum]['civicrm_batch_batch_id'] = CRM_Core_DAO::getFieldValue('CRM_Batch_DAO_Batch', $value, 'title');
772 }
773 $entryFound = TRUE;
774 }
775
776 // Contribution amount links to viewing contribution
777 if (($value = CRM_Utils_Array::value('civicrm_contribution_total_amount_sum', $row)) &&
778 CRM_Core_Permission::check('access CiviContribute')
779 ) {
780 $url = CRM_Utils_System::url("civicrm/contact/view/contribution",
9d72cede
EM
781 "reset=1&id=" . $row['civicrm_contribution_contribution_id'] .
782 "&cid=" . $row['civicrm_contact_id'] .
783 "&action=view&context=contribution&selectedChild=contribute",
6a488035
TO
784 $this->_absoluteUrl
785 );
786 $rows[$rowNum]['civicrm_contribution_total_amount_sum_link'] = $url;
787 $rows[$rowNum]['civicrm_contribution_total_amount_sum_hover'] = ts("View Details of this Contribution.");
788 $entryFound = TRUE;
789 }
790
791 // convert campaign_id to campaign title
792 if (array_key_exists('civicrm_contribution_campaign_id', $row)) {
793 if ($value = $row['civicrm_contribution_campaign_id']) {
794 $rows[$rowNum]['civicrm_contribution_campaign_id'] = $this->activeCampaigns[$value];
795 $entryFound = TRUE;
796 }
797 }
798
70c41bce
DS
799 // soft credits
800 if (array_key_exists('civicrm_contribution_soft_credits', $row) &&
9d72cede
EM
801 'Contribution' ==
802 CRM_Utils_Array::value('civicrm_contribution_contribution_or_soft', $rows[$rowNum]) &&
70c41bce
DS
803 array_key_exists('civicrm_contribution_contribution_id', $row)
804 ) {
805 $query = "
f813f78e 806SELECT civicrm_contact_id, civicrm_contact_sort_name, civicrm_contribution_total_amount_sum, civicrm_contribution_currency
70c41bce
DS
807FROM civireport_contribution_detail_temp2
808WHERE civicrm_contribution_contribution_id={$row['civicrm_contribution_contribution_id']}";
9d72cede 809 $dao = CRM_Core_DAO::executeQuery($query);
70c41bce 810 $string = '';
1ebef749 811 $separator = ($this->_outputMode !== 'csv') ? "<br/>" : ' ';
70c41bce 812 while ($dao->fetch()) {
9d72cede
EM
813 $url = CRM_Utils_System::url("civicrm/contact/view", 'reset=1&cid=' .
814 $dao->civicrm_contact_id);
815 $string = $string . ($string ? $separator : '') .
816 "<a href='{$url}'>{$dao->civicrm_contact_sort_name}</a> " .
c548e07b 817 CRM_Utils_Money::format($dao->civicrm_contribution_total_amount_sum, $dao->civicrm_contribution_currency);
70c41bce
DS
818 }
819 $rows[$rowNum]['civicrm_contribution_soft_credits'] = $string;
820 }
821
822 if (array_key_exists('civicrm_contribution_soft_credit_for', $row) &&
9d72cede
EM
823 'Soft Credit' ==
824 CRM_Utils_Array::value('civicrm_contribution_contribution_or_soft', $rows[$rowNum]) &&
70c41bce
DS
825 array_key_exists('civicrm_contribution_contribution_id', $row)
826 ) {
827 $query = "
f813f78e 828SELECT civicrm_contact_id, civicrm_contact_sort_name
70c41bce
DS
829FROM civireport_contribution_detail_temp1
830WHERE civicrm_contribution_contribution_id={$row['civicrm_contribution_contribution_id']}";
9d72cede 831 $dao = CRM_Core_DAO::executeQuery($query);
70c41bce
DS
832 $string = '';
833 while ($dao->fetch()) {
9d72cede
EM
834 $url = CRM_Utils_System::url("civicrm/contact/view", 'reset=1&cid=' .
835 $dao->civicrm_contact_id);
836 $string = $string .
837 "\n<a href='{$url}'>{$dao->civicrm_contact_sort_name}</a>";
70c41bce
DS
838 }
839 $rows[$rowNum]['civicrm_contribution_soft_credit_for'] = $string;
840 }
841
51fa20cb 842 //convert soft_credit_type_id into label
843 if (array_key_exists('civicrm_contribution_soft_soft_credit_type_id', $rows[$rowNum])) {
7a4192f7 844 $rows[$rowNum]['civicrm_contribution_soft_soft_credit_type_id'] = CRM_Core_PseudoConstant::getLabel(
845 'CRM_Contribute_BAO_ContributionSoft',
846 'soft_credit_type_id',
847 $row['civicrm_contribution_soft_soft_credit_type_id']
848 );
51fa20cb 849 }
850
6a488035
TO
851 $entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'contribute/detail', 'List all contribution(s) for this ') ? TRUE : $entryFound;
852
70bea8e2 853 //handle gender
854 if (array_key_exists('civicrm_contact_gender_id', $row)) {
855 if ($value = $row['civicrm_contact_gender_id']) {
856 $gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
857 $rows[$rowNum]['civicrm_contact_gender_id'] = $gender[$value];
858 }
859 $entryFound = TRUE;
860 }
861
862 // display birthday in the configured custom format
863 if (array_key_exists('civicrm_contact_birth_date', $row)) {
864 $birthDate = $row['civicrm_contact_birth_date'];
865 if ($birthDate) {
866 $rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
867 }
868 $entryFound = TRUE;
869 }
870
6a488035
TO
871 // skip looking further in rows, if first row itself doesn't
872 // have the column we need
873 if (!$entryFound) {
874 break;
875 }
876 $lastKey = $rowNum;
877 }
878 }
1c4d8c3e 879
00be9182 880 public function sectionTotals() {
6a488035
TO
881
882 // Reports using order_bys with sections must populate $this->_selectAliases in select() method.
883 if (empty($this->_selectAliases)) {
884 return;
885 }
886
887 if (!empty($this->_sections)) {
888 // build the query with no LIMIT clause
9d72cede 889 $select = str_ireplace('SELECT SQL_CALC_FOUND_ROWS ', 'SELECT ', $this->_select);
6a488035
TO
890 $sql = "{$select} {$this->_from} {$this->_where} {$this->_groupBy} {$this->_having} {$this->_orderBy}";
891
892 // pull section aliases out of $this->_sections
893 $sectionAliases = array_keys($this->_sections);
894
895 $ifnulls = array();
896 foreach (array_merge($sectionAliases, $this->_selectAliases) as $alias) {
897 $ifnulls[] = "ifnull($alias, '') as $alias";
898 }
899
900 /* Group (un-limited) report by all aliases and get counts. This might
e70a7fc0
TO
901 * be done more efficiently when the contents of $sql are known, ie. by
902 * overriding this method in the report class.
903 */
6a488035
TO
904
905 $addtotals = '';
906
9d72cede
EM
907 if (array_search("civicrm_contribution_total_amount_sum", $this->_selectAliases) !==
908 FALSE
909 ) {
6a488035
TO
910 $addtotals = ", sum(civicrm_contribution_total_amount_sum) as sumcontribs";
911 $showsumcontribs = TRUE;
912 }
913
914 $query = "select "
915 . implode(", ", $ifnulls)
9d72cede
EM
916 .
917 "$addtotals, count(*) as ct from civireport_contribution_detail_temp3 group by " .
918 implode(", ", $sectionAliases);
6a488035
TO
919 // initialize array of total counts
920 $sumcontribs = $totals = array();
921 $dao = CRM_Core_DAO::executeQuery($query);
922 while ($dao->fetch()) {
923
924 // let $this->_alterDisplay translate any integer ids to human-readable values.
925 $rows[0] = $dao->toArray();
926 $this->alterDisplay($rows);
927 $row = $rows[0];
928
929 // add totals for all permutations of section values
930 $values = array();
931 $i = 1;
932 $aliasCount = count($sectionAliases);
933 foreach ($sectionAliases as $alias) {
934 $values[] = $row[$alias];
935 $key = implode(CRM_Core_DAO::VALUE_SEPARATOR, $values);
936 if ($i == $aliasCount) {
937 // the last alias is the lowest-level section header; use count as-is
938 $totals[$key] = $dao->ct;
9d72cede
EM
939 if ($showsumcontribs) {
940 $sumcontribs[$key] = $dao->sumcontribs;
941 }
1c4d8c3e 942 }
6a488035
TO
943 else {
944 // other aliases are higher level; roll count into their total
84178120 945 $totals[$key] = (array_key_exists($key, $totals)) ? $totals[$key] + $dao->ct : $dao->ct;
1c4d8c3e 946 if ($showsumcontribs) {
84178120 947 $sumcontribs[$key] = array_key_exists($key, $sumcontribs) ? $sumcontribs[$key] + $dao->sumcontribs : $dao->sumcontribs;
6a488035
TO
948 }
949 }
950 }
951 }
952 if ($showsumcontribs) {
953 $totalandsum = array();
0161a899
ML
954 // ts exception to avoid having ts("%1 %2: %3")
955 $title = '%1 contributions / soft-credits: %2';
956
9d72cede
EM
957 if (CRM_Utils_Array::value('contribution_or_soft_value', $this->_params) ==
958 'contributions_only'
959 ) {
0161a899 960 $title = '%1 contributions: %2';
9d72cede 961 }
4c9b6178 962 elseif (CRM_Utils_Array::value('contribution_or_soft_value', $this->_params) ==
9d72cede
EM
963 'soft_credits_only'
964 ) {
0161a899 965 $title = '%1 soft-credits: %2';
bec9ef32 966 }
6a488035 967 foreach ($totals as $key => $total) {
0161a899 968 $totalandsum[$key] = ts($title, array(
1c4d8c3e 969 1 => $total,
21dfd5f5 970 2 => CRM_Utils_Money::format($sumcontribs[$key]),
10a5be27 971 ));
6a488035
TO
972 }
973 $this->assign('sectionTotals', $totalandsum);
974 }
975 else {
976 $this->assign('sectionTotals', $totals);
977 }
978 }
979 }
96025800 980
6a488035 981}