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