First commit

This commit is contained in:
Theodotos Andreou 2018-01-14 13:10:16 +00:00
commit c6e2478c40
13918 changed files with 2303184 additions and 0 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,791 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_ActivitySummary extends CRM_Report_Form {
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
protected $_tempTableName;
protected $_tempDurationSumTableName;
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'id' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'sort_name' => array(
'title' => ts('Contact Name'),
'no_repeat' => TRUE,
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
),
),
'group_bys' => array(
'sort_name' => array(
'name' => 'id',
'title' => ts('Contact'),
),
),
'order_bys' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
),
),
'grouping' => 'contact-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
),
),
'order_bys' => array(
'email' => array(
'title' => ts('Email'),
),
),
'grouping' => 'contact-fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'phone' => array(
'title' => ts('Phone'),
),
),
'grouping' => 'contact-fields',
),
'civicrm_activity' => array(
'dao' => 'CRM_Activity_DAO_Activity',
'fields' => array(
'activity_type_id' => array(
'title' => ts('Activity Type'),
'required' => TRUE,
'type' => CRM_Utils_Type::T_STRING,
),
'status_id' => array(
'title' => ts('Activity Status'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_STRING,
),
'duration' => array(
'title' => ts('Duration'),
'default' => TRUE,
),
'priority_id' => array(
'title' => ts('Priority'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_STRING,
),
'id' => array(
'title' => ts('Total Activities'),
'required' => TRUE,
'statistics' => array(
'count' => ts('Count'),
),
),
),
'filters' => array(
'activity_date_time' => array(
'operatorType' => CRM_Report_Form::OP_DATE,
),
'activity_type_id' => array(
'title' => ts('Activity Type'),
'default' => 0,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE),
),
'status_id' => array(
'title' => ts('Activity Status'),
'type' => CRM_Utils_Type::T_STRING,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::activityStatus(),
),
'priority_id' => array(
'title' => ts('Activity Priority'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id'),
),
),
'group_bys' => array(
'activity_date_time' => array(
'title' => ts('Activity Date'),
'frequency' => TRUE,
),
'activity_type_id' => array(
'title' => ts('Activity Type'),
'default' => TRUE,
),
'status_id' => array(
'title' => ts('Activity Status'),
'default' => TRUE,
),
),
'order_bys' => array(
'activity_date_time' => array(
'title' => ts('Activity Date'),
),
'activity_type_id' => array(
'title' => ts('Activity Type'),
),
),
'grouping' => 'activity-fields',
'alias' => 'activity',
),
);
$this->_groupFilter = TRUE;
parent::__construct();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('group_bys', $table)) {
foreach ($table['group_bys'] as $fieldName => $field) {
if (!empty($this->_params['group_bys'][$fieldName])) {
//include column in report when selected in group by but not in column section.
if (empty($this->_params['fields'][$fieldName])) {
$this->_params['fields'][$fieldName] = TRUE;
}
if (isset($this->_params['group_bys_freq']) && !empty($this->_params['group_bys_freq'][$fieldName])) {
switch ($this->_params['group_bys_freq'][$fieldName]) {
case 'YEARWEEK':
$select[] = "DATE_SUB({$field['dbAlias']}, INTERVAL WEEKDAY({$field['dbAlias']}) DAY) AS {$tableName}_{$fieldName}_start";
$select[] = "YEARWEEK({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "WEEKOFYEAR({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Week';
break;
case 'YEAR':
$select[] = "MAKEDATE(YEAR({$field['dbAlias']}), 1) AS {$tableName}_{$fieldName}_start";
$select[] = "YEAR({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "YEAR({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Year';
break;
case 'MONTH':
$select[] = "DATE_SUB({$field['dbAlias']}, INTERVAL (DAYOFMONTH({$field['dbAlias']})-1) DAY) as {$tableName}_{$fieldName}_start";
$select[] = "MONTH({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "MONTHNAME({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Month';
break;
case 'QUARTER':
$select[] = "STR_TO_DATE(CONCAT( 3 * QUARTER( {$field['dbAlias']} ) -2 , '/', '1', '/', YEAR( {$field['dbAlias']} ) ), '%m/%d/%Y') AS {$tableName}_{$fieldName}_start";
$select[] = "QUARTER({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "QUARTER({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Quarter';
break;
}
$this->_interval = $field['title'];
$this->_columnHeaders["{$tableName}_{$fieldName}_start"]['title'] = $field['title'] . ' Beginning';
$this->_columnHeaders["{$tableName}_{$fieldName}_start"]['type'] = $field['type'];
$this->_columnHeaders["{$tableName}_{$fieldName}_start"]['group_by'] = $this->_params['group_bys_freq'][$fieldName];
// just to make sure these values are transferred to rows.
// since we need that for calculation purpose,
// e.g making subtotals look nicer or graphs
$this->_columnHeaders["{$tableName}_{$fieldName}_interval"] = array('no_display' => TRUE);
$this->_columnHeaders["{$tableName}_{$fieldName}_subtotal"] = array('no_display' => TRUE);
}
}
}
}
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) || !empty($this->_params['fields'][$fieldName])) {
if ($tableName == 'civicrm_email' || in_array('email', CRM_Utils_Array::collect('column', $this->_params['order_bys']))) {
$this->_emailField = TRUE;
}
if ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
}
if (!empty($field['statistics'])) {
foreach ($field['statistics'] as $stat => $label) {
switch (strtolower($stat)) {
case 'count':
$select[] = "COUNT(DISTINCT({$field['dbAlias']})) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = CRM_Utils_Type::T_INT;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
}
}
}
elseif ($fieldName == 'activity_type_id') {
if (empty($this->_params['group_bys']['activity_type_id'])) {
$select[] = "GROUP_CONCAT(DISTINCT {$field['dbAlias']} ORDER BY {$field['dbAlias']} ) as {$tableName}_{$fieldName}";
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
}
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = CRM_Utils_Array::value('no_display', $field);
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = CRM_Utils_Array::value('no_display', $field);
}
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* Generate from clause.
*
* @param bool|FALSE $durationMode
*/
public function from($durationMode = FALSE) {
$activityContacts = CRM_Activity_BAO_ActivityContact::buildOptions('record_type_id', 'validate');
$assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
$targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
$sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
if (!$durationMode) {
$this->_from = "
FROM civicrm_activity {$this->_aliases['civicrm_activity']}
LEFT JOIN civicrm_activity_contact target_activity
ON {$this->_aliases['civicrm_activity']}.id = target_activity.activity_id AND
target_activity.record_type_id = {$targetID}
LEFT JOIN civicrm_activity_contact assignment_activity
ON {$this->_aliases['civicrm_activity']}.id = assignment_activity.activity_id AND
assignment_activity.record_type_id = {$assigneeID}
LEFT JOIN civicrm_activity_contact source_activity
ON {$this->_aliases['civicrm_activity']}.id = source_activity.activity_id AND
source_activity.record_type_id = {$sourceID}
LEFT JOIN civicrm_contact contact_civireport
ON target_activity.contact_id = contact_civireport.id
LEFT JOIN civicrm_contact civicrm_contact_assignee
ON assignment_activity.contact_id = civicrm_contact_assignee.id
LEFT JOIN civicrm_contact civicrm_contact_source
ON source_activity.contact_id = civicrm_contact_source.id
{$this->_aclFrom}
LEFT JOIN civicrm_option_value
ON ( {$this->_aliases['civicrm_activity']}.activity_type_id = civicrm_option_value.value )
LEFT JOIN civicrm_option_group
ON civicrm_option_group.id = civicrm_option_value.option_group_id
LEFT JOIN civicrm_case_activity
ON civicrm_case_activity.activity_id = {$this->_aliases['civicrm_activity']}.id
LEFT JOIN civicrm_case
ON civicrm_case_activity.case_id = civicrm_case.id
LEFT JOIN civicrm_case_contact
ON civicrm_case_contact.case_id = civicrm_case.id ";
if ($this->_phoneField) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1 ";
}
}
else {
$this->_from = "
FROM civicrm_activity {$this->_aliases['civicrm_activity']}
LEFT JOIN civicrm_activity_contact target_activity
ON {$this->_aliases['civicrm_activity']}.id = target_activity.activity_id AND
target_activity.record_type_id = {$targetID}
LEFT JOIN civicrm_contact contact_civireport
ON target_activity.contact_id = contact_civireport.id
{$this->_aclFrom}";
}
if ($this->_emailField) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1 ";
}
}
/**
* Generate where clause.
*
* @param bool|FALSE $durationMode
*/
public function where($durationMode = FALSE) {
$optionGroupClause = '';
if (!$durationMode) {
$optionGroupClause = 'civicrm_option_group.name = "activity_type" AND ';
}
$this->_where = " WHERE {$optionGroupClause}
{$this->_aliases['civicrm_activity']}.is_test = 0 AND
{$this->_aliases['civicrm_activity']}.is_deleted = 0 AND
{$this->_aliases['civicrm_activity']}.is_current_revision = 1";
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where .= " ";
}
else {
$this->_where .= " AND " . implode(' AND ', $clauses);
}
if ($this->_aclWhere && !$durationMode) {
$this->_where .= " AND ({$this->_aclWhere} OR civicrm_contact_source.is_deleted=0 OR civicrm_contact_assignee.is_deleted=0)";
}
}
/**
* Group the fields.
*
* @param bool $includeSelectCol
*/
public function groupBy($includeSelectCol = TRUE) {
$this->_groupBy = array();
if (!empty($this->_params['group_bys']) &&
is_array($this->_params['group_bys'])) {
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('group_bys', $table)) {
foreach ($table['group_bys'] as $fieldName => $field) {
if (!empty($this->_params['group_bys'][$fieldName])) {
if (!empty($field['chart'])) {
$this->assign('chartSupported', TRUE);
}
if (!empty($table['group_bys'][$fieldName]['frequency']) &&
!empty($this->_params['group_bys_freq'][$fieldName])
) {
$append = "YEAR({$field['dbAlias']}),";
if (in_array(strtolower($this->_params['group_bys_freq'][$fieldName]),
array('year')
)) {
$append = '';
}
$this->_groupBy[] = "$append {$this->_params['group_bys_freq'][$fieldName]}({$field['dbAlias']})";
$append = TRUE;
}
else {
$this->_groupBy[] = $field['dbAlias'];
}
}
}
}
}
$groupBy = $this->_groupBy;
$this->_groupBy = "GROUP BY " . implode(', ', $this->_groupBy);
}
else {
$groupBy = "{$this->_aliases['civicrm_activity']}.id";
$this->_groupBy = "GROUP BY {$this->_aliases['civicrm_activity']}.id ";
}
if ($includeSelectCol) {
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = array();
$contactFields = array('sort_name', 'email', 'phone');
if (!empty($fields['group_bys'])) {
if (!empty($fields['group_bys']['activity_date_time'])) {
if (!empty($fields['group_bys']['sort_name'])) {
$errors['fields'] = ts("Please do not select GroupBy 'Activity Date' with GroupBy 'Contact'");
}
else {
foreach ($fields['fields'] as $fieldName => $val) {
if (in_array($fieldName, $contactFields)) {
$errors['fields'] = ts("Please do not select any Contact Fields with GroupBy 'Activity Date'");
break;
}
}
}
}
}
// don't allow add to group action unless contact fields are selected.
if (isset($fields['_qf_ActivitySummary_submit_group'])) {
$contactFieldSelected = FALSE;
foreach ($fields['fields'] as $fieldName => $val) {
if (in_array($fieldName, $contactFields)) {
$contactFieldSelected = TRUE;
break;
}
}
if (!$contactFieldSelected) {
$errors['fields'] = ts('You cannot use "Add Contacts to Group" action unless contacts fields are selected.');
}
}
return $errors;
}
public function postProcess() {
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
// get ready with post process params
$this->beginPostProcess();
// build query
$sql = $this->buildQuery();
// main sql statement
$this->select();
$this->from();
$this->customDataFrom();
$this->where();
$this->groupBy();
$this->orderBy();
// order_by columns not selected for display need to be included in SELECT
$unselectedSectionColumns = $this->unselectedSectionColumns();
foreach ($unselectedSectionColumns as $alias => $section) {
$this->_select .= ", {$section['dbAlias']} as {$alias}";
}
if (!empty($applyLimit) && empty($this->_params['charts'])) {
$this->limit();
}
CRM_Utils_Hook::alterReportVar('sql', $this, $this);
// store the duration count in temp table
$this->_tempTableName = CRM_Core_DAO::createTempTableName('civicrm_activity');
// build temporary table column names base on column headers of result
$dbColumns = array();
foreach ($this->_columnHeaders as $fieldName => $dontCare) {
$dbColumns[] = $fieldName . ' VARCHAR(128)';
}
// create temp table to store main result
$tempQuery = "CREATE TEMPORARY TABLE {$this->_tempTableName} (
id int unsigned NOT NULL AUTO_INCREMENT, " . implode(', ', $dbColumns) . ' , PRIMARY KEY (id))'
. $this->_databaseAttributes;
CRM_Core_DAO::executeQuery($tempQuery);
// build main report query
$sql = "{$this->_select} {$this->_from} {$this->_where} {$this->_groupBy} {$this->_having} {$this->_orderBy} {$this->_limit}";
// store the result in temporary table
$insertCols = '';
$insertQuery = "INSERT INTO {$this->_tempTableName} ( " . implode(',', array_keys($this->_columnHeaders)) . " )
{$sql}";
CRM_Core_DAO::executeQuery($insertQuery);
// now build the query for duration sum
$this->from(TRUE);
$this->where(TRUE);
$this->groupBy(FALSE);
// build the query to calulate duration sum
$sql = "SELECT SUM(activity_civireport.duration) as civicrm_activity_duration_total {$this->_from} {$this->_where} {$this->_groupBy} {$this->_having} {$this->_orderBy} {$this->_limit}";
// create temp table to store duration
$this->_tempDurationSumTableName = CRM_Core_DAO::createTempTableName('civicrm_activity');
$tempQuery = "CREATE TEMPORARY TABLE {$this->_tempDurationSumTableName} (
id int unsigned NOT NULL AUTO_INCREMENT, civicrm_activity_duration_total VARCHAR(128), PRIMARY KEY (id))"
. $this->_databaseAttributes;
CRM_Core_DAO::executeQuery($tempQuery);
// store the result in temporary table
$insertQuery = "INSERT INTO {$this->_tempDurationSumTableName} (civicrm_activity_duration_total)
{$sql}";
CRM_Core_DAO::executeQuery($insertQuery);
// build array of result based on column headers. This method also allows
// modifying column headers before using it to build result set i.e $rows.
$rows = array();
$query = "SELECT {$this->_tempTableName}.*, {$this->_tempDurationSumTableName}.civicrm_activity_duration_total
FROM {$this->_tempTableName} INNER JOIN {$this->_tempDurationSumTableName}
ON ({$this->_tempTableName}.id = {$this->_tempDurationSumTableName}.id)";
// finally add duration total to column headers
$this->_columnHeaders['civicrm_activity_duration_total'] = array('no_display' => 1);
$this->buildRows($query, $rows);
// format result set.
$this->formatDisplay($rows);
// assign variables to templates
$this->doTemplateAssignment($rows);
//reset the sql building to default, which is used / called during other actions like "add to group"
// now build the query for duration sum
$this->from();
$this->where();
// do print / pdf / instance stuff if needed
$this->endPostProcess($rows);
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
$totalType = $totalActivity = $totalDuration = 0;
$query = "SELECT {$this->_tempTableName}.civicrm_activity_activity_type_id,
{$this->_tempTableName}.civicrm_activity_id_count,
{$this->_tempDurationSumTableName}.civicrm_activity_duration_total
FROM {$this->_tempTableName} INNER JOIN {$this->_tempDurationSumTableName}
ON ({$this->_tempTableName}.id = {$this->_tempDurationSumTableName}.id)";
$actDAO = CRM_Core_DAO::executeQuery($query);
$activityTypesCount = array();
while ($actDAO->fetch()) {
if (!in_array($actDAO->civicrm_activity_activity_type_id, $activityTypesCount)) {
$activityTypesCount[] = $actDAO->civicrm_activity_activity_type_id;
}
$totalActivity += $actDAO->civicrm_activity_id_count;
$totalDuration += $actDAO->civicrm_activity_duration_total;
}
$totalType = count($activityTypesCount);
$statistics['counts']['type'] = array(
'title' => ts('Total Types'),
'value' => $totalType,
);
$statistics['counts']['activities'] = array(
'title' => ts('Total Number of Activities'),
'value' => $totalActivity,
);
$statistics['counts']['duration'] = array(
'title' => ts('Total Duration (in Minutes)'),
'value' => $totalDuration,
);
return $statistics;
}
public function modifyColumnHeaders() {
//CRM-16719 modify name of column
if (!empty($this->_columnHeaders['civicrm_activity_status_id'])) {
$this->_columnHeaders['civicrm_activity_status_id']['title'] = ts('Status');
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$activityType = CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE);
$activityStatus = CRM_Core_PseudoConstant::activityStatus();
$priority = CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id');
$onHover = ts('View Contact Summary for this Contact');
foreach ($rows as $rowNum => $row) {
// make count columns point to activity detail report
if (!empty($row['civicrm_activity_id_count'])) {
$url = array();
$urlParams = array('activity_type_id', 'gid', 'status_id', 'contact_id');
foreach ($urlParams as $field) {
if (!empty($row['civicrm_activity_' . $field])) {
$url[] = "{$field}_op=in&{$field}_value={$row['civicrm_activity_'.$field]}";
}
elseif (!empty($this->_params[$field . '_value'])) {
$val = implode(",", $this->_params[$field . '_value']);
$url[] = "{$field}_op=in&{$field}_value={$val}";
}
}
$date_suffixes = array('relative', 'from', 'to');
while (list(, $suffix) = each($date_suffixes)) {
if (!empty($this->_params['activity_date_time_' . $suffix])) {
list($from, $to)
= $this->getFromTo(
CRM_Utils_Array::value("activity_date_time_relative", $this->_params),
CRM_Utils_Array::value("activity_date_time_from", $this->_params),
CRM_Utils_Array::value("activity_date_time_to", $this->_params)
);
$url[] = "activity_date_time_from={$from}&activity_date_time_to={$to}";
break;
}
}
// reset date filter on activity reports.
$url[] = "resetDateFilter=1";
$url = implode('&', $url);
$url = CRM_Report_Utils_Report::getNextUrl('activity', "reset=1&force=1&{$url}",
$this->_absoluteUrl,
$this->_id,
$this->_drilldownReport);
$rows[$rowNum]['civicrm_activity_id_count_link'] = $url;
$rows[$rowNum]['civicrm_activity_id_count_hover'] = ts('List all activity(s) for this row.');
$entryFound = TRUE;
}
if (array_key_exists('civicrm_contact_sort_name', $row) && $this->_outputMode != 'csv') {
if ($value = $row['civicrm_contact_id']) {
// unset the name, email and phone fields if the contact is the same as the previous contact
if (isset($previousContact) && $previousContact == $value) {
$rows[$rowNum]['civicrm_contact_sort_name'] = "";
if (array_key_exists('civicrm_email_email', $row)) {
$rows[$rowNum]['civicrm_email_email'] = "";
}
if (array_key_exists('civicrm_phone_phone', $row)) {
$rows[$rowNum]['civicrm_phone_phone'] = "";
}
}
else {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $value,
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name'] = "<a href='$url'>" . $row['civicrm_contact_sort_name'] .
'</a>';
}
// store the contact ID of this contact
$previousContact = $value;
$entryFound = TRUE;
}
}
if (array_key_exists('civicrm_activity_activity_type_id', $row)) {
if ($value = $row['civicrm_activity_activity_type_id']) {
$value = explode(',', $value);
foreach ($value as $key => $id) {
$value[$key] = $activityType[$id];
}
$rows[$rowNum]['civicrm_activity_activity_type_id'] = implode(' , ', $value);
$entryFound = TRUE;
}
}
if (array_key_exists('civicrm_activity_status_id', $row)) {
if ($value = $row['civicrm_activity_status_id']) {
$rows[$rowNum]['civicrm_activity_status_id'] = $activityStatus[$value];
$entryFound = TRUE;
}
}
if (array_key_exists('civicrm_activity_priority_id', $row)) {
if ($value = $row['civicrm_activity_priority_id']) {
$rows[$rowNum]['civicrm_activity_priority_id'] = $priority[$value];
$entryFound = TRUE;
}
}
if (array_key_exists('civicrm_activity_duration', $row)) {
if ($value = $row['civicrm_activity_duration']) {
$rows[$rowNum]['civicrm_activity_duration'] = $rows[$rowNum]['civicrm_activity_duration_total'];
$entryFound = TRUE;
}
}
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,826 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Campaign_SurveyDetails extends CRM_Report_Form {
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
protected $_locationBasedPhoneField = FALSE;
protected $_summary = NULL;
protected $_customGroupGroupBy = FALSE;
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Household',
'Organization',
'Activity',
);
public $_drilldownReport = array('contact/detail' => 'Link to Detail Report');
private static $_surveyRespondentStatus;
// Survey Question titles are overridden when in print or pdf mode to
// say Q1, Q2 instead of the full title - to save space.
private $_columnTitleOverrides = array();
/**
*/
/**
*/
public function __construct() {
//filter options for survey activity status.
$responseStatus = array('' => '- Any -');
self::$_surveyRespondentStatus = array();
$activityStatus = CRM_Core_PseudoConstant::activityStatus('name');
if ($statusId = array_search('Scheduled', $activityStatus)) {
$responseStatus[$statusId] = ts('Reserved');
self::$_surveyRespondentStatus[$statusId] = 'Reserved';
}
if ($statusId = array_search('Completed', $activityStatus)) {
$responseStatus[$statusId] = ts('Interviewed');
self::$_surveyRespondentStatus[$statusId] = 'Interviewed';
}
$optionGroups = CRM_Campaign_BAO_Survey::getResultSets('name');
$resultOptions = array();
foreach ($optionGroups as $gid => $name) {
if ($name) {
$value = array();
$value = CRM_Core_OptionGroup::values($name);
if (!empty($value)) {
$value = array_combine($value, $value);
}
$resultOptions = $resultOptions + $value;
}
}
asort($resultOptions);
//get all interviewers.
$allSurveyInterviewers = CRM_Campaign_BAO_Survey::getInterviewers();
$this->_columns = array(
'civicrm_activity_contact' => array(
'dao' => 'CRM_Activity_DAO_ActivityContact',
'fields' => array('contact_id' => array('title' => ts('Interviewer Name'))),
'filters' => array(
'contact_id' => array(
'name' => 'contact_id',
'title' => ts('Interviewer Name'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
'' => ts('- any interviewer -'),
) + $allSurveyInterviewers,
),
),
'grouping' => 'survey-interviewer-fields',
),
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
'required' => TRUE,
),
'sort_name' => array(
'title' => ts('Respondent Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Respondent Name'),
'operator' => 'like',
),
),
'grouping' => 'contact-fields',
'order_bys' => array(
'sort_name' => array(
'title' => ts('Respondent Name'),
'required' => TRUE,
),
),
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array(
'phone' => array(
'name' => 'phone',
'title' => ts('Phone'),
),
),
'grouping' => 'location-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'name' => 'email',
'title' => ts('Email'),
),
),
'grouping' => 'location-fields',
),
) + $this->getAddressColumns() +
array(
'civicrm_activity' => array(
'dao' => 'CRM_Activity_DAO_Activity',
'alias' => 'survey_activity',
'fields' => array(
'survey_id' => array(
'name' => 'source_record_id',
'title' => ts('Survey'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Campaign_BAO_Survey::getSurveys(),
),
'survey_response' => array(
'name' => 'survey_response',
'title' => ts('Survey Responses'),
),
'details' => array(
'name' => 'details',
'title' => ts('Note'),
'type' => 1,
),
'result' => array(
'name' => 'result',
'required' => TRUE,
'title' => ts('Survey Result'),
),
'activity_date_time' => array(
'name' => 'activity_date_time',
'title' => ts('Date'),
'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
),
),
'filters' => array(
'survey_id' => array(
'name' => 'source_record_id',
'title' => ts('Survey'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Campaign_BAO_Survey::getSurveys(),
),
'status_id' => array(
'name' => 'status_id',
'title' => ts('Respondent Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => $responseStatus,
),
'result' => array(
'title' => ts('Survey Result'),
'type' => CRM_Utils_Type::T_STRING,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $resultOptions,
),
'activity_date_time' => array(
'title' => ts('Date'),
'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
'grouping' => 'survey-activity-fields',
'order_bys' => array(
'activity_date_time' => array(
'title' => ts('Date'),
),
),
),
);
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
//add the survey response fields.
$this->_addSurveyResponseColumns();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (!isset($table['fields'])) {
continue;
}
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName]) ||
CRM_Utils_Array::value('is_required', $field)
) {
$fieldsName = CRM_Utils_Array::value(1, explode('_', $tableName));
if ($fieldsName) {
$this->{"_$fieldsName" . 'Field'} = TRUE;
}
//need to pickup custom data/survey response fields.
if ($fieldName == 'survey_response') {
continue;
}
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
// Set default title
$title = CRM_Utils_Array::value('title', $field);
// Check for an override.
if (!empty($this->_columnTitleOverrides["{$tableName}_{$fieldName}"])) {
$title = $this->_columnTitleOverrides["{$tableName}_{$fieldName}"];
}
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $title;
$this->_selectAliases[] = "{$tableName}_{$fieldName}";
}
}
}
$this->_select = "SELECT " . implode(",\n", $select) . " ";
}
public function from() {
$this->_from = " FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom} ";
$activityContacts = CRM_Activity_BAO_ActivityContact::buildOptions('record_type_id', 'validate');
$assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
$targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
//get the activity table joins.
$this->_from .= " INNER JOIN civicrm_activity_contact civicrm_activity_target ON
( {$this->_aliases['civicrm_contact']}.id = civicrm_activity_target.contact_id AND civicrm_activity_target.record_type_id = {$targetID}) \n";
$this->_from .= " INNER JOIN civicrm_activity {$this->_aliases['civicrm_activity']} ON
( {$this->_aliases['civicrm_activity']}.id = civicrm_activity_target.activity_id )\n";
$this->_from .= " INNER JOIN civicrm_activity_contact activity_contact_civireport ON
( {$this->_aliases['civicrm_activity']}.id = activity_contact_civireport.activity_id AND activity_contact_civireport.record_type_id = {$assigneeID} )\n";
//get the address table.
$this->_from .= " LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']} ON
{$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND {$this->_aliases['civicrm_address']}.is_primary = 1\n";
if ($this->_emailField) {
$this->_from .= "LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']} ON
{$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND {$this->_aliases['civicrm_email']}.is_primary = 1\n";
}
if ($this->_phoneField) {
$this->_from .= "LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']} ON
{$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND {$this->_aliases['civicrm_phone']}.is_primary = 1\n";
}
if ($this->_locationBasedPhoneField) {
foreach ($this->_surveyResponseFields as $key => $value) {
if (substr($key, 0, 5) == 'phone' && !empty($value['location_type_id'])
) {
$fName = str_replace('-', '_', $key);
$this->_from .= "LEFT JOIN civicrm_phone " .
$this->_aliases["civicrm_phone_{$fName}"] .
" ON {$this->_aliases['civicrm_contact']}.id = " .
$this->_aliases["civicrm_phone_{$fName}"] . ".contact_id AND " .
$this->_aliases["civicrm_phone_{$fName}"] .
".location_type_id = {$value['location_type_id']} AND " .
$this->_aliases["civicrm_phone_{$fName}"] .
".phone_type_id = {$value['phone_type_id']}\n";
}
}
}
}
public function where() {
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
//apply survey activity types filter.
$surveyActivityTypes = CRM_Campaign_BAO_Survey::getSurveyActivityType();
if (!empty($surveyActivityTypes)) {
$clauses[] = "( {$this->_aliases['civicrm_activity']}.activity_type_id IN ( " .
implode(' , ', array_keys($surveyActivityTypes)) . ' ) )';
}
// always filter out deleted activities (so contacts that have been released
// don't show up in the report).
$clauses[] = "( {$this->_aliases['civicrm_activity']}.is_deleted = 0 )";
if (empty($clauses)) {
$this->_where = "WHERE ( 1 ) ";
}
else {
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
public function compileContent() {
$coverSheet = $this->_surveyCoverSheet() .
"<div style=\"page-break-after: always\"></div>";
$templateFile = $this->getHookedTemplateFileName();
return $coverSheet .
CRM_Core_Form::$_template->fetch($templateFile) .
CRM_Utils_Array::value('report_footer', $this->_formValues);
}
/**
* @return bool|mixed|null|string
*/
private function _surveyCoverSheet() {
$coverSheet = NULL;
$surveyIds = CRM_Utils_Array::value('survey_id_value', $this->_params);
if (CRM_Utils_System::isNull($surveyIds)) {
return $coverSheet;
}
$fieldIds = array();
$surveyResponseFields = array();
foreach ($this->_columns as $tableName => $values) {
if (!is_array($values['fields'])) {
continue;
}
foreach ($values['fields'] as $name => $field) {
if (!empty($field['isSurveyResponseField'])) {
$fldId = substr($name, 7);
$fieldIds[$fldId] = $fldId;
$title = CRM_Utils_Array::value('label', $field, $field['title']);
$surveyResponseFields[$name] = array(
'id' => $fldId,
'title' => $title,
'name' => "{$tableName}_{$name}",
);
}
}
}
//now pickup all options.
if (!empty($fieldIds)) {
$query = '
SELECT field.id as id,
val.label as label,
val.value as value
FROM civicrm_custom_field field
INNER JOIN civicrm_option_value val ON ( val.option_group_id = field.option_group_id )
WHERE field.id IN (' . implode(' , ', $fieldIds) . ' )
Order By val.weight';
$field = CRM_Core_DAO::executeQuery($query);
$options = array();
while ($field->fetch()) {
$name = "custom_{$field->id}";
$surveyResponseFields[$name]['options'][$field->value] = $field->label;
}
}
//get the result values.
$query = '
SELECT survey.id as id,
survey.title as title,
val.label as label,
val.value as value
FROM civicrm_survey survey
INNER JOIN civicrm_option_value val ON ( val.option_group_id = survey.result_id )
WHERE survey.id IN ( ' . implode(' , ', array_values($surveyIds)) . ' )
Order By val.weight';
$resultSet = CRM_Core_DAO::executeQuery($query);
$surveyResultFields = array();
while ($resultSet->fetch()) {
$surveyResultFields[$resultSet->id]['title'] = $resultSet->title;
$surveyResultFields[$resultSet->id]['options'][$resultSet->value] = $resultSet->label;
}
$this->assign('surveyResultFields', $surveyResultFields);
$this->assign('surveyResponseFields', $surveyResponseFields);
$templateFile = 'CRM/Report/Form/Campaign/SurveyCoverSheet.tpl';
$coverSheet = CRM_Core_Form::$_template->fetch($templateFile);
return $coverSheet;
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$this->_formatSurveyResult($rows);
$this->_formatSurveyResponseData($rows);
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// handle state province
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value);
}
$entryFound = TRUE;
}
// handle country
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value);
}
$entryFound = TRUE;
}
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contact/detail',
'reset=1&force=1&id_op=eq&id_value=' .
$row['civicrm_contact_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$entryFound = TRUE;
}
if (array_key_exists('civicrm_activity_contact_contact_id', $row)) {
$rows[$rowNum]['civicrm_activity_contact_contact_id'] = CRM_Utils_Array::value($row['civicrm_activity_contact_contact_id'],
CRM_Campaign_BAO_Survey::getInterviewers()
);
$entryFound = TRUE;
}
if (array_key_exists('civicrm_activity_survey_id', $row)) {
$rows[$rowNum]['civicrm_activity_survey_id'] = CRM_Utils_Array::value($row['civicrm_activity_survey_id'],
CRM_Campaign_BAO_Survey::getSurveys()
);
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
/**
* @param $rows
*/
private function _formatSurveyResult(&$rows) {
$surveyIds = CRM_Utils_Array::value('survey_id_value', $this->_params);
if (CRM_Utils_System::isNull($surveyIds) ||
empty($this->_params['fields']['result']) ||
!in_array($this->_outputMode, array('print', 'pdf'))
) {
return;
}
//swap the survey result label w/ value.
$query = '
SELECT survey.id as id,
val.label as label,
val.value as value
FROM civicrm_option_value val
INNER JOIN civicrm_option_group grp ON ( grp.id = val.option_group_id )
INNER JOIN civicrm_survey survey ON ( survey.result_id = grp.id )
WHERE survey.id IN (' . implode(' , ', array_values($surveyIds)) . ' )
Order By val.weight';
$result = CRM_Core_DAO::executeQuery($query);
$resultSet = array();
while ($result->fetch()) {
$resultSet[$result->id][$result->value] = $result->label;
}
$statusId = CRM_Utils_Array::value('status_id_value', $this->_params);
$respondentStatus = CRM_Utils_Array::value($statusId, self::$_surveyRespondentStatus);
$surveyId = CRM_Utils_Array::value(0, $surveyIds);
foreach ($rows as & $row) {
if (!empty($row['civicrm_activity_survey_id'])) {
$surveyId = $row['civicrm_activity_survey_id'];
}
$result = CRM_Utils_Array::value($surveyId, $resultSet, array());
$resultLabel = CRM_Utils_Array::value('civicrm_activity_result', $row);
if ($respondentStatus == 'Reserved') {
$row['civicrm_activity_result'] = implode(' | ', array_keys($result));
}
elseif ($resultLabel) {
$resultValue = array_search($resultLabel, $result);
if ($resultValue) {
$row['civicrm_activity_result'] = $resultValue;
}
}
}
}
/**
* @param $rows
*/
private function _formatSurveyResponseData(&$rows) {
$surveyIds = CRM_Utils_Array::value('survey_id_value', $this->_params);
if (CRM_Utils_System::isNull($surveyIds) ||
empty($this->_params['fields']['survey_response'])
) {
return;
}
$surveyResponseFields = array();
$surveyResponseFieldIds = array();
foreach ($this->_columns as $tableName => $values) {
if (!is_array($values['fields'])) {
continue;
}
foreach ($values['fields'] as $name => $field) {
if (!empty($field['isSurveyResponseField'])) {
$fldId = substr($name, 7);
$surveyResponseFields[$name] = "{$tableName}_{$name}";
$surveyResponseFieldIds[$fldId] = $fldId;
}
}
}
if (empty($surveyResponseFieldIds)) {
return;
}
$hasResponseData = FALSE;
foreach ($surveyResponseFields as $fldName) {
foreach ($rows as $row) {
if (!empty($row[$fldName])) {
$hasResponseData = TRUE;
break;
}
}
}
//do check respondent status.
$statusId = CRM_Utils_Array::value('status_id_value', $this->_params);
$respondentStatus = CRM_Utils_Array::value($statusId, self::$_surveyRespondentStatus);
if (!$hasResponseData &&
($respondentStatus != 'Reserved')
) {
return;
}
//start response data formatting.
$query = '
SELECT cf.id,
cf.data_type,
cf.html_type,
cg.table_name,
cf.column_name,
ov.value, ov.label,
cf.option_group_id
FROM civicrm_custom_field cf
INNER JOIN civicrm_custom_group cg ON ( cg.id = cf.custom_group_id )
LEFT JOIN civicrm_option_value ov ON ( cf.option_group_id = ov.option_group_id )
WHERE cf.id IN ( ' . implode(' , ', $surveyResponseFieldIds) . ' )
Order By ov.weight';
$responseFields = array();
$fieldValueMap = array();
$properties = array(
'id',
'data_type',
'html_type',
'column_name',
'option_group_id',
);
$responseField = CRM_Core_DAO::executeQuery($query);
while ($responseField->fetch()) {
$reponseFldName = $responseField->table_name . '_custom_' .
$responseField->id;
foreach ($properties as $prop) {
$responseFields[$reponseFldName][$prop] = $responseField->$prop;
}
if ($responseField->option_group_id) {
//show value for print and pdf.
$value = $responseField->label;
if (in_array($this->_outputMode, array(
'print',
'pdf',
))) {
$value = $responseField->value;
}
$fieldValueMap[$responseField->option_group_id][$responseField->value] = $value;
}
}
$responseField->free();
//actual data formatting.
$hasData = FALSE;
foreach ($rows as & $row) {
if (!is_array($row)) {
continue;
}
foreach ($row as $name => & $value) {
if (!array_key_exists($name, $responseFields)) {
continue;
}
$hasData = TRUE;
if ($respondentStatus == 'Reserved' &&
in_array($this->_outputMode, array('print', 'pdf'))
) {
$optGrpId = CRM_Utils_Array::value('option_group_id', $responseFields[$name]);
$options = CRM_Utils_Array::value($optGrpId, $fieldValueMap, array());
$value = implode(' | ', array_keys($options));
}
else {
$value = CRM_Core_BAO_CustomField::displayValue($value, $responseFields[$name]['id']);
}
}
if (!$hasData) {
break;
}
}
}
private function _addSurveyResponseColumns() {
$surveyIds = CRM_Utils_Array::value('survey_id_value', $this->_params);
if (CRM_Utils_System::isNull($surveyIds) ||
empty($this->_params['fields']['survey_response'])
) {
return;
}
$responseFields = array();
foreach ($surveyIds as $surveyId) {
$responseFields += CRM_Campaign_BAO_Survey::getSurveyResponseFields($surveyId);
$this->_surveyResponseFields = $responseFields;
}
foreach ($responseFields as $key => $value) {
if (substr($key, 0, 5) == 'phone' && !empty($value['location_type_id'])) {
$fName = str_replace('-', '_', $key);
$this->_columns["civicrm_{$fName}"] = array(
'dao' => 'CRM_Core_DAO_Phone',
'alias' => "phone_civireport_{$fName}",
'fields' => array(
$fName => array_merge($value, array(
'is_required' => '1',
'alias' => "phone_civireport_{$fName}",
'dbAlias' => "phone_civireport_{$fName}.phone",
'no_display' => TRUE,
)
),
),
);
$this->_aliases["civicrm_phone_{$fName}"] = $this->_columns["civicrm_{$fName}"]['alias'];
$this->_locationBasedPhoneField = TRUE;
}
}
$responseFieldIds = array();
foreach (array_keys($responseFields) as $key) {
$cfId = CRM_Core_BAO_CustomField::getKeyID($key);
if ($cfId) {
$responseFieldIds[$cfId] = $cfId;
}
}
if (empty($responseFieldIds)) {
return;
}
$query = '
SELECT cg.extends,
cf.data_type,
cf.html_type,
cg.table_name,
cf.column_name,
cf.time_format,
cf.id as cfId,
cf.option_group_id
FROM civicrm_custom_group cg
INNER JOIN civicrm_custom_field cf ON ( cg.id = cf.custom_group_id )
WHERE cf.id IN ( ' . implode(' , ', $responseFieldIds) .
' ) ORDER BY cf.weight';
$response = CRM_Core_DAO::executeQuery($query);
$fieldCnt = 1;
while ($response->fetch()) {
$resTable = $response->table_name;
$fieldName = "custom_{$response->cfId}";
//need to check does these custom data already included.
if (!array_key_exists($resTable, $this->_columns)) {
$this->_columns[$resTable]['dao'] = 'CRM_Contact_DAO_Contact';
$this->_columns[$resTable]['extends'] = $response->extends;
}
if (empty($this->_columns[$resTable]['alias'])) {
$this->_columns[$resTable]['alias'] = "{$resTable}_survey_response";
}
if (!is_array(CRM_Utils_Array::value('fields', $this->_columns[$resTable]))) {
$this->_columns[$resTable]['fields'] = array();
}
if (in_array($this->_outputMode, array(
'print',
'pdf',
))) {
$this->_columnTitleOverrides["{$resTable}_{$fieldName}"] = 'Q' . $fieldCnt;
$fieldCnt++;
}
if (array_key_exists($fieldName, $this->_columns[$resTable]['fields'])) {
$this->_columns[$resTable]['fields'][$fieldName]['required'] = TRUE;
$this->_columns[$resTable]['fields'][$fieldName]['isSurveyResponseField'] = TRUE;
continue;
}
$title = $responseFields[$fieldName]['title'];
$fldType = 'CRM_Utils_Type::T_STRING';
if ($response->time_format) {
$fldType = CRM_Utils_Type::T_TIMESTAMP;
}
$field = array(
'name' => $response->column_name,
'type' => $fldType,
'title' => $title,
'label' => $responseFields[$fieldName]['title'],
'dataType' => $response->data_type,
'htmlType' => $response->html_type,
'required' => TRUE,
'alias' => ($response->data_type == 'ContactReference') ? $this->_columns[$resTable]['alias'] .
'_contact' : $this->_columns[$resTable]['alias'],
'dbAlias' => $this->_columns[$resTable]['alias'] . '.' .
$response->column_name,
'no_display' => TRUE,
'isSurveyResponseField' => TRUE,
);
$this->_columns[$resTable]['fields'][$fieldName] = $field;
$this->_aliases[$resTable] = $this->_columns[$resTable]['alias'];
}
}
}

View file

@ -0,0 +1,491 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Case_Demographics extends CRM_Report_Form {
protected $_summary = NULL;
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
'default' => TRUE,
),
'birth_date' => array(
'title' => ts('Birthdate'),
'default' => FALSE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'operatorType' => CRM_Report_Form::OP_STRING,
),
'contact_type' => array(
'title' => ts('Contact Type'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
'' => ts('-select-'),
'Individual' => ts('Individual'),
'Organization' => ts('Organization'),
'Household' => ts('Household'),
),
'default' => 'Individual',
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
),
'order_bys' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'default_weight' => '1',
'dbAlias' => 'civicrm_contact_sort_name',
),
),
'grouping' => 'contact-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'grouping' => 'contact-fields',
'fields' => array(
'street_address' => array('default' => FALSE),
'city' => array('default' => TRUE),
'postal_code' => NULL,
'state_province_id' => array(
'title' => ts('State/Province'),
),
'country_id' => array(
'title' => ts('Country'),
'default' => FALSE,
),
),
/*
'filters' => array(
'country_id' => array( 'title' => ts( 'Country' ),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::country( ),
),
'state_province_id' => array( 'title' => ts( 'State/Province' ),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::stateProvince( ), ),
),
*/
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array('phone' => NULL),
'grouping' => 'contact-fields',
),
'civicrm_activity' => array(
'dao' => 'CRM_Activity_DAO_Activity',
'fields' => array(
'id' => array(
'title' => ts('Activity ID'),
'no_display' => TRUE,
'required' => TRUE,
),
),
),
'civicrm_case' => array(
'dao' => 'CRM_Case_DAO_Case',
'fields' => array(
'id' => array(
'title' => ts('Case ID'),
'required' => TRUE,
),
'start_date' => array(
'title' => ts('Case Start'),
'required' => TRUE,
),
'end_date' => array(
'title' => ts('Case End'),
'required' => TRUE,
),
),
'filters' => array(
'case_id_filter' => array(
'name' => 'id',
'title' => ts('Cases?'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
1 => ts('Exclude non-case'),
2 => ts('Exclude cases'),
3 => ts('Include Both'),
),
'default' => 3,
),
'start_date' => array(
'title' => ts('Case Start'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'end_date' => array(
'title' => ts('Case End'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
'order_bys' => array(
'id' => array(
'title' => ts('Case ID'),
'default_weight' => '2',
'dbAlias' => 'civicrm_case_id',
),
),
),
);
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
$open_case_val = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_Activity', 'activity_type_id', 'Open Case');
$crmDAO = &CRM_Core_DAO::executeQuery("SELECT cg.table_name, cg.extends AS ext, cf.label, cf.column_name FROM civicrm_custom_group cg INNER JOIN civicrm_custom_field cf ON cg.id = cf.custom_group_id
where (cg.extends='Contact' OR cg.extends='Individual' OR cg.extends_entity_column_value='$open_case_val') AND cg.is_active=1 AND cf.is_active=1 ORDER BY cg.table_name");
$curTable = '';
$curExt = '';
$curFields = array();
while ($crmDAO->fetch()) {
if ($curTable == '') {
$curTable = $crmDAO->table_name;
$curExt = $crmDAO->ext;
}
elseif ($curTable != $crmDAO->table_name) {
// dummy DAO
$this->_columns[$curTable] = array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => $curFields,
'ext' => $curExt,
);
$curTable = $crmDAO->table_name;
$curExt = $crmDAO->ext;
$curFields = array();
}
$curFields[$crmDAO->column_name] = array('title' => $crmDAO->label);
}
if (!empty($curFields)) {
// dummy DAO
$this->_columns[$curTable] = array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => $curFields,
'ext' => $curExt,
);
}
$this->_genders = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
elseif ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
}
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = $grouping = array();
return $errors;
}
public function from() {
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']}
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1 )
LEFT JOIN civicrm_case_contact ccc ON ccc.contact_id = {$this->_aliases['civicrm_contact']}.id
LEFT JOIN civicrm_case {$this->_aliases['civicrm_case']} ON {$this->_aliases['civicrm_case']}.id = ccc.case_id
LEFT JOIN civicrm_case_activity cca ON cca.case_id = {$this->_aliases['civicrm_case']}.id
LEFT JOIN civicrm_activity {$this->_aliases['civicrm_activity']} ON {$this->_aliases['civicrm_activity']}.id = cca.activity_id
";
foreach ($this->_columns as $t => $c) {
if (substr($t, 0, 13) == 'civicrm_value' ||
substr($t, 0, 12) == 'custom_value'
) {
$this->_from .= " LEFT JOIN $t {$this->_aliases[$t]} ON {$this->_aliases[$t]}.entity_id = ";
$this->_from .= ($c['ext'] ==
'Activity') ? "{$this->_aliases['civicrm_activity']}.id" : "{$this->_aliases['civicrm_contact']}.id";
}
}
if ($this->_emailField) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1) ";
}
if ($this->_phoneField) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1 ";
}
}
public function where() {
$clauses = array();
$this->_having = '';
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if ($field['operatorType'] & CRM_Report_Form::OP_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['dbAlias'], $relative, $from, $to, CRM_Utils_Type::T_DATE);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
// handle special case
if ($fieldName == 'case_id_filter') {
$choice = CRM_Utils_Array::value("{$fieldName}_value", $this->_params);
if ($choice == 1) {
$clause = "({$this->_aliases['civicrm_case']}.id Is Not Null)";
}
elseif ($choice == 2) {
$clause = "({$this->_aliases['civicrm_case']}.id Is Null)";
}
}
else {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
$clauses[] = "(({$this->_aliases['civicrm_case']}.is_deleted = 0) OR ({$this->_aliases['civicrm_case']}.is_deleted Is Null))";
$clauses[] = "(({$this->_aliases['civicrm_activity']}.is_deleted = 0) OR ({$this->_aliases['civicrm_activity']}.is_deleted Is Null))";
$clauses[] = "(({$this->_aliases['civicrm_activity']}.is_current_revision = 1) OR ({$this->_aliases['civicrm_activity']}.is_deleted Is Null))";
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
public function groupBy() {
$groupBy = array("{$this->_aliases['civicrm_contact']}.id", "{$this->_aliases['civicrm_case']}.id");
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
public function postProcess() {
$this->beginPostProcess();
$sql = $this->buildQuery(TRUE);
$rows = $graphRows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// make count columns point to detail report
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact details for this contact.");
$entryFound = TRUE;
}
// handle gender
if (array_key_exists('civicrm_contact_gender_id', $row)) {
if ($value = $row['civicrm_contact_gender_id']) {
$rows[$rowNum]['civicrm_contact_gender_id'] = $this->_genders[$value];
}
$entryFound = TRUE;
}
// handle country
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
}
$entryFound = TRUE;
}
// handle custom fields
foreach ($row as $k => $r) {
if (substr($k, 0, 13) == 'civicrm_value' ||
substr($k, 0, 12) == 'custom_value'
) {
if ($r || $r == '0') {
if ($newval = $this->getCustomFieldLabel($k, $r)) {
$rows[$rowNum][$k] = $newval;
}
}
$entryFound = TRUE;
}
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
/**
* @param string $fname
* @param $val
*
* @return null|string
*/
public function getCustomFieldLabel($fname, $val) {
$query = "
SELECT v.label
FROM civicrm_custom_group cg INNER JOIN civicrm_custom_field cf ON cg.id = cf.custom_group_id
INNER JOIN civicrm_option_group g ON cf.option_group_id = g.id
INNER JOIN civicrm_option_value v ON g.id = v.option_group_id
WHERE CONCAT(cg.table_name, '_', cf.column_name) = %1 AND v.value = %2";
$params = array(
1 => array($fname, 'String'),
2 => array($val, 'String'),
);
return CRM_Core_DAO::singleValueQuery($query, $params);
}
}

View file

@ -0,0 +1,757 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Case_Detail extends CRM_Report_Form {
protected $_relField = FALSE;
protected $_addressField = FALSE;
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
protected $_worldRegionField = FALSE;
protected $_activityLast = FALSE;
protected $_activityLastCompleted = FALSE;
protected $_includeCaseDetailExtra = FALSE;
protected $_caseDetailExtra = array();
protected $_customGroupExtends = array('Case');
protected $_caseTypeNameOrderBy = FALSE;
/**
*/
public function __construct() {
$this->case_statuses = CRM_Core_OptionGroup::values('case_status');
$this->case_types = CRM_Case_PseudoConstant::caseType();
$rels = CRM_Core_PseudoConstant::relationshipType();
foreach ($rels as $relid => $v) {
$this->rel_types[$relid] = $v['label_b_a'];
}
$this->deleted_labels = array(
'' => ts('- select -'),
0 => ts('No'),
1 => ts('Yes'),
);
$this->caseActivityTypes = array();
foreach (CRM_Case_PseudoConstant::caseActivityType() as $typeDetail) {
$this->caseActivityTypes[$typeDetail['id']] = $typeDetail['label'];
}
$this->_columns = array(
'civicrm_case' => array(
'dao' => 'CRM_Case_DAO_Case',
'fields' => array(
'id' => array(
'title' => ts('Case ID'),
'no_display' => TRUE,
'required' => TRUE,
),
'subject' => array(
'title' => ts('Subject'),
'required' => TRUE,
),
'start_date' => array(
'title' => ts('Start Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'end_date' => array(
'title' => ts('End Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'status_id' => array('title' => ts('Case Status')),
'case_type_id' => array('title' => ts('Case Type')),
'is_deleted' => array(
'title' => ts('Deleted?'),
'default' => FALSE,
'type' => CRM_Utils_Type::T_INT,
),
),
'filters' => array(
'start_date' => array(
'title' => ts('Start Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'end_date' => array(
'title' => ts('End Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'status_id' => array(
'title' => ts('Case Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Case_BAO_Case::buildOptions('status_id', 'search'),
),
'case_type_id' => array(
'title' => ts('Case Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Case_BAO_Case::buildOptions('case_type_id', 'search'),
),
'is_deleted' => array(
'title' => ts('Deleted?'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => $this->deleted_labels,
'default' => 0,
),
),
'order_bys' => array(
'start_date' => array(
'title' => ts('Start Date'),
'default_weight' => 1,
),
'end_date' => array(
'title' => ts('End Date'),
),
'status_id' => array(
'title' => ts('Status'),
),
'case_type_name' => array(
'title' => 'Case Type',
),
),
),
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'client_sort_name' => array(
'name' => 'sort_name',
'title' => ts('Client Name'),
'required' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'filters' => array(
'sort_name' => array('title' => ts('Client Name')),
),
),
'civicrm_relationship' => array(
'dao' => 'CRM_Contact_DAO_Relationship',
'fields' => array(
'case_role' => array(
'name' => 'relationship_type_id',
'title' => ts('Case Role(s)'),
),
),
'filters' => array(
'case_role' => array(
'name' => 'relationship_type_id',
'title' => ts('Case Role(s)'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->rel_types,
),
),
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array(
'phone' => array(
'title' => ts('Phone'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'fields' => array(
'street_address' => NULL,
'state_province_id' => array(
'title' => ts('State/Province'),
),
'country_id' => array('title' => ts('Country')),
),
'grouping' => 'contact-fields',
'filters' => array(
'country_id' => array(
'title' => ts('Country'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::country(),
),
'state_province_id' => array(
'title' => ts('State/Province'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::stateProvince(),
),
),
),
'civicrm_worldregion' => array(
'dao' => 'CRM_Core_DAO_Worldregion',
'filters' => array(
'worldregion_id' => array(
'name' => 'id',
'title' => ts('World Region'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::worldRegion(),
),
),
),
'civicrm_country' => array(
'dao' => 'CRM_Core_DAO_Country',
),
'civicrm_activity_last' => array(
'dao' => 'CRM_Activity_DAO_Activity',
'fields' => array(
'last_activity_activity_subject' => array(
'name' => 'subject',
'title' => ts('Subject of the last activity in the case'),
),
'last_activity_activity_type' => array(
'name' => 'activity_type_id',
'title' => ts('Activity type of the last activity'),
),
'last_activity_date_time' => array(
'name' => 'activity_date_time',
'title' => ts('Last Action Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
'filters' => array(
'last_activity_date_time' => array(
'name' => 'activity_date_time',
'title' => ts('Last Action Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
'alias' => 'civireport_activity_last',
),
'civicrm_activity_last_completed' => array(
'dao' => 'CRM_Activity_DAO_Activity',
'fields' => array(
'last_completed_activity_subject' => array(
'name' => 'subject',
'title' => ts('Subject of the last completed activity in the case'),
),
'last_completed_activity_type' => array(
'name' => 'activity_type_id',
'title' => ts('Activity type of the last completed activity'),
),
'last_completed_date_time' => array(
'name' => 'activity_date_time',
'title' => ts('Last Completed Action Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
'filters' => array(
'last_completed_date_time' => array(
'name' => 'activity_date_time',
'title' => ts('Last Completed Action Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
),
);
$this->_options = array(
'my_cases' => array(
'title' => ts('My Cases'),
'type' => 'checkbox',
),
);
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function buildQuickForm() {
parent::buildQuickForm();
$this->caseDetailSpecialColumnsAdd();
}
public function caseDetailSpecialColumnsAdd() {
$elements = array();
$elements[] = &$this->createElement('select', 'case_activity_all_dates', NULL,
array(
'' => ts('- select -'),
) + $this->caseActivityTypes
);
$this->addGroup($elements, 'case_detail_extra');
$this->_caseDetailExtra = array(
'case_activity_all_dates' => array(
'title' => ts('List of all dates of activities of Type'),
'name' => 'activity_date_time',
),
);
$this->assign('caseDetailExtra', $this->_caseDetailExtra);
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
}
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
elseif ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
}
elseif ($tableName == 'civicrm_relationship') {
$this->_relField = TRUE;
}
if ($fieldName == 'sort_name') {
$select[] = "GROUP_CONCAT({$field['dbAlias']} ORDER BY {$field['dbAlias']} )
as {$tableName}_{$fieldName}";
}
if ($tableName == 'civicrm_activity_last') {
$this->_activityLast = TRUE;
}
if ($tableName == 'civicrm_activity_last_completed') {
$this->_activityLastCompleted = TRUE;
}
if ($fieldName == 'case_role') {
$select[] = "GROUP_CONCAT(DISTINCT({$field['dbAlias']}) ORDER BY {$field['dbAlias']}) as {$tableName}_{$fieldName}";
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
}
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
if ($orderBys = $this->_params['order_bys']) {
foreach ($orderBys as $orderBy) {
if ($orderBy['column'] == 'case_type_name') {
$select[] = "civireport_case_types.title as case_type_name";
$this->_caseTypeNameOrderBy = TRUE;
}
}
}
$this->_selectClauses = $select;
$this->_select = 'SELECT ' . implode(', ', $select) . ' ';
}
public function from() {
$case = $this->_aliases['civicrm_case'];
$conact = $this->_aliases['civicrm_contact'];
$this->_from = "
FROM civicrm_case $case
LEFT JOIN civicrm_case_contact civireport_case_contact on civireport_case_contact.case_id = {$case}.id
LEFT JOIN civicrm_contact $conact ON {$conact}.id = civireport_case_contact.contact_id
";
if ($this->_relField) {
$this->_from .= "
LEFT JOIN civicrm_relationship {$this->_aliases['civicrm_relationship']} ON {$this->_aliases['civicrm_relationship']}.case_id = {$case}.id
";
}
if ($this->_addressField) {
$this->_from .= "
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON {$conact}.id = {$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1 ";
}
if ($this->_emailField) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON {$conact}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1 ";
}
if ($this->_phoneField) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON ( {$conact}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1) ";
}
if ($this->_worldRegionField) {
$this->_from .= "
LEFT JOIN civicrm_country {$this->_aliases['civicrm_country']}
ON {$this->_aliases['civicrm_country']}.id ={$this->_aliases['civicrm_address']}.country_id
LEFT JOIN civicrm_worldregion {$this->_aliases['civicrm_worldregion']}
ON {$this->_aliases['civicrm_country']}.region_id = {$this->_aliases['civicrm_worldregion']}.id ";
}
// Include clause for last activity of the case
if ($this->_activityLast) {
$this->_from .= " LEFT JOIN civicrm_activity {$this->_aliases['civicrm_activity_last']} ON ( {$this->_aliases['civicrm_activity_last']}.id = ( SELECT max(activity_id) FROM civicrm_case_activity WHERE case_id = {$case}.id) )";
}
// Include clause for last completed activity of the case
if ($this->_activityLastCompleted) {
$this->_from .= " LEFT JOIN civicrm_activity {$this->_aliases['civicrm_activity_last_completed']} ON ( {$this->_aliases['civicrm_activity_last_completed']}.id = ( SELECT max(activity_id) FROM civicrm_case_activity cca, civicrm_activity ca WHERE ca.id = cca.activity_id AND cca.case_id = {$case}.id AND ca.status_id = 2 ) )";
}
//include case type name
if ($this->_caseTypeNameOrderBy) {
$this->_from .= "
LEFT JOIN civicrm_case_type civireport_case_types
ON {$case}.case_type_id = civireport_case_types.id
";
}
}
public function where() {
$clauses = array();
$this->_having = '';
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['dbAlias'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($fieldName == 'case_type_id' &&
!empty($this->_params['case_type_id_value'])
) {
foreach ($this->_params['case_type_id_value'] as $key => $value) {
$this->_params['case_type_id_value'][$key] = $value;
}
}
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (isset($this->_params['options']['my_cases'])) {
$session = CRM_Core_Session::singleton();
$userID = $session->get('userID');
$clauses[] = "{$this->_aliases['civicrm_contact']}.id = {$userID}";
}
if (empty($clauses)) {
$this->_where = 'WHERE ( 1 ) ';
}
else {
$this->_where = 'WHERE ' . implode(' AND ', $clauses);
}
}
public function groupBy() {
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, "{$this->_aliases['civicrm_case']}.id");
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
$select = "select COUNT( DISTINCT( {$this->_aliases['civicrm_address']}.country_id))";
$sql = "{$select} {$this->_from} {$this->_where}";
$countryCount = CRM_Core_DAO::singleValueQuery($sql);
$statistics['counts']['case'] = array(
'title' => ts('Total Number of Cases '),
'value' => isset($statistics['counts']['rowsFound']) ? $statistics['counts']['rowsFound']['value'] : count($rows),
);
$statistics['counts']['country'] = array(
'title' => ts('Total Number of Countries '),
'value' => $countryCount,
);
return $statistics;
}
public function orderBy() {
parent::orderBy();
if ($this->_caseTypeNameOrderBy) {
$this->_orderBy = str_replace('case_civireport.case_type_name', 'civireport_case_types.title', $this->_orderBy);
}
}
public function caseDetailSpecialColumnProcess() {
if (!$this->_includeCaseDetailExtra) {
return;
}
$from = $select = array();
$case = $this->_aliases['civicrm_case'];
if ($activityType = CRM_Utils_Array::value('case_activity_all_dates', $this->_params['case_detail_extra'])) {
$select[] = "GROUP_CONCAT(DISTINCT(civireport_activity_all_{$activityType}.{$this->_caseDetailExtra['case_activity_all_dates']['name']}) ORDER BY civireport_activity_all_{$activityType}.{$this->_caseDetailExtra['case_activity_all_dates']['name']}) as case_activity_all_dates";
$from[] = " LEFT JOIN civicrm_case_activity civireport_case_activity_all_{$activityType} ON ( civireport_case_activity_all_{$activityType}.case_id = {$case}.id)
LEFT JOIN civicrm_activity civireport_activity_all_{$activityType} ON ( civireport_activity_all_{$activityType}.id = civireport_case_activity_all_{$activityType}.activity_id AND civireport_activity_all_{$activityType}.activity_type_id = {$activityType})";
$this->_columnHeaders['case_activity_all_dates'] = array(
'title' => $this->_caseDetailExtra['case_activity_all_dates']['title'] . ": {$this->caseActivityTypes[$activityType]}",
'type' => CRM_Utils_Array::value('type', $this->_caseDetailExtra['case_activity_all_dates']),
);
}
$this->_select .= ', ' . implode(', ', $select) . ' ';
$this->_from .= ' ' . implode(' ', $from) . ' ';
}
public function postProcess() {
$this->beginPostProcess();
$this->checkEnabledFields();
$this->buildQuery(TRUE);
$this->caseDetailSpecialColumnProcess();
$sql = "{$this->_select} {$this->_from} {$this->_where} {$this->_groupBy} {$this->_having} {$this->_orderBy} {$this->_limit}";
$rows = $graphRows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
public function checkEnabledFields() {
if (isset($this->_params['worldregion_id_value']) &&
!empty($this->_params['worldregion_id_value'])
) {
$this->_addressField = TRUE;
$this->_worldRegionField = TRUE;
}
if (isset($this->_params['case_role_value'])
&& !empty($this->_params['case_role_value'])
) {
$this->_relField = TRUE;
}
if (!empty($this->_params['last_completed_date_time_relative']) ||
!empty($this->_params['last_completed_date_time_from']) ||
CRM_Utils_Array::value('last_completed_date_time_to', $this->_params)
) {
$this->_activityLastCompleted = TRUE;
}
if (!empty($this->_params['last_activity_date_time_relative']) ||
!empty($this->_params['last_activity_date_time_from']) ||
CRM_Utils_Array::value('last_activity_date_time_to', $this->_params)
) {
$this->_activityLast = TRUE;
}
foreach (array_keys($this->_caseDetailExtra) as $field) {
if (!empty($this->_params['case_detail_extra'][$field])) {
$this->_includeCaseDetailExtra = TRUE;
break;
}
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, TRUE);
foreach ($rows as $rowNum => $row) {
if (array_key_exists('civicrm_case_status_id', $row)) {
if ($value = $row['civicrm_case_status_id']) {
$rows[$rowNum]['civicrm_case_status_id'] = $this->case_statuses[$value];
$entryFound = TRUE;
}
}
if (array_key_exists('civicrm_case_case_type_id', $row)) {
if ($value = str_replace(CRM_Core_DAO::VALUE_SEPARATOR, '', $row['civicrm_case_case_type_id'])) {
$rows[$rowNum]['civicrm_case_case_type_id'] = $this->case_types[$value];
$entryFound = TRUE;
}
}
if (array_key_exists('civicrm_case_subject', $row)) {
if ($value = $row['civicrm_case_subject']) {
$url = CRM_Utils_System::url("civicrm/case/ajax/details",
"caseId={$row['civicrm_case_id']}&contactId={$row['civicrm_contact_id']}",
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_case_subject'] = "<a class=\"crm-popup\" href=\"$url\">$value</a>";
$rows[$rowNum]['civicrm_case_subject_hover'] = ts('View Details of Case.');
$entryFound = TRUE;
}
}
if (array_key_exists('civicrm_relationship_case_role', $row)) {
if ($value = $row['civicrm_relationship_case_role']) {
$caseRoles = explode(',', $value);
foreach ($caseRoles as $num => $caseRole) {
$caseRoles[$num] = $this->rel_types[$caseRole];
}
$rows[$rowNum]['civicrm_relationship_case_role'] = implode('; ', $caseRoles);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_activity_last_last_activity_activity_subject', $row) &&
empty($row['civicrm_activity_last_last_activity_activity_subject'])
) {
$rows[$rowNum]['civicrm_activity_last_last_activity_activity_subject'] = ts('(no subject)');
$entryFound = TRUE;
}
if (array_key_exists('civicrm_activity_last_completed_last_completed_activity_subject', $row) &&
empty($row['civicrm_activity_last_completed_last_completed_activity_subject'])
) {
$rows[$rowNum]['civicrm_activity_last_completed_last_completed_activity_subject'] = ts('(no subject)');
$entryFound = TRUE;
}
if (array_key_exists('civicrm_contact_client_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url("civicrm/contact/view",
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_client_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_client_sort_name_hover'] = ts("View Contact Summary for this Contact");
$entryFound = TRUE;
}
if (array_key_exists('civicrm_activity_last_last_activity_activity_type', $row)) {
if ($value = $row['civicrm_activity_last_last_activity_activity_type']) {
$rows[$rowNum]['civicrm_activity_last_last_activity_activity_type'] = $activityTypes[$value];
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_activity_last_completed_last_completed_activity_type', $row)) {
if ($value = $row['civicrm_activity_last_completed_last_completed_activity_type']) {
$rows[$rowNum]['civicrm_activity_last_completed_last_completed_activity_type'] = $activityTypes[$value];
}
$entryFound = TRUE;
}
if (array_key_exists('case_activity_all_dates', $row)) {
if ($value = $row['case_activity_all_dates']) {
$activityDates = explode(',', $value);
foreach ($activityDates as $num => $activityDate) {
$activityDates[$num] = CRM_Utils_Date::customFormat($activityDate);
}
$rows[$rowNum]['case_activity_all_dates'] = implode('; ', $activityDates);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_case_is_deleted', $row)) {
$value = $row['civicrm_case_is_deleted'];
$rows[$rowNum]['civicrm_case_is_deleted'] = $this->deleted_labels[$value];
$entryFound = TRUE;
}
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,441 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Case_Summary extends CRM_Report_Form {
protected $_summary = NULL;
protected $_relField = FALSE;
protected $_exposeContactID = FALSE;
protected $_customGroupExtends = array('Case');
/**
* Class constructor.
*/
public function __construct() {
$this->case_types = CRM_Case_PseudoConstant::caseType();
$this->case_statuses = CRM_Core_OptionGroup::values('case_status');
$rels = CRM_Core_PseudoConstant::relationshipType();
foreach ($rels as $relid => $v) {
$this->rel_types[$relid] = $v['label_b_a'];
}
$this->deleted_labels = array(
'' => ts('- select -'),
0 => ts('No'),
1 => ts('Yes'),
);
$this->_columns = array(
'civicrm_c2' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'client_name' => array(
'name' => 'sort_name',
'title' => ts('Contact Name'),
'required' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'order_bys' => array(
'client_name' => array(
'title' => ts('Contact Name'),
'name' => 'sort_name',
),
),
'grouping' => 'case-fields',
),
'civicrm_case' => array(
'dao' => 'CRM_Case_DAO_Case',
'fields' => array(
'id' => array(
'title' => ts('Case ID'),
'required' => TRUE,
),
'subject' => array(
'title' => ts('Case Subject'),
'default' => TRUE,
),
'status_id' => array(
'title' => ts('Status'),
'default' => TRUE,
),
'case_type_id' => array(
'title' => ts('Case Type'),
'default' => TRUE,
),
'start_date' => array(
'title' => ts('Start Date'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_DATE,
),
'end_date' => array(
'title' => ts('End Date'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_DATE,
),
'duration' => array(
'title' => ts('Duration (Days)'),
'default' => FALSE,
),
'is_deleted' => array(
'title' => ts('Deleted?'),
'default' => FALSE,
'type' => CRM_Utils_Type::T_INT,
),
),
'filters' => array(
'start_date' => array(
'title' => ts('Start Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'end_date' => array(
'title' => ts('End Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'case_type_id' => array(
'title' => ts('Case Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Case_BAO_Case::buildOptions('case_type_id', 'search'),
),
'status_id' => array(
'title' => ts('Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Case_BAO_Case::buildOptions('status_id', 'search'),
),
'is_deleted' => array(
'title' => ts('Deleted?'),
'type' => CRM_Report_Form::OP_INT,
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => $this->deleted_labels,
'default' => 0,
),
),
'order_bys' => array(
'start_date' => array(
'title' => ts('Start Date'),
),
'end_date' => array(
'title' => ts('End Date'),
),
'status_id' => array(
'title' => ts('Status'),
),
),
'grouping' => 'case-fields',
),
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Staff Member'),
'default' => TRUE,
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Staff Member'),
),
),
),
'civicrm_relationship' => array(
'dao' => 'CRM_Contact_DAO_Relationship',
'filters' => array(
'relationship_type_id' => array(
'title' => ts('Staff Relationship'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->rel_types,
),
),
),
'civicrm_relationship_type' => array(
'dao' => 'CRM_Contact_DAO_RelationshipType',
'fields' => array(
'label_b_a' => array(
'title' => ts('Relationship'),
'default' => TRUE,
),
),
),
'civicrm_case_contact' => array(
'dao' => 'CRM_Case_DAO_CaseContact',
),
);
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_relationship_type') {
$this->_relField = TRUE;
}
if ($fieldName == 'duration') {
$select[] = "IF({$table['fields']['end_date']['dbAlias']} Is Null, '', DATEDIFF({$table['fields']['end_date']['dbAlias']}, {$table['fields']['start_date']['dbAlias']})) as {$tableName}_{$fieldName}";
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
}
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = $grouping = array();
if (empty($fields['relationship_type_id_value']) &&
(array_key_exists('sort_name', $fields['fields']) ||
array_key_exists('label_b_a', $fields['fields']))
) {
$errors['fields'] = ts('Either filter on at least one relationship type, or de-select Staff Member and Relationship from the list of fields.');
}
if ((!empty($fields['relationship_type_id_value']) ||
!empty($fields['sort_name_value'])) &&
(!array_key_exists('sort_name', $fields['fields']) ||
!array_key_exists('label_b_a', $fields['fields']))
) {
$errors['fields'] = ts('To filter on Staff Member or Relationship, please also select Staff Member and Relationship from the list of fields.');
}
return $errors;
}
public function from() {
$cc = $this->_aliases['civicrm_case'];
$c = $this->_aliases['civicrm_contact'];
$c2 = $this->_aliases['civicrm_c2'];
$cr = $this->_aliases['civicrm_relationship'];
$crt = $this->_aliases['civicrm_relationship_type'];
$ccc = $this->_aliases['civicrm_case_contact'];
if ($this->_relField) {
$this->_from = "
FROM civicrm_contact $c
inner join civicrm_relationship $cr on {$c}.id = ${cr}.contact_id_b
inner join civicrm_case $cc on ${cc}.id = ${cr}.case_id
inner join civicrm_relationship_type $crt on ${crt}.id=${cr}.relationship_type_id
inner join civicrm_case_contact $ccc on ${ccc}.case_id = ${cc}.id
inner join civicrm_contact $c2 on ${c2}.id=${ccc}.contact_id
";
}
else {
$this->_from = "
FROM civicrm_case $cc
inner join civicrm_case_contact $ccc on ${ccc}.case_id = ${cc}.id
inner join civicrm_contact $c2 on ${c2}.id=${ccc}.contact_id
";
}
}
public function where() {
$clauses = array();
$this->_having = '';
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value("operatorType", $field) & CRM_Report_Form::OP_DATE
) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['dbAlias'], $relative, $from, $to,
CRM_Utils_Array::value('type', $field)
);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($fieldName == 'case_type_id') {
$value = CRM_Utils_Array::value("{$fieldName}_value", $this->_params);
if (!empty($value)) {
$operator = '';
if ($op == 'notin') {
$operator = 'NOT';
}
$regexp = "[[:cntrl:]]*" . implode('[[:>:]]*|[[:<:]]*', $value) . "[[:cntrl:]]*";
$clause = "{$field['dbAlias']} {$operator} REGEXP '{$regexp}'";
}
$op = NULL;
}
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE ( 1 ) ";
}
else {
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
}
public function groupBy() {
$this->_groupBy = "";
}
public function postProcess() {
$this->beginPostProcess();
$sql = $this->buildQuery(TRUE);
$rows = $graphRows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
if (array_key_exists('civicrm_case_status_id', $row)) {
if ($value = $row['civicrm_case_status_id']) {
$rows[$rowNum]['civicrm_case_status_id'] = $this->case_statuses[$value];
$entryFound = TRUE;
}
}
if (array_key_exists('civicrm_case_case_type_id', $row) &&
!empty($rows[$rowNum]['civicrm_case_case_type_id'])
) {
$value = $row['civicrm_case_case_type_id'];
$typeIds = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
$value = array();
foreach ($typeIds as $typeId) {
if ($typeId) {
$value[$typeId] = $this->case_types[$typeId];
}
}
$rows[$rowNum]['civicrm_case_case_type_id'] = implode(', ', $value);
$entryFound = TRUE;
}
// convert Case ID and Subject to links to Manage Case
if (array_key_exists('civicrm_case_id', $row) &&
!empty($rows[$rowNum]['civicrm_c2_id'])
) {
$url = CRM_Utils_System::url("civicrm/contact/view/case",
'reset=1&action=view&cid=' . $row['civicrm_c2_id'] . '&id=' .
$row['civicrm_case_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_case_id_link'] = $url;
$rows[$rowNum]['civicrm_case_id_hover'] = ts("Manage Case");
$entryFound = TRUE;
}
if (array_key_exists('civicrm_case_subject', $row) &&
!empty($rows[$rowNum]['civicrm_c2_id'])
) {
$url = CRM_Utils_System::url("civicrm/contact/view/case",
'reset=1&action=view&cid=' . $row['civicrm_c2_id'] . '&id=' .
$row['civicrm_case_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_case_subject_link'] = $url;
$rows[$rowNum]['civicrm_case_subject_hover'] = ts("Manage Case");
$entryFound = TRUE;
}
if (array_key_exists('civicrm_case_is_deleted', $row)) {
$value = $row['civicrm_case_is_deleted'];
$rows[$rowNum]['civicrm_case_is_deleted'] = $this->deleted_labels[$value];
$entryFound = TRUE;
}
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,385 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Case_TimeSpent extends CRM_Report_Form {
/**
* Class constructor.
*/
public function __construct() {
$this->activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, TRUE);
asort($this->activityTypes);
$this->activityStatuses = CRM_Core_PseudoConstant::activityStatus();
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
'required' => TRUE,
),
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'operator' => 'like',
'type' => CRM_Report_Form::OP_STRING,
),
),
'order_bys' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'default_weight' => '1',
),
),
),
'civicrm_activity' => array(
'dao' => 'CRM_Activity_DAO_Activity',
'fields' => array(
'activity_type_id' => array(
'title' => ts('Activity Type'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_STRING,
),
'activity_date_time' => array(
'title' => ts('Activity Date'),
'default' => TRUE,
),
'status_id' => array(
'title' => ts('Activity Status'),
'default' => FALSE,
'type' => CRM_Utils_Type::T_STRING,
),
'id' => array(
'title' => ts('Activity ID'),
'default' => TRUE,
),
'duration' => array(
'title' => ts('Duration'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_INT,
),
'subject' => array(
'title' => ts('Activity Subject'),
'default' => FALSE,
),
),
'filters' => array(
'activity_date_time' => array(
'operatorType' => CRM_Report_Form::OP_DATE,
),
'subject' => array(
'title' => ts('Activity Subject'),
'type' => CRM_Utils_Type::T_STRING,
'operator' => 'like',
),
'activity_type_id' => array(
'title' => ts('Activity Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activityTypes,
),
'status_id' => array(
'title' => ts('Activity Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activityStatuses,
),
),
'order_bys' => array(
'subject' => array(
'title' => ts('Activity Subject'),
),
'activity_type_id' => array(
'title' => ts('Activity Type'),
),
'activity_date_time' => array(
'title' => ts('Activity Date'),
),
'status_id' => array(
'title' => ts('Activity Status'),
),
),
'grouping' => 'case-fields',
),
'civicrm_activity_source' => array(
'dao' => 'CRM_Activity_DAO_ActivityContact',
'fields' => array(
'contact_id' => array(
'title' => ts('Contact ID'),
'default' => TRUE,
'no_display' => TRUE,
),
),
'group_bys' => array(
'contact_id' => array(
'title' => ts('Totals Only'),
'default' => TRUE,
),
),
'grouping' => 'activity-fields',
),
'civicrm_case_activity' => array(
'dao' => 'CRM_Case_DAO_CaseActivity',
'fields' => array(
'case_id' => array(
'title' => ts('Case ID'),
'default' => FALSE,
),
),
'filters' => array(
'case_id_filter' => array(
'name' => 'case_id',
'title' => ts('Cases?'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
1 => ts('Exclude non-case'),
2 => ts('Exclude cases'),
3 => ts('Include Both'),
),
'default' => 3,
),
),
),
);
parent::__construct();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
$this->has_grouping = !empty($this->_params['group_bys']);
$this->has_activity_type = FALSE;
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
(!empty($this->_params['fields'][$fieldName]) &&
((!$this->has_grouping) ||
!in_array($fieldName, array('case_id', 'subject', 'status_id')))
)
) {
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = CRM_Utils_Array::value('no_display', $field);
if ($fieldName == 'activity_type_id') {
$this->has_activity_type = TRUE;
}
if ($fieldName == 'duration' && $this->has_grouping) {
$select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}";
}
elseif ($fieldName == 'activity_date_time' && $this->has_grouping) {
$select[] = "EXTRACT(YEAR_MONTH FROM {$field['dbAlias']}) AS {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = ts('Month/Year');
}
elseif ($tableName == 'civicrm_activity' && $fieldName == 'id' &&
$this->has_grouping
) {
$select[] = "COUNT({$field['dbAlias']}) AS {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = ts('# Activities');
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
}
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$this->_from = "
FROM civicrm_activity {$this->_aliases['civicrm_activity']}
LEFT JOIN civicrm_activity_contact {$this->_aliases['civicrm_activity_source']}
ON {$this->_aliases['civicrm_activity']}.id = {$this->_aliases['civicrm_activity_source']}.activity_id
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON {$this->_aliases['civicrm_activity_source']}.contact_id = {$this->_aliases['civicrm_contact']}.id
LEFT JOIN civicrm_case_activity {$this->_aliases['civicrm_case_activity']}
ON {$this->_aliases['civicrm_case_activity']}.activity_id = {$this->_aliases['civicrm_activity']}.id
";
}
public function where() {
$this->_where = " WHERE {$this->_aliases['civicrm_activity']}.is_current_revision = 1 AND
{$this->_aliases['civicrm_activity']}.is_deleted = 0 AND
{$this->_aliases['civicrm_activity']}.is_test = 0";
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['dbAlias'], $relative, $from, $to);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
// handle special case
if ($fieldName == 'case_id_filter') {
$choice = CRM_Utils_Array::value("{$fieldName}_value", $this->_params);
if ($choice == 1) {
$clause = "({$this->_aliases['civicrm_case_activity']}.id Is Not Null)";
}
elseif ($choice == 2) {
$clause = "({$this->_aliases['civicrm_case_activity']}.id Is Null)";
}
}
else {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where .= " ";
}
else {
$this->_where .= " AND " . implode(' AND ', $clauses);
}
}
public function groupBy() {
$this->_groupBy = '';
if ($this->has_grouping) {
$groupBy = array(
"{$this->_aliases['civicrm_contact']}.id",
"civicrm_activity_activity_date_time",
);
if ($this->has_activity_type) {
$groupBy[] = "{$this->_aliases['civicrm_activity']}.activity_type_id";
}
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
}
public function postProcess() {
parent::postProcess();
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = array();
if (!empty($fields['group_bys']) &&
(!array_key_exists('id', $fields['fields']) ||
!array_key_exists('activity_date_time', $fields['fields']) ||
!array_key_exists('duration', $fields['fields']))
) {
$errors['fields'] = ts('To view totals please select all of activity id, date and duration.');
}
return $errors;
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
if (isset($row['civicrm_activity_activity_type_id'])) {
$entryFound = TRUE;
$val = $row['civicrm_activity_activity_type_id'];
$rows[$rowNum]['civicrm_activity_activity_type_id'] = isset($this->activityTypes[$val]) ? $this->activityTypes[$val] : '';
}
if (isset($row['civicrm_activity_status_id'])) {
$entryFound = TRUE;
$val = $row['civicrm_activity_status_id'];
$rows[$rowNum]['civicrm_activity_status_id'] = isset($this->activityStatuses[$val]) ? $this->activityStatuses[$val] : '';
}
// The next two make it easier to make pivot tables after exporting to Excel
if (isset($row['civicrm_activity_duration'])) {
$entryFound = TRUE;
$rows[$rowNum]['civicrm_activity_duration'] = (int) $row['civicrm_activity_duration'];
}
if (isset($row['civicrm_case_activity_case_id'])) {
$entryFound = TRUE;
$rows[$rowNum]['civicrm_case_activity_case_id'] = (int) $row['civicrm_case_activity_case_id'];
}
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,428 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Contact_CurrentEmployer extends CRM_Report_Form {
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
protected $_summary = NULL;
protected $_customGroupExtends = array(
'Contact',
'Individual',
);
public $_drilldownReport = array('contact/detail' => 'Link to Detail Report');
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_employer' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'organization_name' => array(
'title' => ts('Employer Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'filters' => array(
'organization_name' => array(
'title' => ts('Employer Name'),
'operatorType' => CRM_Report_Form::OP_STRING,
),
),
),
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Employee Name'),
'required' => TRUE,
),
'first_name' => array(
'title' => ts('First Name'),
),
'middle_name' => array(
'title' => ts('Middle Name'),
),
'last_name' => array(
'title' => ts('Last Name'),
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'job_title' => array(
'title' => ts('Job Title'),
'default' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
),
'age' => array(
'title' => ts('Age'),
'dbAlias' => 'TIMESTAMPDIFF(YEAR, contact_civireport.birth_date, CURDATE())',
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => array_merge($this->getBasicContactFilters(), array('sort_name' => array('title' => ts('Employee Name')))),
'grouping' => 'contact-fields',
),
'civicrm_relationship' => array(
'dao' => 'CRM_Contact_DAO_Relationship',
'fields' => array(
'start_date' => array(
'title' => ts('Employee Since'),
'default' => TRUE,
),
),
'filters' => array(
'start_date' => array(
'title' => ts('Employee Since'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
),
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'grouping' => 'contact-fields',
'fields' => array(
'phone' => array(
'title' => ts('Phone'),
'default' => TRUE,
),
),
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'grouping' => 'contact-fields',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'default' => TRUE,
),
),
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'grouping' => 'contact-fields',
'fields' => array(
'street_address' => NULL,
'city' => NULL,
'postal_code' => NULL,
'state_province_id' => array(
'title' => ts('State/Province'),
),
'country_id' => array(
'title' => ts('Country'),
),
),
'filters' => array(
'country_id' => array(
'title' => ts('Country'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::country(NULL, FALSE),
),
'state_province_id' => array(
'title' => ts('State/Province'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::stateProvince(),
),
),
),
'civicrm_group' => array(
'dao' => 'CRM_Contact_DAO_Group',
'alias' => 'cgroup',
'filters' => array(
'gid' => array(
'name' => 'group_id',
'title' => ts('Group'),
'type' => CRM_Utils_Type::T_INT,
'group' => TRUE,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::staticGroup(),
),
),
),
);
$this->_tagFilter = TRUE;
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = $this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$relType = civicrm_api3('RelationshipType', 'getvalue', array(
'return' => "id",
'name_a_b' => "Employee of",
'name_b_a' => "Employer of",
));
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_employer']}
ON {$this->_aliases['civicrm_employer']}.id={$this->_aliases['civicrm_contact']}.employer_id
{$this->_aclFrom}
LEFT JOIN civicrm_relationship {$this->_aliases['civicrm_relationship']}
ON ( {$this->_aliases['civicrm_relationship']}.contact_id_a={$this->_aliases['civicrm_contact']}.id
AND {$this->_aliases['civicrm_relationship']}.contact_id_b={$this->_aliases['civicrm_contact']}.employer_id
AND {$this->_aliases['civicrm_relationship']}.relationship_type_id={$relType})
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id
AND {$this->_aliases['civicrm_address']}.is_primary = 1 )
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id
AND {$this->_aliases['civicrm_phone']}.is_primary = 1)
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id
AND {$this->_aliases['civicrm_email']}.is_primary = 1) ";
}
public function where() {
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('operatorType', $field) & CRM_Report_Form::OP_DATE
) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['dbAlias'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[$fieldName] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE {$this->_aliases['civicrm_contact']}.employer_id!='null' ";
}
else {
$this->_where = "WHERE ({$this->_aliases['civicrm_contact']}.employer_id!='null') AND " . implode(' AND ', $clauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
public function groupBy() {
$groupBy = array(
"{$this->_aliases['civicrm_employer']}.id",
"{$this->_aliases['civicrm_contact']}.id",
);
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
public function orderBy() {
$this->_orderBy = "ORDER BY {$this->_aliases['civicrm_employer']}.organization_name, {$this->_aliases['civicrm_contact']}.display_name";
}
public function postProcess() {
// get the acl clauses built before we assemble the query
$this->buildACLClause(array(
$this->_aliases['civicrm_contact'],
$this->_aliases['civicrm_employer'],
));
parent::postProcess();
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$checkList = array();
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// convert employer name to links
if (array_key_exists('civicrm_employer_organization_name', $row) &&
array_key_exists('civicrm_employer_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contact/detail',
'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_employer_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_employer_organization_name_link'] = $url;
$rows[$rowNum]['civicrm_employer_organization_name_hover'] = ts('View Contact Detail Report for this contact');
$entryFound = TRUE;
}
if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
// not repeat contact display names if it matches with the one
// in previous row
foreach ($row as $colName => $colVal) {
if (!empty($checkList[$colName]) && is_array($checkList[$colName]) &&
in_array($colVal, $checkList[$colName])
) {
$rows[$rowNum][$colName] = "";
}
if (in_array($colName, $this->_noRepeats)) {
$checkList[$colName][] = $colVal;
}
}
}
// Handle ID to label conversion for contact fields
$entryFound = $this->alterDisplayContactFields($row, $rows, $rowNum, 'contact/currentEmployer', 'View Contact Detail') ? TRUE : $entryFound;
// display birthday in the configured custom format
if (array_key_exists('civicrm_contact_birth_date', $row)) {
$birthDate = $row['civicrm_contact_birth_date'];
if ($birthDate) {
$rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
}
$entryFound = TRUE;
}
// convert employee name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contact/detail',
'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts('View Contact Detail Report for this contact');
$entryFound = TRUE;
}
// handle country
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
}
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,972 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Contact_Detail extends CRM_Report_Form {
const ROW_COUNT_LIMIT = 10;
protected $_summary = NULL;
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Household',
'Organization',
);
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_autoIncludeIndexedFieldsAsOrderBys = 1;
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
'first_name' => array(
'title' => ts('First Name'),
),
'middle_name' => array(
'title' => ts('Middle Name'),
),
'last_name' => array(
'title' => ts('Last Name'),
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
),
'age' => array(
'title' => ts('Age'),
'dbAlias' => 'TIMESTAMPDIFF(YEAR, contact_civireport.birth_date, CURDATE())',
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => $this->getBasicContactFilters(),
'grouping' => 'contact-fields',
'order_bys' => array(
'sort_name' => array(
'title' => ts('Last Name, First Name'),
'default' => '1',
'default_weight' => '0',
'default_order' => 'ASC',
),
'first_name' => array(
'title' => ts('First Name'),
),
'gender_id' => array(
'name' => 'gender_id',
'title' => ts('Gender'),
),
'birth_date' => array(
'name' => 'birth_date',
'title' => ts('Birth Date'),
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'grouping' => 'contact-fields',
'fields' => array(
'street_address' => NULL,
'city' => NULL,
'postal_code' => NULL,
'state_province_id' => array(
'title' => ts('State/Province'),
),
),
'order_bys' => array(
'state_province_id' => array('title' => ts('State/Province')),
'city' => array('title' => ts('City')),
'postal_code' => array('title' => ts('Postal Code')),
),
),
'civicrm_country' => array(
'dao' => 'CRM_Core_DAO_Country',
'fields' => array(
'name' => array('title' => ts('Country'), 'default' => TRUE),
),
'order_bys' => array(
'name' => array('title' => ts('Country')),
),
'grouping' => 'contact-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
'order_bys' => array(
'email' => array(
'title' => ts('Email'),
),
),
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'contact_id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'contribution_id' => array(
'title' => ts('Contribution'),
'no_repeat' => TRUE,
'default' => TRUE,
),
'total_amount' => array('default' => TRUE),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'default' => TRUE,
),
'trxn_id' => NULL,
'receive_date' => array('default' => TRUE),
'receipt_date' => NULL,
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'default' => TRUE,
),
'contribution_source' => NULL,
),
),
'civicrm_membership' => array(
'dao' => 'CRM_Member_DAO_Membership',
'fields' => array(
'contact_id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'membership_id' => array(
'title' => ts('Membership'),
'no_repeat' => TRUE,
'default' => TRUE,
),
'membership_type_id' => array(
'title' => ts('Membership Type'),
'default' => TRUE,
),
'join_date' => NULL,
'membership_start_date' => array(
'title' => ts('Start Date'),
'default' => TRUE,
),
'membership_end_date' => array(
'title' => ts('End Date'),
'default' => TRUE,
),
'membership_status_id' => array(
'name' => 'status_id',
'title' => ts('Membership Status'),
'default' => TRUE,
),
'source' => array('title' => ts('Membership Source')),
),
),
'civicrm_participant' => array(
'dao' => 'CRM_Event_DAO_Participant',
'fields' => array(
'contact_id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'participant_id' => array(
'title' => ts('Participant'),
'no_repeat' => TRUE,
'default' => TRUE,
),
'event_id' => array('default' => TRUE),
'participant_status_id' => array(
'name' => 'status_id',
'title' => ts('Participant Status'),
'default' => TRUE,
),
'role_id' => array(
'title' => ts('Role'),
'default' => TRUE,
),
'participant_register_date' => array(
'title' => ts('Register Date'),
'default' => TRUE,
),
'fee_level' => array(
'title' => ts('Fee Level'),
'default' => TRUE,
),
'fee_amount' => array(
'title' => ts('Fee Amount'),
'default' => TRUE,
),
),
),
'civicrm_relationship' => array(
'dao' => 'CRM_Contact_DAO_Relationship',
'fields' => array(
'relationship_id' => array(
'name' => 'id',
'title' => ts('Relationship'),
'no_repeat' => TRUE,
'default' => TRUE,
),
'relationship_type_id' => array(
'title' => ts('Relationship Type'),
'default' => TRUE,
),
'contact_id_b' => array(
'title' => ts('Relationship With'),
'default' => TRUE,
),
'start_date' => array(
'title' => ts('Start Date'),
'type' => CRM_Report_Form::OP_DATE,
),
'end_date' => array(
'title' => ts('End Date'),
'type' => CRM_Report_Form::OP_DATE,
),
),
),
'civicrm_activity' => array(
'dao' => 'CRM_Activity_DAO_Activity',
'fields' => array(
'id' => array(
'title' => ts('Activity'),
'no_repeat' => TRUE,
'default' => TRUE,
),
'activity_type_id' => array(
'title' => ts('Activity Type'),
'default' => TRUE,
),
'subject' => array(
'title' => ts('Subject'),
'default' => TRUE,
),
'activity_date_time' => array(
'title' => ts('Activity Date'),
'default' => TRUE,
),
'activity_status_id' => array(
'name' => 'status_id',
'title' => ts('Activity Status'),
'default' => TRUE,
),
),
'grouping' => 'activity-fields',
),
'civicrm_activity_target' => array(
'dao' => 'CRM_Activity_DAO_ActivityContact',
'fields' => array(
'target_contact_id' => array(
'title' => ts('With Contact'),
'name' => 'contact_id',
'default' => TRUE,
),
),
'grouping' => 'activity-fields',
),
'civicrm_activity_assignment' => array(
'dao' => 'CRM_Activity_DAO_ActivityContact',
'fields' => array(
'assignee_contact_id' => array(
'title' => ts('Assigned to'),
'name' => 'contact_id',
'default' => TRUE,
),
),
'grouping' => 'activity-fields',
),
'civicrm_activity_source' => array(
'dao' => 'CRM_Activity_DAO_ActivityContact',
'fields' => array(
'source_contact_id' => array(
'title' => ts('Added By'),
'name' => 'contact_id',
'default' => TRUE,
),
),
'grouping' => 'activity-fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array(
'phone' => NULL,
'phone_ext' => array(
'title' => ts('Phone Extension'),
),
),
'grouping' => 'contact-fields',
),
);
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
public function preProcess() {
$this->_csvSupported = FALSE;
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
$this->_component = array(
'contribution_civireport',
'membership_civireport',
'participant_civireport',
'relationship_civireport',
'activity_civireport',
);
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
//isolate the select clause compoenent wise
if (in_array($table['alias'], $this->_component)) {
$select[$table['alias']][] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeadersComponent[$table['alias']]["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeadersComponent[$table['alias']]["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
}
elseif ($table['alias'] ==
$this->_aliases['civicrm_activity_target'] ||
$table['alias'] ==
$this->_aliases['civicrm_activity_assignment'] ||
$table['alias'] == $this->_aliases['civicrm_activity_source']
) {
if ($table['alias'] == $this->_aliases['civicrm_activity_target']
) {
$addContactId = 'civicrm_activity_target.contact_id as target_contact_id';
}
elseif ($table['alias'] ==
$this->_aliases['civicrm_activity_source']
) {
$addContactId = 'civicrm_activity_source.contact_id';
}
else {
$addContactId = 'civicrm_activity_assignment.contact_id as assignee_contact_id';
}
$tableName = $table['alias'];
$select['activity_civireport'][] = "$tableName.display_name as {$tableName}_{$fieldName}, $addContactId ";
$this->_columnHeadersComponent['activity_civireport']["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeadersComponent['activity_civireport']["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
}
foreach ($this->_component as $val) {
if (!empty($select[$val])) {
$this->_selectComponent[$val] = "SELECT " . implode(', ', $select[$val]) . " ";
unset($select[$val]);
}
}
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = array();
return $errors;
}
public function from() {
$group = " ";
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}";
if ($this->isTableSelected('civicrm_country') ||
$this->isTableSelected('civicrm_address')
) {
$this->_from .= "
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1 ) ";
}
if ($this->isTableSelected('civicrm_email')) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1) ";
}
if ($this->isTableSelected('civicrm_phone')) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1 ";
}
if ($this->isTableSelected('civicrm_country')) {
$this->_from .= "
LEFT JOIN civicrm_country {$this->_aliases['civicrm_country']}
ON {$this->_aliases['civicrm_address']}.country_id = {$this->_aliases['civicrm_country']}.id AND
{$this->_aliases['civicrm_address']}.is_primary = 1 ";
}
$this->_from .= "{$group}";
foreach ($this->_component as $val) {
if (!empty($this->_selectComponent['contribution_civireport'])) {
$this->_formComponent['contribution_civireport'] = " FROM
civicrm_contact {$this->_aliases['civicrm_contact']}
INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_contribution']}.contact_id
{$group}
";
}
if (!empty($this->_selectComponent['membership_civireport'])) {
$this->_formComponent['membership_civireport'] = " FROM
civicrm_contact {$this->_aliases['civicrm_contact']}
INNER JOIN civicrm_membership {$this->_aliases['civicrm_membership']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_membership']}.contact_id
{$group} ";
}
if (!empty($this->_selectComponent['participant_civireport'])) {
$this->_formComponent['participant_civireport'] = " FROM
civicrm_contact {$this->_aliases['civicrm_contact']}
INNER JOIN civicrm_participant {$this->_aliases['civicrm_participant']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_participant']}.contact_id
{$group} ";
}
if (!empty($this->_selectComponent['activity_civireport'])) {
$activityContacts = CRM_Activity_BAO_ActivityContact::buildOptions('record_type_id', 'validate');
$assigneeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
$targetID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
$sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
$this->_formComponent['activity_civireport'] = "FROM
civicrm_activity {$this->_aliases['civicrm_activity']}
LEFT JOIN civicrm_activity_contact civicrm_activity_target ON
{$this->_aliases['civicrm_activity']}.id = civicrm_activity_target.activity_id AND
civicrm_activity_target.record_type_id = {$targetID}
LEFT JOIN civicrm_activity_contact civicrm_activity_assignment ON
{$this->_aliases['civicrm_activity']}.id = civicrm_activity_assignment.activity_id AND civicrm_activity_assignment.record_type_id = {$assigneeID}
LEFT JOIN civicrm_activity_contact civicrm_activity_source
ON {$this->_aliases['civicrm_activity']}.id = civicrm_activity_source.activity_id AND
civicrm_activity_source.record_type_id = {$sourceID}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_activity_target']} ON
civicrm_activity_target.contact_id = {$this->_aliases['civicrm_activity_target']}.id
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_activity_assignment']} ON
civicrm_activity_assignment.contact_id = {$this->_aliases['civicrm_activity_assignment']}.id
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_activity_source']} ON
civicrm_activity_source.contact_id = {$this->_aliases['civicrm_activity_source']}.id
LEFT JOIN civicrm_option_value ON
( {$this->_aliases['civicrm_activity']}.activity_type_id = civicrm_option_value.value )
LEFT JOIN civicrm_option_group ON
civicrm_option_group.id = civicrm_option_value.option_group_id
LEFT JOIN civicrm_case_activity ON
civicrm_case_activity.activity_id = {$this->_aliases['civicrm_activity']}.id
LEFT JOIN civicrm_case ON
civicrm_case_activity.case_id = civicrm_case.id
LEFT JOIN civicrm_case_contact ON
civicrm_case_contact.case_id = civicrm_case.id ";
}
if (!empty($this->_selectComponent['relationship_civireport'])) {
$this->_formComponent['relationship_civireport'] = "FROM
civicrm_relationship {$this->_aliases['civicrm_relationship']}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']} ON
{$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_relationship']}.contact_id_b
LEFT JOIN civicrm_contact contact_a ON
contact_a.id = {$this->_aliases['civicrm_relationship']}.contact_id_a ";
}
}
}
public function where() {
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('operatorType', $field) & CRM_Report_Form::OP_DATE
) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['dbAlias'], $relative, $from, $to);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE ( 1 ) ";
}
else {
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
/**
* @return array
*/
public function clauseComponent() {
$selectedContacts = implode(',', $this->_contactSelected);
$contribution = $membership = $participant = NULL;
$eligibleResult = $rows = $tempArray = array();
foreach ($this->_component as $val) {
if (!empty($this->_selectComponent[$val]) &&
($val != 'activity_civireport' && $val != 'relationship_civireport')
) {
$sql = "{$this->_selectComponent[$val]} {$this->_formComponent[$val]}
WHERE {$this->_aliases['civicrm_contact']}.id IN ( $selectedContacts )
";
$dao = CRM_Core_DAO::executeQuery($sql);
while ($dao->fetch()) {
$countRecord = 0;
$eligibleResult[$val] = $val;
$CC = 'civicrm_' . substr_replace($val, '', -11, 11) . '_contact_id';
$row = array();
foreach ($this->_columnHeadersComponent[$val] as $key => $value) {
$countRecord++;
$row[$key] = $dao->$key;
}
//if record exist for component(except contact_id)
//since contact_id is selected for every component
if ($countRecord > 1) {
$rows[$dao->$CC][$val][] = $row;
}
$tempArray[$dao->$CC] = $dao->$CC;
}
}
}
if (!empty($this->_selectComponent['relationship_civireport'])) {
$relTypes = CRM_Contact_BAO_Relationship::getContactRelationshipType(NULL, NULL, NULL, NULL, TRUE);
$val = 'relationship_civireport';
$eligibleResult[$val] = $val;
$sql = "{$this->_selectComponent[$val]},{$this->_aliases['civicrm_contact']}.display_name as contact_b_name, contact_a.id as contact_a_id , contact_a.display_name as contact_a_name {$this->_formComponent[$val]}
WHERE ({$this->_aliases['civicrm_contact']}.id IN ( $selectedContacts )
OR
contact_a.id IN ( $selectedContacts ) ) AND
{$this->_aliases['civicrm_relationship']}.is_active = 1 AND
contact_a.is_deleted = 0 AND
{$this->_aliases['civicrm_contact']}.is_deleted = 0
";
$dao = CRM_Core_DAO::executeQuery($sql);
while ($dao->fetch()) {
foreach ($this->_columnHeadersComponent[$val] as $key => $value) {
if ($key == 'civicrm_relationship_contact_id_b') {
$row[$key] = $dao->contact_b_name;
continue;
}
$row[$key] = $dao->$key;
}
$relTitle = "" . $dao->civicrm_relationship_relationship_type_id .
'_a_b';
$row['civicrm_relationship_relationship_type_id'] = $relTypes[$relTitle];
$rows[$dao->contact_a_id][$val][] = $row;
$row['civicrm_relationship_contact_id_b'] = $dao->contact_a_name;
$relTitle = "" . $dao->civicrm_relationship_relationship_type_id .
'_b_a';
if (isset($relTypes[$relTitle])) {
$row['civicrm_relationship_relationship_type_id'] = $relTypes[$relTitle];
}
$rows[$dao->civicrm_relationship_contact_id_b][$val][] = $row;
}
}
if (!empty($this->_selectComponent['activity_civireport'])) {
$componentClause = "civicrm_option_value.component_id IS NULL";
$componentsIn = NULL;
$compInfo = CRM_Core_Component::getEnabledComponents();
foreach ($compInfo as $compObj) {
if ($compObj->info['showActivitiesInCore']) {
$componentsIn = $componentsIn ? ($componentsIn . ', ' .
$compObj->componentID) : $compObj->componentID;
}
}
if ($componentsIn) {
$componentClause = "( $componentClause OR
civicrm_option_value.component_id IN ($componentsIn) )";
}
$val = 'activity_civireport';
$eligibleResult[$val] = $val;
$sql = "{$this->_selectComponent[$val]} ,
{$this->_aliases['civicrm_activity_source']}.display_name as added_by {$this->_formComponent[$val]}
WHERE ( civicrm_activity_source.contact_id IN ($selectedContacts) OR
civicrm_activity_target.contact_id IN ($selectedContacts) OR
civicrm_activity_assignment.contact_id IN ($selectedContacts) OR
civicrm_case_contact.contact_id IN ($selectedContacts) ) AND
civicrm_option_group.name = 'activity_type' AND
{$this->_aliases['civicrm_activity']}.is_test = 0 AND
($componentClause)
ORDER BY {$this->_aliases['civicrm_activity']}.activity_date_time desc ";
$dao = CRM_Core_DAO::executeQuery($sql);
while ($dao->fetch()) {
foreach ($this->_columnHeadersComponent[$val] as $key => $value) {
if ($key == 'civicrm_activity_source_contact_id') {
$row[$key] = $dao->added_by;
continue;
}
$row[$key] = $dao->$key;
}
if (isset($dao->civicrm_activity_source_contact_id)) {
$rows[$dao->civicrm_activity_source_contact_id][$val][] = $row;
}
if (isset($dao->target_contact_id)) {
$rows[$dao->target_contact_id][$val][] = $row;
}
if (isset($dao->assignee_contact_id)) {
$rows[$dao->assignee_contact_id][$val][] = $row;
}
}
//unset the component header if data is not present
foreach ($this->_component as $val) {
if (!in_array($val, $eligibleResult)) {
unset($this->_columnHeadersComponent[$val]);
}
}
}
return $rows;
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = array();
$count = count($rows);
if ($this->_rollup && ($this->_rollup != '')) {
$count++;
}
$this->countStat($statistics, $count);
$this->filterStat($statistics);
return $statistics;
}
/**
* Override to set limit is 10
* @param int $rowCount
*/
public function limit($rowCount = self::ROW_COUNT_LIMIT) {
parent::limit($rowCount);
}
/**
* Override to set pager with limit is 10
* @param int $rowCount
*/
public function setPager($rowCount = self::ROW_COUNT_LIMIT) {
parent::setPager($rowCount);
}
public function postProcess() {
$this->beginPostProcess();
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
$sql = $this->buildQuery(TRUE);
$rows = $graphRows = $this->_contactSelected = array();
$this->buildRows($sql, $rows);
foreach ($rows as $key => $val) {
$rows[$key]['contactID'] = $val['civicrm_contact_id'];
$this->_contactSelected[] = $val['civicrm_contact_id'];
}
$this->formatDisplay($rows);
if (!empty($this->_contactSelected)) {
$componentRows = $this->clauseComponent();
$this->alterComponentDisplay($componentRows);
//unset Conmponent id and contact id from display
foreach ($this->_columnHeadersComponent as $componentTitle => $headers) {
$id_header = 'civicrm_' . substr_replace($componentTitle, '', -11, 11) . '_' .
substr_replace($componentTitle, '', -11, 11) . '_id';
$contact_header = 'civicrm_' . substr_replace($componentTitle, '', -11, 11) .
'_contact_id';
if ($componentTitle == 'activity_civireport') {
$id_header = 'civicrm_' . substr_replace($componentTitle, '', -11, 11) . '_id';
}
unset($this->_columnHeadersComponent[$componentTitle][$id_header]);
unset($this->_columnHeadersComponent[$componentTitle][$contact_header]);
}
$this->assign_by_ref('columnHeadersComponent', $this->_columnHeadersComponent);
$this->assign_by_ref('componentRows', $componentRows);
}
$this->doTemplateAssignment($rows);
$this->endPostProcess();
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// make count columns point to detail report
// change contact name with link
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts('View Contact Record');
$entryFound = TRUE;
}
// Handle ID to label conversion for contact fields
$entryFound = $this->alterDisplayContactFields($row, $rows, $rowNum, NULL, NULL) ? TRUE : $entryFound;
// display birthday in the configured custom format
if (array_key_exists('civicrm_contact_birth_date', $row)) {
$birthDate = $row['civicrm_contact_birth_date'];
if ($birthDate) {
$rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
}
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
/**
* @param $componentRows
*/
public function alterComponentDisplay(&$componentRows) {
// custom code to alter rows
$activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE);
$activityStatus = CRM_Core_PseudoConstant::activityStatus();
$entryFound = FALSE;
foreach ($componentRows as $contactID => $components) {
foreach ($components as $component => $rows) {
foreach ($rows as $rowNum => $row) {
// handle contribution
if ($component == 'contribution_civireport') {
if ($val = CRM_Utils_Array::value('civicrm_contribution_financial_type_id', $row)) {
$componentRows[$contactID][$component][$rowNum]['civicrm_contribution_financial_type_id'] = CRM_Contribute_PseudoConstant::financialType($val, FALSE);
}
if ($val = CRM_Utils_Array::value('civicrm_contribution_contribution_status_id', $row)) {
$componentRows[$contactID][$component][$rowNum]['civicrm_contribution_contribution_status_id'] = CRM_Contribute_PseudoConstant::contributionStatus($val);
}
$entryFound = TRUE;
}
if ($component == 'membership_civireport') {
if ($val = CRM_Utils_Array::value('civicrm_membership_membership_type_id', $row)) {
$componentRows[$contactID][$component][$rowNum]['civicrm_membership_membership_type_id'] = CRM_Member_PseudoConstant::membershipType($val, FALSE);
}
if ($val = CRM_Utils_Array::value('civicrm_membership_status_id', $row)) {
$componentRows[$contactID][$component][$rowNum]['civicrm_membership_status_id'] = CRM_Member_PseudoConstant::membershipStatus($val, FALSE);
}
$entryFound = TRUE;
}
if ($component == 'participant_civireport') {
if ($val = CRM_Utils_Array::value('civicrm_participant_event_id', $row)) {
$componentRows[$contactID][$component][$rowNum]['civicrm_participant_event_id'] = CRM_Event_PseudoConstant::event($val, FALSE);
$url = CRM_Report_Utils_Report::getNextUrl('event/income',
'reset=1&force=1&id_op=in&id_value=' . $val,
$this->_absoluteUrl, $this->_id
);
$componentRows[$contactID][$component][$rowNum]['civicrm_participant_event_id_link'] = $url;
$componentRows[$contactID][$component][$rowNum]['civicrm_participant_event_id_hover'] = ts('View Event Income details for this Event.');
$entryFound = TRUE;
}
if ($val = CRM_Utils_Array::value('civicrm_participant_participant_status_id', $row)) {
$componentRows[$contactID][$component][$rowNum]['civicrm_participant_participant_status_id'] = CRM_Event_PseudoConstant::participantStatus($val, FALSE);
}
if ($val = CRM_Utils_Array::value('civicrm_participant_role_id', $row)) {
$roles = explode(CRM_Core_DAO::VALUE_SEPARATOR, $val);
$value = array();
foreach ($roles as $role) {
$value[$role] = CRM_Event_PseudoConstant::participantRole($role, FALSE);
}
$componentRows[$contactID][$component][$rowNum]['civicrm_participant_role_id'] = implode(', ', $value);
}
$entryFound = TRUE;
}
if ($component == 'activity_civireport') {
if ($val = CRM_Utils_Array::value('civicrm_activity_activity_type_id', $row)) {
$componentRows[$contactID][$component][$rowNum]['civicrm_activity_activity_type_id'] = $activityTypes[$val];
}
if ($val = CRM_Utils_Array::value('civicrm_activity_activity_status_id', $row)) {
$componentRows[$contactID][$component][$rowNum]['civicrm_activity_activity_status_id'] = $activityStatus[$val];
}
$entryFound = TRUE;
}
if ($component == 'membership_civireport') {
if ($val = CRM_Utils_Array::value('civicrm_membership_membership_status_id', $row)) {
$componentRows[$contactID][$component][$rowNum]['civicrm_membership_membership_status_id'] = CRM_Member_PseudoConstant::membershipStatus($val);
}
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}
}
}

View file

@ -0,0 +1,304 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Contact_Log extends CRM_Report_Form {
protected $_summary = NULL;
/**
* Class constructor.
*/
public function __construct() {
$this->activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, TRUE);
asort($this->activityTypes);
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Modified By'),
'required' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Modified By'),
'type' => CRM_Utils_Type::T_STRING,
),
),
'grouping' => 'contact-fields',
),
'civicrm_contact_touched' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name_touched' => array(
'title' => ts('Touched Contact'),
'name' => 'sort_name',
'required' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'filters' => array(
'sort_name_touched' => array(
'title' => ts('Touched Contact'),
'name' => 'sort_name',
'type' => CRM_Utils_Type::T_STRING,
),
),
'grouping' => 'contact-fields',
),
'civicrm_activity' => array(
'dao' => 'CRM_Activity_DAO_Activity',
'fields' => array(
'id' => array(
'title' => ts('Activity ID'),
'no_display' => TRUE,
'required' => TRUE,
),
'subject' => array(
'title' => ts('Touched Activity'),
'required' => TRUE,
),
'activity_type_id' => array(
'title' => ts('Activity Type'),
'required' => TRUE,
),
),
),
'civicrm_activity_source' => array(
'dao' => 'CRM_Activity_DAO_ActivityContact',
'fields' => array(
'contact_id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
),
'civicrm_log' => array(
'dao' => 'CRM_Core_DAO_Log',
'fields' => array(
'modified_date' => array(
'title' => ts('Modified Date'),
'required' => TRUE,
),
'data' => array(
'title' => ts('Description'),
),
),
'filters' => array(
'modified_date' => array(
'title' => ts('Modified Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
'default' => 'this.week',
),
),
),
);
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = $grouping = array();
return $errors;
}
public function from() {
$activityContacts = CRM_Activity_BAO_ActivityContact::buildOptions('record_type_id', 'validate');
$sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
$this->_from = "
FROM civicrm_log {$this->_aliases['civicrm_log']}
inner join civicrm_contact {$this->_aliases['civicrm_contact']} on {$this->_aliases['civicrm_log']}.modified_id = {$this->_aliases['civicrm_contact']}.id
left join civicrm_contact {$this->_aliases['civicrm_contact_touched']} on ({$this->_aliases['civicrm_log']}.entity_table='civicrm_contact' AND {$this->_aliases['civicrm_log']}.entity_id = {$this->_aliases['civicrm_contact_touched']}.id)
left join civicrm_activity {$this->_aliases['civicrm_activity']} on ({$this->_aliases['civicrm_log']}.entity_table='civicrm_activity' AND {$this->_aliases['civicrm_log']}.entity_id = {$this->_aliases['civicrm_activity']}.id)
LEFT JOIN civicrm_activity_contact {$this->_aliases['civicrm_activity_source']} ON
{$this->_aliases['civicrm_activity']}.id = {$this->_aliases['civicrm_activity_source']}.activity_id AND
{$this->_aliases['civicrm_activity_source']}.record_type_id = {$sourceID}
";
}
public function where() {
$clauses = array();
$this->_having = '';
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('operatorType', $field) & CRM_Report_Form::OP_DATE
) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['dbAlias'], $relative, $from, $to);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
$clauses[] = "({$this->_aliases['civicrm_log']}.entity_table <> 'civicrm_domain')";
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
public function orderBy() {
$this->_orderBy = "
ORDER BY {$this->_aliases['civicrm_log']}.modified_date DESC, {$this->_aliases['civicrm_contact']}.sort_name, {$this->_aliases['civicrm_contact_touched']}.sort_name
";
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact details for this contact.");
$entryFound = TRUE;
}
if (array_key_exists('civicrm_contact_touched_sort_name_touched', $row) &&
array_key_exists('civicrm_contact_touched_id', $row) &&
$row['civicrm_contact_touched_sort_name_touched'] !== ''
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_touched_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_touched_sort_name_touched_link'] = $url;
$rows[$rowNum]['civicrm_contact_touched_sort_name_touched_hover'] = ts("View Contact details for this contact.");
$entryFound = TRUE;
}
if (array_key_exists('civicrm_activity_subject', $row) &&
array_key_exists('civicrm_activity_id', $row) &&
$row['civicrm_activity_subject'] !== ''
) {
$url = CRM_Utils_System::url('civicrm/contact/view/activity',
'reset=1&action=view&id=' . $row['civicrm_activity_id'] . '&cid=' .
$row['civicrm_activity_source_contact_id'] . '&atype=' .
$row['civicrm_activity_activity_type_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_activity_subject_link'] = $url;
$rows[$rowNum]['civicrm_activity_subject_hover'] = ts("View Contact details for this contact.");
$entryFound = TRUE;
}
if (array_key_exists('civicrm_activity_activity_type_id', $row)) {
if ($value = $row['civicrm_activity_activity_type_id']) {
$rows[$rowNum]['civicrm_activity_activity_type_id'] = $this->activityTypes[$value];
}
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,66 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Contact_LoggingDetail extends CRM_Logging_ReportDetail {
/**
*/
public function __construct() {
$this->log_conn_id = CRM_Utils_Request::retrieve('log_conn_id', 'String');
$this->log_date = CRM_Utils_Request::retrieve('log_date', 'String');
$this->setTablesToContactRelatedTables();
$this->calculateContactDiffs();
$this->detail = 'logging/contact/detail';
$this->summary = 'logging/contact/summary';
parent::__construct();
}
public function buildQuickForm() {
$layout = CRM_Utils_Request::retrieve('layout', 'String', $this);
$this->assign('layout', $layout);
parent::buildQuickForm();
if ($this->cid) {
// link back to contact summary
$this->assign('backURL', CRM_Utils_System::url('civicrm/contact/view', "reset=1&selectedChild=log&cid={$this->cid}", FALSE, NULL, FALSE));
$this->assign('revertURL', self::$_template->get_template_vars('revertURL') . "&cid={$this->cid}");
}
else {
// link back to summary report
$this->assign('backURL', CRM_Report_Utils_Report::getNextUrl('logging/contact/summary', 'reset=1', FALSE, TRUE));
}
}
}

View file

@ -0,0 +1,336 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Contact_LoggingSummary extends CRM_Logging_ReportSummary {
/**
* Class constructor.
*/
public function __construct() {
parent::__construct();
$logTypes = array();
foreach (array_keys($this->_logTables) as $table) {
$type = $this->getLogType($table);
$logTypes[$type] = $type;
}
asort($logTypes);
$this->_columns = array(
'log_civicrm_entity' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'alias' => 'entity_log',
'fields' => array(
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'log_grouping' => array(
'required' => TRUE,
'title' => ts('Extra information to control grouping'),
'no_display' => TRUE,
),
'log_action' => array(
'default' => TRUE,
'title' => ts('Action'),
),
'log_type' => array(
'required' => TRUE,
'title' => ts('Log Type'),
),
'log_user_id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'log_date' => array(
'default' => TRUE,
'required' => TRUE,
'type' => CRM_Utils_Type::T_TIME,
'title' => ts('When'),
),
'altered_contact' => array(
'default' => TRUE,
'name' => 'display_name',
'title' => ts('Altered Contact'),
'alias' => 'modified_contact_civireport',
),
'altered_contact_id' => array(
'name' => 'id',
'no_display' => TRUE,
'required' => TRUE,
'alias' => 'modified_contact_civireport',
),
'log_conn_id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'is_deleted' => array(
'no_display' => TRUE,
'required' => TRUE,
'alias' => 'modified_contact_civireport',
),
),
'filters' => array(
'log_date' => array(
'title' => ts('When'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'altered_contact' => array(
'name' => 'display_name',
'title' => ts('Altered Contact'),
'type' => CRM_Utils_Type::T_STRING,
'alias' => 'modified_contact_civireport',
),
'altered_contact_id' => array(
'name' => 'id',
'type' => CRM_Utils_Type::T_INT,
'alias' => 'modified_contact_civireport',
'no_display' => TRUE,
),
'log_type' => array(
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $logTypes,
'title' => ts('Log Type'),
'type' => CRM_Utils_Type::T_STRING,
),
'log_type_table' => array(
'name' => 'log_type',
'title' => ts('Log Type Table'),
'type' => CRM_Utils_Type::T_STRING,
),
'log_action' => array(
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => array(
'Insert' => ts('Insert'),
'Update' => ts('Update'),
'Delete' => ts('Delete'),
),
'title' => ts('Action'),
'type' => CRM_Utils_Type::T_STRING,
),
'id' => array(
'no_display' => TRUE,
'type' => CRM_Utils_Type::T_INT,
),
),
),
'altered_by_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'alias' => 'altered_by_contact',
'fields' => array(
'display_name' => array(
'default' => TRUE,
'name' => 'display_name',
'title' => ts('Altered By'),
),
),
'filters' => array(
'display_name' => array(
'name' => 'display_name',
'title' => ts('Altered By'),
'type' => CRM_Utils_Type::T_STRING,
),
),
),
);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
// cache for id → is_deleted mapping
$isDeleted = array();
$newRows = array();
foreach ($rows as $key => &$row) {
$isMerge = 0;
$baseQueryCriteria = "reset=1&log_conn_id={$row['log_civicrm_entity_log_conn_id']}";
if (!CRM_Logging_Differ::checkLogCanBeUsedWithNoLogDate($row['log_civicrm_entity_log_date'])) {
$baseQueryCriteria .= '&log_date=' . CRM_Utils_Date::isoToMysql($row['log_civicrm_entity_log_date']);
}
if ($this->cid) {
$baseQueryCriteria .= '&cid=' . $this->cid;
}
if (!isset($isDeleted[$row['log_civicrm_entity_altered_contact_id']])) {
$isDeleted[$row['log_civicrm_entity_altered_contact_id']] = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact',
$row['log_civicrm_entity_altered_contact_id'], 'is_deleted') !== '0';
}
if (!empty($row['log_civicrm_entity_altered_contact']) &&
!$isDeleted[$row['log_civicrm_entity_altered_contact_id']]
) {
$row['log_civicrm_entity_altered_contact_link'] = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['log_civicrm_entity_altered_contact_id']);
$row['log_civicrm_entity_altered_contact_hover'] = ts("Go to contact summary");
$entity = $this->getEntityValue($row['log_civicrm_entity_id'], $row['log_civicrm_entity_log_type'], $row['log_civicrm_entity_log_date']);
if ($entity) {
$row['log_civicrm_entity_altered_contact'] = $row['log_civicrm_entity_altered_contact'] . " [{$entity}]";
}
if ($entity == 'Contact Merged') {
// We're looking at a merge activity created against the surviving
// contact record. There should be a single activity created against
// the deleted contact record, with this activity as parent.
$deletedID = CRM_Core_DAO::singleValueQuery('
SELECT GROUP_CONCAT(contact_id) FROM civicrm_activity_contact ac
INNER JOIN civicrm_activity a
ON a.id = ac.activity_id AND a.parent_id = ' . $row['log_civicrm_entity_id'] . ' AND ac.record_type_id =
' . CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_ActivityContact', 'record_type_id', 'Activity Targets')
);
if ($deletedID && !stristr($deletedID, ',')) {
$baseQueryCriteria .= '&oid=' . $deletedID;
}
$row['log_civicrm_entity_log_action'] = ts('Contact Merge');
$row = $this->addDetailReportLinksToRow($baseQueryCriteria, $row);
$isMerge = 1;
}
}
$row['altered_by_contact_display_name_link'] = CRM_Utils_System::url('civicrm/contact/view', 'reset=1&cid=' . $row['log_civicrm_entity_log_user_id']);
$row['altered_by_contact_display_name_hover'] = ts("Go to contact summary");
if ($row['log_civicrm_entity_is_deleted'] and 'Update' == CRM_Utils_Array::value('log_civicrm_entity_log_action', $row)) {
$row['log_civicrm_entity_log_action'] = ts('Delete (to trash)');
}
if ('Contact' == CRM_Utils_Array::value('log_type', $this->_logTables[$row['log_civicrm_entity_log_type']]) &&
CRM_Utils_Array::value('log_civicrm_entity_log_action', $row) == ts('Insert')
) {
$row['log_civicrm_entity_log_action'] = ts('Update');
}
// For certain tables, we may want to look at an alternate column to
// determine which action to display, determined by the 'action_column'
// key of the entry in $this->_logTables.
if ($newAction = $this->getEntityAction($row['log_civicrm_entity_id'],
$row['log_civicrm_entity_log_conn_id'],
$row['log_civicrm_entity_log_type'],
CRM_Utils_Array::value('log_civicrm_entity_log_action', $row))
) {
$row['log_civicrm_entity_log_action'] = $newAction;
}
$row['log_civicrm_entity_log_type'] = $this->getLogType($row['log_civicrm_entity_log_type']);
$date = CRM_Utils_Date::isoToMysql($row['log_civicrm_entity_log_date']);
if ('Update' == CRM_Utils_Array::value('log_civicrm_entity_log_action', $row)) {
$row = $this->addDetailReportLinksToRow($baseQueryCriteria, $row);
}
// In the summary, we only want to show one row per entity type,
// connection ID, contact ID, and user ID, rolling up multiple
// related actions against the same entity.
$key = $date . '_' .
$row['log_civicrm_entity_log_type'] . '_' .
// This ensures merge activities are not 'lost' by aggregation.
// I would prefer not to lose other entities either but it's a balancing act as
// described in https://issues.civicrm.org/jira/browse/CRM-12867 so adding this criteria
// while hackish saves us from figuring out if the original decision is still good.
$isMerge . '_' .
$row['log_civicrm_entity_log_conn_id'] . '_' .
$row['log_civicrm_entity_log_user_id'] . '_' .
$row['log_civicrm_entity_altered_contact_id'];
$newRows[$key] = $row;
unset($row['log_civicrm_entity_log_user_id']);
unset($row['log_civicrm_entity_log_conn_id']);
}
krsort($newRows);
$rows = $newRows;
}
/**
* Generate From Clause.
*/
public function from() {
$entity = $this->currentLogTable;
$detail = $this->_logTables[$entity];
$tableName = CRM_Utils_Array::value('table_name', $detail, $entity);
$clause = CRM_Utils_Array::value('entity_table', $detail);
$clause = $clause ? "AND entity_log_civireport.entity_table = 'civicrm_contact'" : NULL;
$joinClause = "
INNER JOIN civicrm_contact modified_contact_civireport
ON (entity_log_civireport.{$detail['fk']} = modified_contact_civireport.id {$clause})";
if (!empty($detail['joins'])) {
$clause = CRM_Utils_Array::value('entity_table', $detail);
$clause = $clause ? "AND fk_table.entity_table = 'civicrm_contact'" : NULL;
$joinClause = "
INNER JOIN `{$this->loggingDB}`.{$detail['joins']['table']} fk_table ON {$detail['joins']['join']}
INNER JOIN civicrm_contact modified_contact_civireport
ON (fk_table.{$detail['fk']} = modified_contact_civireport.id {$clause})";
}
if (!empty($detail['extra_joins'])) {
$joinClause .= "
INNER JOIN `{$this->loggingDB}`.{$detail['extra_joins']['table']} extra_table ON {$detail['extra_joins']['join']}";
}
$this->_from = "
FROM `{$this->loggingDB}`.$tableName entity_log_civireport
{$joinClause}
LEFT JOIN civicrm_contact altered_by_contact_civireport
ON (entity_log_civireport.log_user_id = altered_by_contact_civireport.id)";
}
/**
* Add links & hovers to the detailed report.
*
* @param $baseQueryCriteria
* @param $row
*
* @return mixed
*/
protected function addDetailReportLinksToRow($baseQueryCriteria, $row) {
$q = $baseQueryCriteria;
$q .= (!empty($row['log_civicrm_entity_altered_contact'])) ? '&alteredName=' . $row['log_civicrm_entity_altered_contact'] : '';
$q .= (!empty($row['altered_by_contact_display_name'])) ? '&alteredBy=' . $row['altered_by_contact_display_name'] : '';
$q .= (!empty($row['log_civicrm_entity_log_user_id'])) ? '&alteredById=' . $row['log_civicrm_entity_log_user_id'] : '';
$url1 = CRM_Report_Utils_Report::getNextUrl('logging/contact/detail', "{$q}&snippet=4&section=2&layout=overlay", FALSE, TRUE);
$url2 = CRM_Report_Utils_Report::getNextUrl('logging/contact/detail', "{$q}&section=2", FALSE, TRUE);
$hoverTitle = ts('View details for this update');
$row['log_civicrm_entity_log_action'] = "<a href='{$url1}' class='crm-summary-link'><i class=\"crm-i fa-list-alt\"></i></a>&nbsp;<a title='{$hoverTitle}' href='{$url2}'>" . $row['log_civicrm_entity_log_action'] . '</a>';
return $row;
}
}

View file

@ -0,0 +1,856 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Contact_Relationship extends CRM_Report_Form {
protected $_summary = NULL;
protected $_emailField_a = FALSE;
protected $_emailField_b = FALSE;
protected $_phoneField_a = FALSE;
protected $_phoneField_b = FALSE;
protected $_customGroupExtends = array(
'Relationship',
);
public $_drilldownReport = array('contact/detail' => 'Link to Detail Report');
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* This will be a_b or b_a.
*
* @var string
*/
protected $relationType;
/**
* Class constructor.
*/
public function __construct() {
$contact_type = CRM_Contact_BAO_ContactType::getSelectElements(FALSE, TRUE, '_');
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name_a' => array(
'title' => ts('Contact A'),
'name' => 'sort_name',
'required' => TRUE,
),
'display_name_a' => array(
'title' => ts('Contact A Full Name'),
'name' => 'display_name',
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'contact_type_a' => array(
'title' => ts('Contact Type (Contact A)'),
'name' => 'contact_type',
),
'contact_sub_type_a' => array(
'title' => ts('Contact Subtype (Contact A)'),
'name' => 'contact_sub_type',
),
),
'filters' => array(
'sort_name_a' => array(
'title' => ts('Contact A'),
'name' => 'sort_name',
'operator' => 'like',
'type' => CRM_Report_Form::OP_STRING,
),
'contact_type_a' => array(
'title' => ts('Contact Type A'),
'name' => 'contact_type',
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $contact_type,
'type' => CRM_Utils_Type::T_STRING,
),
),
'order_bys' => array(
'sort_name_a' => array(
'title' => ts('Contact A'),
'name' => 'sort_name',
'default_weight' => '1',
),
),
'grouping' => 'contact_a_fields',
),
'civicrm_contact_b' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'alias' => 'contact_b',
'fields' => array(
'sort_name_b' => array(
'title' => ts('Contact B'),
'name' => 'sort_name',
'required' => TRUE,
),
'display_name_b' => array(
'title' => ts('Contact B Full Name'),
'name' => 'display_name',
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'contact_type_b' => array(
'title' => ts('Contact Type (Contact B)'),
'name' => 'contact_type',
),
'contact_sub_type_b' => array(
'title' => ts('Contact Subtype (Contact B)'),
'name' => 'contact_sub_type',
),
),
'filters' => array(
'sort_name_b' => array(
'title' => ts('Contact B'),
'name' => 'sort_name',
'operator' => 'like',
'type' => CRM_Report_Form::OP_STRING,
),
'contact_type_b' => array(
'title' => ts('Contact Type B'),
'name' => 'contact_type',
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $contact_type,
'type' => CRM_Utils_Type::T_STRING,
),
),
'order_bys' => array(
'sort_name_b' => array(
'title' => ts('Contact B'),
'name' => 'sort_name',
'default_weight' => '2',
),
),
'grouping' => 'contact_b_fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email_a' => array(
'title' => ts('Email (Contact A)'),
'name' => 'email',
),
),
'grouping' => 'contact_a_fields',
),
'civicrm_email_b' => array(
'dao' => 'CRM_Core_DAO_Email',
'alias' => 'email_b',
'fields' => array(
'email_b' => array(
'title' => ts('Email (Contact B)'),
'name' => 'email',
),
),
'grouping' => 'contact_b_fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'alias' => 'phone_a',
'fields' => array(
'phone_a' => array(
'title' => ts('Phone (Contact A)'),
'name' => 'phone',
),
'phone_ext_a' => array(
'title' => ts('Phone Ext (Contact A)'),
'name' => 'phone_ext',
),
),
'grouping' => 'contact_a_fields',
),
'civicrm_phone_b' => array(
'dao' => 'CRM_Core_DAO_Phone',
'alias' => 'phone_b',
'fields' => array(
'phone_b' => array(
'title' => ts('Phone (Contact B)'),
'name' => 'phone',
),
'phone_ext_b' => array(
'title' => ts('Phone Ext (Contact B)'),
'name' => 'phone_ext',
),
),
'grouping' => 'contact_b_fields',
),
'civicrm_relationship_type' => array(
'dao' => 'CRM_Contact_DAO_RelationshipType',
'fields' => array(
'label_a_b' => array(
'title' => ts('Relationship A-B '),
'default' => TRUE,
),
'label_b_a' => array(
'title' => ts('Relationship B-A '),
'default' => TRUE,
),
),
'order_bys' => array(
'label_a_b' => array(
'title' => ts('Relationship A-B'),
'name' => 'label_a_b',
),
'label_b_A' => array(
'title' => ts('Relationship B-A'),
'name' => 'label_b_a',
),
),
'grouping' => 'relation-fields',
),
'civicrm_relationship' => array(
'dao' => 'CRM_Contact_DAO_Relationship',
'fields' => array(
'start_date' => array(
'title' => ts('Relationship Start Date'),
),
'end_date' => array(
'title' => ts('Relationship End Date'),
),
'is_permission_a_b' => array(
'title' => ts('Is permission A over B?'),
),
'is_permission_b_a' => array(
'title' => ts('Is permission B over A?'),
),
'description' => array(
'title' => ts('Description'),
),
'relationship_id' => array(
'title' => ts('Rel ID'),
'name' => 'id',
),
),
'filters' => array(
'is_active' => array(
'title' => ts('Relationship Status'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
'' => ts('- Any -'),
1 => ts('Active'),
0 => ts('Inactive'),
),
'type' => CRM_Utils_Type::T_INT,
),
'is_valid' => array(
'title' => ts('Relationship Dates Validity'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
NULL => ts('- Any -'),
1 => ts('Not expired'),
0 => ts('Expired'),
),
'type' => CRM_Utils_Type::T_INT,
),
'relationship_type_id' => array(
'title' => ts('Relationship'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contact_BAO_Relationship::getContactRelationshipType(NULL, NULL, NULL, NULL, TRUE),
'type' => CRM_Utils_Type::T_INT,
),
'start_date' => array(
'title' => ts('Start Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'end_date' => array(
'title' => ts('End Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'is_permission_a_b' => array(
'title' => ts('Does contact A have permission over contact B?'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
'' => ts('- Any -'),
1 => ts('Yes'),
0 => ts('No'),
),
'type' => CRM_Utils_Type::T_INT,
),
'is_permission_b_a' => array(
'title' => ts('Does contact B have permission over contact A?'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
'' => ts('- Any -'),
1 => ts('Yes'),
0 => ts('No'),
),
'type' => CRM_Utils_Type::T_INT,
),
),
'order_bys' => array(
'start_date' => array(
'title' => ts('Start Date'),
'name' => 'start_date',
),
'active_period_date' => array(
'title' => ts('Active Period'),
'type' => CRM_Utils_Type::T_DATE,
),
),
'grouping' => 'relation-fields',
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'filters' => array(
'country_id' => array(
'title' => ts('Country'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::country(),
),
'state_province_id' => array(
'title' => ts('State/Province'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::stateProvince(),
),
),
'grouping' => 'contact-fields',
),
);
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = $this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($fieldName == 'email_a') {
$this->_emailField_a = TRUE;
}
if ($fieldName == 'email_b') {
$this->_emailField_b = TRUE;
}
if ($fieldName == 'phone_a') {
$this->_phoneField_a = TRUE;
}
if ($fieldName == 'phone_b') {
$this->_phoneField_b = TRUE;
}
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$this->_from = "
FROM civicrm_relationship {$this->_aliases['civicrm_relationship']}
INNER JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON ( {$this->_aliases['civicrm_relationship']}.contact_id_a =
{$this->_aliases['civicrm_contact']}.id )
INNER JOIN civicrm_contact {$this->_aliases['civicrm_contact_b']}
ON ( {$this->_aliases['civicrm_relationship']}.contact_id_b =
{$this->_aliases['civicrm_contact_b']}.id )
{$this->_aclFrom} ";
if (!empty($this->_params['country_id_value']) ||
!empty($this->_params['state_province_id_value'])
) {
$this->_from .= "
INNER JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON (( {$this->_aliases['civicrm_address']}.contact_id =
{$this->_aliases['civicrm_contact']}.id OR
{$this->_aliases['civicrm_address']}.contact_id =
{$this->_aliases['civicrm_contact_b']}.id ) AND
{$this->_aliases['civicrm_address']}.is_primary = 1 ) ";
}
$this->_from .= "
INNER JOIN civicrm_relationship_type {$this->_aliases['civicrm_relationship_type']}
ON ( {$this->_aliases['civicrm_relationship']}.relationship_type_id =
{$this->_aliases['civicrm_relationship_type']}.id ) ";
// Include Email Field.
if ($this->_emailField_a) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ( {$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1 )";
}
if ($this->_emailField_b) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email_b']}
ON ( {$this->_aliases['civicrm_contact_b']}.id =
{$this->_aliases['civicrm_email_b']}.contact_id AND
{$this->_aliases['civicrm_email_b']}.is_primary = 1 )";
}
// Include Phone Field.
if ($this->_phoneField_a) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON ( {$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1 )";
}
if ($this->_phoneField_b) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone_b']}
ON ( {$this->_aliases['civicrm_contact_b']}.id =
{$this->_aliases['civicrm_phone_b']}.contact_id AND
{$this->_aliases['civicrm_phone_b']}.is_primary = 1 )";
}
}
public function where() {
$whereClauses = $havingClauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($fieldName == 'active_period_date') {
$clause = $this->activeClause($field['name'], $relative, $from, $to, $field['type']);
}
else {
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
if (($tableName == 'civicrm_contact' ||
$tableName == 'civicrm_contact_b') &&
($fieldName == 'contact_type_a' ||
$fieldName == 'contact_type_b')
) {
$cTypes = CRM_Utils_Array::value("{$fieldName}_value", $this->_params);
$contactTypes = $contactSubTypes = array();
if (!empty($cTypes)) {
foreach ($cTypes as $ctype) {
$getTypes = CRM_Utils_System::explode('_', $ctype, 2);
if ($getTypes[1] &&
!in_array($getTypes[1], $contactSubTypes)
) {
$contactSubTypes[] = $getTypes[1];
}
elseif ($getTypes[0] &&
!in_array($getTypes[0], $contactTypes)
) {
$contactTypes[] = $getTypes[0];
}
}
}
if (!empty($contactTypes)) {
$clause = $this->whereClause($field,
$op,
$contactTypes,
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
if (!empty($contactSubTypes)) {
$field['name'] = 'contact_sub_type';
$field['dbAlias'] = $field['alias'] . '.' . $field['name'];
$subTypeClause = $this->whereClause($field,
$op,
$contactSubTypes,
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
if ($clause) {
$clause = '(' . $clause . ' OR ' . $subTypeClause . ')';
}
else {
$clause = $subTypeClause;
}
}
}
else {
if ($fieldName == 'is_valid') {
$clause = $this->buildValidityQuery(CRM_Utils_Array::value("{$fieldName}_value", $this->_params));
}
else {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
}
}
if (!empty($clause)) {
if (!empty($field['having'])) {
$havingClauses[] = $clause;
}
else {
$whereClauses[] = $clause;
}
}
}
}
}
$this->_where = "WHERE ( {$this->_aliases['civicrm_contact']}.is_deleted = 0 AND {$this->_aliases['civicrm_contact_b']}.is_deleted = 0 ) ";
if ($whereClauses) {
$this->_where .= ' AND ' . implode(' AND ', $whereClauses);
}
else {
$this->_having = '';
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
if (!empty($havingClauses)) {
// use this clause to construct group by clause.
$this->_having = 'HAVING ' . implode(' AND ', $havingClauses);
}
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
$isStatusFilter = FALSE;
$relStatus = NULL;
if (CRM_Utils_Array::value('is_active_value', $this->_params) == '1') {
$relStatus = 'Is equal to Active';
}
elseif (CRM_Utils_Array::value('is_active_value', $this->_params) == '0') {
$relStatus = 'Is equal to Inactive';
}
if (!empty($statistics['filters'])) {
foreach ($statistics['filters'] as $id => $value) {
// For displaying relationship type filter.
if ($value['title'] == 'Relationship') {
$relTypes = CRM_Core_PseudoConstant::relationshipType();
$op = CRM_Utils_Array::value('relationship_type_id_op', $this->_params) == 'in' ? ts('Is one of') . ' ' : ts('Is not one of') . ' ';
$relationshipTypes = array();
foreach ($this->_params['relationship_type_id_value'] as $relationship) {
$relationshipTypes[] = $relTypes[$relationship]['label_' . $this->relationType];
}
$statistics['filters'][$id]['value'] = $op .
implode(', ', $relationshipTypes);
}
// For displaying relationship status.
if ($value['title'] == 'Relationship Status') {
$isStatusFilter = TRUE;
$statistics['filters'][$id]['value'] = $relStatus;
}
}
}
// For displaying relationship status.
if (!$isStatusFilter && $relStatus) {
$statistics['filters'][] = array(
'title' => ts('Relationship Status'),
'value' => $relStatus,
);
}
return $statistics;
}
public function groupBy() {
$this->_groupBy = " ";
$groupBy = array();
if ($this->relationType == 'a_b') {
$groupBy[] = " {$this->_aliases['civicrm_contact']}.id";
}
elseif ($this->relationType == 'b_a') {
$groupBy[] = " {$this->_aliases['civicrm_contact_b']}.id";
}
if (!empty($groupBy)) {
$groupBy[] = "{$this->_aliases['civicrm_relationship']}.id";
}
else {
$groupBy = array("{$this->_aliases['civicrm_relationship']}.id");
}
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
public function postProcess() {
$this->beginPostProcess();
$originalRelationshipTypeIdValue = CRM_Utils_Array::value('relationship_type_id_value', $this->_params);
if ($originalRelationshipTypeIdValue) {
$relationshipTypes = array();
$direction = array();
foreach ((array) $originalRelationshipTypeIdValue as $relationship_type) {
$relType = explode('_', $relationship_type);
$direction[] = $relType[1] . '_' . $relType[2];
$relationshipTypes[] = intval($relType[0]);
}
// Lets take the first relationship type to guide us in the relationship
// direction we should use.
$this->relationType = $direction[0];
$this->_params['relationship_type_id_value'] = $relationshipTypes;
}
$this->buildACLClause(array(
$this->_aliases['civicrm_contact'],
$this->_aliases['civicrm_contact_b'],
));
$sql = $this->buildQuery();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
if (!empty($originalRelationshipTypeIdValue)) {
// Store its old value, CRM-5837.
$this->_params['relationship_type_id_value'] = $originalRelationshipTypeIdValue;
}
$this->endPostProcess($rows);
}
/**
* @param $rows
*/
public function alterDisplay(&$rows) {
// Custom code to alter rows.
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// Handle ID to label conversion for contact fields
$entryFound = $this->alterDisplayContactFields($row, $rows, $rowNum, 'contact/relationship', 'View Relationships') ? TRUE : $entryFound;
// Handle contact subtype A
// @todo refactor into separate function
if (array_key_exists('civicrm_contact_contact_sub_type_a', $row)) {
if ($value = $row['civicrm_contact_contact_sub_type_a']) {
$rowValues = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
$rowLabels = array();
foreach ($rowValues as $rowValue) {
if ($rowValue) {
$rowLabels[] = CRM_Core_Pseudoconstant::getLabel('CRM_Contact_BAO_Contact', 'contact_sub_type', $rowValue);
}
}
$rows[$rowNum]['civicrm_contact_contact_sub_type_a'] = implode(', ', $rowLabels);
}
$entryFound = TRUE;
}
// Handle contact subtype B
// @todo refactor into separate function
if (array_key_exists('civicrm_contact_b_contact_sub_type_b', $row)) {
if ($value = $row['civicrm_contact_b_contact_sub_type_b']) {
$rowValues = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
$rowLabels = array();
foreach ($rowValues as $rowValue) {
if ($rowValue) {
$rowLabels[] = CRM_Core_Pseudoconstant::getLabel('CRM_Contact_BAO_Contact', 'contact_sub_type', $rowValue);
}
}
$rows[$rowNum]['civicrm_contact_b_contact_sub_type_b'] = implode(', ', $rowLabels);
}
$entryFound = TRUE;
}
// Handle country
// @todo use alterDisplayAddressFields function
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
// Handle state/province
// @todo use alterDisplayAddressFields function
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
}
$entryFound = TRUE;
}
// Handle contact name A
// @todo refactor into separate function
if (array_key_exists('civicrm_contact_sort_name_a', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contact/detail',
'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_sort_name_a']
= $rows[$rowNum]['civicrm_contact_sort_name_a'] . ' (' .
$rows[$rowNum]['civicrm_contact_id'] . ')';
$rows[$rowNum]['civicrm_contact_sort_name_a_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_a_hover'] = ts('View Contact Detail Report for this contact');
$entryFound = TRUE;
}
// Handle contact name B
// @todo refactor into separate function
if (array_key_exists('civicrm_contact_b_sort_name_b', $row) &&
array_key_exists('civicrm_contact_b_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contact/detail',
'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_b_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_b_sort_name_b']
= $rows[$rowNum]['civicrm_contact_b_sort_name_b'] . ' (' .
$rows[$rowNum]['civicrm_contact_b_id'] . ')';
$rows[$rowNum]['civicrm_contact_b_sort_name_b_link'] = $url;
$rows[$rowNum]['civicrm_contact_b_sort_name_b_hover'] = ts('View Contact Detail Report for this contact');
$entryFound = TRUE;
}
// Handle relationship
if (array_key_exists('civicrm_relationship_relationship_id', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = "/civicrm/contact/view/rel?reset=1&action=update&rtype=a_b&cid=" .
$row['civicrm_contact_id'] . "&id=" .
$row['civicrm_relationship_relationship_id'];
$rows[$rowNum]['civicrm_relationship_relationship_id_link'] = $url;
$rows[$rowNum]['civicrm_relationship_relationship_id_hover'] = ts("Edit this relationship.");
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
/**
* @param $valid bool - set to 1 if we are looking for a valid relationship, 0 if not
*
* @return array
*/
public function buildValidityQuery($valid) {
$clause = NULL;
if ($valid == '1') {
// Relationships dates are not expired.
$clause = "((start_date <= CURDATE() OR start_date is null) AND (end_date >= CURDATE() OR end_date is null))";
}
elseif ($valid == '0') {
// Relationships dates are expired or has not started yet.
$clause = "(start_date >= CURDATE() OR end_date < CURDATE())";
}
return $clause;
}
/**
* Get SQL where clause for a active period field.
*
* @param string $fieldName
* @param string $relative
* @param string $from
* @param string $to
* @param string $type
* @param string $fromTime
* @param string $toTime
*
* @return null|string
*/
public function activeClause(
$fieldName,
$relative, $from, $to, $type = NULL, $fromTime = NULL, $toTime = NULL
) {
$clauses = array();
if (in_array($relative, array_keys($this->getOperationPair(CRM_Report_Form::OP_DATE)))) {
return NULL;
}
list($from, $to) = $this->getFromTo($relative, $from, $to, $fromTime, $toTime);
if ($from) {
$from = ($type == CRM_Utils_Type::T_DATE) ? substr($from, 0, 8) : $from;
}
if ($to) {
$to = ($type == CRM_Utils_Type::T_DATE) ? substr($to, 0, 8) : $to;
}
if ($from || $to) {
return CRM_Contact_BAO_Query::getRelationshipActivePeriodClauses($from, $to, FALSE);
}
return NULL;
}
}

View file

@ -0,0 +1,296 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Contact_Summary extends CRM_Report_Form {
public $_summary = NULL;
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Household',
'Organization',
);
public $_drilldownReport = array('contact/detail' => 'Link to Detail Report');
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_autoIncludeIndexedFieldsAsOrderBys = 1;
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array_merge(
$this->getBasicContactFields(),
array(
'modified_date' => array(
'title' => ts('Modified Date'),
'default' => FALSE,
),
)
),
'filters' => $this->getBasicContactFilters(),
'grouping' => 'contact-fields',
'order_bys' => array(
'sort_name' => array(
'title' => ts('Last Name, First Name'),
'default' => '1',
'default_weight' => '0',
'default_order' => 'ASC',
),
'first_name' => array(
'name' => 'first_name',
'title' => ts('First Name'),
),
'gender_id' => array(
'name' => 'gender_id',
'title' => ts('Gender'),
),
'birth_date' => array(
'name' => 'birth_date',
'title' => ts('Birth Date'),
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
'order_bys' => array(
'email' => array(
'title' => ts('Email'),
),
),
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array(
'phone' => NULL,
'phone_ext' => array(
'title' => ts('Phone Extension'),
),
),
'grouping' => 'contact-fields',
),
) + $this->getAddressColumns(array('group_by' => FALSE));
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
elseif ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
}
elseif ($tableName == 'civicrm_country') {
$this->_countryField = TRUE;
}
$alias = "{$tableName}_{$fieldName}";
$select[] = "{$field['dbAlias']} as {$alias}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
$this->_selectAliases[] = $alias;
}
}
}
}
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = $grouping = array();
return $errors;
}
public function from() {
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1 ) ";
if ($this->isTableSelected('civicrm_email')) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1) ";
}
if ($this->_phoneField) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1 ";
}
if ($this->isTableSelected('civicrm_country')) {
$this->_from .= "
LEFT JOIN civicrm_country {$this->_aliases['civicrm_country']}
ON {$this->_aliases['civicrm_address']}.country_id = {$this->_aliases['civicrm_country']}.id AND
{$this->_aliases['civicrm_address']}.is_primary = 1 ";
}
}
public function postProcess() {
$this->beginPostProcess();
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
$sql = $this->buildQuery(TRUE);
$rows = $graphRows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// make count columns point to detail report
// convert sort name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contact/detail',
'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts('View Contact Detail Report for this contact');
$entryFound = TRUE;
}
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
// Handle ID to label conversion for contact fields
$entryFound = $this->alterDisplayContactFields($row, $rows, $rowNum, 'contact/summary', 'View Contact Summary') ? TRUE : $entryFound;
// display birthday in the configured custom format
if (array_key_exists('civicrm_contact_birth_date', $row)) {
$birthDate = $row['civicrm_contact_birth_date'];
if ($birthDate) {
$rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
}
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,714 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Contribute_Bookkeeping extends CRM_Report_Form {
protected $_addressField = FALSE;
protected $_emailField = FALSE;
protected $_summary = NULL;
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Contribution',
'Membership',
);
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_autoIncludeIndexedFieldsAsOrderBys = 1;
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
'first_name' => array(
'title' => ts('First Name'),
),
'middle_name' => array(
'title' => ts('Middle Name'),
),
'last_name' => array(
'title' => ts('Last Name'),
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
),
'age' => array(
'title' => ts('Age'),
'dbAlias' => 'TIMESTAMPDIFF(YEAR, contact_civireport.birth_date, CURDATE())',
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'grouping' => 'contact-fields',
'order_bys' => array(
'sort_name' => array(
'title' => ts('Last Name, First Name'),
'default' => '1',
'default_weight' => '0',
'default_order' => 'ASC',
),
'first_name' => array(
'name' => 'first_name',
'title' => ts('First Name'),
),
'gender_id' => array(
'name' => 'gender_id',
'title' => ts('Gender'),
),
'birth_date' => array(
'name' => 'birth_date',
'title' => ts('Birth Date'),
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'operator' => 'like',
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
),
'civicrm_membership' => array(
'dao' => 'CRM_Member_DAO_Membership',
'fields' => array(
'id' => array(
'title' => ts('Membership #'),
'no_display' => TRUE,
'required' => TRUE,
),
),
),
'civicrm_financial_account' => array(
'dao' => 'CRM_Financial_DAO_FinancialAccount',
'fields' => array(
'debit_accounting_code' => array(
'title' => ts('Financial Account Code - Debit'),
'name' => 'accounting_code',
'alias' => 'financial_account_civireport_debit',
'default' => TRUE,
),
'debit_contact_id' => array(
'title' => ts('Financial Account Owner - Debit'),
'name' => 'organization_name',
'alias' => 'debit_contact',
),
'credit_accounting_code' => array(
'title' => ts('Financial Account Code - Credit'),
'name' => 'accounting_code',
'alias' => 'financial_account_civireport_credit',
'default' => TRUE,
),
'credit_contact_id' => array(
'title' => ts('Financial Account Owner - Credit'),
'name' => 'organization_name',
'alias' => 'credit_contact',
),
'debit_name' => array(
'title' => ts('Financial Account Name - Debit'),
'name' => 'name',
'alias' => 'financial_account_civireport_debit',
'default' => TRUE,
),
'credit_name' => array(
'title' => ts('Financial Account Name - Credit'),
'name' => 'name',
'alias' => 'financial_account_civireport_credit',
'default' => TRUE,
),
),
'filters' => array(
'debit_accounting_code' => array(
'title' => ts('Financial Account Code - Debit'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialAccount(NULL, NULL, 'accounting_code', 'accounting_code'),
'name' => 'accounting_code',
'alias' => 'financial_account_civireport_debit',
),
'debit_contact_id' => array(
'title' => ts('Financial Account Owner - Debit'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'type' => CRM_Utils_Type::T_INT,
'options' => array('' => '- Select Organization -') + CRM_Financial_BAO_FinancialAccount::getOrganizationNames(),
'name' => 'contact_id',
'alias' => 'financial_account_civireport_debit',
),
'credit_accounting_code' => array(
'title' => ts('Financial Account Code - Credit'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialAccount(NULL, NULL, 'accounting_code', 'accounting_code'),
'name' => 'accounting_code',
'alias' => 'financial_account_civireport_credit',
),
'credit_contact_id' => array(
'title' => ts('Financial Account Owner - Credit'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'type' => CRM_Utils_Type::T_INT,
'options' => array('' => '- Select Organization -') + CRM_Financial_BAO_FinancialAccount::getOrganizationNames(),
'name' => 'contact_id',
'alias' => 'financial_account_civireport_credit',
),
'debit_name' => array(
'title' => ts('Financial Account Name - Debit'),
'type' => CRM_Utils_Type::T_STRING,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialAccount(),
'name' => 'id',
'alias' => 'financial_account_civireport_debit',
),
'credit_name' => array(
'title' => ts('Financial Account Name - Credit'),
'type' => CRM_Utils_Type::T_STRING,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialAccount(),
'name' => 'id',
'alias' => 'financial_account_civireport_credit',
),
),
),
'civicrm_line_item' => array(
'dao' => 'CRM_Price_DAO_LineItem',
'fields' => array(
'financial_type_id' => array(
'title' => ts('Financial Type'),
'default' => TRUE,
),
),
'filters' => array(
'financial_type_id' => array(
'title' => ts('Financial Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes(),
),
),
'order_bys' => array(
'financial_type_id' => array('title' => ts('Financial Type')),
),
),
'civicrm_batch' => array(
'dao' => 'CRM_Batch_DAO_Batch',
'fields' => array(
'title' => array(
'title' => ts('Batch Title'),
'alias' => 'batch',
'default' => FALSE,
),
'name' => array(
'title' => ts('Batch Name'),
'alias' => 'batch',
'default' => TRUE,
),
),
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'receive_date' => array(
'default' => TRUE,
),
'invoice_id' => array(
'title' => ts('Invoice ID'),
'default' => TRUE,
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'default' => TRUE,
),
'id' => array(
'title' => ts('Contribution ID'),
'default' => TRUE,
),
),
'filters' => array(
'contribution_id' => array(
'title' => ts('Contribution ID'),
'name' => 'id',
'operatorType' => CRM_Report_Form::OP_INT,
'type' => CRM_Utils_Type::T_INT,
),
'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => array(1),
),
),
'order_bys' => array(
'contribution_id' => array('title' => ts('Contribution #')),
'contribution_status_id' => array('title' => ts('Contribution Status')),
),
'grouping' => 'contri-fields',
),
'civicrm_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'check_number' => array(
'title' => ts('Cheque #'),
'default' => TRUE,
),
'payment_instrument_id' => array(
'title' => ts('Payment Method'),
'default' => TRUE,
),
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'trxn_date' => array(
'title' => ts('Transaction Date'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_DATE,
),
'trxn_id' => array(
'title' => ts('Trans #'),
'default' => TRUE,
),
'card_type_id' => array(
'title' => ts('Credit Card Type'),
),
),
'filters' => array(
'payment_instrument_id' => array(
'title' => ts('Payment Method'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::paymentInstrument(),
),
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'trxn_date' => array(
'title' => ts('Transaction Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'status_id' => array(
'title' => ts('Financial Transaction Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => array(1),
),
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
),
'order_bys' => array(
'payment_instrument_id' => array('title' => ts('Payment Method')),
),
),
'civicrm_entity_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_EntityFinancialTrxn',
'fields' => array(
'amount' => array(
'title' => ts('Amount'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_STRING,
),
),
'filters' => array(
'amount' => array('title' => ts('Amount')),
),
),
);
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
switch ($fieldName) {
case 'credit_accounting_code':
case 'credit_name':
$select[] = " CASE
WHEN {$this->_aliases['civicrm_financial_trxn']}.from_financial_account_id IS NOT NULL
THEN {$this->_aliases['civicrm_financial_account']}_credit_1.{$field['name']}
ELSE {$this->_aliases['civicrm_financial_account']}_credit_2.{$field['name']}
END AS civicrm_financial_account_{$fieldName} ";
break;
case 'amount':
$select[] = " CASE
WHEN {$this->_aliases['civicrm_entity_financial_trxn']}_item.entity_id IS NOT NULL
THEN {$this->_aliases['civicrm_entity_financial_trxn']}_item.amount
ELSE {$this->_aliases['civicrm_entity_financial_trxn']}.amount
END AS civicrm_entity_financial_trxn_amount ";
break;
case 'credit_contact_id':
$select[] = " CASE
WHEN {$this->_aliases['civicrm_financial_trxn']}.from_financial_account_id IS NOT NULL
THEN credit_contact_1.{$field['name']}
ELSE credit_contact_2.{$field['name']}
END AS civicrm_financial_account_{$fieldName} ";
break;
default:
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
break;
}
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
}
}
}
}
$this->_selectClauses = $select;
$this->_select = 'SELECT ' . implode(', ', $select) . ' ';
}
public function from() {
$this->_from = NULL;
$this->_from = "FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}
INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_contribution']}.contact_id AND
{$this->_aliases['civicrm_contribution']}.is_test = 0
LEFT JOIN civicrm_membership_payment payment
ON ( {$this->_aliases['civicrm_contribution']}.id = payment.contribution_id )
LEFT JOIN civicrm_membership {$this->_aliases['civicrm_membership']}
ON payment.membership_id = {$this->_aliases['civicrm_membership']}.id
LEFT JOIN civicrm_entity_financial_trxn {$this->_aliases['civicrm_entity_financial_trxn']}
ON ({$this->_aliases['civicrm_contribution']}.id = {$this->_aliases['civicrm_entity_financial_trxn']}.entity_id AND
{$this->_aliases['civicrm_entity_financial_trxn']}.entity_table = 'civicrm_contribution')
LEFT JOIN civicrm_financial_trxn {$this->_aliases['civicrm_financial_trxn']}
ON {$this->_aliases['civicrm_financial_trxn']}.id = {$this->_aliases['civicrm_entity_financial_trxn']}.financial_trxn_id
LEFT JOIN civicrm_financial_account {$this->_aliases['civicrm_financial_account']}_debit
ON {$this->_aliases['civicrm_financial_trxn']}.to_financial_account_id = {$this->_aliases['civicrm_financial_account']}_debit.id
LEFT JOIN civicrm_contact debit_contact ON {$this->_aliases['civicrm_financial_account']}_debit.contact_id = debit_contact.id
LEFT JOIN civicrm_financial_account {$this->_aliases['civicrm_financial_account']}_credit_1
ON {$this->_aliases['civicrm_financial_trxn']}.from_financial_account_id = {$this->_aliases['civicrm_financial_account']}_credit_1.id
LEFT JOIN civicrm_contact credit_contact_1 ON {$this->_aliases['civicrm_financial_account']}_credit_1.contact_id = credit_contact_1.id
LEFT JOIN civicrm_entity_financial_trxn {$this->_aliases['civicrm_entity_financial_trxn']}_item
ON ({$this->_aliases['civicrm_financial_trxn']}.id = {$this->_aliases['civicrm_entity_financial_trxn']}_item.financial_trxn_id AND
{$this->_aliases['civicrm_entity_financial_trxn']}_item.entity_table = 'civicrm_financial_item')
LEFT JOIN civicrm_financial_item fitem
ON fitem.id = {$this->_aliases['civicrm_entity_financial_trxn']}_item.entity_id
LEFT JOIN civicrm_financial_account {$this->_aliases['civicrm_financial_account']}_credit_2
ON fitem.financial_account_id = {$this->_aliases['civicrm_financial_account']}_credit_2.id
LEFT JOIN civicrm_contact credit_contact_2 ON {$this->_aliases['civicrm_financial_account']}_credit_2.contact_id = credit_contact_2.id
LEFT JOIN civicrm_line_item {$this->_aliases['civicrm_line_item']}
ON fitem.entity_id = {$this->_aliases['civicrm_line_item']}.id AND fitem.entity_table = 'civicrm_line_item'
";
if ($this->isTableSelected('civicrm_batch')) {
$this->_from .= "LEFT JOIN civicrm_entity_batch ent_batch
ON {$this->_aliases['civicrm_financial_trxn']}.id = ent_batch.entity_id AND ent_batch.entity_table = 'civicrm_financial_trxn'
LEFT JOIN civicrm_batch batch
ON ent_batch.batch_id = batch.id";
}
$this->getPermissionedFTQuery($this, "civicrm_line_item_1");
}
public function orderBy() {
parent::orderBy();
// please note this will just add the order-by columns to select query, and not display in column-headers.
// This is a solution to not throw fatal errors when there is a column in order-by, not present in select/display columns.
foreach ($this->_orderByFields as $orderBy) {
if (!array_key_exists($orderBy['name'], $this->_params['fields']) &&
empty($orderBy['section'])
) {
$this->_select .= ", {$orderBy['dbAlias']} as {$orderBy['tplField']}";
}
}
}
public function where() {
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (in_array($fieldName, array(
'credit_accounting_code',
'credit_name',
'credit_contact_id',
)
)) {
$field['dbAlias'] = "CASE
WHEN financial_trxn_civireport.from_financial_account_id IS NOT NULL
THEN financial_account_civireport_credit_1.{$field['name']}
ELSE financial_account_civireport_credit_2.{$field['name']}
END";
}
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = 'WHERE ( 1 )';
}
else {
$this->_where = 'WHERE ' . implode(' AND ', $clauses);
}
}
public function postProcess() {
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
parent::postProcess();
}
public function groupBy() {
$groupBy = array(
"{$this->_aliases['civicrm_entity_financial_trxn']}.id",
"{$this->_aliases['civicrm_line_item']}.id",
);
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
$tempTableName = CRM_Core_DAO::createTempTableName('civicrm_contribution');
$financialSelect = "CASE WHEN {$this->_aliases['civicrm_entity_financial_trxn']}_item.entity_id IS NOT NULL
THEN {$this->_aliases['civicrm_entity_financial_trxn']}_item.amount
ELSE {$this->_aliases['civicrm_entity_financial_trxn']}.amount
END as amount";
$this->_selectClauses = array(
"{$this->_aliases['civicrm_contribution']}.id",
"{$this->_aliases['civicrm_entity_financial_trxn']}.id as trxnID",
"{$this->_aliases['civicrm_contribution']}.currency",
$financialSelect,
);
$select = "SELECT " . implode(', ', $this->_selectClauses);
$this->groupBy();
$tempQuery = "CREATE TEMPORARY TABLE {$tempTableName} {$this->_databaseAttributes} AS
{$select} {$this->_from} {$this->_where} {$this->_groupBy} ";
CRM_Core_DAO::executeQuery($tempQuery);
$sql = "SELECT COUNT(trxnID) as count, SUM(amount) as amount, currency
FROM {$tempTableName}
GROUP BY currency";
$dao = CRM_Core_DAO::executeQuery($sql);
$amount = $avg = array();
while ($dao->fetch()) {
$amount[] = CRM_Utils_Money::format($dao->amount, $dao->currency);
$avg[] = CRM_Utils_Money::format(round(($dao->amount /
$dao->count), 2), $dao->currency);
}
$statistics['counts']['amount'] = array(
'value' => implode(', ', $amount),
'title' => ts('Total Amount'),
'type' => CRM_Utils_Type::T_STRING,
);
$statistics['counts']['avg'] = array(
'value' => implode(', ', $avg),
'title' => ts('Average'),
'type' => CRM_Utils_Type::T_STRING,
);
return $statistics;
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$contributionTypes = CRM_Contribute_PseudoConstant::financialType();
$paymentInstruments = CRM_Contribute_PseudoConstant::paymentInstrument();
$contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus();
$creditCardTypes = CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id');
foreach ($rows as $rowNum => $row) {
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
!empty($rows[$rowNum]['civicrm_contact_sort_name']) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts('View Contact Summary for this Contact.');
}
// handle contribution status id
if ($value = CRM_Utils_Array::value('civicrm_contribution_contribution_status_id', $row)) {
$rows[$rowNum]['civicrm_contribution_contribution_status_id'] = $contributionStatus[$value];
}
// handle payment instrument id
if ($value = CRM_Utils_Array::value('civicrm_financial_trxn_payment_instrument_id', $row)) {
$rows[$rowNum]['civicrm_financial_trxn_payment_instrument_id'] = $paymentInstruments[$value];
}
// handle financial type id
if ($value = CRM_Utils_Array::value('civicrm_line_item_financial_type_id', $row)) {
$rows[$rowNum]['civicrm_line_item_financial_type_id'] = $contributionTypes[$value];
}
if ($value = CRM_Utils_Array::value('civicrm_entity_financial_trxn_amount', $row)) {
$rows[$rowNum]['civicrm_entity_financial_trxn_amount'] = CRM_Utils_Money::format($rows[$rowNum]['civicrm_entity_financial_trxn_amount'], $rows[$rowNum]['civicrm_financial_trxn_currency']);
}
//handle gender
if (array_key_exists('civicrm_contact_gender_id', $row)) {
if ($value = $row['civicrm_contact_gender_id']) {
$gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
$rows[$rowNum]['civicrm_contact_gender_id'] = $gender[$value];
}
$entryFound = TRUE;
}
if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
$rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = CRM_Utils_Array::value($row['civicrm_financial_trxn_card_type_id'], $creditCardTypes);
$entryFound = TRUE;
}
// display birthday in the configured custom format
if (array_key_exists('civicrm_contact_birth_date', $row)) {
$birthDate = $row['civicrm_contact_birth_date'];
if ($birthDate) {
$rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
}
$entryFound = TRUE;
}
}
}
}

View file

@ -0,0 +1,548 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Contribute_DeferredRevenue extends CRM_Report_Form {
/**
* Holds Deferred Financial Account
*/
protected $_deferredFinancialAccount = array();
/**
*/
public function __construct() {
$this->_exposeContactID = FALSE;
$this->_deferredFinancialAccount = CRM_Financial_BAO_FinancialAccount::getAllDeferredFinancialAccount();
$this->_columns = array(
'civicrm_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'status_id' => array(
'title' => ts('Transaction'),
),
'trxn_date' => array(
'title' => ts('Transaction Date'),
'type' => CRM_Utils_Type::T_DATE,
'required' => TRUE,
),
'total_amount' => array(
'title' => ts('Transaction Amount'),
'type' => CRM_Utils_Type::T_MONEY,
'required' => TRUE,
'dbAlias' => 'SUM(financial_trxn_1_civireport.total_amount )',
),
),
'filters' => array(
'trxn_date' => array(
'title' => ts('Transaction Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
),
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'id' => array(
'title' => ts('Contribution ID'),
),
'contribution_id' => array(
'title' => ts('Contribution ID'),
'required' => TRUE,
'no_display' => TRUE,
'dbAlias' => 'contribution_civireport.id',
),
'contact_id' => array(
'title' => ts('Contact ID'),
),
'source' => array(
'title' => ts('Source'),
),
'receive_date' => array(
'title' => ts('Receive Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'cancel_date' => array(
'title' => ts('Cancel Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'revenue_recognition_date' => array(
'title' => ts('Revenue Recognition Date'),
'type' => CRM_Utils_Type::T_DATE,
),
),
'filters' => array(
'receive_date' => array(
'title' => ts('Receive Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'cancel_date' => array(
'title' => ts('Cancel Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'revenue_recognition_date' => array(
'title' => ts('Revenue Recognition Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'revenue_recognition_date_toggle' => array(
'title' => ts("Current month's revenue?"),
'type' => CRM_Utils_Type::T_BOOLEAN,
'default' => 0,
'pseudofield' => TRUE,
),
),
),
'civicrm_financial_account' => array(
'dao' => 'CRM_Financial_DAO_FinancialAccount',
'fields' => array(
'name' => array(
'title' => ts('Deferred Account'),
'required' => TRUE,
'no_display' => TRUE,
),
'id' => array(
'title' => ts('Deferred Account ID'),
'required' => TRUE,
'no_display' => TRUE,
),
'accounting_code' => array(
'title' => ts('Deferred Accounting Code'),
'required' => TRUE,
'no_display' => TRUE,
),
),
'filters' => array(
'id' => array(
'title' => ts('Deferred Financial Account'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->_deferredFinancialAccount,
'type' => CRM_Utils_Type::T_INT,
),
),
),
'civicrm_financial_account_1' => array(
'dao' => 'CRM_Financial_DAO_FinancialAccount',
'fields' => array(
'name' => array(
'title' => ts('Revenue Account'),
'required' => TRUE,
'no_display' => TRUE,
),
'id' => array(
'title' => ts('Revenue Account ID'),
'required' => TRUE,
'no_display' => TRUE,
),
'accounting_code' => array(
'title' => ts('Revenue Accounting code'),
'no_display' => TRUE,
'required' => TRUE,
),
),
),
'civicrm_financial_item' => array(
'dao' => 'CRM_Financial_DAO_FinancialItem',
'fields' => array(
'status_id' => array(
'title' => ts('Status'),
'required' => TRUE,
'no_display' => TRUE,
),
'id' => array(
'title' => ts('Financial Item ID'),
'required' => TRUE,
'no_display' => TRUE,
),
'description' => array(
'title' => ts('Item'),
),
),
),
'civicrm_financial_trxn_1' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'total_amount' => array(
'title' => ts('Deferred Transaction Amount'),
'type' => CRM_Utils_Type::T_MONEY,
'required' => TRUE,
'no_display' => TRUE,
'dbAlias' => 'GROUP_CONCAT(financial_trxn_1_civireport.total_amount)',
),
'trxn_date' => array(
'title' => ts('Deferred Transaction Date'),
'required' => TRUE,
'no_display' => TRUE,
'dbAlias' => 'GROUP_CONCAT(financial_trxn_1_civireport.trxn_date)',
'type' => CRM_Utils_Type::T_DATE,
),
),
),
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'display_name' => array(
'title' => ts('Contact Name'),
),
'id' => array(
'title' => ts('Contact ID'),
'required' => TRUE,
'no_display' => TRUE,
),
),
),
'civicrm_membership' => array(
'dao' => 'CRM_Member_DAO_Membership',
'fields' => array(
'start_date' => array(
'title' => ts('Start Date'),
'dbAlias' => 'IFNULL(membership_civireport.start_date, event_civireport.start_date)',
'type' => CRM_Utils_Type::T_DATE,
),
'end_date' => array(
'title' => ts('End Date'),
'dbdbAlias' => 'IFNULL(membership_civireport.end_date, event_civireport.end_date)',
'type' => CRM_Utils_Type::T_DATE,
),
),
),
'civicrm_event' => array(
'dao' => 'CRM_Event_DAO_Event',
),
'civicrm_participant' => array(
'dao' => 'CRM_Event_DAO_Participant',
),
'civicrm_batch' => array(
'dao' => 'CRM_Batch_DAO_EntityBatch',
'grouping' => 'contri-fields',
'fields' => array(
'batch_id' => array(
'title' => ts('Batch Title'),
'dbAlias' => "GROUP_CONCAT(DISTINCT batch_civireport.batch_id
ORDER BY batch_civireport.batch_id SEPARATOR ',')",
),
),
'filters' => array(
'batch_id' => array(
'title' => ts('Batch Title'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Batch_BAO_Batch::getBatches(),
'type' => CRM_Utils_Type::T_INT,
),
),
),
);
parent::__construct();
}
/**
* Pre process function.
*
* Called prior to build form.
*/
public function preProcess() {
parent::preProcess();
}
/**
* Build from clause.
*/
public function from() {
$deferredRelationship = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Deferred Revenue Account is' "));
$revenueRelationship = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Income Account is' "));
$this->_from = "
FROM civicrm_financial_item {$this->_aliases['civicrm_financial_item']}
INNER JOIN civicrm_entity_financial_account entity_financial_account_deferred
ON {$this->_aliases['civicrm_financial_item']}.financial_account_id = entity_financial_account_deferred.financial_account_id
AND entity_financial_account_deferred.entity_table = 'civicrm_financial_type'
AND entity_financial_account_deferred.account_relationship = {$deferredRelationship}
INNER JOIN civicrm_financial_account {$this->_aliases['civicrm_financial_account']}
ON entity_financial_account_deferred.financial_account_id = {$this->_aliases['civicrm_financial_account']}.id
INNER JOIN civicrm_entity_financial_account entity_financial_account_revenue
ON entity_financial_account_deferred.entity_id = entity_financial_account_revenue.entity_id
AND entity_financial_account_deferred.entity_table= entity_financial_account_revenue.entity_table
INNER JOIN civicrm_financial_account {$this->_aliases['civicrm_financial_account_1']}
ON entity_financial_account_revenue.financial_account_id = {$this->_aliases['civicrm_financial_account_1']}.id
AND {$revenueRelationship} = entity_financial_account_revenue.account_relationship
INNER JOIN civicrm_entity_financial_trxn entity_financial_trxn_item
ON entity_financial_trxn_item.entity_id = {$this->_aliases['civicrm_financial_item']}.id
AND entity_financial_trxn_item.entity_table = 'civicrm_financial_item'
INNER JOIN civicrm_financial_trxn {$this->_aliases['civicrm_financial_trxn_1']}
ON {$this->_aliases['civicrm_financial_trxn_1']}.to_financial_account_id = {$this->_aliases['civicrm_financial_account']}.id
AND {$this->_aliases['civicrm_financial_trxn_1']}.id = entity_financial_trxn_item.financial_trxn_id
INNER JOIN civicrm_entity_financial_trxn financial_trxn_contribution
ON financial_trxn_contribution.financial_trxn_id = {$this->_aliases['civicrm_financial_trxn_1']}.id
AND financial_trxn_contribution.entity_table = 'civicrm_contribution'
INNER JOIN civicrm_entity_financial_trxn entity_financial_trxn_contribution
ON entity_financial_trxn_contribution.entity_id = {$this->_aliases['civicrm_financial_item']}.id
AND entity_financial_trxn_contribution.entity_table = 'civicrm_financial_item'
INNER JOIN civicrm_financial_trxn {$this->_aliases['civicrm_financial_trxn']}
ON {$this->_aliases['civicrm_financial_trxn']}.id = entity_financial_trxn_contribution.financial_trxn_id
AND ({$this->_aliases['civicrm_financial_trxn']}.from_financial_account_id NOT IN (" . implode(',', array_keys($this->_deferredFinancialAccount)) . ")
OR {$this->_aliases['civicrm_financial_trxn']}.from_financial_account_id IS NULL)
INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON {$this->_aliases['civicrm_contribution']}.id = financial_trxn_contribution.entity_id
INNER JOIN civicrm_line_item line_item
ON line_item.contribution_id = {$this->_aliases['civicrm_contribution']}.id
AND line_item.financial_type_id = entity_financial_account_deferred.entity_id
LEFT JOIN civicrm_participant {$this->_aliases['civicrm_participant']}
ON CASE
WHEN line_item.entity_table = 'civicrm_participant'
THEN line_item.entity_id = {$this->_aliases['civicrm_participant']}.id
ELSE {$this->_aliases['civicrm_participant']}.id = 0
END
LEFT JOIN civicrm_event {$this->_aliases['civicrm_event']}
ON {$this->_aliases['civicrm_participant']}.event_id = {$this->_aliases['civicrm_event']}.id";
if ($this->isTableSelected('civicrm_contact')) {
$this->_from .= "
INNER JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_contribution']}.contact_id";
}
if ($this->isTableSelected('civicrm_membership')) {
$this->_from .= "
LEFT JOIN civicrm_membership {$this->_aliases['civicrm_membership']}
ON CASE
WHEN line_item.entity_table = 'civicrm_membership'
THEN line_item.entity_id = {$this->_aliases['civicrm_membership']}.id
ELSE {$this->_aliases['civicrm_membership']}.id = 0
END";
}
if ($this->isTableSelected('civicrm_batch')) {
$this->_from .= "
LEFT JOIN civicrm_entity_batch {$this->_aliases['civicrm_batch']}
ON {$this->_aliases['civicrm_batch']}.entity_id = {$this->_aliases['civicrm_financial_trxn']}.id
AND {$this->_aliases['civicrm_batch']}.entity_table = 'civicrm_financial_trxn'";
}
}
/**
* Post process function.
*/
public function postProcess() {
$this->_noFields = TRUE;
parent::postProcess();
}
/**
* Set limit.
*
* @param int $rowCount
*/
public function limit($rowCount = self::ROW_COUNT_LIMIT) {
$this->_limit = NULL;
}
/**
* Build where clause.
*/
public function where() {
parent::where();
$startDate = date('Y-m-01');
$endDate = date('Y-m-t', strtotime(date('ymd') . '+11 month'));
$this->_where .= " AND {$this->_aliases['civicrm_financial_trxn_1']}.trxn_date BETWEEN '{$startDate}' AND '{$endDate}'";
}
/**
* Build group by clause.
*/
public function groupBy() {
$this->_groupBy = "GROUP BY {$this->_aliases['civicrm_financial_account']}.id, {$this->_aliases['civicrm_financial_account_1']}.id, {$this->_aliases['civicrm_financial_item']}.id";
$this->_select = CRM_Contact_BAO_Query::appendAnyValueToSelect(
$this->_selectClauses,
array(
"{$this->_aliases['civicrm_financial_account_1']}.id",
"{$this->_aliases['civicrm_financial_item']}.id",
)
);
}
/**
* Modify column headers.
*/
public function modifyColumnHeaders() {
// Re-order the columns in a custom order defined below.
$sortArray = array(
'civicrm_batch_batch_id',
'civicrm_financial_trxn_status_id',
'civicrm_financial_trxn_trxn_date',
'civicrm_contribution_receive_date',
'civicrm_contribution_cancel_date',
'civicrm_contribution_revenue_recognition_date',
'civicrm_financial_trxn_total_amount',
'civicrm_financial_item_description',
'civicrm_contribution_contact_id',
'civicrm_contact_display_name',
'civicrm_contribution_source',
);
// Only re-order selected columns.
$sortArray = array_flip(array_intersect_key(array_flip($sortArray), $this->_columnHeaders));
// Re-ordering.
$this->_columnHeaders = array_merge(array_flip($sortArray), $this->_columnHeaders);
// Add months to the columns.
if ($this->_params['revenue_recognition_date_toggle_value']) {
$this->_columnHeaders[date('M, Y', strtotime(date('Y-m-d')))] = array(
'title' => date('M, Y', strtotime(date('Y-m-d'))),
'type' => CRM_Utils_Type::T_DATE,
);
}
else {
for ($i = 0; $i < 12; $i++) {
$this->_columnHeaders[date('M, Y', strtotime(date('Y-m-d') . "+{$i} month"))] = array(
'title' => date('M, Y', strtotime(date('Y-m-d') . "+{$i} month")),
'type' => CRM_Utils_Type::T_DATE,
);
}
}
}
/**
* Build output rows.
*
* @param string $sql
* @param array $rows
*/
public function buildRows($sql, &$rows) {
$dao = CRM_Core_DAO::executeQuery($sql);
// use this method to modify $this->_columnHeaders
$this->modifyColumnHeaders();
// Get custom date format.
$dateFormat = Civi::settings()->get('dateformatFinancialBatch');
if (!is_array($rows)) {
$rows = array();
}
while ($dao->fetch()) {
$row = array();
foreach ($this->_columnHeaders as $key => $value) {
$arraykey = $dao->civicrm_financial_account_id . '_' . $dao->civicrm_financial_account_1_id;
if (property_exists($dao, $key)) {
if (CRM_Utils_Array::value('type', $value) & CRM_Utils_Type::T_DATE) {
$row[$key] = CRM_Utils_Date::customFormat($dao->$key, $dateFormat);
}
elseif (CRM_Utils_Array::value('type', $value) & CRM_Utils_Type::T_MONEY) {
$row[$key] = CRM_Utils_Money::format($dao->$key);
}
else {
$row[$key] = $dao->$key;
}
}
$rows[$arraykey]['rows'][$dao->civicrm_financial_item_id] = $row;
$rows[$arraykey]['label'] = "Deferred Revenue Account: {$dao->civicrm_financial_account_name} ({$dao->civicrm_financial_account_accounting_code}), Revenue Account: {$dao->civicrm_financial_account_1_name} {$dao->civicrm_financial_account_1_accounting_code}";
$trxnDate = explode(',', $dao->civicrm_financial_trxn_1_trxn_date);
$trxnAmount = explode(',', $dao->civicrm_financial_trxn_1_total_amount);
foreach ($trxnDate as $key => $date) {
$keyDate = date('M, Y', strtotime($date));
$rows[$arraykey]['rows'][$dao->civicrm_financial_item_id][$keyDate] = CRM_Utils_Money::format($trxnAmount[$key]);
}
}
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
foreach ($rows as &$entry) {
foreach ($entry['rows'] as $rowNum => &$row) {
// convert transaction status id to status name
if ($status = CRM_Utils_Array::value('civicrm_financial_trxn_status_id', $row)) {
$row['civicrm_financial_trxn_status_id'] = CRM_Core_PseudoConstant::getLabel('CRM_Core_BAO_FinancialTrxn', 'status_id', $status);
$entryFound = TRUE;
}
// convert batch id to batch title
if ($batchId = CRM_Utils_Array::value('civicrm_batch_batch_id', $row)) {
$row['civicrm_batch_batch_id'] = $this->getLabels($batchId, 'CRM_Batch_BAO_EntityBatch', 'batch_id');
$entryFound = TRUE;
}
// add hotlink for contribution
if ($amount = CRM_Utils_Array::value('civicrm_financial_trxn_total_amount', $row)) {
$contributionUrl = CRM_Utils_System::url("civicrm/contact/view/contribution",
'reset=1&action=view&cid=' . $row['civicrm_contact_id'] . '&id=' . $row['civicrm_contribution_contribution_id'],
$this->_absoluteUrl
);
$row['civicrm_financial_trxn_total_amount'] = "<a href={$contributionUrl}>{$amount}</a>";
if ($contributionId = CRM_Utils_Array::value('civicrm_contribution_id', $row)) {
$row['civicrm_contribution_id'] = "<a href={$contributionUrl}>{$contributionId}</a>";
}
$entryFound = TRUE;
}
// add hotlink for contact
if ($contactName = CRM_Utils_Array::value('civicrm_contact_display_name', $row)) {
$contactUrl = CRM_Utils_System::url("civicrm/contact/view",
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$row['civicrm_contact_display_name'] = "<a href={$contactUrl}>{$contactName}</a>";
$entryFound = TRUE;
}
if ($contactId = CRM_Utils_Array::value('civicrm_contribution_contact_id', $row)) {
$contactUrl = CRM_Utils_System::url("civicrm/contact/view",
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$row['civicrm_contribution_contact_id'] = "<a href={$contactUrl}>{$contactId}</a>";
$entryFound = TRUE;
}
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,896 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Contribute_History extends CRM_Report_Form {
// Primary Contacts count limitCONSTROW_COUNT_LIMIT = 10;
protected $_addressField = FALSE;
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
protected $_relationshipColumns = array();
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Contribution',
);
protected $_referenceYear = array(
'this_year' => '',
'other_year' => '',
);
protected $_yearStatisticsFrom = '';
protected $_yearStatisticsTo = '';
/**
*/
public function __construct() {
$this->_autoIncludeIndexedFieldsAsOrderBys = 1;
$yearsInPast = 4;
$date = CRM_Core_SelectValues::date('custom', NULL, $yearsInPast, 0);
$count = $date['maxYear'];
$optionYear = array('' => ts('- select -'));
$this->_yearStatisticsFrom = $date['minYear'];
$this->_yearStatisticsTo = $date['maxYear'];
while ($date['minYear'] <= $count) {
$optionYear[$date['minYear']] = $date['minYear'];
$date['minYear']++;
}
$relationTypeOp = array();
$relationshipTypes = CRM_Core_PseudoConstant::relationshipType();
foreach ($relationshipTypes as $rid => $rtype) {
if ($rtype['label_a_b'] != $rtype['label_b_a']) {
$relationTypeOp[$rid] = "{$rtype['label_a_b']}/{$rtype['label_b_a']}";
}
else {
$relationTypeOp[$rid] = $rtype['label_a_b'];
}
}
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'default' => TRUE,
'required' => TRUE,
'no_repeat' => TRUE,
),
'first_name' => array(
'title' => ts('First Name'),
),
'middle_name' => array(
'title' => ts('Middle Name'),
),
'last_name' => array(
'title' => ts('Last Name'),
),
'id' => array(
'no_display' => TRUE,
'default' => TRUE,
'required' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
),
'age' => array(
'title' => ts('Age'),
'dbAlias' => 'TIMESTAMPDIFF(YEAR, contact_civireport.birth_date, CURDATE())',
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'grouping' => 'contact-fields',
'order_bys' => array(
'sort_name' => array(
'title' => ts('Last Name, First Name'),
'default' => '1',
'default_weight' => '0',
'default_order' => 'ASC',
),
'first_name' => array(
'name' => 'first_name',
'title' => ts('First Name'),
),
'gender_id' => array(
'name' => 'gender_id',
'title' => ts('Gender'),
),
'birth_date' => array(
'name' => 'birth_date',
'title' => ts('Birth Date'),
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => array(
'sort_name' => array('title' => ts('Contact Name')),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array(
'phone' => array(
'title' => ts('Phone'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
),
) + $this->addAddressFields(FALSE, FALSE, FALSE, array()) + array(
'civicrm_relationship' => array(
'dao' => 'CRM_Contact_DAO_Relationship',
'fields' => array(
'relationship_type_id' => array(
'title' => ts('Relationship Type'),
'default' => TRUE,
),
'contact_id_a' => array('no_display' => TRUE),
'contact_id_b' => array('no_display' => TRUE),
),
'filters' => array(
'relationship_type_id' => array(
'title' => ts('Relationship Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $relationTypeOp,
'type' => CRM_Utils_Type::T_STRING,
),
),
),
) + array(
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'total_amount' => array(
'title' => ts('Amount Statistics'),
'default' => TRUE,
'required' => TRUE,
'no_display' => TRUE,
'statistics' => array('sum' => ts('Aggregate Amount')),
),
'receive_date' => array(
'required' => TRUE,
'default' => TRUE,
'no_display' => TRUE,
),
),
'grouping' => 'contri-fields',
'filters' => array(
'this_year' => array(
'title' => ts('This Year'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => $optionYear,
'default' => '',
),
'other_year' => array(
'title' => ts('Other Years'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => $optionYear,
'default' => '',
),
'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => array(1),
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialType(),
),
'total_amount' => array(
'title' => ts('Contribution Amount'),
),
'total_sum' => array(
'title' => ts('Aggregate Amount'),
'type' => CRM_Report_Form::OP_INT,
'dbAlias' => 'civicrm_contribution_total_amount_sum',
'having' => TRUE,
),
),
),
);
$this->_columns += array(
'civicrm_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
),
),
'filters' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
),
),
);
$this->_columns['civicrm_contribution']['fields']['civicrm_upto_' .
$this->_yearStatisticsFrom] = array(
'title' => ts('Up To %1 Donation', array(1 => $this->_yearStatisticsFrom)),
'default' => TRUE,
'type' => CRM_Utils_Type::T_MONEY,
'is_statistics' => TRUE,
);
$yearConter = $this->_yearStatisticsFrom;
$yearConter++;
while ($yearConter <= $this->_yearStatisticsTo) {
$this->_columns['civicrm_contribution']['fields'][$yearConter] = array(
'title' => ts('%1 Donation', array(1 => $yearConter)),
'default' => TRUE,
'type' => CRM_Utils_Type::T_MONEY,
'is_statistics' => TRUE,
);
$yearConter++;
}
$this->_columns['civicrm_contribution']['fields']['aggregate_amount'] = array(
'title' => ts('Aggregate Amount'),
'type' => CRM_Utils_Type::T_MONEY,
'is_statistics' => TRUE,
);
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
}
if ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
if ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
}
if ($tableName == 'civicrm_relationship') {
$this->_relationshipColumns["{$tableName}_{$fieldName}"] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
continue;
}
if (!empty($field['is_statistics'])) {
$this->_columnHeaders[$fieldName]['type'] = $field['type'];
$this->_columnHeaders[$fieldName]['title'] = $field['title'];
continue;
}
elseif ($fieldName == 'receive_date') {
if ((CRM_Utils_Array::value('this_year_op', $this->_params) ==
'fiscal' && !empty($this->_params['this_year_value'])) ||
(CRM_Utils_Array::value('other_year_op', $this->_params ==
'fiscal') && !empty($this->_params['other_year_value']))
) {
$select[] = self::fiscalYearOffset($field['dbAlias']) .
" as {$tableName}_{$fieldName}";
}
else {
$select[] = " YEAR(" . $field['dbAlias'] . ")" .
" as {$tableName}_{$fieldName}";
}
}
elseif ($fieldName == 'total_amount') {
$select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}";
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
if (!empty($field['no_display'])) {
$this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = TRUE;
}
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']}
INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_contribution']}.contact_id AND
{$this->_aliases['civicrm_contribution']}.is_test = 0 ";
if ($this->_emailField) {
$this->_from .= " LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1) ";
}
if ($this->_phoneField) {
$this->_from .= " LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1) ";
}
$relContacAlias = 'contact_relationship';
$this->_relationshipFrom = " INNER JOIN civicrm_relationship {$this->_aliases['civicrm_relationship']}
ON (({$this->_aliases['civicrm_relationship']}.contact_id_a = {$relContacAlias}.id OR {$this->_aliases['civicrm_relationship']}.contact_id_b = {$relContacAlias}.id ) AND {$this->_aliases['civicrm_relationship']}.is_active = 1) ";
$this->addAddressFromClause();
// for credit card type
$this->addFinancialTrxnFromClause();
}
public function where() {
$whereClauses = $havingClauses = $relationshipWhere = array();
$this->_relationshipWhere = '';
$this->_statusClause = '';
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if ($fieldName == 'this_year' || $fieldName == 'other_year') {
continue;
}
elseif (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE
) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
if ($tableName == 'civicrm_relationship') {
$relationshipWhere[] = $clause;
continue;
}
if ($fieldName == 'contribution_status_id') {
$this->_statusClause = " AND " . $clause;
}
if (!empty($field['having'])) {
$havingClauses[] = $clause;
}
else {
$whereClauses[] = $clause;
}
}
}
}
}
if (empty($whereClauses)) {
$this->_where = "WHERE ( 1 ) ";
$this->_having = "";
}
else {
$this->_where = "WHERE " . implode(' AND ', $whereClauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
if (!empty($havingClauses)) {
// use this clause to construct group by clause.
$this->_having = "HAVING " . implode(' AND ', $havingClauses);
}
if (!empty($relationshipWhere)) {
$this->_relationshipWhere = ' AND ' .
implode(' AND ', $relationshipWhere);
}
}
public function groupBy() {
$groupBy = array(
"{$this->_aliases['civicrm_contribution']}.contact_id",
"YEAR({$this->_aliases['civicrm_contribution']}.receive_date)",
);
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
/**
* Override to set limit to 10.
*
* @param int $rowCount
*
* @return array
*/
public function limit($rowCount = self::ROW_COUNT_LIMIT) {
return parent::limit($rowCount);
}
/**
* Override to set pager with limit is 10.
*
* @param int $rowCount
*/
public function setPager($rowCount = self::ROW_COUNT_LIMIT) {
parent::setPager($rowCount);
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
$count = 0;
foreach ($rows as $rownum => $row) {
if (is_numeric($rownum)) {
$count++;
}
}
$statistics['counts']['rowCount'] = array(
'title' => ts('Primary Contact(s) Listed'),
'value' => $count,
);
if ($this->_rowsFound && ($this->_rowsFound > $count)) {
$statistics['counts']['rowsFound'] = array(
'title' => ts('Total Primary Contact(s)'),
'value' => $this->_rowsFound,
);
}
return $statistics;
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = array();
if (!empty($fields['this_year_value']) &&
!empty($fields['other_year_value']) &&
($fields['this_year_value'] == $fields['other_year_value'])
) {
$errors['other_year_value'] = ts("Value for filters 'This Year' and 'Other Years' can not be same.");
}
return $errors;
}
public function postProcess() {
// get ready with post process params
$this->beginPostProcess();
$this->fixReportParams();
$this->buildACLClause($this->_aliases['civicrm_contact']);
$this->select();
$this->where();
$this->from();
$this->customDataFrom();
$this->groupBy();
$sql = NULL;
$rows = array();
// build array of result based on column headers. This method also allows
// modifying column headers before using it to build result set i.e $rows.
$this->buildRows($sql, $rows);
// format result set.
$this->formatDisplay($rows, FALSE);
// assign variables to templates
$this->doTemplateAssignment($rows);
// do print / pdf / instance stuff if needed
$this->endPostProcess($rows);
}
public function fixReportParams() {
if (!empty($this->_params['this_year_value'])) {
$this->_referenceYear['this_year'] = $this->_params['this_year_value'];
}
if (!empty($this->_params['other_year_value'])) {
$this->_referenceYear['other_year'] = $this->_params['other_year_value'];
}
}
/**
* @param $sql
* @param $rows
*/
public function buildRows($sql, &$rows) {
$contactIds = array();
$addWhere = '';
if (!empty($this->_referenceYear['other_year'])) {
(CRM_Utils_Array::value('other_year_op', $this->_params) ==
'calendar') ? $other_receive_date = 'YEAR (contri.receive_date)' : $other_receive_date = self::fiscalYearOffset('contri.receive_date');
$addWhere .= " AND {$this->_aliases['civicrm_contact']}.id NOT IN ( SELECT DISTINCT cont.id FROM civicrm_contact cont, civicrm_contribution contri WHERE cont.id = contri.contact_id AND {$other_receive_date} = {$this->_referenceYear['other_year']} AND contri.is_test = 0 ) ";
}
if (!empty($this->_referenceYear['this_year'])) {
(CRM_Utils_Array::value('this_year_op', $this->_params) ==
'calendar') ? $receive_date = 'YEAR (contri.receive_date)' : $receive_date = self::fiscalYearOffset('contri.receive_date');
$addWhere .= " AND {$this->_aliases['civicrm_contact']}.id IN ( SELECT DISTINCT cont.id FROM civicrm_contact cont, civicrm_contribution contri WHERE cont.id = contri.contact_id AND {$receive_date} = {$this->_referenceYear['this_year']} AND contri.is_test = 0 ) ";
}
$this->limit();
$getContacts = "SELECT SQL_CALC_FOUND_ROWS {$this->_aliases['civicrm_contact']}.id as cid, SUM({$this->_aliases['civicrm_contribution']}.total_amount) as civicrm_contribution_total_amount_sum {$this->_from} {$this->_where} {$addWhere} GROUP BY {$this->_aliases['civicrm_contact']}.id {$this->_having} {$this->_limit}";
$dao = CRM_Core_DAO::executeQuery($getContacts);
while ($dao->fetch()) {
$contactIds[] = $dao->cid;
}
$dao->free();
$this->setPager();
$relationshipRows = array();
if (empty($contactIds)) {
return;
}
$primaryContributions = $this->buildContributionRows($contactIds);
list($relationshipRows, $relatedContactIds) = $this->buildRelationshipRows($contactIds);
if (empty($relatedContactIds)) {
$rows = $primaryContributions;
return;
}
$relatedContributions = $this->buildContributionRows($relatedContactIds);
$summaryYears = array();
$summaryYears[] = "civicrm_upto_{$this->_yearStatisticsFrom}";
$yearConter = $this->_yearStatisticsFrom;
$yearConter++;
while ($yearConter <= $this->_yearStatisticsTo) {
$summaryYears[] = $yearConter;
$yearConter++;
}
$summaryYears[] = 'aggregate_amount';
foreach ($primaryContributions as $cid => $primaryRow) {
$row = $primaryRow;
if (!isset($relationshipRows[$cid])) {
$rows[$cid] = $row;
continue;
}
$total = array();
$total['civicrm_contact_sort_name'] = ts('Total');
foreach ($summaryYears as $year) {
$total[$year] = CRM_Utils_Array::value($year, $primaryRow, 0);
}
$relatedContact = FALSE;
$rows[$cid] = $row;
foreach ($relationshipRows[$cid] as $relcid => $relRow) {
if (!isset($relatedContributions[$relcid])) {
continue;
}
$relatedContact = TRUE;
$relatedRow = $relatedContributions[$relcid];
foreach ($summaryYears as $year) {
$total[$year] += CRM_Utils_Array::value($year, $relatedRow, 0);
}
foreach (array_keys($this->_relationshipColumns) as $col) {
if (!empty($relRow[$col])) {
$relatedRow[$col] = $relRow[$col];
}
}
$rows["{$cid}_{$relcid}"] = $relatedRow;
}
if ($relatedContact) {
$rows["{$cid}_total"] = $total;
$rows["{$cid}_bank"] = array('civicrm_contact_sort_name' => '&nbsp;');
}
}
}
/**
* @param $contactIds
*
* @return array
*/
public function buildContributionRows($contactIds) {
$rows = array();
if (empty($contactIds)) {
return $rows;
}
$sqlContribution = "{$this->_select} {$this->_from} WHERE {$this->_aliases['civicrm_contact']}.id IN (" .
implode(',', $contactIds) .
") AND {$this->_aliases['civicrm_contribution']}.is_test = 0 {$this->_statusClause} {$this->_groupBy} ";
$dao = CRM_Core_DAO::executeQuery($sqlContribution);
$contributionSum = 0;
$yearcal = array();
while ($dao->fetch()) {
if (!$dao->civicrm_contact_id) {
continue;
}
foreach ($this->_columnHeaders as $key => $value) {
if (property_exists($dao, $key)) {
$rows[$dao->civicrm_contact_id][$key] = $dao->$key;
}
}
if ($dao->civicrm_contribution_receive_date) {
if ($dao->civicrm_contribution_receive_date >
$this->_yearStatisticsFrom
) {
$rows[$dao->civicrm_contact_id][$dao->civicrm_contribution_receive_date] = $dao->civicrm_contribution_total_amount;
}
else {
if (!isset($rows[$dao->civicrm_contact_id]["civicrm_upto_{$this->_yearStatisticsFrom}"])) {
$rows[$dao->civicrm_contact_id]["civicrm_upto_{$this->_yearStatisticsFrom}"] = 0;
}
$rows[$dao->civicrm_contact_id]["civicrm_upto_{$this->_yearStatisticsFrom}"] += $dao->civicrm_contribution_total_amount;
}
}
if (!isset($rows[$dao->civicrm_contact_id]['aggregate_amount'])) {
$rows[$dao->civicrm_contact_id]['aggregate_amount'] = 0;
}
$rows[$dao->civicrm_contact_id]['aggregate_amount'] += $dao->civicrm_contribution_total_amount;
}
$dao->free();
return $rows;
}
/**
* @param $contactIds
*
* @return array
*/
public function buildRelationshipRows($contactIds) {
$relationshipRows = $relatedContactIds = array();
if (empty($contactIds)) {
return array($relationshipRows, $relatedContactIds);
}
$relContactAlias = 'contact_relationship';
$addRelSelect = '';
if (!empty($this->_relationshipColumns)) {
$addRelSelect = ', ' . implode(', ', $this->_relationshipColumns);
}
$sqlRelationship = "SELECT {$this->_aliases['civicrm_relationship']}.relationship_type_id as relationship_type_id, {$this->_aliases['civicrm_relationship']}.contact_id_a as contact_id_a, {$this->_aliases['civicrm_relationship']}.contact_id_b as contact_id_b {$addRelSelect} FROM civicrm_contact {$relContactAlias} {$this->_relationshipFrom} WHERE {$relContactAlias}.id IN (" .
implode(',', $contactIds) .
") AND {$this->_aliases['civicrm_relationship']}.is_active = 1 {$this->_relationshipWhere} GROUP BY {$this->_aliases['civicrm_relationship']}.contact_id_a, {$this->_aliases['civicrm_relationship']}.contact_id_b, {$this->_aliases['civicrm_relationship']}.relationship_type_id";
$relationshipTypes = CRM_Core_PseudoConstant::relationshipType();
$dao = CRM_Core_DAO::executeQuery($sqlRelationship);
while ($dao->fetch()) {
$row = array();
foreach (array_keys($this->_relationshipColumns) as $rel_column) {
$row[$rel_column] = $dao->$rel_column;
}
if (in_array($dao->contact_id_a, $contactIds)) {
$row['civicrm_relationship_relationship_type_id'] = $relationshipTypes[$dao->relationship_type_id]['label_a_b'];
$row['civicrm_relationship_contact_id'] = $dao->contact_id_b;
$relationshipRows[$dao->contact_id_a][$dao->contact_id_b] = $row;
$relatedContactIds[$dao->contact_id_b] = $dao->contact_id_b;
}
if (in_array($dao->contact_id_b, $contactIds)) {
$row['civicrm_relationship_contact_id'] = $dao->contact_id_a;
$row['civicrm_relationship_relationship_type_id'] = $relationshipTypes[$dao->relationship_type_id]['label_b_a'];
$relationshipRows[$dao->contact_id_b][$dao->contact_id_a] = $row;
$relatedContactIds[$dao->contact_id_a] = $dao->contact_id_a;
}
}
$dao->free();
return array($relationshipRows, $relatedContactIds);
}
/**
* Override "This Year" $op options
* @param string $type
* @param null $fieldName
*
* @return array
*/
public function getOperationPair($type = "string", $fieldName = NULL) {
if ($fieldName == 'this_year' || $fieldName == 'other_year') {
return array(
'calendar' => ts('Is Calendar Year'),
'fiscal' => ts('Fiscal Year Starting'),
);
}
return parent::getOperationPair($type, $fieldName);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
if (empty($rows)) {
return;
}
$last_primary = NULL;
foreach ($rows as $rowNum => $row) {
//handle gender
if (array_key_exists('civicrm_contact_gender_id', $row)) {
if ($value = $row['civicrm_contact_gender_id']) {
$gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
$row['civicrm_contact_gender_id'] = $rows[$rowNum]['civicrm_contact_gender_id'] = $gender[$value];
}
$entryFound = TRUE;
}
// Highlight primary contact and amount row
if (is_numeric($rowNum) ||
($last_primary && ($rowNum == "{$last_primary}_total"))
) {
if (is_numeric($rowNum)) {
$last_primary = $rowNum;
}
foreach ($row as $key => $value) {
if ($key == 'civicrm_contact_id') {
continue;
}
if (empty($value)) {
$row[$key] = '';
continue;
}
if ($last_primary && ($rowNum == "{$last_primary}_total")) {
$value = CRM_Utils_Money::format($value, ' ');
}
$row[$key] = '<strong>' . $value . '</strong>';
}
$rows[$rowNum] = $row;
}
// Convert Display name into link
if (!empty($row['civicrm_contact_sort_name']) &&
!empty($row['civicrm_contact_id'])
) {
$url = CRM_Report_Utils_Report::getNextUrl('contribute/detail',
'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'],
$this->_absoluteUrl, $this->_id
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contribution Details for this Contact.");
}
if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
$rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
$entryFound = TRUE;
}
// display birthday in the configured custom format
if (array_key_exists('civicrm_contact_birth_date', $row)) {
$birthDate = $row['civicrm_contact_birth_date'];
if ($birthDate) {
$rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
}
$entryFound = TRUE;
}
}
}
}

View file

@ -0,0 +1,614 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Contribute_HouseholdSummary extends CRM_Report_Form {
protected $_addressField = FALSE;
protected $_emailField = FALSE;
public $_drilldownReport = array('contribute/detail' => 'Link to Detail Report');
protected $_summary = NULL;
/**
*/
/**
*/
public function __construct() {
self::validRelationships();
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
$this->_columns = array(
'civicrm_contact_household' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'household_name' => array(
'title' => ts('Household Name'),
'required' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => array(
'household_name' => array('title' => ts('Household Name')),
),
'grouping' => 'household-fields',
),
'civicrm_line_item' => array(
'dao' => 'CRM_Price_DAO_LineItem',
),
'civicrm_relationship' => array(
'dao' => 'CRM_Contact_DAO_Relationship',
'fields' => array(
'relationship_type_id' => array(
'title' => ts('Relationship Type'),
),
),
'filters' => array(
'relationship_type_id' => array(
'title' => ts('Relationship Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => $this->relationTypes,
'default' => key($this->relationTypes),
),
),
'grouping' => 'household-fields',
),
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'total_amount' => array(
'title' => ts('Amount'),
'required' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'default' => TRUE,
),
'check_number' => array(
'title' => ts('Check Number'),
),
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
),
'trxn_id' => NULL,
'receive_date' => array('default' => TRUE),
'receipt_date' => NULL,
),
'filters' => array(
'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'total_amount' => array('title' => ts('Amount Between')),
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => array(1),
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialType(),
),
),
'grouping' => 'contri-fields',
),
'civicrm_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
),
),
'filters' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
),
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'fields' => array(
'street_address' => NULL,
'city' => NULL,
'postal_code' => NULL,
'state_province_id' => array(
'title' => ts('State/Province'),
),
'country_id' => array(
'title' => ts('Country'),
),
),
'grouping' => 'contact-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => NULL,
),
'grouping' => 'contact-fields',
),
);
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_contribution']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
);
$this->_columns['civicrm_contribution']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
}
$this->_currencyColumn = 'civicrm_contribution_currency';
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$this->_columnHeaders = $select = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
}
elseif ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
if (!empty($field['statistics'])) {
foreach ($field['statistics'] as $stat => $label) {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
}
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
}
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$this->_from = NULL;
$this->_from = "
FROM civicrm_relationship {$this->_aliases['civicrm_relationship']}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact_household']} ON
({$this->_aliases['civicrm_contact_household']}.id = {$this->_aliases['civicrm_relationship']}.$this->householdContact AND {$this->_aliases['civicrm_contact_household']}.contact_type='Household')
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']} ON
({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_relationship']}.$this->otherContact )
{$this->_aclFrom}
INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']} ON
({$this->_aliases['civicrm_contribution']}.contact_id = {$this->_aliases['civicrm_relationship']}.$this->otherContact ) AND {$this->_aliases['civicrm_contribution']}.is_test = 0 ";
if ($this->_addressField) {
$this->_from .= "
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']} ON
{$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1\n ";
}
if ($this->_emailField) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']} ON
{$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1\n ";
}
// for credit card type
$this->addFinancialTrxnFromClause();
}
public function where() {
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
if ($fieldName == 'relationship_type_id') {
$clause = "{$this->_aliases['civicrm_relationship']}.relationship_type_id=" . $this->relationshipId;
}
else {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE ( 1 )";
}
else {
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
public function groupBy() {
$groupBy = array(
"{$this->_aliases['civicrm_relationship']}.$this->householdContact",
"{$this->_aliases['civicrm_relationship']}.$this->otherContact",
"{$this->_aliases['civicrm_contribution']}.id",
"{$this->_aliases['civicrm_relationship']}.relationship_type_id",
);
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
public function orderBy() {
$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";
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
//hack filter display for relationship type
$type = substr($this->_params['relationship_type_id_value'], -3);
foreach ($statistics['filters'] as $id => $value) {
if (
$value['title'] == 'Relationship Type' &&
isset($this->relationTypes[$this->relationshipId . '_' . $type])
) {
$statistics['filters'][$id]['value'] = 'Is equal to ' .
$this->relationTypes[$this->relationshipId . '_' . $type];
}
}
return $statistics;
}
public function postProcess() {
$this->beginPostProcess();
$this->buildACLClause(array(
$this->_aliases['civicrm_contact'],
$this->_aliases['civicrm_contact_household'],
));
$sql = $this->buildQuery(TRUE);
$rows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* Set variables to be accessed by API and form layer in processing.
*/
public function beginPostProcessCommon() {
$getRelationship = $this->_params['relationship_type_id_value'];
$type = substr($getRelationship, -3);
$this->relationshipId = intval((substr($getRelationship, 0, strpos($getRelationship, '_'))));
if ($type == 'b_a') {
$this->householdContact = 'contact_id_b';
$this->otherContact = 'contact_id_a';
}
else {
$this->householdContact = 'contact_id_a';
$this->otherContact = 'contact_id_b';
}
}
public function validRelationships() {
$this->relationTypes = $relationTypes = array();
$params = array('contact_type_b' => 'Household', 'version' => 3);
$typesA = civicrm_api('relationship_type', 'get', $params);
if (empty($typesA['is_error'])) {
foreach ($typesA['values'] as $rel) {
$relationTypes[$rel['id']][$rel['id'] . '_b_a'] = $rel['label_b_a'];
}
}
$params = array('contact_type_a' => 'Household', 'version' => 3);
$typesB = civicrm_api('relationship_type', 'get', $params);
if (empty($typesB['is_error'])) {
foreach ($typesB['values'] as $rel) {
$relationTypes[$rel['id']][$rel['id'] . '_a_b'] = $rel['label_a_b'];
//$this->relationTypes[$rel['id'].'_a_b'] = $rel['label_a_b'];
}
}
ksort($relationTypes);
foreach ($relationTypes as $relationship) {
foreach ($relationship as $index => $label) {
$this->relationTypes[$index] = $label;
}
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$type = substr($this->_params['relationship_type_id_value'], -3);
$entryFound = FALSE;
$flagHousehold = $flagContact = 0;
foreach ($rows as $rowNum => $row) {
//replace retionship id by relationship name
if (array_key_exists('civicrm_relationship_relationship_type_id', $row)) {
if ($value = $row['civicrm_relationship_relationship_type_id']) {
$rows[$rowNum]['civicrm_relationship_relationship_type_id'] = $this->relationTypes[$value . '_' . $type];
$entryFound = TRUE;
}
}
//remove duplicate Organization names
if (array_key_exists('civicrm_contact_household_household_name', $row) &&
$this->_outputMode != 'csv'
) {
if ($value = $row['civicrm_contact_household_household_name']) {
if ($rowNum == 0) {
$priviousHousehold = $value;
}
else {
if ($priviousHousehold == $value) {
$flagHousehold = 1;
$priviousHousehold = $value;
}
else {
$flagHousehold = 0;
$priviousHousehold = $value;
}
}
if ($flagHousehold == 1) {
$rows[$rowNum]['civicrm_contact_household_household_name'] = "";
}
else {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $rows[$rowNum]['civicrm_contact_household_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_household_household_name'] = "<a href='$url' title='" . ts('View contact summary for this househould') . "'>" . $value . '</a>';
}
$entryFound = TRUE;
}
}
//remove duplicate Contact names and relationship type
if (array_key_exists('civicrm_contact_id', $row) &&
$this->_outputMode != 'csv'
) {
if ($value = $row['civicrm_contact_id']) {
if ($rowNum == 0) {
$priviousContact = $value;
}
else {
if ($priviousContact == $value) {
$flagContact = 1;
$priviousContact = $value;
}
else {
$flagContact = 0;
$priviousContact = $value;
}
}
if ($flagContact == 1 && $flagHousehold == 1) {
$rows[$rowNum]['civicrm_contact_sort_name'] = "";
$rows[$rowNum]['civicrm_relationship_relationship_type_id'] = "";
}
$entryFound = TRUE;
}
}
if (array_key_exists('civicrm_contribution_contribution_status_id', $row)) {
if ($value = $row['civicrm_contribution_contribution_status_id']) {
$rows[$rowNum]['civicrm_contribution_contribution_status_id'] = CRM_Contribute_PseudoConstant::contributionStatus($value);
}
}
if (array_key_exists('civicrm_contribution_financial_type_id', $row)) {
if ($value = $row['civicrm_contribution_financial_type_id']) {
$rows[$rowNum]['civicrm_contribution_financial_type_id'] = CRM_Contribute_PseudoConstant::financialType($value);
}
}
// handle state province
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($value, FALSE);
}
$entryFound = TRUE;
}
// handle country
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
$rows[$rowNum]['civicrm_contact_sort_name'] &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contribute/detail',
'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts('View contribution details for this individual');
$entryFound = TRUE;
}
if (!empty($row['civicrm_contribution_total_amount'])) {
$row['civicrm_contribution_total_amount'] = CRM_Utils_Money::format($row['civicrm_contribution_total_amount'], $row['civicrm_contribution_currency']);
}
if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
$rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
$entryFound = TRUE;
}
// Contribution amount links to view contribution
if (($value = CRM_Utils_Array::value('civicrm_contribution_total_amount', $row)) &&
CRM_Core_Permission::check('access CiviContribute')
) {
$url = CRM_Utils_System::url("civicrm/contact/view/contribution",
"reset=1&id=" . $row['civicrm_contribution_id'] . "&cid=" .
$row['civicrm_contact_id'] .
"&action=view&context=contribution&selectedChild=contribute",
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contribution_total_amount_link'] = $url;
$rows[$rowNum]['civicrm_contribution_total_amount_hover'] = ts("View this contribution.");
$entryFound = TRUE;
}
// convert campaign_id to campaign title
if (array_key_exists('civicrm_contribution_campaign_id', $row)) {
if ($value = $row['civicrm_contribution_campaign_id']) {
$rows[$rowNum]['civicrm_contribution_campaign_id'] = $this->activeCampaigns[$value];
$entryFound = TRUE;
}
}
// skip looking further in rows, if first row itself doesn't
if (!$entryFound) {
break;
}
$lastKey = $rowNum;
}
}
}

View file

@ -0,0 +1,789 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Contribute_Lybunt extends CRM_Report_Form {
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
/**
* This is the report that links will lead to.
*
* It is a bit problematic to use contribute/detail for anything other than a single contact
* as the filtering from this report does not carry over to that report.
*
* @var array
*/
public $_drilldownReport = array('contribute/detail' => 'Link to Detail Report');
protected $lifeTime_from = NULL;
protected $lifeTime_where = NULL;
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Household',
'Organization',
);
/**
* Table containing list of contact IDs.
*
* @var string
*/
protected $contactTempTable = '';
/**
* This report has been optimised for group filtering.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = FALSE;
/**
* Class constructor.
*/
public function __construct() {
$this->_rollup = 'WITH ROLLUP';
$this->_autoIncludeIndexedFieldsAsOrderBys = 1;
$yearsInPast = 10;
$yearsInFuture = 1;
$date = CRM_Core_SelectValues::date('custom', NULL, $yearsInPast, $yearsInFuture);
$count = $date['maxYear'];
while ($date['minYear'] <= $count) {
$optionYear[$date['minYear']] = $date['minYear'];
$date['minYear']++;
}
// Check if CiviCampaign is a) enabled and b) has active campaigns
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'grouping' => 'contact-field',
'fields' => $this->getBasicContactFields(),
'order_bys' => array(
'sort_name' => array(
'title' => ts('Last Name, First Name'),
'default' => '0',
'default_order' => 'ASC',
),
'first_name' => array(
'name' => 'first_name',
'title' => ts('First Name'),
),
'gender_id' => array(
'name' => 'gender_id',
'title' => ts('Gender'),
),
'birth_date' => array(
'name' => 'birth_date',
'title' => ts('Birth Date'),
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Donor Name'),
'operator' => 'like',
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
'is_deceased' => array(),
'do_not_phone' => array(),
'do_not_email' => array(),
'do_not_sms' => array(),
'do_not_mail' => array(),
'is_opt_out' => array(),
),
),
'civicrm_line_item' => array(
'dao' => 'CRM_Price_DAO_LineItem',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'grouping' => 'contact-field',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'default' => TRUE,
),
'on_hold' => array(
'title' => ts('Email on hold'),
),
),
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'grouping' => 'contact-field',
'fields' => array(
'phone' => array(
'title' => ts('Phone'),
'default' => TRUE,
),
),
),
);
$this->_columns += $this->addAddressFields(FALSE);
$this->_columns += array(
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'contact_id' => array(
'title' => ts('contactId'),
'no_display' => TRUE,
'required' => TRUE,
'no_repeat' => TRUE,
),
'receive_date' => array(
'title' => ts('Year'),
'no_display' => TRUE,
'required' => TRUE,
'no_repeat' => TRUE,
),
'last_year_total_amount' => array(
'title' => ts('Last Year Total'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_MONEY,
'required' => TRUE,
),
'civicrm_life_time_total' => array(
'title' => ts('Lifetime Total'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_MONEY,
'statistics' => array('sum' => ts('Lifetime total')),
),
),
'filters' => array(
'yid' => array(
'name' => 'receive_date',
'title' => ts('This Year'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => $optionYear,
'default' => date('Y'),
'type' => CRM_Utils_Type::T_INT,
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes(),
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => array('1'),
),
),
'order_bys' => array(
'last_year_total_amount' => array(
'title' => ts('Total amount last year'),
'default' => '1',
'default_weight' => '0',
'default_order' => 'DESC',
),
),
),
);
$this->_columns += array(
'civicrm_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
),
),
'filters' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
),
),
);
// If we have a campaign, build out the relevant elements
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_contribution']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
'type' => CRM_Utils_Type::T_INT,
);
$this->_columns['civicrm_contribution']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
}
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
/**
* Build select clause for a single field.
*
* @param string $tableName
* @param string $tableKey
* @param string $fieldName
* @param string $field
*
* @return string
*/
public function selectClause(&$tableName, $tableKey, &$fieldName, &$field) {
if ($fieldName == 'last_year_total_amount') {
$this->_columnHeaders["{$tableName}_{$fieldName}"] = $field;
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $this->getLastYearColumnTitle();
$this->_statFields[$this->getLastYearColumnTitle()] = "{$tableName}_{$fieldName}";
return "SUM(IF(" . $this->whereClauseLastYear('contribution_civireport.receive_date') . ", contribution_civireport.total_amount, 0)) as {$tableName}_{$fieldName}";
}
if ($fieldName == 'civicrm_life_time_total') {
$this->_columnHeaders["{$tableName}_{$fieldName}"] = $field;
$this->_statFields[$field['title']] = "{$tableName}_{$fieldName}";
return "SUM({$this->_aliases[$tableName]}.total_amount) as {$tableName}_{$fieldName}";
}
if ($fieldName == 'receive_date') {
return self::fiscalYearOffset($field['dbAlias']) .
" as {$tableName}_{$fieldName} ";
}
return FALSE;
}
/**
* Get the title for the last year column.
*/
public function getLastYearColumnTitle() {
if ($this->getYearFilterType() == 'calendar') {
return ts('Total for ') . ($this->getCurrentYear() - 1);
}
return ts('Total for Fiscal Year ') . ($this->getCurrentYear() - 1) . '-' . ($this->getCurrentYear());
}
/**
* Construct from clause.
*
* On the first run we are creating a table of contacts to include in the report.
*
* Once contactTempTable is populated we should avoid using any further filters that affect
* the contacts that should be visible.
*/
public function from() {
if (!empty($this->contactTempTable)) {
$this->_from = "
FROM civicrm_contribution {$this->_aliases['civicrm_contribution']}
INNER JOIN $this->contactTempTable restricted_contacts
ON restricted_contacts.cid = {$this->_aliases['civicrm_contribution']}.contact_id
AND {$this->_aliases['civicrm_contribution']}.is_test = 0
INNER JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON restricted_contacts.cid = {$this->_aliases['civicrm_contact']}.id";
if ($this->isTableSelected('civicrm_email')) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id
AND {$this->_aliases['civicrm_email']}.is_primary = 1";
}
if ($this->isTableSelected('civicrm_phone')) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id
AND {$this->_aliases['civicrm_phone']}.is_primary = 1";
}
$this->addAddressFromClause();
}
else {
$this->setFromBase('civicrm_contact');
$this->_from .= " INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']} ";
if (!$this->groupTempTable) {
// The received_date index is better than the contribution_status_id index (fairly substantially).
// But if we have already pre-filtered down to a group of contacts then we want that to be the
// primary filter and the index hint will block that.
$this->_from .= "USE index (received_date)";
}
$this->_from .= " ON {$this->_aliases['civicrm_contribution']}.contact_id = {$this->_aliases['civicrm_contact']}.id
AND {$this->_aliases['civicrm_contribution']}.is_test = 0
AND " . $this->whereClauseLastYear("{$this->_aliases['civicrm_contribution']}.receive_date") . "
{$this->_aclFrom}
LEFT JOIN civicrm_contribution cont_exclude ON cont_exclude.contact_id = {$this->_aliases['civicrm_contact']}.id
AND " . $this->whereClauseThisYear('cont_exclude.receive_date');
$this->selectivelyAddLocationTablesJoinsToFilterQuery();
}
// for credit card type
$this->addFinancialTrxnFromClause();
}
/**
* Generate where clause.
*
* We are overriding this primarily for 'before-after' handling of the receive_date placeholder field.
*
* We call this twice. The first time we are generating a temp table and we want to do an IS NULL on the
* join that draws in contributions from this year. The second time we are filtering elsewhere (contacts via
* the temp table & contributions via selective addition of contributions in the select function).
*
* If lifetime total is NOT selected we can add a further filter here to possibly improve performance
* but the benefit if unproven as yet.
* $clause = $this->whereClauseLastYear("{$this->_aliases['civicrm_contribution']}.receive_date");
*
* @param array $field Field specifications
* @param string $op Query operator (not an exact match to sql)
* @param mixed $value
* @param float $min
* @param float $max
*
* @return null|string
*/
public function whereClause(&$field, $op, $value, $min, $max) {
if ($field['name'] == 'receive_date') {
$clause = 1;
if (empty($this->contactTempTable)) {
$this->_whereClauses[] = "cont_exclude.id IS NULL";
}
}
// Group filtering is already done so skip.
elseif (!empty($field['group']) && $this->contactTempTable) {
return 1;
}
else {
$clause = parent::whereClause($field, $op, $value, $min, $max);
}
return $clause;
}
/**
* Generate where clause for last calendar year or fiscal year.
*
* @todo must be possible to re-use relative dates stuff.
*
* @param string $fieldName
*
* @return string
*/
public function whereClauseLastYear($fieldName) {
return "$fieldName BETWEEN '" . $this->getFirstDateOfPriorRange() . "' AND '" . $this->getLastDateOfPriorRange() . "'";
}
/**
* Generate where clause for last calendar year or fiscal year.
*
* @todo must be possible to re-use relative dates stuff.
*
* @param string $fieldName
*
* @param int $current_year
* @return null|string
*/
public function whereClauseThisYear($fieldName, $current_year = NULL) {
return "$fieldName BETWEEN '" . $this->getFirstDateOfCurrentRange() . "' AND '" . $this->getLastDateOfCurrentRange() . "'";
}
/**
* Get the year value for the current year.
*
* @return string
*/
public function getCurrentYear() {
return $this->_params['yid_value'];
}
/**
* Get the date time of the first date in the 'this year' range.
*
* @return string
*/
public function getFirstDateOfCurrentRange() {
$current_year = $this->getCurrentYear();
if ($this->getYearFilterType() == 'calendar') {
return "{$current_year }-01-01";
}
else {
$fiscalYear = CRM_Core_Config::singleton()->fiscalYearStart;
return "{$current_year}-{$fiscalYear['M']}-{$fiscalYear['d']}";
}
}
/**
* Get the year value for the current year.
*
* @return string
*/
public function getYearFilterType() {
return CRM_Utils_Array::value('yid_op', $this->_params, 'calendar');
}
/**
* Get the date time of the last date in the 'this year' range.
*
* @return string
*/
public function getLastDateOfCurrentRange() {
return date('YmdHis', strtotime('+ 1 year - 1 second', strtotime($this->getFirstDateOfCurrentRange())));
}
/**
* Get the date time of the first date in the 'last year' range.
*
* @return string
*/
public function getFirstDateOfPriorRange() {
return date('YmdHis', strtotime('- 1 year', strtotime($this->getFirstDateOfCurrentRange())));
}
/**
* Get the date time of the last date in the 'last year' range.
*
* @return string
*/
public function getLastDateOfPriorRange() {
return date('YmdHis', strtotime('+ 1 year - 1 second', strtotime($this->getFirstDateOfPriorRange())));
}
public function groupBy() {
$this->_groupBy = "GROUP BY {$this->_aliases['civicrm_contribution']}.contact_id ";
$this->_select = CRM_Contact_BAO_Query::appendAnyValueToSelect($this->_selectClauses, "{$this->_aliases['civicrm_contribution']}.contact_id");
$this->assign('chartSupported', TRUE);
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
// The parent class does something odd where it adds an extra row to the count for the grand total.
// Perhaps that works on some other report? But here it just seems odd.
$this->countStat($statistics, count($rows));
if (!empty($rows)) {
if (!empty($this->rollupRow) && !empty($this->rollupRow['civicrm_contribution_last_year_total_amount'])) {
$statistics['counts']['civicrm_contribution_last_year_total_amount'] = array(
'value' => $this->rollupRow['civicrm_contribution_last_year_total_amount'],
'title' => $this->getLastYearColumnTitle(),
'type' => CRM_Utils_Type::T_MONEY,
);
}
if (!empty($this->rollupRow) && !empty($this->rollupRow['civicrm_contribution_civicrm_life_time_total'])) {
$statistics['counts']['civicrm_contribution_civicrm_life_time_total'] = array(
'value' => $this->rollupRow['civicrm_contribution_civicrm_life_time_total'],
'title' => ts('Total LifeTime'),
'type' => CRM_Utils_Type::T_MONEY,
);
}
else {
$select = "SELECT SUM({$this->_aliases['civicrm_contribution']}.total_amount) as amount,
SUM(IF( " . $this->whereClauseLastYear('contribution_civireport.receive_date') . ", contribution_civireport.total_amount, 0)) as last_year
";
$sql = "{$select} {$this->_from} {$this->_where}";
$dao = CRM_Core_DAO::executeQuery($sql);
if ($dao->fetch()) {
$statistics['counts']['amount'] = array(
'value' => $dao->amount,
'title' => ts('Total LifeTime'),
'type' => CRM_Utils_Type::T_MONEY,
);
$statistics['counts']['last_year'] = array(
'value' => $dao->last_year,
'title' => $this->getLastYearColumnTitle(),
'type' => CRM_Utils_Type::T_MONEY,
);
}
}
}
return $statistics;
}
/**
* This function is called by both the api (tests) and the UI.
*/
public function beginPostProcessCommon() {
$this->buildQuery();
// @todo this acl has no test coverage and is very hard to test manually so could be fragile.
$this->resetFormSqlAndWhereHavingClauses();
$this->contactTempTable = 'civicrm_report_temp_lybunt_c_' . date('Ymd_') . uniqid();
$this->limit();
$getContacts = "
CREATE TEMPORARY TABLE $this->contactTempTable {$this->_databaseAttributes}
SELECT SQL_CALC_FOUND_ROWS {$this->_aliases['civicrm_contact']}.id as cid {$this->_from} {$this->_where}
GROUP BY {$this->_aliases['civicrm_contact']}.id";
$this->executeReportQuery($getContacts);
if (empty($this->_params['charts'])) {
$this->setPager();
}
// Reset where clauses to be regenerated in postProcess.
$this->_whereClauses = array();
}
/**
* Build the report query.
*
* The issue we are hitting is that if we want to do group by & then ORDER BY we have to
* wrap the query in an outer query with the order by - otherwise the group by takes precedent.
* This is an issue when we want to group by contact but order by the maximum aggregate donation.
*
* @param bool $applyLimit
*
* @return string
*/
public function buildQuery($applyLimit = TRUE) {
$this->buildGroupTempTable();
$this->buildPermissionClause();
// Calling where & select before FROM allows us to build temp tables to use in from.
$this->where();
$this->select();
$this->from();
$this->customDataFrom(empty($this->contactTempTable));
$this->groupBy();
$this->orderBy();
$this->getPermissionedFTQuery($this);
$limitFilter = '';
// order_by columns not selected for display need to be included in SELECT
// This differs from parent in that we are getting those not in order by rather than not in
// sections, as we need to adapt to our contact group by.
$unselectedSectionColumns = array_diff_key($this->_orderByFields, $this->getSelectColumns());
foreach ($unselectedSectionColumns as $alias => $section) {
$this->_select .= ", {$section['dbAlias']} as {$alias}";
}
if ($applyLimit && empty($this->_params['charts'])) {
$this->limit();
}
$sql = "{$this->_select} {$this->_from} {$this->_where} {$limitFilter} {$this->_groupBy} {$this->_having} {$this->_rollup}";
if (!empty($this->_orderByArray)) {
$this->_orderBy = str_replace('contact_civireport.', 'civicrm_contact_', "ORDER BY ISNULL(civicrm_contribution_contact_id), " . implode(', ', $this->_orderByArray));
$this->_orderBy = str_replace('contribution_civireport.', 'civicrm_contribution_', $this->_orderBy);
foreach ($this->_orderByFields as $field) {
$this->_orderBy = str_replace($field['dbAlias'], $field['tplField'], $this->_orderBy);
}
$sql = str_replace('SQL_CALC_FOUND_ROWS', '', $sql);
$sql = "SELECT SQL_CALC_FOUND_ROWS * FROM ( $sql ) as inner_query {$this->_orderBy} $this->_limit";
}
CRM_Utils_Hook::alterReportVar('sql', $this, $this);
$this->addToDeveloperTab($sql);
return $sql;
}
/**
* Reset the form sql and where / having clause arrays.
*
* We do an early iteration of the report queries to generate the temp table.
*
* However, that iteration populates the sql for the developer tab,
* the whereClauses & the havingClauses and they are populated again in the normal
* report flow. This is harmless but confusing - ie. the where clause winds up repeating
* the same filters and the dev tab shows the query twice, so we rest them.
*/
protected function resetFormSqlAndWhereHavingClauses() {
$this->sql = '';
$this->_havingClauses = array();
$this->_whereClauses = array();
$this->sqlArray = array();
}
/**
* @param $rows
*/
public function buildChart(&$rows) {
$graphRows = array();
$count = 0;
$display = array();
$current_year = $this->_params['yid_value'];
$previous_year = $current_year - 1;
$interval[$previous_year] = $previous_year;
$interval['life_time'] = 'Life Time';
foreach ($rows as $key => $row) {
$display['life_time'] = CRM_Utils_Array::value('life_time', $display) +
$row['civicrm_life_time_total'];
$display[$previous_year] = CRM_Utils_Array::value($previous_year, $display) + $row[$previous_year];
}
$config = CRM_Core_Config::Singleton();
$graphRows['value'] = $display;
$chartInfo = array(
'legend' => ts('Lybunt Report'),
'xname' => ts('Year'),
'yname' => ts('Amount (%1)', array(1 => $config->defaultCurrency)),
);
if ($this->_params['charts']) {
// build chart.
CRM_Utils_OpenFlashChart::reportChart($graphRows, $this->_params['charts'], $interval, $chartInfo);
$this->assign('chartType', $this->_params['charts']);
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
//Convert Display name into link
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contribution_contact_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contribute/detail',
'reset=1&force=1&id_op=eq&id_value=' .
$row['civicrm_contribution_contact_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contribution Details for this Contact.");
$entryFound = TRUE;
}
// convert campaign_id to campaign title
if (array_key_exists('civicrm_contribution_campaign_id', $row)) {
if ($value = $row['civicrm_contribution_campaign_id']) {
$rows[$rowNum]['civicrm_contribution_campaign_id'] = $this->activeCampaigns[$value];
$entryFound = TRUE;
}
}
// Display 'Yes' if the email is on hold (leave blank for no so it stands out better).
if (array_key_exists('civicrm_email_on_hold', $row)) {
$rows[$rowNum]['civicrm_email_on_hold'] = $row['civicrm_email_on_hold'] ? ts('Yes') : '';
$entryFound = TRUE;
}
$entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, NULL, 'List all contribution(s)') ? TRUE : $entryFound;
$entryFound = $this->alterDisplayContactFields($row, $rows, $rowNum, NULL, 'List all contribution(s)') ? TRUE : $entryFound;
//handle gender
if (array_key_exists('civicrm_contact_gender_id', $row)) {
if ($value = $row['civicrm_contact_gender_id']) {
$gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
$rows[$rowNum]['civicrm_contact_gender_id'] = $gender[$value];
}
$entryFound = TRUE;
}
// display birthday in the configured custom format
if (array_key_exists('civicrm_contact_birth_date', $row)) {
$birthDate = $row['civicrm_contact_birth_date'];
if ($birthDate) {
$rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
}
$entryFound = TRUE;
}
if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
$rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
/**
* Override "This Year" $op options
* @param string $type
* @param null $fieldName
*
* @return array
*/
public function getOperationPair($type = "string", $fieldName = NULL) {
if ($fieldName == 'yid') {
return array(
'calendar' => ts('Is Calendar Year'),
'fiscal' => ts('Fiscal Year Starting'),
);
}
return parent::getOperationPair($type, $fieldName);
}
}

View file

@ -0,0 +1,607 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Contribute_OrganizationSummary extends CRM_Report_Form {
protected $_addressField = FALSE;
protected $_emailField = FALSE;
public $_drilldownReport = array('contribute/detail' => 'Link to Detail Report');
protected $_summary = NULL;
/**
* Organisation contact ie. 'contact_id_b' or 'contact_id_a'
* @var string
*/
protected $orgContact;
/**
* Related Contact ie. 'contact_id_b' or 'contact_id_a'
* @var string
*/
protected $otherContact;
/**
*/
/**
*/
public function __construct() {
self::validRelationships();
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array('CiviCampaign', $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
$this->_columns = array(
'civicrm_contact_organization' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'organization_name' => array(
'title' => ts('Organization Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => array(
'organization_name' => array('title' => ts('Organization Name')),
),
'grouping' => 'organization-fields',
),
'civicrm_line_item' => array(
'dao' => 'CRM_Price_DAO_LineItem',
),
'civicrm_relationship' => array(
'dao' => 'CRM_Contact_DAO_Relationship',
'fields' => array(
'relationship_type_id' => array(
'title' => ts('Relationship Type'),
),
),
'filters' => array(
'relationship_type_id' => array(
'title' => ts('Relationship Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => $this->relationTypes,
'default' => key($this->relationTypes),
),
),
'grouping' => 'organization-fields',
),
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'total_amount' => array(
'title' => ts('Amount'),
'required' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'default' => TRUE,
),
'check_number' => array(
'title' => ts('Check Number'),
),
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'trxn_id' => NULL,
'receive_date' => array('default' => TRUE),
'receipt_date' => NULL,
),
'filters' => array(
'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'total_amount' => array('title' => ts('Amount Between')),
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => array(1),
),
),
'grouping' => 'contri-fields',
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'fields' => array(
'street_address' => NULL,
'city' => NULL,
'postal_code' => NULL,
'state_province_id' => array(
'title' => ts('State/Province'),
),
'country_id' => array(
'title' => ts('Country'),
),
),
'grouping' => 'contact-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array('email' => NULL),
'grouping' => 'contact-fields',
),
'civicrm_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
),
),
'filters' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
),
),
);
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_contribution']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
);
$this->_columns['civicrm_contribution']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
}
$this->_currencyColumn = 'civicrm_contribution_currency';
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$this->_columnHeaders = $select = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) || !empty($this->_params['fields'][$fieldName])) {
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
}
elseif ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
if (!empty($field['statistics'])) {
foreach ($field['statistics'] as $stat => $label) {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
}
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
}
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$this->_from = NULL;
$this->_from = "
FROM civicrm_relationship {$this->_aliases['civicrm_relationship']}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact_organization']} ON
({$this->_aliases['civicrm_contact_organization']}.id = {$this->_aliases['civicrm_relationship']}.$this->orgContact AND {$this->_aliases['civicrm_contact_organization']}.contact_type='Organization')
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']} ON
({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_relationship']}.$this->otherContact )
{$this->_aclFrom}
INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']} ON
({$this->_aliases['civicrm_contribution']}.contact_id = {$this->_aliases['civicrm_relationship']}.$this->otherContact ) AND {$this->_aliases['civicrm_contribution']}.is_test = 0 ";
if ($this->_addressField) {
$this->_from .= "
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']} ON
{$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1\n ";
}
if ($this->_emailField) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']} ON
{$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1\n ";
}
// for credit card type
$this->addFinancialTrxnFromClause();
}
public function where() {
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
if ($fieldName == 'relationship_type_id') {
$clause = "{$this->_aliases['civicrm_relationship']}.relationship_type_id=" . $this->relationshipId;
}
else {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE ( 1 )";
}
else {
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
public function groupBy() {
$groupBy = array(
"{$this->_aliases['civicrm_relationship']}.$this->orgContact",
"{$this->_aliases['civicrm_relationship']}.$this->otherContact",
"{$this->_aliases['civicrm_contribution']}.id",
"{$this->_aliases['civicrm_relationship']}.relationship_type_id",
);
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
public function orderBy() {
$this->_orderBy = " ORDER BY {$this->_aliases['civicrm_contact_organization']}.organization_name, {$this->_aliases['civicrm_relationship']}.$this->orgContact, {$this->_aliases['civicrm_contact']}.sort_name, {$this->_aliases['civicrm_relationship']}.$this->otherContact";
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
//hack filter display for relationship type
$type = substr($this->_params['relationship_type_id_value'], -3);
foreach ($statistics['filters'] as $id => $value) {
if ($value['title'] == 'Relationship Type' && !empty($id)) {
$statistics['filters'][$id]['value'] = 'Is equal to ' .
$this->relationTypes[$this->relationshipId . '_' . $type];
}
}
return $statistics;
}
public function postProcess() {
$this->beginPostProcess();
$this->buildACLClause(array($this->_aliases['civicrm_contact'], $this->_aliases['civicrm_contact_organization']));
$sql = $this->buildQuery(TRUE);
$rows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* Set variables to be accessed by API and form layer in processing.
*/
public function beginPostProcessCommon() {
$getRelationship = $this->_params['relationship_type_id_value'];
$type = substr($getRelationship, -3);
$this->relationshipId = intval((substr($getRelationship, 0, strpos($getRelationship, '_'))));
if ($type == 'b_a') {
$this->orgContact = 'contact_id_b';
$this->otherContact = 'contact_id_a';
}
else {
$this->orgContact = 'contact_id_a';
$this->otherContact = 'contact_id_b';
}
}
public function validRelationships() {
$this->relationTypes = $relationTypes = array();
$params = array('contact_type_b' => 'Organization', 'version' => 3);
$typesA = civicrm_api('relationship_type', 'get', $params);
if (empty($typesA['is_error'])) {
foreach ($typesA['values'] as $rel) {
$relationTypes[$rel['id']][$rel['id'] . '_b_a'] = $rel['label_b_a'];
}
}
$params = array('contact_type_a' => 'Organization', 'version' => 3);
$typesB = civicrm_api('relationship_type', 'get', $params);
if (empty($typesB['is_error'])) {
foreach ($typesB['values'] as $rel) {
$relationTypes[$rel['id']][$rel['id'] . '_a_b'] = $rel['label_a_b'];
}
}
ksort($relationTypes);
foreach ($relationTypes as $relationship) {
foreach ($relationship as $index => $label) {
$this->relationTypes[$index] = $label;
}
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$type = substr($this->_params['relationship_type_id_value'], -3);
$entryFound = FALSE;
$flagOrganization = $flagContact = 0;
foreach ($rows as $rowNum => $row) {
//replace retionship id by relationship name
if (array_key_exists('civicrm_relationship_relationship_type_id', $row)) {
if ($value = $row['civicrm_relationship_relationship_type_id']) {
$rows[$rowNum]['civicrm_relationship_relationship_type_id'] = $this->relationTypes[$value . '_' . $type];
$entryFound = TRUE;
}
}
//remove duplicate Organization names
if (array_key_exists('civicrm_contact_organization_id', $row) && $this->_outputMode != 'csv') {
if ($value = $row['civicrm_contact_organization_id']) {
if ($rowNum == 0) {
$previousOrganization = $value;
}
else {
if ($previousOrganization == $value) {
$flagOrganization = 1;
$previousOrganization = $value;
}
else {
$flagOrganization = 0;
$previousOrganization = $value;
}
}
if ($flagOrganization == 1) {
foreach ($row as $colName => $colVal) {
if (in_array($colName, $this->_noRepeats)) {
unset($rows[$rowNum][$colName]);
}
}
}
$entryFound = TRUE;
}
}
// convert Organization display name to links
if (array_key_exists('civicrm_contact_organization_organization_name', $row) && !empty($rows[$rowNum]['civicrm_contact_organization_organization_name']) &&
array_key_exists('civicrm_contact_organization_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' .
$rows[$rowNum]['civicrm_contact_organization_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_organization_organization_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_organization_organization_name_hover'] = ts('View contact summary for this organization.');
}
//remove duplicate Contact names and relationship type
if (array_key_exists('civicrm_contact_id', $row) && $this->_outputMode != 'csv') {
if ($value = $row['civicrm_contact_id']) {
if ($rowNum == 0) {
$previousContact = $value;
}
else {
if ($previousContact == $value) {
$flagContact = 1;
$previousContact = $value;
}
else {
$flagContact = 0;
$previousContact = $value;
}
}
if ($flagContact == 1 && $flagOrganization == 1) {
$rows[$rowNum]['civicrm_contact_sort_name'] = "";
$rows[$rowNum]['civicrm_relationship_relationship_type_id'] = "";
}
$entryFound = TRUE;
}
}
if (array_key_exists('civicrm_contribution_contribution_status_id', $row)) {
if ($value = $row['civicrm_contribution_contribution_status_id']) {
$rows[$rowNum]['civicrm_contribution_contribution_status_id'] = CRM_Contribute_PseudoConstant::contributionStatus($value);
}
}
// handle state province
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($value, FALSE);
}
$entryFound = TRUE;
}
// handle country
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
$rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
$entryFound = TRUE;
}
// convert Individual display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
$rows[$rowNum]['civicrm_contact_sort_name'] &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contribute/detail',
'reset=1&force=1&id_op=eq&id_value=' .
$row['civicrm_contact_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts('View contribution details for this individual');
$entryFound = TRUE;
}
// Contribution amount links to view contribution
if (($value = CRM_Utils_Array::value('civicrm_contribution_total_amount', $row)) &&
CRM_Core_Permission::check('access CiviContribute')
) {
$url = CRM_Utils_System::url('civicrm/contact/view/contribution',
"reset=1&id=" . $row['civicrm_contribution_id'] . "&cid=" . $row['civicrm_contact_id'] .
"&action=view&context=contribution&selectedChild=contribute",
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contribution_total_amount_link'] = $url;
$rows[$rowNum]['civicrm_contribution_total_amount_hover'] = ts('View this contribution.');
$entryFound = TRUE;
}
// convert campaign_id to campaign title
if (array_key_exists('civicrm_contribution_campaign_id', $row)) {
if ($value = $row['civicrm_contribution_campaign_id']) {
$rows[$rowNum]['civicrm_contribution_campaign_id'] = $this->activeCampaigns[$value];
$entryFound = TRUE;
}
}
// skip looking further in rows, if first row itself doesn't
if (!$entryFound) {
break;
}
$lastKey = $rowNum;
}
}
}

View file

@ -0,0 +1,418 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Contribute_PCP extends CRM_Report_Form {
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Supporter'),
'required' => TRUE,
'default' => TRUE,
),
'id' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'contact_type' => array(
'title' => ts('Supporter Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Supporter Contact Subtype'),
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Supporter Name'),
'type' => CRM_Utils_Type::T_STRING,
'operator' => 'like',
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
),
'grouping' => 'pcp-fields',
),
'civicrm_contribution_page' => array(
'dao' => 'CRM_Contribute_DAO_ContributionPage',
'alias' => 'cp',
'fields' => array(
'page_title' => array(
'title' => ts('Page Title'),
'name' => 'title',
'dbAlias' => 'coalesce(cp_civireport.title, e_civireport.title)',
'default' => TRUE,
),
),
'filters' => array(
'page_title' => array(
'title' => ts('Contribution Page Title'),
'name' => 'title',
'type' => CRM_Utils_Type::T_STRING,
),
),
'grouping' => 'pcp-fields',
),
'civicrm_event' => array(
'alias' => 'e',
'filters' => array(
'event_title' => array(
'title' => ts('Event Title'),
'name' => 'title',
'type' => CRM_Utils_Type::T_STRING,
),
),
'grouping' => 'pcp-fields',
),
'civicrm_pcp' => array(
'dao' => 'CRM_PCP_DAO_PCP',
'fields' => array(
'title' => array(
'title' => ts('Personal Campaign Title'),
'default' => TRUE,
),
'page_type' => array(
'title' => ts('Page Type'),
'default' => FALSE,
),
'goal_amount' => array(
'title' => ts('Goal Amount'),
'type' => CRM_Utils_Type::T_MONEY,
'default' => TRUE,
),
),
'filters' => array(
'title' => array(
'title' => ts('Personal Campaign Title'),
'type' => CRM_Utils_Type::T_STRING,
),
),
'grouping' => 'pcp-fields',
),
'civicrm_contribution_soft' => array(
'dao' => 'CRM_Contribute_DAO_ContributionSoft',
'fields' => array(
'amount_1' => array(
'title' => ts('Committed Amount'),
'name' => 'amount',
'type' => CRM_Utils_Type::T_MONEY,
'default' => TRUE,
'statistics' => array(
'sum' => ts('Committed Amount'),
),
),
'amount_2' => array(
'title' => ts('Amount Received'),
'name' => 'amount',
'type' => CRM_Utils_Type::T_MONEY,
'default' => TRUE,
// nice trick with dbAlias
'dbAlias' => 'SUM(IF( contribution_civireport.contribution_status_id > 1, 0, contribution_soft_civireport.amount))',
),
'soft_id' => array(
'title' => ts('Number of Donors'),
'name' => 'id',
'default' => TRUE,
'statistics' => array(
'count' => ts('Number of Donors'),
),
),
),
'filters' => array(
'amount_2' => array(
'title' => ts('Amount Received'),
'type' => CRM_Utils_Type::T_MONEY,
'dbAlias' => 'SUM(IF( contribution_civireport.contribution_status_id > 1, 0, contribution_soft_civireport.amount))',
),
),
'grouping' => 'pcp-fields',
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'contribution_id' => array(
'name' => 'id',
'no_display' => TRUE,
'required' => TRUE,
),
'receive_date' => array(
'title' => ts('Most Recent Contribution'),
'default' => TRUE,
'statistics' => array(
'max' => ts('Most Recent Contribution'),
),
),
),
'grouping' => 'pcp-fields',
),
'civicrm_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
),
),
'filters' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
),
),
);
parent::__construct();
}
public function from() {
$this->_from = "
FROM civicrm_pcp {$this->_aliases['civicrm_pcp']}
LEFT JOIN civicrm_contribution_soft {$this->_aliases['civicrm_contribution_soft']}
ON {$this->_aliases['civicrm_pcp']}.id =
{$this->_aliases['civicrm_contribution_soft']}.pcp_id
LEFT JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON {$this->_aliases['civicrm_contribution_soft']}.contribution_id =
{$this->_aliases['civicrm_contribution']}.id
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON {$this->_aliases['civicrm_pcp']}.contact_id =
{$this->_aliases['civicrm_contact']}.id
LEFT JOIN civicrm_contribution_page {$this->_aliases['civicrm_contribution_page']}
ON {$this->_aliases['civicrm_pcp']}.page_id =
{$this->_aliases['civicrm_contribution_page']}.id
AND {$this->_aliases['civicrm_pcp']}.page_type = 'contribute'
LEFT JOIN civicrm_event {$this->_aliases['civicrm_event']}
ON {$this->_aliases['civicrm_pcp']}.page_id =
{$this->_aliases['civicrm_event']}.id
AND {$this->_aliases['civicrm_pcp']}.page_type = 'event'";
// for credit card type
$this->addFinancialTrxnFromClause();
}
public function groupBy() {
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, "{$this->_aliases['civicrm_pcp']}.id");
}
public function orderBy() {
$this->_orderBy = " ORDER BY {$this->_aliases['civicrm_contact']}.sort_name ";
}
public function where() {
$whereClauses = $havingClauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
if ($tableName == 'civicrm_contribution_soft' &&
$fieldName == 'amount_2'
) {
$havingClauses[] = $clause;
}
else {
$whereClauses[] = $clause;
}
}
}
}
}
if (empty($whereClauses)) {
$this->_where = "WHERE ( 1 ) ";
}
else {
$this->_where = "WHERE " . implode(' AND ', $whereClauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
$this->_having = "";
if (!empty($havingClauses)) {
// use this clause to construct group by clause.
$this->_having = "HAVING " . implode(' AND ', $havingClauses);
}
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
// Calculate totals from the civicrm_contribution_soft table.
$select = "SELECT SUM({$this->_aliases['civicrm_contribution_soft']}.amount) "
. "as committed_total, COUNT({$this->_aliases['civicrm_contribution_soft']}.id) "
. "as donors_total, SUM(IF( contribution_civireport.contribution_status_id > 1, 0, "
. "contribution_soft_civireport.amount)) AS received_total ";
$sql = "{$select} {$this->_from} {$this->_where}";
$dao = CRM_Core_DAO::executeQuery($sql);
$dao->fetch();
$committed_total = $dao->committed_total;
$received_total = $dao->received_total;
$donors_total = $dao->donors_total;
// Calculate goal total goal from the PCP table (we only want one result per
// PCP page - the query above produces one result per contribution made).
$sql = "SELECT SUM(goal_amount) as goal_total FROM civicrm_pcp WHERE "
. "goal_amount IS NOT NULL AND id IN ("
. "SELECT DISTINCT {$this->_aliases['civicrm_pcp']}.id {$this->_from} "
. "{$this->_where}"
. ")";
$dao = CRM_Core_DAO::executeQuery($sql);
$dao->fetch();
$goal_total = $dao->goal_total;
$statistics['counts']['goal_total'] = array(
'title' => ts('Goal Total'),
'value' => $goal_total,
'type' => CRM_Utils_Type::T_MONEY,
);
$statistics['counts']['committed_total'] = array(
'title' => ts('Total Committed'),
'value' => $committed_total,
'type' => CRM_Utils_Type::T_MONEY,
);
$statistics['counts']['received_total'] = array(
'title' => ts('Total Received'),
'value' => $received_total,
'type' => CRM_Utils_Type::T_MONEY,
);
$statistics['counts']['donors_total'] = array(
'title' => ts('Total Donors'),
'value' => $donors_total,
'type' => CRM_Utils_Type::T_INT,
);
return $statistics;
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$checkList = array();
foreach ($rows as $rowNum => $row) {
if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
// not repeat contact sort names if it matches with the one
// in previous row
$repeatFound = FALSE;
foreach ($row as $colName => $colVal) {
if (!empty($checkList[$colName]) &&
is_array($checkList[$colName]) &&
in_array($colVal, $checkList[$colName])
) {
$rows[$rowNum][$colName] = "";
$repeatFound = TRUE;
}
if (in_array($colName, $this->_noRepeats)) {
$checkList[$colName][] = $colVal;
}
}
}
if (array_key_exists('civicrm_contact_sort_name', $row) &&
$rows[$rowNum]['civicrm_contact_sort_name'] &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url("civicrm/contact/view",
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact Summary for this Contact.");
$entryFound = TRUE;
}
if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
$rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
$entryFound = TRUE;
}
if (!empty($row['civicrm_pcp_page_type'])) {
$rows[$rowNum]['civicrm_pcp_page_type'] = ucfirst($rows[$rowNum]['civicrm_pcp_page_type']);
$entryFound = TRUE;
}
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,401 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Contribute_Recur extends CRM_Report_Form {
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'order_bys' => array(
'sort_name' => array(
'title' => ts("Last name, First name"),
),
),
'fields' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'no_repeat' => TRUE,
'default' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array(
'phone' => array(
'title' => ts('Phone'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'total_amount' => array(
'title' => ts('Amount Contributed to Date'),
'statistics' => array(
'sum' => ts("Total Amount Contributed"),
),
),
),
),
'civicrm_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
),
),
'filters' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
),
),
'civicrm_contribution_recur' => array(
'dao' => 'CRM_Contribute_DAO_ContributionRecur',
'fields' => array(
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'currency' => array(
'title' => ts("Currency"),
'required' => TRUE,
'no_display' => TRUE,
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
),
'frequency_interval' => array(
'title' => ts('Frequency interval'),
'default' => TRUE,
),
'frequency_unit' => array(
'title' => ts('Frequency unit'),
'default' => TRUE,
),
'amount' => array(
'title' => ts('Installment Amount'),
'default' => TRUE,
),
'installments' => array(
'title' => ts('Installments'),
'default' => TRUE,
),
'start_date' => array(
'title' => ts('Start Date'),
),
'create_date' => array(
'title' => ts('Create Date'),
),
'modified_date' => array(
'title' => ts('Modified Date'),
),
'cancel_date' => array(
'title' => ts('Cancel Date'),
),
'end_date' => array(
'title' => ts('End Date'),
),
'next_sched_contribution_date' => array(
'title' => ts('Next Scheduled Contribution Date'),
),
'failure_count' => array(
'title' => ts('Failure Count'),
),
'failure_retry_date' => array(
'title' => ts('Failure Retry Date'),
),
),
'filters' => array(
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => array(5),
'type' => CRM_Utils_Type::T_INT,
),
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes(),
'type' => CRM_Utils_Type::T_INT,
),
'frequency_unit' => array(
'title' => ts('Frequency Unit'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('recur_frequency_units'),
'type' => CRM_Utils_Type::T_STRING,
),
'frequency_interval' => array(
'title' => ts('Frequency Interval'),
'type' => CRM_Utils_Type::T_INT,
),
'amount' => array(
'title' => ts('Installment Amount'),
'type' => CRM_Utils_Type::T_MONEY,
),
'installments' => array(
'title' => ts('Installments'),
'type' => CRM_Utils_Type::T_INT,
),
'start_date' => array(
'title' => ts('Start Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
),
'next_sched_contribution_date' => array(
'title' => ts('Next Scheduled Contribution Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
),
'end_date' => array(
'title' => ts('End Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
),
'modified_date' => array(
'title' => ts('Last Contribution Processed'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE + CRM_Utils_Type::T_TIME,
),
'calculated_end_date' => array(
'title' => ts('Calculated end date (either end date or date all installments will be made)'),
'description' => "does this work?",
'operatorType' => CRM_Report_Form::OP_DATE,
'pseudofield' => TRUE,
),
),
),
);
$this->_currencyColumn = 'civicrm_contribution_recur_currency';
$this->_groupFilter = TRUE;
parent::__construct();
}
/**
* Get template file name.
*
* @return string
*/
public function getTemplateName() {
return 'CRM/Report/Form.tpl';
}
/**
* Generate FROM SQL clause.
*/
public function from() {
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']}
INNER JOIN civicrm_contribution_recur {$this->_aliases['civicrm_contribution_recur']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_contribution_recur']}.contact_id";
$this->_from .= "
LEFT JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON {$this->_aliases['civicrm_contribution_recur']}.id = {$this->_aliases['civicrm_contribution']}.contribution_recur_id";
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1)";
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1)";
// for credit card type
$this->addFinancialTrxnFromClause();
}
public function groupBy() {
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, "{$this->_aliases['civicrm_contribution_recur']}.id");
}
public function where() {
parent::where();
// Handle calculated end date. This can come from one of two sources:
// Either there is a specified end date for the end_date field
// Or, we calculate the end date based on the start date +
// installments * intervals using the mysql date_add function, along
// with the interval unit (e.g. DATE_ADD(start_date, INTERVAL 12 * 1 MONTH)
$date_suffixes = array('relative', 'from', 'to');
while (list(, $suffix) = each($date_suffixes)) {
$isBreak = FALSE;
// Check to see if the user wants to search by calculated date.
if (!empty($this->_params['calculated_end_date_' . $suffix])) {
// The calculated date field is in use - spring into action
// Gather values
$relative = CRM_Utils_Array::value("calculated_end_date_relative", $this->_params);
$from = CRM_Utils_Array::value("calculated_end_date_from", $this->_params);
$to = CRM_Utils_Array::value("calculated_end_date_to", $this->_params);
$end_date_db_alias = $this->_columns['civicrm_contribution_recur']['filters']['end_date']['dbAlias'];
$end_date_type = $this->_columns['civicrm_contribution_recur']['filters']['end_date']['type'];
$start_date_type = $this->_columns['civicrm_contribution_recur']['filters']['start_date']['type'];
$frequency_unit_db_alias = $this->_columns['civicrm_contribution_recur']['filters']['frequency_unit']['dbAlias'];
$frequency_interval_db_alias = $this->_columns['civicrm_contribution_recur']['filters']['frequency_interval']['dbAlias'];
$installments_db_alias = $this->_columns['civicrm_contribution_recur']['filters']['installments']['dbAlias'];
$start_date_db_alias = $this->_columns['civicrm_contribution_recur']['filters']['start_date']['dbAlias'];
// The end date clause is simple to construct
$end_date_clause = $this->dateClause($end_date_db_alias, $relative, $from, $to, $end_date_type, NULL, NULL);
// NOTE: For the calculation based on installment, there doesn't
// seem to be a way to include the interval unit (e.g. month,
// date, etc) as a field name - so we have to build a complex
// OR statement instead.
$this->_where .= 'AND (' .
$this->dateClause("DATE_ADD($start_date_db_alias, INTERVAL $installments_db_alias * COALESCE($frequency_interval_db_alias,1) month)",
$relative, $from, $to, $start_date_type, NULL, NULL);
$this->_where .= " AND $frequency_unit_db_alias = 'month' ) OR \n";
$this->_where .= '(' .
$this->dateClause("DATE_ADD($start_date_db_alias, INTERVAL $installments_db_alias * COALESCE($frequency_interval_db_alias,1) day)",
$relative, $from, $to, $start_date_type, NULL, NULL);
$this->_where .= " AND $frequency_unit_db_alias = 'day' ) OR \n";
$this->_where .= '(' .
$this->dateClause("DATE_ADD($start_date_db_alias, INTERVAL $installments_db_alias * COALESCE($frequency_interval_db_alias, 1) week)",
$relative, $from, $to, $start_date_type, NULL, NULL);
$this->_where .= " AND $frequency_unit_db_alias = 'week' ) OR \n";
$this->_where .= '(' .
$this->dateClause("DATE_ADD($start_date_db_alias, INTERVAL $installments_db_alias * COALESCE($frequency_interval_db_alias, 1) year)",
$relative, $from, $to, $start_date_type, NULL, NULL);
$this->_where .= " AND $frequency_unit_db_alias = 'year' )
AND (($end_date_db_alias IS NOT NULL AND $end_date_clause)
OR ($installments_db_alias IS NOT NULL))
";
$isBreak = TRUE;
}
if (!empty($this->_params['modified_date_' . $suffix])) {
$this->_where .= " AND {$this->_aliases['civicrm_contribution_recur']}.contribution_status_id = 1";
$isBreak = TRUE;
}
if (!empty($isBreak)) {
break;
}
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus();
foreach ($rows as $rowNum => $row) {
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
CRM_Utils_Array::value('civicrm_contact_sort_name', $rows[$rowNum]) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts('View Contact Summary for this Contact.');
}
// handle contribution status id
if ($value = CRM_Utils_Array::value('civicrm_contribution_recur_contribution_status_id', $row)) {
$rows[$rowNum]['civicrm_contribution_recur_contribution_status_id'] = $contributionStatus[$value];
}
if ($value = CRM_Utils_Array::value('civicrm_contribution_recur_amount', $row)) {
$rows[$rowNum]['civicrm_contribution_recur_amount'] = CRM_Utils_Money::format($rows[$rowNum]['civicrm_contribution_recur_amount'], $rows[$rowNum]['civicrm_contribution_recur_currency']);
}
if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
$rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
}
}
}
}

View file

@ -0,0 +1,344 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Contribute_RecurSummary extends CRM_Report_Form {
/**
*/
public function __construct() {
$this->_columns = array(
'civicrm_contribution_recur' => array(
'dao' => 'CRM_Contribute_DAO_ContributionRecur',
'fields' => array(
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'payment_instrument_id' => array(
'title' => ts('Payment Instrument'),
'default' => TRUE,
'required' => TRUE,
),
'start_date' => array(
'title' => ts('Started'),
'default' => TRUE,
'required' => TRUE,
),
'cancel_date' => array(
'title' => ts('Cancelled'),
'default' => TRUE,
'required' => TRUE,
),
'contribution_status_id' => array(
'title' => ts('Active'),
'default' => TRUE,
'required' => TRUE,
),
'amount' => array(
'title' => ts('Total Amount'),
'default' => TRUE,
'required' => TRUE,
),
),
'filters' => array(
'start_date' => array(
'title' => ts('Start Date'),
'operatorType' => CRM_Report_Form::OP_DATETIME,
'type' => CRM_Utils_Type::T_TIME,
),
),
),
);
$this->_currencyColumn = 'civicrm_contribution_recur_currency';
parent::__construct();
}
/**
* @param bool $freeze
*
* @return array
*/
public function setDefaultValues($freeze = TRUE) {
return parent::setDefaultValues($freeze);
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('group_bys', $table)) {
foreach ($table['group_bys'] as $fieldName => $field) {
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
}
if (!empty($this->_params['group_bys'][$fieldName])) {
switch (CRM_Utils_Array::value($fieldName, $this->_params['group_bys_freq'])) {
case 'YEARWEEK':
$select[] = "DATE_SUB({$field['dbAlias']}, INTERVAL WEEKDAY({$field['dbAlias']}) DAY) AS {$tableName}_{$fieldName}_start";
$select[] = "YEARWEEK({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "WEEKOFYEAR({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Week';
break;
case 'YEAR':
$select[] = "MAKEDATE(YEAR({$field['dbAlias']}), 1) AS {$tableName}_{$fieldName}_start";
$select[] = "YEAR({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "YEAR({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Year';
break;
case 'MONTH':
$select[] = "DATE_SUB({$field['dbAlias']}, INTERVAL (DAYOFMONTH({$field['dbAlias']})-1) DAY) as {$tableName}_{$fieldName}_start";
$select[] = "MONTH({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "MONTHNAME({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Month';
break;
case 'QUARTER':
$select[] = "STR_TO_DATE(CONCAT( 3 * QUARTER( {$field['dbAlias']} ) -2 , '/', '1', '/', YEAR( {$field['dbAlias']} ) ), '%m/%d/%Y') AS {$tableName}_{$fieldName}_start";
$select[] = "QUARTER({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "QUARTER({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Quarter';
break;
}
if (!empty($this->_params['group_bys_freq'][$fieldName])) {
$this->_interval = $field['title'];
$this->_columnHeaders["{$tableName}_{$fieldName}_start"]['title'] = $field['title'] . ' Beginning';
$this->_columnHeaders["{$tableName}_{$fieldName}_start"]['type'] = $field['type'];
$this->_columnHeaders["{$tableName}_{$fieldName}_start"]['group_by'] = $this->_params['group_bys_freq'][$fieldName];
// just to make sure these values are transfered to rows.
// since we need that for calculation purpose,
// e.g making subtotals look nicer or graphs
$this->_columnHeaders["{$tableName}_{$fieldName}_interval"] = array('no_display' => TRUE);
$this->_columnHeaders["{$tableName}_{$fieldName}_subtotal"] = array('no_display' => TRUE);
}
}
}
}
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
}
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
// only include statistics columns if set
if (!empty($field['statistics'])) {
foreach ($field['statistics'] as $stat => $label) {
switch (strtolower($stat)) {
case 'sum':
$select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'count':
$select[] = "COUNT({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = CRM_Utils_Type::T_INT;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'avg':
$select[] = "ROUND(AVG({$field['dbAlias']}),2) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
}
}
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
}
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$softCreditJoin = "LEFT";
if (!empty($this->_params['fields']['soft_amount']) &&
empty($this->_params['fields']['total_amount'])
) {
// if its only soft credit stats, use inner join
$softCreditJoin = "INNER";
}
$this->_from = "
FROM civicrm_contribution_recur {$this->_aliases['civicrm_contribution_recur']}
";
}
public function postProcess() {
$this->beginPostProcess();
$sql = $this->buildQuery(TRUE);
$rows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
public function groupBy() {
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, "{$this->_aliases['civicrm_contribution_recur']}.payment_instrument_id");
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$paymentInstruments = CRM_Contribute_PseudoConstant::paymentInstrument();
$entryFound = FALSE;
$startDateFrom = CRM_Utils_Array::value("start_date_to", $this->_params);
$startDateTo = CRM_Utils_Array::value("start_date_from", $this->_params);
$startDateRelative = CRM_Utils_Array::value("start_date_relative", $this->_params);
$startedDateSql = $this->dateClause('start_date', $startDateRelative, $startDateFrom, $startDateTo);
$startedDateSql = $startedDateSql ? $startedDateSql : " ( 1 ) ";
$cancelledDateSql = $this->dateClause('cancel_date', $startDateRelative, $startDateFrom, $startDateTo);
$cancelledDateSql = $cancelledDateSql ? $cancelledDateSql : " ( cancel_date IS NOT NULL ) ";
$started = $cancelled = $active = $total = 0;
foreach ($rows as $rowNum => $row) {
$paymentInstrumentId = CRM_Utils_Array::value('civicrm_contribution_recur_payment_instrument_id', $row);
$rows[$rowNum]['civicrm_contribution_recur_start_date'] = 0;
$rows[$rowNum]['civicrm_contribution_recur_cancel_date'] = 0;
$rows[$rowNum]['civicrm_contribution_recur_contribution_status_id'] = 0;
$startedSql = "SELECT count(*) as count FROM civicrm_contribution_recur WHERE payment_instrument_id = $paymentInstrumentId AND $startedDateSql ";
$startedDao = CRM_Core_DAO::executeQuery($startedSql);
$startedDao->fetch();
$rows[$rowNum]['civicrm_contribution_recur_start_date'] = $startedDao->count;
$started = $started + $startedDao->count;
$cancelledSql = "SELECT count(*) as count FROM civicrm_contribution_recur WHERE payment_instrument_id = $paymentInstrumentId AND $cancelledDateSql ";
$cancelledDao = CRM_Core_DAO::executeQuery($cancelledSql);
$cancelledDao->fetch();
$rows[$rowNum]['civicrm_contribution_recur_cancel_date'] = $cancelledDao->count;
$cancelled = $cancelled + $cancelledDao->count;
$activeSql = "SELECT count(*) as count FROM civicrm_contribution_recur WHERE payment_instrument_id = $paymentInstrumentId";
list($from, $to) = $this->getFromTo($startDateRelative, $startDateFrom, $startDateTo);
// To find active recurring contribution start date must be >= to start of selected date-range AND
// end date or cancel date must be >= to end of selected date-range if NOT null OR end date is null
if (!empty($from)) {
$activeSql .= " AND start_date >= '{$from}'";
}
if (!empty($to)) {
$activeSql .= " AND (
( end_date >= '{$to}' AND end_date IS NOT NULL ) OR
( cancel_date >= '{$to}' AND cancel_date IS NOT NULL ) OR
end_date IS NULL )";
}
$activeDao = CRM_Core_DAO::executeQuery($activeSql);
$activeDao->fetch();
$rows[$rowNum]['civicrm_contribution_recur_contribution_status_id'] = $activeDao->count;
$active = $active + $activeDao->count;
$lineTotal = 0;
$amountSql = "
SELECT SUM(cc.total_amount) as amount FROM `civicrm_contribution` cc
INNER JOIN civicrm_contribution_recur cr ON (cr.id = cc.contribution_recur_id AND cr.payment_instrument_id = {$paymentInstrumentId})
WHERE cc.contribution_status_id = 1 AND cc.is_test = 0 AND ";
$amountSql .= str_replace("start_date", "cc.`receive_date`", $startedDateSql);
$amountDao = CRM_Core_DAO::executeQuery($amountSql);
$amountDao->fetch();
if ($amountDao->amount) {
$lineTotal = $amountDao->amount;
}
$rows[$rowNum]['civicrm_contribution_recur_amount'] = CRM_Utils_Money::format($lineTotal);
$total = $total + $amountDao->amount;
// handle payment instrument id
if ($value = CRM_Utils_Array::value('civicrm_contribution_recur_payment_instrument_id', $row)) {
$rows[$rowNum]['civicrm_contribution_recur_payment_instrument_id'] = $paymentInstruments[$value];
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
// Add total line only if results are available
if (count($rows) > 0) {
$lastRow = array(
'civicrm_contribution_recur_payment_instrument_id' => '',
'civicrm_contribution_recur_start_date' => $started,
'civicrm_contribution_recur_cancel_date' => $cancelled,
'civicrm_contribution_recur_contribution_status_id' => $active,
'civicrm_contribution_recur_amount' => CRM_Utils_Money::format($total),
);
$rows[] = $lastRow;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,679 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Contribute_SoftCredit extends CRM_Report_Form {
protected $_emailField = FALSE;
protected $_emailFieldCredit = FALSE;
protected $_phoneField = FALSE;
protected $_phoneFieldCredit = FALSE;
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Contribution',
);
public $_drilldownReport = array('contribute/detail' => 'Link to Detail Report');
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
*/
public function __construct() {
// Check if CiviCampaign is a) enabled and b) has active campaigns
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'display_name_creditor' => array(
'title' => ts('Soft Credit Name'),
'name' => 'sort_name',
'alias' => 'contact_civireport',
'required' => TRUE,
'no_repeat' => TRUE,
),
'id_creditor' => array(
'title' => ts('Soft Credit Id'),
'name' => 'id',
'alias' => 'contact_civireport',
'no_display' => TRUE,
'required' => TRUE,
),
'display_name_constituent' => array(
'title' => ts('Contributor Name'),
'name' => 'sort_name',
'alias' => 'constituentname',
'required' => TRUE,
),
'id_constituent' => array(
'title' => ts('Const Id'),
'name' => 'id',
'alias' => 'constituentname',
'no_display' => TRUE,
'required' => TRUE,
),
'first_name' => array(
'title' => ts('First Name'),
),
'middle_name' => array(
'title' => ts('Middle Name'),
),
'last_name' => array(
'title' => ts('Last Name'),
),
'gender_id' => array(
'title' => ts('Gender'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
),
'age' => array(
'title' => ts('Age'),
'dbAlias' => 'TIMESTAMPDIFF(YEAR, contact_civireport.birth_date, CURDATE())',
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'grouping' => 'contact-fields',
'order_bys' => array(
'sort_name' => array(
'title' => ts('Last Name, First Name'),
'default' => '1',
'default_weight' => '0',
'default_order' => 'ASC',
),
'first_name' => array(
'name' => 'first_name',
'title' => ts('First Name'),
),
'gender_id' => array(
'name' => 'gender_id',
'title' => ts('Gender'),
),
'birth_date' => array(
'name' => 'birth_date',
'title' => ts('Birth Date'),
),
'age_at_event' => array(
'name' => 'age_at_event',
'title' => ts('Age at Event'),
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => array(
'sort_name' => array(
'name' => 'sort_name',
'title' => ts('Soft Credit Name'),
),
'gender_id' => array(
'title' => ts('Gender'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email_creditor' => array(
'title' => ts('Soft Credit Email'),
'name' => 'email',
'alias' => 'emailcredit',
'default' => TRUE,
'no_repeat' => TRUE,
),
'email_constituent' => array(
'title' => ts('Contributor\'s Email'),
'name' => 'email',
'alias' => 'emailconst',
),
),
'grouping' => 'contact-fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array(
'phone_creditor' => array(
'title' => ts('Soft Credit Phone'),
'name' => 'phone',
'alias' => 'pcredit',
'default' => TRUE,
),
'phone_constituent' => array(
'title' => ts('Contributor\'s Phone'),
'name' => 'phone',
'alias' => 'pconst',
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_financial_type' => array(
'dao' => 'CRM_Financial_DAO_FinancialType',
'fields' => array('financial_type' => NULL),
'filters' => array(
'id' => array(
'name' => 'id',
'title' => ts('Financial Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes(),
),
),
'grouping' => 'softcredit-fields',
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'contribution_source' => NULL,
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
),
'grouping' => 'softcredit-fields',
'filters' => array(
'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => array(1),
),
),
),
'civicrm_contribution_soft' => array(
'dao' => 'CRM_Contribute_DAO_ContributionSoft',
'fields' => array(
'contribution_id' => array(
'title' => ts('Contribution ID'),
'no_display' => TRUE,
'default' => TRUE,
),
'amount' => array(
'title' => ts('Amount Statistics'),
'default' => TRUE,
'statistics' => array(
'sum' => ts('Aggregate Amount'),
'count' => ts('Contributions'),
'avg' => ts('Average'),
),
),
'id' => array(
'default' => TRUE,
'no_display' => TRUE,
),
'soft_credit_type_id' => array('title' => ts('Soft Credit Type')),
),
'filters' => array(
'soft_credit_type_id' => array(
'title' => ts('Soft Credit Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('soft_credit_type'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'amount' => array(
'title' => ts('Soft Credit Amount'),
),
),
'grouping' => 'softcredit-fields',
),
'civicrm_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
),
),
'filters' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
),
),
);
// If we have a campaign, build out the relevant elements
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_contribution']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
);
$this->_columns['civicrm_contribution']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
}
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
$this->_currencyColumn = 'civicrm_contribution_currency';
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
// include email column if set
if ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
$this->_emailFieldCredit = TRUE;
}
elseif ($tableName == 'civicrm_email_creditor') {
$this->_emailFieldCredit = TRUE;
}
// include phone columns if set
if ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
$this->_phoneFieldCredit = TRUE;
}
elseif ($tableName == 'civicrm_phone_creditor') {
$this->_phoneFieldCredit = TRUE;
}
// only include statistics columns if set
if (!empty($field['statistics'])) {
foreach ($field['statistics'] as $stat => $label) {
switch (strtolower($stat)) {
case 'sum':
$select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'count':
$select[] = "COUNT({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = CRM_Utils_Type::T_INT;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'avg':
$select[] = "ROUND(AVG({$field['dbAlias']}),2) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
}
}
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
}
$this->selectClause = $select;
$this->_select = 'SELECT ' . implode(', ', $select) . ' ';
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = $grouping = array();
return $errors;
}
public function from() {
$alias_constituent = 'constituentname';
$alias_creditor = 'contact_civireport';
$this->_from = "
FROM civicrm_contribution {$this->_aliases['civicrm_contribution']}
INNER JOIN civicrm_contribution_soft {$this->_aliases['civicrm_contribution_soft']}
ON {$this->_aliases['civicrm_contribution_soft']}.contribution_id =
{$this->_aliases['civicrm_contribution']}.id
INNER JOIN civicrm_contact {$alias_constituent}
ON {$this->_aliases['civicrm_contribution']}.contact_id =
{$alias_constituent}.id
LEFT JOIN civicrm_financial_type {$this->_aliases['civicrm_financial_type']}
ON {$this->_aliases['civicrm_contribution']}.financial_type_id =
{$this->_aliases['civicrm_financial_type']}.id
LEFT JOIN civicrm_contact {$alias_creditor}
ON {$this->_aliases['civicrm_contribution_soft']}.contact_id =
{$alias_creditor}.id
{$this->_aclFrom} ";
// include Constituent email field if email column is to be included
if ($this->_emailField) {
$alias = 'emailconst';
$this->_from .= "
LEFT JOIN civicrm_email {$alias}
ON {$alias_constituent}.id =
{$alias}.contact_id AND
{$alias}.is_primary = 1\n";
}
// include Creditors email field if email column is to be included
if ($this->_emailFieldCredit) {
$alias = 'emailcredit';
$this->_from .= "
LEFT JOIN civicrm_email {$alias}
ON {$alias_creditor}.id =
{$alias}.contact_id AND
{$alias}.is_primary = 1\n";
}
// include Constituents phone field if email column is to be included
if ($this->_phoneField) {
$alias = 'pconst';
$this->_from .= "
LEFT JOIN civicrm_phone {$alias}
ON {$alias_constituent}.id =
{$alias}.contact_id AND
{$alias}.is_primary = 1\n";
}
// include Creditors phone field if email column is to be included
if ($this->_phoneFieldCredit) {
$alias = 'pcredit';
$this->_from .= "
LEFT JOIN civicrm_phone pcredit
ON {$alias_creditor}.id =
{$alias}.contact_id AND
{$alias}.is_primary = 1\n";
}
// for credit card type
$this->addFinancialTrxnFromClause();
}
public function groupBy() {
$this->_rollup = 'WITH ROLLUP';
$this->_select = CRM_Contact_BAO_Query::appendAnyValueToSelect($this->selectClause, array("{$this->_aliases['civicrm_contribution_soft']}.contact_id", "constituentname.id"));
$this->_groupBy = "
GROUP BY {$this->_aliases['civicrm_contribution_soft']}.contact_id, constituentname.id {$this->_rollup}";
}
public function where() {
parent::where();
$this->_where .= " AND {$this->_aliases['civicrm_contribution']}.is_test = 0 ";
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
$select = "
SELECT COUNT({$this->_aliases['civicrm_contribution_soft']}.amount ) as count,
SUM({$this->_aliases['civicrm_contribution_soft']}.amount ) as amount,
ROUND(AVG({$this->_aliases['civicrm_contribution_soft']}.amount), 2) as avg,
{$this->_aliases['civicrm_contribution']}.currency as currency
";
$sql = "{$select} {$this->_from} {$this->_where}
GROUP BY {$this->_aliases['civicrm_contribution']}.currency
";
$dao = CRM_Core_DAO::executeQuery($sql);
$count = 0;
$totalAmount = $average = array();
while ($dao->fetch()) {
$totalAmount[] = CRM_Utils_Money::format($dao->amount, $dao->currency) . '(' .
$dao->count . ')';
$average[] = CRM_Utils_Money::format($dao->avg, $dao->currency);
$count += $dao->count;
}
$statistics['counts']['amount'] = array(
'title' => ts('Total Amount'),
'value' => implode(', ', $totalAmount),
'type' => CRM_Utils_Type::T_STRING,
);
$statistics['counts']['count'] = array(
'title' => ts('Total Contributions'),
'value' => $count,
);
$statistics['counts']['avg'] = array(
'title' => ts('Average'),
'value' => implode(', ', $average),
'type' => CRM_Utils_Type::T_STRING,
);
return $statistics;
}
public function postProcess() {
$this->beginPostProcess();
$this->buildACLClause(array('constituentname', 'contact_civireport'));
$sql = $this->buildQuery();
$dao = CRM_Core_DAO::executeQuery($sql);
$rows = $graphRows = array();
$count = 0;
while ($dao->fetch()) {
$row = array();
foreach ($this->_columnHeaders as $key => $value) {
$row[$key] = $dao->$key;
}
$rows[] = $row;
}
$this->formatDisplay($rows);
// to hide the contact ID field from getting displayed
unset($this->_columnHeaders['civicrm_contact_id_constituent']);
unset($this->_columnHeaders['civicrm_contact_id_creditor']);
// assign variables to templates
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$dispname_flag = $phone_flag = $email_flag = 0;
$prev_email = $prev_dispname = $prev_phone = NULL;
foreach ($rows as $rowNum => $row) {
// Link constituent (contributor) to contribution detail
if (array_key_exists('civicrm_contact_display_name_constituent', $row) &&
array_key_exists('civicrm_contact_id_constituent', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contribute/detail',
'reset=1&force=1&id_op=eq&id_value=' .
$row['civicrm_contact_id_constituent'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_display_name_constituent_link'] = $url;
$rows[$rowNum]['civicrm_contact_display_name_constituent_hover'] = ts('List all direct contribution(s) from this contact.');
$entryFound = TRUE;
}
// convert soft credit contact name to link
if (array_key_exists('civicrm_contact_display_name_creditor', $row) &&
!empty($rows[$rowNum]['civicrm_contact_display_name_creditor']) &&
array_key_exists('civicrm_contact_id_creditor', $row)
) {
$url = CRM_Utils_System::url("civicrm/contact/view",
'reset=1&cid=' . $row['civicrm_contact_id_creditor'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_display_name_creditor_link'] = $url;
$rows[$rowNum]['civicrm_contact_display_name_creditor_hover'] = ts("view contact summary");
}
// make subtotals look nicer
if (array_key_exists('civicrm_contact_id_constituent', $row) &&
!$row['civicrm_contact_id_constituent']
) {
$this->fixSubTotalDisplay($rows[$rowNum], $this->_statFields);
$entryFound = TRUE;
}
// convert campaign_id to campaign title
if (array_key_exists('civicrm_contribution_campaign_id', $row)) {
if ($value = $row['civicrm_contribution_campaign_id']) {
$rows[$rowNum]['civicrm_contribution_campaign_id'] = $this->activeCampaigns[$value];
$entryFound = TRUE;
}
}
//convert soft_credit_type_id into label
if (array_key_exists('civicrm_contribution_soft_soft_credit_type_id', $rows[$rowNum])) {
$rows[$rowNum]['civicrm_contribution_soft_soft_credit_type_id'] = CRM_Core_PseudoConstant::getLabel(
'CRM_Contribute_BAO_ContributionSoft',
'soft_credit_type_id',
$row['civicrm_contribution_soft_soft_credit_type_id']
);
}
//handle gender
if (array_key_exists('civicrm_contact_gender_id', $row)) {
if ($value = $row['civicrm_contact_gender_id']) {
$gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
$rows[$rowNum]['civicrm_contact_gender_id'] = $gender[$value];
}
$entryFound = TRUE;
}
// display birthday in the configured custom format
if (array_key_exists('civicrm_contact_birth_date', $row)) {
$birthDate = $row['civicrm_contact_birth_date'];
if ($birthDate) {
$rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
}
$entryFound = TRUE;
}
if (!empty($row['civicrm_financial_trxn_card_type_id']) && !in_array('Subtotal', $rows[$rowNum])) {
$rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
$this->removeDuplicates($rows);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,668 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Contribute_Sybunt extends CRM_Report_Form {
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Contribution',
);
public $_drilldownReport = array('contribute/detail' => 'Link to Detail Report');
/**
* This report has been optimised for group filtering.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = FALSE;
/**
* Class constructor.
*/
public function __construct() {
$this->_rollup = 'WITH ROLLUP';
$this->_autoIncludeIndexedFieldsAsOrderBys = 1;
$yearsInPast = 10;
$yearsInFuture = 1;
$date = CRM_Core_SelectValues::date('custom', NULL, $yearsInPast, $yearsInFuture);
$count = $date['maxYear'];
while ($date['minYear'] <= $count) {
$optionYear[$date['minYear']] = $date['minYear'];
$date['minYear']++;
}
// Check if CiviCampaign is a) enabled and b) has active campaigns
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'grouping' => 'contact-field',
'fields' => array(
'sort_name' => array(
'title' => ts('Donor Name'),
'required' => TRUE,
),
'first_name' => array(
'title' => ts('First Name'),
),
'middle_name' => array(
'title' => ts('Middle Name'),
),
'last_name' => array(
'title' => ts('Last Name'),
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
),
'age' => array(
'title' => ts('Age'),
'dbAlias' => 'TIMESTAMPDIFF(YEAR, contact_civireport.birth_date, CURDATE())',
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'order_bys' => array(
'sort_name' => array(
'title' => ts('Last Name, First Name'),
'default' => '1',
'default_weight' => '0',
'default_order' => 'ASC',
),
'first_name' => array(
'name' => 'first_name',
'title' => ts('First Name'),
),
'gender_id' => array(
'name' => 'gender_id',
'title' => ts('Gender'),
),
'birth_date' => array(
'name' => 'birth_date',
'title' => ts('Birth Date'),
),
'age_at_event' => array(
'name' => 'age_at_event',
'title' => ts('Age at Event'),
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Donor Name'),
'operator' => 'like',
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
),
'civicrm_line_item' => array(
'dao' => 'CRM_Price_DAO_LineItem',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'grouping' => 'contact-field',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'default' => TRUE,
),
),
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'grouping' => 'contact-field',
'fields' => array(
'phone' => array(
'title' => ts('Phone'),
'default' => TRUE,
),
),
),
);
$this->_columns += $this->addAddressFields();
$this->_columns += array(
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'contact_id' => array(
'title' => ts('contactId'),
'no_display' => TRUE,
'required' => TRUE,
'no_repeat' => TRUE,
),
'total_amount' => array(
'title' => ts('Total Amount'),
'no_display' => TRUE,
'required' => TRUE,
'no_repeat' => TRUE,
),
'receive_date' => array(
'title' => ts('Year'),
'no_display' => TRUE,
'required' => TRUE,
'no_repeat' => TRUE,
),
),
'filters' => array(
'yid' => array(
'name' => 'receive_date',
'title' => ts('This Year'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => $optionYear,
'default' => date('Y'),
'type' => CRM_Utils_Type::T_INT,
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes(),
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => array('1'),
),
),
),
);
$this->_columns += array(
'civicrm_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
),
),
'filters' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'default' => NULL,
'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
'type' => CRM_Utils_Type::T_STRING,
),
),
),
);
// If we have a campaign, build out the relevant elements
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_contribution']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
);
$this->_columns['civicrm_contribution']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
}
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
$current_year = $this->_params['yid_value'];
$previous_year = $current_year - 1;
$previous_pyear = $current_year - 2;
$previous_ppyear = $current_year - 3;
$upTo_year = $current_year - 4;
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($fieldName == 'total_amount') {
$select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}";
$this->_columnHeaders["civicrm_upto_{$upTo_year}"]['type'] = $field['type'];
$this->_columnHeaders["civicrm_upto_{$upTo_year}"]['title'] = ts("Up To %1", array(1 => $upTo_year));
$this->_columnHeaders["year_{$previous_ppyear}"]['type'] = $field['type'];
$this->_columnHeaders["year_{$previous_ppyear}"]['title'] = $previous_ppyear;
$this->_columnHeaders["year_{$previous_pyear}"]['type'] = $field['type'];
$this->_columnHeaders["year_{$previous_pyear}"]['title'] = $previous_pyear;
$this->_columnHeaders["year_{$previous_year}"]['type'] = $field['type'];
$this->_columnHeaders["year_{$previous_year}"]['title'] = $previous_year;
$this->_columnHeaders["civicrm_life_time_total"]['type'] = $field['type'];
$this->_columnHeaders["civicrm_life_time_total"]['title'] = ts('LifeTime');
}
elseif ($fieldName == 'receive_date') {
$select[] = self::fiscalYearOffset($field['dbAlias']) .
" as {$tableName}_{$fieldName}";
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
if (!empty($field['no_display'])) {
$this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = TRUE;
}
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$this->setFromBase('civicrm_contribution', 'contact_id');
$this->_from .= "
INNER JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_contribution']}.contact_id
{$this->_aclFrom}";
if ($this->isTableSelected('civicrm_email')) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id
AND {$this->_aliases['civicrm_email']}.is_primary = 1";
}
if ($this->isTableSelected('civicrm_phone')) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1";
}
// for credit card type
$this->addFinancialTrxnFromClause();
$this->addAddressFromClause();
}
public function where() {
$this->_statusClause = "";
$clauses = array($this->_aliases['civicrm_contribution'] . '.is_test = 0');
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if ($fieldName == 'yid') {
$clause = "contribution_civireport.contact_id NOT IN
(SELECT distinct cont.id FROM civicrm_contact cont, civicrm_contribution contri
WHERE cont.id = contri.contact_id AND " .
self::fiscalYearOffset('contri.receive_date') .
" = {$this->_params['yid_value']} AND contri.is_test = 0 )";
}
elseif (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE
) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($relative || $from || $to) {
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
if (($fieldName == 'contribution_status_id' ||
$fieldName == 'financial_type_id') && !empty($clause)
) {
$this->_statusClause .= " AND " . $clause;
}
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
$this->_where = "WHERE " . implode(' AND ', $clauses);
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
public function groupBy() {
$this->assign('chartSupported', TRUE);
$fiscalYearOffset = self::fiscalYearOffset("{$this->_aliases['civicrm_contribution']}.receive_date");
$this->_groupBy = "GROUP BY {$this->_aliases['civicrm_contribution']}.contact_id, {$fiscalYearOffset}";
$this->_select = CRM_Contact_BAO_Query::appendAnyValueToSelect($this->_selectClauses, array("{$this->_aliases['civicrm_contribution']}.contact_id", $fiscalYearOffset));
$this->_groupBy .= " {$this->_rollup}";
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
if (!empty($rows)) {
$select = "
SELECT
SUM({$this->_aliases['civicrm_contribution']}.total_amount ) as amount ";
$sql = "{$select} {$this->_from} {$this->_where}";
$dao = CRM_Core_DAO::executeQuery($sql);
if ($dao->fetch()) {
$statistics['counts']['amount'] = array(
'value' => $dao->amount,
'title' => ts('Total LifeTime'),
'type' => CRM_Utils_Type::T_MONEY,
);
}
}
return $statistics;
}
public function postProcess() {
// get ready with post process params
$this->beginPostProcess();
$this->buildACLClause($this->_aliases['civicrm_contact']);
$this->buildQuery();
$rows = $contactIds = array();
if (empty($this->_params['charts'])) {
$this->limit();
$getContacts = "SELECT SQL_CALC_FOUND_ROWS {$this->_aliases['civicrm_contact']}.id as cid {$this->_from} {$this->_where} GROUP BY {$this->_aliases['civicrm_contact']}.id {$this->_limit}";
$dao = CRM_Core_DAO::executeQuery($getContacts);
while ($dao->fetch()) {
$contactIds[] = $dao->cid;
}
$dao->free();
$this->setPager();
}
if (!empty($contactIds) || !empty($this->_params['charts'])) {
if (!empty($this->_params['charts'])) {
$sql = "{$this->_select} {$this->_from} {$this->_where} {$this->_groupBy}";
}
else {
$sql = "" .
"{$this->_select} {$this->_from} WHERE {$this->_aliases['civicrm_contact']}.id IN (" .
implode(',', $contactIds) .
") AND {$this->_aliases['civicrm_contribution']}.is_test = 0 {$this->_statusClause} {$this->_groupBy} ";
}
$current_year = $this->_params['yid_value'];
$previous_year = $current_year - 1;
$previous_pyear = $current_year - 2;
$previous_ppyear = $current_year - 3;
$upTo_year = $current_year - 4;
$rows = $row = array();
$dao = CRM_Core_DAO::executeQuery($sql);
$contributionSum = 0;
$yearcal = array();
while ($dao->fetch()) {
if (!$dao->civicrm_contribution_contact_id) {
continue;
}
$row = array();
foreach ($this->_columnHeaders as $key => $value) {
if (property_exists($dao, $key)) {
$rows[$dao->civicrm_contribution_contact_id][$key] = $dao->$key;
}
}
if ($dao->civicrm_contribution_receive_date) {
if ($dao->civicrm_contribution_receive_date > $upTo_year) {
$contributionSum += $dao->civicrm_contribution_total_amount;
$rows[$dao->civicrm_contribution_contact_id]['year_' . $dao->civicrm_contribution_receive_date] = $dao->civicrm_contribution_total_amount;
}
}
else {
$rows[$dao->civicrm_contribution_contact_id]['civicrm_life_time_total'] = $dao->civicrm_contribution_total_amount;
if (($dao->civicrm_contribution_total_amount - $contributionSum) > 0
) {
$rows[$dao->civicrm_contribution_contact_id]["civicrm_upto_{$upTo_year}"]
= $dao->civicrm_contribution_total_amount - $contributionSum;
}
$contributionSum = 0;
}
}
$dao->free();
}
// format result set.
$this->formatDisplay($rows, FALSE);
// assign variables to templates
$this->doTemplateAssignment($rows);
// do print / pdf / instance stuff if needed
$this->endPostProcess($rows);
}
/**
* @param $rows
*/
public function buildChart(&$rows) {
$graphRows = array();
$count = 0;
$current_year = $this->_params['yid_value'];
$previous_year = $current_year - 1;
$previous_two_year = $current_year - 2;
$previous_three_year = $current_year - 3;
$upto = $current_year - 4;
$interval[$previous_year] = $previous_year;
$interval[$previous_two_year] = $previous_two_year;
$interval[$previous_three_year] = $previous_three_year;
$interval["upto_{$upto}"] = "Up To {$upto}";
foreach ($rows as $key => $row) {
$display["upto_{$upto}"]
= CRM_Utils_Array::value("upto_{$upto}", $display) + CRM_Utils_Array::value("civicrm_upto_{$upto}", $row);
$display[$previous_year]
= CRM_Utils_Array::value($previous_year, $display) + CRM_Utils_Array::value($previous_year, $row);
$display[$previous_two_year]
= CRM_Utils_Array::value($previous_two_year, $display) + CRM_Utils_Array::value($previous_two_year, $row);
$display[$previous_three_year]
= CRM_Utils_Array::value($previous_three_year, $display) + CRM_Utils_Array::value($previous_three_year, $row);
}
$graphRows['value'] = $display;
$config = CRM_Core_Config::Singleton();
$chartInfo = array(
'legend' => 'Sybunt Report',
'xname' => 'Year',
'yname' => "Amount ({$config->defaultCurrency})",
);
if ($this->_params['charts']) {
// build the chart.
CRM_Utils_OpenFlashChart::reportChart($graphRows, $this->_params['charts'], $interval, $chartInfo);
$this->assign('chartType', $this->_params['charts']);
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
//Convert Display name into link
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contribution_contact_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contribute/detail',
'reset=1&force=1&id_op=eq&id_value=' .
$row['civicrm_contribution_contact_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contribution Details for this Contact.");
$entryFound = TRUE;
}
// convert campaign_id to campaign title
if (array_key_exists('civicrm_contribution_campaign_id', $row)) {
if ($value = $row['civicrm_contribution_campaign_id']) {
$rows[$rowNum]['civicrm_contribution_campaign_id'] = $this->activeCampaigns[$value];
$entryFound = TRUE;
}
}
$entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'contribute/detail', 'List all contribution(s)') ? TRUE : $entryFound;
//handle gender
if (array_key_exists('civicrm_contact_gender_id', $row)) {
if ($value = $row['civicrm_contact_gender_id']) {
$gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
$rows[$rowNum]['civicrm_contact_gender_id'] = $gender[$value];
}
$entryFound = TRUE;
}
// display birthday in the configured custom format
if (array_key_exists('civicrm_contact_birth_date', $row)) {
$birthDate = $row['civicrm_contact_birth_date'];
if ($birthDate) {
$rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
}
$entryFound = TRUE;
}
if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
$rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
/**
* Override "This Year" $op options
* @param string $type
* @param null $fieldName
*
* @return array
*/
public function getOperationPair($type = "string", $fieldName = NULL) {
if ($fieldName == 'yid') {
return array(
'calendar' => ts('Is Calendar Year'),
'fiscal' => ts('Fiscal Year Starting'),
);
}
return parent::getOperationPair($type, $fieldName);
}
}

View file

@ -0,0 +1,533 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Contribute_TopDonor extends CRM_Report_Form {
protected $_summary = NULL;
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Contribution',
);
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
public $_drilldownReport = array('contribute/detail' => 'Link to Detail Report');
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
/**
*/
public function __construct() {
$this->_autoIncludeIndexedFieldsAsOrderBys = 1;
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'display_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
'first_name' => array(
'title' => ts('First Name'),
),
'middle_name' => array(
'title' => ts('Middle Name'),
),
'last_name' => array(
'title' => ts('Last Name'),
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
),
'age' => array(
'title' => ts('Age'),
'dbAlias' => 'TIMESTAMPDIFF(YEAR, contact_civireport.birth_date, CURDATE())',
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => $this->getBasicContactFilters(),
),
'civicrm_line_item' => array(
'dao' => 'CRM_Price_DAO_LineItem',
),
);
$this->_columns += $this->getAddressColumns();
$this->_columns += array(
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'total_amount' => array(
'title' => ts('Amount Statistics'),
'required' => TRUE,
'statistics' => array(
'sum' => ts('Aggregate Amount'),
'count' => ts('Donations'),
'avg' => ts('Average'),
),
),
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
),
'filters' => array(
'receive_date' => array(
'default' => 'this.year',
'operatorType' => CRM_Report_Form::OP_DATE,
),
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'total_range' => array(
'title' => ts('Show no. of Top Donors'),
'type' => CRM_Utils_Type::T_INT,
'default_op' => 'eq',
),
'financial_type_id' => array(
'name' => 'financial_type_id',
'title' => ts('Financial Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_BAO_FinancialType::getAvailableFinancialTypes(),
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => array(1),
),
),
),
'civicrm_financial_trxn' => array(
'dao' => 'CRM_Financial_DAO_FinancialTrxn',
'fields' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
),
),
'filters' => array(
'card_type_id' => array(
'title' => ts('Credit Card Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
),
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'default' => TRUE,
'no_repeat' => TRUE,
),
),
'grouping' => 'email-fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array(
'phone' => array(
'title' => ts('Phone'),
'default' => TRUE,
'no_repeat' => TRUE,
),
),
'grouping' => 'phone-fields',
),
);
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
$this->_currencyColumn = 'civicrm_contribution_currency';
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
//Headers for Rank column
$this->_columnHeaders["civicrm_donor_rank"]['title'] = ts('Rank');
$this->_columnHeaders["civicrm_donor_rank"]['type'] = 1;
//$select[] ="(@rank:=@rank+1) as civicrm_donor_rank ";
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
// only include statistics columns if set
if (!empty($field['statistics'])) {
foreach ($field['statistics'] as $stat => $label) {
switch (strtolower($stat)) {
case 'sum':
$select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'count':
$select[] = "COUNT({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = CRM_Utils_Type::T_INT;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'avg':
$select[] = "ROUND(AVG({$field['dbAlias']}),2) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
}
}
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
// $field['type'] is not always set. Use string type as default if not set.
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = isset($field['type']) ? $field['type'] : 2;
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
}
$this->_selectClauses = $select;
$this->_select = " SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = array();
$op = CRM_Utils_Array::value('total_range_op', $fields);
$val = CRM_Utils_Array::value('total_range_value', $fields);
if (!in_array($op, array(
'eq',
'lte',
))
) {
$errors['total_range_op'] = ts("Please select 'Is equal to' OR 'Is Less than or equal to' operator");
}
if ($val && !CRM_Utils_Rule::positiveInteger($val)) {
$errors['total_range_value'] = ts("Please enter positive number");
}
return $errors;
}
public function from() {
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}
INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_contribution']}.contact_id AND {$this->_aliases['civicrm_contribution']}.is_test = 0
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id
AND {$this->_aliases['civicrm_email']}.is_primary = 1
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1";
// for credit card type
$this->addFinancialTrxnFromClause();
$this->addAddressFromClause();
}
public function where() {
$clauses = array();
$this->_tempClause = $this->_outerCluase = $this->_groupLimit = '';
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($relative || $from || $to) {
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
if ($fieldName == 'total_range') {
$value = CRM_Utils_Array::value("total_range_value", $this->_params);
$this->_outerCluase = " WHERE (( @rows := @rows + 1) <= {$value}) ";
$this->_groupLimit = " LIMIT {$value}";
}
else {
$clauses[] = $clause;
}
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE ( 1 ) ";
}
else {
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
public function groupBy() {
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, array("{$this->_aliases['civicrm_contact']}.id", "{$this->_aliases['civicrm_contribution']}.currency"));
}
public function postProcess() {
$this->beginPostProcess();
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
$this->buildQuery();
//set the variable value rank, rows = 0
$setVariable = " SET @rows:=0, @rank=0 ";
CRM_Core_DAO::singleValueQuery($setVariable);
$sql = "SELECT * FROM ( {$this->_select} {$this->_from} {$this->_where} {$this->_groupBy}
ORDER BY civicrm_contribution_total_amount_sum DESC
) as abc {$this->_outerCluase} $this->_limit
";
$dao = CRM_Core_DAO::executeQuery($sql);
while ($dao->fetch()) {
$row = array();
foreach ($this->_columnHeaders as $key => $value) {
if (property_exists($dao, $key)) {
$row[$key] = $dao->$key;
}
}
$rows[] = $row;
}
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* @param int $groupID
*/
public function add2group($groupID) {
if (is_numeric($groupID)) {
$sql = "
{$this->_select} {$this->_from} {$this->_where} {$this->_groupBy}
ORDER BY civicrm_contribution_total_amount_sum DESC
) as abc {$this->_groupLimit}";
$dao = CRM_Core_DAO::executeQuery($sql);
$contact_ids = array();
// Add resulting contacts to group
while ($dao->fetch()) {
$contact_ids[$dao->civicrm_contact_id] = $dao->civicrm_contact_id;
}
CRM_Contact_BAO_GroupContact::addContactsToGroup($contact_ids, $groupID);
CRM_Core_Session::setStatus(ts("Listed contact(s) have been added to the selected group."), ts('Contacts Added'), 'success');
}
}
/**
* @param int $rowCount
*/
public function limit($rowCount = CRM_Report_Form::ROW_COUNT_LIMIT) {
// lets do the pager if in html mode
$this->_limit = NULL;
// CRM-14115, over-ride row count if rowCount is specified in URL
if ($this->_dashBoardRowCount) {
$rowCount = $this->_dashBoardRowCount;
}
if ($this->_outputMode == 'html' || $this->_outputMode == 'group') {
// Replace only first occurrence of SELECT.
$this->_select = preg_replace('/SELECT/', 'SELECT SQL_CALC_FOUND_ROWS ', $this->_select, 1);
$pageId = CRM_Utils_Request::retrieve('crmPID', 'Integer');
if (!$pageId && !empty($_POST) && isset($_POST['crmPID_B'])) {
if (!isset($_POST['PagerBottomButton'])) {
unset($_POST['crmPID_B']);
}
else {
$pageId = max((int) @$_POST['crmPID_B'], 1);
}
}
$pageId = $pageId ? $pageId : 1;
$this->set(CRM_Utils_Pager::PAGE_ID, $pageId);
$offset = ($pageId - 1) * $rowCount;
$offset = CRM_Utils_Type::escape($offset, 'Int');
$rowCount = CRM_Utils_Type::escape($rowCount, 'Int');
$this->_limit = " LIMIT $offset, " . $rowCount;
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$rank = 1;
if (!empty($rows)) {
foreach ($rows as $rowNum => $row) {
$rows[$rowNum]['civicrm_donor_rank'] = $rank++;
// convert display name to links
if (array_key_exists('civicrm_contact_display_name', $row) &&
array_key_exists('civicrm_contact_id', $row) &&
!empty($row['civicrm_contribution_currency'])
) {
$url = CRM_Report_Utils_Report::getNextUrl('contribute/detail',
'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'] .
"&currency_value=" . $row['civicrm_contribution_currency'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_display_name_link'] = $url;
$entryFound = TRUE;
}
$entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'contribute/detail', 'List all contribution(s)') ? TRUE : $entryFound;
//handle gender
if (array_key_exists('civicrm_contact_gender_id', $row)) {
if ($value = $row['civicrm_contact_gender_id']) {
$gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
$rows[$rowNum]['civicrm_contact_gender_id'] = $gender[$value];
}
$entryFound = TRUE;
}
// display birthday in the configured custom format
if (array_key_exists('civicrm_contact_birth_date', $row)) {
$birthDate = $row['civicrm_contact_birth_date'];
if ($birthDate) {
$rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
}
$entryFound = TRUE;
}
if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
$rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}
}

View file

@ -0,0 +1,39 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Event extends CRM_Report_Form {
// Nothing here.
// FIXME: Do these reports really have nothing in common? Really?
}

View file

@ -0,0 +1,385 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Event_Income extends CRM_Report_Form_Event {
const ROW_COUNT_LIMIT = 2;
protected $_summary = NULL;
protected $_noFields = TRUE;
protected $_add2groupSupported = FALSE;
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_event' => array(
'dao' => 'CRM_Event_DAO_Event',
'filters' => array(
'id' => array(
'title' => ts('Event'),
'operatorType' => CRM_Report_Form::OP_ENTITYREF,
'type' => CRM_Utils_Type::T_INT,
'attributes' => array('select' => array('minimumInputLength' => 0)),
),
),
),
);
parent::__construct();
}
public function preProcess() {
$this->_csvSupported = FALSE;
parent::preProcess();
}
/**
* Build event report.
*
* @param array $eventIDs
*/
public function buildEventReport($eventIDs) {
$this->assign('events', $eventIDs);
$eventID = implode(',', $eventIDs);
$participantStatus = CRM_Event_PseudoConstant::participantStatus(NULL, "is_counted = 1", "label");
$participantRole = CRM_Event_PseudoConstant::participantRole();
$paymentInstruments = CRM_Contribute_PseudoConstant::paymentInstrument();
$rows = $eventSummary = $roleRows = $statusRows = $instrumentRows = $count = array();
$optionGroupDAO = new CRM_Core_DAO_OptionGroup();
$optionGroupDAO->name = 'event_type';
$optionGroupId = NULL;
if ($optionGroupDAO->find(TRUE)) {
$optionGroupId = $optionGroupDAO->id;
}
//show the income of active participant status (Counted = filter = 1)
$activeParticipantStatusIDArray = $activeParticipantStatusLabelArray = array();
foreach ($participantStatus as $id => $label) {
$activeParticipantStatusIDArray[] = $id;
$activeParticipantStatusLabelArray[] = $label;
}
$activeParticipantStatus = implode(',', $activeParticipantStatusIDArray);
$activeparticipnatStutusLabel = implode(', ', $activeParticipantStatusLabelArray);
$activeParticipantClause = " AND civicrm_participant.status_id IN ( $activeParticipantStatus ) ";
$select = array(
"civicrm_event.id as event_id",
"civicrm_event.title as event_title",
"civicrm_event.max_participants as max_participants",
"civicrm_event.start_date as start_date",
"civicrm_event.end_date as end_date",
"civicrm_option_value.label as event_type",
"civicrm_participant.fee_currency as currency",
);
$groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($select, 'civicrm_event.id');
$sql = "
SELECT " . implode(', ', $select) . ",
SUM(civicrm_participant.fee_amount) as total,
COUNT(civicrm_participant.id) as participant
FROM civicrm_event
LEFT JOIN civicrm_option_value
ON ( civicrm_event.event_type_id = civicrm_option_value.value AND
civicrm_option_value.option_group_id = {$optionGroupId} )
LEFT JOIN civicrm_participant ON ( civicrm_event.id = civicrm_participant.event_id
{$activeParticipantClause} AND civicrm_participant.is_test = 0 )
WHERE civicrm_event.id IN( {$eventID}) {$groupBy}";
$eventDAO = $this->executeReportQuery($sql);
$currency = array();
while ($eventDAO->fetch()) {
$eventSummary[$eventDAO->event_id][ts('Title')] = $eventDAO->event_title;
$eventSummary[$eventDAO->event_id][ts('Max Participants')] = $eventDAO->max_participants;
$eventSummary[$eventDAO->event_id][ts('Start Date')] = CRM_Utils_Date::customFormat($eventDAO->start_date);
$eventSummary[$eventDAO->event_id][ts('End Date')] = CRM_Utils_Date::customFormat($eventDAO->end_date);
$eventSummary[$eventDAO->event_id][ts('Event Type')] = $eventDAO->event_type;
$eventSummary[$eventDAO->event_id][ts('Event Income')] = CRM_Utils_Money::format($eventDAO->total, $eventDAO->currency);
$eventSummary[$eventDAO->event_id][ts('Registered Participant')] = "{$eventDAO->participant} ({$activeparticipnatStutusLabel})";
$currency[$eventDAO->event_id] = $eventDAO->currency;
}
$this->assign_by_ref('summary', $eventSummary);
//Total Participant Registerd for the Event
$pariticipantCount = "
SELECT COUNT(civicrm_participant.id ) as count, civicrm_participant.event_id as event_id
FROM civicrm_participant
WHERE civicrm_participant.event_id IN( {$eventID}) AND
civicrm_participant.is_test = 0
{$activeParticipantClause}
GROUP BY civicrm_participant.event_id
";
$counteDAO = $this->executeReportQuery($pariticipantCount);
while ($counteDAO->fetch()) {
$count[$counteDAO->event_id] = $counteDAO->count;
}
// Count the Participant by Role ID for Event.
$role = "
SELECT civicrm_participant.role_id as ROLEID,
COUNT( civicrm_participant.id ) as participant,
SUM(civicrm_participant.fee_amount) as amount,
civicrm_participant.event_id as event_id,
civicrm_participant.fee_currency as currency
FROM civicrm_participant
WHERE civicrm_participant.event_id IN ( {$eventID}) AND
civicrm_participant.is_test = 0
{$activeParticipantClause}
GROUP BY civicrm_participant.role_id, civicrm_participant.event_id, civicrm_participant.fee_currency
";
$roleDAO = $this->executeReportQuery($role);
while ($roleDAO->fetch()) {
// fix for multiple role, CRM-6507
$roles = explode(CRM_Core_DAO::VALUE_SEPARATOR, $roleDAO->ROLEID);
foreach ($roles as $roleId) {
if (!isset($roleRows[$roleDAO->event_id][$participantRole[$roleId]])) {
$roleRows[$roleDAO->event_id][$participantRole[$roleId]]['total'] = 0;
$roleRows[$roleDAO->event_id][$participantRole[$roleId]]['round'] = 0;
$roleRows[$roleDAO->event_id][$participantRole[$roleId]]['amount'] = 0;
}
$roleRows[$roleDAO->event_id][$participantRole[$roleId]]['total'] += $roleDAO->participant;
$roleRows[$roleDAO->event_id][$participantRole[$roleId]]['amount'] += $roleDAO->amount;
}
}
foreach ($roleRows as $eventId => $roleInfo) {
foreach ($participantRole as $roleName) {
if (isset($roleInfo[$roleName])) {
$roleRows[$eventId][$roleName]['round'] = round(($roleRows[$eventId][$roleName]['total'] / $count[$eventId]) * 100, 2);
}
if (!empty($roleRows[$eventId][$roleName])) {
$roleRows[$eventId][$roleName]['amount'] = CRM_Utils_Money::format($roleRows[$eventId][$roleName]['amount'], $currency[$eventId]);
}
}
}
$rows[ts('Role')] = $roleRows;
// Count the Participant by status ID for Event.
$status = "
SELECT civicrm_participant.status_id as STATUSID,
COUNT( civicrm_participant.id ) as participant,
SUM(civicrm_participant.fee_amount) as amount,
civicrm_participant.event_id as event_id
FROM civicrm_participant
WHERE civicrm_participant.event_id IN ({$eventID}) AND
civicrm_participant.is_test = 0
{$activeParticipantClause}
GROUP BY civicrm_participant.status_id, civicrm_participant.event_id
";
$statusDAO = $this->executeReportQuery($status);
while ($statusDAO->fetch()) {
$statusRows[$statusDAO->event_id][$participantStatus[$statusDAO->STATUSID]]['total'] = $statusDAO->participant;
$statusRows[$statusDAO->event_id][$participantStatus[$statusDAO->STATUSID]]['round'] = round(($statusDAO->participant / $count[$statusDAO->event_id]) * 100, 2);
$statusRows[$statusDAO->event_id][$participantStatus[$statusDAO->STATUSID]]['amount'] = CRM_Utils_Money::format($statusDAO->amount, $currency[$statusDAO->event_id]);
}
$rows[ts('Status')] = $statusRows;
//Count the Participant by payment instrument ID for Event
//e.g. Credit Card, Check,Cash etc
$paymentInstrument = "
SELECT c.payment_instrument_id as INSTRUMENT,
COUNT( civicrm_participant.id ) as participant,
SUM( civicrm_participant.fee_amount ) as amount,
civicrm_participant.event_id as event_id
FROM civicrm_participant,
civicrm_participant_payment pp
LEFT JOIN civicrm_contribution c ON ( pp.contribution_id = c.id)
WHERE civicrm_participant.event_id IN ( {$eventID} )
AND civicrm_participant.is_test = 0
{$activeParticipantClause}
AND ((pp.participant_id = civicrm_participant.id )
OR (pp.participant_id = civicrm_participant.registered_by_id ))
GROUP BY c.payment_instrument_id, civicrm_participant.event_id
";
$instrumentDAO = $this->executeReportQuery($paymentInstrument);
while ($instrumentDAO->fetch()) {
//allow only if instrument is present in contribution table
if ($instrumentDAO->INSTRUMENT) {
$instrumentRows[$instrumentDAO->event_id][$paymentInstruments[$instrumentDAO->INSTRUMENT]]['total'] = $instrumentDAO->participant;
$instrumentRows[$instrumentDAO->event_id][$paymentInstruments[$instrumentDAO->INSTRUMENT]]['round'] = round(($instrumentDAO->participant / $count[$instrumentDAO->event_id]) * 100, 2);
$instrumentRows[$instrumentDAO->event_id][$paymentInstruments[$instrumentDAO->INSTRUMENT]]['amount'] = CRM_Utils_Money::format($instrumentDAO->amount, $currency[$instrumentDAO->event_id]);
}
}
$rows[ts('Payment Method')] = $instrumentRows;
$this->assign_by_ref('rows', $rows);
if (!$this->_setVariable) {
$this->_params['id_value'] = NULL;
}
$this->assign('statistics', $this->statistics($eventIDs));
}
/**
* @param $eventIDs
*
* @return array
*/
public function statistics(&$eventIDs) {
$statistics = array();
$count = count($eventIDs);
$this->countStat($statistics, $count);
if ($this->_setVariable) {
$this->filterStat($statistics);
}
return $statistics;
}
/**
* @inheritDoc
*/
public function limit($rowCount = self::ROW_COUNT_LIMIT) {
parent::limit($rowCount);
// Modify limit.
$pageId = $this->get(CRM_Utils_Pager::PAGE_ID);
//if pageId is greater than last page then display last page.
if ((($pageId * self::ROW_COUNT_LIMIT) - 1) > $this->_rowsFound) {
$pageId = ceil((float) $this->_rowsFound / (float) self::ROW_COUNT_LIMIT);
$this->set(CRM_Utils_Pager::PAGE_ID, $pageId);
}
$this->_limit = ($pageId - 1) * self::ROW_COUNT_LIMIT;
}
/**
* @param int $rowCount
*/
public function setPager($rowCount = self::ROW_COUNT_LIMIT) {
$params = array(
'total' => $this->_rowsFound,
'rowCount' => self::ROW_COUNT_LIMIT,
'status' => ts('Records %%StatusMessage%%'),
'buttonBottom' => 'PagerBottomButton',
'buttonTop' => 'PagerTopButton',
'pageID' => $this->get(CRM_Utils_Pager::PAGE_ID),
);
$pager = new CRM_Utils_Pager($params);
$this->assign_by_ref('pager', $pager);
}
/**
* Form post process function.
*
* @return bool
*/
public function postProcess() {
$this->beginPostProcess();
$this->_setVariable = TRUE;
$noSelection = FALSE;
if (empty($this->_params['id_value'])) {
$this->_params['id_value'] = array();
$this->_setVariable = FALSE;
$events = CRM_Event_PseudoConstant::event(NULL, NULL,
"is_template = 0"
);
if (empty($events)) {
return FALSE;
}
foreach ($events as $key => $dnt) {
$this->_params['id_value'][] = $key;
}
$noSelection = TRUE;
}
elseif (!is_array($this->_params['id_value'])) {
$this->_params['id_value'] = explode(',', $this->_params['id_value']);
}
$this->_rowsFound = count($this->_params['id_value']);
//set pager and limit if output mode is html
if ($this->_outputMode == 'html') {
$this->limit();
$this->setPager();
$showEvents = array();
$count = 0;
$numRows = $this->_limit;
if (CRM_Utils_Array::value('id_op', $this->_params, 'in') == 'in' || $noSelection) {
while ($count < self::ROW_COUNT_LIMIT) {
if (!isset($this->_params['id_value'][$numRows])) {
break;
}
$showEvents[] = $this->_params['id_value'][$numRows];
$count++;
$numRows++;
}
}
elseif ($this->_params['id_op'] == 'notin') {
$events = CRM_Event_PseudoConstant::event(NULL, NULL,
"is_template = 0"
);
$showEvents = array_diff(array_keys($events), $this->_params['id_value']);
}
$this->buildEventReport($showEvents);
}
else {
$this->buildEventReport($this->_params['id_value']);
}
parent::endPostProcess();
}
}

View file

@ -0,0 +1,445 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Event_IncomeCountSummary extends CRM_Report_Form_Event {
protected $_summary = NULL;
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
protected $_add2groupSupported = FALSE;
protected $_customGroupExtends = array(
'Event',
);
public $_drilldownReport = array('event/participantlist' => 'Link to Detail Report');
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_event' => array(
'dao' => 'CRM_Event_DAO_Event',
'fields' => array(
'title' => array(
'title' => ts('Event'),
'required' => TRUE,
),
'id' => array(
'title' => ts('Event ID'),
'no_display' => TRUE,
'required' => TRUE,
),
'event_type_id' => array(
'title' => ts('Event Type'),
),
'fee_label' => array(
'title' => ts('Fee Label'),
),
'event_start_date' => array(
'title' => ts('Event Start Date'),
),
'event_end_date' => array(
'title' => ts('Event End Date'),
),
'max_participants' => array(
'title' => ts('Capacity'),
'type' => CRM_Utils_Type::T_INT,
),
),
'filters' => array(
'id' => array(
'title' => ts('Event'),
'operatorType' => CRM_Report_Form::OP_ENTITYREF,
'type' => CRM_Utils_Type::T_INT,
'attributes' => array('select' => array('minimumInputLength' => 0)),
),
'event_type_id' => array(
'name' => 'event_type_id',
'title' => ts('Event Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('event_type'),
),
'event_start_date' => array(
'title' => ts('Event Start Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'event_end_date' => array(
'title' => ts('Event End Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
),
'civicrm_line_item' => array(
'dao' => 'CRM_Price_DAO_LineItem',
'fields' => array(
'participant_count' => array(
'title' => ts('Participants'),
'default' => TRUE,
'statistics' => array(
'count' => ts('Participants'),
),
),
'line_total' => array(
'title' => ts('Income Statistics'),
'type' => CRM_Utils_Type::T_MONEY,
'default' => TRUE,
'statistics' => array(
'sum' => ts('Income'),
'avg' => ts('Average'),
),
),
),
),
'civicrm_participant' => array(
'dao' => 'CRM_Event_DAO_Participant',
'filters' => array(
'sid' => array(
'name' => 'status_id',
'title' => ts('Participant Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Event_PseudoConstant::participantStatus(NULL, NULL, "label"),
),
'rid' => array(
'name' => 'role_id',
'title' => ts('Participant Role'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Event_PseudoConstant::participantRole(),
),
'participant_register_date' => array(
'title' => ts('Registration Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
),
);
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if (!empty($field['statistics'])) {
foreach ($field['statistics'] as $stat => $label) {
switch (strtolower($stat)) {
case 'count':
$select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = CRM_Utils_Type::T_INT;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'sum':
$select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = CRM_Utils_Type::T_MONEY;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'avg':
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = CRM_Utils_Type::T_MONEY;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
}
}
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select);
}
public function from() {
$this->_from = "
FROM civicrm_event {$this->_aliases['civicrm_event']}
LEFT JOIN civicrm_participant {$this->_aliases['civicrm_participant']}
ON {$this->_aliases['civicrm_event']}.id = {$this->_aliases['civicrm_participant']}.event_id AND
{$this->_aliases['civicrm_participant']}.is_test = 0
LEFT JOIN civicrm_line_item {$this->_aliases['civicrm_line_item']}
ON {$this->_aliases['civicrm_participant']}.id ={$this->_aliases['civicrm_line_item']}.entity_id AND
{$this->_aliases['civicrm_line_item']}.entity_table = 'civicrm_participant' ";
}
public function where() {
$clauses = array();
$this->_participantWhere = "";
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($relative || $from || $to) {
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($this->_params['id_value'])) {
$idValue = is_array($this->_params['id_value']) ? implode(',', $this->_params['id_value']) : $this->_params['id_value'];
$this->_participantWhere = " AND civicrm_participant.event_id IN ( $idValue ) ";
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
$clauses[] = "{$this->_aliases['civicrm_event']}.is_template = 0";
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
$select = "
SELECT SUM( {$this->_aliases['civicrm_line_item']}.participant_count ) as count,
SUM( {$this->_aliases['civicrm_line_item']}.line_total ) as amount";
$sql = "{$select} {$this->_from} {$this->_where}";
$dao = CRM_Core_DAO::executeQuery($sql);
if ($dao->fetch()) {
$avg = 0;
if ($dao->count && $dao->amount) {
$avg = $dao->amount / $dao->count;
}
$statistics['counts']['count'] = array(
'value' => $dao->count,
'title' => ts('Total Participants'),
'type' => CRM_Utils_Type::T_INT,
);
$statistics['counts']['amount'] = array(
'value' => $dao->amount,
'title' => ts('Total Income'),
'type' => CRM_Utils_Type::T_MONEY,
);
$statistics['counts']['avg'] = array(
'value' => $avg,
'title' => ts('Average'),
'type' => CRM_Utils_Type::T_MONEY,
);
}
return $statistics;
}
public function groupBy() {
$this->assign('chartSupported', TRUE);
$this->_rollup = " WITH ROLLUP";
$this->_select = CRM_Contact_BAO_Query::appendAnyValueToSelect($this->_selectClauses, "{$this->_aliases['civicrm_event']}.id");
$this->_groupBy = " GROUP BY {$this->_aliases['civicrm_event']}.id {$this->_rollup}";
}
public function postProcess() {
$this->beginPostProcess();
$sql = $this->buildQuery(TRUE);
$dao = CRM_Core_DAO::executeQuery($sql);
//set pager before execution of query in function participantInfo()
$this->setPager();
$rows = $graphRows = array();
$count = 0;
while ($dao->fetch()) {
$row = array();
foreach ($this->_columnHeaders as $key => $value) {
if (($key == 'civicrm_event_start_date') ||
($key == 'civicrm_event_end_date')
) {
//get event start date and end date in custom datetime format
$row[$key] = CRM_Utils_Date::customFormat($dao->$key);
}
elseif ($key == 'civicrm_participant_fee_amount_avg') {
if ($dao->civicrm_participant_fee_amount_sum &&
$dao->civicrm_line_item_participant_count_count
) {
$row[$key] = $dao->civicrm_participant_fee_amount_sum /
$dao->civicrm_line_item_participant_count_count;
}
}
elseif ($key == 'civicrm_line_item_line_total_avg') {
if ($dao->civicrm_line_item_line_total_sum &&
$dao->civicrm_line_item_participant_count_count
) {
$row[$key] = $dao->civicrm_line_item_line_total_sum /
$dao->civicrm_line_item_participant_count_count;
}
}
else {
if (isset($dao->$key)) {
$row[$key] = $dao->$key;
}
}
}
$rows[] = $row;
}
// do not call pager here
$this->formatDisplay($rows, FALSE);
unset($this->_columnHeaders['civicrm_event_id']);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* @param $rows
*/
public function buildChart(&$rows) {
$this->_interval = 'events';
$countEvent = NULL;
if (!empty($this->_params['charts'])) {
foreach ($rows as $key => $value) {
if ($value['civicrm_event_id']) {
$graphRows['totalParticipants'][] = ($rows[$key]['civicrm_line_item_participant_count_count']);
$graphRows[$this->_interval][] = substr($rows[$key]['civicrm_event_title'], 0, 12) . "..(" .
$rows[$key]['civicrm_event_id'] . ") ";
$graphRows['value'][] = ($rows[$key]['civicrm_line_item_participant_count_count']);
}
}
if (($rows[$key]['civicrm_line_item_participant_count_count']) == 0) {
$countEvent = count($rows);
}
if ((!empty($rows)) && $countEvent != 1) {
$chartInfo = array(
'legend' => 'Participants Summary',
'xname' => 'Event',
'yname' => 'Total Participants',
);
if (!empty($graphRows)) {
foreach ($graphRows[$this->_interval] as $key => $val) {
$graph[$val] = $graphRows['value'][$key];
}
$chartInfo['values'] = $graph;
$chartInfo['tip'] = 'Participants : #val#';
$chartInfo['xLabelAngle'] = 20;
// build the chart.
CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
}
}
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
if (is_array($rows)) {
$eventType = CRM_Core_OptionGroup::values('event_type');
foreach ($rows as $rowNum => $row) {
if (array_key_exists('civicrm_event_title', $row)) {
if ($value = $row['civicrm_event_id']) {
CRM_Event_PseudoConstant::event($value, FALSE);
$url = CRM_Report_Utils_Report::getNextUrl('event/participantlist',
'reset=1&force=1&event_id_op=eq&event_id_value=' . $value,
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_event_title_link'] = $url;
$rows[$rowNum]['civicrm_event_title_hover'] = ts("View Event Participants For this Event");
}
}
//handle event type
if (array_key_exists('civicrm_event_event_type_id', $row)) {
if ($value = $row['civicrm_event_event_type_id']) {
$rows[$rowNum]['civicrm_event_event_type_id'] = $eventType[$value];
}
}
}
}
}
}

View file

@ -0,0 +1,633 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Event_ParticipantListCount extends CRM_Report_Form_Event {
protected $_summary = NULL;
protected $_groupFilter = TRUE;
protected $_tagFilter = TRUE;
protected $_customGroupExtends = array(
'Participant',
'Event',
);
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
public $_drilldownReport = array('event/income' => 'Link to Detail Report');
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Name'),
'default' => TRUE,
'no_repeat' => TRUE,
'required' => TRUE,
),
'first_name' => array(
'title' => ts('First Name'),
),
'middle_name' => array(
'title' => ts('Middle Name'),
),
'last_name' => array(
'title' => ts('Last Name'),
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
),
'age' => array(
'title' => ts('Age'),
'dbAlias' => 'TIMESTAMPDIFF(YEAR, contact_civireport.birth_date, CURDATE())',
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Participant Name'),
'operator' => 'like',
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
'gender_id' => array(
'title' => ts('Gender'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'),
),
'birth_date' => array(
'title' => ts('Birth Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'grouping' => 'contact-fields',
'order_bys' => array(
'sort_name' => array(
'title' => ts('Last Name, First Name'),
'default' => '1',
'default_weight' => '0',
'default_order' => 'ASC',
),
'first_name' => array(
'name' => 'first_name',
'title' => ts('First Name'),
),
'gender_id' => array(
'name' => 'gender_id',
'title' => ts('Gender'),
),
'birth_date' => array(
'name' => 'birth_date',
'title' => ts('Birth Date'),
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
),
'civicrm_employer' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'grouping' => 'contact-fields',
'fields' => array(
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'organization_name' => array(
'title' => ts('Employer'),
'default' => TRUE,
'no_repeat' => TRUE,
),
),
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
'filters' => array(
'email' => array(
'title' => ts('Participant E-mail'),
'operator' => 'like',
),
),
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'grouping' => 'contact-fields',
'fields' => array(
'phone' => array(
'title' => ts('Phone No'),
'default' => TRUE,
),
),
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'fields' => array(
'street_address' => NULL,
'city' => NULL,
'postal_code' => NULL,
'state_province_id' => array(
'title' => ts('State/Province'),
),
'country_id' => array(
'title' => ts('Country'),
),
),
'grouping' => 'contact-fields',
),
'civicrm_participant' => array(
'dao' => 'CRM_Event_DAO_Participant',
'fields' => array(
'participant_id' => array(
'title' => ts('Participant ID'),
'default' => TRUE,
),
'event_id' => array(
'title' => ts('Event'),
'type' => CRM_Utils_Type::T_STRING,
),
'role_id' => array(
'title' => ts('Role'),
'default' => TRUE,
),
'status_id' => array(
'title' => ts('Status'),
'default' => TRUE,
),
'participant_register_date' => array(
'title' => ts('Registration Date'),
),
),
'grouping' => 'event-fields',
'filters' => array(
'event_id' => array(
'name' => 'event_id',
'title' => ts('Event'),
'operatorType' => CRM_Report_Form::OP_ENTITYREF,
'type' => CRM_Utils_Type::T_INT,
'attributes' => array(
'entity' => 'event',
'select' => array('minimumInputLength' => 0),
),
),
'sid' => array(
'name' => 'status_id',
'title' => ts('Participant Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Event_PseudoConstant::participantStatus(NULL, NULL, 'label'),
),
'rid' => array(
'name' => 'role_id',
'title' => ts('Participant Role'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT_SEPARATOR,
'type' => CRM_Utils_Type::T_INT,
'options' => CRM_Event_PseudoConstant::participantRole(),
),
'participant_register_date' => array(
'title' => ts('Registration Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
'group_bys' => array(
'event_id' => array(
'title' => ts('Event'),
),
),
),
'civicrm_event' => array(
'dao' => 'CRM_Event_DAO_Event',
'fields' => array(
'event_type_id' => array(
'title' => ts('Event Type'),
),
'start_date' => array(
'title' => ts('Event Start Date'),
),
'end_date' => array(
'title' => ts('Event End Date'),
),
),
'grouping' => 'event-fields',
'filters' => array(
'eid' => array(
'name' => 'event_type_id',
'title' => ts('Event Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('event_type'),
),
'event_start_date' => array(
'name' => 'event_start_date',
'title' => ts('Event Start Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'event_end_date' => array(
'name' => 'event_end_date',
'title' => ts('Event End Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
'group_bys' => array(
'event_type_id' => array(
'title' => ts('Event Type '),
),
),
),
'civicrm_line_item' => array(
'dao' => 'CRM_Price_DAO_LineItem',
'fields' => array(
'line_total' => array(
'title' => ts('Income'),
'default' => TRUE,
'statistics' => array(
'sum' => ts('Amount'),
'avg' => ts('Average'),
),
),
'participant_count' => array(
'title' => ts('Count'),
'default' => TRUE,
'statistics' => array(
'sum' => ts('Count'),
),
),
),
),
);
$this->_options = array(
'blank_column_begin' => array(
'title' => ts('Blank column at the Begining'),
'type' => 'checkbox',
),
'blank_column_end' => array(
'title' => ts('Blank column at the End'),
'type' => 'select',
'options' => array(
'' => '-select-',
1 => ts('One'),
2 => ts('Two'),
3 => ts('Three'),
),
),
);
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
/**
* Add The statistics.
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
$avg = NULL;
$select = " SELECT SUM( {$this->_aliases['civicrm_line_item']}.participant_count ) as count,
SUM( {$this->_aliases['civicrm_line_item']}.line_total ) as amount
";
$sql = "{$select} {$this->_from} {$this->_where}";
$dao = CRM_Core_DAO::executeQuery($sql);
if ($dao->fetch()) {
if ($dao->count && $dao->amount) {
$avg = $dao->amount / $dao->count;
}
$statistics['counts']['count'] = array(
'value' => $dao->count,
'title' => ts('Total Participants'),
'type' => CRM_Utils_Type::T_INT,
);
$statistics['counts']['amount'] = array(
'value' => $dao->amount,
'title' => ts('Total Income'),
'type' => CRM_Utils_Type::T_MONEY,
);
$statistics['counts']['avg'] = array(
'value' => $avg,
'title' => ts('Average'),
'type' => CRM_Utils_Type::T_MONEY,
);
}
return $statistics;
}
public function select() {
$select = array();
$this->_columnHeaders = array();
//add blank column at the Start
if (array_key_exists('options', $this->_params) &&
!empty($this->_params['options']['blank_column_begin'])
) {
$select[] = " '' as blankColumnBegin";
$this->_columnHeaders['blankColumnBegin']['title'] = '_ _ _ _';
}
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if (!empty($field['statistics'])) {
foreach ($field['statistics'] as $stat => $label) {
switch (strtolower($stat)) {
case 'sum':
$select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = CRM_Utils_Type::T_INT;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
}
}
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
}
//add blank column at the end
if ($blankcols = CRM_Utils_Array::value('blank_column_end', $this->_params)) {
for ($i = 1; $i <= $blankcols; $i++) {
$select[] = " '' as blankColumnEnd_{$i}";
$this->_columnHeaders["blank_{$i}"]['title'] = "_ _ _ _";
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = $grouping = array();
return $errors;
}
public function from() {
$this->_from = "
FROM civicrm_participant {$this->_aliases['civicrm_participant']}
LEFT JOIN civicrm_event {$this->_aliases['civicrm_event']}
ON ({$this->_aliases['civicrm_event']}.id = {$this->_aliases['civicrm_participant']}.event_id ) AND {$this->_aliases['civicrm_event']}.is_template = 0
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON ({$this->_aliases['civicrm_participant']}.contact_id = {$this->_aliases['civicrm_contact']}.id )
{$this->_aclFrom}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_employer']}
ON ({$this->_aliases['civicrm_employer']}.id = {$this->_aliases['civicrm_contact']}.employer_id )
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1)
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1
LEFT JOIN civicrm_line_item {$this->_aliases['civicrm_line_item']}
ON {$this->_aliases['civicrm_line_item']}.entity_table = 'civicrm_participant' AND {$this->_aliases['civicrm_participant']}.id ={$this->_aliases['civicrm_line_item']}.entity_id";
}
public function storeWhereHavingClauseArray() {
parent::storeWhereHavingClauseArray();
$this->_whereClauses[] = "{$this->_aliases['civicrm_participant']}.is_test = 0";
}
public function groupBy() {
// We override this function because we use GROUP functions in the
// SELECT clause, therefore we have to group by *something*. If the
// user doesn't select a column to group by, we should group by participant id.
parent::groupBy();
if (empty($this->_groupBy)) {
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, "{$this->_aliases['civicrm_participant']}.id");
}
}
public function postProcess() {
// get ready with post process params
$this->beginPostProcess();
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
// build query
$sql = $this->buildQuery(TRUE);
// build array of result based on column headers. This method also allows
// modifying column headers before using it to build result set i.e $rows.
$this->buildRows($sql, $rows);
// format result set.
$this->formatDisplay($rows);
// assign variables to templates
$this->doTemplateAssignment($rows);
// do print / pdf / instance stuff if needed
$this->endPostProcess($rows);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$eventType = CRM_Core_OptionGroup::values('event_type');
foreach ($rows as $rowNum => $row) {
// convert sort name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
if ($value = $row['civicrm_contact_sort_name']) {
$url = CRM_Utils_System::url("civicrm/contact/view",
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact Summary for this Contact.");
}
$entryFound = TRUE;
}
// convert participant ID to links
if (array_key_exists('civicrm_participant_participant_id', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
if ($value = $row['civicrm_participant_participant_id']) {
$url = CRM_Utils_System::url("civicrm/contact/view/participant",
'reset=1&id=' . $row['civicrm_participant_participant_id'] .
'&cid=' . $row['civicrm_contact_id'] .
'&action=view&context=participant',
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_participant_participant_id_link'] = $url;
$rows[$rowNum]['civicrm_participant_participant_id_hover'] = ts("View Participant Record for this Contact.");
}
$entryFound = TRUE;
}
// convert event name to links
if (array_key_exists('civicrm_participant_event_id', $row)) {
if ($value = $row['civicrm_participant_event_id']) {
$rows[$rowNum]['civicrm_participant_event_id'] = CRM_Event_PseudoConstant::event($value, FALSE);
$url = CRM_Report_Utils_Report::getNextUrl('event/Income',
'reset=1&force=1&event_id_op=eq&event_id_value=' . $value,
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_participant_event_id_link'] = $url;
$rows[$rowNum]['civicrm_participant_event_id_hover'] = ts("View Event Income Details for this Event");
}
$entryFound = TRUE;
}
// handle event type id
if (array_key_exists('civicrm_event_event_type_id', $row)) {
if ($value = $row['civicrm_event_event_type_id']) {
$rows[$rowNum]['civicrm_event_event_type_id'] = $eventType[$value];
}
$entryFound = TRUE;
}
// handle participant status id
if (array_key_exists('civicrm_participant_status_id', $row)) {
if ($value = $row['civicrm_participant_status_id']) {
$rows[$rowNum]['civicrm_participant_status_id'] = CRM_Event_PseudoConstant::participantStatus($value, FALSE);
}
$entryFound = TRUE;
}
// handle participant role id
if (array_key_exists('civicrm_participant_role_id', $row)) {
if ($value = $row['civicrm_participant_role_id']) {
$roles = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
$value = array();
foreach ($roles as $role) {
$value[$role] = CRM_Event_PseudoConstant::participantRole($role, FALSE);
}
$rows[$rowNum]['civicrm_participant_role_id'] = implode(', ', $value);
}
$entryFound = TRUE;
}
//handle gender
if (array_key_exists('civicrm_contact_gender_id', $row)) {
if ($value = $row['civicrm_contact_gender_id']) {
$gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
$rows[$rowNum]['civicrm_contact_gender_id'] = $gender[$value];
}
$entryFound = TRUE;
}
// display birthday in the configured custom format
if (array_key_exists('civicrm_contact_birth_date', $row)) {
$birthDate = $row['civicrm_contact_birth_date'];
if ($birthDate) {
$rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
}
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,790 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Event_ParticipantListing extends CRM_Report_Form_Event {
protected $_summary = NULL;
protected $_contribField = FALSE;
protected $_groupFilter = TRUE;
protected $_tagFilter = TRUE;
protected $_balance = FALSE;
protected $activeCampaigns;
protected $_customGroupExtends = array(
'Participant',
'Contact',
'Individual',
'Event',
);
public $_drilldownReport = array('event/income' => 'Link to Detail Report');
/**
* Class constructor.
*/
public function __construct() {
$this->_autoIncludeIndexedFieldsAsOrderBys = 1;
// Check if CiviCampaign is a) enabled and b) has active campaigns
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array_merge(array(
// CRM-17115 - to avoid changing report output at this stage re-instate
// old field name for sort name
'sort_name_linked' => array(
'title' => ts('Participant Name'),
'required' => TRUE,
'no_repeat' => TRUE,
'dbAlias' => 'contact_civireport.sort_name',
)),
$this->getBasicContactFields(),
array(
'age_at_event' => array(
'title' => ts('Age at Event'),
'dbAlias' => 'TIMESTAMPDIFF(YEAR, contact_civireport.birth_date, event_civireport.start_date)',
),
)
),
'grouping' => 'contact-fields',
'order_bys' => array(
'sort_name' => array(
'title' => ts('Last Name, First Name'),
'default' => '1',
'default_weight' => '0',
'default_order' => 'ASC',
),
'first_name' => array(
'name' => 'first_name',
'title' => ts('First Name'),
),
'gender_id' => array(
'name' => 'gender_id',
'title' => ts('Gender'),
),
'birth_date' => array(
'name' => 'birth_date',
'title' => ts('Birth Date'),
),
'age_at_event' => array(
'name' => 'age_at_event',
'title' => ts('Age at Event'),
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'filters' => CRM_Report_Form::getBasicContactFilters(),
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
'filters' => array(
'email' => array(
'title' => ts('Participant E-mail'),
'operator' => 'like',
),
),
),
);
$this->_columns += $this->getAddressColumns();
$this->_columns += array(
'civicrm_participant' => array(
'dao' => 'CRM_Event_DAO_Participant',
'fields' => array(
'participant_id' => array('title' => ts('Participant ID')),
'participant_record' => array(
'name' => 'id',
'no_display' => TRUE,
'required' => TRUE,
),
'event_id' => array(
'default' => TRUE,
'type' => CRM_Utils_Type::T_STRING,
),
'status_id' => array(
'title' => ts('Status'),
'default' => TRUE,
),
'role_id' => array(
'title' => ts('Role'),
'default' => TRUE,
),
'fee_currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'registered_by_id' => array(
'title' => ts('Registered by Participant ID'),
),
'source' => array(
'title' => ts('Source'),
),
'participant_fee_level' => NULL,
'participant_fee_amount' => array('title' => ts('Participant Fee')),
'participant_register_date' => array('title' => ts('Registration Date')),
'total_paid' => array(
'title' => ts('Total Paid'),
'dbAlias' => 'IFNULL(SUM(ft.total_amount), 0)',
'type' => 1024,
),
'balance' => array(
'title' => ts('Balance'),
'dbAlias' => 'participant_civireport.fee_amount - IFNULL(SUM(ft.total_amount), 0)',
'type' => 1024,
),
),
'grouping' => 'event-fields',
'filters' => array(
'event_id' => array(
'name' => 'event_id',
'title' => ts('Event'),
'operatorType' => CRM_Report_Form::OP_ENTITYREF,
'type' => CRM_Utils_Type::T_INT,
'attributes' => array(
'entity' => 'event',
'select' => array('minimumInputLength' => 0),
),
),
'sid' => array(
'name' => 'status_id',
'title' => ts('Participant Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Event_PseudoConstant::participantStatus(NULL, NULL, 'label'),
),
'rid' => array(
'name' => 'role_id',
'title' => ts('Participant Role'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Event_PseudoConstant::participantRole(),
),
'participant_register_date' => array(
'title' => ts('Registration Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'fee_currency' => array(
'title' => ts('Fee Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'registered_by_id' => array(
'title' => ts('Registered by Participant ID'),
'type' => CRM_Utils_Type::T_STRING,
'operator' => 'like',
),
'source' => array(
'title' => ts('Source'),
'type' => CRM_Utils_Type::T_STRING,
'operator' => 'like',
),
),
'order_bys' => array(
'participant_register_date' => array(
'title' => ts('Registration Date'),
'default_weight' => '1',
'default_order' => 'ASC',
),
'event_id' => array(
'title' => ts('Event'),
'default_weight' => '1',
'default_order' => 'ASC',
),
),
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array(
'phone' => array(
'title' => ts('Phone'),
'default' => TRUE,
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_event' => array(
'dao' => 'CRM_Event_DAO_Event',
'fields' => array(
'event_type_id' => array(
'title' => ts('Event Type'),
),
'event_start_date' => array(
'title' => ts('Event Start Date'),
),
'event_end_date' => array(
'title' => ts('Event End Date'),
),
),
'grouping' => 'event-fields',
'filters' => array(
'eid' => array(
'name' => 'event_type_id',
'title' => ts('Event Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('event_type'),
),
'event_start_date' => array(
'title' => ts('Event Start Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'event_end_date' => array(
'title' => ts('Event End Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
'order_bys' => array(
'event_type_id' => array(
'title' => ts('Event Type'),
'default_weight' => '2',
'default_order' => 'ASC',
),
'event_start_date' => array(
'title' => ts('Event Start Date'),
),
),
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'contribution_id' => array(
'name' => 'id',
'no_display' => TRUE,
'required' => TRUE,
'csv_display' => TRUE,
'title' => ts('Contribution ID'),
),
'financial_type_id' => array('title' => ts('Financial Type')),
'receive_date' => array('title' => ts('Payment Date')),
'contribution_status_id' => array('title' => ts('Contribution Status')),
'payment_instrument_id' => array('title' => ts('Payment Type')),
'contribution_source' => array(
'name' => 'source',
'title' => ts('Contribution Source'),
),
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'trxn_id' => NULL,
'fee_amount' => array('title' => ts('Transaction Fee')),
'net_amount' => NULL,
),
'grouping' => 'contrib-fields',
'filters' => array(
'receive_date' => array(
'title' => ts('Payment Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialType(),
),
'currency' => array(
'title' => ts('Contribution Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'payment_instrument_id' => array(
'title' => ts('Payment Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::paymentInstrument(),
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => NULL,
),
),
),
'civicrm_line_item' => array(
'dao' => 'CRM_Price_DAO_LineItem',
'grouping' => 'priceset-fields',
'filters' => array(
'price_field_value_id' => array(
'name' => 'price_field_value_id',
'title' => ts('Fee Level'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->getPriceLevels(),
),
),
),
);
$this->_options = array(
'blank_column_begin' => array(
'title' => ts('Blank column at the Begining'),
'type' => 'checkbox',
),
'blank_column_end' => array(
'title' => ts('Blank column at the End'),
'type' => 'select',
'options' => array(
'' => ts('-select-'),
1 => ts('One'),
2 => ts('Two'),
3 => ts('Three'),
),
),
);
// CRM-17115 avoid duplication of sort_name - would be better to standardise name
// & behaviour across reports but trying for no change at this point.
$this->_columns['civicrm_contact']['fields']['sort_name']['no_display'] = TRUE;
// If we have active campaigns add those elements to both the fields and filters
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_participant']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
);
$this->_columns['civicrm_participant']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
$this->_columns['civicrm_participant']['order_bys']['campaign_id'] = array(
'title' => ts('Campaign'),
);
}
$this->_currencyColumn = 'civicrm_participant_fee_currency';
parent::__construct();
}
/**
* Searches database for priceset values.
*
* @return array
*/
public function getPriceLevels() {
$query = "
SELECT CONCAT(cv.label, ' (', ps.title, ' - ', cf.label , ')') label, cv.id
FROM civicrm_price_field_value cv
LEFT JOIN civicrm_price_field cf
ON cv.price_field_id = cf.id
LEFT JOIN civicrm_price_set_entity ce
ON ce.price_set_id = cf.price_set_id
LEFT JOIN civicrm_price_set ps
ON ce.price_set_id = ps.id
WHERE ce.entity_table = 'civicrm_event'
ORDER BY cv.label
";
$dao = CRM_Core_DAO::executeQuery($query);
$elements = array();
while ($dao->fetch()) {
$elements[$dao->id] = "$dao->label\n";
}
return $elements;
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
//add blank column at the Start
if (array_key_exists('options', $this->_params) &&
!empty($this->_params['options']['blank_column_begin'])
) {
$select[] = " '' as blankColumnBegin";
$this->_columnHeaders['blankColumnBegin']['title'] = '_ _ _ _';
}
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_contribution') {
$this->_contribField = TRUE;
}
if ($fieldName == 'total_paid' || $fieldName == 'balance') {
$this->_balance = TRUE;
// modify the select if filtered by fee_level as the from clause
// already selects the total_amount from civicrm_contribution table
if (!empty($this->_params['price_field_value_id_value'])) {
$field['dbAlias'] = str_replace('SUM(ft.total_amount)', 'ft.total_amount', $field['dbAlias']);
}
}
$alias = "{$tableName}_{$fieldName}";
$select[] = "{$field['dbAlias']} as $alias";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = CRM_Utils_Array::value('no_display', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
$this->_selectAliases[] = $alias;
}
}
}
}
//add blank column at the end
$blankcols = CRM_Utils_Array::value('blank_column_end', $this->_params);
if ($blankcols) {
for ($i = 1; $i <= $blankcols; $i++) {
$select[] = " '' as blankColumnEnd_{$i}";
$this->_columnHeaders["blank_{$i}"]['title'] = "_ _ _ _";
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = $grouping = array();
return $errors;
}
public function from() {
$this->_from = "
FROM civicrm_participant {$this->_aliases['civicrm_participant']}
LEFT JOIN civicrm_event {$this->_aliases['civicrm_event']}
ON ({$this->_aliases['civicrm_event']}.id = {$this->_aliases['civicrm_participant']}.event_id ) AND
{$this->_aliases['civicrm_event']}.is_template = 0
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON ({$this->_aliases['civicrm_participant']}.contact_id = {$this->_aliases['civicrm_contact']}.id )
{$this->_aclFrom}
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1)
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1
";
if ($this->_contribField) {
$this->_from .= "
LEFT JOIN civicrm_participant_payment pp
ON ({$this->_aliases['civicrm_participant']}.id = pp.participant_id)
LEFT JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON (pp.contribution_id = {$this->_aliases['civicrm_contribution']}.id)
";
}
if (!empty($this->_params['price_field_value_id_value'])) {
$this->_from .= "
LEFT JOIN civicrm_line_item line_item_civireport
ON line_item_civireport.entity_table = 'civicrm_participant' AND
line_item_civireport.entity_id = {$this->_aliases['civicrm_participant']}.id AND
line_item_civireport.qty > 0
";
}
if ($this->_balance) {
$this->_from .= "
LEFT JOIN civicrm_entity_financial_trxn eft
ON (eft.entity_id = {$this->_aliases['civicrm_contribution']}.id)
LEFT JOIN civicrm_financial_trxn ft
ON (ft.id = eft.financial_trxn_id AND eft.entity_table = 'civicrm_contribution') AND
(ft.is_payment = 1)
";
}
}
public function where() {
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($relative || $from || $to) {
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($fieldName == 'rid') {
$value = CRM_Utils_Array::value("{$fieldName}_value", $this->_params);
if (!empty($value)) {
$operator = '';
if ($op == 'notin') {
$operator = 'NOT';
}
$regexp = "[[:cntrl:]]*" . implode('[[:>:]]*|[[:<:]]*', $value) . "[[:cntrl:]]*";
$clause = "{$field['dbAlias']} {$operator} REGEXP '{$regexp}'";
}
$op = NULL;
}
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE {$this->_aliases['civicrm_participant']}.is_test = 0 ";
}
else {
$this->_where = "WHERE {$this->_aliases['civicrm_participant']}.is_test = 0 AND " .
implode(' AND ', $clauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
public function groupBy() {
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, "{$this->_aliases['civicrm_participant']}.id");
}
public function postProcess() {
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
parent::postProcess();
}
/**
* @param $rows
* @param $entryFound
* @param $row
* @param int $rowId
* @param $rowNum
* @param $types
*
* @return bool
*/
private function _initBasicRow(&$rows, &$entryFound, $row, $rowId, $rowNum, $types) {
if (!array_key_exists($rowId, $row)) {
return FALSE;
}
$value = $row[$rowId];
if ($value) {
$rows[$rowNum][$rowId] = $types[$value];
}
$entryFound = TRUE;
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$eventType = CRM_Core_OptionGroup::values('event_type');
$financialTypes = CRM_Contribute_PseudoConstant::financialType();
$contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus();
$paymentInstruments = CRM_Contribute_PseudoConstant::paymentInstrument();
foreach ($rows as $rowNum => $row) {
// make count columns point to detail report
// convert display name to links
if (array_key_exists('civicrm_participant_event_id', $row)) {
$eventId = $row['civicrm_participant_event_id'];
if ($eventId) {
$rows[$rowNum]['civicrm_participant_event_id'] = CRM_Event_PseudoConstant::event($eventId, FALSE);
$url = CRM_Report_Utils_Report::getNextUrl('event/income',
'reset=1&force=1&id_op=in&id_value=' . $eventId,
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_participant_event_id_link'] = $url;
$rows[$rowNum]['civicrm_participant_event_id_hover'] = ts("View Event Income Details for this Event");
}
$entryFound = TRUE;
}
// handle event type id
$this->_initBasicRow($rows, $entryFound, $row, 'civicrm_event_event_type_id', $rowNum, $eventType);
// handle participant status id
if (array_key_exists('civicrm_participant_status_id', $row)) {
$statusId = $row['civicrm_participant_status_id'];
if ($statusId) {
$rows[$rowNum]['civicrm_participant_status_id'] = CRM_Event_PseudoConstant::participantStatus($statusId, FALSE, 'label');
}
$entryFound = TRUE;
}
// handle participant role id
if (array_key_exists('civicrm_participant_role_id', $row)) {
$roleId = $row['civicrm_participant_role_id'];
if ($roleId) {
$roles = explode(CRM_Core_DAO::VALUE_SEPARATOR, $roleId);
$roleId = array();
foreach ($roles as $role) {
$roleId[$role] = CRM_Event_PseudoConstant::participantRole($role, FALSE);
}
$rows[$rowNum]['civicrm_participant_role_id'] = implode(', ', $roleId);
}
$entryFound = TRUE;
}
// Handel value seperator in Fee Level
if (array_key_exists('civicrm_participant_participant_fee_level', $row)) {
$feeLevel = $row['civicrm_participant_participant_fee_level'];
if ($feeLevel) {
CRM_Event_BAO_Participant::fixEventLevel($feeLevel);
$rows[$rowNum]['civicrm_participant_participant_fee_level'] = $feeLevel;
}
$entryFound = TRUE;
}
// Convert display name to link
$displayName = CRM_Utils_Array::value('civicrm_contact_sort_name_linked', $row);
$cid = CRM_Utils_Array::value('civicrm_contact_id', $row);
$id = CRM_Utils_Array::value('civicrm_participant_participant_record', $row);
if ($displayName && $cid && $id) {
$url = CRM_Report_Utils_Report::getNextUrl('contact/detail',
"reset=1&force=1&id_op=eq&id_value=$cid",
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$viewUrl = CRM_Utils_System::url("civicrm/contact/view/participant",
"reset=1&id=$id&cid=$cid&action=view&context=participant"
);
$contactTitle = ts('View Contact Details');
$participantTitle = ts('View Participant Record');
$rows[$rowNum]['civicrm_contact_sort_name_linked'] = "<a title='$contactTitle' href=$url>$displayName</a>";
// Add a "View" link to the participant record if this isn't a CSV/PDF/printed document.
if ($this->_outputMode !== 'csv' && $this->_outputMode !== 'pdf' && $this->_outputMode !== 'print') {
$rows[$rowNum]['civicrm_contact_sort_name_linked'] .=
"<span style='float: right;'><a title='$participantTitle' href=$viewUrl>" .
ts('View') . "</a></span>";
}
$entryFound = TRUE;
}
// Handle employer id
if (array_key_exists('civicrm_contact_employer_id', $row)) {
$employerId = $row['civicrm_contact_employer_id'];
if ($employerId) {
$rows[$rowNum]['civicrm_contact_employer_id'] = CRM_Contact_BAO_Contact::displayName($employerId);
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $employerId, $this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_employer_id_link'] = $url;
$rows[$rowNum]['civicrm_contact_employer_id_hover'] = ts('View Contact Summary for this Contact.');
}
}
// Convert campaign_id to campaign title
$this->_initBasicRow($rows, $entryFound, $row, 'civicrm_participant_campaign_id', $rowNum, $this->activeCampaigns);
// handle contribution status
$this->_initBasicRow($rows, $entryFound, $row, 'civicrm_contribution_contribution_status_id', $rowNum, $contributionStatus);
// handle payment instrument
$this->_initBasicRow($rows, $entryFound, $row, 'civicrm_contribution_payment_instrument_id', $rowNum, $paymentInstruments);
// handle financial type
$this->_initBasicRow($rows, $entryFound, $row, 'civicrm_contribution_financial_type_id', $rowNum, $financialTypes);
$entryFound = $this->alterDisplayContactFields($row, $rows, $rowNum, 'event/participantListing', 'View Event Income Details') ? TRUE : $entryFound;
// display birthday in the configured custom format
if (array_key_exists('civicrm_contact_birth_date', $row)) {
$birthDate = $row['civicrm_contact_birth_date'];
if ($birthDate) {
$rows[$rowNum]['civicrm_contact_birth_date'] = CRM_Utils_Date::customFormat($birthDate, '%Y%m%d');
}
$entryFound = TRUE;
}
$entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'event/ParticipantListing', 'List all participant(s) for this ') ? TRUE : $entryFound;
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,420 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Event_Summary extends CRM_Report_Form_Event {
protected $_summary = NULL;
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
protected $_add2groupSupported = FALSE;
protected $_customGroupExtends = array(
'Event',
);
public $_drilldownReport = array('event/income' => 'Link to Detail Report');
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_event' => array(
'dao' => 'CRM_Event_DAO_Event',
'fields' => array(
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'title' => array(
'title' => ts('Event Title'),
'required' => TRUE,
),
'event_type_id' => array(
'title' => ts('Event Type'),
'required' => TRUE,
),
'fee_label' => array('title' => ts('Fee Label')),
'event_start_date' => array(
'title' => ts('Event Start Date'),
),
'event_end_date' => array('title' => ts('Event End Date')),
'max_participants' => array(
'title' => ts('Capacity'),
'type' => CRM_Utils_Type::T_INT,
),
),
'filters' => array(
'id' => array(
'title' => ts('Event'),
'operatorType' => CRM_Report_Form::OP_ENTITYREF,
'type' => CRM_Utils_Type::T_INT,
'attributes' => array('select' => array('minimumInputLength' => 0)),
),
'event_type_id' => array(
'name' => 'event_type_id',
'title' => ts('Event Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('event_type'),
),
'event_start_date' => array(
'title' => ts('Event Start Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'event_end_date' => array(
'title' => ts('Event End Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
),
);
$this->_currencyColumn = 'civicrm_participant_fee_currency';
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
}
}
}
}
$this->_selectClauses = $select;
$this->_select = 'SELECT ' . implode(', ', $select);
}
public function from() {
$this->_from = " FROM civicrm_event {$this->_aliases['civicrm_event']} ";
}
public function where() {
$clauses = array();
$this->_participantWhere = "";
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($relative || $from || $to) {
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($this->_params['id_value'])) {
$idValue = is_array($this->_params['id_value']) ? implode(',', $this->_params['id_value']) : $this->_params['id_value'];
$this->_participantWhere = " AND civicrm_participant.event_id IN ( $idValue ) ";
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
$clauses[] = "{$this->_aliases['civicrm_event']}.is_template = 0";
$this->_where = 'WHERE ' . implode(' AND ', $clauses);
}
public function groupBy() {
$this->assign('chartSupported', TRUE);
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, "{$this->_aliases['civicrm_event']}.id");
}
/**
* get participants information for events.
* @return array
*/
public function participantInfo() {
$statusType1 = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 1');
$statusType2 = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 0');
$sql = "
SELECT civicrm_participant.event_id AS event_id,
civicrm_participant.status_id AS statusId,
COUNT( civicrm_participant.id ) AS participant,
SUM( civicrm_participant.fee_amount ) AS amount,
civicrm_participant.fee_currency
FROM civicrm_participant
WHERE civicrm_participant.is_test = 0
$this->_participantWhere
GROUP BY civicrm_participant.event_id,
civicrm_participant.status_id,
civicrm_participant.fee_currency";
$info = CRM_Core_DAO::executeQuery($sql);
$participant_data = $participant_info = $currency = array();
while ($info->fetch()) {
$participant_data[$info->event_id][$info->statusId]['participant'] = $info->participant;
$participant_data[$info->event_id][$info->statusId]['amount'] = $info->amount;
$currency[$info->event_id] = $info->fee_currency;
}
$amt = $particiType1 = $particiType2 = 0;
foreach ($participant_data as $event_id => $event_data) {
foreach ($event_data as $status_id => $data) {
if (array_key_exists($status_id, $statusType1)) {
//total income of event
$amt = $amt + $data['amount'];
//number of Registered/Attended participants
$particiType1 = $particiType1 + $data['participant'];
}
elseif (array_key_exists($status_id, $statusType2)) {
//number of No-show/Cancelled/Pending participants
$particiType2 = $particiType2 + $data['participant'];
}
}
$participant_info[$event_id]['totalAmount'] = $amt;
$participant_info[$event_id]['statusType1'] = $particiType1;
$participant_info[$event_id]['statusType2'] = $particiType2;
$participant_info[$event_id]['currency'] = $currency[$event_id];
$amt = $particiType1 = $particiType2 = 0;
}
return $participant_info;
}
/**
* Build header for table.
*/
public function buildColumnHeaders() {
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
}
}
}
}
$statusType1 = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 1', 'label');
$statusType2 = CRM_Event_PseudoConstant::participantStatus(NULL, 'is_counted = 0', 'label');
//make column header for participant status Registered/Attended
$type1_header = implode('/', $statusType1);
//make column header for participant status No-show/Cancelled/Pending
$type2_header = implode('/', $statusType2);
$this->_columnHeaders['statusType1'] = array(
'title' => $type1_header,
'type' => CRM_Utils_Type::T_INT,
);
$this->_columnHeaders['statusType2'] = array(
'title' => $type2_header,
'type' => CRM_Utils_Type::T_INT,
);
$this->_columnHeaders['totalAmount'] = array(
'title' => ts('Total Income'),
'type' => CRM_Utils_Type::T_STRING,
);
}
public function postProcess() {
$this->beginPostProcess();
$this->buildColumnHeaders();
$sql = $this->buildQuery(TRUE);
$dao = CRM_Core_DAO::executeQuery($sql);
//set pager before exicution of query in function participantInfo()
$this->setPager();
$rows = $graphRows = array();
$count = 0;
while ($dao->fetch()) {
$row = array();
foreach ($this->_columnHeaders as $key => $value) {
if (($key == 'civicrm_event_start_date') ||
($key == 'civicrm_event_end_date')
) {
//get event start date and end date in custom datetime format
$row[$key] = CRM_Utils_Date::customFormat($dao->$key);
}
else {
if (isset($dao->$key)) {
$row[$key] = $dao->$key;
}
}
}
$rows[] = $row;
}
if (!empty($rows)) {
$participant_info = $this->participantInfo();
foreach ($rows as $key => $value) {
if (array_key_exists($value['civicrm_event_id'], $participant_info)) {
foreach ($participant_info[$value['civicrm_event_id']] as $k => $v) {
$rows[$key][$k] = $v;
}
}
}
}
// do not call pager here
$this->formatDisplay($rows, FALSE);
unset($this->_columnHeaders['civicrm_event_id']);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* @param $rows
*/
public function buildChart(&$rows) {
$this->_interval = 'events';
$countEvent = NULL;
if (!empty($this->_params['charts'])) {
foreach ($rows as $key => $value) {
$graphRows['totalAmount'][] = $graphRows['value'][] = CRM_Utils_Array::value('totalAmount', $rows[$key]);
$graphRows[$this->_interval][] = substr($rows[$key]['civicrm_event_title'], 0, 12) . "..(" .
$rows[$key]['civicrm_event_id'] . ") ";
}
if (CRM_Utils_Array::value('totalAmount', $rows[$key]) == 0) {
$countEvent = count($rows);
}
if ((!empty($rows)) && $countEvent != 1) {
$config = CRM_Core_Config::Singleton();
$chartInfo = array(
'legend' => 'Event Summary',
'xname' => 'Event',
'yname' => "Total Amount ({$config->defaultCurrency})",
);
if (!empty($graphRows)) {
foreach ($graphRows[$this->_interval] as $key => $val) {
$graph[$val] = $graphRows['value'][$key];
}
$chartInfo['values'] = $graph;
$chartInfo['xLabelAngle'] = 20;
// build the chart.
CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
$this->assign('chartType', $this->_params['charts']);
}
}
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
if (is_array($rows)) {
$eventType = CRM_Core_OptionGroup::values('event_type');
foreach ($rows as $rowNum => $row) {
if (array_key_exists('totalAmount', $row) &&
array_key_exists('currency', $row)
) {
$rows[$rowNum]['totalAmount'] = CRM_Utils_Money::format($rows[$rowNum]['totalAmount'], $rows[$rowNum]['currency']);
}
if (array_key_exists('civicrm_event_title', $row)) {
if ($value = $row['civicrm_event_id']) {
//CRM_Event_PseudoConstant::event( $value, false );
$url = CRM_Report_Utils_Report::getNextUrl('event/income',
'reset=1&force=1&id_op=in&id_value=' . $value,
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_event_title_link'] = $url;
$rows[$rowNum]['civicrm_event_title_hover'] = ts('View Event Income For this Event');
}
}
//handle event type
if (array_key_exists('civicrm_event_event_type_id', $row)) {
if ($value = $row['civicrm_event_event_type_id']) {
$rows[$rowNum]['civicrm_event_event_type_id'] = $eventType[$value];
}
}
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,373 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Grant_Detail extends CRM_Report_Form {
protected $_addressField = FALSE;
protected $_customGroupExtends = array(
'Grant',
);
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'grouping' => 'contact-fields',
'filters' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'operator' => 'like',
),
'gender_id' => array(
'title' => ts('Gender'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'),
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
),
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'filters' => array(
'country_id' => array(
'title' => ts('Country'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::country(),
),
'state_province_id' => array(
'title' => ts('State/Province'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::stateProvince(),
),
),
),
'civicrm_grant' => array(
'dao' => 'CRM_Grant_DAO_Grant',
'fields' => array(
'grant_type_id' => array(
'name' => 'grant_type_id',
'title' => ts('Grant Type'),
),
'status_id' => array(
'name' => 'status_id',
'title' => ts('Grant Status'),
),
'amount_total' => array(
'name' => 'amount_total',
'title' => ts('Amount Requested'),
'type' => CRM_Utils_Type::T_MONEY,
),
'amount_granted' => array(
'name' => 'amount_granted',
'title' => ts('Amount Granted'),
),
'application_received_date' => array(
'name' => 'application_received_date',
'title' => ts('Application Received'),
'default' => TRUE,
),
'money_transfer_date' => array(
'name' => 'money_transfer_date',
'title' => ts('Money Transfer Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'grant_due_date' => array(
'name' => 'grant_due_date',
'title' => ts('Grant Report Due'),
'type' => CRM_Utils_Type::T_DATE,
),
'decision_date' => array(
'name' => 'decision_date',
'title' => ts('Grant Decision Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'rationale' => array(
'name' => 'rationale',
'title' => ts('Rationale'),
),
'grant_report_received' => array(
'name' => 'grant_report_received',
'title' => ts('Grant Report Received'),
),
),
'filters' => array(
'grant_type' => array(
'name' => 'grant_type_id',
'title' => ts('Grant Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Grant_DAO_Grant', 'grant_type_id'),
),
'status_id' => array(
'name' => 'status_id',
'title' => ts('Grant Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Grant_DAO_Grant', 'status_id'),
),
'amount_granted' => array(
'title' => ts('Amount Granted'),
'operatorType' => CRM_Report_Form::OP_INT,
),
'amount_total' => array(
'title' => ts('Amount Requested'),
'operatorType' => CRM_Report_Form::OP_INT,
),
'application_received_date' => array(
'title' => ts('Application Received'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'money_transfer_date' => array(
'title' => ts('Money Transfer Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'grant_due_date' => array(
'title' => ts('Grant Report Due'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'decision_date' => array(
'title' => ts('Grant Decision Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
),
'group_bys' => array(
'grant_type_id' => array(
'title' => ts('Grant Type'),
),
'status_id' => array(
'title' => ts('Grant Status'),
),
'amount_total' => array(
'title' => ts('Amount Requested'),
),
'amount_granted' => array(
'title' => ts('Amount Granted'),
),
'application_received_date' => array(
'title' => ts('Application Received Date'),
),
'money_transfer_date' => array(
'title' => ts('Money Transfer Date'),
),
'decision_date' => array(
'title' => ts('Grant Decision Date'),
),
),
),
);
parent::__construct();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
}
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
}
}
}
}
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$this->_from = "
FROM civicrm_grant {$this->_aliases['civicrm_grant']}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON ({$this->_aliases['civicrm_grant']}.contact_id = {$this->_aliases['civicrm_contact']}.id ) ";
if ($this->_addressField) {
$this->_from .= "
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON {$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1\n";
}
}
public function where() {
$clauses = array();
$this->_where = '';
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($relative || $from || $to) {
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (!empty($clauses)) {
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
}
public function groupBy() {
$this->_groupBy = "";
if (!empty($this->_params['group_bys']) &&
is_array($this->_params['group_bys']) &&
!empty($this->_params['group_bys'])
) {
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('group_bys', $table)) {
foreach ($table['group_bys'] as $fieldName => $field) {
if (!empty($this->_params['group_bys'][$fieldName])) {
$this->_groupBy[] = $field['dbAlias'];
}
}
}
}
}
if (!empty($this->_groupBy)) {
$this->_groupBy = "ORDER BY " . implode(', ', $this->_groupBy) .
", {$this->_aliases['civicrm_contact']}.sort_name";
}
else {
$this->_groupBy = "ORDER BY {$this->_aliases['civicrm_contact']}.sort_name";
}
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View contact details for this record.");
$entryFound = TRUE;
}
if (array_key_exists('civicrm_grant_grant_type_id', $row)) {
if ($value = $row['civicrm_grant_grant_type_id']) {
$rows[$rowNum]['civicrm_grant_grant_type_id'] = CRM_Core_PseudoConstant::getLabel('CRM_Grant_DAO_Grant', 'grant_type_id', $value);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_grant_status_id', $row)) {
if ($value = $row['civicrm_grant_status_id']) {
$rows[$rowNum]['civicrm_grant_status_id'] = CRM_Core_PseudoConstant::getLabel('CRM_Grant_DAO_Grant', 'status_id', $value);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_grant_grant_report_received', $row)) {
if ($value = $row['civicrm_grant_grant_report_received']) {
if ($value == 1) {
$value = 'Yes';
}
else {
$value = 'No';
}
$rows[$rowNum]['civicrm_grant_grant_report_received'] = $value;
}
$entryFound = TRUE;
}
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,585 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Grant_Statistics extends CRM_Report_Form {
protected $_addressField = FALSE;
protected $_customGroupExtends = array('Grant');
protected $_add2groupSupported = FALSE;
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_grant' => array(
'dao' => 'CRM_Grant_DAO_Grant',
'fields' => array(
'summary_statistics' => array(
'name' => 'id',
'title' => ts('Summary Statistics'),
'required' => TRUE,
),
'grant_type_id' => array(
'name' => 'grant_type_id',
'title' => ts('By Grant Type'),
),
'status_id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'amount_total' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'grant_report_received' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'currency' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'filters' => array(
'application_received_date' => array(
'name' => 'application_received_date',
'title' => ts('Application Received'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'decision_date' => array(
'name' => 'decision_date',
'title' => ts('Grant Decision'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'money_transfer_date' => array(
'name' => 'money_transfer_date',
'title' => ts('Money Transferred'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'grant_due_date' => array(
'name' => 'grant_due_date',
'title' => ts('Grant Report Due'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'grant_type' => array(
'name' => 'grant_type_id',
'title' => ts('Grant Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Grant_DAO_Grant', 'grant_type_id'),
),
'status_id' => array(
'name' => 'status_id',
'title' => ts('Grant Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Grant_DAO_Grant', 'status_id'),
),
'amount_requested' => array(
'name' => 'amount_requested',
'title' => ts('Amount Requested'),
'type' => CRM_Utils_Type::T_MONEY,
),
'amount_granted' => array(
'name' => 'amount_granted',
'title' => ts('Amount Granted'),
),
'grant_report_received' => array(
'name' => 'grant_report_received',
'title' => ts('Report Received'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
'' => ts('- select -'),
0 => ts('No'),
1 => ts('Yes'),
),
),
),
),
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'id' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'gender_id' => array(
'name' => 'gender_id',
'title' => ts('By Gender'),
),
'contact_type' => array(
'name' => 'contact_type',
'title' => ts('By Contact Type'),
),
),
'filters' => array(
'gender_id' => array(
'name' => 'gender_id',
'title' => ts('Gender'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'),
),
'contact_type' => array(
'name' => 'contact_type',
'title' => ts('Contact Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contact_BAO_ContactType::basicTypePairs(),
),
),
'grouping' => 'contact-fields',
),
'civicrm_world_region' => array(
'dao' => 'CRM_Core_DAO_Worldregion',
'fields' => array(
'id' => array(
'no_display' => TRUE,
),
'name' => array(
'name' => 'name',
'title' => ts('By World Region'),
),
),
'filters' => array(
'region_id' => array(
'name' => 'id',
'title' => ts('World Region'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::worldRegion(),
),
),
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'fields' => array(
'country_id' => array(
'name' => 'country_id',
'title' => ts('By Country'),
),
),
'filters' => array(
'country_id' => array(
'title' => ts('Country'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::country(),
),
),
),
);
parent::__construct();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (in_array($tableName, array(
'civicrm_address',
'civicrm_world_region',
))) {
$this->_addressField = TRUE;
}
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$this->_from = "
FROM civicrm_grant {$this->_aliases['civicrm_grant']}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON ({$this->_aliases['civicrm_grant']}.contact_id = {$this->_aliases['civicrm_contact']}.id ) ";
if ($this->_addressField) {
$this->_from .= "
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON {$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1\n
LEFT JOIN civicrm_country country
ON {$this->_aliases['civicrm_address']}.country_id =
country.id
LEFT JOIN civicrm_worldregion {$this->_aliases['civicrm_world_region']}
ON country.region_id =
{$this->_aliases['civicrm_world_region']}.id";
}
}
public function where() {
$whereClause = "
WHERE {$this->_aliases['civicrm_grant']}.amount_total IS NOT NULL
AND {$this->_aliases['civicrm_grant']}.amount_total > 0";
$this->_where = $whereClause;
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($relative || $from || $to) {
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if (($fieldName == 'grant_report_received') &&
(CRM_Utils_Array::value("{$fieldName}_value", $this->_params) ===
0)
) {
$op = 'nll';
$this->_params["{$fieldName}_value"] = NULL;
}
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (!empty($clauses)) {
$this->_where = "WHERE " . implode(' AND ', $clauses);
$this->_whereClause = $whereClause . " AND " . implode(' AND ', $clauses);
}
}
public function groupBy() {
$this->_groupBy = '';
if (!empty($this->_params['fields']) &&
is_array($this->_params['fields']) &&
!empty($this->_params['fields'])
) {
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($this->_params['fields'][$fieldName])) {
$groupBy[] = $field['dbAlias'];
}
}
}
}
}
if (!empty($groupBy)) {
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
}
public function postProcess() {
// get ready with post process params
$this->beginPostProcess();
// build query, do not apply limit
$sql = $this->buildQuery(FALSE);
// build array of result based on column headers. This method also allows
// modifying column headers before using it to build result set i.e $rows.
$this->buildRows($sql, $rows);
// format result set.
$this->formatDisplay($rows);
// assign variables to templates
$this->doTemplateAssignment($rows);
// do print / pdf / instance stuff if needed
$this->endPostProcess($rows);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$totalStatistics = $grantStatistics = array();
$totalStatistics = parent::statistics($rows);
$awardedGrantsAmount = $grantsReceived = $totalAmount = $awardedGrants = $grantReportsReceived = 0;
$grantStatistics = array();
$grantTypes = CRM_Core_PseudoConstant::get('CRM_Grant_DAO_Grant', 'grant_type_id');
$countries = CRM_Core_PseudoConstant::country();
$gender = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id');
$grantAmountTotal = "
SELECT COUNT({$this->_aliases['civicrm_grant']}.id) as count ,
SUM({$this->_aliases['civicrm_grant']}.amount_total) as totalAmount
{$this->_from} ";
if (!empty($this->_whereClause)) {
$grantAmountTotal .= " {$this->_whereClause}";
}
$result = CRM_Core_DAO::executeQuery($grantAmountTotal);
while ($result->fetch()) {
$grantsReceived = $result->count;
$totalAmount = $result->totalAmount;
}
if (!$grantsReceived) {
return;
}
$grantAmountAwarded = "
SELECT COUNT({$this->_aliases['civicrm_grant']}.id) as count ,
SUM({$this->_aliases['civicrm_grant']}.amount_granted) as grantedAmount,
SUM({$this->_aliases['civicrm_grant']}.amount_total) as totalAmount
{$this->_from} ";
if (!empty($this->_where)) {
$grantAmountAwarded .= " {$this->_where}";
}
$values = CRM_Core_DAO::executeQuery($grantAmountAwarded);
while ($values->fetch()) {
$awardedGrants = $values->count;
$awardedGrantsAmount = $values->totalAmount;
$amountGranted = $values->grantedAmount;
}
foreach ($rows as $key => $values) {
if (!empty($values['civicrm_grant_grant_report_received'])) {
$grantReportsReceived++;
}
if (!empty($values['civicrm_grant_grant_type_id'])) {
$grantType = CRM_Utils_Array::value($values['civicrm_grant_grant_type_id'], $grantTypes);
$grantStatistics['civicrm_grant_grant_type_id']['title'] = ts('By Grant Type');
self::getStatistics($grantStatistics['civicrm_grant_grant_type_id'], $grantType, $values,
$awardedGrants, $awardedGrantsAmount
);
}
if (array_key_exists('civicrm_world_region_name', $values)) {
$region = CRM_Utils_Array::value('civicrm_world_region_name', $values);
$region = ($region) ? $region : 'Unassigned';
$grantStatistics['civicrm_world_region_name']['title'] = ts('By Region');
self::getStatistics($grantStatistics['civicrm_world_region_name'], $region, $values,
$awardedGrants, $awardedGrantsAmount
);
}
if (array_key_exists('civicrm_address_country_id', $values)) {
$country = CRM_Utils_Array::value($values['civicrm_address_country_id'], $countries);
$country = ($country) ? $country : 'Unassigned';
$grantStatistics['civicrm_address_country_id']['title'] = ts('By Country');
self::getStatistics($grantStatistics['civicrm_address_country_id'], $country, $values,
$awardedGrants, $awardedGrantsAmount
);
}
if ($type = CRM_Utils_Array::value('civicrm_contact_contact_type', $values)) {
$grantStatistics['civicrm_contact_contact_type']['title'] = ts('By Contact Type');
$title = "Total Number of {$type}(s)";
self::getStatistics($grantStatistics['civicrm_contact_contact_type'], $title, $values,
$awardedGrants, $awardedGrantsAmount
);
}
if (array_key_exists('civicrm_contact_gender_id', $values)) {
$genderLabel = CRM_Utils_Array::value($values['civicrm_contact_gender_id'], $gender);
$genderLabel = ($genderLabel) ? $genderLabel : 'Unassigned';
$grantStatistics['civicrm_contact_gender_id']['title'] = ts('By Gender');
self::getStatistics($grantStatistics['civicrm_contact_gender_id'], $genderLabel, $values,
$awardedGrants, $awardedGrantsAmount
);
}
foreach ($values as $customField => $customValue) {
if (strstr($customField, 'civicrm_value_')) {
$customFieldTitle = CRM_Utils_Array::value('title', $this->_columnHeaders[$customField]);
$customGroupTitle = explode('_custom', strstr($customField, 'civicrm_value_'));
$customGroupTitle = $this->_columns[$customGroupTitle[0]]['group_title'];
$grantStatistics[$customGroupTitle]['title'] = ts('By %1', array(1 => $customGroupTitle));
$customData = ($customValue) ? FALSE : TRUE;
self::getStatistics($grantStatistics[$customGroupTitle], $customFieldTitle, $values,
$awardedGrants, $awardedGrantsAmount, $customData
);
}
}
}
$totalStatistics['total_statistics'] = array(
'grants_received' => array(
'title' => ts('Grant Requests Received'),
'count' => $grantsReceived,
'amount' => $totalAmount,
),
'grants_awarded' => array(
'title' => ts('Grants Awarded'),
'count' => $awardedGrants,
'amount' => $amountGranted,
),
'grants_report_received' => array(
'title' => ts('Grant Reports Received'),
'count' => $grantReportsReceived,
),
);
$this->assign('totalStatistics', $totalStatistics);
$this->assign('grantStatistics', $grantStatistics);
if ($this->_outputMode == 'csv' ||
$this->_outputMode == 'pdf'
) {
$row = array();
$this->_columnHeaders = array(
'civicrm_grant_total_grants' => array('title' => ts('Summary')),
'civicrm_grant_count' => array('title' => ts('Count')),
'civicrm_grant_amount' => array('title' => ts('Amount')),
);
foreach ($totalStatistics['total_statistics'] as $title => $value) {
$row[] = array(
'civicrm_grant_total_grants' => $value['title'],
'civicrm_grant_count' => $value['count'],
'civicrm_grant_amount' => $value['amount'],
);
}
if (!empty($grantStatistics)) {
foreach ($grantStatistics as $key => $value) {
$row[] = array(
'civicrm_grant_total_grants' => $value['title'],
'civicrm_grant_count' => ts('Number of Grants') . ' (%)',
'civicrm_grant_amount' => ts('Total Amount') . ' (%)',
);
foreach ($value['value'] as $field => $values) {
foreach ($values['currency'] as $currency => $amount) {
$totalAmount[$currency] = $currency . $amount['value'] .
"({$values['percentage']}%)";
}
$totalAmt = implode(', ', $totalAmount);
$count = (boolean) CRM_Utils_Array::value('count', $values, 0) ? $values['count'] . " ({$values['percentage']}%)" : '';
$row[] = array(
'civicrm_grant_total_grants' => $field,
'civicrm_grant_count' => $count,
'civicrm_grant_amount' => $totalAmt,
);
}
}
}
$rows = $row;
}
}
/**
* @param $grantStatistics
* @param $fieldValue
* @param $values
* @param $awardedGrants
* @param $awardedGrantsAmount
* @param bool $customData
*/
public static function getStatistics(
&$grantStatistics, $fieldValue, $values,
$awardedGrants, $awardedGrantsAmount, $customData = FALSE
) {
if (!$awardedGrantsAmount) {
return;
}
$currencies = CRM_Core_PseudoConstant::get('CRM_Grant_DAO_Grant', 'currency', array('labelColumn' => 'symbol'));
$currency = $currencies[$values['civicrm_grant_currency']];
if (!$customData) {
if (!isset($grantStatistics['value'][$fieldValue]['currency'][$currency])
||
!isset($grantStatistics['value'][$fieldValue]['currency'][$currency]['value'])
) {
$grantStatistics['value'][$fieldValue]['currency'][$currency]['value'] = 0;
}
$grantStatistics['value'][$fieldValue]['currency'][$currency]['value'] += $values['civicrm_grant_amount_total'];
$grantStatistics['value'][$fieldValue]['currency'][$currency]['percentage'] = round(($grantStatistics['value'][$fieldValue]['currency'][$currency]['value'] /
$awardedGrantsAmount) * 100);
if (!isset($grantStatistics['value'][$fieldValue]['count'])) {
$grantStatistics['value'][$fieldValue]['count'] = 0;
}
$grantStatistics['value'][$fieldValue]['count']++;
$grantStatistics['value'][$fieldValue]['percentage'] = round(($grantStatistics['value'][$fieldValue]['count'] /
$awardedGrants) * 100);
}
else {
if (!isset($grantStatistics['value'][$fieldValue]['unassigned_currency'][$currency])
||
!isset($grantStatistics['value'][$fieldValue]['unassigned_currency'][$currency]['value'])
) {
$grantStatistics['value'][$fieldValue]['unassigned_currency'][$currency]['value'] = 0;
}
$grantStatistics['value'][$fieldValue]['unassigned_currency'][$currency]['value'] += $values['civicrm_grant_amount_total'];
$grantStatistics['value'][$fieldValue]['unassigned_currency'][$currency]['percentage'] = round(($grantStatistics['value'][$fieldValue]['unassigned_currency'][$currency]['value'] /
$awardedGrantsAmount) * 100);
$grantStatistics['value'][$fieldValue]['unassigned_count']++;
$grantStatistics['value'][$fieldValue]['unassigned_percentage'] = round(($grantStatistics['value'][$fieldValue]['unassigned_count'] /
$awardedGrants) * 100);
}
}
}

View file

@ -0,0 +1,408 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
* Class CRM_Report_Form_Instance
*/
class CRM_Report_Form_Instance {
/**
* Build form.
*
* @param CRM_Core_Form $form
*/
public static function buildForm(&$form) {
// We should not build form elements in dashlet mode.
if ($form->_section) {
return;
}
// Check role based permission.
$instanceID = $form->getVar('_id');
if ($instanceID && !CRM_Report_Utils_Report::isInstanceGroupRoleAllowed($instanceID)) {
$url = CRM_Utils_System::url('civicrm/report/list', 'reset=1');
CRM_Core_Error::statusBounce(ts('You do not have permission to access this report.'),
$url
);
}
$attributes = CRM_Core_DAO::getAttribute('CRM_Report_DAO_ReportInstance');
$form->add('text',
'title',
ts('Report Title'),
$attributes['title']
);
$form->add('text',
'description',
ts('Report Description'),
$attributes['description']
);
$form->add('text',
'email_subject',
ts('Subject'),
$attributes['email_subject']
);
$form->add('text',
'email_to',
ts('To'),
$attributes['email_to']
);
$form->add('text',
'email_cc',
ts('CC'),
$attributes['email_subject']
);
$form->add('number',
'row_count',
ts('Limit Dashboard Results'),
array('class' => 'four', 'min' => 1)
);
$form->add('textarea',
'report_header',
ts('Report Header'),
$attributes['header']
);
$form->add('textarea',
'report_footer',
ts('Report Footer'),
$attributes['footer']
);
$form->addElement('checkbox', 'is_navigation', ts('Include Report in Navigation Menu?'), NULL,
array('onclick' => "return showHideByValue('is_navigation','','navigation_menu','table-row','radio',false);")
);
$form->addElement('select', 'view_mode', ts('Configure link to...'), array(
'view' => ts('View Results'),
'criteria' => ts('Show Criteria'),
));
$form->addElement('checkbox', 'addToDashboard', ts('Available for Dashboard?'));
$form->add('number', 'cache_minutes', ts('Cache dashlet for'), array('class' => 'four', 'min' => 1));
$form->addElement('checkbox', 'add_to_my_reports', ts('Add to My Reports?'), NULL);
$form->addElement('checkbox', 'is_reserved', ts('Reserved Report?'));
if (!CRM_Core_Permission::check('administer reserved reports')) {
$form->freeze('is_reserved');
}
$config = CRM_Core_Config::singleton();
if ($config->userFramework != 'Joomla' ||
$config->userFramework != 'WordPress'
) {
$form->addElement('select',
'permission',
ts('Permission'),
array('0' => ts('Everyone (includes anonymous)')) + CRM_Core_Permission::basicPermissions()
);
// prepare user_roles to save as names not as ids
if (function_exists('user_roles')) {
$user_roles_array = user_roles();
foreach ($user_roles_array as $key => $value) {
$user_roles[$value] = $value;
}
$grouprole = &$form->addElement('advmultiselect',
'grouprole',
ts('ACL Group/Role'),
$user_roles,
array(
'size' => 5,
'style' => 'width:240px',
'class' => 'advmultiselect',
)
);
$grouprole->setButtonAttributes('add', array('value' => ts('Add >>')));
$grouprole->setButtonAttributes('remove', array('value' => ts('<< Remove')));
}
}
// navigation field
$parentMenu = CRM_Core_BAO_Navigation::getNavigationList();
$form->add('select', 'parent_id', ts('Parent Menu'), array('' => ts('- select -')) + $parentMenu);
// For now we only providing drilldown for one primary detail report only. In future this could be multiple reports
foreach ($form->_drilldownReport as $reportUrl => $drillLabel) {
$instanceList = CRM_Report_Utils_Report::getInstanceList($reportUrl);
if (count($instanceList) > 1) {
$form->add('select', 'drilldown_id', $drillLabel, array('' => ts('- select -')) + $instanceList);
}
break;
}
$form->addButtons(array(
array(
'type' => 'submit',
'name' => ts('Save Report'),
'isDefault' => TRUE,
),
array(
'type' => 'cancel',
'name' => ts('Cancel'),
),
)
);
$form->addFormRule(array('CRM_Report_Form_Instance', 'formRule'), $form);
}
/**
* Add form rules.
*
* @param array $fields
* @param array $errors
* @param CRM_Report_Form_Instance $self
*
* @return array|bool
*/
public static function formRule($fields, $errors, $self) {
// Validate both the "next" and "save" buttons for creating/updating a report.
$nextButton = $self->controller->getButtonName();
$saveButton = str_replace('_next', '_save', $nextButton);
$clickedButton = $self->getVar('_instanceButtonName');
$errors = array();
if ($clickedButton == $nextButton || $clickedButton == $saveButton) {
if (empty($fields['title'])) {
$errors['title'] = ts('Title is a required field.');
$self->assign('instanceFormError', TRUE);
}
}
return empty($errors) ? TRUE : $errors;
}
/**
* Set default values.
*
* @param CRM_Core_Form $form
* @param array $defaults
*/
public static function setDefaultValues(&$form, &$defaults) {
// we should not build form elements in dashlet mode.
if ($form->_section) {
return;
}
$instanceID = $form->getVar('_id');
$navigationDefaults = array();
if (!isset($defaults['permission'])) {
$defaults['permission'] = 'access CiviReport';
}
$userFrameworkResourceURL = CRM_Core_Config::singleton()->userFrameworkResourceURL;
// Add a special region for the default HTML header of printed reports. It
// won't affect reports with customized headers, just ones with the default.
$printHeaderRegion = CRM_Core_Region::instance('default-report-header', FALSE);
$htmlHeader = ($printHeaderRegion) ? $printHeaderRegion->render('', FALSE) : '';
$defaults['report_header'] = $report_header = "<html>
<head>
<title>CiviCRM Report</title>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
<style type=\"text/css\">@import url({$userFrameworkResourceURL}css/print.css);</style>
{$htmlHeader}
</head>
<body><div id=\"crm-container\">";
$defaults['report_footer'] = $report_footer = "<p><img src=\"{$userFrameworkResourceURL}i/powered_by.png\" /></p></div></body>
</html>
";
// CRM-17225 view_mode currently supports 'view' or 'criteria'.
// Prior to 4.7 'view' meant reset=1 in the url & if not set
// then show criteria.
// From 4.7 we will pro-actively set 'force=1' but still respect the old behaviour.
// we may look to add pdf, print_view, csv & various charts as these could simply
// be added to the url allowing us to conceptualise 'view right now' vs saved view
// & using a multiselect (option value?) could help here.
// Note that accessing reports without reset=1 in the url turns out to be
// dangerous as it seems to carry actions like 'delete' from one report to another.
$defaults['view_mode'] = 'view';
$output = CRM_Utils_Request::retrieve('output', 'String');
if ($output == 'criteria') {
$defaults['view_mode'] = 'criteria';
}
if (empty($defaults['cache_minutes'])) {
$defaults['cache_minutes'] = '60';
}
if ($instanceID) {
// this is already retrieved via Form.php
$defaults['description'] = CRM_Utils_Array::value('description', $defaults);
if (!empty($defaults['header'])) {
$defaults['report_header'] = $defaults['header'];
}
if (!empty($defaults['footer'])) {
$defaults['report_footer'] = $defaults['footer'];
}
// CRM-17310 private reports option.
$defaults['add_to_my_reports'] = 0;
if (CRM_Utils_Array::value('owner_id', $defaults) != NULL) {
$defaults['add_to_my_reports'] = 1;
}
if (!empty($defaults['navigation_id'])) {
// Get the default navigation parent id.
$params = array('id' => $defaults['navigation_id']);
CRM_Core_BAO_Navigation::retrieve($params, $navigationDefaults);
$defaults['is_navigation'] = 1;
$defaults['parent_id'] = CRM_Utils_Array::value('parent_id', $navigationDefaults);
if (!empty($navigationDefaults['is_active'])) {
$form->assign('is_navigation', TRUE);
}
// A saved view mode will over-ride any url assumptions.
if (strpos($navigationDefaults['url'], 'output=criteria')) {
$defaults['view_mode'] = 'criteria';
}
if (!empty($navigationDefaults['id'])) {
$form->_navigation['id'] = $navigationDefaults['id'];
$form->_navigation['parent_id'] = !empty($navigationDefaults['parent_id']) ?
$navigationDefaults['parent_id'] : NULL;
}
}
if (!empty($defaults['grouprole'])) {
foreach (explode(CRM_Core_DAO::VALUE_SEPARATOR, $defaults['grouprole']) as $value) {
$groupRoles[] = $value;
}
$defaults['grouprole'] = $groupRoles;
}
}
elseif (property_exists($form, '_description')) {
$defaults['description'] = $form->_description;
}
}
/**
* Post process function.
*
* @param CRM_Core_Form $form
* @param bool $redirect
*/
public static function postProcess(&$form, $redirect = TRUE) {
$params = $form->getVar('_params');
$instanceID = $form->getVar('_id');
if ($isNew = $form->getVar('_createNew')) {
// set the report_id since base template is going to be same, and we going to unset $instanceID
// which will make it difficult later on, to compute report_id
$params['report_id'] = CRM_Report_Utils_Report::getValueFromUrl($instanceID);
// Unset $instanceID so a new copy would be created.
$instanceID = NULL;
}
$params['instance_id'] = $instanceID;
if (!empty($params['is_navigation'])) {
$params['navigation'] = $form->_navigation;
}
elseif ($instanceID) {
// Delete navigation if exists.
$navId = CRM_Core_DAO::getFieldValue('CRM_Report_DAO_ReportInstance', $instanceID, 'navigation_id', 'id');
if ($navId) {
CRM_Core_BAO_Navigation::processDelete($navId);
CRM_Core_BAO_Navigation::resetNavigation();
}
}
// make a copy of params
$formValues = $params;
// unset params from $formValues that doesn't match with DB columns of instance tables, and also not required in form-values for sure
$unsetFields = array(
'title',
'to_emails',
'cc_emails',
'header',
'footer',
'qfKey',
'id',
'_qf_default',
'report_header',
'report_footer',
'grouprole',
'task',
);
foreach ($unsetFields as $field) {
unset($formValues[$field]);
}
$view_mode = $formValues['view_mode'];
// CRM-17310 my reports functionality - we should set owner if the checkbox is 1,
// it seems to be not set at all if unchecked.
if (!empty($formValues['add_to_my_reports'])) {
$params['owner_id'] = CRM_Core_Session::getLoggedInContactID();
}
else {
$params['owner_id'] = 'null';
}
unset($formValues['add_to_my_reports']);
// pass form_values as string
$params['form_values'] = serialize($formValues);
$instance = CRM_Report_BAO_ReportInstance::create($params);
$form->set('id', $instance->id);
if ($instanceID && !$isNew) {
// updating existing instance
$statusMsg = ts('"%1" report has been updated.', array(1 => $instance->title));
}
elseif ($form->getVar('_id') && $isNew) {
$statusMsg = ts('Your report has been successfully copied as "%1". You are currently viewing the new copy.', array(1 => $instance->title));
}
else {
$statusMsg = ts('"%1" report has been successfully created. You are currently viewing the new report instance.', array(1 => $instance->title));
}
CRM_Core_Session::setStatus($statusMsg);
if ($redirect) {
$urlParams = array('reset' => 1);
if ($view_mode == 'view') {
$urlParams['force'] = 1;
}
else {
$urlParams['output'] = 'criteria';
}
CRM_Utils_System::redirect(CRM_Utils_System::url("civicrm/report/instance/{$instance->id}", $urlParams));
}
}
}

View file

@ -0,0 +1,525 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Mailing_Bounce extends CRM_Report_Form {
protected $_summary = NULL;
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Household',
'Organization',
);
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array();
$this->_columns['civicrm_contact'] = array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'id' => array(
'title' => ts('Contact ID'),
'required' => TRUE,
),
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
),
'source' => array(
'title' => ts('Contact Source'),
'type' => CRM_Utils_Type::T_STRING,
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
),
'order_bys' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'default' => TRUE,
'default_order' => 'ASC',
),
),
'grouping' => 'contact-fields',
);
$this->_columns['civicrm_mailing'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'mailing_name' => array(
'name' => 'name',
'title' => ts('Mailing Name'),
'default' => TRUE,
),
'mailing_name_alias' => array(
'name' => 'name',
'required' => TRUE,
'no_display' => TRUE,
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
'default' => TRUE,
),
),
'filters' => array(
'mailing_id' => array(
'name' => 'id',
'title' => ts('Mailing Name'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'type' => CRM_Utils_Type::T_INT,
'options' => CRM_Mailing_BAO_Mailing::getMailingsList(),
'operator' => 'like',
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
'type' => CRM_Utils_Type::T_STRING,
'operator' => 'like',
),
),
'order_bys' => array(
'mailing_name' => array(
'name' => 'name',
'title' => ts('Mailing Name'),
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
),
),
'grouping' => 'mailing-fields',
);
$this->_columns['civicrm_mailing_event_bounce'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'bounce_reason' => array(
'title' => ts('Bounce Reason'),
),
'time_stamp' => array(
'title' => ts('Bounce Date'),
),
),
'filters' => array(
'bounce_reason' => array(
'title' => ts('Bounce Reason'),
'type' => CRM_Utils_Type::T_STRING,
),
'time_stamp' => array(
'title' => ts('Bounce Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
),
'order_bys' => array(
'bounce_reason' => array(
'title' => ts('Bounce Reason'),
),
'time_stamp' => array(
'title' => ts('Bounce Date'),
),
),
'grouping' => 'mailing-fields',
);
$this->_columns['civicrm_mailing_bounce_type'] = array(
'dao' => 'CRM_Mailing_DAO_BounceType',
'fields' => array(
'bounce_name' => array(
'name' => 'name',
'title' => ts('Bounce Type'),
),
),
'filters' => array(
'bounce_type_name' => array(
'name' => 'name',
'title' => ts('Bounce Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'type' => CRM_Utils_Type::T_STRING,
'options' => self::bounce_type(),
'operator' => 'like',
),
),
'order_bys' => array(
'bounce_name' => array(
'name' => 'name',
'title' => ts('Bounce Type'),
),
),
'grouping' => 'mailing-fields',
);
$this->_columns['civicrm_email'] = array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'no_repeat' => TRUE,
),
'on_hold' => array(
'title' => ts('On hold'),
),
'hold_date' => array(
'title' => ts('Hold date'),
),
'reset_date' => array(
'title' => ts('Hold reset date'),
),
),
'filters' => array(
'on_hold' => array(
'title' => ts('On hold'),
),
'hold_date' => array(
'title' => ts('Hold date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'reset_date' => array(
'title' => ts('Hold reset date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
),
'order_bys' => array(
'email' => array('title' => ts('Email'), 'default_order' => 'ASC'),
),
'grouping' => 'contact-fields',
);
$this->_columns['civicrm_phone'] = array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array('phone' => NULL),
'grouping' => 'contact-fields',
);
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
public function preProcess() {
$this->assign('chartSupported', TRUE);
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
elseif ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
}
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = CRM_Utils_Array::value('no_display', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
}
}
}
}
if (!empty($this->_params['charts'])) {
$select[] = "COUNT({$this->_aliases['civicrm_mailing_event_bounce']}.id) as civicrm_mailing_bounce_count";
$this->_columnHeaders["civicrm_mailing_bounce_count"]['title'] = ts('Bounce Count');
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = $grouping = array();
return $errors;
}
public function from() {
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}";
// LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
// ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND
// {$this->_aliases['civicrm_address']}.is_primary = 1 ) ";
$this->_from .= "
INNER JOIN civicrm_mailing_event_queue
ON civicrm_mailing_event_queue.contact_id = {$this->_aliases['civicrm_contact']}.id
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON civicrm_mailing_event_queue.email_id = {$this->_aliases['civicrm_email']}.id
INNER JOIN civicrm_mailing_event_bounce {$this->_aliases['civicrm_mailing_event_bounce']}
ON {$this->_aliases['civicrm_mailing_event_bounce']}.event_queue_id = civicrm_mailing_event_queue.id
LEFT JOIN civicrm_mailing_bounce_type {$this->_aliases['civicrm_mailing_bounce_type']}
ON {$this->_aliases['civicrm_mailing_event_bounce']}.bounce_type_id = {$this->_aliases['civicrm_mailing_bounce_type']}.id
INNER JOIN civicrm_mailing_job
ON civicrm_mailing_event_queue.job_id = civicrm_mailing_job.id
INNER JOIN civicrm_mailing {$this->_aliases['civicrm_mailing']}
ON civicrm_mailing_job.mailing_id = {$this->_aliases['civicrm_mailing']}.id
";
if ($this->_phoneField) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1 ";
}
}
public function where() {
$clauses = array();
// Exclude SMS mailing type
$clauses[] = "{$this->_aliases['civicrm_mailing']}.sms_provider_id IS NULL";
// Build date filter clauses
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($this->_aliases[$tableName] . '.' . $field['name'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
public function groupBy() {
if (!empty($this->_params['charts'])) {
$groupBy = "{$this->_aliases['civicrm_mailing']}.id";
}
else {
$groupBy = "{$this->_aliases['civicrm_mailing_event_bounce']}.id";
}
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
public function postProcess() {
$this->beginPostProcess();
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
$sql = $this->buildQuery(TRUE);
$rows = $graphRows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* @param $rows
*/
public function buildChart(&$rows) {
if (empty($rows)) {
return;
}
$chartInfo = array(
'legend' => ts('Mail Bounce Report'),
'xname' => ts('Mailing'),
'yname' => ts('Bounce'),
'xLabelAngle' => 20,
'tip' => ts('Mail Bounce: %1', array(1 => '#val#')),
);
foreach ($rows as $row) {
$chartInfo['values'][$row['civicrm_mailing_mailing_name_alias']] = $row['civicrm_mailing_bounce_count'];
}
// build the chart.
CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
$this->assign('chartType', $this->_params['charts']);
}
/**
* @return array
*/
public function bounce_type() {
$data = array();
$bounce_type = new CRM_Mailing_DAO_BounceType();
$query = "SELECT name FROM civicrm_mailing_bounce_type";
$bounce_type->query($query);
while ($bounce_type->fetch()) {
$data[$bounce_type->name] = $bounce_type->name;
}
return $data;
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$config = CRM_Core_Config::Singleton();
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// If the email address has been deleted
if (array_key_exists('civicrm_email_email', $row)) {
if (empty($rows[$rowNum]['civicrm_email_email'])) {
$rows[$rowNum]['civicrm_email_email'] = '<del>Email address deleted</del>';
}
$entryFound = TRUE;
}
// make count columns point to detail report
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact details for this contact.");
$entryFound = TRUE;
}
// Handle on_hold boolean display
if (array_key_exists('civicrm_email_on_hold', $row)) {
$rows[$rowNum]['civicrm_email_on_hold'] = (!empty($row['civicrm_email_on_hold'])) ? 'Yes' : 'No';
$entryFound = TRUE;
}
// Convert datetime values to custom date and time format
$dateFields = array(
'civicrm_mailing_event_bounce_time_stamp',
'civicrm_email_hold_date',
'civicrm_email_reset_date',
);
foreach ($dateFields as $dateField) {
if (array_key_exists($dateField, $row)) {
if (!empty($rows[$rowNum][$dateField])) {
$rows[$rowNum][$dateField] = CRM_Utils_Date::customFormat($row[$dateField], $config->dateformatDatetime);
}
$entryFound = TRUE;
}
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,406 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Mailing_Clicks extends CRM_Report_Form {
protected $_summary = NULL;
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Household',
'Organization',
);
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array();
$this->_columns['civicrm_contact'] = array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'id' => array(
'title' => ts('Contact ID'),
'required' => TRUE,
),
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
),
'source' => array(
'title' => ts('Contact Source'),
'type' => CRM_Utils_Type::T_STRING,
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
),
'order_bys' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'default' => TRUE,
'default_order' => 'ASC',
),
),
'grouping' => 'contact-fields',
);
$this->_columns['civicrm_mailing'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'mailing_name' => array(
'name' => 'name',
'title' => ts('Mailing Name'),
'default' => TRUE,
),
'mailing_name_alias' => array(
'name' => 'name',
'required' => TRUE,
'no_display' => TRUE,
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
'default' => TRUE,
),
),
'filters' => array(
'mailing_id' => array(
'name' => 'id',
'title' => ts('Mailing Name'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'type' => CRM_Utils_Type::T_INT,
'options' => CRM_Mailing_BAO_Mailing::getMailingsList(),
'operator' => 'like',
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
'type' => CRM_Utils_Type::T_STRING,
'operator' => 'like',
),
),
'order_bys' => array(
'mailing_name' => array(
'name' => 'name',
'title' => ts('Mailing Name'),
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
),
),
'grouping' => 'mailing-fields',
);
$this->_columns['civicrm_email'] = array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
);
$this->_columns['civicrm_phone'] = array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array('phone' => NULL),
'grouping' => 'contact-fields',
);
$this->_columns['civicrm_mailing_trackable_url'] = array(
'dao' => 'CRM_Mailing_DAO_TrackableURL',
'fields' => array(
'url' => array(
'title' => ts('Click through URL'),
),
),
// To do this filter should really be like mailing id filter a multi select, However
// Not clear on how to make filter dependant on selected mailings at this stage so have set a
// text filter which works for now
'filters' => array(
'url' => array(
'title' => ts('URL'),
'type' => CRM_Utils_Type::T_STRING,
'operator' => 'like',
),
),
'order_bys' => array(
'url' => array('title' => ts('Click through URL')),
),
'grouping' => 'mailing-fields',
);
$this->_columns['civicrm_mailing_event_trackable_url_open'] = array(
'dao' => 'CRM_Mailing_Event_DAO_TrackableURLOpen',
'fields' => array(
'time_stamp' => array(
'title' => ts('Click Date'),
'default' => TRUE,
),
),
'filters' => array(
'time_stamp' => array(
'title' => ts('Click Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
),
'order_bys' => array(
'time_stamp' => array(
'title' => ts('Click Date'),
),
),
'grouping' => 'mailing-fields',
);
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
public function preProcess() {
$this->assign('chartSupported', TRUE);
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
elseif ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
}
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = CRM_Utils_Array::value('no_display', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
}
}
}
}
if (!empty($this->_params['charts'])) {
$select[] = "COUNT({$this->_aliases['civicrm_event_trackable_url_open']}.id) as civicrm_mailing_click_count";
$this->_columnHeaders["civicrm_mailing_click_count"]['title'] = ts('Click Count');
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = $grouping = array();
return $errors;
}
public function from() {
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}";
$this->_from .= "
INNER JOIN civicrm_mailing_event_queue
ON civicrm_mailing_event_queue.contact_id = {$this->_aliases['civicrm_contact']}.id
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON civicrm_mailing_event_queue.email_id = {$this->_aliases['civicrm_email']}.id
INNER JOIN civicrm_mailing_event_trackable_url_open {$this->_aliases['civicrm_mailing_event_trackable_url_open']}
ON {$this->_aliases['civicrm_mailing_event_trackable_url_open']}.event_queue_id = civicrm_mailing_event_queue.id
INNER JOIN civicrm_mailing_trackable_url {$this->_aliases['civicrm_mailing_trackable_url']}
ON {$this->_aliases['civicrm_mailing_event_trackable_url_open']}.trackable_url_id = {$this->_aliases['civicrm_mailing_trackable_url']}.id
INNER JOIN civicrm_mailing_job
ON civicrm_mailing_event_queue.job_id = civicrm_mailing_job.id
INNER JOIN civicrm_mailing {$this->_aliases['civicrm_mailing']}
ON civicrm_mailing_job.mailing_id = {$this->_aliases['civicrm_mailing']}.id
AND civicrm_mailing_job.is_test = 0
";
if ($this->_phoneField) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id
AND {$this->_aliases['civicrm_phone']}.is_primary = 1
";
}
}
public function where() {
parent::where();
$this->_where .= " AND {$this->_aliases['civicrm_mailing']}.sms_provider_id IS NULL";
}
public function groupBy() {
$this->_groupBy = '';
if (!empty($this->_params['charts'])) {
$groupBy = "{$this->_aliases['civicrm_mailing']}.id";
}
else {
$groupBy = "{$this->_aliases['civicrm_mailing_event_trackable_url_open']}.id";
}
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
public function postProcess() {
$this->beginPostProcess();
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
$sql = $this->buildQuery(TRUE);
$rows = $graphRows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* @param $rows
*/
public function buildChart(&$rows) {
if (empty($rows)) {
return;
}
$chartInfo = array(
'legend' => ts('Mail Click-Through Report'),
'xname' => ts('Mailing'),
'yname' => ts('Clicks'),
'xLabelAngle' => 20,
'tip' => ts('Clicks: %1', array(1 => '#val#')),
);
foreach ($rows as $row) {
$chartInfo['values'][$row['civicrm_mailing_mailing_name_alias']] = $row['civicrm_mailing_click_count'];
}
// build the chart.
CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
$this->assign('chartType', $this->_params['charts']);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// If the email address has been deleted
if (array_key_exists('civicrm_email_email', $row)) {
if (empty($rows[$rowNum]['civicrm_email_email'])) {
$rows[$rowNum]['civicrm_email_email'] = '<del>Email address deleted</del>';
}
$entryFound = TRUE;
}
// make count columns point to detail report
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact details for this contact.");
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,519 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Mailing_Detail extends CRM_Report_Form {
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Household',
'Organization',
);
protected $_exposeContactID = FALSE;
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array();
$this->_columns['civicrm_contact'] = array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'id' => array(
'name' => 'id',
'title' => ts('Contact ID'),
'required' => TRUE,
'no_display' => TRUE,
),
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
),
'order_bys' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'default' => TRUE,
'default_order' => 'ASC',
),
),
'grouping' => 'contact-fields',
);
$this->_columns['civicrm_mailing'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'mailing_name' => array(
'name' => 'name',
'title' => ts('Mailing Name'),
'default' => TRUE,
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
'default' => TRUE,
),
),
'filters' => array(
'mailing_id' => array(
'name' => 'id',
'title' => ts('Mailing Name'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'type' => CRM_Utils_Type::T_INT,
'options' => CRM_Mailing_BAO_Mailing::getMailingsList(),
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
'type' => CRM_Utils_Type::T_STRING,
'operator' => 'like',
),
),
'order_bys' => array(
'mailing_name' => array(
'name' => 'name',
'title' => ts('Mailing Name'),
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
),
),
'grouping' => 'mailing-fields',
);
// adding dao just to have alias
$this->_columns['civicrm_mailing_event_bounce'] = array(
'dao' => 'CRM_Mailing_Event_DAO_Bounce',
);
$this->_columns['civicrm_mailing_event_delivered'] = array(
'dao' => 'CRM_Mailing_Event_DAO_Delivered',
'fields' => array(
'delivery_id' => array(
'name' => 'id',
'title' => ts('Delivery Status'),
'default' => TRUE,
),
),
'filters' => array(
'delivery_status' => array(
'name' => 'delivery_status',
'title' => ts('Delivery Status'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'type' => CRM_Utils_Type::T_STRING,
'options' => array(
'' => 'Any',
'successful' => 'Successful',
'bounced' => 'Bounced',
),
),
),
'grouping' => 'mailing-fields',
);
$this->_columns['civicrm_mailing_event_unsubscribe'] = array(
'dao' => 'CRM_Mailing_Event_DAO_Unsubscribe',
'fields' => array(
'unsubscribe_id' => array(
'name' => 'id',
'title' => ts('Unsubscribe'),
'default' => TRUE,
),
'optout_id' => array(
'name' => 'id',
'title' => ts('Opt-out'),
'default' => TRUE,
'alias' => 'mailing_event_unsubscribe_civireport2',
),
),
'filters' => array(
'is_unsubscribed' => array(
'name' => 'id',
'title' => ts('Unsubscribed'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
'' => ts('Any'),
'0' => ts('No'),
'1' => ts('Yes'),
),
'clause' => 'mailing_event_unsubscribe_civireport.id IS NULL',
),
'is_optout' => array(
'title' => ts('Opted-out'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
'' => ts('Any'),
'0' => ts('No'),
'1' => ts('Yes'),
),
'clause' => 'mailing_event_unsubscribe_civireport2.id IS NULL',
),
),
'grouping' => 'mailing-fields',
);
$this->_columns['civicrm_mailing_event_reply'] = array(
'dao' => 'CRM_Mailing_Event_DAO_Reply',
'fields' => array(
'reply_id' => array(
'name' => 'id',
'title' => ts('Reply'),
),
),
'filters' => array(
'is_replied' => array(
'name' => 'id',
'title' => ts('Replied'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
'' => ts('Any'),
'0' => ts('No'),
'1' => ts('Yes'),
),
'clause' => 'mailing_event_reply_civireport.id IS NULL',
),
),
'grouping' => 'mailing-fields',
);
$this->_columns['civicrm_mailing_event_forward'] = array(
'dao' => 'CRM_Mailing_Event_DAO_Forward',
'fields' => array(
'forward_id' => array(
'name' => 'id',
'title' => ts('Forwarded to Email'),
),
),
'filters' => array(
'is_forwarded' => array(
'name' => 'id',
'title' => ts('Forwarded'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_SELECT,
'options' => array(
'' => ts('Any'),
'0' => ts('No'),
'1' => ts('Yes'),
),
'clause' => 'mailing_event_forward_civireport.id IS NULL',
),
),
'grouping' => 'mailing-fields',
);
$this->_columns['civicrm_email'] = array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
),
),
'grouping' => 'contact-fields',
);
$this->_columns['civicrm_phone'] = array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array('phone' => NULL),
'grouping' => 'contact-fields',
);
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
public function select() {
$select = $columns = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if (in_array($fieldName, array(
'unsubscribe_id',
'optout_id',
'forward_id',
'reply_id',
))) {
$select[] = "IF({$field['dbAlias']} IS NULL, 'No', 'Yes') as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = CRM_Utils_Array::value('no_display', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
unset($this->_columns[$tableName]['fields'][$fieldName]);
$columns[$tableName][$fieldName] = $field;
}
elseif ($fieldName == 'delivery_id') {
$select[] = "IF(mailing_event_bounce_civireport.id IS NOT NULL, 'Bounced', IF(mailing_event_delivered_civireport.id IS NOT NULL, 'Successful', 'Unknown')) as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = CRM_Utils_Array::value('no_display', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
unset($this->_columns[$tableName]['fields'][$fieldName]);
$columns[$tableName][$fieldName] = $field;
}
}
}
}
}
parent::select();
if (!empty($select)) {
$this->_select .= ', ' . implode(', ', $select) . " ";
}
// put the fields that were unset, back in place
foreach ($columns as $tableName => $table) {
foreach ($table as $fieldName => $fields) {
$this->_columns[$tableName]['fields'][$fieldName] = $fields;
}
}
// simple sort
ksort($this->_columnHeaders);
}
public function from() {
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']}";
$this->_from .= "
INNER JOIN civicrm_mailing_event_queue
ON civicrm_mailing_event_queue.contact_id = {$this->_aliases['civicrm_contact']}.id
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON civicrm_mailing_event_queue.email_id = {$this->_aliases['civicrm_email']}.id";
if (array_key_exists('delivery_id', $this->_params['fields'])) {
$this->_from .= "
LEFT JOIN civicrm_mailing_event_delivered {$this->_aliases['civicrm_mailing_event_delivered']}
ON {$this->_aliases['civicrm_mailing_event_delivered']}.event_queue_id = civicrm_mailing_event_queue.id
LEFT JOIN civicrm_mailing_event_bounce {$this->_aliases['civicrm_mailing_event_bounce']}
ON {$this->_aliases['civicrm_mailing_event_bounce']}.event_queue_id = civicrm_mailing_event_queue.id";
if (CRM_Utils_Array::value('delivery_status_value', $this->_params) ==
'bounced'
) {
$this->_columns['civicrm_mailing_event_delivered']['filters']['delivery_status']['clause'] = "{$this->_aliases['civicrm_mailing_event_bounce']}.id IS NOT NULL";
}
elseif (CRM_Utils_Array::value('delivery_status_value', $this->_params) ==
'successful'
) {
$this->_columns['civicrm_mailing_event_delivered']['filters']['delivery_status']['clause'] = "{$this->_aliases['civicrm_mailing_event_delivered']}.id IS NOT NULL AND {$this->_aliases['civicrm_mailing_event_bounce']}.id IS NULL";
}
}
else {
unset($this->_columns['civicrm_mailing_event_delivered']['filters']['delivery_status']);
}
if (array_key_exists('reply_id', $this->_params['fields']) ||
is_numeric(CRM_Utils_Array::value('is_replied_value', $this->_params))
) {
if (CRM_Utils_Array::value('is_replied_value', $this->_params) == 1) {
$joinType = 'INNER';
$this->_columns['civicrm_mailing_event_reply']['filters']['is_replied']['clause'] = '(1)';
}
else {
$joinType = 'LEFT';
}
$this->_from .= "
{$joinType} JOIN civicrm_mailing_event_reply {$this->_aliases['civicrm_mailing_event_reply']}
ON {$this->_aliases['civicrm_mailing_event_reply']}.event_queue_id = civicrm_mailing_event_queue.id";
}
else {
unset($this->_columns['civicrm_mailing_event_reply']['filters']['is_replied']);
}
if (array_key_exists('unsubscribe_id', $this->_params['fields']) ||
is_numeric(CRM_Utils_Array::value('is_unsubscribed_value', $this->_params))
) {
if (CRM_Utils_Array::value('is_unsubscribed_value', $this->_params) == 1
) {
$joinType = 'INNER';
$this->_columns['civicrm_mailing_event_unsubscribe']['filters']['is_unsubscribed']['clause'] = '(1)';
}
else {
$joinType = 'LEFT';
}
$this->_from .= "
{$joinType} JOIN civicrm_mailing_event_unsubscribe {$this->_aliases['civicrm_mailing_event_unsubscribe']}
ON {$this->_aliases['civicrm_mailing_event_unsubscribe']}.event_queue_id = civicrm_mailing_event_queue.id
AND {$this->_aliases['civicrm_mailing_event_unsubscribe']}.org_unsubscribe = 0";
}
else {
unset($this->_columns['civicrm_mailing_event_unsubscribe']['filters']['is_unsubscribed']);
}
if (array_key_exists('optout_id', $this->_params['fields']) ||
is_numeric(CRM_Utils_Array::value('is_optout_value', $this->_params))
) {
if (CRM_Utils_Array::value('is_optout_value', $this->_params) == 1) {
$joinType = 'INNER';
$this->_columns['civicrm_mailing_event_unsubscribe']['filters']['is_optout']['clause'] = '(1)';
}
else {
$joinType = 'LEFT';
}
$this->_from .= "
{$joinType} JOIN civicrm_mailing_event_unsubscribe {$this->_aliases['civicrm_mailing_event_unsubscribe']}2
ON {$this->_aliases['civicrm_mailing_event_unsubscribe']}2.event_queue_id = civicrm_mailing_event_queue.id
AND {$this->_aliases['civicrm_mailing_event_unsubscribe']}2.org_unsubscribe = 1";
}
else {
unset($this->_columns['civicrm_mailing_event_unsubscribe']['filters']['is_optout']);
}
if (array_key_exists('forward_id', $this->_params['fields']) ||
is_numeric(CRM_Utils_Array::value('is_forwarded_value', $this->_params))
) {
if (CRM_Utils_Array::value('is_forwarded_value', $this->_params) == 1) {
$joinType = 'INNER';
$this->_columns['civicrm_mailing_event_forward']['filters']['is_forwarded']['clause'] = '(1)';
}
else {
$joinType = 'LEFT';
}
$this->_from .= "
{$joinType} JOIN civicrm_mailing_event_forward {$this->_aliases['civicrm_mailing_event_forward']}
ON {$this->_aliases['civicrm_mailing_event_forward']}.event_queue_id = civicrm_mailing_event_queue.id";
}
else {
unset($this->_columns['civicrm_mailing_event_forward']['filters']['is_forwarded']);
}
$this->_from .= "
INNER JOIN civicrm_mailing_job
ON civicrm_mailing_event_queue.job_id = civicrm_mailing_job.id
INNER JOIN civicrm_mailing {$this->_aliases['civicrm_mailing']}
ON civicrm_mailing_job.mailing_id = {$this->_aliases['civicrm_mailing']}.id
AND civicrm_mailing_job.is_test = 0";
if ($this->_phoneField) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1 ";
}
}
public function where() {
parent::where();
$this->_where .= " AND {$this->_aliases['civicrm_mailing']}.sms_provider_id IS NULL";
}
/**
* @return array
*/
public function mailingList() {
$data = array();
$mailing = new CRM_Mailing_BAO_Mailing();
$query = "SELECT name FROM civicrm_mailing ";
$mailing->query($query);
while ($mailing->fetch()) {
$data[CRM_Core_DAO::escapeString($mailing->name)] = $mailing->name;
}
return $data;
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// If the email address has been deleted
if (array_key_exists('civicrm_email_email', $row)) {
if (empty($rows[$rowNum]['civicrm_email_email'])) {
$rows[$rowNum]['civicrm_email_email'] = '<del>Email address deleted</del>';
}
$entryFound = TRUE;
}
// make count columns point to detail report
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact details for this contact.");
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,385 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Mailing_Opened extends CRM_Report_Form {
protected $_summary = NULL;
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Household',
'Organization',
);
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array();
$this->_columns['civicrm_contact'] = array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'id' => array(
'title' => ts('Contact ID'),
'required' => TRUE,
),
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
),
'source' => array(
'title' => ts('Contact Source'),
'type' => CRM_Utils_Type::T_STRING,
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
),
'order_bys' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'default' => TRUE,
'default_order' => 'ASC',
),
),
'grouping' => 'contact-fields',
);
$this->_columns['civicrm_mailing'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'mailing_name' => array(
'name' => 'name',
'title' => ts('Mailing Name'),
'default' => TRUE,
),
'mailing_name_alias' => array(
'name' => 'name',
'required' => TRUE,
'no_display' => TRUE,
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
'default' => TRUE,
),
),
'filters' => array(
'mailing_id' => array(
'name' => 'id',
'title' => ts('Mailing Name'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'type' => CRM_Utils_Type::T_INT,
'options' => CRM_Mailing_BAO_Mailing::getMailingsList(),
'operator' => 'like',
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
'type' => CRM_Utils_Type::T_STRING,
'operator' => 'like',
),
),
'order_bys' => array(
'mailing_name' => array(
'name' => 'name',
'title' => ts('Mailing Name'),
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
),
),
'grouping' => 'mailing-fields',
);
$this->_columns['civicrm_email'] = array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Email'),
'no_repeat' => TRUE,
),
),
'order_bys' => array(
'email' => array('title' => ts('Email'), 'default_order' => 'ASC'),
),
'grouping' => 'contact-fields',
);
$this->_columns['civicrm_phone'] = array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array('phone' => NULL),
'grouping' => 'contact-fields',
);
$this->_columns['civicrm_mailing_event_opened'] = array(
'dao' => 'CRM_Mailing_Event_DAO_Opened',
'fields' => array(
'id' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'time_stamp' => array(
'title' => ts('Open Date'),
'default' => TRUE,
),
),
'filters' => array(
'time_stamp' => array(
'title' => ts('Open Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
),
'order_bys' => array(
'time_stamp' => array(
'title' => ts('Open Date'),
),
),
'grouping' => 'mailing-fields',
);
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
public function preProcess() {
$this->assign('chartSupported', TRUE);
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
elseif ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
}
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['no_display'] = CRM_Utils_Array::value('no_display', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
}
}
}
}
if (!empty($this->_params['charts'])) {
$select[] = "COUNT({$this->_aliases['civicrm_mailing_event_opened']}.id) as civicrm_mailing_opened_count";
$this->_columnHeaders["civicrm_mailing_opened_count"]['title'] = ts('Opened Count');
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = $grouping = array();
return $errors;
}
public function from() {
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}";
$this->_from .= "
INNER JOIN civicrm_mailing_event_queue
ON civicrm_mailing_event_queue.contact_id = {$this->_aliases['civicrm_contact']}.id
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON civicrm_mailing_event_queue.email_id = {$this->_aliases['civicrm_email']}.id
INNER JOIN civicrm_mailing_event_opened {$this->_aliases['civicrm_mailing_event_opened']}
ON {$this->_aliases['civicrm_mailing_event_opened']}.event_queue_id = civicrm_mailing_event_queue.id
INNER JOIN civicrm_mailing_job
ON civicrm_mailing_event_queue.job_id = civicrm_mailing_job.id
INNER JOIN civicrm_mailing {$this->_aliases['civicrm_mailing']}
ON civicrm_mailing_job.mailing_id = {$this->_aliases['civicrm_mailing']}.id
AND civicrm_mailing_job.is_test = 0
";
if ($this->_phoneField) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id
AND {$this->_aliases['civicrm_phone']}.is_primary = 1
";
}
}
public function where() {
parent::where();
$this->_where .= " AND {$this->_aliases['civicrm_mailing']}.sms_provider_id IS NULL";
}
public function groupBy() {
if (!empty($this->_params['charts'])) {
$groupBy = "{$this->_aliases['civicrm_mailing']}.id";
}
else {
$groupBy = "civicrm_mailing_event_queue.email_id";
}
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
public function postProcess() {
$this->beginPostProcess();
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
$sql = $this->buildQuery(TRUE);
$rows = $graphRows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* @param $rows
*/
public function buildChart(&$rows) {
if (empty($rows)) {
return;
}
$chartInfo = array(
'legend' => ts('Mail Opened Report'),
'xname' => ts('Mailing'),
'yname' => ts('Opened'),
'xLabelAngle' => 20,
'tip' => ts('Mail Opened: %1', array(1 => '#val#')),
);
foreach ($rows as $row) {
$chartInfo['values'][$row['civicrm_mailing_mailing_name_alias']] = $row['civicrm_mailing_opened_count'];
}
// build the chart.
CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
$this->assign('chartType', $this->_params['charts']);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// If the email address has been deleted
if (array_key_exists('civicrm_email_email', $row)) {
if (empty($rows[$rowNum]['civicrm_email_email'])) {
$rows[$rowNum]['civicrm_email_email'] = '<del>Email address deleted</del>';
}
$entryFound = TRUE;
}
// make count columns point to detail report
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact details for this contact.");
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,702 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Mailing_Summary extends CRM_Report_Form {
protected $_summary = NULL;
protected $_customGroupExtends = array();
protected $_add2groupSupported = FALSE;
public $_drilldownReport = array('mailing/detail' => 'Link to Detail Report');
protected $_charts = array(
'' => 'Tabular',
'bar_3dChart' => 'Bar Chart',
);
public $campaignEnabled = FALSE;
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array();
$this->_columns['civicrm_mailing'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'id' => array(
'name' => 'id',
'title' => ts('Mailing ID'),
'required' => TRUE,
'no_display' => TRUE,
),
'name' => array(
'title' => ts('Mailing Name'),
'required' => TRUE,
),
'created_date' => array(
'title' => ts('Date Created'),
),
'subject' => array(
'title' => ts('Subject'),
),
),
'filters' => array(
'is_completed' => array(
'title' => ts('Mailing Status'),
'operatorType' => CRM_Report_Form::OP_SELECT,
'type' => CRM_Utils_Type::T_INT,
'options' => array(
0 => 'Incomplete',
1 => 'Complete',
),
//'operator' => 'like',
'default' => 1,
),
'mailing_name' => array(
'name' => 'name',
'title' => ts('Mailing Name'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'type' => CRM_Utils_Type::T_STRING,
'options' => self::mailing_select(),
'operator' => 'like',
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
'type' => CRM_Utils_Type::T_STRING,
'operator' => 'like',
),
),
'order_bys' => array(
'mailing_name' => array(
'name' => 'name',
'title' => ts('Mailing Name'),
),
'mailing_subject' => array(
'name' => 'subject',
'title' => ts('Mailing Subject'),
),
),
);
$this->_columns['civicrm_mailing_job'] = array(
'dao' => 'CRM_Mailing_DAO_MailingJob',
'fields' => array(
'start_date' => array(
'title' => ts('Start Date'),
),
'end_date' => array(
'title' => ts('End Date'),
),
),
'filters' => array(
'status' => array(
'type' => CRM_Utils_Type::T_STRING,
'default' => 'Complete',
'no_display' => TRUE,
),
'is_test' => array(
'type' => CRM_Utils_Type::T_INT,
'default' => 0,
'no_display' => TRUE,
),
'start_date' => array(
'title' => ts('Start Date'),
'default' => 'this.year',
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
'end_date' => array(
'title' => ts('End Date'),
'default' => 'this.year',
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
),
'order_bys' => array(
'start_date' => array(
'title' => ts('Start Date'),
'dbAlias' => 'MIN(mailing_job_civireport.start_date)',
),
'end_date' => array(
'title' => ts('End Date'),
'default_weight' => '1',
'default_order' => 'DESC',
'dbAlias' => 'MAX(mailing_job_civireport.end_date)',
),
),
'grouping' => 'mailing-fields',
);
$this->_columns['civicrm_mailing_event_queue'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'queue_count' => array(
'name' => 'id',
'title' => ts('Intended Recipients'),
),
),
);
$this->_columns['civicrm_mailing_event_delivered'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'delivered_count' => array(
'name' => 'event_queue_id',
'title' => ts('Delivered'),
),
'accepted_rate' => array(
'title' => ts('Accepted Rate'),
'statistics' => array(
'calc' => 'PERCENTAGE',
'top' => 'civicrm_mailing_event_delivered.delivered_count',
'base' => 'civicrm_mailing_event_queue.queue_count',
),
),
),
);
$this->_columns['civicrm_mailing_event_bounce'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'bounce_count' => array(
'name' => 'event_queue_id',
'title' => ts('Bounce'),
),
'bounce_rate' => array(
'title' => ts('Bounce Rate'),
'statistics' => array(
'calc' => 'PERCENTAGE',
'top' => 'civicrm_mailing_event_bounce.bounce_count',
'base' => 'civicrm_mailing_event_queue.queue_count',
),
),
),
);
$this->_columns['civicrm_mailing_event_opened'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'unique_open_count' => array(
'name' => 'id',
'alias' => 'mailing_event_opened_civireport',
'dbAlias' => 'mailing_event_opened_civireport.event_queue_id',
'title' => ts('Unique Opens'),
),
'unique_open_rate' => array(
'title' => ts('Unique Open Rate'),
'statistics' => array(
'calc' => 'PERCENTAGE',
'top' => 'civicrm_mailing_event_opened.unique_open_count',
'base' => 'civicrm_mailing_event_delivered.delivered_count',
),
),
'open_count' => array(
'name' => 'event_queue_id',
'title' => ts('Total Opens'),
),
'open_rate' => array(
'title' => ts('Total Open Rate'),
'statistics' => array(
'calc' => 'PERCENTAGE',
'top' => 'civicrm_mailing_event_opened.open_count',
'base' => 'civicrm_mailing_event_delivered.delivered_count',
),
),
),
);
$this->_columns['civicrm_mailing_event_trackable_url_open'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'click_count' => array(
'name' => 'event_queue_id',
'title' => ts('Clicks'),
),
'CTR' => array(
'title' => ts('Click through Rate'),
'default' => 0,
'statistics' => array(
'calc' => 'PERCENTAGE',
'top' => 'civicrm_mailing_event_trackable_url_open.click_count',
'base' => 'civicrm_mailing_event_delivered.delivered_count',
),
),
'CTO' => array(
'title' => ts('Click to Open Rate'),
'default' => 0,
'statistics' => array(
'calc' => 'PERCENTAGE',
'top' => 'civicrm_mailing_event_trackable_url_open.click_count',
'base' => 'civicrm_mailing_event_opened.open_count',
),
),
),
);
$this->_columns['civicrm_mailing_event_unsubscribe'] = array(
'dao' => 'CRM_Mailing_DAO_Mailing',
'fields' => array(
'unsubscribe_count' => array(
'name' => 'id',
'title' => ts('Unsubscribe'),
'alias' => 'mailing_event_unsubscribe_civireport',
'dbAlias' => 'mailing_event_unsubscribe_civireport.event_queue_id',
),
'optout_count' => array(
'name' => 'id',
'title' => ts('Opt-outs'),
'alias' => 'mailing_event_optout_civireport',
'dbAlias' => 'mailing_event_optout_civireport.event_queue_id',
),
),
);
$this->_columns['civicrm_mailing_group'] = array(
'dao' => 'CRM_Mailing_DAO_MailingGroup',
'filters' => array(
'entity_id' => array(
'title' => ts('Groups Included in Mailing'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'type' => CRM_Utils_Type::T_INT,
'options' => CRM_Core_PseudoConstant::group(),
),
),
);
$config = CRM_Core_Config::singleton();
$this->campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
if ($this->campaignEnabled) {
$this->_columns['civicrm_campaign'] = array(
'dao' => 'CRM_Campaign_DAO_Campaign',
'fields' => array(
'title' => array(
'title' => ts('Campaign Name'),
),
),
'filters' => array(
'title' => array(
'type' => CRM_Utils_Type::T_STRING,
),
),
);
}
parent::__construct();
}
/**
* @return array
*/
public function mailing_select() {
$data = array();
$mailing = new CRM_Mailing_BAO_Mailing();
$query = "SELECT name FROM civicrm_mailing WHERE sms_provider_id IS NULL";
$mailing->query($query);
while ($mailing->fetch()) {
$data[CRM_Core_DAO::escapeString($mailing->name)] = $mailing->name;
}
return $data;
}
public function preProcess() {
$this->assign('chartSupported', TRUE);
parent::preProcess();
}
/**
* manipulate the select function to query count functions.
*/
public function select() {
$count_tables = array(
'civicrm_mailing_event_queue',
'civicrm_mailing_event_delivered',
'civicrm_mailing_event_opened',
'civicrm_mailing_event_bounce',
'civicrm_mailing_event_trackable_url_open',
'civicrm_mailing_event_unsubscribe',
);
// Define a list of columns that should be counted with the DISTINCT
// keyword. For example, civicrm_mailing_event_opened.unique_open_count
// should display the number of unique records, whereas something like
// civicrm_mailing_event_opened.open_count should display the total number.
// Each string here is in the form $tableName.$fieldName, where $tableName
// is the key in $this->_columns, and $fieldName is the key in that array's
// ['fields'] array.
// Reference: CRM-20660
$distinctCountColumns = array(
'civicrm_mailing_event_queue.queue_count',
'civicrm_mailing_event_delivered.delivered_count',
'civicrm_mailing_event_bounce.bounce_count',
'civicrm_mailing_event_opened.unique_open_count',
'civicrm_mailing_event_trackable_url_open.click_count',
'civicrm_mailing_event_unsubscribe.unsubscribe_count',
'civicrm_mailing_event_unsubscribe.optout_count',
);
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) || !empty($this->_params['fields'][$fieldName])) {
# for statistics
if (!empty($field['statistics'])) {
switch ($field['statistics']['calc']) {
case 'PERCENTAGE':
$base_table_column = explode('.', $field['statistics']['base']);
$top_table_column = explode('.', $field['statistics']['top']);
$select[] = "CONCAT(round(
count(DISTINCT {$this->_columns[$top_table_column[0]]['fields'][$top_table_column[1]]['dbAlias']}) /
count(DISTINCT {$this->_columns[$base_table_column[0]]['fields'][$base_table_column[1]]['dbAlias']}) * 100, 2
), '%') as {$tableName}_{$fieldName}";
break;
}
}
else {
if (in_array($tableName, $count_tables)) {
// Use the DISTINCT keyword appropriately, based on the contents
// of $distinct_count_columns.
$distinct = '';
if (in_array("{$tableName}.{$fieldName}", $distinctCountColumns)) {
$distinct = 'DISTINCT';
}
$select[] = "count($distinct {$field['dbAlias']}) as {$tableName}_{$fieldName}";
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
}
}
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
//print_r($this->_select);
}
public function from() {
$this->_from = "
FROM civicrm_mailing {$this->_aliases['civicrm_mailing']}
LEFT JOIN civicrm_mailing_job {$this->_aliases['civicrm_mailing_job']}
ON {$this->_aliases['civicrm_mailing']}.id = {$this->_aliases['civicrm_mailing_job']}.mailing_id
LEFT JOIN civicrm_mailing_event_queue {$this->_aliases['civicrm_mailing_event_queue']}
ON {$this->_aliases['civicrm_mailing_event_queue']}.job_id = {$this->_aliases['civicrm_mailing_job']}.id
LEFT JOIN civicrm_mailing_event_bounce {$this->_aliases['civicrm_mailing_event_bounce']}
ON {$this->_aliases['civicrm_mailing_event_bounce']}.event_queue_id = {$this->_aliases['civicrm_mailing_event_queue']}.id
LEFT JOIN civicrm_mailing_event_delivered {$this->_aliases['civicrm_mailing_event_delivered']}
ON {$this->_aliases['civicrm_mailing_event_delivered']}.event_queue_id = {$this->_aliases['civicrm_mailing_event_queue']}.id
AND {$this->_aliases['civicrm_mailing_event_bounce']}.id IS null
LEFT JOIN civicrm_mailing_event_opened {$this->_aliases['civicrm_mailing_event_opened']}
ON {$this->_aliases['civicrm_mailing_event_opened']}.event_queue_id = {$this->_aliases['civicrm_mailing_event_queue']}.id
LEFT JOIN civicrm_mailing_event_trackable_url_open {$this->_aliases['civicrm_mailing_event_trackable_url_open']}
ON {$this->_aliases['civicrm_mailing_event_trackable_url_open']}.event_queue_id = {$this->_aliases['civicrm_mailing_event_queue']}.id
LEFT JOIN civicrm_mailing_event_unsubscribe {$this->_aliases['civicrm_mailing_event_unsubscribe']}
ON {$this->_aliases['civicrm_mailing_event_unsubscribe']}.event_queue_id = {$this->_aliases['civicrm_mailing_event_queue']}.id AND {$this->_aliases['civicrm_mailing_event_unsubscribe']}.org_unsubscribe = 0
LEFT JOIN civicrm_mailing_event_unsubscribe mailing_event_optout_civireport
ON mailing_event_optout_civireport.event_queue_id = {$this->_aliases['civicrm_mailing_event_queue']}.id AND mailing_event_optout_civireport.org_unsubscribe = 1";
if ($this->isTableSelected('civicrm_mailing_group')) {
$this->_from .= "
LEFT JOIN civicrm_mailing_group {$this->_aliases['civicrm_mailing_group']}
ON {$this->_aliases['civicrm_mailing_group']}.mailing_id = {$this->_aliases['civicrm_mailing']}.id";
}
if ($this->campaignEnabled) {
$this->_from .= "
LEFT JOIN civicrm_campaign {$this->_aliases['civicrm_campaign']}
ON {$this->_aliases['civicrm_campaign']}.id = {$this->_aliases['civicrm_mailing']}.campaign_id";
}
// need group by and order by
//print_r($this->_from);
}
public function where() {
$clauses = array();
//to avoid the sms listings
$clauses[] = "{$this->_aliases['civicrm_mailing']}.sms_provider_id IS NULL";
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($this->_aliases[$tableName] . '.' . $field['name'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
if ($fieldName == 'relationship_type_id') {
$clause = "{$this->_aliases['civicrm_relationship']}.relationship_type_id=" . $this->relationshipId;
}
else {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE ( 1 )";
}
else {
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
}
public function groupBy() {
$groupBy = array(
"{$this->_aliases['civicrm_mailing']}.id",
);
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
public function orderBy() {
parent::orderBy();
CRM_Contact_BAO_Query::getGroupByFromOrderBy($this->_groupBy, $this->_orderByArray);
}
public function postProcess() {
$this->beginPostProcess();
// get the acl clauses built before we assemble the query
$this->buildACLClause(CRM_Utils_Array::value('civicrm_contact', $this->_aliases));
$sql = $this->buildQuery(TRUE);
// print_r($sql);
$rows = $graphRows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* @return array
*/
public static function getChartCriteria() {
return array(
'count' => array(
'civicrm_mailing_event_delivered_delivered_count' => ts('Delivered'),
'civicrm_mailing_event_bounce_bounce_count' => ts('Bounce'),
'civicrm_mailing_event_opened_open_count' => ts('Total Opens'),
'civicrm_mailing_event_opened_unique_open_count' => ts('Unique Opens'),
'civicrm_mailing_event_trackable_url_open_click_count' => ts('Clicks'),
'civicrm_mailing_event_unsubscribe_unsubscribe_count' => ts('Unsubscribe'),
),
'rate' => array(
'civicrm_mailing_event_delivered_accepted_rate' => ts('Accepted Rate'),
'civicrm_mailing_event_bounce_bounce_rate' => ts('Bounce Rate'),
'civicrm_mailing_event_opened_open_rate' => ts('Total Open Rate'),
'civicrm_mailing_event_opened_unique_open_rate' => ts('Unique Open Rate'),
'civicrm_mailing_event_trackable_url_open_CTR' => ts('Click through Rate'),
'civicrm_mailing_event_trackable_url_open_CTO' => ts('Click to Open Rate'),
),
);
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = array();
if (empty($fields['charts'])) {
return $errors;
}
$criteria = self::getChartCriteria();
$isError = TRUE;
foreach ($fields['fields'] as $fld => $isActive) {
if (in_array($fld, array(
'delivered_count',
'bounce_count',
'open_count',
'click_count',
'unsubscribe_count',
'accepted_rate',
'bounce_rate',
'open_rate',
'CTR',
'CTO',
'unique_open_rate',
'unique_open_count',
))) {
$isError = FALSE;
}
}
if ($isError) {
$errors['_qf_default'] = ts('For Chart view, please select at least one field from %1 OR %2.', array(
1 => implode(', ', $criteria['count']),
2 => implode(', ', $criteria['rate']),
));
}
return $errors;
}
/**
* @param $rows
*/
public function buildChart(&$rows) {
if (empty($rows)) {
return;
}
$criteria = self::getChartCriteria();
$chartInfo = array(
'legend' => ts('Mail Summary'),
'xname' => ts('Mailing'),
'yname' => ts('Statistics'),
'xLabelAngle' => 20,
'tip' => array(),
);
$plotRate = $plotCount = TRUE;
foreach ($rows as $row) {
$chartInfo['values'][$row['civicrm_mailing_name']] = array();
if ($plotCount) {
foreach ($criteria['count'] as $criteriaName => $label) {
if (isset($row[$criteriaName])) {
$chartInfo['values'][$row['civicrm_mailing_name']][$label] = $row[$criteriaName];
$chartInfo['tip'][$label] = "{$label} #val#";
$plotRate = FALSE;
}
elseif (isset($criteria['count'][$criteriaName])) {
unset($criteria['count'][$criteriaName]);
}
}
}
if ($plotRate) {
foreach ($criteria['rate'] as $criteriaName => $label) {
if (isset($row[$criteria])) {
$chartInfo['values'][$row['civicrm_mailing_name']][$label] = $row[$criteriaName];
$chartInfo['tip'][$label] = "{$label} #val#";
$plotCount = FALSE;
}
elseif (isset($criteria['rate'][$criteriaName])) {
unset($criteria['rate'][$criteriaName]);
}
}
}
}
if ($plotCount) {
$criteria = $criteria['count'];
}
else {
$criteria = $criteria['rate'];
}
$chartInfo['criteria'] = array_values($criteria);
// dynamically set the graph size
$chartInfo['xSize'] = ((count($rows) * 125) + (count($rows) * count($criteria) * 40));
// build the chart.
CRM_Utils_OpenFlashChart::buildChart($chartInfo, $this->_params['charts']);
$this->assign('chartType', $this->_params['charts']);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// CRM-16506
if (array_key_exists('civicrm_mailing_name', $row) &&
array_key_exists('civicrm_mailing_id', $row)
) {
$rows[$rowNum]['civicrm_mailing_name_link'] = CRM_Report_Utils_Report::getNextUrl('mailing/detail',
'reset=1&force=1&mailing_id_op=eq&mailing_id_value=' . $row['civicrm_mailing_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_mailing_name_hover'] = ts('View Mailing details for this mailing');
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,841 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Member_ContributionDetail extends CRM_Report_Form {
protected $_addressField = FALSE;
protected $_emailField = FALSE;
protected $_summary = NULL;
protected $_customGroupExtends = array(
'Contribution',
'Membership',
'Contact',
);
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array('CiviCampaign', $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Donor Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
'first_name' => array(
'title' => ts('First Name'),
'no_repeat' => TRUE,
),
'last_name' => array(
'title' => ts('Last Name'),
'no_repeat' => TRUE,
),
'nick_name' => array(
'title' => ts('Nickname'),
'no_repeat' => TRUE,
),
'contact_type' => array(
'title' => ts('Contact Type'),
'no_repeat' => TRUE,
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
'no_repeat' => TRUE,
),
'do_not_email' => array(
'title' => ts('Do Not Email'),
'no_repeat' => TRUE,
),
'is_opt_out' => array(
'title' => ts('No Bulk Email(Is Opt Out)'),
'no_repeat' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
'csv_display' => TRUE,
'title' => ts('Contact ID'),
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Donor Name'),
'operator' => 'like',
),
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'title' => ts('Donor Email'),
'default' => TRUE,
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array(
'phone' => array(
'title' => ts('Donor Phone'),
'default' => TRUE,
'no_repeat' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'first_donation' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'first_donation_date' => array(
'title' => ts('First Contribution Date'),
'base_field' => 'receive_date',
'no_repeat' => TRUE,
),
'first_donation_amount' => array(
'title' => ts('First Contribution Amount'),
'base_field' => 'total_amount',
'no_repeat' => TRUE,
),
),
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'contribution_id' => array(
'name' => 'id',
'no_display' => TRUE,
'required' => TRUE,
'csv_display' => TRUE,
'title' => ts('Contribution ID'),
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'default' => TRUE,
),
'contribution_recur_id' => array(
'title' => ts('Recurring Contribution Id'),
'name' => 'contribution_recur_id',
'required' => TRUE,
'no_display' => TRUE,
'csv_display' => TRUE,
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
),
'payment_instrument_id' => array(
'title' => ts('Payment Type'),
),
'contribution_source' => array(
'name' => 'source',
'title' => ts('Contribution Source'),
),
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'trxn_id' => NULL,
'receive_date' => array('default' => TRUE),
'receipt_date' => NULL,
'fee_amount' => NULL,
'net_amount' => NULL,
'total_amount' => array(
'title' => ts('Amount'),
'required' => TRUE,
),
),
'filters' => array(
'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialType(),
),
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'payment_instrument_id' => array(
'title' => ts('Payment Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::paymentInstrument(),
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'default' => array(1),
),
'total_amount' => array('title' => ts('Contribution Amount')),
),
'grouping' => 'contri-fields',
),
'civicrm_product' => array(
'dao' => 'CRM_Contribute_DAO_Product',
'fields' => array(
'product_name' => array(
'name' => 'name',
'title' => ts('Premium'),
),
),
),
'civicrm_batch' => array(
'dao' => 'CRM_Batch_DAO_EntityBatch',
'grouping' => 'contri-fields',
'fields' => array(
'batch_id' => array(
'name' => 'batch_id',
'title' => ts('Batch Name'),
),
),
'filters' => array(
'bid' => array(
'title' => ts('Batch Name'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Batch_BAO_Batch::getBatches(),
'type' => CRM_Utils_Type::T_INT,
'dbAlias' => 'batch_civireport.batch_id',
),
),
),
'civicrm_contribution_product' => array(
'dao' => 'CRM_Contribute_DAO_ContributionProduct',
'fields' => array(
'product_id' => array(
'no_display' => TRUE,
),
'product_option' => array(
'title' => ts('Premium Option'),
),
'fulfilled_date' => array(
'title' => ts('Premium Fulfilled Date'),
),
'contribution_id' => array(
'no_display' => TRUE,
),
),
),
'civicrm_contribution_ordinality' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'alias' => 'cordinality',
'filters' => array(
'ordinality' => array(
'title' => ts('Contribution Ordinality'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => array(
0 => 'First by Contributor',
1 => 'Second or Later by Contributor',
),
),
),
),
'civicrm_membership' => array(
'dao' => 'CRM_Member_DAO_Membership',
'fields' => array(
'membership_type_id' => array(
'title' => ts('Membership Type'),
'required' => TRUE,
'no_repeat' => TRUE,
),
'membership_start_date' => array(
'title' => ts('Start Date'),
'default' => TRUE,
),
'membership_end_date' => array(
'title' => ts('End Date'),
'default' => TRUE,
),
'join_date' => array(
'title' => ts('Join Date'),
'default' => TRUE,
),
'source' => array('title' => ts('Membership Source')),
),
'filters' => array(
'join_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'membership_start_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'membership_end_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'owner_membership_id' => array(
'title' => ts('Membership Owner ID'),
'operatorType' => CRM_Report_Form::OP_INT,
),
'tid' => array(
'name' => 'membership_type_id',
'title' => ts('Membership Types'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Member_PseudoConstant::membershipType(),
),
),
'grouping' => 'member-fields',
),
'civicrm_membership_status' => array(
'dao' => 'CRM_Member_DAO_MembershipStatus',
'alias' => 'mem_status',
'fields' => array(
'membership_status_name' => array(
'name' => 'name',
'title' => ts('Membership Status'),
'default' => TRUE,
),
),
'filters' => array(
'sid' => array(
'name' => 'id',
'title' => ts('Membership Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Member_PseudoConstant::membershipStatus(NULL, NULL, 'label'),
),
),
'grouping' => 'member-fields',
),
'civicrm_note' => array(
'dao' => 'CRM_Core_DAO_Note',
'fields' => array(
'contribution_note' => array(
'name' => 'note',
'title' => ts('Contribution Note'),
),
),
'filters' => array(
'note' => array(
'name' => 'note',
'title' => ts('Contribution Note'),
'operator' => 'like',
'type' => CRM_Utils_Type::T_STRING,
),
),
),
) + $this->addAddressFields(FALSE);
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_contribution']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
);
$this->_columns['civicrm_contribution']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
$this->_columns['civicrm_contribution']['order_bys']['campaign_id'] = array('title' => ts('Campaign'));
}
$this->_currencyColumn = 'civicrm_contribution_currency';
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
}
if ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
// only include statistics columns if set
if (!empty($field['statistics'])) {
foreach ($field['statistics'] as $stat => $label) {
switch (strtolower($stat)) {
case 'sum':
$select[] = "SUM({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'count':
$select[] = "COUNT({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'avg':
$select[] = "ROUND(AVG({$field['dbAlias']}),2) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
}
}
}
elseif ($fieldName == 'first_donation_date' ||
$fieldName == 'first_donation_amount'
) {
$baseField = CRM_Utils_Array::value('base_field', $field);
$select[] = "{$this->_aliases['civicrm_contribution']}.{$baseField} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
}
}
}
}
}
$this->_selectClauses = $select;
$this->_select = 'SELECT ' . implode(', ', $select) . ' ';
}
public function from() {
$this->_from = "
FROM civireport_membership_contribution_detail
INNER JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON (civireport_membership_contribution_detail.contribution_id = {$this->_aliases['civicrm_contribution']}.id)
LEFT JOIN civicrm_membership {$this->_aliases['civicrm_membership']}
ON (civireport_membership_contribution_detail.membership_id = {$this->_aliases['civicrm_membership']}.id)
INNER JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON (civireport_membership_contribution_detail.contact_id = {$this->_aliases['civicrm_contact']}.id)
LEFT JOIN civicrm_membership_status {$this->_aliases['civicrm_membership_status']}
ON {$this->_aliases['civicrm_membership_status']}.id =
{$this->_aliases['civicrm_membership']}.status_id
{$this->_aclFrom}
";
//for premiums
if (!empty($this->_params['fields']['product_name']) ||
!empty($this->_params['fields']['product_option']) ||
!empty($this->_params['fields']['fulfilled_date'])
) {
$this->_from .= "
LEFT JOIN civicrm_contribution_product {$this->_aliases['civicrm_contribution_product']}
ON ({$this->_aliases['civicrm_contribution_product']}.contribution_id = {$this->_aliases['civicrm_contribution']}.id)
LEFT JOIN civicrm_product {$this->_aliases['civicrm_product']} ON ({$this->_aliases['civicrm_product']}.id = {$this->_aliases['civicrm_contribution_product']}.product_id)";
}
if (!empty($this->_params['ordinality_value'])) {
$this->_from .= "
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']}
ON {$this->_aliases['civicrm_contribution_ordinality']}.id = {$this->_aliases['civicrm_contribution']}.id";
}
// include contribution note
if (!empty($this->_params['fields']['contribution_note']) ||
!empty($this->_params['note_value'])
) {
$this->_from .= "
LEFT JOIN civicrm_note {$this->_aliases['civicrm_note']}
ON ( {$this->_aliases['civicrm_note']}.entity_table = 'civicrm_contribution' AND
{$this->_aliases['civicrm_contribution']}.id = {$this->_aliases['civicrm_note']}.entity_id )";
}
if (!empty($this->_params['fields']['phone'])) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON ({$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1)";
}
//for contribution batches
if (!empty($this->_params['fields']['batch_id']) ||
!empty($this->_params['bid_value'])
) {
$this->_from .= "
LEFT JOIN civicrm_entity_financial_trxn eft
ON eft.entity_id = {$this->_aliases['civicrm_contribution']}.id AND
eft.entity_table = 'civicrm_contribution'
LEFT JOIN civicrm_entity_batch {$this->_aliases['civicrm_batch']}
ON ({$this->_aliases['civicrm_batch']}.entity_id = eft.financial_trxn_id
AND {$this->_aliases['civicrm_batch']}.entity_table = 'civicrm_financial_trxn')";
}
if ($this->_addressField OR
(!empty($this->_params['state_province_id_value']) OR
!empty($this->_params['country_id_value']))
) {
$this->_from .= "
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1\n";
}
if ($this->_emailField) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1\n";
}
}
/**
* @param bool $applyLimit
*/
public function tempTable($applyLimit = TRUE) {
// create temp table with contact ids,contribtuion id,membership id
$dropTempTable = 'DROP TEMPORARY TABLE IF EXISTS civireport_membership_contribution_detail';
CRM_Core_DAO::executeQuery($dropTempTable);
$sql = 'CREATE TEMPORARY TABLE civireport_membership_contribution_detail
(contribution_id int, INDEX USING HASH(contribution_id), contact_id int, INDEX USING HASH(contact_id),
membership_id int, INDEX USING HASH(membership_id), payment_id int, INDEX USING HASH(payment_id)) ENGINE=MEMORY' . $this->_databaseAttributes;
CRM_Core_DAO::executeQuery($sql);
$fillTemp = "
INSERT INTO civireport_membership_contribution_detail (contribution_id, contact_id, membership_id)
SELECT contribution.id, {$this->_aliases['civicrm_contact']}.id, m.id
FROM civicrm_contribution contribution
INNER JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON {$this->_aliases['civicrm_contact']}.id = contribution.contact_id AND contribution.is_test = 0
{$this->_aclFrom}
LEFT JOIN civicrm_membership_payment mp
ON contribution.id = mp.contribution_id
LEFT JOIN civicrm_membership m
ON mp.membership_id = m.id AND m.is_test = 0 ";
CRM_Core_DAO::executeQuery($fillTemp);
}
/**
* @param bool $applyLimit
*
* @return string
*/
public function buildQuery($applyLimit = TRUE) {
$this->select();
//create temp table to be used as base table
$this->tempTable();
$this->from();
$this->customDataFrom();
$this->buildPermissionClause();
$this->where();
$this->groupBy();
$this->orderBy();
// order_by columns not selected for display need to be included in SELECT
$unselectedSectionColumns = $this->unselectedSectionColumns();
foreach ($unselectedSectionColumns as $alias => $section) {
$this->_select .= ", {$section['dbAlias']} as {$alias}";
}
if ($applyLimit && empty($this->_params['charts'])) {
$this->limit();
}
$sql = "{$this->_select} {$this->_from} {$this->_where} {$this->_groupBy} {$this->_having} {$this->_orderBy} {$this->_limit}";
$this->addToDeveloperTab($sql);
return $sql;
}
public function groupBy() {
$groupBy = array(
"{$this->_aliases['civicrm_contact']}.id",
"{$this->_aliases['civicrm_contribution']}.id",
);
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
public function orderBy() {
$this->_orderBy = " ORDER BY {$this->_aliases['civicrm_contact']}.sort_name, {$this->_aliases['civicrm_contact']}.id ";
if (!empty($this->_params['fields']['first_donation_date']) ||
!empty($this->_params['fields']['first_donation_amount'])
) {
$this->_orderBy .= ", {$this->_aliases['civicrm_contribution']}.receive_date";
}
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
$select = "SELECT DISTINCT {$this->_aliases['civicrm_contribution']}.id";
$sql = "SELECT COUNT(cc.id) as count, SUM(cc.total_amount) as amount, ROUND(AVG(cc.total_amount), 2) as avg, cc.currency as currency
FROM civicrm_contribution cc
WHERE cc.id IN ({$select} {$this->_from} {$this->_where})
GROUP BY cc.currency";
$dao = CRM_Core_DAO::executeQuery($sql);
$totalAmount = $average = array();
while ($dao->fetch()) {
$totalAmount[]
= CRM_Utils_Money::format($dao->amount, $dao->currency) . "(" .
$dao->count . ")";
$average[] = CRM_Utils_Money::format($dao->avg, $dao->currency);
}
$statistics['counts']['amount'] = array(
'title' => ts('Total Amount'),
'value' => implode(', ', $totalAmount),
'type' => CRM_Utils_Type::T_STRING,
);
$statistics['counts']['avg'] = array(
'title' => ts('Average'),
'value' => implode(', ', $average),
'type' => CRM_Utils_Type::T_STRING,
);
return $statistics;
}
public function postProcess() {
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
parent::postProcess();
}
/**
* @param $rows
*/
public function alterDisplay(&$rows) {
// custom code to alter rows
$checkList = array();
$entryFound = FALSE;
$contributionTypes = CRM_Contribute_PseudoConstant::financialType();
$contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus();
$paymentInstruments = CRM_Contribute_PseudoConstant::paymentInstrument();
$batches = CRM_Batch_BAO_Batch::getBatches();
//altering the csv display adding additional fields
if ($this->_outputMode == 'csv') {
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['csv_display']) && !empty($field['no_display'])) {
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
}
}
}
}
}
// allow repeat for first donation amount and date in csv
$fAmt = '';
$fDate = '';
foreach ($rows as $rowNum => $row) {
if ($this->_outputMode == 'csv') {
if (array_key_exists('civicrm_contact_id', $row)) {
if ($contactId = $row['civicrm_contact_id']) {
if ($rowNum == 0) {
$pcid = $contactId;
$fAmt = $row['first_donation_first_donation_amount'];
$fDate = $row['first_donation_first_donation_date'];
}
else {
if ($pcid == $contactId) {
$rows[$rowNum]['first_donation_first_donation_amount'] = $fAmt;
$rows[$rowNum]['first_donation_first_donation_date'] = $fDate;
$pcid = $contactId;
}
else {
$fAmt = $row['first_donation_first_donation_amount'];
$fDate = $row['first_donation_first_donation_date'];
$pcid = $contactId;
}
}
}
}
}
if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
$repeatFound = FALSE;
$display_flag = NULL;
if (array_key_exists('civicrm_contact_id', $row)) {
if ($cid = $row['civicrm_contact_id']) {
if ($rowNum == 0) {
$prev_cid = $cid;
}
else {
if ($prev_cid == $cid) {
$display_flag = 1;
$prev_cid = $cid;
}
else {
$display_flag = 0;
$prev_cid = $cid;
}
}
if ($display_flag) {
foreach ($row as $colName => $colVal) {
if (in_array($colName, $this->_noRepeats)) {
unset($rows[$rowNum][$colName]);
}
}
}
$entryFound = TRUE;
}
}
}
if (array_key_exists('civicrm_membership_membership_type_id', $row)) {
if ($value = $row['civicrm_membership_membership_type_id']) {
$rows[$rowNum]['civicrm_membership_membership_type_id'] = CRM_Member_PseudoConstant::membershipType($value, FALSE);
}
$entryFound = TRUE;
}
if (!empty($row['civicrm_batch_batch_id'])) {
$rows[$rowNum]['civicrm_batch_batch_id'] = CRM_Utils_Array::value($row['civicrm_batch_batch_id'], $batches);
$entryFound = TRUE;
}
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
// convert donor sort name to link
if (array_key_exists('civicrm_contact_sort_name', $row) &&
!empty($rows[$rowNum]['civicrm_contact_sort_name']) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url('civicrm/contact/view',
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts('View Contact Summary for this Contact.');
}
if ($value = CRM_Utils_Array::value('civicrm_contribution_financial_type_id', $row)) {
$rows[$rowNum]['civicrm_contribution_financial_type_id'] = $contributionTypes[$value];
$entryFound = TRUE;
}
if ($value = CRM_Utils_Array::value('civicrm_contribution_contribution_status_id', $row)) {
$rows[$rowNum]['civicrm_contribution_contribution_status_id'] = $contributionStatus[$value];
$entryFound = TRUE;
}
if ($value = CRM_Utils_Array::value('civicrm_contribution_payment_instrument_id', $row)) {
$rows[$rowNum]['civicrm_contribution_payment_instrument_id'] = $paymentInstruments[$value];
$entryFound = TRUE;
}
if (($value = CRM_Utils_Array::value('civicrm_contribution_total_amount_sum', $row)) &&
CRM_Core_Permission::check('access CiviContribute')
) {
$url = CRM_Utils_System::url('civicrm/contact/view/contribution',
'reset=1&id=' . $row['civicrm_contribution_contribution_id'] .
'&cid=' . $row['civicrm_contact_id'] .
'&action=view&context=contribution&selectedChild=contribute',
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contribution_total_amount_sum_link'] = $url;
$rows[$rowNum]['civicrm_contribution_total_amount_sum_hover'] = ts('View Details of this Contribution.');
$entryFound = TRUE;
}
// convert campaign_id to campaign title
if (array_key_exists('civicrm_contribution_campaign_id', $row)) {
if ($value = $row['civicrm_contribution_campaign_id']) {
$rows[$rowNum]['civicrm_contribution_campaign_id'] = $this->activeCampaigns[$value];
$entryFound = TRUE;
}
}
$entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'member/contributionDetail', 'List all contribution(s) for this ') ? TRUE : $entryFound;
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
$lastKey = $rowNum;
}
}
}

View file

@ -0,0 +1,489 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Member_Detail extends CRM_Report_Form {
protected $_addressField = FALSE;
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
protected $_contribField = FALSE;
protected $_summary = NULL;
protected $_customGroupExtends = array(
'Membership',
'Contribution',
'Contact',
'Individual',
'Household',
'Organization',
);
protected $_customGroupGroupBy = FALSE;
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
// Check if CiviCampaign is a) enabled and b) has active campaigns
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => $this->getBasicContactFields(),
'filters' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'operator' => 'like',
),
'id' => array('no_display' => TRUE),
),
'order_bys' => array(
'sort_name' => array(
'title' => ts('Last Name, First Name'),
'default' => '1',
'default_weight' => '0',
'default_order' => 'ASC',
),
),
'grouping' => 'contact-fields',
),
'civicrm_membership' => array(
'dao' => 'CRM_Member_DAO_Membership',
'fields' => array(
'membership_type_id' => array(
'title' => ts('Membership Type'),
'required' => TRUE,
'no_repeat' => TRUE,
),
'membership_start_date' => array(
'title' => ts('Start Date'),
'default' => TRUE,
),
'membership_end_date' => array(
'title' => ts('End Date'),
'default' => TRUE,
),
'join_date' => array(
'title' => ts('Join Date'),
'default' => TRUE,
),
'source' => array('title' => ts('Source')),
),
'filters' => array(
'join_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'membership_start_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'membership_end_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'owner_membership_id' => array(
'title' => ts('Membership Owner ID'),
'operatorType' => CRM_Report_Form::OP_INT,
),
'tid' => array(
'name' => 'membership_type_id',
'title' => ts('Membership Types'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Member_PseudoConstant::membershipType(),
),
),
'order_bys' => array(
'membership_type_id' => array(
'title' => ts('Membership Type'),
'default' => '0',
'default_weight' => '1',
'default_order' => 'ASC',
),
),
'grouping' => 'member-fields',
'group_bys' => array(
'id' => array(
'title' => ts('Membership'),
'default' => TRUE,
),
),
),
'civicrm_membership_status' => array(
'dao' => 'CRM_Member_DAO_MembershipStatus',
'alias' => 'mem_status',
'fields' => array(
'name' => array(
'title' => ts('Status'),
'default' => TRUE,
),
),
'filters' => array(
'sid' => array(
'name' => 'id',
'title' => ts('Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Member_PseudoConstant::membershipStatus(NULL, NULL, 'label'),
),
),
'grouping' => 'member-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array('email' => NULL),
'grouping' => 'contact-fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array('phone' => NULL),
'grouping' => 'contact-fields',
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'contribution_id' => array(
'name' => 'id',
'no_display' => TRUE,
'required' => TRUE,
),
'financial_type_id' => array('title' => ts('Financial Type')),
'contribution_status_id' => array('title' => ts('Contribution Status')),
'payment_instrument_id' => array('title' => ts('Payment Type')),
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'trxn_id' => NULL,
'receive_date' => NULL,
'receipt_date' => NULL,
'fee_amount' => NULL,
'net_amount' => NULL,
'total_amount' => array(
'title' => ts('Payment Amount (most recent)'),
'statistics' => array('sum' => ts('Amount')),
),
),
'filters' => array(
'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialType(),
'type' => CRM_Utils_Type::T_INT,
),
'payment_instrument_id' => array(
'title' => ts('Payment Type'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::paymentInstrument(),
'type' => CRM_Utils_Type::T_INT,
),
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
'type' => CRM_Utils_Type::T_INT,
),
'total_amount' => array('title' => ts('Contribution Amount')),
),
'order_bys' => array(
'receive_date' => array(
'title' => ts('Date Received'),
'default_weight' => '2',
'default_order' => 'DESC',
),
),
'grouping' => 'contri-fields',
),
) + $this->getAddressColumns(array(
// These options are only excluded because they were not previously present.
'order_by' => FALSE,
'group_by' => FALSE,
));
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
// If we have active campaigns add those elements to both the fields and filters
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_membership']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
);
$this->_columns['civicrm_membership']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
$this->_columns['civicrm_membership']['order_bys']['campaign_id'] = array('title' => ts('Campaign'));
}
$this->_currencyColumn = 'civicrm_contribution_currency';
parent::__construct();
}
public function preProcess() {
$this->assign('reportTitle', ts('Membership Detail Report'));
parent::preProcess();
}
public function select() {
$select = $this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) || !empty($this->_params['fields'][$fieldName])) {
if ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
elseif ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
}
elseif ($tableName == 'civicrm_contribution') {
$this->_contribField = TRUE;
}
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
if (array_key_exists('title', $field)) {
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}
INNER JOIN civicrm_membership {$this->_aliases['civicrm_membership']}
ON {$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_membership']}.contact_id AND {$this->_aliases['civicrm_membership']}.is_test = 0
LEFT JOIN civicrm_membership_status {$this->_aliases['civicrm_membership_status']}
ON {$this->_aliases['civicrm_membership_status']}.id =
{$this->_aliases['civicrm_membership']}.status_id ";
if ($this->isTableSelected('civicrm_address')) {
$this->_from .= "
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON {$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_address']}.contact_id AND
{$this->_aliases['civicrm_address']}.is_primary = 1\n";
}
//used when email field is selected
if ($this->_emailField) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON {$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_email']}.contact_id AND
{$this->_aliases['civicrm_email']}.is_primary = 1\n";
}
//used when phone field is selected
if ($this->_phoneField) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_phone']}.contact_id AND
{$this->_aliases['civicrm_phone']}.is_primary = 1\n";
}
//used when contribution field is selected
if ($this->_contribField) {
$this->_from .= "
LEFT JOIN civicrm_membership_payment cmp
ON {$this->_aliases['civicrm_membership']}.id = cmp.membership_id
LEFT JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON cmp.contribution_id={$this->_aliases['civicrm_contribution']}.id\n";
}
}
public function postProcess() {
$this->beginPostProcess();
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
$sql = $this->buildQuery(TRUE);
$rows = array();
$this->buildRows($sql, $rows);
$this->formatDisplay($rows);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$checkList = array();
$contributionTypes = CRM_Contribute_PseudoConstant::financialType();
$contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus();
$paymentInstruments = CRM_Contribute_PseudoConstant::paymentInstrument();
$repeatFound = FALSE;
foreach ($rows as $rowNum => $row) {
if ($repeatFound == FALSE ||
$repeatFound < $rowNum - 1
) {
unset($checkList);
$checkList = array();
}
if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
// not repeat contact display names if it matches with the one
// in previous row
foreach ($row as $colName => $colVal) {
if (in_array($colName, $this->_noRepeats) &&
$rowNum > 0
) {
if ($rows[$rowNum][$colName] == $rows[$rowNum - 1][$colName] ||
(!empty($checkList[$colName]) &&
in_array($colVal, $checkList[$colName]))
) {
$rows[$rowNum][$colName] = "";
// CRM-15917: Don't blank the name if it's a different contact
if ($colName == 'civicrm_contact_exposed_id') {
$rows[$rowNum]['civicrm_contact_sort_name'] = "";
}
$repeatFound = $rowNum;
}
}
if (in_array($colName, $this->_noRepeats)) {
$checkList[$colName][] = $colVal;
}
}
}
if (array_key_exists('civicrm_membership_membership_type_id', $row)) {
if ($value = $row['civicrm_membership_membership_type_id']) {
$rows[$rowNum]['civicrm_membership_membership_type_id'] = CRM_Member_PseudoConstant::membershipType($value, FALSE);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
if (array_key_exists('civicrm_contact_sort_name', $row) &&
$rows[$rowNum]['civicrm_contact_sort_name'] &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url("civicrm/contact/view",
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact Summary for this Contact.");
$entryFound = TRUE;
}
if ($value = CRM_Utils_Array::value('civicrm_contribution_financial_type_id', $row)) {
$rows[$rowNum]['civicrm_contribution_financial_type_id'] = $contributionTypes[$value];
$entryFound = TRUE;
}
if ($value = CRM_Utils_Array::value('civicrm_contribution_contribution_status_id', $row)) {
$rows[$rowNum]['civicrm_contribution_contribution_status_id'] = $contributionStatus[$value];
$entryFound = TRUE;
}
if ($value = CRM_Utils_Array::value('civicrm_contribution_payment_instrument_id', $row)) {
$rows[$rowNum]['civicrm_contribution_payment_instrument_id'] = $paymentInstruments[$value];
$entryFound = TRUE;
}
// Convert campaign_id to campaign title
if (array_key_exists('civicrm_membership_campaign_id', $row)) {
if ($value = $row['civicrm_membership_campaign_id']) {
$rows[$rowNum]['civicrm_membership_campaign_id'] = $this->activeCampaigns[$value];
$entryFound = TRUE;
}
}
$entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'member/detail', 'List all memberships(s) for this ') ? TRUE : $entryFound;
$entryFound = $this->alterDisplayContactFields($row, $rows, $rowNum, 'member/detail', 'List all memberships(s) for this ') ? TRUE : $entryFound;
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,457 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Member_Lapse extends CRM_Report_Form {
protected $_summary = NULL;
protected $_addressField = FALSE;
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
protected $_charts = array('' => 'Tabular');
protected $_customGroupExtends = array(
'Membership',
);
public $_drilldownReport = array('member/detail' => 'Link to Detail Report');
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
// Check if CiviCampaign is a) enabled and b) has active campaigns
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
// UI for selecting columns to appear in the report list
// array containing the columns, group_bys and filters build and provided to Form
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Member Name'),
'no_repeat' => TRUE,
'required' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'first_name' => array(
'title' => ts('First Name'),
'no_repeat' => TRUE,
),
'last_name' => array(
'title' => ts('Last Name'),
'no_repeat' => TRUE,
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
'grouping' => 'contact-fields',
),
'civicrm_membership_type' => array(
'dao' => 'CRM_Member_DAO_MembershipType',
'grouping' => 'member-fields',
'filters' => array(
'tid' => array(
'name' => 'id',
'title' => ts('Membership Types'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Member_PseudoConstant::membershipType(),
),
),
),
'civicrm_membership' => array(
'dao' => 'CRM_Member_DAO_Membership',
'grouping' => 'member-fields',
'fields' => array(
'membership_type_id' => array(
'title' => ts('Membership Type'),
'required' => TRUE,
'type' => CRM_Utils_Type::T_STRING,
),
'membership_start_date' => array(
'title' => ts('Current Cycle Start Date'),
),
'membership_end_date' => array(
'title' => ts('Membership Lapse Date'),
'required' => TRUE,
),
),
'filters' => array(
'membership_end_date' => array(
'title' => ts('Lapsed Memberships'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
),
),
'civicrm_membership_status' => array(
'dao' => 'CRM_Member_DAO_MembershipStatus',
'alias' => 'mem_status',
'fields' => array(
'name' => array(
'title' => ts('Current Status'),
'required' => TRUE,
),
),
'grouping' => 'member-fields',
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'fields' => array(
'street_address' => NULL,
'city' => NULL,
'postal_code' => NULL,
'state_province_id' => array(
'title' => ts('State/Province'),
),
'country_id' => array(
'title' => ts('Country'),
'default' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'alias' => 'phone',
'fields' => array('phone' => NULL),
'grouping' => 'contact-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array('email' => NULL),
'grouping' => 'contact-fields',
),
);
// If we have a campaign, build out the relevant elements
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_membership']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
);
$this->_columns['civicrm_membership']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
}
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
// to include optional columns address ,email and phone only if checked
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
}
elseif ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
elseif ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
}
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = $grouping = array();
//check for searching combination of dispaly columns and
//grouping criteria
return $errors;
}
public function from() {
$this->_from = NULL;
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}
INNER JOIN civicrm_membership {$this->_aliases['civicrm_membership']}
ON {$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_membership']}.contact_id AND {$this->_aliases['civicrm_membership']}.is_test = 0
LEFT JOIN civicrm_membership_status {$this->_aliases['civicrm_membership_status']}
ON {$this->_aliases['civicrm_membership_status']}.id =
{$this->_aliases['civicrm_membership']}.status_id
LEFT JOIN civicrm_membership_type {$this->_aliases['civicrm_membership_type']}
ON {$this->_aliases['civicrm_membership']}.membership_type_id =
{$this->_aliases['civicrm_membership_type']}.id";
// include address field if address column is to be included
if ($this->_addressField) {
$this->_from .= "
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND {$this->_aliases['civicrm_address']}.is_primary = 1\n";
}
// include email field if email column is to be included
if ($this->_emailField) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND {$this->_aliases['civicrm_email']}.is_primary = 1\n";
}
// include phone field if phone column is to be included
if ($this->_phoneField) {
$this->_from .= "
LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id
AND {$this->_aliases['civicrm_phone']}.is_primary = 1\n";
}
}
public function where() {
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if ($field['operatorType'] & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($relative || $from || $to) {
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[$fieldName] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE end_date < '" . date('Y-m-d') .
"' AND {$this->_aliases['civicrm_membership_status']}.name = 'Expired'";
}
else {
if (!array_key_exists('end_date', $clauses)) {
$this->_where = "WHERE end_date < '" . date('Y-m-d') . "' AND " .
implode(' AND ', $clauses);
}
else {
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
public function orderBy() {
$this->_orderBy = " ORDER BY {$this->_aliases['civicrm_contact']}.sort_name, {$this->_aliases['civicrm_contact']}.id, {$this->_aliases['civicrm_membership']}.membership_type_id";
}
public function postProcess() {
$this->beginPostProcess();
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
$sql = $this->buildQuery(TRUE);
$dao = CRM_Core_DAO::executeQuery($sql);
$rows = $graphRows = array();
$count = 0;
while ($dao->fetch()) {
$row = array();
foreach ($this->_columnHeaders as $key => $value) {
$row[$key] = $dao->$key;
}
$rows[] = $row;
}
$this->formatDisplay($rows);
// assign variables to templates
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$checkList = array();
foreach ($rows as $rowNum => $row) {
if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
// not repeat contact display names if it matches with the one
// in previous row
$repeatFound = FALSE;
foreach ($row as $colName => $colVal) {
if (!empty($checkList[$colName]) &&
is_array($checkList[$colName]) &&
in_array($colVal, $checkList[$colName])
) {
$rows[$rowNum][$colName] = "";
$repeatFound = TRUE;
}
if (in_array($colName, $this->_noRepeats)) {
$checkList[$colName][] = $colVal;
}
}
}
//handle the Membership Type Ids
if (array_key_exists('civicrm_membership_membership_type_id', $row)) {
if ($value = $row['civicrm_membership_membership_type_id']) {
$rows[$rowNum]['civicrm_membership_membership_type_id'] = CRM_Member_PseudoConstant::membershipType($value, FALSE);
}
$entryFound = TRUE;
}
// handle state province
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
}
$entryFound = TRUE;
}
// handle country
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('member/detail',
'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Membership Detail for this Contact.");
}
// If using campaigns, convert campaign_id to campaign title
if (array_key_exists('civicrm_membership_campaign_id', $row)) {
if ($value = $row['civicrm_membership_campaign_id']) {
$rows[$rowNum]['civicrm_membership_campaign_id'] = $this->activeCampaigns[$value];
}
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,658 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Member_Summary extends CRM_Report_Form {
protected $_summary = NULL;
protected $_interval = NULL;
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
protected $_add2groupSupported = FALSE;
protected $_customGroupExtends = array('Membership');
protected $_customGroupGroupBy = FALSE;
public $_drilldownReport = array('member/detail' => 'Link to Detail Report');
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
// UI for selecting columns to appear in the report list
// Array containing the columns, group_bys and filters build and provided to Form
// Check if CiviCampaign is a) enabled and b) has active campaigns
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
$this->_columns = array(
'civicrm_membership' => array(
'dao' => 'CRM_Member_DAO_MembershipType',
'grouping' => 'member-fields',
'fields' => array(
'membership_type_id' => array(
'title' => ts('Membership Type'),
'required' => TRUE,
),
),
'filters' => array(
'join_date' => array(
'title' => ts('Member Since'),
'type' => CRM_Utils_Type::T_DATE,
'operatorType' => CRM_Report_Form::OP_DATE,
),
'membership_start_date' => array(
'name' => 'start_date',
'title' => ts('Membership Start Date'),
'type' => CRM_Utils_Type::T_DATE,
'operatorType' => CRM_Report_Form::OP_DATE,
),
'membership_end_date' => array(
'name' => 'end_date',
'title' => ts('Membership End Date'),
'type' => CRM_Utils_Type::T_DATE,
'operatorType' => CRM_Report_Form::OP_DATE,
),
'owner_membership_id' => array(
'title' => ts('Membership Owner ID'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_INT,
),
'membership_type_id' => array(
'title' => ts('Membership Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Member_PseudoConstant::membershipType(),
),
'status_id' => array(
'title' => ts('Membership Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Member_PseudoConstant::membershipStatus(NULL, NULL, 'label'),
),
),
'group_bys' => array(
'join_date' => array(
'title' => ts('Member Since'),
'default' => TRUE,
'frequency' => TRUE,
'chart' => TRUE,
'type' => 12,
),
'membership_type_id' => array(
'title' => ts('Membership Type'),
'default' => TRUE,
'chart' => TRUE,
),
),
),
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'contact_id' => array(
'no_display' => TRUE,
),
'contact_type' => array(
'title' => ts('Contact Type'),
),
'contact_sub_type' => array(
'title' => ts('Contact Subtype'),
),
),
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'fields' => array(
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'total_amount' => array(
'title' => ts('Amount Statistics'),
'required' => TRUE,
'statistics' => array(
'sum' => ts('Total Payments Made'),
'count' => ts('Contribution Count'),
'avg' => ts('Average'),
),
),
),
'filters' => array(
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'contribution_status_id' => array(
'title' => ts('Contribution Status'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
),
),
'grouping' => 'member-fields',
),
);
$this->_tagFilter = TRUE;
// If we have a campaign, build out the relevant elements
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_membership']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
);
$this->_columns['civicrm_membership']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
$this->_columns['civicrm_membership']['group_bys']['campaign_id'] = array('title' => ts('Campaign'));
}
$this->_groupFilter = TRUE;
$this->_currencyColumn = 'civicrm_contribution_currency';
parent::__construct();
}
public function select() {
$select = array();
$groupBys = FALSE;
$this->_columnHeaders = array();
$select[] = " COUNT( DISTINCT {$this->_aliases['civicrm_membership']}.id ) as civicrm_membership_member_count";
$select['joinDate'] = " {$this->_aliases['civicrm_membership']}.join_date as civicrm_membership_member_join_date";
$this->_columnHeaders["civicrm_membership_member_join_date"] = array(
'title' => ts('Member Since'),
'type' => CRM_Utils_Type::T_DATE,
);
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('group_bys', $table)) {
foreach ($table['group_bys'] as $fieldName => $field) {
if (!empty($this->_params['group_bys'][$fieldName])) {
switch (CRM_Utils_Array::value($fieldName, $this->_params['group_bys_freq'])) {
case 'YEARWEEK':
$select[] = "DATE_SUB({$field['dbAlias']}, INTERVAL WEEKDAY({$field['dbAlias']}) DAY) AS {$tableName}_{$fieldName}_start";
$select[] = "YEARWEEK({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "WEEKOFYEAR({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Week';
break;
case 'YEAR':
$select[] = "MAKEDATE(YEAR({$field['dbAlias']}), 1) AS {$tableName}_{$fieldName}_start";
$select[] = "YEAR({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "YEAR({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Year';
break;
case 'MONTH':
$select[] = "DATE_SUB({$field['dbAlias']}, INTERVAL (DAYOFMONTH({$field['dbAlias']})-1) DAY) as {$tableName}_{$fieldName}_start";
$select[] = "MONTH({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "MONTHNAME({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Month';
break;
case 'QUARTER':
$select[] = "STR_TO_DATE(CONCAT( 3 * QUARTER( {$field['dbAlias']} ) -2 , '/', '1', '/', YEAR( {$field['dbAlias']} ) ), '%m/%d/%Y') AS {$tableName}_{$fieldName}_start";
$select[] = "QUARTER({$field['dbAlias']}) AS {$tableName}_{$fieldName}_subtotal";
$select[] = "QUARTER({$field['dbAlias']}) AS {$tableName}_{$fieldName}_interval";
$field['title'] = 'Quarter';
break;
}
if (!empty($this->_params['group_bys_freq'][$fieldName])) {
$this->_interval = $field['title'];
$this->_columnHeaders["{$tableName}_{$fieldName}_start"]['title'] = $field['title'] . ' Beginning';
$this->_columnHeaders["{$tableName}_{$fieldName}_start"]['type'] = $field['type'];
$this->_columnHeaders["{$tableName}_{$fieldName}_start"]['group_by'] = $this->_params['group_bys_freq'][$fieldName];
// just to make sure these values are transferred to rows.
// since we need that for calculation purpose,
// e.g making subtotals look nicer or graphs
$this->_columnHeaders["{$tableName}_{$fieldName}_interval"] = array('no_display' => TRUE);
$this->_columnHeaders["{$tableName}_{$fieldName}_subtotal"] = array('no_display' => TRUE);
}
$groupBys = TRUE;
}
}
}
// end of select
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
// only include statistics columns if set
if (!empty($field['statistics'])) {
$this->_statFields[] = 'civicrm_membership_member_count';
foreach ($field['statistics'] as $stat => $label) {
switch (strtolower($stat)) {
case 'sum':
$select[] = "IFNULL(SUM({$field['dbAlias']}), 0) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'count':
$select[] = "COUNT({$field['dbAlias']}) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = CRM_Utils_Type::T_INT;
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
case 'avg':
$select[] = "IFNULL(ROUND(AVG({$field['dbAlias']}),2), 0) as {$tableName}_{$fieldName}_{$stat}";
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['type'] = $field['type'];
$this->_columnHeaders["{$tableName}_{$fieldName}_{$stat}"]['title'] = $label;
$this->_statFields[] = "{$tableName}_{$fieldName}_{$stat}";
break;
}
}
}
elseif ($fieldName == 'membership_type_id') {
if (empty($this->_params['group_bys']['membership_type_id']) &&
!empty($this->_params['group_bys']['join_date'])
) {
$select[] = "GROUP_CONCAT(DISTINCT {$field['dbAlias']} ORDER BY {$field['dbAlias']} ) as {$tableName}_{$fieldName}";
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
}
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
$this->_columnHeaders["{$tableName}_{$fieldName}"]['operatorType'] = CRM_Utils_Array::value('operatorType', $field);
}
else {
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
$this->_columnHeaders["{$tableName}_{$fieldName}"]['operatorType'] = CRM_Utils_Array::value('operatorType', $field);
}
}
}
}
$this->_columnHeaders["civicrm_membership_member_count"] = array(
'title' => ts('Member Count'),
'type' => CRM_Utils_Type::T_INT,
);
}
//If grouping is availabled then remove join date from field
if ($groupBys) {
unset($select['joinDate']);
unset($this->_columnHeaders["civicrm_membership_member_join_date"]);
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$this->_from = "
FROM civicrm_membership {$this->_aliases['civicrm_membership']}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']} ON ( {$this->_aliases['civicrm_membership']}.contact_id = {$this->_aliases['civicrm_contact']}.id )
LEFT JOIN civicrm_membership_status
ON ({$this->_aliases['civicrm_membership']}.status_id = civicrm_membership_status.id )
LEFT JOIN civicrm_membership_payment payment
ON ( {$this->_aliases['civicrm_membership']}.id = payment.membership_id )
LEFT JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON payment.contribution_id = {$this->_aliases['civicrm_contribution']}.id";
}
public function where() {
$this->_whereClauses[] = "{$this->_aliases['civicrm_membership']}.is_test = 0 AND
{$this->_aliases['civicrm_contact']}.is_deleted = 0";
parent::where();
}
public function groupBy() {
$this->_groupBy = "";
if (is_array($this->_params['group_bys']) &&
!empty($this->_params['group_bys'])
) {
foreach ($this->_columns as $table) {
if (array_key_exists('group_bys', $table)) {
foreach ($table['group_bys'] as $fieldName => $field) {
if (!empty($this->_params['group_bys'][$fieldName])) {
if (!empty($field['chart'])) {
$this->assign('chartSupported', TRUE);
}
if (!empty($table['group_bys'][$fieldName]['frequency']) &&
!empty($this->_params['group_bys_freq'][$fieldName])
) {
$append = "YEAR({$field['dbAlias']})";
if (in_array(strtolower($this->_params['group_bys_freq'][$fieldName]),
array('year')
)) {
$append = '';
}
$this->_groupByArray[] = $append;
$this->_groupByArray[] = "{$this->_params['group_bys_freq'][$fieldName]}({$field['dbAlias']})";
$append = TRUE;
}
else {
$this->_groupByArray[] = $field['dbAlias'];
}
}
}
}
}
$this->_rollup = ' WITH ROLLUP';
$this->_select = CRM_Contact_BAO_Query::appendAnyValueToSelect($this->_selectClauses, array_filter($this->_groupByArray));
$this->_groupBy = 'GROUP BY ' . implode(', ', array_filter($this->_groupByArray)) .
" {$this->_rollup} ";
}
else {
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, "{$this->_aliases['civicrm_membership']}.join_date");
}
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
$select = "
SELECT COUNT({$this->_aliases['civicrm_contribution']}.total_amount ) as count,
IFNULL(SUM({$this->_aliases['civicrm_contribution']}.total_amount ), 0) as amount,
IFNULL(ROUND(AVG({$this->_aliases['civicrm_contribution']}.total_amount), 2),0) as avg,
COUNT( DISTINCT {$this->_aliases['civicrm_membership']}.id ) as memberCount,
{$this->_aliases['civicrm_contribution']}.currency as currency
";
$sql = "{$select} {$this->_from} {$this->_where}
GROUP BY {$this->_aliases['civicrm_contribution']}.currency
";
$dao = CRM_Core_DAO::executeQuery($sql);
$totalAmount = $average = array();
$count = $memberCount = 0;
while ($dao->fetch()) {
$totalAmount[] = CRM_Utils_Money::format($dao->amount, $dao->currency) . "(" . $dao->count . ")";
$average[] = CRM_Utils_Money::format($dao->avg, $dao->currency);
$count += $dao->count;
$memberCount += $dao->memberCount;
}
$statistics['counts']['amount'] = array(
'title' => ts('Total Amount'),
'value' => implode(', ', $totalAmount),
'type' => CRM_Utils_Type::T_STRING,
);
$statistics['counts']['count'] = array(
'title' => ts('Total Contributions'),
'value' => $count,
);
$statistics['counts']['memberCount'] = array(
'title' => ts('Total Members'),
'value' => $memberCount,
);
$statistics['counts']['avg'] = array(
'title' => ts('Average'),
'value' => implode(', ', $average),
'type' => CRM_Utils_Type::T_STRING,
);
if (!(int) $statistics['counts']['amount']['value']) {
//if total amount is zero then hide Chart Options
$this->assign('chartSupported', FALSE);
}
return $statistics;
}
public function postProcess() {
parent::postProcess();
}
/**
* @param $rows
*/
public function buildChart(&$rows) {
$graphRows = array();
$count = 0;
$membershipTypeValues = CRM_Member_PseudoConstant::membershipType();
$isMembershipType = CRM_Utils_Array::value('membership_type_id', $this->_params['group_bys']);
$isJoiningDate = CRM_Utils_Array::value('join_date', $this->_params['group_bys']);
if (!empty($this->_params['charts'])) {
foreach ($rows as $key => $row) {
if (!($row['civicrm_membership_join_date_subtotal'] &&
$row['civicrm_membership_membership_type_id']
)
) {
continue;
}
if ($isMembershipType) {
$join_date = CRM_Utils_Array::value('civicrm_membership_join_date_start', $row);
$displayInterval = CRM_Utils_Array::value('civicrm_membership_join_date_interval', $row);
if ($join_date) {
list($year, $month) = explode('-', $join_date);
}
if (!empty($row['civicrm_membership_join_date_subtotal'])) {
switch ($this->_interval) {
case 'Month':
$displayRange = $displayInterval . ' ' . $year;
break;
case 'Quarter':
$displayRange = 'Quarter ' . $displayInterval . ' of ' . $year;
break;
case 'Week':
$displayRange = 'Week ' . $displayInterval . ' of ' . $year;
break;
case 'Year':
$displayRange = $year;
break;
}
$membershipType = $displayRange . "-" .
$membershipTypeValues[$row['civicrm_membership_membership_type_id']];
}
else {
$membershipType = $membershipTypeValues[$row['civicrm_membership_membership_type_id']];
}
$interval[$membershipType] = $membershipType;
$display[$membershipType] = $row['civicrm_contribution_total_amount_sum'];
}
else {
$graphRows['receive_date'][] = CRM_Utils_Array::value('civicrm_membership_join_date_start', $row);
$graphRows[$this->_interval][] = CRM_Utils_Array::value('civicrm_membership_join_date_interval', $row);
$graphRows['value'][] = $row['civicrm_contribution_total_amount_sum'];
$count++;
}
}
// build chart.
if ($isMembershipType) {
$graphRows['value'] = $display;
$chartInfo = array(
'legend' => 'Membership Summary',
'xname' => 'Member Since / Member Type',
'yname' => 'Fees',
);
CRM_Utils_OpenFlashChart::reportChart($graphRows, $this->_params['charts'], $interval, $chartInfo);
}
else {
CRM_Utils_OpenFlashChart::chart($graphRows, $this->_params['charts'], $this->_interval);
}
}
$this->assign('chartType', $this->_params['charts']);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// make count columns point to detail report
if (!empty($this->_params['group_bys']['join_date']) &&
!empty($row['civicrm_membership_join_date_start']) &&
$row['civicrm_membership_join_date_start'] &&
$row['civicrm_membership_join_date_subtotal']
) {
$dateStart = CRM_Utils_Date::customFormat($row['civicrm_membership_join_date_start'], '%Y%m%d');
$endDate = new DateTime($dateStart);
$dateEnd = array();
list($dateEnd['Y'], $dateEnd['M'], $dateEnd['d']) = explode(':', $endDate->format('Y:m:d'));
switch (strtolower($this->_params['group_bys_freq']['join_date'])) {
case 'month':
$dateEnd = date("Ymd", mktime(0, 0, 0, $dateEnd['M'] + 1,
$dateEnd['d'] - 1, $dateEnd['Y']
));
break;
case 'year':
$dateEnd = date("Ymd", mktime(0, 0, 0, $dateEnd['M'],
$dateEnd['d'] - 1, $dateEnd['Y'] + 1
));
break;
case 'yearweek':
$dateEnd = date("Ymd", mktime(0, 0, 0, $dateEnd['M'],
$dateEnd['d'] + 6, $dateEnd['Y']
));
break;
case 'quarter':
$dateEnd = date("Ymd", mktime(0, 0, 0, $dateEnd['M'] + 3,
$dateEnd['d'] - 1, $dateEnd['Y']
));
break;
}
$typeUrl = '';
if (!empty($this->_params['group_bys']['membership_type_id']) &&
$typeID = $row['civicrm_membership_membership_type_id']
) {
$typeUrl = "&tid_op=in&tid_value={$typeID}";
}
$statusUrl = '';
if (!empty($this->_params['status_id_value'])) {
$statusUrl = "&sid_op=in&sid_value=" .
implode(",", $this->_params['status_id_value']);
}
$url = CRM_Report_Utils_Report::getNextUrl('member/detail',
"reset=1&force=1&join_date_from={$dateStart}&join_date_to={$dateEnd}{$typeUrl}{$statusUrl}",
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$row['civicrm_membership_join_date_start'] = CRM_Utils_Date::format($row['civicrm_membership_join_date_start']);
$rows[$rowNum]['civicrm_membership_join_date_start_link'] = $url;
$rows[$rowNum]['civicrm_membership_join_date_start_hover'] = ts("Lists Summary of Memberships for this date unit.");
$entryFound = TRUE;
}
// handle Membership Types
if (array_key_exists('civicrm_membership_membership_type_id', $row)) {
if ($value = $row['civicrm_membership_membership_type_id']) {
$value = explode(',', $value);
foreach ($value as $key => $id) {
$value[$key] = CRM_Member_PseudoConstant::membershipType($id, FALSE);
}
$rows[$rowNum]['civicrm_membership_membership_type_id'] = implode(' , ', $value);
}
$entryFound = TRUE;
}
// make subtotals look nicer
if (array_key_exists('civicrm_membership_join_date_subtotal', $row) &&
!$row['civicrm_membership_join_date_subtotal']
) {
$this->fixSubTotalDisplay($rows[$rowNum], $this->_statFields);
$entryFound = TRUE;
}
elseif (array_key_exists('civicrm_membership_join_date_subtotal', $row) &&
$row['civicrm_membership_join_date_subtotal'] &&
!$row['civicrm_membership_membership_type_id']
) {
$this->fixSubTotalDisplay($rows[$rowNum], $this->_statFields, FALSE);
$rows[$rowNum]['civicrm_membership_membership_type_id'] = '<b>' . ts('Subtotal') . '</b>';
$entryFound = TRUE;
}
// If using campaigns, convert campaign_id to campaign title
if (array_key_exists('civicrm_membership_campaign_id', $row)) {
if ($value = $row['civicrm_membership_campaign_id']) {
$rows[$rowNum]['civicrm_membership_campaign_id'] = $this->activeCampaigns[$value];
}
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,443 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Membership_Summary extends CRM_Report_Form {
protected $_summary = NULL;
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
/**
* Constructor function.
*/
public function __construct() {
// UI for selecting columns to appear in the report list
// array containing the columns, group_bys and filters build and provided to Form
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Member Name'),
'no_repeat' => TRUE,
'required' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'group_bys' => array(
'id' => array('title' => ts('Contact ID')),
'display_name' => array(
'title' => ts('Contact Name'),
),
),
'grouping' => 'contact-fields',
),
'civicrm_membership_type' => array(
'dao' => 'CRM_Member_DAO_MembershipType',
'grouping' => 'member-fields',
'filters' => array(
'gid' => array(
'name' => 'id',
'title' => ts('Membership Types'),
'type' => CRM_Utils_Type::T_INT + CRM_Utils_Type::T_ENUM,
'options' => CRM_Member_PseudoConstant::membershipType(),
),
),
),
'civicrm_membership' => array(
'dao' => 'CRM_Member_DAO_Membership',
'grouping' => 'member-fields',
'fields' => array(
'membership_type_id' => array(
'title' => ts('Membership Type'),
'required' => TRUE,
),
'join_date' => NULL,
'start_date' => array(
'title' => ts('Current Cycle Start Date'),
),
'end_date' => array(
'title' => ts('Current Cycle End Date'),
),
),
'group_bys' => array(
'membership_type_id' => array('title' => ts('Membership Type')),
),
'filters' => array(
'join_date' => array('type' => CRM_Utils_Type::T_DATE),
),
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'fields' => array(
'street_address' => NULL,
'city' => NULL,
'postal_code' => NULL,
'state_province_id' => array(
'title' => ts('State/Province'),
),
'country_id' => array(
'title' => ts('Country'),
'default' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array('email' => NULL),
'grouping' => 'contact-fields',
),
'civicrm_contribution' => array(
'dao' => 'CRM_Contribute_DAO_Contribution',
'filters' => array(
'total_amount' => array(
'title' => ts('Contribution Amount'),
),
),
),
);
parent::__construct();
}
/**
* Pre-process function.
*/
public function preProcess() {
$this->assign('reportTitle', ts('Membership Summary Report'));
parent::preProcess();
}
/**
* Generate select clause.
*/
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
// to include optional columns address and email, only if checked
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
$this->_emailField = TRUE;
}
elseif ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = $field['type'];
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
}
}
}
}
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
/**
* Generate from clause.
*/
public function from() {
$this->_from = NULL;
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']}
INNER JOIN civicrm_membership {$this->_aliases['civicrm_membership']}
ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_membership']}.contact_id
LEFT JOIN civicrm_membership_type {$this->_aliases['civicrm_membership_type']}
ON {$this->_aliases['civicrm_membership']}.membership_type_id = {$this->_aliases['civicrm_membership_type']}.id
LEFT JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
ON {$this->_aliases['civicrm_membership']}.contact_id = {$this->_aliases['civicrm_contribution']}.contact_id
";
// Include address table if address column is to be included.
if ($this->_addressField) {
$this->_from .= "LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']} ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND {$this->_aliases['civicrm_address']}.is_primary = 1\n";
}
// Include email table if email column is to be included.
if ($this->_emailField) {
$this->_from .= "LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']} ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND {$this->_aliases['civicrm_email']}.is_primary = 1\n";
}
}
/**
* Generate where clause.
*
* @todo this looks like it duplicates the parent & could go.
*/
public function where() {
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if ($field['type'] & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($relative || $from || $to) {
$clause = $this->dateClause($field['name'], $relative, $from, $to);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE ( 1 ) ";
}
else {
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
}
/**
* Generate statistics (bottom section of the report).
*
* @param array $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = array();
$statistics[] = array(
'title' => ts('Row(s) Listed'),
'value' => count($rows),
);
return $statistics;
}
/**
* Generate group by clause.
*
* @todo looks like a broken duplicate of the parent.
*/
public function groupBy() {
$this->_groupBy = "";
if (is_array($this->_params['group_bys']) &&
!empty($this->_params['group_bys'])
) {
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('group_bys', $table)) {
foreach ($table['group_bys'] as $fieldName => $field) {
if (!empty($this->_params['group_bys'][$fieldName])) {
$this->_groupBy[] = $field['dbAlias'];
}
}
}
}
if (!empty($this->_statFields) &&
(($append && count($this->_groupBy) <= 1) || (!$append))
) {
$this->_rollup = " WITH ROLLUP";
}
$this->_groupBy = "GROUP BY " . implode(', ', $this->_groupBy) .
" {$this->_rollup} ";
}
else {
$this->_groupBy = "GROUP BY contact.id";
}
}
/**
* PostProcess function.
*/
public function postProcess() {
$this->_params = $this->controller->exportValues($this->_name);
if (empty($this->_params) &&
$this->_force
) {
$this->_params = $this->_formValues;
}
$this->_formValues = $this->_params;
$this->processReportMode();
$this->select();
$this->from();
$this->where();
$this->groupBy();
$sql = "{$this->_select} {$this->_from} {$this->_where} {$this->_groupBy}";
$dao = CRM_Core_DAO::executeQuery($sql);
$rows = $graphRows = array();
$count = 0;
while ($dao->fetch()) {
$row = array();
foreach ($this->_columnHeaders as $key => $value) {
$row[$key] = $dao->$key;
}
if (!empty($this->_params['charts']) &&
$row['civicrm_contribution_receive_date_subtotal']
) {
$graphRows['receive_date'][] = $row['civicrm_contribution_receive_date_start'];
$graphRows[$this->_interval][] = $row['civicrm_contribution_receive_date_interval'];
$graphRows['value'][] = $row['civicrm_contribution_total_amount_sum'];
$count++;
}
$rows[] = $row;
}
$this->formatDisplay($rows);
$this->assign_by_ref('columnHeaders', $this->_columnHeaders);
$this->assign_by_ref('rows', $rows);
$this->assign('statistics', $this->statistics($rows));
if (!empty($this->_params['charts'])) {
foreach (array(
'receive_date',
$this->_interval,
'value',
) as $ignore) {
unset($graphRows[$ignore][$count - 1]);
}
// build chart.
CRM_Utils_OpenFlashChart::chart($graphRows, $this->_params['charts'], $this->_interval);
}
parent::endPostProcess();
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$checkList = array();
foreach ($rows as $rowNum => $row) {
if (!empty($this->_noRepeats)) {
// not repeat contact display names if it matches with the one
// in previous row
$repeatFound = FALSE;
foreach ($row as $colName => $colVal) {
if (is_array($checkList[$colName]) &&
in_array($colVal, $checkList[$colName])
) {
$rows[$rowNum][$colName] = "";
$repeatFound = TRUE;
}
if (in_array($colName, $this->_noRepeats)) {
$checkList[$colName][] = $colVal;
}
}
}
//handle the Membership Type Ids
if (array_key_exists('civicrm_membership_membership_type_id', $row)) {
if ($value = $row['civicrm_membership_membership_type_id']) {
$rows[$rowNum]['civicrm_membership_membership_type_id'] = CRM_Member_PseudoConstant::membershipType($value, FALSE);
}
$entryFound = TRUE;
}
// handle state province
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($value, FALSE);
}
$entryFound = TRUE;
}
// handle country
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url(
'civicrm/report/member/detail',
'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name']
= "<a href='$url'>" . $row["civicrm_contact_sort_name"] . '</a>';
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,624 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/*
* !!!!!!!!!!!!!!!!!!!!
* NB: this is named detail but behaves like a summary report.
* It is also accessed through the Pledge Summary link in the UI
* This should presumably be changed.
* ~ Doten
* !!!!!!!!!!!!!!!!!!!!
*
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Pledge_Detail extends CRM_Report_Form {
protected $_summary = NULL;
protected $_totalPaid = FALSE;
protected $_pledgeStatuses = array();
protected $_customGroupExtends = array(
'Pledge',
'Individual',
);
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_pledgeStatuses = CRM_Core_OptionGroup::values('pledge_status',
FALSE, FALSE, FALSE, NULL, 'label'
);
// Check if CiviCampaign is a) enabled and b) has active campaigns
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
),
'filters' => array(
'sort_name' => array('title' => ts('Contact Name')),
'id' => array('no_display' => TRUE),
),
'grouping' => 'contact-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array('no_repeat' => TRUE),
),
'grouping' => 'contact-fields',
),
'civicrm_pledge' => array(
'dao' => 'CRM_Pledge_DAO_Pledge',
'fields' => array(
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'contact_id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
),
'amount' => array(
'title' => ts('Pledge Amount'),
'required' => TRUE,
'type' => CRM_Utils_Type::T_MONEY,
),
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'frequency_unit' => array(
'title' => ts('Frequency Unit'),
),
'installments' => array(
'title' => ts('Installments'),
),
'pledge_create_date' => array(
'title' => ts('Pledge Made Date'),
),
'start_date' => array(
'title' => ts('Pledge Start Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'end_date' => array(
'title' => ts('Pledge End Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'status_id' => array(
'title' => ts('Pledge Status'),
'required' => TRUE,
),
),
'filters' => array(
'pledge_create_date' => array(
'title' => ts('Pledge Made Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'pledge_amount' => array(
'title' => ts('Pledged Amount'),
'operatorType' => CRM_Report_Form::OP_INT,
),
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'sid' => array(
'name' => 'status_id',
'title' => ts('Pledge Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('pledge_status'),
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialType(),
),
),
),
'civicrm_pledge_payment' => array(
'dao' => 'CRM_Pledge_DAO_PledgePayment',
'fields' => array(
'total_paid' => array(
'title' => ts('Total Amount Paid'),
'type' => CRM_Utils_Type::T_MONEY,
),
'balance_due' => array(
'title' => ts('Balance Due'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_MONEY,
),
),
),
);
$this->_columns += $this->getAddressColumns(array('group_by' => FALSE)) + $this->getPhoneColumns();
// If we have a campaign, build out the relevant elements
$this->_tagFilter = TRUE;
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_pledge']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
);
$this->_columns['civicrm_pledge']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
$this->_columns['civicrm_pledge']['group_bys']['campaign_id'] = array('title' => ts('Campaign'));
}
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
$this->_currencyColumn = 'civicrm_pledge_currency';
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
parent::select();
}
/**
* If we are retrieving total paid we need to define the inclusion of pledge_payment.
*
* @param string $tableName
* @param $tableKey
* @param string $fieldName
* @param $field
*
* @return bool|string
*/
public function selectClause(&$tableName, $tableKey, &$fieldName, &$field) {
if ($fieldName == 'total_paid') {
$this->_totalPaid = TRUE; // add pledge_payment join
$this->_columnHeaders["{$tableName}_{$fieldName}"] = array(
'title' => $field['title'],
'type' => $field['type'],
);
return "COALESCE(sum({$this->_aliases[$tableName]}.actual_amount), 0) as {$tableName}_{$fieldName}";
}
if ($fieldName == 'balance_due') {
$cancelledStatus = array_search('Cancelled', $this->_pledgeStatuses);
$completedStatus = array_search('Completed', $this->_pledgeStatuses);
$this->_totalPaid = TRUE; // add pledge_payment join
$this->_columnHeaders["{$tableName}_{$fieldName}"] = $field['title'];
$this->_columnHeaders["{$tableName}_{$fieldName}"] = array(
'title' => $field['title'],
'type' => $field['type'],
);
return "IF({$this->_aliases['civicrm_pledge']}.status_id IN({$cancelledStatus}, $completedStatus), 0, COALESCE({$this->_aliases['civicrm_pledge']}.amount, 0) - COALESCE(sum({$this->_aliases[$tableName]}.actual_amount),0)) as {$tableName}_{$fieldName}";
}
return FALSE;
}
public function groupBy() {
parent::groupBy();
if (empty($this->_groupBy) && $this->_totalPaid) {
$groupBy = array("{$this->_aliases['civicrm_pledge']}.id", "{$this->_aliases['civicrm_pledge']}.currency");
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
}
public function from() {
$this->_from = "
FROM civicrm_pledge {$this->_aliases['civicrm_pledge']}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON ({$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_pledge']}.contact_id )
{$this->_aclFrom} ";
if ($this->_totalPaid) {
$this->_from .= "
LEFT JOIN civicrm_pledge_payment {$this->_aliases['civicrm_pledge_payment']} ON
{$this->_aliases['civicrm_pledge']}.id = {$this->_aliases['civicrm_pledge_payment']}.pledge_id
AND {$this->_aliases['civicrm_pledge_payment']}.status_id = 1
";
}
$this->addPhoneFromClause();
$this->addAddressFromClause();
// include email field if email column is to be included
if ($this->_emailField) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ({$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_email']}.contact_id) AND
{$this->_aliases['civicrm_email']}.is_primary = 1\n";
}
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
//regenerate the from field without extra left join on pledge payments
$totalPaid = $this->_totalPaid;
$this->_totalPaid = FALSE;
$this->from();
$this->customDataFrom();
if (!$this->_having) {
$totalAmount = $average = array();
$count = 0;
$select = "
SELECT COUNT({$this->_aliases['civicrm_pledge']}.amount ) as count,
SUM({$this->_aliases['civicrm_pledge']}.amount ) as amount,
ROUND(AVG({$this->_aliases['civicrm_pledge']}.amount), 2) as avg,
{$this->_aliases['civicrm_pledge']}.currency as currency
";
$group = "GROUP BY {$this->_aliases['civicrm_pledge']}.currency";
$sql = "{$select} {$this->_from} {$this->_where} {$group}";
$dao = CRM_Core_DAO::executeQuery($sql);
$count = $index = $totalCount = 0;
// this will run once per currency
while ($dao->fetch()) {
$totalAmount = CRM_Utils_Money::format($dao->amount, $dao->currency);
$average = CRM_Utils_Money::format($dao->avg, $dao->currency);
$count = $dao->count;
$totalCount .= $count;
$statistics['counts']['amount' . $index] = array(
'title' => ts('Total Pledged') . ' (' . $dao->currency . ')',
'value' => $totalAmount,
'type' => CRM_Utils_Type::T_STRING,
);
$statistics['counts']['avg' . $index] = array(
'title' => ts('Average') . ' (' . $dao->currency . ')',
'value' => $average,
'type' => CRM_Utils_Type::T_STRING,
);
$statistics['counts']['count' . $index] = array(
'title' => ts('Total No Pledges') . ' (' . $dao->currency . ')',
'value' => $count,
'type' => CRM_Utils_Type::T_INT,
);
$index++;
}
if ($totalCount > $count) {
$statistics['counts']['count' . $index] = array(
'title' => ts('Total No Pledges'),
'value' => $totalCount,
'type' => CRM_Utils_Type::T_INT,
);
}
}
// reset from clause
if ($totalPaid) {
$this->_totalPaid = TRUE;
$this->from();
}
return $statistics;
}
public function orderBy() {
$this->_orderBy = "ORDER BY {$this->_aliases['civicrm_contact']}.sort_name, {$this->_aliases['civicrm_contact']}.id";
}
public function where() {
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($relative || $from || $to) {
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value",
$this->_params
),
CRM_Utils_Array::value("{$fieldName}_min",
$this->_params
),
CRM_Utils_Array::value("{$fieldName}_max",
$this->_params
)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE ({$this->_aliases['civicrm_pledge']}.is_test=0 ) ";
}
else {
$this->_where = "WHERE ({$this->_aliases['civicrm_pledge']}.is_test=0 ) AND
" . implode(' AND ', $clauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
public function postProcess() {
$this->beginPostProcess();
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
$sql = $this->buildQuery();
$rows = $payment = array();
$dao = CRM_Core_DAO::executeQuery($sql);
// Set pager for the Main Query only which displays basic information
$this->setPager();
$this->assign('columnHeaders', $this->_columnHeaders);
while ($dao->fetch()) {
$pledgeID = $dao->civicrm_pledge_id;
foreach ($this->_columnHeaders as $columnHeadersKey => $columnHeadersValue) {
$row = array();
if (property_exists($dao, $columnHeadersKey)) {
$display[$pledgeID][$columnHeadersKey] = $dao->$columnHeadersKey;
}
}
$pledgeIDArray[] = $pledgeID;
}
// Add Special headers
$this->_columnHeaders['scheduled_date'] = array(
'type' => CRM_Utils_Type::T_DATE,
'title' => ts('Next Payment Due'),
);
$this->_columnHeaders['scheduled_amount'] = array(
'type' => CRM_Utils_Type::T_MONEY,
'title' => ts('Next Payment Amount'),
);
$this->_columnHeaders['status_id'] = NULL;
/*
* this is purely about ordering the total paid & balance due fields off to the end
* of the table in case custom or address fields cause them to fall in the middle
* (arguably the pledge amount should be moved to after these fields too)
*
*/
$tableHeaders = array(
'civicrm_pledge_payment_total_paid',
'civicrm_pledge_payment_balance_due',
);
foreach ($tableHeaders as $header) {
//per above, unset & reset them so they move to the end
if (isset($this->_columnHeaders[$header])) {
$headervalue = $this->_columnHeaders[$header];
unset($this->_columnHeaders[$header]);
$this->_columnHeaders[$header] = $headervalue;
}
}
// To Display Payment Details of pledged amount
// for pledge payments In Progress
if (!empty($display)) {
$statusId = array_keys(CRM_Core_PseudoConstant::accountOptionValues("contribution_status", NULL, " AND v.name IN ('Pending', 'Overdue')"));
$statusId = implode(',', $statusId);
$select = "payment.pledge_id, payment.scheduled_amount, pledge.contact_id";
$sqlPayment = "
SELECT min(payment.scheduled_date) as scheduled_date,
{$select}
FROM civicrm_pledge_payment payment
LEFT JOIN civicrm_pledge pledge
ON pledge.id = payment.pledge_id
WHERE payment.status_id IN ({$statusId})
GROUP BY {$select}";
$daoPayment = CRM_Core_DAO::executeQuery($sqlPayment);
while ($daoPayment->fetch()) {
foreach ($pledgeIDArray as $key => $val) {
if ($val == $daoPayment->pledge_id) {
$display[$daoPayment->pledge_id]['scheduled_date'] = $daoPayment->scheduled_date;
$display[$daoPayment->pledge_id]['scheduled_amount'] = $daoPayment->scheduled_amount;
}
}
}
}
// Displaying entire data on the form
if (!empty($display)) {
foreach ($display as $key => $value) {
$row = array();
foreach ($this->_columnHeaders as $columnKey => $columnValue) {
if (array_key_exists($columnKey, $value)) {
$row[$columnKey] = !empty($value[$columnKey]) ? $value[$columnKey] : '';
}
}
$rows[] = $row;
}
}
unset($this->_columnHeaders['status_id']);
unset($this->_columnHeaders['civicrm_pledge_id']);
unset($this->_columnHeaders['civicrm_pledge_contact_id']);
$this->formatDisplay($rows, FALSE);
$this->doTemplateAssignment($rows);
$this->endPostProcess($rows);
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$checkList = array();
$display_flag = $prev_cid = $cid = 0;
foreach ($rows as $rowNum => $row) {
if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
// don't repeat contact details if its same as the previous row
if (array_key_exists('civicrm_pledge_contact_id', $row)) {
if ($cid = $row['civicrm_pledge_contact_id']) {
if ($rowNum == 0) {
$prev_cid = $cid;
}
else {
if ($prev_cid == $cid) {
$display_flag = 1;
$prev_cid = $cid;
}
else {
$display_flag = 0;
$prev_cid = $cid;
}
}
if ($display_flag) {
foreach ($row as $colName => $colVal) {
if (in_array($colName, $this->_noRepeats)) {
unset($rows[$rowNum][$colName]);
}
}
}
$entryFound = TRUE;
}
}
}
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_pledge_contact_id', $row)
) {
$url = CRM_Utils_System::url("civicrm/contact/view",
'reset=1&cid=' . $row['civicrm_pledge_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact Summary for this Contact.");
$entryFound = TRUE;
}
if (array_key_exists('civicrm_pledge_financial_type_id', $row)) {
if ($value = $row['civicrm_pledge_financial_type_id']) {
$rows[$rowNum]['civicrm_pledge_financial_type_id'] = CRM_Contribute_PseudoConstant::financialType($value, FALSE);
}
$entryFound = TRUE;
}
//handle status id
if (array_key_exists('civicrm_pledge_status_id', $row)) {
if ($value = $row['civicrm_pledge_status_id']) {
$rows[$rowNum]['civicrm_pledge_status_id'] = CRM_Core_PseudoConstant::getLabel('CRM_Pledge_BAO_Pledge', 'status_id', $value);
}
$entryFound = TRUE;
}
// If using campaigns, convert campaign_id to campaign title
if (array_key_exists('civicrm_pledge_campaign_id', $row)) {
if ($value = $row['civicrm_pledge_campaign_id']) {
$rows[$rowNum]['civicrm_pledge_campaign_id'] = $this->activeCampaigns[$value];
}
$entryFound = TRUE;
}
$entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'pledge/detail', 'List all pledge(s) for this ') ? TRUE : $entryFound;
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,426 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Pledge_Pbnp extends CRM_Report_Form {
protected $_charts = array(
'' => 'Tabular',
'barChart' => 'Bar Chart',
'pieChart' => 'Pie Chart',
);
public $_drilldownReport = array('pledge/summary' => 'Link to Detail Report');
protected $_customGroupExtends = array(
'Pledge',
);
/**
* Class constructor.
*/
public function __construct() {
// Check if CiviCampaign is a) enabled and b) has active campaigns
$config = CRM_Core_Config::singleton();
$campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
if ($campaignEnabled) {
$getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
$this->activeCampaigns = $getCampaigns['campaigns'];
asort($this->activeCampaigns);
}
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Constituent Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_pledge' => array(
'dao' => 'CRM_Pledge_DAO_Pledge',
'fields' => array(
'pledge_create_date' => array(
'title' => ts('Pledge Made'),
'required' => TRUE,
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'required' => TRUE,
),
'frequency_unit' => array(
'title' => ts('Frequency Unit'),
),
'installments' => array(
'title' => ts('Installments'),
),
'amount' => array(
'title' => ts('Amount'),
'required' => TRUE,
'type' => CRM_Utils_Type::T_MONEY,
),
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'status_id' => array(
'title' => ts('Status'),
),
),
'filters' => array(
'pledge_create_date' => array(
'title' => ts('Pledge Made'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'pledge_amount' => array(
'title' => ts('Pledged Amount'),
'operatorType' => CRM_Report_Form::OP_INT,
),
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialType(),
),
'pledge_status_id' => array(
'name' => 'status_id',
'title' => ts('Pledge Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('pledge_status'),
),
'installments' => array(
'title' => ts('Installments'),
'type' => CRM_Utils_Type::T_INT,
),
),
'grouping' => 'pledge-fields',
),
'civicrm_pledge_payment' => array(
'dao' => 'CRM_Pledge_DAO_PledgePayment',
'fields' => array(
'scheduled_date' => array(
'title' => ts('Next Payment Due'),
'type' => CRM_Utils_Type::T_DATE,
'required' => TRUE,
),
'scheduled_amount' => array(
'type' => CRM_Utils_Type::T_MONEY,
'title' => ts('Next Payment Amount'),
),
),
'filters' => array(
'scheduled_date' => array(
'title' => ts('Next Payment Due'),
'operatorType' => CRM_Report_Form::OP_DATE,
'type' => CRM_Utils_Type::T_DATE,
),
),
'grouping' => 'pledge-fields',
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'fields' => array(
'street_address' => NULL,
'city' => NULL,
'postal_code' => NULL,
'state_province_id' => array(
'title' => ts('State/Province'),
),
'country_id' => array(
'title' => ts('Country'),
'default' => TRUE,
),
),
'grouping' => 'contact-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array('email' => NULL),
'grouping' => 'contact-fields',
),
'civicrm_group' => array(
'dao' => 'CRM_Contact_DAO_Group',
'alias' => 'cgroup',
'filters' => array(
'gid' => array(
'name' => 'group_id',
'title' => ts('Group'),
'type' => CRM_Utils_Type::T_INT,
'group' => TRUE,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_PseudoConstant::staticGroup(),
),
),
),
);
// If we have a campaign, build out the relevant elements
if ($campaignEnabled && !empty($this->activeCampaigns)) {
$this->_columns['civicrm_pledge']['fields']['campaign_id'] = array(
'title' => ts('Campaign'),
'default' => 'false',
);
$this->_columns['civicrm_pledge']['filters']['campaign_id'] = array(
'title' => ts('Campaign'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => $this->activeCampaigns,
'type' => CRM_Utils_Type::T_INT,
);
}
$this->_tagFilter = TRUE;
$this->_currencyColumn = 'civicrm_pledge_currency';
parent::__construct();
}
public function preProcess() {
$this->assign('reportTitle', ts('Pledged but not Paid Report'));
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('fields', $table)) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
// to include optional columns address and email, only if checked
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
$this->_emailField = TRUE;
}
elseif ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = CRM_Utils_Array::value('type', $field);
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = CRM_Utils_Array::value('title', $field);
}
}
}
}
$this->_selectClauses = $select;
$this->_select = "SELECT " . implode(', ', $select) . " ";
}
public function from() {
$this->_from = NULL;
$allStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');
$pendingStatus = array_search('Pending', $allStatus);
foreach (array(
'Pending',
'In Progress',
'Overdue',
) as $statusKey) {
if ($key = CRM_Utils_Array::key($statusKey, $allStatus)) {
$unpaidStatus[] = $key;
}
}
$statusIds = implode(', ', $unpaidStatus);
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}
INNER JOIN civicrm_pledge {$this->_aliases['civicrm_pledge']}
ON ({$this->_aliases['civicrm_pledge']}.contact_id =
{$this->_aliases['civicrm_contact']}.id) AND
{$this->_aliases['civicrm_pledge']}.status_id IN ( {$statusIds} )\n";
// Note that the derived query protects us from providing inaccurate data in the edge case where pledge
// payments have been edited such that they are not in id order. This might be better as a temp table.
$this->_from .= "LEFT JOIN (SELECT * FROM civicrm_pledge_payment ORDER BY scheduled_date) as {$this->_aliases['civicrm_pledge_payment']}
ON ({$this->_aliases['civicrm_pledge']}.id =
{$this->_aliases['civicrm_pledge_payment']}.pledge_id AND {$this->_aliases['civicrm_pledge_payment']}.status_id = {$pendingStatus} ) ";
// include address field if address column is to be included
if ($this->_addressField) {
$this->_from .= "
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON ({$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_address']}.contact_id) AND
{$this->_aliases['civicrm_address']}.is_primary = 1\n";
}
// include email field if email column is to be included
if ($this->_emailField) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ({$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_email']}.contact_id) AND
{$this->_aliases['civicrm_email']}.is_primary = 1\n";
}
}
public function groupBy() {
$groupBy = array(
"{$this->_aliases['civicrm_pledge']}.contact_id",
"{$this->_aliases['civicrm_pledge']}.id",
"{$this->_aliases['civicrm_pledge']}.currency",
);
$this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, $groupBy);
}
public function orderBy() {
$this->_orderBy = "ORDER BY {$this->_aliases['civicrm_contact']}.sort_name, {$this->_aliases['civicrm_pledge']}.contact_id, {$this->_aliases['civicrm_pledge']}.id";
}
public function postProcess() {
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
parent::PostProcess();
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$checkList = array();
$display_flag = $prev_cid = $cid = 0;
foreach ($rows as $rowNum => $row) {
if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
// don't repeat contact details if its same as the previous row
if (array_key_exists('civicrm_contact_id', $row)) {
if ($cid = $row['civicrm_contact_id']) {
if ($rowNum == 0) {
$prev_cid = $cid;
}
else {
if ($prev_cid == $cid) {
$display_flag = 1;
$prev_cid = $cid;
}
else {
$display_flag = 0;
$prev_cid = $cid;
}
}
if ($display_flag) {
foreach ($row as $colName => $colVal) {
if (in_array($colName, $this->_noRepeats)) {
unset($rows[$rowNum][$colName]);
}
}
}
$entryFound = TRUE;
}
}
}
//handle the Financial Type Ids
if (array_key_exists('civicrm_pledge_financial_type_id', $row)) {
if ($value = $row['civicrm_pledge_financial_type_id']) {
$rows[$rowNum]['civicrm_pledge_financial_type_id'] = CRM_Contribute_PseudoConstant::financialType($value, FALSE);
}
$entryFound = TRUE;
}
//handle the Status Ids
if (array_key_exists('civicrm_pledge_status_id', $row)) {
if ($value = $row['civicrm_pledge_status_id']) {
$rows[$rowNum]['civicrm_pledge_status_id'] = CRM_Core_PseudoConstant::getLabel('CRM_Pledge_BAO_Pledge', 'status_id', $value);
}
$entryFound = TRUE;
}
// handle state province
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($value, FALSE);
}
$entryFound = TRUE;
}
// handle country
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
}
$entryFound = TRUE;
}
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('pledge/summary',
'reset=1&force=1&id_op=eq&id_value=' .
$row['civicrm_contact_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Pledge Details for this contact");
$entryFound = TRUE;
}
// If using campaigns, convert campaign_id to campaign title
if (array_key_exists('civicrm_pledge_campaign_id', $row)) {
if ($value = $row['civicrm_pledge_campaign_id']) {
$rows[$rowNum]['civicrm_pledge_campaign_id'] = $this->activeCampaigns[$value];
}
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,447 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Pledge_Summary extends CRM_Report_Form {
protected $_summary = NULL;
protected $_totalPaid = FALSE;
protected $_customGroupExtends = array('Pledge', 'Individual');
protected $_customGroupGroupBy = TRUE;
protected $_addressField = FALSE;
protected $_emailField = FALSE;
/**
* This report has not been optimised for group filtering.
*
* The functionality for group filtering has been improved but not
* all reports have been adjusted to take care of it. This report has not
* and will run an inefficient query until fixed.
*
* CRM-19170
*
* @var bool
*/
protected $groupFilterNotOptimised = TRUE;
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'no_repeat' => TRUE,
),
'postal_greeting_display' => array('title' => ts('Postal Greeting')),
'id' => array(
'no_display' => TRUE,
'required' => TRUE,
),
),
'grouping' => 'contact-fields',
'group_bys' => array(
'id' => array('title' => ts('Contact ID')),
'sort_name' => array(
'title' => ts('Contact Name'),
),
),
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array(
'email' => array(
'no_repeat' => TRUE,
'title' => ts('email'),
),
),
'grouping' => 'contact-fields',
),
'civicrm_pledge' => array(
'dao' => 'CRM_Pledge_DAO_Pledge',
'fields' => array(
'id' => array(
'no_display' => TRUE,
'required' => FALSE,
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
),
'currency' => array(
'required' => TRUE,
'no_display' => TRUE,
),
'amount' => array(
'title' => ts('Pledge Amount'),
'required' => TRUE,
'type' => CRM_Utils_Type::T_MONEY,
'statistics' => array(
'sum' => ts('Aggregate Amount Pledged'),
'count' => ts('Pledges'),
'avg' => ts('Average'),
),
),
'frequency_unit' => array(
'title' => ts('Frequency Unit'),
),
'installments' => array(
'title' => ts('Installments'),
),
'pledge_create_date' => array(
'title' => ts('Pledge Made Date'),
),
'start_date' => array(
'title' => ts('Pledge Start Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'end_date' => array(
'title' => ts('Pledge End Date'),
'type' => CRM_Utils_Type::T_DATE,
),
'status_id' => array(
'title' => ts('Pledge Status'),
),
),
'filters' => array(
'pledge_create_date' => array(
'title' => ts('Pledge Made Date'),
'operatorType' => CRM_Report_Form::OP_DATE,
),
'pledge_amount' => array(
'title' => ts('Pledged Amount'),
'operatorType' => CRM_Report_Form::OP_INT,
),
'currency' => array(
'title' => ts('Currency'),
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
'default' => NULL,
'type' => CRM_Utils_Type::T_STRING,
),
'sid' => array(
'name' => 'status_id',
'title' => ts('Pledge Status'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Core_OptionGroup::values('pledge_status'),
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
'type' => CRM_Utils_Type::T_INT,
'operatorType' => CRM_Report_Form::OP_MULTISELECT,
'options' => CRM_Contribute_PseudoConstant::financialType(),
),
),
'group_bys' => array(
'pledge_create_date' => array(
'frequency' => TRUE,
'default' => TRUE,
'chart' => TRUE,
),
'frequency_unit' => array(
'title' => ts('Frequency Unit'),
),
'status_id' => array(
'title' => ts('Pledge Status'),
),
'financial_type_id' => array(
'title' => ts('Financial Type'),
),
),
),
'civicrm_pledge_payment' => array(
'dao' => 'CRM_Pledge_DAO_PledgePayment',
'fields' => array(
'total_paid' => array(
'title' => ts('Total Amount Paid'),
'type' => CRM_Utils_Type::T_STRING,
'dbAlias' => 'sum(pledge_payment_civireport.actual_amount)',
),
),
),
) + $this->addAddressFields();
$this->_groupFilter = TRUE;
$this->_tagFilter = TRUE;
$this->_currencyColumn = 'civicrm_pledge_currency';
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
parent::select();
}
public function from() {
$this->_from = "
FROM civicrm_pledge {$this->_aliases['civicrm_pledge']}
LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
ON ({$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_pledge']}.contact_id )
{$this->_aclFrom} ";
// include address field if address column is to be included
if ($this->_addressField) {
$this->_from .= "
LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']}
ON ({$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_address']}.contact_id) AND
{$this->_aliases['civicrm_address']}.is_primary = 1\n";
}
// include email field if email column is to be included
if ($this->_emailField) {
$this->_from .= "
LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']}
ON ({$this->_aliases['civicrm_contact']}.id =
{$this->_aliases['civicrm_email']}.contact_id) AND
{$this->_aliases['civicrm_email']}.is_primary = 1\n";
}
if (!empty($this->_params['fields']['total_paid'])) {
$this->_from .= "
LEFT JOIN civicrm_pledge_payment {$this->_aliases['civicrm_pledge_payment']} ON
{$this->_aliases['civicrm_pledge']}.id = {$this->_aliases['civicrm_pledge_payment']}.pledge_id
AND {$this->_aliases['civicrm_pledge_payment']}.status_id = 1
";
}
}
public function groupBy() {
$this->_groupBy = "";
$append = FALSE;
if (is_array($this->_params['group_bys']) &&
!empty($this->_params['group_bys'])
) {
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('group_bys', $table)) {
foreach ($table['group_bys'] as $fieldName => $field) {
if (!empty($this->_params['group_bys'][$fieldName])) {
if (!empty($field['chart'])) {
$this->assign('chartSupported', TRUE);
}
if (!empty($table['group_bys'][$fieldName]['frequency']) &&
!empty($this->_params['group_bys_freq'][$fieldName])
) {
$append = "YEAR({$field['dbAlias']}),";
if (in_array(strtolower($this->_params['group_bys_freq'][$fieldName]),
array('year')
)) {
$append = '';
}
$this->_groupByArray[] = "$append {$this->_params['group_bys_freq'][$fieldName]}({$field['dbAlias']})";
$append = TRUE;
}
else {
$this->_groupByArray[] = $field['dbAlias'];
}
}
}
}
}
if (!empty($this->_statFields) &&
(($append && count($this->_groupByArray) <= 1) || (!$append)) &&
!$this->_having
) {
$this->_rollup = " WITH ROLLUP";
}
$groupBy = $this->_groupByArray;
$this->_groupBy = "GROUP BY " . implode(', ', $this->_groupByArray);
}
else {
$groupBy = "{$this->_aliases['civicrm_contact']}.id";
$this->_groupBy = "GROUP BY {$groupBy}";
}
$this->_select = CRM_Contact_BAO_Query::appendAnyValueToSelect($this->_selectClauses, $groupBy);
$this->_groupBy .= " {$this->_rollup}";
}
/**
* @param $rows
*
* @return array
*/
public function statistics(&$rows) {
$statistics = parent::statistics($rows);
if (!$this->_having) {
$select = "
SELECT COUNT({$this->_aliases['civicrm_pledge']}.amount ) as count,
SUM({$this->_aliases['civicrm_pledge']}.amount ) as amount,
ROUND(AVG({$this->_aliases['civicrm_pledge']}.amount), 2) as avg
";
$sql = "{$select} {$this->_from} {$this->_where}";
$dao = CRM_Core_DAO::executeQuery($sql);
if ($dao->fetch()) {
$statistics['count']['amount'] = array(
'value' => $dao->amount,
'title' => ts('Total Pledged'),
'type' => CRM_Utils_Type::T_MONEY,
);
$statistics['count']['count '] = array(
'value' => $dao->count,
'title' => ts('Total No Pledges'),
);
$statistics['count']['avg '] = array(
'value' => $dao->avg,
'title' => ts('Average'),
'type' => CRM_Utils_Type::T_MONEY,
);
}
}
return $statistics;
}
public function where() {
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
if ($relative || $from || $to) {
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value",
$this->_params
),
CRM_Utils_Array::value("{$fieldName}_min",
$this->_params
),
CRM_Utils_Array::value("{$fieldName}_max",
$this->_params
)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE ({$this->_aliases['civicrm_pledge']}.is_test=0 ) ";
}
else {
$this->_where = "WHERE ({$this->_aliases['civicrm_pledge']}.is_test=0 ) AND
" . implode(' AND ', $clauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
public function postProcess() {
parent::postProcess();
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
$checkList = array();
$display_flag = $prev_cid = $cid = 0;
foreach ($rows as $rowNum => $row) {
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Utils_System::url("civicrm/contact/view",
'reset=1&cid=' . $row['civicrm_contact_id'],
$this->_absoluteUrl
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact Summary for this Contact.");
$entryFound = TRUE;
}
if (array_key_exists('civicrm_pledge_financial_type_id', $row)) {
if ($value = $row['civicrm_pledge_financial_type_id']) {
$rows[$rowNum]['civicrm_pledge_financial_type_id'] = CRM_Contribute_PseudoConstant::financialType($value, FALSE);
}
$entryFound = TRUE;
}
//handle status id
if (array_key_exists('civicrm_pledge_status_id', $row)) {
if ($value = $row['civicrm_pledge_status_id']) {
$rows[$rowNum]['civicrm_pledge_status_id'] = CRM_Core_PseudoConstant::getLabel('CRM_Pledge_BAO_Pledge', 'status_id', $value);
}
$entryFound = TRUE;
}
$entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'pledge/summary', 'List all pledge(s) for this ') ? TRUE : $entryFound;
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}

View file

@ -0,0 +1,205 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
* $Id$
*
*/
class CRM_Report_Form_Register extends CRM_Core_Form {
public $_id;
protected $_values = NULL;
public function preProcess() {
$this->_action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE);
$this->_id = CRM_Utils_Request::retrieve('id', 'String', $this, FALSE);
CRM_Utils_System::setTitle(ts('Report Template'));
if ($this->_action & CRM_Core_Action::DELETE) {
return;
}
$this->_opID = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup',
'report_template', 'id', 'name'
);
$instanceInfo = array();
}
/**
* This virtual function is used to set the default values of.
* various form elements
*
* access public
*
* @return array
* reference to the array of default values
*/
public function setDefaultValues() {
$defaults = array();
if ($this->_action & CRM_Core_Action::DELETE) {
return $defaults;
}
if ($this->_id) {
$params = array('id' => $this->_id);
$defaults = array();
CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_OptionValue', $params, $defaults);
}
else {
$defaults['weight'] = CRM_Utils_Weight::getDefaultWeight('CRM_Core_DAO_OptionValue',
array('option_group_id' => $this->_opID)
);
}
return $defaults;
}
public function buildQuickForm() {
if ($this->_action & CRM_Core_Action::DELETE) {
$this->addButtons(array(
array(
'type' => 'next',
'name' => ts('Delete'),
'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
'isDefault' => TRUE,
),
array(
'type' => 'cancel',
'name' => ts('Cancel'),
),
)
);
return;
}
$this->add('text', 'label', ts('Title'), array('size' => 40), TRUE);
$this->add('text', 'value', ts('URL'), array('size' => 40), TRUE);
$this->add('text', 'name', ts('Class'), array('size' => 40), TRUE);
$element = $this->add('text', 'weight', ts('Order'), array('size' => 4), TRUE);
// $element->freeze( );
$this->add('text', 'description', ts('Description'), array('size' => 40), TRUE);
$this->add('checkbox', 'is_active', ts('Enabled?'));
$this->_components = CRM_Core_Component::getComponents();
//unset the report component
unset($this->_components['CiviReport']);
$components = array();
foreach ($this->_components as $name => $object) {
$components[$object->componentID] = $object->info['translatedName'];
}
$this->add('select', 'component_id', ts('Component'), array('' => ts('Contact')) + $components);
$this->addButtons(array(
array(
'type' => 'upload',
'name' => ts('Save'),
'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
'isDefault' => TRUE,
),
array(
'type' => 'cancel',
'name' => ts('Cancel'),
),
)
);
$this->addFormRule(array('CRM_Report_Form_Register', 'formRule'), $this);
}
/**
* @param $fields
* @param $files
* @param $self
*
* @return array
*/
public static function formRule($fields, $files, $self) {
$errors = array();
$dupeClass = FALSE;
$reportUrl = new CRM_Core_DAO_OptionValue();
$reportUrl->option_group_id = $self->_opID;
$reportUrl->value = $fields['value'];
if ($reportUrl->find(TRUE) && $self->_id != $reportUrl->id) {
$errors['value'] = ts('Url already exists in Database.');
if ($reportUrl->name == $fields['name']) {
$dupeClass = TRUE;
}
}
if (!$dupeClass) {
$reportClass = new CRM_Core_DAO_OptionValue();
$reportClass->option_group_id = $self->_opID;
$reportClass->name = $fields['name'];
if ($reportClass->find(TRUE) && $self->_id != $reportClass->id) {
$dupeClass = TRUE;
}
}
if ($dupeClass) {
$errors['name'] = ts('Class already exists in Database.');
}
return $errors;
}
/**
* Process the form submission.
*
*
* @return void
*/
public function postProcess() {
if ($this->_action & CRM_Core_Action::DELETE) {
if (CRM_Core_BAO_OptionValue::del($this->_id)) {
CRM_Core_Session::setStatus(ts('Selected %1 Report has been deleted.', array(1 => $this->_GName)), ts('Record Deleted'), 'success');
CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/report/options/report_template', "reset=1"));
}
else {
CRM_Core_Session::setStatus(ts('Selected %1 type has not been deleted.', array(1 => $this->_GName)), '', 'info');
CRM_Utils_Weight::correctDuplicateWeights('CRM_Core_DAO_OptionValue', $fieldValues);
}
}
else {
// get the submitted form values.
$params = $this->controller->exportValues($this->_name);
$ids = array();
$groupParams = array('name' => ('report_template'));
$optionValue = CRM_Core_OptionValue::addOptionValue($params, $groupParams, $this->_action, $this->_id);
CRM_Core_Session::setStatus(ts('The %1 \'%2\' has been saved.', array(
1 => 'Report Template',
2 => $optionValue->label,
)), ts('Saved'), 'success');
CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin/report/options/report_template', "reset=1"));
}
}
}

View file

@ -0,0 +1,279 @@
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
/**
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class CRM_Report_Form_Walklist_Walklist extends CRM_Report_Form {
protected $_addressField = FALSE;
protected $_emailField = FALSE;
protected $_phoneField = FALSE;
protected $_summary = NULL;
public $_drilldownReport = array('contact/detail' => 'Link to Detail Report');
protected $_customGroupExtends = array(
'Contact',
'Individual',
'Household',
'Organization',
);
/**
* Class constructor.
*/
public function __construct() {
$this->_columns = array(
'civicrm_contact' => array(
'dao' => 'CRM_Contact_DAO_Contact',
'fields' => array(
'id' => array(
'title' => ts('Contact ID'),
'no_display' => TRUE,
'required' => TRUE,
),
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
'no_repeat' => TRUE,
),
),
'filters' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'operator' => 'like',
),
),
'grouping' => 'contact-fields',
'order_bys' => array(
'sort_name' => array(
'title' => ts('Contact Name'),
'required' => TRUE,
),
),
),
'civicrm_address' => array(
'dao' => 'CRM_Core_DAO_Address',
'fields' => array(
'street_number' => array(
'title' => ts('Street Number'),
'type' => 1,
),
'street_address' => NULL,
'city' => NULL,
'postal_code' => NULL,
'state_province_id' => array(
'title' => ts('State/Province'),
'default' => TRUE,
'type' => CRM_Utils_Type::T_INT,
),
'country_id' => array(
'title' => ts('Country'),
),
),
'filters' => array(
'street_number' => array(
'title' => ts('Street Number'),
'type' => 1,
'name' => 'street_number',
),
'street_address' => NULL,
'city' => NULL,
),
'grouping' => 'location-fields',
),
'civicrm_email' => array(
'dao' => 'CRM_Core_DAO_Email',
'fields' => array('email' => array('default' => TRUE)),
'grouping' => 'location-fields',
),
'civicrm_phone' => array(
'dao' => 'CRM_Core_DAO_Phone',
'fields' => array('phone' => NULL),
'grouping' => 'location-fields',
),
);
parent::__construct();
}
public function preProcess() {
parent::preProcess();
}
public function select() {
$select = array();
$this->_columnHeaders = array();
foreach ($this->_columns as $tableName => $table) {
foreach ($table['fields'] as $fieldName => $field) {
if (!empty($field['required']) ||
!empty($this->_params['fields'][$fieldName])
) {
if ($tableName == 'civicrm_address') {
$this->_addressField = TRUE;
}
elseif ($tableName == 'civicrm_email') {
$this->_emailField = TRUE;
}
elseif ($tableName == 'civicrm_phone') {
$this->_phoneField = TRUE;
}
$select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
$this->_columnHeaders["{$tableName}_{$fieldName}"]['title'] = $field['title'];
$this->_columnHeaders["{$tableName}_{$fieldName}"]['type'] = $field['type'];
}
}
}
$this->_select = "SELECT " . implode(",\n", $select) . " ";
}
public function from() {
$this->_from = NULL;
$this->_from = "
FROM civicrm_contact {$this->_aliases['civicrm_contact']} {$this->_aclFrom}
";
if ($this->_addressField) {
$this->_from .= "LEFT JOIN civicrm_address {$this->_aliases['civicrm_address']} ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_address']}.contact_id AND {$this->_aliases['civicrm_address']}.is_primary = 1\n";
}
if ($this->_emailField) {
$this->_from .= "LEFT JOIN civicrm_email {$this->_aliases['civicrm_email']} ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_email']}.contact_id AND {$this->_aliases['civicrm_email']}.is_primary = 1\n";
}
if ($this->_phoneField) {
$this->_from .= "LEFT JOIN civicrm_phone {$this->_aliases['civicrm_phone']} ON {$this->_aliases['civicrm_contact']}.id = {$this->_aliases['civicrm_phone']}.contact_id AND {$this->_aliases['civicrm_phone']}.is_primary = 1\n";
}
}
public function where() {
$clauses = array();
foreach ($this->_columns as $tableName => $table) {
if (array_key_exists('filters', $table)) {
foreach ($table['filters'] as $fieldName => $field) {
$clause = NULL;
if ($field['type'] & CRM_Utils_Type::T_DATE) {
$relative = CRM_Utils_Array::value("{$fieldName}_relative", $this->_params);
$from = CRM_Utils_Array::value("{$fieldName}_from", $this->_params);
$to = CRM_Utils_Array::value("{$fieldName}_to", $this->_params);
$clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
}
else {
$op = CRM_Utils_Array::value("{$fieldName}_op", $this->_params);
if ($op) {
$clause = $this->whereClause($field,
$op,
CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
);
}
}
if (!empty($clause)) {
$clauses[] = $clause;
}
}
}
}
if (empty($clauses)) {
$this->_where = "WHERE ( 1 ) ";
}
else {
$this->_where = "WHERE " . implode(' AND ', $clauses);
}
if ($this->_aclWhere) {
$this->_where .= " AND {$this->_aclWhere} ";
}
}
public function postProcess() {
// get the acl clauses built before we assemble the query
$this->buildACLClause($this->_aliases['civicrm_contact']);
parent::postProcess();
}
/**
* Alter display of rows.
*
* Iterate through the rows retrieved via SQL and make changes for display purposes,
* such as rendering contacts as links.
*
* @param array $rows
* Rows generated by SQL, with an array for each row.
*/
public function alterDisplay(&$rows) {
$entryFound = FALSE;
foreach ($rows as $rowNum => $row) {
// handle state province
if (array_key_exists('civicrm_address_state_province_id', $row)) {
if ($value = $row['civicrm_address_state_province_id']) {
$rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value);
}
$entryFound = TRUE;
}
// handle country
if (array_key_exists('civicrm_address_country_id', $row)) {
if ($value = $row['civicrm_address_country_id']) {
$rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value);
}
$entryFound = TRUE;
}
// convert display name to links
if (array_key_exists('civicrm_contact_sort_name', $row) &&
array_key_exists('civicrm_contact_id', $row)
) {
$url = CRM_Report_Utils_Report::getNextUrl('contact/detail',
'reset=1&force=1&id_op=eq&id_value=' . $row['civicrm_contact_id'],
$this->_absoluteUrl, $this->_id, $this->_drilldownReport
);
$rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
$entryFound = TRUE;
}
// skip looking further in rows, if first row itself doesn't
// have the column we need
if (!$entryFound) {
break;
}
}
}
}