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

dev/core#530 Make a_b relationships available as case roles #13916

Merged
merged 9 commits into from
Jun 12, 2019
4 changes: 2 additions & 2 deletions CRM/Activity/Page/AJAX.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public static function getCaseRoles() {

foreach ($caseRelationships as $key => $value) {
// This role has been filled
unset($caseRoles[$value['relation_type']]);
unset($caseRoles[$value['relation_type'] . '_' . $value['relationship_direction']]);
// mark original case relationships record to use on setting edit links below
$caseRelationships[$key]['source'] = 'caseRel';
}
Expand Down Expand Up @@ -209,7 +209,7 @@ public static function getCaseRoles() {
foreach ($caseRelationships as $key => &$row) {
$typeLabel = $row['relation'];
// Add "<br />(Case Manager)" to label
if (!empty($row['relation_type']) && $row['relation_type'] == $managerRoleId) {
if (!empty($row['relation_type']) && !empty($row['relationship_direction']) && $row['relation_type'] . '_' . $row['relationship_direction'] == $managerRoleId) {
$row['relation'] .= '<br />' . '(' . ts('Case Manager') . ')';
}
// view user links
Expand Down
185 changes: 145 additions & 40 deletions CRM/Case/BAO/Case.php
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ public static function getCaseActivityQuery($type = 'upcoming', $userID, $condit
'civicrm_case.status_id as case_status_id',
't_act.status_id as status_id',
'civicrm_case.start_date as case_start_date',
'case_relation_type.label_b_a as case_role',
"GROUP_CONCAT(DISTINCT IF(case_relationship.contact_id_b = $userID, case_relation_type.label_a_b, case_relation_type.label_b_a) SEPARATOR ', ') as case_role",
't_act.activity_date_time as activity_date_time',
't_act.id as activity_id',
);
Expand Down Expand Up @@ -475,8 +475,8 @@ public static function getCaseActivityQuery($type = 'upcoming', $userID, $condit
ON civicrm_phone.contact_id = civicrm_contact.id
AND civicrm_phone.is_primary = 1
LEFT JOIN civicrm_relationship case_relationship
ON case_relationship.contact_id_a = civicrm_case_contact.contact_id
AND case_relationship.contact_id_b = {$userID}
ON ((case_relationship.contact_id_a = civicrm_case_contact.contact_id AND case_relationship.contact_id_b = {$userID})
OR (case_relationship.contact_id_b = civicrm_case_contact.contact_id AND case_relationship.contact_id_a = {$userID}))
AND case_relationship.is_active
AND case_relationship.case_id = civicrm_case.id
LEFT JOIN civicrm_relationship_type case_relation_type
Expand Down Expand Up @@ -535,10 +535,11 @@ public static function getCases($allCases = TRUE, $params = array(), $context =
$whereClauses = array('civicrm_case.is_deleted = 0 AND civicrm_contact.is_deleted <> 1');

if (!$allCases) {
$whereClauses[] .= " case_relationship.contact_id_b = {$userID} AND case_relationship.is_active ";
$whereClauses[] = "(case_relationship.contact_id_b = {$userID} OR case_relationship.contact_id_a = {$userID})";
$whereClauses[] = 'case_relationship.is_active';
}
if (empty($params['status_id']) && ($type == 'upcoming' || $type == 'any')) {
$whereClauses[] = " civicrm_case.status_id != " . CRM_Core_PseudoConstant::getKey('CRM_Case_BAO_Case', 'case_status_id', 'Closed');
$whereClauses[] = "civicrm_case.status_id != " . CRM_Core_PseudoConstant::getKey('CRM_Case_BAO_Case', 'case_status_id', 'Closed');
}

foreach (array('case_type_id', 'status_id') as $column) {
Expand Down Expand Up @@ -703,26 +704,28 @@ public static function getCasesSummary($allCases = TRUE) {

// build rows with actual data
$rows = array();
$myGroupByClause = $mySelectClause = $myCaseFromClause = $myCaseWhereClause = '';
$myGroupByClause = $mySelectClause = $myCaseFromClause = $myCaseWhereClauseA = $myCaseWhereClauseB = '';

if ($allCases) {
$userID = 'null';
$all = 1;
$case_owner = 1;
$myGroupByClause = ' GROUP BY civicrm_case.id';
$myGroupByClauseB = ' GROUP BY civicrm_case.id';
}
else {
$all = 0;
$case_owner = 2;
$myCaseWhereClause = " AND case_relationship.contact_id_b = {$userID} AND case_relationship.is_active ";
$myGroupByClause = " GROUP BY CONCAT(case_relationship.case_id,'-',case_relationship.contact_id_b)";
$myCaseWhereClauseA = " AND case_relationship.contact_id_a = {$userID} AND case_relationship.is_active ";
$myGroupByClauseA = " GROUP BY CONCAT(civicrm_case.id,'-',case_relationship.contact_id_a)";
$myCaseWhereClauseB = " AND case_relationship.contact_id_b = {$userID} AND case_relationship.is_active ";
$myGroupByClauseB = " GROUP BY CONCAT(civicrm_case.id,'-',case_relationship.contact_id_b)";
}
$myGroupByClause .= ", case_status.label, status_id, case_type_id";

$myGroupByClauseB .= ", case_status.label, status_id, case_type_id, civicrm_case.id";
$myGroupByClauseA = $myGroupByClauseB;
// FIXME: This query could be a lot more efficient if it used COUNT() instead of returning all rows and then counting them with php
$query = "
SELECT case_status.label AS case_status, status_id, civicrm_case_type.title AS case_type,
case_type_id, case_relationship.contact_id_b
SELECT civicrm_case.id, case_status.label AS case_status, status_id, civicrm_case_type.title AS case_type,
case_type_id, case_relationship.contact_id_b as case_contact
FROM civicrm_case
INNER JOIN civicrm_case_contact cc on cc.case_id = civicrm_case.id
LEFT JOIN civicrm_case_type ON civicrm_case.case_type_id = civicrm_case_type.id
Expand All @@ -732,7 +735,20 @@ public static function getCasesSummary($allCases = TRUE) {
LEFT JOIN civicrm_relationship case_relationship ON ( case_relationship.case_id = civicrm_case.id
AND case_relationship.contact_id_b = {$userID} AND case_relationship.is_active )
WHERE is_deleted = 0 AND cc.contact_id IN (SELECT id FROM civicrm_contact WHERE is_deleted <> 1)
{$myCaseWhereClause} {$myGroupByClause}";
{$myCaseWhereClauseB} {$myGroupByClauseB}
UNION
SELECT civicrm_case.id, case_status.label AS case_status, status_id, civicrm_case_type.title AS case_type,
case_type_id, case_relationship.contact_id_a as case_contact
FROM civicrm_case
INNER JOIN civicrm_case_contact cc on cc.case_id = civicrm_case.id
LEFT JOIN civicrm_case_type ON civicrm_case.case_type_id = civicrm_case_type.id
LEFT JOIN civicrm_option_group option_group_case_status ON ( option_group_case_status.name = 'case_status' )
LEFT JOIN civicrm_option_value case_status ON ( civicrm_case.status_id = case_status.value
AND option_group_case_status.id = case_status.option_group_id )
LEFT JOIN civicrm_relationship case_relationship ON ( case_relationship.case_id = civicrm_case.id
AND case_relationship.contact_id_a = {$userID})
WHERE is_deleted = 0 AND cc.contact_id IN (SELECT id FROM civicrm_contact WHERE is_deleted <> 1)
{$myCaseWhereClauseA} {$myGroupByClauseA}";

$res = CRM_Core_DAO::executeQuery($query);
while ($res->fetch()) {
Expand Down Expand Up @@ -1204,29 +1220,53 @@ public static function getRelatedContacts($caseID, $includeDetails = TRUE) {
$caseInfo = civicrm_api3('Case', 'getsingle', array(
'id' => $caseID,
// Most efficient way of retrieving definition is to also include case type id and name so the api doesn't have to look it up separately
'return' => array('case_type_id', 'case_type_id.name', 'case_type_id.definition'),
'return' => array('case_type_id', 'case_type_id.name', 'case_type_id.definition', 'contact_id'),
));
if (!empty($caseInfo['case_type_id.definition']['caseRoles'])) {
$caseRoles = CRM_Utils_Array::rekey($caseInfo['case_type_id.definition']['caseRoles'], 'name');
}
}
$values = array();
$query = '
SELECT cc.display_name as name, cc.sort_name as sort_name, cc.id, cr.relationship_type_id, crt.label_b_a as role, crt.name_b_a, ce.email, cp.phone
FROM civicrm_relationship cr
LEFT JOIN civicrm_relationship_type crt
ON crt.id = cr.relationship_type_id
LEFT JOIN civicrm_contact cc
ON cc.id = cr.contact_id_b
LEFT JOIN civicrm_email ce
ON ce.contact_id = cc.id
AND ce.is_primary= 1
LEFT JOIN civicrm_phone cp
ON cp.contact_id = cc.id
AND cp.is_primary= 1
WHERE cr.case_id = %1 AND cr.is_active AND cc.is_deleted <> 1';

$params = array(1 => array($caseID, 'Integer'));
$values = array();
$query = <<<HERESQL
SELECT cc.display_name as name, cc.sort_name as sort_name, cc.id, cr.relationship_type_id, crt.label_b_a as role, crt.name_b_a as role_name, ce.email, cp.phone
FROM civicrm_relationship cr
JOIN civicrm_relationship_type crt
ON crt.id = cr.relationship_type_id
JOIN civicrm_contact cc
ON cc.id = cr.contact_id_a
AND cc.is_deleted <> 1
LEFT JOIN civicrm_email ce
ON ce.contact_id = cc.id
AND ce.is_primary= 1
LEFT JOIN civicrm_phone cp
ON cp.contact_id = cc.id
AND cp.is_primary= 1
WHERE cr.case_id = %1
AND cr.is_active
AND cc.id NOT IN (%2)
UNION
SELECT cc.display_name as name, cc.sort_name as sort_name, cc.id, cr.relationship_type_id, crt.label_a_b as role, crt.name_a_b as role_name, ce.email, cp.phone
FROM civicrm_relationship cr
JOIN civicrm_relationship_type crt
ON crt.id = cr.relationship_type_id
JOIN civicrm_contact cc
ON cc.id = cr.contact_id_b
AND cc.is_deleted <> 1
LEFT JOIN civicrm_email ce
ON ce.contact_id = cc.id
AND ce.is_primary= 1
LEFT JOIN civicrm_phone cp
ON cp.contact_id = cc.id
AND cp.is_primary= 1
WHERE cr.case_id = %1
AND cr.is_active
AND cc.id NOT IN (%2)
HERESQL;
$params = array(
1 => array($caseID, 'Integer'),
2 => array(implode(',', $caseInfo['client_id']), 'String'),
);
$dao = CRM_Core_DAO::executeQuery($query, $params);

while ($dao->fetch()) {
Expand All @@ -1244,7 +1284,7 @@ public static function getRelatedContacts($caseID, $includeDetails = TRUE) {
'phone' => $dao->phone,
);
// Add more info about the role (creator, manager)
$role = CRM_Utils_Array::value($dao->name_b_a, $caseRoles);
$role = CRM_Utils_Array::value($dao->role_name, $caseRoles);
if ($role) {
unset($role['name']);
$details += $role;
Expand Down Expand Up @@ -1848,16 +1888,27 @@ public static function getCaseManagerContact($caseType, $caseId) {
$managerRoleId = $xmlProcessor->getCaseManagerRoleId($caseType);

if (!empty($managerRoleId)) {
$managerRoleQuery = "
SELECT civicrm_contact.id as casemanager_id,
civicrm_contact.sort_name as casemanager
FROM civicrm_contact
LEFT JOIN civicrm_relationship ON (civicrm_relationship.contact_id_b = civicrm_contact.id AND civicrm_relationship.relationship_type_id = %1) AND civicrm_relationship.is_active
LEFT JOIN civicrm_case ON civicrm_case.id = civicrm_relationship.case_id
WHERE civicrm_case.id = %2 AND is_active = 1";
if (substr($managerRoleId, -4) == '_a_b') {
$managerRoleQuery = "
SELECT civicrm_contact.id as casemanager_id,
civicrm_contact.sort_name as casemanager
FROM civicrm_contact
LEFT JOIN civicrm_relationship ON (civicrm_relationship.contact_id_b = civicrm_contact.id AND civicrm_relationship.relationship_type_id = %1) AND civicrm_relationship.is_active
LEFT JOIN civicrm_case ON civicrm_case.id = civicrm_relationship.case_id
WHERE civicrm_case.id = %2 AND is_active = 1";
}
if (substr($managerRoleId, -4) == '_b_a') {
$managerRoleQuery = "
SELECT civicrm_contact.id as casemanager_id,
civicrm_contact.sort_name as casemanager
FROM civicrm_contact
LEFT JOIN civicrm_relationship ON (civicrm_relationship.contact_id_a = civicrm_contact.id AND civicrm_relationship.relationship_type_id = %1) AND civicrm_relationship.is_active
LEFT JOIN civicrm_case ON civicrm_case.id = civicrm_relationship.case_id
WHERE civicrm_case.id = %2 AND is_active = 1";
}

$managerRoleParams = array(
1 => array($managerRoleId, 'Integer'),
1 => array(substr($managerRoleId, 0, -4), 'Integer'),
2 => array($caseId, 'Integer'),
);

Expand Down Expand Up @@ -3214,4 +3265,58 @@ public static function getEntityRefFilters() {
return $filters;
}

/**
* Fetch Case Role direction from Case Type
*/
public static function getCaseRoleDirection($caseId, $roleTypeId = NULL) {
try {
$case = civicrm_api3('Case', 'getsingle', array('id' => $caseId));
}
catch (CiviCRM_API3_Exception $e) {
// Lack of permissions will throw an exception
return 0;
}
if (!empty($case['case_type_id'])) {
try {
$caseType = civicrm_api3('CaseType', 'getsingle', array('id' => $case['case_type_id'], 'return' => array('definition')));
}
catch (CiviCRM_API3_Exception $e) {
// Lack of permissions will throw an exception
return 'no case type found';
}
if (!empty($caseType['definition']['caseRoles'])) {
$caseRoles = array();
foreach ($caseType['definition']['caseRoles'] as $key => $roleDetails) {
// Check if its an a_b label
try {
$relType = civicrm_api3('RelationshipType', 'getsingle', array('label_a_b' => $roleDetails['name']));
}
catch (CiviCRM_API3_Exception $e) {
}
if (!empty($relType['id'])) {
$roleDetails['id'] = $relType['id'];
$roleDetails['direction'] = 'b_a';
}
// Check if its a b_a label
try {
$relTypeBa = civicrm_api3('RelationshipType', 'getsingle', array('label_b_a' => $roleDetails['name']));
}
catch (CiviCRM_API3_Exception $e) {
}
if (!empty($relTypeBa['id'])) {
if (!empty($roleDetails['direction'])) {
$roleDetails['direction'] = 'bidrectional';
}
else {
$roleDetails['id'] = $relTypeBa['id'];
$roleDetails['direction'] = 'a_b';
}
}
$caseRoles[$roleDetails['id']] = $roleDetails;
}
}
return $caseRoles;
}
}

}
7 changes: 3 additions & 4 deletions CRM/Case/BAO/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public static function select(&$query) {
}

if (!empty($query->_returnProperties['case_role'])) {
$query->_select['case_role'] = "case_relation_type.label_b_a as case_role";
$query->_select['case_role'] = "IF(case_relationship.contact_id_b = contact_a.id, case_relation_type.label_b_a, case_relation_type.label_a_b) as case_role";
$query->_element['case_role'] = 1;
$query->_tables['case_relationship'] = $query->_whereTables['case_relationship'] = 1;
$query->_tables['case_relation_type'] = $query->_whereTables['case_relation_type'] = 1;
Expand Down Expand Up @@ -296,7 +296,7 @@ public static function whereClauseSingle(&$values, &$query) {
if ($value == 2) {
$session = CRM_Core_Session::singleton();
$userID = $session->get('userID');
$query->_where[$grouping][] = ' ( ' . CRM_Contact_BAO_Query::buildClause("case_relationship.contact_id_b", $op, $userID, 'Int') . ' AND ' . CRM_Contact_BAO_Query::buildClause("case_relationship.is_active", '<>', 0, 'Int') . ' ) ';
$query->_where[$grouping][] = ' (( ' . CRM_Contact_BAO_Query::buildClause("case_relationship.contact_id_b", $op, $userID, 'Int') . ' AND ' . CRM_Contact_BAO_Query::buildClause("case_relationship.is_active", '<>', 0, 'Int') . ' ) OR ( ' . CRM_Contact_BAO_Query::buildClause("case_relationship.contact_id_a", $op, $userID, 'Int') . ' AND ' . CRM_Contact_BAO_Query::buildClause("case_relationship.is_active", '<>', 0, 'Int') . ' ))';
$query->_qill[$grouping][] = ts('Case %1 My Cases', [1 => $op]);
$query->_tables['case_relationship'] = $query->_whereTables['case_relationship'] = 1;
}
Expand Down Expand Up @@ -434,7 +434,6 @@ public static function whereClauseSingle(&$values, &$query) {
// adding where clause for case_role

case 'case_role':
$query->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause("case_relation_type.name_b_a", $op, $value, 'String');
$query->_qill[$grouping][] = ts("Role in Case %1 '%2'", [1 => $op, 2 => $value]);
$query->_tables['case_relation_type'] = $query->_whereTables['case_relationship_type'] = 1;
$query->_tables['civicrm_case'] = $query->_whereTables['civicrm_case'] = 1;
Expand Down Expand Up @@ -549,7 +548,7 @@ public static function from($name, $mode, $side) {
case 'case_relationship':
$session = CRM_Core_Session::singleton();
$userID = $session->get('userID');
$from .= " $side JOIN civicrm_relationship case_relationship ON ( case_relationship.contact_id_a = civicrm_case_contact.contact_id AND case_relationship.contact_id_b = {$userID} AND case_relationship.case_id = civicrm_case.id )";
$from .= " $side JOIN civicrm_relationship case_relationship ON ( case_relationship.contact_id_a = civicrm_case_contact.contact_id AND case_relationship.contact_id_b = {$userID} AND case_relationship.case_id = civicrm_case.id OR case_relationship.contact_id_b = civicrm_case_contact.contact_id AND case_relationship.contact_id_a = {$userID} AND case_relationship.case_id = civicrm_case.id )";
break;

case 'case_relation_type':
Expand Down
14 changes: 11 additions & 3 deletions CRM/Case/Form/AddToCaseAsRole.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,23 @@ public function postProcess() {
$contacts = $this->_contactIds;

$clients = CRM_Case_BAO_Case::getCaseClients($caseId);
$caseRole = CRM_Case_BAO_Case::getCaseRoleDirection($caseId, $roleTypeId);

$params = [
'contact_id_a' => $clients[0],
'contact_id_b' => $contacts,
'case_id' => $caseId,
'relationship_type_id' => $roleTypeId,
];

CRM_Contact_BAO_Relationship::createMultiple($params, 'a');
if ($caseRole[$roleTypeId]['direction'] == 'b_a') {
$params['contact_id_b'] = $clients[0];
$params['contact_id_a'] = $contacts;
CRM_Contact_BAO_Relationship::createMultiple($params, 'b');
}
elseif ($caseRole[$roleTypeId]['direction'] == 'a_b' || $caseRole[$roleTypeId]['direction'] = 'bidirectional') {
$params['contact_id_a'] = $clients[0];
$params['contact_id_b'] = $contacts;
CRM_Contact_BAO_Relationship::createMultiple($params, 'a');
}

$url = CRM_Utils_System::url(
'civicrm/contact/view/case',
Expand Down
2 changes: 1 addition & 1 deletion CRM/Case/Form/CaseView.php
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ public function buildQuickForm() {

foreach ($caseRelationships as $key => & $value) {
if (!empty($managerRoleId)) {
if ($managerRoleId == $value['relation_type']) {
if (substr($managerRoleId, 0, -4) == $value['relation_type'] && substr($managerRoleId, -3) == $value['relationship_direction']) {
$value['relation'] = $managerLabel;
}
}
Expand Down
10 changes: 8 additions & 2 deletions CRM/Case/Info.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,14 @@ public function getReferenceCounts($dao) {
}
elseif ($dao instanceof CRM_Contact_DAO_RelationshipType) {
/** @var $dao CRM_Contact_DAO_RelationshipType */
$count = CRM_Case_XMLRepository::singleton()
->getRelationshipReferenceCount($dao->{CRM_Case_XMLProcessor::REL_TYPE_CNAME});

// Need to look both directions, but no need to translate case role
// direction from XML perspective to client-based perspective
$xmlRepo = CRM_Case_XMLRepository::singleton();
$count = $xmlRepo->getRelationshipReferenceCount($dao->label_a_b);
if ($dao->label_a_b != $dao->label_b_a) {
$count += $xmlRepo->getRelationshipReferenceCount($dao->label_b_a);
}
if ($count > 0) {
$result[] = [
'name' => 'casetypexml:relationships',
Expand Down
Loading