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