From 90e251f5123770d14c17b3039258db560e6be609 Mon Sep 17 00:00:00 2001
From: Peter Rotich <peter@osticket.com>
Date: Tue, 6 May 2014 20:42:22 +0000
Subject: [PATCH] Limit ticket assignment to department members

Add department setting to limit ticket assignment within department to
department members only. This is necessary for departments with strict
policy on who can access tickets.

The setting doesn't limit team assignment or auto-assignment via help topics
and ticket filters.
---
 include/class.config.php          |  9 ++++
 include/class.dept.php            | 74 ++++++++++++++++++++++---------
 include/class.email.php           |  9 ++++
 include/class.staff.php           |  9 ++--
 include/class.ticket.php          |  4 +-
 include/staff/department.inc.php  | 13 +++++-
 include/staff/filter.inc.php      | 19 +++-----
 include/staff/helptopic.inc.php   | 12 ++---
 include/staff/ticket-view.inc.php | 13 +++++-
 9 files changed, 113 insertions(+), 49 deletions(-)

diff --git a/include/class.config.php b/include/class.config.php
index 68704cd7b..eaf2aac42 100644
--- a/include/class.config.php
+++ b/include/class.config.php
@@ -126,6 +126,15 @@ class Config {
                 return false;
         return true;
     }
