3 +--------------------------------------------------------------------+
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2019
33 class CRM_Report_Form_Contribute_HouseholdSummary
extends CRM_Report_Form
{
35 public $_drilldownReport = ['contribute/detail' => 'Link to Detail Report'];
37 protected $_summary = NULL;
42 public function __construct() {
43 self
::validRelationships();
46 'civicrm_contact_household' => [
47 'dao' => 'CRM_Contact_DAO_Contact',
50 'title' => ts('Household Name'),
58 'title' => ts('Contact Type'),
60 'contact_sub_type' => [
61 'title' => ts('Contact Subtype'),
66 'title' => ts('Household Name'),
70 'type' => CRM_Utils_Type
::T_BOOLEAN
,
73 'grouping' => 'household-fields',
75 'civicrm_line_item' => [
76 'dao' => 'CRM_Price_DAO_LineItem',
78 'civicrm_relationship' => [
79 'dao' => 'CRM_Contact_DAO_Relationship',
81 'relationship_type_id' => [
82 'title' => ts('Relationship Type'),
86 'relationship_type_id' => [
87 'title' => ts('Relationship Type'),
88 'type' => CRM_Utils_Type
::T_INT
,
89 'operatorType' => CRM_Report_Form
::OP_SELECT
,
90 'options' => $this->relationTypes
,
91 'default' => key($this->relationTypes
),
94 'grouping' => 'household-fields',
96 'civicrm_contact' => [
97 'dao' => 'CRM_Contact_DAO_Contact',
100 'title' => ts('Contact Name'),
104 'no_display' => TRUE,
108 'grouping' => 'contact-fields',
110 'civicrm_contribution' => [
111 'dao' => 'CRM_Contribute_DAO_Contribution',
114 'title' => ts('Amount'),
118 'no_display' => TRUE,
121 'contribution_status_id' => [
122 'title' => ts('Contribution Status'),
126 'title' => ts('Check Number'),
130 'no_display' => TRUE,
132 'financial_type_id' => [
133 'title' => ts('Financial Type'),
136 'receive_date' => ['default' => TRUE],
137 'receipt_date' => NULL,
140 'receive_date' => ['operatorType' => CRM_Report_Form
::OP_DATE
],
141 'total_amount' => ['title' => ts('Amount Between')],
143 'title' => ts('Currency'),
144 'operatorType' => CRM_Report_Form
::OP_MULTISELECT
,
145 'options' => CRM_Core_OptionGroup
::values('currencies_enabled'),
147 'type' => CRM_Utils_Type
::T_STRING
,
149 'contribution_status_id' => [
150 'title' => ts('Contribution Status'),
151 'operatorType' => CRM_Report_Form
::OP_MULTISELECT
,
152 'options' => CRM_Contribute_PseudoConstant
::contributionStatus(),
155 'financial_type_id' => [
156 'title' => ts('Financial Type'),
157 'operatorType' => CRM_Report_Form
::OP_MULTISELECT
,
158 'options' => CRM_Contribute_PseudoConstant
::financialType(),
161 'grouping' => 'contri-fields',
163 'civicrm_financial_trxn' => [
164 'dao' => 'CRM_Financial_DAO_FinancialTrxn',
167 'title' => ts('Credit Card Type'),
168 'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
173 'title' => ts('Credit Card Type'),
174 'operatorType' => CRM_Report_Form
::OP_MULTISELECT
,
175 'options' => CRM_Financial_DAO_FinancialTrxn
::buildOptions('card_type_id'),
177 'type' => CRM_Utils_Type
::T_STRING
,
181 'civicrm_address' => [
182 'dao' => 'CRM_Core_DAO_Address',
184 'street_address' => NULL,
186 'postal_code' => NULL,
187 'state_province_id' => [
188 'title' => ts('State/Province'),
191 'title' => ts('Country'),
194 'grouping' => 'contact-fields',
197 'dao' => 'CRM_Core_DAO_Email',
201 'grouping' => 'contact-fields',
205 // If we have a campaign, build out the relevant elements
206 $this->addCampaignFields('civicrm_contribution');
208 $this->_currencyColumn
= 'civicrm_contribution_currency';
209 parent
::__construct();
212 public function select() {
213 // @todo remove this & use parent select.
214 $this->_columnHeaders
= $select = [];
215 foreach ($this->_columns
as $tableName => $table) {
216 if (array_key_exists('fields', $table)) {
217 foreach ($table['fields'] as $fieldName => $field) {
218 if (!empty($field['required']) ||
219 !empty($this->_params
['fields'][$fieldName])
222 if (!empty($field['statistics'])) {
223 foreach ($field['statistics'] as $stat => $label) {
224 $select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}_{$stat}";
225 $this->_columnHeaders
["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
226 $this->_columnHeaders
["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
227 $this->_statFields
[] = "{$tableName}_{$fieldName}_{$stat}";
231 $select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
233 $this->_columnHeaders
["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array
::value('title', $field);
234 $this->_columnHeaders
["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array
::value('type', $field);
240 $this->_selectClauses
= $select;
241 $this->_select
= "SELECT " . implode(', ', $select) . " ";
244 public function from() {
246 FROM civicrm_relationship {$this->_aliases['civicrm_relationship']}
247 LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact_household']} ON
248 ({$this->_aliases['civicrm_contact_household']}.id = {$this->_aliases['civicrm_relationship']}.$this->householdContact AND {$this->_aliases['civicrm_contact_household']}.contact_type='Household')
249 LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']} ON
250 ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_relationship']}.$this->otherContact )
252 INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']} ON
253 ({$this->_aliases['civicrm_contribution']}.contact_id = {$this->_aliases['civicrm_relationship']}.$this->otherContact ) AND {$this->_aliases['civicrm_contribution']}.is_test = 0 ";
255 $this->joinAddressFromContact();
256 $this->joinEmailFromContact();
258 // for credit card type
259 $this->addFinancialTrxnFromClause();
262 public function where() {
264 foreach ($this->_columns
as $tableName => $table) {
265 if (array_key_exists('filters', $table)) {
266 foreach ($table['filters'] as $fieldName => $field) {
268 if (CRM_Utils_Array
::value('type', $field) & CRM_Utils_Type
::T_DATE
) {
269 $relative = CRM_Utils_Array
::value("{$fieldName}_relative", $this->_params
);
270 $from = CRM_Utils_Array
::value("{$fieldName}_from", $this->_params
);
271 $to = CRM_Utils_Array
::value("{$fieldName}_to", $this->_params
);
272 $clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
275 $op = CRM_Utils_Array
::value("{$fieldName}_op", $this->_params
);
277 if ($fieldName == 'relationship_type_id') {
278 $clause = "{$this->_aliases['civicrm_relationship']}.relationship_type_id=" . $this->relationshipId
;
281 $clause = $this->whereClause($field,
283 CRM_Utils_Array
::value("{$fieldName}_value", $this->_params
),
284 CRM_Utils_Array
::value("{$fieldName}_min", $this->_params
),
285 CRM_Utils_Array
::value("{$fieldName}_max", $this->_params
)
291 if (!empty($clause)) {
292 $clauses[] = $clause;
298 if (empty($clauses)) {
299 $this->_where
= "WHERE ( 1 )";
302 $this->_where
= "WHERE " . implode(' AND ', $clauses);
305 if ($this->_aclWhere
) {
306 $this->_where
.= " AND {$this->_aclWhere} ";
310 public function groupBy() {
312 "{$this->_aliases['civicrm_relationship']}.$this->householdContact",
313 "{$this->_aliases['civicrm_relationship']}.$this->otherContact",
314 "{$this->_aliases['civicrm_contribution']}.id",
315 "{$this->_aliases['civicrm_relationship']}.relationship_type_id",
317 $this->_groupBy
= CRM_Contact_BAO_Query
::getGroupByFromSelectColumns($this->_selectClauses
, $groupBy);
320 public function orderBy() {
321 $this->_orderBy
= " ORDER BY {$this->_aliases['civicrm_contact_household']}.household_name, {$this->_aliases['civicrm_relationship']}.$this->householdContact, {$this->_aliases['civicrm_contact']}.sort_name, {$this->_aliases['civicrm_relationship']}.$this->otherContact";
329 public function statistics(&$rows) {
330 $statistics = parent
::statistics($rows);
332 //hack filter display for relationship type
333 $type = substr($this->_params
['relationship_type_id_value'], -3);
334 foreach ($statistics['filters'] as $id => $value) {
336 $value['title'] == 'Relationship Type' &&
337 isset($this->relationTypes
[$this->relationshipId
. '_' . $type])
339 $statistics['filters'][$id]['value'] = 'Is equal to ' .
340 $this->relationTypes
[$this->relationshipId
. '_' . $type];
346 public function postProcess() {
348 $this->beginPostProcess();
349 $this->buildACLClause([
350 $this->_aliases
['civicrm_contact'],
351 $this->_aliases
['civicrm_contact_household'],
353 $sql = $this->buildQuery(TRUE);
356 $this->buildRows($sql, $rows);
357 $this->formatDisplay($rows);
358 $this->doTemplateAssignment($rows);
359 $this->endPostProcess($rows);
363 * Set variables to be accessed by API and form layer in processing.
365 public function beginPostProcessCommon() {
366 $getRelationship = $this->_params
['relationship_type_id_value'];
367 $type = substr($getRelationship, -3);
368 $this->relationshipId
= intval((substr($getRelationship, 0, strpos($getRelationship, '_'))));
369 if ($type == 'b_a') {
370 $this->householdContact
= 'contact_id_b';
371 $this->otherContact
= 'contact_id_a';
374 $this->householdContact
= 'contact_id_a';
375 $this->otherContact
= 'contact_id_b';
379 public function validRelationships() {
380 $this->relationTypes
= $relationTypes = [];
382 $params = ['contact_type_b' => 'Household', 'version' => 3];
383 $typesA = civicrm_api('relationship_type', 'get', $params);
384 if (empty($typesA['is_error'])) {
385 foreach ($typesA['values'] as $rel) {
386 $relationTypes[$rel['id']][$rel['id'] . '_b_a'] = $rel['label_b_a'];
389 $params = ['contact_type_a' => 'Household', 'version' => 3];
390 $typesB = civicrm_api('relationship_type', 'get', $params);
391 if (empty($typesB['is_error'])) {
392 foreach ($typesB['values'] as $rel) {
393 $relationTypes[$rel['id']][$rel['id'] . '_a_b'] = $rel['label_a_b'];
394 //$this->relationTypes[$rel['id'].'_a_b'] = $rel['label_a_b'];
398 ksort($relationTypes);
399 foreach ($relationTypes as $relationship) {
400 foreach ($relationship as $index => $label) {
401 $this->relationTypes
[$index] = $label;
407 * Alter display of rows.
409 * Iterate through the rows retrieved via SQL and make changes for display purposes,
410 * such as rendering contacts as links.
413 * Rows generated by SQL, with an array for each row.
415 public function alterDisplay(&$rows) {
416 $type = substr($this->_params
['relationship_type_id_value'], -3);
419 $flagHousehold = $flagContact = 0;
420 foreach ($rows as $rowNum => $row) {
422 //replace retionship id by relationship name
423 if (array_key_exists('civicrm_relationship_relationship_type_id', $row)) {
424 if ($value = $row['civicrm_relationship_relationship_type_id']) {
425 $rows[$rowNum]['civicrm_relationship_relationship_type_id'] = $this->relationTypes
[$value . '_' . $type];
430 //remove duplicate Organization names
431 if (array_key_exists('civicrm_contact_household_household_name', $row) &&
432 $this->_outputMode
!= 'csv'
434 if ($value = $row['civicrm_contact_household_household_name']) {
436 $priviousHousehold = $value;
439 if ($priviousHousehold == $value) {
441 $priviousHousehold = $value;
445 $priviousHousehold = $value;
449 if ($flagHousehold == 1) {
450 $rows[$rowNum]['civicrm_contact_household_household_name'] = "";
453 $url = CRM_Utils_System
::url('civicrm/contact/view',
454 'reset=1&cid=' . $rows[$rowNum]['civicrm_contact_household_id'],
458 $rows[$rowNum]['civicrm_contact_household_household_name'] = "<a href='$url' title='" . ts('View contact summary for this househould') . "'>" . $value . '</a>';
464 //remove duplicate Contact names and relationship type
465 if (array_key_exists('civicrm_contact_id', $row) &&
466 $this->_outputMode
!= 'csv'
468 if ($value = $row['civicrm_contact_id']) {
470 $priviousContact = $value;
473 if ($priviousContact == $value) {
475 $priviousContact = $value;
479 $priviousContact = $value;
483 if ($flagContact == 1 && $flagHousehold == 1) {
484 $rows[$rowNum]['civicrm_contact_sort_name'] = "";
485 $rows[$rowNum]['civicrm_relationship_relationship_type_id'] = "";
492 if (array_key_exists('civicrm_contribution_contribution_status_id', $row)) {
493 if ($value = $row['civicrm_contribution_contribution_status_id']) {
494 $rows[$rowNum]['civicrm_contribution_contribution_status_id'] = CRM_Contribute_PseudoConstant
::contributionStatus($value);
498 if (array_key_exists('civicrm_contribution_financial_type_id', $row)) {
499 if ($value = $row['civicrm_contribution_financial_type_id']) {
500 $rows[$rowNum]['civicrm_contribution_financial_type_id'] = CRM_Contribute_PseudoConstant
::financialType($value);
504 // convert display name to links
505 if (array_key_exists('civicrm_contact_sort_name', $row) &&
506 $rows[$rowNum]['civicrm_contact_sort_name'] &&
507 array_key_exists('civicrm_contact_id', $row)
509 $url = CRM_Report_Utils_Report
::getNextUrl('contribute/detail',
510 'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'],
511 $this->_absoluteUrl
, $this->_id
, $this->_drilldownReport
513 $rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
514 $rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts('View contribution details for this individual');
519 if (!empty($row['civicrm_contribution_total_amount'])) {
520 $row['civicrm_contribution_total_amount'] = CRM_Utils_Money
::format($row['civicrm_contribution_total_amount'], $row['civicrm_contribution_currency']);
523 if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
524 $rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
528 // Contribution amount links to view contribution
529 if (($value = CRM_Utils_Array
::value('civicrm_contribution_total_amount', $row)) &&
530 CRM_Core_Permission
::check('access CiviContribute')
532 $url = CRM_Utils_System
::url("civicrm/contact/view/contribution",
533 "reset=1&id=" . $row['civicrm_contribution_id'] . "&cid=" .
534 $row['civicrm_contact_id'] .
535 "&action=view&context=contribution&selectedChild=contribute",
538 $rows[$rowNum]['civicrm_contribution_total_amount_link'] = $url;
539 $rows[$rowNum]['civicrm_contribution_total_amount_hover'] = ts("View this contribution.");
543 // convert campaign_id to campaign title
544 if (array_key_exists('civicrm_contribution_campaign_id', $row)) {
545 if ($value = $row['civicrm_contribution_campaign_id']) {
546 $rows[$rowNum]['civicrm_contribution_campaign_id'] = $this->campaigns
[$value];
551 $entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, NULL, NULL) ?
TRUE : $entryFound;
553 // skip looking further in rows, if first row itself doesn't