From 06f210644508d79b1d9c9e2fa4c2abf35027468b Mon Sep 17 00:00:00 2001 From: Tunbola Ogunwande Date: Thu, 7 Feb 2019 15:34:16 +0100 Subject: [PATCH] dev/core#641: Implementing Case Activity Assignment Restriction functionality --- CRM/Case/BAO/CaseType.php | 21 ++++++ CRM/Case/Form/Activity.php | 105 +++++++++++++++++++++++++-- ang/crmCaseType.js | 7 ++ ang/crmCaseType/caseTypeDetails.html | 17 +++++ 4 files changed, 143 insertions(+), 7 deletions(-) diff --git a/CRM/Case/BAO/CaseType.php b/CRM/Case/BAO/CaseType.php index ec5210d13d..aa65688f87 100644 --- a/CRM/Case/BAO/CaseType.php +++ b/CRM/Case/BAO/CaseType.php @@ -190,7 +190,20 @@ class CRM_Case_BAO_CaseType extends CRM_Case_DAO_CaseType { $xmlFile .= "\n"; } + if (array_key_exists('restrictActivityAsgmtToCmsUser', $definition)) { + $xmlFile .= "" . $definition['restrictActivityAsgmtToCmsUser'] . "\n"; + } + + if (!empty($definition['activityAsgmtGrps'])) { + $xmlFile .= "\n"; + foreach ($definition['activityAsgmtGrps'] as $value) { + $xmlFile .= "$value\n"; + } + $xmlFile .= "\n"; + } + $xmlFile .= ''; + return $xmlFile; } @@ -226,6 +239,14 @@ class CRM_Case_BAO_CaseType extends CRM_Case_DAO_CaseType { $definition['forkable'] = (int) $xml->forkable; } + if (isset($xml->RestrictActivityAsgmtToCmsUser)) { + $definition['restrictActivityAsgmtToCmsUser'] = (int) $xml->RestrictActivityAsgmtToCmsUser; + } + + if (isset($xml->ActivityAsgmtGrps)) { + $definition['activityAsgmtGrps'] = (array) $xml->ActivityAsgmtGrps->Group; + } + // set activity types if (isset($xml->ActivityTypes)) { $definition['activityTypes'] = array(); diff --git a/CRM/Case/Form/Activity.php b/CRM/Case/Form/Activity.php index 7a7b3b92b6..9e2dda642d 100644 --- a/CRM/Case/Form/Activity.php +++ b/CRM/Case/Form/Activity.php @@ -37,16 +37,16 @@ class CRM_Case_Form_Activity extends CRM_Activity_Form_Activity { /** - * The default variable defined. + * Cases this activity belongs to. * - * @var int + * @var []int */ public $_caseId; /** * The default case type variable defined. * - * @var int + * @var []int */ public $_caseType; @@ -57,12 +57,20 @@ class CRM_Case_Form_Activity extends CRM_Activity_Form_Activity { */ public $_relatedContacts; + /** + * The case type definition column info + * for the caseId; + * + * @var array + */ + public $_caseTypeDefinition; + /** * Build the form object. */ public function preProcess() { - $caseIds = CRM_Utils_Request::retrieve('caseid', 'String', $this); - $this->_caseId = explode(',', $caseIds); + $caseIds = CRM_Utils_Request::retrieve('caseid', 'CommaSeparatedIntegers', $this); + $this->_caseId = $caseIds ? explode(',', $caseIds) : []; $this->_context = CRM_Utils_Request::retrieve('context', 'Alphanumeric', $this); if (!$this->_context) { $this->_context = 'caseActivity'; @@ -76,7 +84,7 @@ class CRM_Case_Form_Activity extends CRM_Activity_Form_Activity { $this->assign('scheduleStatusId', $scheduleStatusId); if (!$this->_caseId && $this->_activityId) { - $this->_caseId = CRM_Core_DAO::getFieldValue('CRM_Case_DAO_CaseActivity', $this->_activityId, + $this->_caseId = (array) CRM_Core_DAO::getFieldValue('CRM_Case_DAO_CaseActivity', $this->_activityId, 'case_id', 'activity_id' ); } @@ -124,6 +132,8 @@ class CRM_Case_Form_Activity extends CRM_Activity_Form_Activity { } $this->assign('caseType', $this->_caseType); + $this->_caseTypeDefinition = $this->getCaseTypeDefinition(); + $xmlProcessorProcess = new CRM_Case_XMLProcessor_Process(); $isMultiClient = $xmlProcessorProcess->getAllowMultipleCaseClients(); $this->assign('multiClient', $isMultiClient); @@ -248,10 +258,31 @@ class CRM_Case_Form_Activity extends CRM_Activity_Form_Activity { $this->_fields['source_contact_id']['label'] = ts('Reported By'); unset($this->_fields['status_id']['attributes']['required']); + if ($this->restrictAssignmentByUserAccount()) { + $assigneeParameters['uf_user'] = 1; + } + + $activityAssignmentGroups = $this->getActivityAssignmentGroups(); + if (!empty($activityAssignmentGroups)) { + $assigneeParameters['group'] = ['IN' => $activityAssignmentGroups]; + } + + if (!empty($assigneeParameters)) { + $this->_fields['assignee_contact_id']['attributes']['api']['params'] + = array_merge($this->_fields['assignee_contact_id']['attributes']['api']['params'], $assigneeParameters); + + $this->_fields['followup_assignee_contact_id']['attributes']['api']['params'] + = array_merge($this->_fields['followup_assignee_contact_id']['attributes']['api']['params'], $assigneeParameters); + + //Disallow creating a contact from the assignee field UI. + $this->_fields['assignee_contact_id']['attributes']['create'] = FALSE; + $this->_fields['followup_assignee_contact_id']['attributes']['create'] = FALSE; + } + if ($this->_caseType) { $xmlProcessor = new CRM_Case_XMLProcessor_Process(); $aTypes = array(); - foreach ($this->_caseType as $key => $val) { + foreach (array_unique($this->_caseType) as $val) { $activityTypes = $xmlProcessor->get($val, 'ActivityTypes', TRUE); $aTypes = $aTypes + $activityTypes; } @@ -651,4 +682,64 @@ class CRM_Case_Form_Activity extends CRM_Activity_Form_Activity { } } + /** + * Returns the groups that contacts must belong to in order to be assigned + * an activity for this case. It returns an empty array if no groups are found for + * the case type linked to the caseId. + * + * @return array + */ + private function getActivityAssignmentGroups() { + if (!$this->_caseTypeDefinition) { + return []; + } + + $assignmentGroups = []; + foreach ($this->_caseTypeDefinition as $caseId => $definition) { + if (!empty($definition['activityAsgmtGrps'])) { + $assignmentGroups = array_merge($assignmentGroups, $definition['activityAsgmtGrps']); + } + } + + return $assignmentGroups; + } + + /** + * Returns whether contacts must have a user account in order to be + * assigned an activity for this case. + * + * @return bool + */ + private function restrictAssignmentByUserAccount() { + if (!$this->_caseTypeDefinition) { + return FALSE; + } + + foreach ($this->_caseTypeDefinition as $caseId => $definition) { + if (!empty($definition['restrictActivityAsgmtToCmsUser'])) { + return TRUE; + } + } + + return FALSE; + } + + /** + * Returns the case type definition column value for the case type linked to the caseId. + * + * @return array + */ + private function getCaseTypeDefinition() { + if (!$this->_caseId) { + return []; + } + + $definitions = civicrm_api3('CaseType', 'get', [ + 'return' => ['name', 'definition'], + 'name' => ['IN' => array_unique($this->_caseType)], + ]); + + return array_column($definitions['values'], 'definition', 'name'); + } + } diff --git a/ang/crmCaseType.js b/ang/crmCaseType.js index 994c9fb1f0..ab8e2d4c12 100644 --- a/ang/crmCaseType.js +++ b/ang/crmCaseType.js @@ -312,6 +312,8 @@ $scope.caseType.definition.caseRoles = $scope.caseType.definition.caseRoles || []; $scope.caseType.definition.statuses = $scope.caseType.definition.statuses || []; $scope.caseType.definition.timelineActivityTypes = $scope.caseType.definition.timelineActivityTypes || []; + $scope.caseType.definition.restrictActivityAsgmtToCmsUser = $scope.caseType.definition.restrictActivityAsgmtToCmsUser || 0; + $scope.caseType.definition.activityAsgmtGrps = $scope.caseType.definition.activityAsgmtGrps || []; _.each($scope.caseType.definition.activitySets, function (set) { _.each(set.activityTypes, function (type, name) { @@ -525,6 +527,11 @@ }); // Ignore if ALL or NONE selected $scope.caseType.definition.statuses = selectedStatuses.length == _.size($scope.selectedStatuses) ? [] : selectedStatuses; + + if ($scope.caseType.definition.activityAsgmtGrps) { + $scope.caseType.definition.activityAsgmtGrps = $scope.caseType.definition.activityAsgmtGrps.toString().split(","); + } + var result = crmApi('CaseType', 'create', $scope.caseType, true); result.then(function(data) { if (data.is_error === 0 || data.is_error == '0') { diff --git a/ang/crmCaseType/caseTypeDetails.html b/ang/crmCaseType/caseTypeDetails.html index 9b121d0f4d..99f91f3807 100644 --- a/ang/crmCaseType/caseTypeDetails.html +++ b/ang/crmCaseType/caseTypeDetails.html @@ -41,5 +41,22 @@ The original form used table layout; don't know if we have an alternative, CSS-b
+
+ +
+
+ +
-- 2.25.1