From 9c7ffe36390ed579a925096e068446d9eac648b4 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Mon, 21 Oct 2019 17:45:51 -0400 Subject: [PATCH 1/3] Option to limit case roles to certain groups --- CRM/Case/BAO/CaseType.php | 8 +++-- CRM/Case/Form/CaseView.php | 22 +++++++++++- ang/crmCaseType/rolesTable.html | 5 +++ templates/CRM/Case/Form/CaseView.js | 52 ++++++++++++++++------------- 4 files changed, 60 insertions(+), 27 deletions(-) diff --git a/CRM/Case/BAO/CaseType.php b/CRM/Case/BAO/CaseType.php index deaf69ab8225..e8466a7f59bb 100644 --- a/CRM/Case/BAO/CaseType.php +++ b/CRM/Case/BAO/CaseType.php @@ -167,7 +167,7 @@ public static function convertDefinitionToXML($name, $definition) { foreach ($definition['caseRoles'] as $values) { $xmlFile .= "\n"; foreach ($values as $key => $value) { - $xmlFile .= "<{$key}>" . self::encodeXmlString($value) . "\n"; + $xmlFile .= "<{$key}>" . (is_array($value) ? implode(',', array_map(['\CRM_Case_BAO_CaseType', 'encodeXmlString'], $value)) : self::encodeXmlString($value)) . "\n"; } $xmlFile .= "\n"; } @@ -284,7 +284,11 @@ public static function convertXmlToDefinition($xml) { if (isset($xml->CaseRoles)) { $definition['caseRoles'] = []; foreach ($xml->CaseRoles->RelationshipType as $caseRoleXml) { - $definition['caseRoles'][] = json_decode(json_encode($caseRoleXml), TRUE); + $caseRole = json_decode(json_encode($caseRoleXml), TRUE); + if (!empty($caseRole['groups'])) { + $caseRole['groups'] = explode(',', $caseRole['groups']); + } + $definition['caseRoles'][] = $caseRole; } } diff --git a/CRM/Case/Form/CaseView.php b/CRM/Case/Form/CaseView.php index 811b2b68f1cd..d3dae3609d75 100644 --- a/CRM/Case/Form/CaseView.php +++ b/CRM/Case/Form/CaseView.php @@ -168,11 +168,31 @@ public function buildQuickForm() { } $allowedRelationshipTypes = CRM_Contact_BAO_Relationship::getContactRelationshipType($this->_contactID); + $relationshipTypeMetadata = CRM_Contact_Form_Relationship::getRelationshipTypeMetadata($allowedRelationshipTypes); + + $caseTypeDefinition = civicrm_api3('CaseType', 'getsingle', ['name' => $this->_caseType])['definition']; + + foreach ($caseTypeDefinition['caseRoles'] as $role) { + if (!empty($role['groups'])) { + $relationshipType = civicrm_api3('RelationshipType', 'get', [ + 'sequential' => 1, + 'name_a_b' => $role['name'], + 'name_b_a' => $role['name'], + 'options' => ['limit' => 1, 'or' => [["name_a_b", "name_b_a"]]], + ]); + if (($relationshipType['values'][0]['name_a_b'] ?? NULL) === $role['name']) { + $relationshipTypeMetadata[$relationshipType['id']]['group_a'] = $role['groups']; + } + if (($relationshipType['values'][0]['name_b_a'] ?? NULL) === $role['name']) { + $relationshipTypeMetadata[$relationshipType['id']]['group_b'] = $role['groups']; + } + } + } CRM_Core_Resources::singleton() ->addScriptFile('civicrm', 'js/crm.livePage.js', 1, 'html-header') ->addScriptFile('civicrm', 'templates/CRM/Case/Form/CaseView.js', 2, 'html-header') - ->addVars('relationshipTypes', CRM_Contact_Form_Relationship::getRelationshipTypeMetadata($allowedRelationshipTypes)); + ->addVars('relationshipTypes', $relationshipTypeMetadata); $xmlProcessor = new CRM_Case_XMLProcessor_Process(); $caseRoles = $xmlProcessor->get($this->_caseType, 'CaseRoles'); diff --git a/ang/crmCaseType/rolesTable.html b/ang/crmCaseType/rolesTable.html index 8af3b488c4f9..ed8983db0c42 100644 --- a/ang/crmCaseType/rolesTable.html +++ b/ang/crmCaseType/rolesTable.html @@ -8,6 +8,7 @@ {{ts('Display Label')}} {{ts('Assign to Creator')}} {{ts('Is Manager')}} + {{ts('Restrict to Groups')}} @@ -17,6 +18,10 @@ {{relType.displayLabel}} + diff --git a/templates/CRM/Case/Form/CaseView.js b/templates/CRM/Case/Form/CaseView.js index 06fdec4b0000..192a52b86707 100644 --- a/templates/CRM/Case/Form/CaseView.js +++ b/templates/CRM/Case/Form/CaseView.js @@ -73,29 +73,12 @@ var val = $(this).val(); $contactField.val('').change().prop('disabled', !val); if (val) { - var - pieces = val.split('_'), - rType = pieces[0], - target = pieces[2], // b or a - contact_type = CRM.vars.relationshipTypes[rType]['contact_type_' + target], - contact_sub_type = CRM.vars.relationshipTypes[rType]['contact_sub_type_' + target], - api = {params: {}}; - if (contact_type) { - api.params.contact_type = contact_type; - } - if (contact_sub_type) { - api.params.contact_sub_type = contact_sub_type; - } - $contactField - .data('api-params', api) - .data('user-filter', {}) - .attr('placeholder', CRM.vars.relationshipTypes[rType]['placeholder_' + target]) - .change(); + prepareRelationshipField(val, $contactField); } }) .val('') .change(); - $contactField.val('').crmEntityRef({create: true, api: {params: {contact_type: 'Individual'}}}); + $contactField.val('').crmEntityRef(); }, post: function(data) { var contactID = $('[name=add_role_contact_id]', this).val(), @@ -114,11 +97,7 @@ }, '#editCaseRoleDialog': { pre: function(data) { - var params = {create: true}; - if (data.contact_type) { - params.api = {params: {contact_type: data.contact_type}}; - } - $('[name=edit_role_contact_id]', this).val('').crmEntityRef(params); + prepareRelationshipField(data.rel_type, $('[name=edit_role_contact_id]', this)); }, post: function(data) { data.rel_contact = $('[name=edit_role_contact_id]', this).val(); @@ -164,6 +143,31 @@ }, detached = {}; + function prepareRelationshipField(relType, $contactField) { + var + pieces = relType.split('_'), + rType = pieces[0], + target = pieces[2], // b or a + relationshipType = CRM.vars.relationshipTypes[rType], + api = {params: {}}; + if (relationshipType['contact_type_' + target]) { + api.params.contact_type = relationshipType['contact_type_' + target]; + } + if (relationshipType['contact_sub_type_' + target]) { + api.params.contact_sub_type = relationshipType['contact_sub_type_' + target]; + } + if (relationshipType['group_' + target]) { + api.params.group = {IN: relationshipType['group_' + target]}; + } + $contactField + .data('create-links', !relationshipType['group_' + target]) + .data('api-params', api) + .data('user-filter', {}) + .attr('placeholder', relationshipType['placeholder_' + target]) + .change() + .crmEntityRef(); + } + function detachMiniForms() { detached = {}; $.each(miniForms, function(selector) { From 85148081be76b6f0eae62f3484364f9aa149b08f Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Mon, 21 Oct 2019 17:54:44 -0400 Subject: [PATCH 2/3] Change caseType activityAsgmtGrps to store group name instead of id --- CRM/Case/BAO/CaseType.php | 6 ++++++ ang/crmCaseType/caseTypeDetails.html | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CRM/Case/BAO/CaseType.php b/CRM/Case/BAO/CaseType.php index e8466a7f59bb..415a079a1420 100644 --- a/CRM/Case/BAO/CaseType.php +++ b/CRM/Case/BAO/CaseType.php @@ -234,6 +234,12 @@ public static function convertXmlToDefinition($xml) { if (isset($xml->ActivityAsgmtGrps)) { $definition['activityAsgmtGrps'] = (array) $xml->ActivityAsgmtGrps->Group; + // Backwards compat - convert group ids to group names if ids are supplied + if (array_filter($definition['activityAsgmtGrps'], ['\CRM_Utils_Rule', 'integer']) === $definition['activityAsgmtGrps']) { + foreach ($definition['activityAsgmtGrps'] as $idx => $group) { + $definition['activityAsgmtGrps'][$idx] = CRM_Core_DAO::getFieldValue('CRM_Contact_BAO_Group', $group); + } + } } // set activity types diff --git a/ang/crmCaseType/caseTypeDetails.html b/ang/crmCaseType/caseTypeDetails.html index d11cc913c306..2bc30182eaaf 100644 --- a/ang/crmCaseType/caseTypeDetails.html +++ b/ang/crmCaseType/caseTypeDetails.html @@ -48,7 +48,7 @@ From c4bfbde35f7848645ada6cb6f2066f2c2b639606 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Sat, 11 Jan 2020 13:21:24 -0500 Subject: [PATCH 3/3] Add caseType test --- CRM/Case/BAO/CaseType.php | 4 ++-- tests/phpunit/api/v3/CaseTypeTest.php | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/CRM/Case/BAO/CaseType.php b/CRM/Case/BAO/CaseType.php index 415a079a1420..a65deb470bdf 100644 --- a/CRM/Case/BAO/CaseType.php +++ b/CRM/Case/BAO/CaseType.php @@ -167,7 +167,7 @@ public static function convertDefinitionToXML($name, $definition) { foreach ($definition['caseRoles'] as $values) { $xmlFile .= "\n"; foreach ($values as $key => $value) { - $xmlFile .= "<{$key}>" . (is_array($value) ? implode(',', array_map(['\CRM_Case_BAO_CaseType', 'encodeXmlString'], $value)) : self::encodeXmlString($value)) . "\n"; + $xmlFile .= "<{$key}>" . ($key == 'groups' ? implode(',', array_map(['\CRM_Case_BAO_CaseType', 'encodeXmlString'], (array) $value)) : self::encodeXmlString($value)) . "\n"; } $xmlFile .= "\n"; } @@ -180,7 +180,7 @@ public static function convertDefinitionToXML($name, $definition) { if (!empty($definition['activityAsgmtGrps'])) { $xmlFile .= "\n"; - foreach ($definition['activityAsgmtGrps'] as $value) { + foreach ((array) $definition['activityAsgmtGrps'] as $value) { $xmlFile .= "$value\n"; } $xmlFile .= "\n"; diff --git a/tests/phpunit/api/v3/CaseTypeTest.php b/tests/phpunit/api/v3/CaseTypeTest.php index 22476c745eac..60392857617f 100644 --- a/tests/phpunit/api/v3/CaseTypeTest.php +++ b/tests/phpunit/api/v3/CaseTypeTest.php @@ -241,4 +241,31 @@ public function testCaseStatusByCaseType() { $this->assertEquals($template['definition']['statuses'], array_values($result['values'])); } + public function testDefinitionGroups() { + $gid1 = $this->groupCreate(['name' => 'testDefinitionGroups1', 'title' => 'testDefinitionGroups1']); + $gid2 = $this->groupCreate(['name' => 'testDefinitionGroups2', 'title' => 'testDefinitionGroups2']); + $def = $this->fixtures['Application_with_Definition']; + $def['definition']['caseRoles'][] = [ + 'name' => 'Second role', + 'groups' => ['testDefinitionGroups1', 'testDefinitionGroups2'], + ]; + $def['definition']['caseRoles'][] = [ + 'name' => 'Third role', + 'groups' => 'testDefinitionGroups2', + ]; + $def['definition']['activityAsgmtGrps'] = $gid1; + $createCaseType = $this->callAPISuccess('CaseType', 'create', $def); + $caseType = $this->callAPISuccess('CaseType', 'getsingle', ['id' => $createCaseType['id']]); + + // Assert the group id got converted to array with name not id + $this->assertEquals(['testDefinitionGroups1'], $caseType['definition']['activityAsgmtGrps']); + + // Assert multiple groups are stored + $this->assertEquals(['testDefinitionGroups1', 'testDefinitionGroups2'], $caseType['definition']['caseRoles'][1]['groups']); + + // Assert single group got converted to array + $this->assertEquals(['testDefinitionGroups2'], $caseType['definition']['caseRoles'][2]['groups']); + + } + }