Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRM-21829: Show Related Cases For Organizations #101

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CRM/Civicase/APIHelpers/CaseList.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ public function getCaseList($params) {
'tag_id.name', 'tag_id.color', 'tag_id.description',
);
$params['return'] = (isset($params['return']) ? array_merge($defaultAPIReturnedColumns, $params['return']) : $defaultAPIReturnedColumns);
if(isset($params['related_cids'])) {
$params['contact_id'] = $params['related_cids'];
}
$cases = civicrm_api3('Case', 'getdetails', $params);

foreach ($cases['values'] as &$case) {
Expand Down
4 changes: 4 additions & 0 deletions CRM/Civicase/Page/ContactCaseTab.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ class CRM_Civicase_Page_ContactCaseTab extends CRM_Core_Page {
public function run() {
$cid = CRM_Utils_Request::retrieve('cid', 'Positive', CRM_Core_DAO::$_nullObject, TRUE);
$this->assign('cid', $cid);
// For Related cases tab (optional)
$related_cids = CRM_Utils_Request::retrieve('related_cids', 'String');
if($related_cids)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always use braces for if statements, even if they only have a single line.

$this->assign('related_cids', $related_cids);
parent::run();
}

Expand Down
2 changes: 1 addition & 1 deletion ang/civicase/CaseList.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
function loadCaseApiParams(filters, sort, page) {
var returnParams = {
sequential: 1,
return: ['subject', 'case_type_id', 'status_id', 'is_deleted', 'start_date', 'modified_date', 'contacts', 'activity_summary', 'category_count', 'tag_id.name', 'tag_id.color', 'tag_id.description'],
return: ['subject', 'case_type_id', 'status_id', 'is_deleted', 'start_date', 'modified_date', 'contacts', 'activity_summary', 'category_count', 'tag_id.name', 'tag_id.color', 'tag_id.description', 'related_cids'],
options: {
sort: sort.field + ' ' + sort.dir,
limit: page.size,
Expand Down
97 changes: 95 additions & 2 deletions civicase.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
*/
function civicase_civicrm_tabset($tabsetName, &$tabs, $context) {
$useAng = FALSE;

switch ($tabsetName) {
case 'civicrm/contact/view':
$caseTabPresent = FALSE;
Expand Down Expand Up @@ -44,6 +43,22 @@ function civicase_civicrm_tabset($tabsetName, &$tabs, $context) {
);
}

if(CRM_Core_Permission::check('basic case information') &&
getContactType($context['contact_id']) == 'Organization' &&
Civi::settings()->get('civicaseRelatedCasesTab', 0)) {
$caseTabKey = array_search('case', array_column($tabs, 'id'));
$tabs[] = array(
'id' => 'related_case',
'url' => CRM_Utils_System::url('civicrm/case/contact-case-tab', array(
'cid' => $context['contact_id'],
'related_cids' => implode(',', getOrganizationRelatedCaseContactIds($context['contact_id'])),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could pose problems in the long term, if there's an organization with a lot of members. Like on ATL. And each member could have several related cases. I think it'd be better if you just send a flag to tell if the organization has related cases or not and look for the actual related id's when the form is being built (or preprocessed).

)),
'title' => ts('Related Cases'),
'weight' => $tabs[$caseTabKey]['weight']+1,
'count' => getOrganizationRelatedCasesCount($context['contact_id']),
'class' => 'livePage',
);
}
break;

}
Expand Down Expand Up @@ -195,7 +210,6 @@ function civicase_civicrm_alterSettingsFolders(&$metaDataFolders = NULL) {
_civicase_civix_civicrm_alterSettingsFolders($metaDataFolders);
}


/**
* Implements hook_civicrm_buildForm().
*
Expand Down Expand Up @@ -340,6 +354,14 @@ function civicase_civicrm_buildForm($formName, &$form) {
}
}
}
if($formName == 'CRM_Admin_Form_Setting_Case') {
$form->addYesNo('_qf_civicaseRelatedCasesTab', ts('Display cases from related individuals on organisation contacts'));
$form->setDefaults(array('_qf_civicaseRelatedCasesTab' => Civi::settings()->get('civicaseRelatedCasesTab', 0)));
$templatePath = realpath(dirname(__FILE__)."/templates");
CRM_Core_Region::instance('page-body')->add(array(
'template' => "{$templatePath}/RelatedCasesField.tpl"
));
}
}

/**
Expand Down Expand Up @@ -415,6 +437,12 @@ function civicase_civicrm_postProcess($formName, &$form) {
civicrm_api3('Activity', 'delete', array('id' => $urlParams['draft_id']));
}
}
if($formName = 'CRM_Admin_Form_Setting_Case' && isset($form->_submitValues['_qf_civicaseRelatedCasesTab'])) {
if($form->_submitValues['_qf_civicaseRelatedCasesTab'] == 1)
Civi::settings()->set('civicaseRelatedCasesTab', 1);
else
Civi::settings()->set('civicaseRelatedCasesTab', 0);
}
}

/**
Expand Down Expand Up @@ -556,3 +584,68 @@ function civicase_civicrm_selectWhereClause($entity, &$clauses) {
unset($clauses['id']);
}
}

/**
* Retrieve contact ids of all contacts(with cases) related to given Organization contact.
*
* @param int $organizationId
*
* @return array
*/
function getOrganizationRelatedCaseContactIds($organizationId, $countOnly=FALSE) {
if(!$organizationId) {
return array();
}
$sql = 'SELECT';
if($countOnly) {
$sql .= ' COUNT(cc.case_id) ';
}
else {
$sql .= ' rel.contact_id_a as id ';
}
$sql .= "FROM civicrm_case_contact AS cc
INNER JOIN civicrm_relationship AS rel ON rel.contact_id_a = cc.contact_id
INNER JOIN civicrm_relationship_type AS rtype ON rel.relationship_type_id = rtype.id
WHERE 'Organization' IN (rtype.contact_type_a, rtype.contact_type_b)
AND %1 = CASE
WHEN (rtype.contact_type_a = 'Organization') THEN rel.contact_id_a
ELSE rel.contact_id_b
END";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We really should have this kind of code in a separate class. That way we could create tests if need be and also help us get rid of the clutter here. Most of the hooks implemented in this extension are slowly starting to get out of control, I think they would really benefit if you could refactor your code into a separate class/classes, as you see fit. The idea is to keep business logic out of the extension's main file and have classes that do the bulk of the work.

$all = CRM_Core_DAO::executeQuery($sql, array(
1 => array($organizationId, 'Integer'),
));
if($countOnly) {
return $all->fetchValue();
}
$all = $all->fetchAll();
$ids = array();
foreach($all as $each) {
if(!in_array($each['id'], $ids))
$ids[] = $each['id'];
}
return $ids;
}

/**
* Retrieve count of all cases of all contacts that are related to given Organization contact.
*
* @param int $organizationId
* @return int
*/
function getOrganizationRelatedCasesCount($organizationId) {
return getOrganizationRelatedCaseContactIds($organizationId, TRUE);
}

/**
* Retrieve contact type for given contact id
*
* @param int $contact_id
* @return string
*/
function getContactType($contact_id) {
$sql = "SELECT contact_type FROM civicrm_contact
WHERE id = %1";
return CRM_Core_DAO::executeQuery($sql, array(
1 => array($contact_id, 'Integer'),
))->fetchValue();
}
30 changes: 27 additions & 3 deletions templates/CRM/Civicase/Page/ContactCaseTab.tpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{if $related_cids}
<div id="civicaseRelatedContactTab" >
{else}
<div id="civicaseContactTab" >
{/if}
<div class="container" ng-view></div>
</div>
{literal}
Expand All @@ -10,9 +14,18 @@
reloadOnSearch: false,
resolve: {
hiddenFilters: function() {
return {
"contact_id": [{/literal}{$cid|json}{literal}]
var ret = {
"contact_id": [{/literal}{$cid|json}{literal}]
};
{/literal}
{if $related_cids}
{literal}
var rcids = [{/literal}{$related_cids|json}{literal}];
ret["related_cids"] = rcids.toString().split(',');
{/literal}
{/if}
{literal}
return ret;
}
},
controller: 'CivicaseCaseList',
Expand All @@ -22,7 +35,18 @@
})(angular, CRM.$, CRM._);

CRM.$(document).one('crmLoad', function(){
angular.bootstrap(document.getElementById('civicaseContactTab'), ['civicaseContactTab']);
{/literal}
{if $related_cids}
{literal}
var caseTab = document.getElementById('civicaseRelatedContactTab');
{/literal}
{else}
{literal}
var caseTab = document.getElementById('civicaseContactTab');
{/literal}
{/if}
{literal}
angular.bootstrap(caseTab, ['civicaseContactTab']);
});
</script>
{/literal}
11 changes: 11 additions & 0 deletions templates/RelatedCasesField.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<table>
<tr class="crm-case-form-block-civicaseRelatedCasesTab" id="civicaseRelatedCasesTab">
<td class="label">{$form._qf_civicaseRelatedCasesTab.label}</td>
<td>{$form._qf_civicaseRelatedCasesTab.html}<br />
<span class="description">{ts}With this checkbox enabled cases from individuals who are directly related to the organisation will be displayed on the organisation records on a tab called "Related Cases".{/ts}</span>
</td>
</tr>
</table>
<script type="text/javascript">
cj('form.CRM_Admin_Form_Setting_Case table.form-layout tbody').append(cj('#civicaseRelatedCasesTab'));
</script>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing new-line at end of file.