From 41cf58d3ed398a63e7ab07648301237894b65cc6 Mon Sep 17 00:00:00 2001 From: Alice Frumin Date: Thu, 31 Jan 2019 17:19:40 -0500 Subject: [PATCH] dev/core#530 CiviCase: making roles available in either direction --- CRM/Activity/Page/AJAX.php | 4 +- CRM/Case/BAO/Case.php | 183 ++++++++++++++---- CRM/Case/BAO/Query.php | 7 +- CRM/Case/Form/AddToCaseAsRole.php | 14 +- CRM/Case/Form/CaseView.php | 2 +- CRM/Case/Info.php | 2 +- CRM/Case/ManagedEntities.php | 7 +- CRM/Case/XMLProcessor.php | 15 +- CRM/Case/XMLProcessor/Process.php | 19 +- CRM/Report/Form/Case/Summary.php | 8 +- ang/crmCaseType.ang.php | 6 - ang/crmCaseType.js | 57 +++--- tests/karma/unit/crmCaseTypeSpec.js | 28 ++- .../phpunit/CRM/Case/BAO/CaseTypeForkTest.php | 2 +- 14 files changed, 242 insertions(+), 112 deletions(-) diff --git a/CRM/Activity/Page/AJAX.php b/CRM/Activity/Page/AJAX.php index 1da789c273..6c78fb59c5 100644 --- a/CRM/Activity/Page/AJAX.php +++ b/CRM/Activity/Page/AJAX.php @@ -161,7 +161,7 @@ class CRM_Activity_Page_AJAX { 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'; } @@ -209,7 +209,7 @@ class CRM_Activity_Page_AJAX { foreach ($caseRelationships as $key => &$row) { $typeLabel = $row['relation']; // Add "
(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'] .= '
' . '(' . ts('Case Manager') . ')'; } // view user links diff --git a/CRM/Case/BAO/Case.php b/CRM/Case/BAO/Case.php index aaa37f5a59..f7d40e7e19 100644 --- a/CRM/Case/BAO/Case.php +++ b/CRM/Case/BAO/Case.php @@ -434,7 +434,7 @@ WHERE cc.contact_id = %1 AND civicrm_case_type.name = '{$caseType}'"; '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', ); @@ -475,8 +475,8 @@ HERESQL; 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 @@ -535,10 +535,11 @@ HERESQL; $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) { @@ -703,26 +704,28 @@ HERESQL; // 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 + 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 @@ -732,7 +735,20 @@ SELECT case_status.label AS case_status, status_id, civicrm_case_type.title AS c 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 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()) { @@ -1204,29 +1220,53 @@ SELECT case_status.label AS case_status, status_id, civicrm_case_type.title AS c $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 = << 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()) { @@ -1244,7 +1284,7 @@ SELECT case_status.label AS case_status, status_id, civicrm_case_type.title AS c '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; @@ -1848,16 +1888,27 @@ SELECT case_status.label AS case_status, status_id, civicrm_case_type.title AS c $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'), ); @@ -3214,4 +3265,58 @@ WHERE id IN (' . implode(',', $copiedActivityIds) . ')'; 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'] = 'a_b'; + } + // 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'] = 'b_a'; + } + } + $caseRoles[$roleDetails['id']] = $roleDetails; + } + } + return $caseRoles; + } + } + } diff --git a/CRM/Case/BAO/Query.php b/CRM/Case/BAO/Query.php index e5bf54125e..321118bf96 100644 --- a/CRM/Case/BAO/Query.php +++ b/CRM/Case/BAO/Query.php @@ -110,7 +110,7 @@ class CRM_Case_BAO_Query extends CRM_Core_BAO_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; @@ -296,7 +296,7 @@ class CRM_Case_BAO_Query extends CRM_Core_BAO_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; } @@ -434,7 +434,6 @@ class CRM_Case_BAO_Query extends CRM_Core_BAO_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; @@ -549,7 +548,7 @@ class CRM_Case_BAO_Query extends CRM_Core_BAO_Query { 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': diff --git a/CRM/Case/Form/AddToCaseAsRole.php b/CRM/Case/Form/AddToCaseAsRole.php index 20be94a95a..f2809047e3 100644 --- a/CRM/Case/Form/AddToCaseAsRole.php +++ b/CRM/Case/Form/AddToCaseAsRole.php @@ -68,15 +68,23 @@ class CRM_Case_Form_AddToCaseAsRole extends CRM_Contact_Form_Task { $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', diff --git a/CRM/Case/Form/CaseView.php b/CRM/Case/Form/CaseView.php index fdf587ca58..2f9eb82a0e 100644 --- a/CRM/Case/Form/CaseView.php +++ b/CRM/Case/Form/CaseView.php @@ -289,7 +289,7 @@ class CRM_Case_Form_CaseView extends CRM_Core_Form { 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; } } diff --git a/CRM/Case/Info.php b/CRM/Case/Info.php index 413385c55d..f7f0e0cd95 100644 --- a/CRM/Case/Info.php +++ b/CRM/Case/Info.php @@ -145,7 +145,7 @@ class CRM_Case_Info extends CRM_Core_Component_Info { 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}); + ->getRelationshipReferenceCount($dao->label_a_b); if ($count > 0) { $result[] = [ 'name' => 'casetypexml:relationships', diff --git a/CRM/Case/ManagedEntities.php b/CRM/Case/ManagedEntities.php index 461b51f5da..d3d33a0278 100644 --- a/CRM/Case/ManagedEntities.php +++ b/CRM/Case/ManagedEntities.php @@ -112,7 +112,12 @@ class CRM_Case_ManagedEntities { if (!isset(Civi::$statics[__CLASS__]['reltypes'])) { $relationshipInfo = CRM_Core_PseudoConstant::relationshipType('label', TRUE, NULL); - Civi::$statics[__CLASS__]['reltypes'] = CRM_Utils_Array::collect(CRM_Case_XMLProcessor::REL_TYPE_CNAME, $relationshipInfo); + foreach ($relationshipInfo as $id => $relTypeDetails) { + Civi::$statics[__CLASS__]['reltypes']["{$id}_a_b"] = $relTypeDetails['label_a_b']; + if ($relTypeDetails['label_a_b'] != $relTypeDetails['label_b_a']) { + Civi::$statics[__CLASS__]['reltypes']["{$id}_b_a"] = $relTypeDetails['label_b_a']; + } + } } $validRelTypes = Civi::$statics[__CLASS__]['reltypes']; diff --git a/CRM/Case/XMLProcessor.php b/CRM/Case/XMLProcessor.php index 863ea68ff5..f118d4c203 100644 --- a/CRM/Case/XMLProcessor.php +++ b/CRM/Case/XMLProcessor.php @@ -52,16 +52,6 @@ class CRM_Case_XMLProcessor { */ public static $relationshipTypes = NULL; - /** - * Relationship-types have four name fields (name_a_b, name_b_a, label_a_b, - * label_b_a), but CiviCase XML refers to reltypes by a single name. - * REL_TYPE_CNAME identifies the canonical name field as used by CiviCase XML. - * - * This appears to be "label_b_a", but IMHO "name_b_a" would be more - * sensible. - */ - const REL_TYPE_CNAME = 'label_b_a'; - /** * @param $caseType * @@ -119,7 +109,10 @@ class CRM_Case_XMLProcessor { self::$relationshipTypes = []; foreach ($relationshipInfo as $id => $info) { - self::$relationshipTypes[$id] = $info[CRM_Case_XMLProcessor::REL_TYPE_CNAME]; + self::$relationshipTypes[$id . '_b_a'] = $info['label_b_a']; + if ($info['label_b_a'] !== $info['label_a_b']) { + self::$relationshipTypes[$id . '_a_b'] = $info['label_a_b']; + } } } diff --git a/CRM/Case/XMLProcessor/Process.php b/CRM/Case/XMLProcessor/Process.php index b83e11cce6..03501e993e 100644 --- a/CRM/Case/XMLProcessor/Process.php +++ b/CRM/Case/XMLProcessor/Process.php @@ -214,10 +214,10 @@ class CRM_Case_XMLProcessor_Process extends CRM_Case_XMLProcessor { */ public function createRelationships($relationshipTypeName, &$params) { $relationshipTypes = &$this->allRelationshipTypes(); - // get the relationship id - $relationshipTypeID = array_search($relationshipTypeName, $relationshipTypes); + // get the relationship + $relationshipType = array_search($relationshipTypeName, $relationshipTypes); - if ($relationshipTypeID === FALSE) { + if ($relationshipType === FALSE) { $docLink = CRM_Utils_System::docURL2("user/case-management/set-up"); CRM_Core_Error::fatal(ts('Relationship type %1, found in case configuration file, is not present in the database %2', [1 => $relationshipTypeName, 2 => $docLink] @@ -232,15 +232,22 @@ class CRM_Case_XMLProcessor_Process extends CRM_Case_XMLProcessor { foreach ($client as $key => $clientId) { $relationshipParams = [ - 'relationship_type_id' => $relationshipTypeID, - 'contact_id_a' => $clientId, - 'contact_id_b' => $params['creatorID'], + 'relationship_type_id' => substr($relationshipType, 0, -4), 'is_active' => 1, 'case_id' => $params['caseID'], 'start_date' => date("Ymd"), 'end_date' => CRM_Utils_Array::value('relationship_end_date', $params), ]; + if (substr($relationshipType, -4) == '_b_a') { + $relationshipParams['contact_id_b'] = $clientId; + $relationshipParams['contact_id_a'] = $params['creatorID']; + } + if (substr($relationshipType, -4) == '_a_b') { + $relationshipParams['contact_id_a'] = $clientId; + $relationshipParams['contact_id_b'] = $params['creatorID']; + } + if (!$this->createRelationship($relationshipParams)) { CRM_Core_Error::fatal(); return FALSE; diff --git a/CRM/Report/Form/Case/Summary.php b/CRM/Report/Form/Case/Summary.php index 1db23629ce..286fe3b233 100644 --- a/CRM/Report/Form/Case/Summary.php +++ b/CRM/Report/Form/Case/Summary.php @@ -229,6 +229,9 @@ class CRM_Report_Form_Case_Summary extends CRM_Report_Form { 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}"; } + elseif ($tableName == 'civicrm_relationship_type') { + $select[] = " IF(contact_civireport.id = relationship_civireport.contact_id_a, relationship_type_civireport.label_b_a, relationship_type_civireport.label_a_b) as civicrm_relationship_type_label_b_a"; + } else { $select[] = "{$field['dbAlias']} as {$tableName}_{$fieldName}"; } @@ -290,7 +293,7 @@ class CRM_Report_Form_Case_Summary extends CRM_Report_Form { if ($this->_relField) { $this->_from = " FROM civicrm_contact $c -inner join civicrm_relationship $cr on {$c}.id = ${cr}.contact_id_b +inner join civicrm_relationship $cr on {$c}.id = ${cr}.contact_id_b OR {$c}.id = ${cr}.contact_id_a 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 @@ -308,6 +311,9 @@ inner join civicrm_contact $c2 on ${c2}.id=${ccc}.contact_id public function where() { $clauses = []; + if (!empty($this->_params['fields']['label_b_a']) && $this->_params['fields']['label_b_a'] == 1) { + $clauses[] = 'contact_civireport.sort_name != c2_civireport.sort_name'; + } $this->_having = ''; foreach ($this->_columns as $tableName => $table) { if (array_key_exists('filters', $table)) { diff --git a/ang/crmCaseType.ang.php b/ang/crmCaseType.ang.php index 21596810d4..c71e9c6678 100644 --- a/ang/crmCaseType.ang.php +++ b/ang/crmCaseType.ang.php @@ -5,12 +5,6 @@ // ODDITY: This only loads if CiviCase is active. -CRM_Core_Resources::singleton()->addSetting([ - 'crmCaseType' => [ - 'REL_TYPE_CNAME' => CRM_Case_XMLProcessor::REL_TYPE_CNAME, - ], -]); - return [ 'ext' => 'civicrm', 'js' => ['ang/crmCaseType.js'], diff --git a/ang/crmCaseType.js b/ang/crmCaseType.js index ee2344ece8..41f28286a8 100644 --- a/ang/crmCaseType.js +++ b/ang/crmCaseType.js @@ -74,11 +74,22 @@ limit: 0 } }]; - reqs.relTypes = ['RelationshipType', 'get', { + reqs.relTypes = ['Relationship', 'getoptions', { sequential: 1, + field: 'relationship_type_id', + context: 'create', + is_active: 1, + options: { + limit: 0 + } + }]; + reqs.relTypesForm = ['Relationship', 'getoptions', { + sequential: 1, + field: 'relationship_type_id', + context: 'create', + isForm: 1, is_active: 1, options: { - sort: CRM.crmCaseType.REL_TYPE_CNAME, limit: 0 } }]; @@ -238,11 +249,9 @@ }); crmCaseType.controller('CaseTypeCtrl', function($scope, crmApi, apiCalls, crmUiHelp) { - var REL_TYPE_CNAME, defaultAssigneeDefaultValue, ts; + var defaultAssigneeDefaultValue, ts; (function init () { - // CRM_Case_XMLProcessor::REL_TYPE_CNAME - REL_TYPE_CNAME = CRM.crmCaseType.REL_TYPE_CNAME; ts = $scope.ts = CRM.ts(null); $scope.hs = crmUiHelp({file: 'CRM/Case/CaseType'}); @@ -264,36 +273,16 @@ $scope.activityTypeOptions = _.map(apiCalls.actTypes.values, formatActivityTypeOption); $scope.defaultAssigneeTypes = apiCalls.defaultAssigneeTypes.values; $scope.relationshipTypeOptions = _.map(apiCalls.relTypes.values, function(type) { - return {id: type[REL_TYPE_CNAME], text: type.label_b_a}; + return {id: type.key, text: type.value}; + }); + $scope.defaultRelationshipTypeOptions = _.map(apiCalls.relTypesForm.values, function(type) { + return {value: type.key, label: type.value}; }); - $scope.defaultRelationshipTypeOptions = getDefaultRelationshipTypeOptions(); // stores the default assignee values indexed by their option name: $scope.defaultAssigneeTypeValues = _.chain($scope.defaultAssigneeTypes) .indexBy('name').mapValues('value').value(); } - /// Returns the default relationship type options. If the relationship is - /// bidirectional (Ex: Spouse of) it adds a single option otherwise it adds - /// two options representing the relationship type directions - /// (Ex: Employee of, Employer is) - function getDefaultRelationshipTypeOptions() { - return _.transform(apiCalls.relTypes.values, function(result, relType) { - var isBidirectionalRelationship = relType.label_a_b === relType.label_b_a; - - result.push({ - label: relType.label_b_a, - value: relType.id + '_b_a' - }); - - if (!isBidirectionalRelationship) { - result.push({ - label: relType.label_a_b, - value: relType.id + '_a_b' - }); - } - }, []); - } - /// initializes the case type object function initCaseType() { var isNewCaseType = !apiCalls.caseType; @@ -434,11 +423,15 @@ if (_.where($scope.relationshipTypeOptions, {id: roleName}).length) { roles.push({name: roleName}); } else { - CRM.loadForm(CRM.url('civicrm/admin/reltype', {action: 'add', reset: 1, label_a_b: roleName, label_b_a: roleName})) + CRM.loadForm(CRM.url('civicrm/admin/reltype', {action: 'add', reset: 1, label_a_b: roleName})) .on('crmFormSuccess', function(e, data) { var newType = _.values(data.relationshipType)[0]; - roles.push({name: newType[REL_TYPE_CNAME]}); - $scope.relationshipTypeOptions.push({id: newType[REL_TYPE_CNAME], text: newType.label_b_a}); + roles.push({name: newType.label_a_b}); + // Assume that the case role should be A-B but add both directions as options. + $scope.relationshipTypeOptions.push({id: newType.label_a_b, text: newType.label_a_b}); + if (newType.label_a_b != newType.label_b_a) { + $scope.relationshipTypeOptions.push({id: newType.label_b_a, text: newType.label_b_a}); + } $scope.$digest(); }); } diff --git a/tests/karma/unit/crmCaseTypeSpec.js b/tests/karma/unit/crmCaseTypeSpec.js index 3369579c19..4b0a221346 100644 --- a/tests/karma/unit/crmCaseTypeSpec.js +++ b/tests/karma/unit/crmCaseTypeSpec.js @@ -18,10 +18,6 @@ describe('crmCaseType', function() { CRM.resourceUrls = { 'civicrm': '' }; - // CRM_Case_XMLProcessor::REL_TYPE_CNAME - CRM.crmCaseType = { - 'REL_TYPE_CNAME': 'label_b_a' - }; module('crmCaseType'); module('crmJsonComparator'); inject(function(crmJsonComparator) { @@ -203,6 +199,30 @@ describe('crmCaseType', function() { } ] }, + relTypesForm: { + values: [ + { + "key": "14_b_a", + "value": "Benefits Specialist" + }, + { + "key": "14_a_b", + "value": "Benefits Specialist is" + }, + { + "key": "9_b_a", + "value": "Case Coordinator" + }, + { + "key": "9_a_b", + "value": "Case Coordinator is" + }, + { + "key": "2_b_a", + "value": "Spouse of" + } + ] + }, caseType: { "id": "1", "name": "housing_support", diff --git a/tests/phpunit/CRM/Case/BAO/CaseTypeForkTest.php b/tests/phpunit/CRM/Case/BAO/CaseTypeForkTest.php index caa23c93d3..09ca91dbe6 100644 --- a/tests/phpunit/CRM/Case/BAO/CaseTypeForkTest.php +++ b/tests/phpunit/CRM/Case/BAO/CaseTypeForkTest.php @@ -39,7 +39,7 @@ class CRM_Case_BAO_CaseTypeForkTest extends CiviCaseTestCase { ]); //Check if manager is correctly retrieved from xml processor. $xmlProcessor = new CRM_Case_XMLProcessor_Process(); - $this->assertEquals($relTypeID, $xmlProcessor->getCaseManagerRoleId('ForkableCaseType')); + $this->assertEquals($relTypeID . '_b_a', $xmlProcessor->getCaseManagerRoleId('ForkableCaseType')); } /** -- 2.25.1