diff --git a/include/ajax.tasks.php b/include/ajax.tasks.php index c92d72f239483229153d969e26221191dca087ce..88b11bee010075c07b8293d260ec09f284569891 100644 --- a/include/ajax.tasks.php +++ b/include/ajax.tasks.php @@ -288,7 +288,9 @@ class TasksAjaxAPI extends AjaxController { Q::all(array( 'dept_access__dept__id__in' => $depts, Q::not(array('dept_access__dept__flags__hasbit' - => Dept::FLAG_ASSIGN_MEMBERS_ONLY)) + => Dept::FLAG_ASSIGN_MEMBERS_ONLY, + 'dept_access__dept__flags__hasbit' + => Dept::FLAG_ASSIGN_PRIMARY_ONLY)) )) ))); } diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index 51c4e66973e90b94432b974ff732426548b7120e..643d8b4613ad80ee89da610c33843bca7b3d6610 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -735,7 +735,9 @@ function refer($tid, $target=null) { Q::all(array( 'dept_access__dept__id__in' => $depts, Q::not(array('dept_access__dept__flags__hasbit' - => Dept::FLAG_ASSIGN_MEMBERS_ONLY)) + => Dept::FLAG_ASSIGN_MEMBERS_ONLY, + 'dept_access__dept__flags__hasbit' + => Dept::FLAG_ASSIGN_PRIMARY_ONLY)) )) ))); } diff --git a/include/class.dept.php b/include/class.dept.php index 88cbcad9772e8236b253372ba9813b0532efeeac..7c9f92bfca05df65120fa59d52fd25a602aa03a7 100644 --- a/include/class.dept.php +++ b/include/class.dept.php @@ -70,6 +70,7 @@ implements TemplateVariable, Searchable { const FLAG_DISABLE_AUTO_CLAIM = 0x0002; const FLAG_ACTIVE = 0x0004; const FLAG_ARCHIVED = 0x0008; + const FLAG_ASSIGN_PRIMARY_ONLY = 0x0010; function asVar() { return $this->getName(); @@ -280,14 +281,27 @@ implements TemplateVariable, Searchable { return $this->_extended_members; } - // Get members eligible members only + // Get eligible members only function getAssignees() { - $members = clone $this->getAvailableMembers(); - // If restricted then filter to primary members ONLY! - if ($this->assignMembersOnly()) - $members->filter(array('dept_id' => $this->getId())); - return $members; + //this is for if all members is set + if (!$this->assignPrimaryOnly() && !$this->assignMembersOnly()) { + $members = Staff::objects()->filter(array( + 'onvacation' => 0, + 'isactive' => 1, + )); + + return Staff::nsort($members); + } + + //this gets just the members of the dept + $members = clone $this->getAvailableMembers(); + + //this gets just the primary members of the dept + if ($this->assignPrimaryOnly()) + $members->filter(array('dept_id' => $this->getId())); + + return Staff::nsort($members); } function getMembersForAlerts() { @@ -359,6 +373,23 @@ implements TemplateVariable, Searchable { return ($this->getSignature() && $this->isPublic()); } + //Check if an agent is eligible for assignment + function canAssign(Staff $assignee) { + //Primary members only + if ($this->assignPrimaryOnly() && !$this->isPrimaryMember($assignee)) + return false; + + //Extended members only + if ($this->assignMembersOnly() && !$this->isMember($assignee)) + return false; + + //Make sure agent is active & not on vacation + if (!$assignee->isActive() || $assignee->onVacation()) + return false; + + return true; + } + function getManagerId() { return $this->manager_id; } @@ -367,22 +398,24 @@ implements TemplateVariable, Searchable { return $this->manager; } - function isManager($staff) { - if (is_object($staff)) - $staff = $staff->getId(); + function isManager(Staff $staff) { + $staff = $staff->getId(); return ($this->getManagerId() && $this->getManagerId()==$staff); } - function isMember($staff) { - if (is_object($staff)) - $staff = $staff->getId(); + function isMember(Staff $staff) { + $staff = $staff->getId(); return $this->getMembers()->findFirst(array( 'staff_id' => $staff )); } + function isPrimaryMember(Staff $staff) { + return ($staff->getDeptId() == $this->getId()); + } + function isPublic() { return $this->ispublic; } @@ -403,6 +436,19 @@ implements TemplateVariable, Searchable { return $this->flags & self::FLAG_ASSIGN_MEMBERS_ONLY; } + function assignPrimaryOnly() { + return $this->flags & self::FLAG_ASSIGN_PRIMARY_ONLY; + } + + function getAssignmentFlag() { + if($this->flags & self::FLAG_ASSIGN_MEMBERS_ONLY) + return 'members'; + elseif($this->flags & self::FLAG_ASSIGN_PRIMARY_ONLY) + return 'primary'; + else + return 'all'; + } + function disableAutoClaim() { return $this->flags & self::FLAG_DISABLE_AUTO_CLAIM; } @@ -417,9 +463,10 @@ implements TemplateVariable, Searchable { foreach (static::$meta['joins'] as $k => $v) unset($ht[$k]); - $ht['assign_members_only'] = $this->assignMembersOnly(); $ht['disable_auto_claim'] = $this->disableAutoClaim(); $ht['status'] = $this->getStatus(); + $ht['assignment_flag'] = $this->getAssignmentFlag(); + return $ht; } @@ -732,6 +779,7 @@ implements TemplateVariable, Searchable { $this->group_membership = $vars['group_membership']; $this->ticket_auto_response = isset($vars['ticket_auto_response'])?$vars['ticket_auto_response']:1; $this->message_auto_response = isset($vars['message_auto_response'])?$vars['message_auto_response']:1; + $this->setFlag(self::FLAG_ASSIGN_MEMBERS_ONLY, isset($vars['assign_members_only'])); $this->setFlag(self::FLAG_DISABLE_AUTO_CLAIM, isset($vars['disable_auto_claim'])); @@ -755,6 +803,23 @@ implements TemplateVariable, Searchable { case 'archived': $this->setFlag(self::FLAG_ACTIVE, false); $this->setFlag(self::FLAG_ARCHIVED, true); + } + + $this->flags = 0; + $this->setFlag(self::FLAG_DISABLE_AUTO_CLAIM, isset($vars['disable_auto_claim'])); + + switch ($vars['assignment_flag']) { + case 'all': + $this->setFlag(self::FLAG_ASSIGN_MEMBERS_ONLY, false); + $this->setFlag(self::FLAG_ASSIGN_PRIMARY_ONLY, false); + break; + case 'members': + $this->setFlag(self::FLAG_ASSIGN_MEMBERS_ONLY, true); + $this->setFlag(self::FLAG_ASSIGN_PRIMARY_ONLY, false); + break; + case 'primary': + $this->setFlag(self::FLAG_ASSIGN_MEMBERS_ONLY, false); + $this->setFlag(self::FLAG_ASSIGN_PRIMARY_ONLY, true); break; } diff --git a/include/class.task.php b/include/class.task.php index 5e8ae0fe45c6af4d5fca52895d54e6eecd0f87f5..55f0152896da820a1897076c884596659bc462e4 100644 --- a/include/class.task.php +++ b/include/class.task.php @@ -648,7 +648,7 @@ class Task extends TaskModel implements RestrictedAccess, Threadable { $errors['err'] = __('Unknown assignee'); } elseif (!$assignee->isAvailable()) { $errors['err'] = __('Agent is unavailable for assignment'); - } elseif ($dept->assignMembersOnly() && !$dept->isMember($assignee)) { + } elseif (!$dept->canAssign($assignee)) { $errors['err'] = __('Permission denied'); } @@ -692,6 +692,7 @@ class Task extends TaskModel implements RestrictedAccess, Threadable { $evd = array(); $assignee = $form->getAssignee(); if ($assignee instanceof Staff) { + $dept = $this->getDept(); if ($this->getStaffId() == $assignee->getId()) { $errors['assignee'] = sprintf(__('%s already assigned to %s'), __('Task'), @@ -699,7 +700,10 @@ class Task extends TaskModel implements RestrictedAccess, Threadable { ); } elseif(!$assignee->isAvailable()) { $errors['assignee'] = __('Agent is unavailable for assignment'); - } else { + } elseif (!$dept->canAssign($assignee)) { + $errors['err'] = __('Permission denied'); + } + else { $this->staff_id = $assignee->getId(); if ($thisstaff && $thisstaff->getId() == $assignee->getId()) $evd['claim'] = true; diff --git a/include/class.ticket.php b/include/class.ticket.php index 604ead02f070d545bea570b5e7e11c958b895223..0855f1196c5395ea6f0964c0427a0d1a74f062b0 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -847,9 +847,10 @@ implements RestrictedAccess, Threadable, Searchable { $prompt = $assignee = ''; // Possible assignees - $assignees = array(); + $assignees = null; switch (strtolower($options['target'])) { case 'agents': + $assignees = array(); $dept = $this->getDept(); foreach ($dept->getAssignees() as $member) $assignees['s'.$member->getId()] = $member; @@ -859,6 +860,7 @@ implements RestrictedAccess, Threadable, Searchable { $prompt = __('Select an Agent'); break; case 'teams': + $assignees = array(); if (($teams = Team::getActiveTeams())) foreach ($teams as $id => $name) $assignees['t'.$id] = $name; @@ -874,7 +876,8 @@ implements RestrictedAccess, Threadable, Searchable { $source = array('assignee' => array($assignee)); $form = AssignmentForm::instantiate($source, $options); - if ($assignees) + + if (isset($assignees)) $form->setAssignees($assignees); if (($refer = $form->getField('refer'))) { @@ -2338,7 +2341,7 @@ implements RestrictedAccess, Threadable, Searchable { $errors['err'] = __('Unknown assignee'); } elseif (!$assignee->isAvailable()) { $errors['err'] = __('Agent is unavailable for assignment'); - } elseif ($dept->assignMembersOnly() && !$dept->isMember($assignee)) { + } elseif (!$dept->canAssign($assignee)) { $errors['err'] = __('Permission denied'); } @@ -2404,7 +2407,7 @@ implements RestrictedAccess, Threadable, Searchable { ); } elseif(!$assignee->isAvailable()) { $errors['assignee'] = __('Agent is unavailable for assignment'); - } elseif ($dept->assignMembersOnly() && !$dept->isMember($assignee)) { + } elseif (!$dept->canAssign($assignee)) { $errors['err'] = __('Permission denied'); } else { $refer = $this->staff ?: null; diff --git a/include/i18n/en_US/help/tips/staff.department.yaml b/include/i18n/en_US/help/tips/staff.department.yaml index aee25f97df04081c04a2639d49d08fb54f9d2ccf..96e348f6470924028c4e5c19540c8f94f875ddfc 100644 --- a/include/i18n/en_US/help/tips/staff.department.yaml +++ b/include/i18n/en_US/help/tips/staff.department.yaml @@ -77,10 +77,9 @@ group_membership: sandboxing: title: Ticket Assignment Restrictions content: > - Enable this to restrict ticket assignment to include only members - of this Department. Department membership can be extended to Groups, - if <span class="doc-desc-title">Alerts & Notices - Recipients</span> includes groups members. + Determine if Tickets can be assigned to all agents, + agents with Primary or Extended Department access, + or only agents with Primary Department access. disable_auto_claim: title: Disable Auto Claim diff --git a/include/staff/department.inc.php b/include/staff/department.inc.php index 2005cf53490b00a4db5ceb1a97124e74d5a052fd..caab736fde8588f807d885fcaac6193819bd3451 100644 --- a/include/staff/department.inc.php +++ b/include/staff/department.inc.php @@ -167,17 +167,16 @@ $info = Format::htmlchars(($errors && $_POST) ? $_POST : $info); </td> </tr> <tr> - <td><?php echo __('Ticket Assignment'); ?>:</td> + <td><?php echo __('Ticket Assignment'); ?>:</td> <td> - <label> - <input type="checkbox" name="assign_members_only" <?php echo - $info['assign_members_only']?'checked="checked"':''; ?>> - <?php echo __('Restrict ticket assignment to department members'); ?> - </label> - <i class="help-tip icon-question-sign" href="#sandboxing"></i> + <select name="assignment_flag"> + <option value="all"<?php echo ($info['assignment_flag'] == 'all')?'selected="selected"':'';?>><?php echo __('All'); ?></option> + <option value="members"<?php echo ($info['assignment_flag'] == 'members') ?'selected="selected"':'';?>><?php echo __('Department Members'); ?></option> + <option value="primary"<?php echo ($info['assignment_flag'] == 'primary') ?'selected="selected"':'';?>><?php echo __('Primary Members'); ?></option> + </select> + <span class="error"> </span> <i class="help-tip icon-question-sign" href="#sandboxing"></i> </td> </tr> - <tr> <td><?php echo __('Claim on Response'); ?>:</td> <td>