3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
17 class CRM_Report_Form_Case_Detail
extends CRM_Report_Form
{
19 protected $_relField = FALSE;
21 protected $_addressField = TRUE;
23 protected $_activityLast = FALSE;
25 protected $_activityLastCompleted = FALSE;
27 protected $_includeCaseDetailExtra = FALSE;
29 protected $_caseDetailExtra = [];
31 protected $_customGroupExtends = [
36 protected $_caseTypeNameOrderBy = FALSE;
40 public function __construct() {
41 $this->case_statuses
= CRM_Core_OptionGroup
::values('case_status');
42 $this->case_types
= CRM_Case_PseudoConstant
::caseType();
43 $rels = CRM_Core_PseudoConstant
::relationshipType();
44 foreach ($rels as $relid => $v) {
45 $this->rel_types
[$relid] = $v['label_b_a'];
48 $this->caseActivityTypes
= [];
49 foreach (CRM_Case_PseudoConstant
::caseActivityType() as $typeDetail) {
50 $this->caseActivityTypes
[$typeDetail['id']] = $typeDetail['label'];
55 'dao' => 'CRM_Case_DAO_Case',
58 'title' => ts('Case ID'),
63 'title' => ts('Case ID'),
64 'type' => CRM_Utils_Type
::T_INT
,
67 'title' => ts('Subject'),
71 'title' => ts('Start Date'),
72 'type' => CRM_Utils_Type
::T_DATE
,
75 'title' => ts('End Date'),
76 'type' => CRM_Utils_Type
::T_DATE
,
78 'status_id' => ['title' => ts('Case Status')],
79 'case_type_id' => ['title' => ts('Case Type')],
81 'title' => ts('Deleted?'),
83 'type' => CRM_Utils_Type
::T_BOOLEAN
,
88 'title' => ts('Start Date'),
89 'operatorType' => CRM_Report_Form
::OP_DATE
,
90 'type' => CRM_Utils_Type
::T_DATE
,
93 'title' => ts('End Date'),
94 'operatorType' => CRM_Report_Form
::OP_DATE
,
95 'type' => CRM_Utils_Type
::T_DATE
,
98 'title' => ts('Case Status'),
99 'type' => CRM_Utils_Type
::T_INT
,
100 'operatorType' => CRM_Report_Form
::OP_MULTISELECT
,
101 'options' => CRM_Case_BAO_Case
::buildOptions('status_id', 'search'),
104 'title' => ts('Case Type'),
105 'type' => CRM_Utils_Type
::T_INT
,
106 'operatorType' => CRM_Report_Form
::OP_MULTISELECT
,
107 'options' => CRM_Case_BAO_Case
::buildOptions('case_type_id', 'search'),
110 'title' => ts('Deleted?'),
111 'type' => CRM_Utils_Type
::T_BOOLEAN
,
117 'title' => ts('Start Date'),
118 'default_weight' => 1,
121 'title' => ts('End Date'),
124 'title' => ts('Status'),
128 'civicrm_case_type' => [
129 'dao' => 'CRM_Case_DAO_Case',
131 'case_type_title' => [
132 'title' => ts('Case Type'),
137 'civicrm_contact' => [
138 'dao' => 'CRM_Contact_DAO_Contact',
140 'client_sort_name' => [
141 'name' => 'sort_name',
142 'title' => ts('Client Name'),
146 'no_display' => TRUE,
151 'sort_name' => ['title' => ts('Client Name')],
154 'civicrm_relationship' => [
155 'dao' => 'CRM_Contact_DAO_Relationship',
158 'name' => 'relationship_type_id',
159 'title' => ts('Case Role(s)'),
164 'name' => 'relationship_type_id',
165 'title' => ts('Case Role(s)'),
166 'type' => CRM_Utils_Type
::T_INT
,
167 'operatorType' => CRM_Report_Form
::OP_MULTISELECT
,
168 'options' => $this->rel_types
,
171 'title' => ts('Active Role?'),
172 'type' => CRM_Utils_Type
::T_BOOLEAN
,
177 'dao' => 'CRM_Core_DAO_Email',
180 'title' => ts('Email'),
184 'grouping' => 'contact-fields',
187 'dao' => 'CRM_Core_DAO_Phone',
190 'title' => ts('Phone'),
194 'grouping' => 'contact-fields',
196 'civicrm_address' => [
197 'dao' => 'CRM_Core_DAO_Address',
199 'street_address' => NULL,
201 'state_province_id' => [
202 'title' => ts('State/Province'),
204 'country_id' => ['title' => ts('Country')],
206 'grouping' => 'contact-fields',
209 'title' => ts('Country'),
210 'type' => CRM_Utils_Type
::T_INT
,
211 'operatorType' => CRM_Report_Form
::OP_MULTISELECT
,
212 'options' => CRM_Core_PseudoConstant
::country(),
214 'state_province_id' => [
215 'title' => ts('State/Province'),
216 'type' => CRM_Utils_Type
::T_INT
,
217 'operatorType' => CRM_Report_Form
::OP_MULTISELECT
,
218 'options' => CRM_Core_PseudoConstant
::stateProvince(),
222 'civicrm_worldregion' => [
223 'dao' => 'CRM_Core_DAO_Worldregion',
225 'worldregion_id' => [
227 'title' => ts('World Region'),
228 'type' => CRM_Utils_Type
::T_INT
,
229 'operatorType' => CRM_Report_Form
::OP_MULTISELECT
,
230 'options' => CRM_Core_PseudoConstant
::worldRegion(),
234 'civicrm_country' => [
235 'dao' => 'CRM_Core_DAO_Country',
237 'civicrm_activity_last' => [
238 'dao' => 'CRM_Activity_DAO_Activity',
240 'last_activity_activity_subject' => [
242 'title' => ts('Subject of the last activity in the case'),
244 'last_activity_activity_type' => [
245 'name' => 'activity_type_id',
246 'title' => ts('Activity type of the last activity'),
248 'last_activity_date_time' => [
249 'name' => 'activity_date_time',
250 'title' => ts('Last Action Date'),
251 'operatorType' => CRM_Report_Form
::OP_DATE
,
255 'last_activity_activity_type' => [
256 'name' => 'activity_type_id',
257 'title' => ts('Activity type of the last activity'),
258 'operatorType' => CRM_Report_Form
::OP_MULTISELECT
,
259 'options' => CRM_Core_PseudoConstant
::activityType(TRUE, TRUE, FALSE, 'label', TRUE),
261 'last_activity_date_time' => [
262 'name' => 'activity_date_time',
263 'title' => ts('Last Action Date'),
264 'operatorType' => CRM_Report_Form
::OP_DATE
,
267 'alias' => 'civireport_activity_last',
269 'civicrm_activity_last_completed' => [
270 'dao' => 'CRM_Activity_DAO_Activity',
272 'last_completed_activity_subject' => [
274 'title' => ts('Subject of the last completed activity in the case'),
276 'last_completed_activity_type' => [
277 'name' => 'activity_type_id',
278 'title' => ts('Activity type of the last completed activity'),
280 'last_completed_date_time' => [
281 'name' => 'activity_date_time',
282 'title' => ts('Last Completed Action Date'),
283 'operatorType' => CRM_Report_Form
::OP_DATE
,
287 'last_completed_date_time' => [
288 'name' => 'activity_date_time',
289 'title' => ts('Last Completed Action Date'),
290 'operatorType' => CRM_Report_Form
::OP_DATE
,
298 'title' => ts('My Cases'),
299 'type' => 'checkbox',
302 parent
::__construct();
305 public function preProcess() {
306 parent
::preProcess();
309 public function buildQuickForm() {
310 parent
::buildQuickForm();
311 $this->caseDetailSpecialColumnsAdd();
314 public function caseDetailSpecialColumnsAdd() {
316 $elements[] = &$this->createElement('select', 'case_activity_all_dates', NULL,
318 '' => ts('- select -'),
319 ] +
$this->caseActivityTypes
321 $this->addGroup($elements, 'case_detail_extra');
323 $this->_caseDetailExtra
= [
324 'case_activity_all_dates' => [
325 'title' => ts('List of all dates of activities of Type'),
326 'name' => 'activity_date_time',
330 $this->assign('caseDetailExtra', $this->_caseDetailExtra
);
333 public function select() {
334 // @todo - get rid of this function & use parent. Use selectWhere to setthe clause for the
335 // few fields that need custom handling.
337 $this->_columnHeaders
= [];
338 foreach ($this->_columns
as $tableName => $table) {
339 if (array_key_exists('fields', $table)) {
340 foreach ($table['fields'] as $fieldName => $field) {
341 if (!empty($field['required']) ||
342 !empty($this->_params
['fields'][$fieldName])
344 if ($tableName == 'civicrm_relationship') {
345 $this->_relField
= TRUE;
347 if ($fieldName == 'sort_name') {
348 $select[] = "GROUP_CONCAT({$field['dbAlias']} ORDER BY {$field['dbAlias']} )
349 as {$tableName}_{$fieldName}";
351 if ($tableName == 'civicrm_activity_last') {
352 $this->_activityLast
= TRUE;
354 if ($tableName == 'civicrm_activity_last_completed') {
355 $this->_activityLastCompleted
= TRUE;
358 if ($fieldName == 'case_role') {
359 $select[] = "GROUP_CONCAT(DISTINCT({$field['dbAlias']}) ORDER BY {$field['dbAlias']}) as {$tableName}_{$fieldName}";
362 $select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}";
365 $this->_columnHeaders
["{$tableName}_{$fieldName}"]['type'] = $field['type'] ??
NULL;
366 $this->_columnHeaders
["{$tableName}_{$fieldName}"]['title'] = $field['title'];
372 $this->_selectClauses
= $select;
374 $this->_select
= 'SELECT ' . implode(', ', $select) . ' ';
377 public function from() {
379 $case = $this->_aliases
['civicrm_case'];
380 $conact = $this->_aliases
['civicrm_contact'];
383 FROM civicrm_case $case
384 LEFT JOIN civicrm_case_contact civireport_case_contact on civireport_case_contact.case_id = {$case}.id
385 LEFT JOIN civicrm_contact $conact ON {$conact}.id = civireport_case_contact.contact_id
387 if ($this->_relField
) {
389 LEFT JOIN civicrm_relationship {$this->_aliases['civicrm_relationship']} ON {$this->_aliases['civicrm_relationship']}.case_id = {$case}.id
393 $this->joinAddressFromContact();
394 $this->joinPhoneFromContact();
395 $this->joinEmailFromContact();
397 if ($this->isTableSelected('civicrm_worldregion')) {
399 LEFT JOIN civicrm_country {$this->_aliases['civicrm_country']}
400 ON {$this->_aliases['civicrm_country']}.id ={$this->_aliases['civicrm_address']}.country_id
401 LEFT JOIN civicrm_worldregion {$this->_aliases['civicrm_worldregion']}
402 ON {$this->_aliases['civicrm_country']}.region_id = {$this->_aliases['civicrm_worldregion']}.id ";
405 // Include clause for last activity of the case
406 if ($this->_activityLast
) {
407 $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) )";
410 // Include clause for last completed activity of the case
411 if ($this->_activityLastCompleted
) {
412 $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 ) )";
415 if ($this->isTableSelected('civicrm_case_type')) {
417 LEFT JOIN civicrm_case_type {$this->_aliases['civicrm_case_type']}
418 ON {$this->_aliases['civicrm_case']}.case_type_id = {$this->_aliases['civicrm_case_type']}.id
423 public function where() {
426 foreach ($this->_columns
as $tableName => $table) {
427 if (array_key_exists('filters', $table)) {
428 foreach ($table['filters'] as $fieldName => $field) {
431 if (CRM_Utils_Array
::value('type', $field) & CRM_Utils_Type
::T_DATE
) {
432 $relative = $this->_params
["{$fieldName}_relative"] ??
NULL;
433 $from = $this->_params
["{$fieldName}_from"] ??
NULL;
434 $to = $this->_params
["{$fieldName}_to"] ??
NULL;
436 $clause = $this->dateClause($field['dbAlias'], $relative, $from, $to, $field['type']);
440 $op = $this->_params
["{$fieldName}_op"] ??
NULL;
441 if ($fieldName == 'case_type_id' &&
442 !empty($this->_params
['case_type_id_value'])
444 foreach ($this->_params
['case_type_id_value'] as $key => $value) {
445 $this->_params
['case_type_id_value'][$key] = $value;
450 $clause = $this->whereClause($field,
452 CRM_Utils_Array
::value("{$fieldName}_value", $this->_params
),
453 CRM_Utils_Array
::value("{$fieldName}_min", $this->_params
),
454 CRM_Utils_Array
::value("{$fieldName}_max", $this->_params
)
459 if (!empty($clause)) {
460 $clauses[] = $clause;
466 if (isset($this->_params
['options']['my_cases'])) {
467 $session = CRM_Core_Session
::singleton();
468 $userID = $session->get('userID');
469 $clauses[] = "{$this->_aliases['civicrm_contact']}.id = {$userID}";
472 if (empty($clauses)) {
473 $this->_where
= 'WHERE ( 1 ) ';
476 $this->_where
= 'WHERE ' . implode(' AND ', $clauses);
480 public function groupBy() {
481 $this->_groupBy
= CRM_Contact_BAO_Query
::getGroupByFromSelectColumns($this->_selectClauses
, "{$this->_aliases['civicrm_case']}.id");
489 public function statistics(&$rows) {
490 $statistics = parent
::statistics($rows);
492 $select = "select COUNT( DISTINCT( {$this->_aliases['civicrm_address']}.country_id))";
493 $sql = "{$select} {$this->_from} {$this->_where}";
494 $countryCount = CRM_Core_DAO
::singleValueQuery($sql);
496 $statistics['counts']['case'] = [
497 'title' => ts('Total Number of Cases '),
498 'value' => isset($statistics['counts']['rowsFound']) ?
$statistics['counts']['rowsFound']['value'] : count($rows),
500 $statistics['counts']['country'] = [
501 'title' => ts('Total Number of Countries '),
502 'value' => $countryCount,
508 public function caseDetailSpecialColumnProcess() {
509 if (!$this->_includeCaseDetailExtra
) {
513 $from = $select = [];
514 $case = $this->_aliases
['civicrm_case'];
516 if ($activityType = CRM_Utils_Array
::value('case_activity_all_dates', $this->_params
['case_detail_extra'])) {
517 $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";
519 $from[] = " LEFT JOIN civicrm_case_activity civireport_case_activity_all_{$activityType} ON ( civireport_case_activity_all_{$activityType}.case_id = {$case}.id)
520 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})";
522 $this->_columnHeaders
['case_activity_all_dates'] = [
523 'title' => $this->_caseDetailExtra
['case_activity_all_dates']['title'] . ": {$this->caseActivityTypes[$activityType]}",
524 'type' => $this->_caseDetailExtra
['case_activity_all_dates']['type'] ??
NULL,
528 $this->_select
.= ', ' . implode(', ', $select) . ' ';
529 $this->_from
.= ' ' . implode(' ', $from) . ' ';
532 public function postProcess() {
534 $this->beginPostProcess();
536 $this->checkEnabledFields();
538 $this->buildQuery(TRUE);
540 $this->caseDetailSpecialColumnProcess();
542 $sql = "{$this->_select} {$this->_from} {$this->_where} {$this->_groupBy} {$this->_having} {$this->_orderBy} {$this->_limit}";
544 $rows = $graphRows = [];
545 $this->buildRows($sql, $rows);
547 $this->formatDisplay($rows);
549 $this->doTemplateAssignment($rows);
550 $this->endPostProcess($rows);
553 public function checkEnabledFields() {
554 if ((isset($this->_params
['case_role_value'])
555 && !empty($this->_params
['case_role_value'])) ||
556 (isset($this->_params
['is_active_value']))
558 $this->_relField
= TRUE;
561 if (!empty($this->_params
['last_completed_date_time_relative']) ||
562 !empty($this->_params
['last_completed_date_time_from']) ||
563 !empty($this->_params
['last_completed_date_time_to'])
565 $this->_activityLastCompleted
= TRUE;
568 if (!empty($this->_params
['last_activity_date_time_relative']) ||
569 !empty($this->_params
['last_activity_date_time_from']) ||
570 !empty($this->_params
['last_activity_date_time_to'])
572 $this->_activityLast
= TRUE;
575 foreach (array_keys($this->_caseDetailExtra
) as $field) {
576 if (!empty($this->_params
['case_detail_extra'][$field])) {
577 $this->_includeCaseDetailExtra
= TRUE;
584 * Alter display of rows.
586 * Iterate through the rows retrieved via SQL and make changes for display purposes,
587 * such as rendering contacts as links.
590 * Rows generated by SQL, with an array for each row.
592 public function alterDisplay(&$rows) {
594 $activityTypes = CRM_Core_PseudoConstant
::activityType(TRUE, TRUE);
596 foreach ($rows as $rowNum => $row) {
597 if (array_key_exists('civicrm_case_status_id', $row)) {
598 if ($value = $row['civicrm_case_status_id']) {
599 $rows[$rowNum]['civicrm_case_status_id'] = $this->case_statuses
[$value];
604 if (array_key_exists('civicrm_case_case_type_id', $row)) {
605 if ($value = str_replace(CRM_Core_DAO
::VALUE_SEPARATOR
, '', $row['civicrm_case_case_type_id'])) {
606 $rows[$rowNum]['civicrm_case_case_type_id'] = $this->case_types
[$value];
611 if (array_key_exists('civicrm_case_subject', $row)) {
612 if ($value = $row['civicrm_case_subject']) {
613 $url = CRM_Utils_System
::url("civicrm/case/ajax/details",
614 "caseId={$row['civicrm_case_id']}&contactId={$row['civicrm_contact_id']}",
617 $rows[$rowNum]['civicrm_case_subject'] = "<a class=\"crm-popup\" href=\"$url\">$value</a>";
618 $rows[$rowNum]['civicrm_case_subject_hover'] = ts('View Details of Case.');
623 if (array_key_exists('civicrm_relationship_case_role', $row)) {
624 if ($value = $row['civicrm_relationship_case_role']) {
625 $caseRoles = explode(',', $value);
626 foreach ($caseRoles as $num => $caseRole) {
627 $caseRoles[$num] = $this->rel_types
[$caseRole];
629 $rows[$rowNum]['civicrm_relationship_case_role'] = implode('; ', $caseRoles);
633 if (array_key_exists('civicrm_activity_last_last_activity_activity_subject', $row) &&
634 empty($row['civicrm_activity_last_last_activity_activity_subject'])
636 $rows[$rowNum]['civicrm_activity_last_last_activity_activity_subject'] = ts('(no subject)');
639 if (array_key_exists('civicrm_activity_last_completed_last_completed_activity_subject', $row) &&
640 empty($row['civicrm_activity_last_completed_last_completed_activity_subject'])
642 $rows[$rowNum]['civicrm_activity_last_completed_last_completed_activity_subject'] = ts('(no subject)');
645 if (array_key_exists('civicrm_contact_client_sort_name', $row) &&
646 array_key_exists('civicrm_contact_id', $row)
648 $url = CRM_Utils_System
::url("civicrm/contact/view",
649 'reset=1&cid=' . $row['civicrm_contact_id'],
652 $rows[$rowNum]['civicrm_contact_client_sort_name_link'] = $url;
653 $rows[$rowNum]['civicrm_contact_client_sort_name_hover'] = ts("View Contact Summary for this Contact");
656 if (array_key_exists('civicrm_activity_last_last_activity_activity_type', $row)) {
657 if ($value = $row['civicrm_activity_last_last_activity_activity_type']) {
658 $rows[$rowNum]['civicrm_activity_last_last_activity_activity_type'] = $activityTypes[$value];
662 if (array_key_exists('civicrm_activity_last_completed_last_completed_activity_type', $row)) {
663 if ($value = $row['civicrm_activity_last_completed_last_completed_activity_type']) {
664 $rows[$rowNum]['civicrm_activity_last_completed_last_completed_activity_type'] = $activityTypes[$value];
669 if (array_key_exists('case_activity_all_dates', $row)) {
670 if ($value = $row['case_activity_all_dates']) {
671 $activityDates = explode(',', $value);
672 foreach ($activityDates as $num => $activityDate) {
673 $activityDates[$num] = CRM_Utils_Date
::customFormat($activityDate);
675 $rows[$rowNum]['case_activity_all_dates'] = implode('; ', $activityDates);
680 $entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, NULL, NULL) ?
TRUE : $entryFound;