+
+    function destrory() {
+
+        $sql='DELETE FROM '.$this->table
+            .' WHERE `'.$this->section_column.'` = '.db_input($this->section);
+
+        db_query($sql);
+        unset($this->session);
+    }
 }
 
 class OsticketConfig extends Config {
diff --git a/include/class.dept.php b/include/class.dept.php
index 0fb59d36f..d99985b44 100644
--- a/include/class.dept.php
+++ b/include/class.dept.php
@@ -50,6 +50,7 @@ class Dept {
         $this->id=$this->ht['dept_id'];
         $this->email=$this->sla=$this->manager=null;
         $this->getEmail(); //Auto load email struct.
+        $this->config = new Config('dept.'.$this->id);
         $this->members=$this->groups=array();
 
         return true;
@@ -99,29 +100,47 @@ class Dept {
         return count($this->getMembers());
     }
 
-    function getMembers() {
+    function getMembers($criteria=null) {
 
-        if(!$this->members) {
-            $this->members = array();
+        if(!$this->members || $criteria) {
+            $members = array();
             $sql='SELECT DISTINCT s.staff_id FROM '.STAFF_TABLE.' s '
-                .' LEFT JOIN '.GROUP_DEPT_TABLE.' g ON(s.group_id=g.group_id) '
+                .' LEFT JOIN '.GROUP_TABLE.' g ON (g.group_id=s.group_id) '
+                .' LEFT JOIN '.GROUP_DEPT_TABLE.' gd ON(s.group_id=gd.group_id) '
                 .' INNER JOIN '.DEPT_TABLE.' d
                        ON(d.dept_id=s.dept_id
                             OR d.manager_id=s.staff_id
-                            OR (d.dept_id=g.dept_id AND d.group_membership=1)
+                            OR (d.dept_id=gd.dept_id AND d.group_membership=1)
                         ) '
-                .' WHERE d.dept_id='.db_input($this->getId())
-                .' ORDER BY s.lastname, s.firstname';
+                .' WHERE d.dept_id='.db_input($this->getId());
+
+            if ($criteria && $criteria['available'])
+                $sql .= ' AND
+                        ( g.group_enabled=1
+                          AND s.isactive=1
+                          AND s.onvacation=0 ) ';
+
+            $sql.=' ORDER BY s.lastname, s.firstname';
 
             if(($res=db_query($sql)) && db_num_rows($res)) {
                 while(list($id)=db_fetch_row($res))
-                    $this->members[] = Staff::lookup($id);
+                    $members[$id] = Staff::lookup($id);
             }
+
+            if ($criteria)
+                return $members;
+
+            $this->members = $members;
+
         }
 
         return $this->members;
     }
 
+    function getAvailableMembers() {
+        return $this->getMembers(array('available' =>1));
+    }
+
 
     function getSLAId() {
         return $this->ht['sla_id'];
@@ -210,6 +229,9 @@ class Dept {
          return ($this->ht['noreply_autoresp']);
     }
 
+    function assignMembersOnly() {
+        return ($this->config->get('assign_members_only', 0));
+    }
 
     function isGroupMembershipEnabled() {
         return ($this->ht['group_membership']);
@@ -220,11 +242,9 @@ class Dept {
     }
 
     function getInfo() {
-        return $this->getHashtable();
+        return $this->config->getInfo() + $this->getHashtable();
     }
 
-
-
     function getAllowedGroups() {
 
         if($this->groups) return $this->groups;
@@ -240,25 +260,26 @@ class Dept {
         return $this->groups;
     }
 
-    function updateAllowedGroups($groups) {
+    function updateSettings($vars) {
 
-        if($groups && is_array($groups)) {
-            foreach($groups as $k=>$id) {
+        // Groups allowes to access department
+        if($vars['groups'] && is_array($vars['groups'])) {
+            foreach($vars['groups'] as $k=>$id) {
                 $sql='INSERT IGNORE INTO '.GROUP_DEPT_TABLE
                     .' SET dept_id='.db_input($this->getId()).', group_id='.db_input($id);
                 db_query($sql);
             }
         }
-
-
         $sql='DELETE FROM '.GROUP_DEPT_TABLE.' WHERE dept_id='.db_input($this->getId());
-        if($groups && is_array($groups))
-            $sql.=' AND group_id NOT IN('.implode(',', db_input($groups)).')';
+        if($vars['groups'] && is_array($vars['groups']))
+            $sql.=' AND group_id NOT IN ('.implode(',', db_input($vars['groups'])).')';
 
         db_query($sql);
 
-        return true;
+        // Misc. config settings
+        $this->config->set('assign_members_only', $vars['assign_members_only']);
 
+        return true;
     }
 
     function update($vars, &$errors) {
@@ -266,7 +287,7 @@ class Dept {
         if(!$this->save($this->getId(), $vars, $errors))
             return false;
 
-        $this->updateAllowedGroups($vars['groups']);
+        $this->updateSettings($vars);
         $this->reload();
 
         return true;
@@ -298,6 +319,9 @@ class Dept {
 
             //Delete group access
             db_query('DELETE FROM '.GROUP_DEPT_TABLE.' WHERE dept_id='.db_input($id));
+
+            // Destrory config settings
+            $this->config->destroy();
         }
 
         return $num;
@@ -340,6 +364,8 @@ class Dept {
         if(($manager=$criteria['manager']))
             $sql.=' AND manager_id='.db_input(is_object($manager)?$manager->getId():$manager);
 
+        $sql.=' ORDER BY dept_name';
+
         if(($res=db_query($sql)) && db_num_rows($res)) {
             while(list($id, $name)=db_fetch_row($res))
                 $depts[$id] = $name;
@@ -353,8 +379,12 @@ class Dept {
     }
 
     function create($vars, &$errors) {
-        if(($id=self::save(0, $vars, $errors)) && ($dept=self::lookup($id)))
-            $dept->updateAllowedGroups($vars['groups']);
+
+        if(!($id=self::save(0, $vars, $errors)))
+            return null;
+
+        if (($dept=self::lookup($id)))
+            $dept->updateSettings($vars);
 
         return $id;
     }
diff --git a/include/class.email.php b/include/class.email.php
index 17c035328..0bae5c95a 100644
--- a/include/class.email.php
+++ b/include/class.email.php
@@ -195,6 +195,15 @@ class Email {
     }
 
 
+   function __toString() {
+
+       $email = $this->getEmail();
+       if ($this->getName())
+           $email = sprintf('%s <%s>', $this->getName(), $this->getEmail());
+
+       return $email;
+   }
+
     /******* Static functions ************/
 
    function getIdByEmail($email) {
diff --git a/include/class.staff.php b/include/class.staff.php
index ed6a0ae1d..4b28b6092 100644
--- a/include/class.staff.php
+++ b/include/class.staff.php
@@ -93,12 +93,12 @@ class Staff extends AuthenticatedUser {
         return $this->__toString();
     }
 
-    function getHastable() {
+    function getHashtable() {
         return $this->ht;
     }
 
     function getInfo() {
-        return $this->config->getInfo() + $this->getHastable();
+        return $this->config->getInfo() + $this->getHashtable();
     }
 
     // AuthenticatedUser implementation...
@@ -585,6 +585,9 @@ class Staff extends AuthenticatedUser {
 
             //Cleanup Team membership table.
             db_query('DELETE FROM '.TEAM_MEMBER_TABLE.' WHERE staff_id='.db_input($this->getId()));
+
+            // Destrory config settings
+            $this->config->destroy();
         }
 
         Signal::send('model.deleted', $this);
@@ -595,7 +598,7 @@ class Staff extends AuthenticatedUser {
     /**** Static functions ********/
     function getStaffMembers($availableonly=false) {
 
-        $sql='SELECT s.staff_id,CONCAT_WS(", ",s.lastname, s.firstname) as name '
+        $sql='SELECT s.staff_id, CONCAT_WS(" ", s.firstname, s.lastname) as name '
             .' FROM '.STAFF_TABLE.' s ';
 
         if($availableonly) {
diff --git a/include/class.ticket.php b/include/class.ticket.php
index c7dc74953..943dd0bbc 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -1420,7 +1420,7 @@ class Ticket {
         if(!is_object($staff) && !($staff=Staff::lookup($staff)))
             return false;
 
-        if(!$this->setStaffId($staff->getId()))
+        if (!$staff->isAvailable() || !$this->setStaffId($staff->getId()))
             return false;
 
         $this->onAssign($staff, $note, $alert);
@@ -1434,7 +1434,7 @@ class Ticket {
         if(!is_object($team) && !($team=Team::lookup($team)))
             return false;
 
-        if(!$this->setTeamId($team->getId()))
+        if (!$team->isActive() || !$this->setTeamId($team->getId()))
             return false;
 
         //Clear - staff if it's a closed ticket
diff --git a/include/staff/department.inc.php b/include/staff/department.inc.php
index 2a001a403..d8998bda5 100644
--- a/include/staff/department.inc.php
+++ b/include/staff/department.inc.php
@@ -147,7 +147,18 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
             </td>
             <td>
                 <input type="checkbox" name="group_membership" value="0" <?php echo $info['group_membership']?'checked="checked"':''; ?> >
-                Extend membership to groups with access. <i>(Alerts and  notices will include groups)</i>
+                Extend membership to groups with access <em>(Alerts and
+                        notices will include groups)</em>
+            </td>
+        </tr>
+        <tr>
+            <td>Ticket Assignment:</td>
+            <td>
+                <input type="checkbox" name="assign_members_only" <?php echo
+                $info['assign_members_only']?'checked="checked"':''; ?>>
+                Limit ticket assignment to department members
+                <!-- Help Tip:
+                     Tickets can ONLY be assigned to department members (+ group members)-->
             </td>
         </tr>
         <tr>
diff --git a/include/staff/filter.inc.php b/include/staff/filter.inc.php
index 74e721068..4a6f505c0 100644
--- a/include/staff/filter.inc.php
+++ b/include/staff/filter.inc.php
@@ -281,27 +281,20 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
             <td>
                 <select name="assign">
                     <option value="0">&mdash; Unassigned &mdash;</option>
-
-
                     <?php
-
-
-                    $sql=' SELECT staff_id,CONCAT_WS(", ",lastname,firstname) as name '.
-                         ' FROM '.STAFF_TABLE.' WHERE isactive=1 ORDER BY name';
-
-                    if(($res=db_query($sql)) && db_num_rows($res)){
+                    if (($users=Staff::getStaffMembers())) {
                         echo '<OPTGROUP label="Staff Members">';
-                        while (list($id,$name) = db_fetch_row($res)){
+                        foreach($users as $id => $name) {
+                            $name = new PersonsName($name);
                             $k="s$id";
                             $selected = ($info['assign']==$k || $info['staff_id']==$id)?'selected="selected"':'';
                             ?>
                             <option value="<?php echo $k; ?>"<?php echo $selected; ?>><?php echo $name; ?></option>
-
-                        <?php }
+                        <?php
+                        }
                         echo '</OPTGROUP>';
-
                     }
-                    $sql='SELECT team_id, name FROM '.TEAM_TABLE.' WHERE isenabled=1';
+                    $sql='SELECT team_id, name FROM '.TEAM_TABLE .' ORDER BY name';
                     if(($res=db_query($sql)) && db_num_rows($res)){
                         echo '<OPTGROUP label="Teams">';
                         while (list($id,$name) = db_fetch_row($res)){
diff --git a/include/staff/helptopic.inc.php b/include/staff/helptopic.inc.php
index 9e9a34d14..071e515df 100644
--- a/include/staff/helptopic.inc.php
+++ b/include/staff/helptopic.inc.php
@@ -193,20 +193,20 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                 <select name="assign">
                     <option value="0">&mdash; Unassigned &mdash;</option>
                     <?php
-                    $sql=' SELECT staff_id,CONCAT_WS(", ",lastname,firstname) as name '.
-                         ' FROM '.STAFF_TABLE.' WHERE isactive=1 ORDER BY name';
-                    if(($res=db_query($sql)) && db_num_rows($res)){
+                    if (($users=Staff::getStaffMembers())) {
                         echo '<OPTGROUP label="Staff Members">';
-                        while (list($id,$name) = db_fetch_row($res)){
+                        foreach ($users as $id => $name) {
+                            $name = new PersonsName($name);
                             $k="s$id";
                             $selected = ($info['assign']==$k || $info['staff_id']==$id)?'selected="selected"':'';
                             ?>
                             <option value="<?php echo $k; ?>"<?php echo $selected; ?>><?php echo $name; ?></option>
 
-                        <?php }
+                        <?php
+                        }
                         echo '</OPTGROUP>';
                     }
-                    $sql='SELECT team_id, name FROM '.TEAM_TABLE.' WHERE isenabled=1';
+                    $sql='SELECT team_id, name FROM '.TEAM_TABLE.' ORDER BY name';
                     if(($res=db_query($sql)) && db_num_rows($res)){
                         echo '<OPTGROUP label="Teams">';
                         while (list($id,$name) = db_fetch_row($res)){
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index 4042692d4..dcce0d8f8 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -802,16 +802,25 @@ $tcount+= $ticket->getNumNotes();
                             echo sprintf('<option value="%d">Claim Ticket (comments optional)</option>', $thisstaff->getId());
 
                         $sid=$tid=0;
-                        if(($users=Staff::getAvailableStaffMembers())) {
+
+                        if ($dept->assignMembersOnly())
+                            $users = $dept->getAvailableMembers();
+                        else
+                            $users = Staff::getAvailableStaffMembers();
+
+                        if ($users) {
                             echo '<OPTGROUP label="Staff Members ('.count($users).')">';
                             $staffId=$ticket->isAssigned()?$ticket->getStaffId():0;
                             foreach($users as $id => $name) {
                                 if($staffId && $staffId==$id)
                                     continue;
 
+                                if (!is_object($name))
+                                    $name = new PersonsName($name);
+
                                 $k="s$id";
                                 echo sprintf('<option value="%s" %s>%s</option>',
-                                        $k,(($info['assignId']==$k)?'selected="selected"':''),$name);
+                                        $k,(($info['assignId']==$k)?'selected="selected"':''), $name);
                             }
                             echo '</OPTGROUP>';
                         }
-- 
GitLab