Merge pull request #4940 from mlutfy/crm15824
[civicrm-core.git] / CRM / Report / Form / Contribute / SoftCredit.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
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 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35class CRM_Report_Form_Contribute_SoftCredit extends CRM_Report_Form {
36
37 protected $_emailField = FALSE;
38 protected $_emailFieldCredit = FALSE;
39 protected $_phoneField = FALSE;
40 protected $_phoneFieldCredit = FALSE;
41 protected $_charts = array(
42 '' => 'Tabular',
43 'barChart' => 'Bar Chart',
44 'pieChart' => 'Pie Chart',
f813f78e 45 );
6a488035 46 public $_drilldownReport = array('contribute/detail' => 'Link to Detail Report');
f813f78e 47
74cf4551 48 /**
74cf4551
EM
49 */
50 /**
74cf4551 51 */
00be9182 52 public function __construct() {
d62fab33
RN
53
54 // Check if CiviCampaign is a) enabled and b) has active campaigns
55 $config = CRM_Core_Config::singleton();
56 $campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
57 if ($campaignEnabled) {
58 $getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
59 $this->activeCampaigns = $getCampaigns['campaigns'];
60 asort($this->activeCampaigns);
f813f78e 61 }
d62fab33 62
6a488035 63 $this->_columns = array(
9d72cede 64 'civicrm_contact' => array(
6a488035 65 'dao' => 'CRM_Contact_DAO_Contact',
9d72cede
EM
66 'fields' => array(
67 'display_name_creditor' => array(
68 'title' => ts('Soft Credit Name'),
6a488035
TO
69 'name' => 'sort_name',
70 'alias' => 'contact_civireport',
71 'required' => TRUE,
72 'no_repeat' => TRUE,
73 ),
9d72cede
EM
74 'id_creditor' => array(
75 'title' => ts('Soft Credit Id'),
6a488035
TO
76 'name' => 'id',
77 'alias' => 'contact_civireport',
78 'no_display' => TRUE,
79 'required' => TRUE,
80 ),
9d72cede
EM
81 'display_name_constituent' => array(
82 'title' => ts('Contributor Name'),
6a488035
TO
83 'name' => 'sort_name',
84 'alias' => 'constituentname',
85 'required' => TRUE,
86 ),
9d72cede
EM
87 'id_constituent' => array(
88 'title' => ts('Const Id'),
6a488035
TO
89 'name' => 'id',
90 'alias' => 'constituentname',
91 'no_display' => TRUE,
92 'required' => TRUE,
93 ),
9d72cede 94 'contact_type' => array(
30f85891
RN
95 'title' => ts('Contact Type'),
96 ),
9d72cede 97 'contact_sub_type' => array(
b8f96eb8 98 'title' => ts('Contact Subtype'),
30f85891 99 ),
6a488035 100 ),
9d72cede
EM
101 'filters' => array(
102 'sort_name' => array(
73f4acb4 103 'name' => 'sort_name',
21dfd5f5 104 'title' => ts('Soft Credit Name'),
73f4acb4
S
105 ),
106 ),
6a488035
TO
107 'grouping' => 'contact-fields',
108 ),
9d72cede 109 'civicrm_email' => array(
6a488035 110 'dao' => 'CRM_Core_DAO_Email',
9d72cede
EM
111 'fields' => array(
112 'email_creditor' => array(
113 'title' => ts('Soft Credit Email'),
6a488035
TO
114 'name' => 'email',
115 'alias' => 'emailcredit',
116 'default' => TRUE,
117 'no_repeat' => TRUE,
118 ),
9d72cede
EM
119 'email_constituent' => array(
120 'title' => ts('Contributor\'s Email'),
6a488035
TO
121 'name' => 'email',
122 'alias' => 'emailconst',
123 ),
124 ),
125 'grouping' => 'contact-fields',
126 ),
9d72cede 127 'civicrm_phone' => array(
6a488035 128 'dao' => 'CRM_Core_DAO_Phone',
9d72cede
EM
129 'fields' => array(
130 'phone_creditor' => array(
131 'title' => ts('Soft Credit Phone'),
6a488035
TO
132 'name' => 'phone',
133 'alias' => 'pcredit',
134 'default' => TRUE,
135 ),
9d72cede
EM
136 'phone_constituent' => array(
137 'title' => ts('Contributor\'s Phone'),
6a488035
TO
138 'name' => 'phone',
139 'alias' => 'pconst',
140 'no_repeat' => TRUE,
141 ),
142 ),
143 'grouping' => 'contact-fields',
144 ),
9d72cede
EM
145 'civicrm_financial_type' => array(
146 'dao' => 'CRM_Financial_DAO_FinancialType',
84178120 147 'fields' => array('financial_type' => NULL),
9d72cede
EM
148 'filters' => array(
149 'id' => array(
6a488035 150 'name' => 'id',
b914f4e8 151 'title' => ts('Financial Type'),
6a488035 152 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
21dfd5f5 153 'options' => CRM_Contribute_PseudoConstant::financialType(),
b914f4e8
PN
154 ),
155 ),
6a488035
TO
156 'grouping' => 'softcredit-fields',
157 ),
9d72cede 158 'civicrm_contribution' => array(
6a488035 159 'dao' => 'CRM_Contribute_DAO_Contribution',
9d72cede 160 'fields' => array(
6a488035 161 'contribution_source' => NULL,
c6348f97 162 'currency' => array(
163 'required' => TRUE,
164 'no_display' => TRUE,
165 ),
9d72cede
EM
166 'total_amount' => array(
167 'title' => ts('Amount Statistics'),
6a488035 168 'default' => TRUE,
9d72cede
EM
169 'statistics' => array(
170 'sum' => ts('Aggregate Amount'),
be205937 171 'count' => ts('Contributions'),
6a488035
TO
172 'avg' => ts('Average'),
173 ),
174 ),
175 ),
176 'grouping' => 'softcredit-fields',
9d72cede
EM
177 'filters' => array(
178 'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
179 'currency' => array(
180 'title' => 'Currency',
c6348f97 181 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
182 'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
d1b0931b 183 'default' => NULL,
c6348f97 184 'type' => CRM_Utils_Type::T_STRING,
185 ),
9d72cede
EM
186 'contribution_status_id' => array(
187 'title' => ts('Contribution Status'),
6a488035
TO
188 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
189 'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
190 'default' => array(1),
191 ),
9d72cede
EM
192 'total_amount' => array(
193 'title' => ts('Contribution Amount'),
6a488035
TO
194 ),
195 ),
196 ),
9d72cede 197 'civicrm_contribution_soft' => array(
6a488035 198 'dao' => 'CRM_Contribute_DAO_ContributionSoft',
9d72cede
EM
199 'fields' => array(
200 'contribution_id' => array(
201 'title' => ts('Contribution ID'),
6a488035
TO
202 'no_display' => TRUE,
203 'default' => TRUE,
204 ),
9d72cede 205 'id' => array(
6a488035
TO
206 'default' => TRUE,
207 'no_display' => TRUE,
208 ),
51fa20cb 209 'soft_credit_type_id' => array('title' => ts('Soft Credit Type')),
210 ),
9d72cede
EM
211 'filters' => array(
212 'soft_credit_type_id' => array(
213 'title' => 'Soft Credit Type',
51fa20cb 214 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
215 'options' => CRM_Core_OptionGroup::values('soft_credit_type'),
216 'default' => NULL,
217 'type' => CRM_Utils_Type::T_STRING,
218 ),
6a488035
TO
219 ),
220 'grouping' => 'softcredit-fields',
221 ),
6a488035
TO
222 );
223
d62fab33
RN
224 // If we have a campaign, build out the relevant elements
225 if ($campaignEnabled && !empty($this->activeCampaigns)) {
226 $this->_columns['civicrm_contribution']['fields']['campaign_id'] = array(
227 'title' => ts('Campaign'),
228 'default' => 'false',
229 );
9d72cede
EM
230 $this->_columns['civicrm_contribution']['filters']['campaign_id'] = array(
231 'title' => ts('Campaign'),
d62fab33
RN
232 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
233 'options' => $this->activeCampaigns,
234 );
235 }
236
16e2e80c 237 $this->_groupFilter = TRUE;
6a488035 238 $this->_tagFilter = TRUE;
c6348f97 239
240 $this->_currencyColumn = 'civicrm_contribution_currency';
6a488035
TO
241 parent::__construct();
242 }
243
00be9182 244 public function preProcess() {
6a488035
TO
245 parent::preProcess();
246 }
247
00be9182 248 public function select() {
6a488035
TO
249 $select = array();
250 $this->_columnHeaders = array();
251 foreach ($this->_columns as $tableName => $table) {
252 if (array_key_exists('fields', $table)) {
253 foreach ($table['fields'] as $fieldName => $field) {
9d72cede
EM
254 if (!empty($field['required']) ||
255 !empty($this->_params['fields'][$fieldName])
256 ) {
6a488035
TO
257
258 // include email column if set
259 if ($tableName == 'civicrm_email') {
260 $this->_emailField = TRUE;
261 $this->_emailFieldCredit = TRUE;
262 }
263 elseif ($tableName == 'civicrm_email_creditor') {
264 $this->_emailFieldCredit = TRUE;
265 }
266
267 // include phone columns if set
268 if ($tableName == 'civicrm_phone') {
269 $this->_phoneField = TRUE;
270 $this->_phoneFieldCredit = TRUE;
271 }
272 elseif ($tableName == 'civicrm_phone_creditor') {
273 $this->_phoneFieldCredit = TRUE;
274 }
275
276 // only include statistics columns if set
a7488080 277 if (!empty($field['statistics'])) {
6a488035
TO
278 foreach ($field['statistics'] as $stat => $label) {
279 switch (strtolower($stat)) {
280 case 'sum':
281 $select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
282 $this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
283 $this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
284 $this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
285 break;
286
287 case 'count':
288 $select[] = "COUNT({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
289 $this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = CRM_Utils_Type::T_INT;
290 $this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
291 $this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
292 break;
293
294 case 'avg':
295 $select[] = "ROUND(AVG({$field['dbAlias']}),2) as {$tableName}_{$fieldName}_{$stat}";
296 $this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
297 $this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
298 $this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
299 break;
300 }
301 }
302 }
303 else {
304 $select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
305 $this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
306 $this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
307 }
308 }
309 }
310 }
311 }
312
c6348f97 313 $this->_select = 'SELECT ' . implode(', ', $select) . ' ';
6a488035
TO
314 }
315
74cf4551
EM
316 /**
317 * @param $fields
318 * @param $files
319 * @param $self
320 *
321 * @return array
322 */
00be9182 323 public static function formRule($fields, $files, $self) {
6a488035
TO
324 $errors = $grouping = array();
325 return $errors;
326 }
327
00be9182 328 public function from() {
6a488035 329 $alias_constituent = 'constituentname';
9d72cede
EM
330 $alias_creditor = 'contact_civireport';
331 $this->_from = "
6a488035 332 FROM civicrm_contribution {$this->_aliases['civicrm_contribution']}
f813f78e 333 INNER JOIN civicrm_contribution_soft {$this->_aliases['civicrm_contribution_soft']}
334 ON {$this->_aliases['civicrm_contribution_soft']}.contribution_id =
6a488035 335 {$this->_aliases['civicrm_contribution']}.id
f813f78e 336 INNER JOIN civicrm_contact {$alias_constituent}
337 ON {$this->_aliases['civicrm_contribution']}.contact_id =
6a488035 338 {$alias_constituent}.id
f813f78e 339 LEFT JOIN civicrm_financial_type {$this->_aliases['civicrm_financial_type']}
340 ON {$this->_aliases['civicrm_contribution']}.financial_type_id =
6a488035
TO
341 {$this->_aliases['civicrm_financial_type']}.id
342 LEFT JOIN civicrm_contact {$alias_creditor}
f813f78e 343 ON {$this->_aliases['civicrm_contribution_soft']}.contact_id =
344 {$alias_creditor}.id
6a488035
TO
345 {$this->_aclFrom} ";
346
347 // include Constituent email field if email column is to be included
348 if ($this->_emailField) {
349 $alias = 'emailconst';
350 $this->_from .= "
f813f78e 351 LEFT JOIN civicrm_email {$alias}
352 ON {$alias_constituent}.id =
353 {$alias}.contact_id AND
6a488035
TO
354 {$alias}.is_primary = 1\n";
355 }
356
357 // include Creditors email field if email column is to be included
358 if ($this->_emailFieldCredit) {
359 $alias = 'emailcredit';
360 $this->_from .= "
f813f78e 361 LEFT JOIN civicrm_email {$alias}
362 ON {$alias_creditor}.id =
363 {$alias}.contact_id AND
6a488035
TO
364 {$alias}.is_primary = 1\n";
365 }
366
367 // include Constituents phone field if email column is to be included
368 if ($this->_phoneField) {
369 $alias = 'pconst';
370 $this->_from .= "
f813f78e 371 LEFT JOIN civicrm_phone {$alias}
372 ON {$alias_constituent}.id =
6a488035
TO
373 {$alias}.contact_id AND
374 {$alias}.is_primary = 1\n";
375 }
376
377 // include Creditors phone field if email column is to be included
378 if ($this->_phoneFieldCredit) {
379 $alias = 'pcredit';
380 $this->_from .= "
381 LEFT JOIN civicrm_phone pcredit
f813f78e 382 ON {$alias_creditor}.id =
383 {$alias}.contact_id AND
6a488035
TO
384 {$alias}.is_primary = 1\n";
385 }
386 }
387
00be9182 388 public function groupBy() {
9d72cede
EM
389 $this->_rollup = 'WITH ROLLUP';
390 $this->_groupBy = "
6a488035
TO
391GROUP BY {$this->_aliases['civicrm_contribution_soft']}.contact_id, constituentname.id {$this->_rollup}";
392 }
393
00be9182 394 public function where() {
6a488035
TO
395 parent::where();
396 $this->_where .= " AND {$this->_aliases['civicrm_contribution']}.is_test = 0 ";
397 }
398
74cf4551
EM
399 /**
400 * @param $rows
401 *
402 * @return array
403 */
00be9182 404 public function statistics(&$rows) {
6a488035
TO
405 $statistics = parent::statistics($rows);
406
407 $select = "
408 SELECT COUNT({$this->_aliases['civicrm_contribution']}.total_amount ) as count,
409 SUM({$this->_aliases['civicrm_contribution']}.total_amount ) as amount,
c6348f97 410 ROUND(AVG({$this->_aliases['civicrm_contribution']}.total_amount), 2) as avg,
411 {$this->_aliases['civicrm_contribution']}.currency as currency
6a488035
TO
412 ";
413
c6348f97 414 $sql = "{$select} {$this->_from} {$this->_where}
415GROUP BY {$this->_aliases['civicrm_contribution']}.currency
416";
6a488035 417
c6348f97 418 $dao = CRM_Core_DAO::executeQuery($sql);
419 $count = 0;
51fa20cb 420 $totalAmount = $average = array();
c6348f97 421 while ($dao->fetch()) {
9d72cede
EM
422 $totalAmount[] =
423 CRM_Utils_Money::format($dao->amount, $dao->currency) . '(' .
424 $dao->count . ')';
425 $average[] = CRM_Utils_Money::format($dao->avg, $dao->currency);
c6348f97 426 $count += $dao->count;
6a488035 427 }
c6348f97 428 $statistics['counts']['amount'] = array(
429 'title' => ts('Total Amount'),
430 'value' => implode(', ', $totalAmount),
431 'type' => CRM_Utils_Type::T_STRING,
432 );
433 $statistics['counts']['count'] = array(
be205937 434 'title' => ts('Total Contributions'),
c6348f97 435 'value' => $count,
436 );
437 $statistics['counts']['avg'] = array(
438 'title' => ts('Average'),
439 'value' => implode(', ', $average),
440 'type' => CRM_Utils_Type::T_STRING,
441 );
6a488035
TO
442
443 return $statistics;
444 }
445
00be9182 446 public function postProcess() {
6a488035
TO
447 $this->beginPostProcess();
448
449 $this->buildACLClause(array('constituentname', 'contact_civireport'));
450 $sql = $this->buildQuery();
451
9d72cede
EM
452 $dao = CRM_Core_DAO::executeQuery($sql);
453 $rows = $graphRows = array();
6a488035
TO
454 $count = 0;
455 while ($dao->fetch()) {
456 $row = array();
457 foreach ($this->_columnHeaders as $key => $value) {
458 $row[$key] = $dao->$key;
459 }
460 $rows[] = $row;
461 }
462 $this->formatDisplay($rows);
463
464 // to hide the contact ID field from getting displayed
465 unset($this->_columnHeaders['civicrm_contact_id_constituent']);
466 unset($this->_columnHeaders['civicrm_contact_id_creditor']);
467
468 // assign variables to templates
469 $this->doTemplateAssignment($rows);
470 $this->endPostProcess($rows);
471 }
472
74cf4551
EM
473 /**
474 * @param $rows
475 */
00be9182 476 public function alterDisplay(&$rows) {
6a488035
TO
477 // custom code to alter rows
478
9d72cede 479 $entryFound = FALSE;
6a488035 480 $dispname_flag = $phone_flag = $email_flag = 0;
9d72cede 481 $prev_email = $prev_dispname = $prev_phone = NULL;
6a488035
TO
482
483 foreach ($rows as $rowNum => $row) {
484 // Link constituent (contributor) to contribution detail
485 if (array_key_exists('civicrm_contact_display_name_constituent', $row) &&
486 array_key_exists('civicrm_contact_id_constituent', $row)
487 ) {
488
489 $url = CRM_Report_Utils_Report::getNextUrl('contribute/detail',
9d72cede
EM
490 'reset=1&force=1&id_op=eq&id_value=' .
491 $row['civicrm_contact_id_constituent'],
6a488035
TO
492 $this->_absoluteUrl, $this->_id, $this->_drilldownReport
493 );
494 $rows[$rowNum]['civicrm_contact_display_name_constituent_link'] = $url;
c6348f97 495 $rows[$rowNum]['civicrm_contact_display_name_constituent_hover'] = ts('List all direct contribution(s) from this contact.');
6a488035
TO
496 $entryFound = TRUE;
497 }
498
e1ea3ee3 499 // convert soft credit contact name to link
9d72cede
EM
500 if (array_key_exists('civicrm_contact_display_name_creditor', $row) &&
501 !empty($rows[$rowNum]['civicrm_contact_display_name_creditor']) &&
e1ea3ee3
DG
502 array_key_exists('civicrm_contact_id_creditor', $row)
503 ) {
504 $url = CRM_Utils_System::url("civicrm/contact/view",
505 'reset=1&cid=' . $row['civicrm_contact_id_creditor'],
506 $this->_absoluteUrl
507 );
508 $rows[$rowNum]['civicrm_contact_display_name_creditor_link'] = $url;
509 $rows[$rowNum]['civicrm_contact_display_name_creditor_hover'] = ts("view contact summary");
510 }
511
6a488035
TO
512 // make subtotals look nicer
513 if (array_key_exists('civicrm_contact_id_constituent', $row) &&
514 !$row['civicrm_contact_id_constituent']
515 ) {
516 $this->fixSubTotalDisplay($rows[$rowNum], $this->_statFields);
517 $entryFound = TRUE;
518 }
519
d62fab33
RN
520 // convert campaign_id to campaign title
521 if (array_key_exists('civicrm_contribution_campaign_id', $row)) {
522 if ($value = $row['civicrm_contribution_campaign_id']) {
523 $rows[$rowNum]['civicrm_contribution_campaign_id'] = $this->activeCampaigns[$value];
524 $entryFound = TRUE;
525 }
526 }
527
51fa20cb 528 //convert soft_credit_type_id into label
529 if (array_key_exists('civicrm_contribution_soft_soft_credit_type_id', $rows[$rowNum])) {
530 $rows[$rowNum]['civicrm_contribution_soft_soft_credit_type_id'] = CRM_Core_OptionGroup::getLabel('soft_credit_type',
531 $row['civicrm_contribution_soft_soft_credit_type_id']);
532 }
533
6a488035
TO
534 // skip looking further in rows, if first row itself doesn't
535 // have the column we need
536 if (!$entryFound) {
537 break;
538 }
539 }
540
541 $this->removeDuplicates($rows);
542 }
543}