diff --git a/include/class.dept.php b/include/class.dept.php
index 5a2babdd3da4021a7b81c736a79210fdf11f1d97..00609db105ccd781491997e61e5eb302aadfbfae 100644
--- a/include/class.dept.php
+++ b/include/class.dept.php
@@ -19,6 +19,9 @@ class Dept {
     var $email;
     var $sla;
     var $manager; 
+    var $members;
+    var $groups;
+
     var $ht;
   
     function Dept($id){
@@ -47,7 +50,7 @@ class Dept {
         $this->id=$this->ht['dept_id'];
         $this->email=$this->sla=$this->manager=null;
         $this->getEmail(); //Auto load email struct.
-        $this->members=array();
+        $this->members=$this->groups=array();
 
         return true;
     }
@@ -89,22 +92,30 @@ class Dept {
         return $this->getNumStaff();
     }
 
-    function getAvailableMembers(){
+    function getMembers() {
 
-        if(!$this->members && $this->getNumStaff()){
-            $sql='SELECT m.staff_id FROM '.STAFF_TABLE.' m '
-                .'WHERE m.dept_id='.db_input($this->getId())
-                .' AND m.staff_id IS NOT NULL '
-                .'ORDER BY m.lastname, m.firstname';
-            if(($res=db_query($sql)) && db_num_rows($res)){
-                while(list($id)=db_fetch_row($res))
-                    if(($staff=Staff::lookup($id)) && $staff->isAvailable())
-                        $this->members[]= $staff;
+        if(!$this->members && $this->getNumStaff()) {
+            $sql='SELECT DISTINCT s.staff_id, s.dept_id FROM '.STAFF_TABLE.' s '
+                .' LEFT JOIN '.GROUP_DEPT_TABLE.' g ON(s.group_id=g.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) '
+                .' WHERE d.dept_id='.db_input($this->getId())
+                .' ORDER BY s.lastname, s.firstname';
+           
+            if(($res=db_query($sql)) && db_num_rows($res)) {
+                while(list($staffId, $deptId)=db_fetch_row($res)) {
+                    if(!$this->enableGroupMembership() 
+                            && $deptId!=$this->getId() 
+                            && $staffId!=$this->getManagerId()) continue;
+
+                    $this->members[] = Staff::lookup($staffId);
+                }
             }
         }
+
         return $this->members;
     }
 
+
     function getSLAId(){
         return $this->ht['sla_id'];
     }
@@ -179,6 +190,11 @@ class Dept {
     function noreplyAutoResp(){
          return ($this->ht['noreply_autoresp']);
     }
+
+
+    function enableGroupMembership() {
+        return ($this->ht['group_membership']);
+    }
    
     function getHashtable() {
         return $this->ht;
@@ -188,14 +204,53 @@ class Dept {
         return $this->getHashtable();
     }
 
-    function update($vars,&$errors){
 
-        if($this->save($this->getId(),$vars,$errors)) {
-            $this->reload();
-            return true;
+      
+    function getAllowedGroups() {
+
+        if($this->groups) return $this->groups;
+
+        $sql='SELECT group_id FROM '.GROUP_DEPT_TABLE
+            .' WHERE dept_id='.db_input($this->getId());
+
+        if(($res=db_query($sql)) && db_num_rows($res)) {
+            while(list($id)=db_fetch_row($res))
+                $this->groups[] = $id;
         }
 
-        return false;
+        return $this->groups;
+    }
+
+    function updateAllowedGroups($groups) {
+
+        if($groups) {
+            foreach($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) 
+            $sql.=' AND group_id NOT IN('.implode(',', db_input($groups)).')';
+
+        db_query($sql);
+
+        return true;
+
+    }
+
+    function update($vars,&$errors){
+
+        if(!$this->save($this->getId(),$vars,$errors))
+            return false;
+
+        $this->updateAllowedGroups($vars['groups']);
+        $this->reload();
+        
+        return true;
     }
 
     function delete() {
@@ -214,7 +269,8 @@ class Dept {
             db_query('UPDATE '.STAFF_TABLE.' SET dept_id='.db_input($cfg->getDefaultDeptId()).' WHERE dept_id='.db_input($id));
             //make help topic using the dept default to default-dept.
             db_query('UPDATE '.TOPIC_TABLE.' SET dept_id='.db_input($cfg->getDefaultDeptId()).' WHERE dept_id='.db_input($id));
-            
+            //Delete group access
+            db_query('DELETE FROM '.GROUP_DEPT_TABLE.' WHERE dept_id='.db_input($id));
         }
 
         return $num;
@@ -267,7 +323,10 @@ class Dept {
     }
 
     function create($vars,&$errors) {
-        return Dept::save(0,$vars,$errors);
+        if(($id=self::save(0, $vars, $errors)) && ($dept=self::lookup($id)))
+            $dept->updateAllowedGroups($vars['groups']);
+
+        return $id;
     }
 
     function save($id,$vars,&$errors) {
@@ -305,6 +364,7 @@ class Dept {
             .' ,manager_id='.db_input($vars['manager_id']?$vars['manager_id']:0)
             .' ,dept_name='.db_input(Format::striptags($vars['name']))
             .' ,dept_signature='.db_input(Format::striptags($vars['signature']))
+            .' ,group_membership='.db_input(isset($vars['group_membership'])?1:0)
             .' ,ticket_auto_response='.db_input(isset($vars['ticket_auto_response'])?$vars['ticket_auto_response']:1)
             .' ,message_auto_response='.db_input(isset($vars['message_auto_response'])?$vars['message_auto_response']:1);
 
diff --git a/include/class.group.php b/include/class.group.php
index 1b21dce29e4511b469c8dfb70386e7e940626d48..e53cb8538f57edbdb78548c52bfc8cb75e8c7626 100644
--- a/include/class.group.php
+++ b/include/class.group.php
@@ -19,13 +19,19 @@ class Group {
     var $id;
     var $ht;
 
+    var $members;
+    var $departments;
+
     function Group($id){
 
         $this->id=0;
         return $this->load($id);
     }
 
-    function load($id){
+    function load($id=0) {
+
+        if(!$id && !($id=$this->getId()))
+            return false;
 
         $sql='SELECT grp.*,grp.group_name as name, grp.group_enabled as isactive, count(staff.staff_id) as users '
             .'FROM '.GROUP_TABLE.' grp '
@@ -37,12 +43,13 @@ class Group {
         $this->ht=db_fetch_array($res);
         $this->id=$this->ht['group_id'];
         $this->members=array();
+        $this->departments = array();
 
         return $this->id;
     }
 
     function reload(){
-        return $this->load($this->getId());
+        return $this->load();
     }
 
     function getHashtable() {
@@ -73,17 +80,85 @@ class Group {
     function isActive(){
         return $this->isEnabled();
     }
+ 
+    //Get members of the group.
+    function getMembers() {
+
+        if(!$this->members && $this->getNumUsers()) {
+            $sql='SELECT staff_id FROM '.STAFF_TABLE
+                .' WHERE group_id='.db_input($this->getId()).' AND staff_id IS NOT NULL '
+                .' ORDER BY lastname, firstname';
+            if(($res=db_query($sql)) && db_num_rows($res)) {
+                while(list($id)=db_fetch_row($res))
+                    if(($staff=Staff::lookup($id)))
+                        $this->members[]= $staff;
+            }
+        }
 
+        return $this->members;
+    }
 
+    //Get departments the group is allowed to access.
+    function getDepartments() {
 
-    function update($vars,&$errors) {
+        if(!$this->departments) {
+            $sql='SELECT dept_id FROM '.GROUP_DEPT_TABLE
+                .' WHERE group_id='.db_input($this->getId());
+            if(($res=db_query($sql)) && db_num_rows($res)) {
+                while(list($id)=db_fetch_row($res))
+                    $this->departments[]= $id;
+            }
+        }
 
-        if(Group::save($this->getId(),$vars,$errors)){
-            $this->reload();
-            return true;
+        return $this->departments;
+    }
+
+        
+    function updateDeptAccess($depts) {
+
+        if($depts) {
+            foreach($depts as $k=>$id) {
+                $sql='INSERT IGNORE INTO '.GROUP_DEPT_TABLE
+                    .' SET group_id='.db_input($this->getId())
+                    .', dept_id='.db_input($id);
+                db_query($sql);
+            }
         }
 
-        return false;
+        $sql='DELETE FROM '.GROUP_DEPT_TABLE.' WHERE group_id='.db_input($this->getId());
+        if($depts) // just inserted departments IF any.
+            $sql.=' AND dept_id NOT IN('.implode(',', db_input($depts)).')';
+
+        db_query($sql);
+
+        return true;
+    }
+
+    function update($vars,&$errors) {
+
+        if(!Group::save($this->getId(),$vars,$errors))
+            return false;
+
+        $this->updateDeptAccess($vars['depts']);
+        $this->reload();
+        
+        return true;
+    }
+
+    function delete() {
+
+        //Can't delete with members
+        if($this->getNumUsers())
+            return false;
+
+        $res = db_query('DELETE FROM '.GROUP_TABLE.' WHERE group_id='.db_input($this->getId()).' LIMIT 1');
+        if(!$res || !db_affected_rows($res))
+            return false;
+
+        //Remove dept access entry.
+        db_query('DELETE FROM '.GROUP_DEPT_TABLE.' WHERE group_id='.db_input($this->getId()));
+
+        return true;
     }
 
     /*** Static functions ***/
@@ -99,9 +174,11 @@ class Group {
         return ($id && is_numeric($id) && ($g= new Group($id)) && $g->getId()==$id)?$g:null;
     }
 
+    function create($vars, &$errors) { 
+        if(($id=self::save(0,$vars,$errors)) && ($group=self::lookup($id)))
+            $group->updateDeptAccess($vars['depts']);
 
-    function create($vars,&$errors) { 
-        return self::save(0,$vars,$errors);
+        return $id;
     }
 
     function save($id,$vars,&$errors) {
@@ -119,19 +196,19 @@ class Group {
         
         if($errors) return false;
             
-        $sql=' SET updated=NOW(), group_name='.db_input(Format::striptags($vars['name'])).
-             ', group_enabled='.db_input($vars['isactive']).
-             ', dept_access='.db_input($vars['depts']?implode(',',$vars['depts']):'').
-             ', can_create_tickets='.db_input($vars['can_create_tickets']).
-             ', can_delete_tickets='.db_input($vars['can_delete_tickets']).
-             ', can_edit_tickets='.db_input($vars['can_edit_tickets']).
-             ', can_assign_tickets='.db_input($vars['can_assign_tickets']).
-             ', can_transfer_tickets='.db_input($vars['can_transfer_tickets']).
-             ', can_close_tickets='.db_input($vars['can_close_tickets']).
-             ', can_ban_emails='.db_input($vars['can_ban_emails']).
-             ', can_manage_premade='.db_input($vars['can_manage_premade']).
-             ', can_manage_faq='.db_input($vars['can_manage_faq']).
-             ', notes='.db_input($vars['notes']);
+        $sql=' SET updated=NOW() '
+            .', group_name='.db_input(Format::striptags($vars['name']))
+            .', group_enabled='.db_input($vars['isactive'])
+            .', can_create_tickets='.db_input($vars['can_create_tickets'])
+            .', can_delete_tickets='.db_input($vars['can_delete_tickets'])
+            .', can_edit_tickets='.db_input($vars['can_edit_tickets'])
+            .', can_assign_tickets='.db_input($vars['can_assign_tickets'])
+            .', can_transfer_tickets='.db_input($vars['can_transfer_tickets'])
+            .', can_close_tickets='.db_input($vars['can_close_tickets'])
+            .', can_ban_emails='.db_input($vars['can_ban_emails'])
+            .', can_manage_premade='.db_input($vars['can_manage_premade'])
+            .', can_manage_faq='.db_input($vars['can_manage_faq'])
+            .', notes='.db_input($vars['notes']);
             
         if($id) {
             
diff --git a/include/class.staff.php b/include/class.staff.php
index b95329fa69c3191c69fdc65006785fc420ff2ed0..b607f6eac145aa7e7c13547218d936f7662ceb8a 100644
--- a/include/class.staff.php
+++ b/include/class.staff.php
@@ -25,6 +25,8 @@ class Staff {
     var $id;
 
     var $dept;
+    var $departments;
+    var $group;
     var $teams;
     var $timezone;
     var $stats;
@@ -51,8 +53,9 @@ class Staff {
         
         $this->ht=db_fetch_array($res);
         $this->id  = $this->ht['staff_id'];
-        $this->teams = $this->ht['teams']= array();
-        $this->stats=array();
+        $this->teams = $this->ht['teams'] = array();
+        $this->group = $this->dept = null;
+        $this->departments = $this->stats = array();
 
         //WE have to patch info here to support upgrading from old versions.
         if(($time=strtotime($this->ht['passwdreset']?$this->ht['passwdreset']:$this->ht['added'])))
@@ -154,10 +157,6 @@ class Staff {
         return $this->ht['lastname'];
     }
     
-    function getGroupId() {
-        return $this->ht['group_id'];
-    }
-
     function getSignature() {
         return $this->ht['signature'];
     }
@@ -174,13 +173,46 @@ class Staff {
         return ($this->ht['change_passwd']);
     }
 
+    function getDepartments() {
+
+        if($this->departments)
+            return $this->departments;
+
+        //Departments the staff is "allowed" to access...
+        // based on the group they belong to + user's primary dept + user's managed depts.
+        $sql='SELECT DISTINCT d.dept_id FROM '.STAFF_TABLE.' s '
+            .' LEFT JOIN '.GROUP_DEPT_TABLE.' g ON(s.group_id=g.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) '
+            .' WHERE s.staff_id='.db_input($this->getId());
+
+        $depts = array();
+        if(($res=db_query($sql)) && db_num_rows($res)) {
+            while(list($id)=db_fetch_row($res))
+                $depts[] = $id;
+        } else { //Neptune help us! (fallback)
+            $depts = array_merge($this->getGroup()->getDepartments(), array($this->getDeptId()));
+        }
+
+        $this->departments = array_filter(array_unique($depts));
+
+
+        return $this->departments;
+    }
+
     function getDepts() {
-        //Departments the user is allowed to access...based on the group they belong to + user's dept.
-        return array_filter(array_unique(array_merge(explode(',', $this->ht['dept_access']), array($this->getDeptId())))); //Neptune help us
+        return $this->getDepartments();
+    }
+     
+    function getGroupId() {
+        return $this->ht['group_id'];
     }
 
-    function getDepartments() {
-        return $this->getDepts();
+    function getGroup() {
+     
+        if(!$this->group && $this->getGroupId())
+            $this->group = Group::lookup($this->getGroupId());
+
+        return $this->group;
     }
 
     function getDeptId() {
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 7e53ec51bd10247932fbd6e416e4afed1939deee..683ab25c46e69e83e0150baee01c329e90c5f7e4 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -866,7 +866,7 @@ class Ticket{
               
             //Only alerts dept members if the ticket is NOT assigned.
             if($cfg->alertDeptMembersONNewTicket() && !$this->isAssigned()) {
-                if(($members=$dept->getAvailableMembers()))
+                if(($members=$dept->getMembers()))
                     $recipients=array_merge($recipients, $members);
             }
             
@@ -877,6 +877,7 @@ class Ticket{
                 if(!is_object($staff) || !$staff->isAvailable() || in_array($staff->getEmail(),$sentlist)) continue;
                 $alert = str_replace("%staff",$staff->getFirstName(),$body);
                 $email->send($staff->getEmail(),$subj,$alert);
+                $sentlist[] = $staff->getEmail();
             }
            
            
@@ -1029,8 +1030,8 @@ class Ticket{
                 if(!is_object($staff) || !$staff->isAvailable() || in_array($staff->getEmail(),$sentlist)) continue;
                 $alert = str_replace('%staff', $staff->getFirstName(), $body);
                 $email->send($staff->getEmail(), $subj, $alert);
+                $sentlist[] = $staff->getEmail();
             }
-            print_r($sentlist);
         }
 
         return true;
@@ -1072,7 +1073,7 @@ class Ticket{
                     $recipients=array_merge($recipients, $members);
             } elseif($cfg->alertDeptMembersONOverdueTicket() && !$this->isAssigned()) {
                 //Only alerts dept members if the ticket is NOT assigned.
-                if(($members=$dept->getAvailableMembers()))
+                if(($members=$dept->getMembers()))
                     $recipients=array_merge($recipients, $members);
             }
             //Always alert dept manager??
@@ -1084,6 +1085,7 @@ class Ticket{
                 if(!is_object($staff) || !$staff->isAvailable() || in_array($staff->getEmail(),$sentlist)) continue;
                 $alert = str_replace("%staff",$staff->getFirstName(),$body);
                 $email->send($staff->getEmail(),$subj,$alert);
+                $sentlist[] = $staff->getEmail();
             }
 
         }
@@ -1200,7 +1202,7 @@ class Ticket{
                     $recipients+=$members;
             } elseif($cfg->alertDeptMembersONTransfer() && !$this->isAssigned()) {
                 //Only alerts dept members if the ticket is NOT assigned.
-                if(($members=$dept->getAvailableMembers()))
+                if(($members=$dept->getMembers()))
                     $recipients+=$members;
             }
 
@@ -1213,6 +1215,7 @@ class Ticket{
                 if(!is_object($staff) || !$staff->isAvailable() || in_array($staff->getEmail(),$sentlist)) continue;
                 $alert = str_replace("%staff",$staff->getFirstName(),$body);
                 $email->send($staff->getEmail(),$subj,$alert);
+                $sentlist[] = $staff->getEmail();
             }
          }
 
@@ -1361,7 +1364,7 @@ class Ticket{
                 if(!$staff || !$staff->getEmail() || !$staff->isAvailable() && in_array($staff->getEmail(),$sentlist)) continue;
                 $alert = str_replace("%staff",$staff->getFirstName(),$body);
                 $email->send($staff->getEmail(),$subj,$alert);
-                $sentlist[]=$staff->getEmail();
+                $sentlist[] = $staff->getEmail();
             }
         }
         
@@ -1544,7 +1547,7 @@ class Ticket{
                 if(in_array($staff->getEmail(),$sentlist) || ($thisstaff && $thisstaff->getId()==$staff->getId())) continue; 
                 $alert = str_replace('%staff',$staff->getFirstName(),$body);
                 $email->send($staff->getEmail(),$subj,$alert);
-                $sentlist[]=$staff->getEmail();
+                $sentlist[] = $staff->getEmail();
             }
         }
         
diff --git a/include/class.upgrader.php b/include/class.upgrader.php
index 4487e53b26844c8094b72406c5f739cb67702bf3..c886bb0ab927f2e59e1dd656b7e593b6f4ae490b 100644
--- a/include/class.upgrader.php
+++ b/include/class.upgrader.php
@@ -275,17 +275,21 @@ class Upgrader extends SetupWizard {
                                  'desc' => 'Transitioning to db-backed sessions');
                 break;
             case '98ae1ed2-e342f869': //v1.6 RC1-4 -> v1.6 RC5
-                $task[] = array('func' => 'migrateAPIKeys',
-                                'desc' => 'Migrating API keys to a new table');
+                $tasks[] = array('func' => 'migrateAPIKeys',
+                                 'desc' => 'Migrating API keys to a new table');
+                break;
+            case '435c62c3-6007d45b':
+                $tasks[] = array('func' => 'migrateGroupDeptAccess',
+                                 'desc' => 'Migrating group\'s department access to a new table');
                 break;
         }
 
-        //Check IF SQL cleanup is exists. 
+        //Check IF SQL cleanup exists. 
         $file=$this->getSQLDir().$phash.'.cleanup.sql';
         if(file_exists($file)) 
-            $tasks[] = array('func' => 'cleanup', 'desc' => 'Post-upgrade cleanup!',
-                        'phash' => $phash);
-
+            $tasks[] = array('func' => 'cleanup',
+                             'desc' => 'Post-upgrade cleanup!',
+                             'phash' => $phash);
 
         return $tasks;
     }
@@ -336,7 +340,7 @@ class Upgrader extends SetupWizard {
 
         list($whitelist, $key) = db_fetch_row($res);
 
-        $ips=array_filter(explode(',', ereg_replace(' ', '', $whitelist)));
+        $ips=array_filter(array_map('trim', explode(',', $whitelist)));
         foreach($ips as $ip) {
             $sql='INSERT INTO '.API_KEY_TABLE.' SET created=NOW(), updated=NOW(), isactive=1 '
                 .',ipaddr='.db_input($ip)
@@ -346,5 +350,26 @@ class Upgrader extends SetupWizard {
 
         return 0;
     }
+
+    function migrateGroupDeptAccess($taskId) {
+
+        $res = db_query('SELECT group_id, dept_access FROM '.GROUP_TABLE);
+        if(!$res || !db_num_rows($res))
+            return 0;  //No groups??
+
+        while(list($groupId, $access) = db_fetch_row($res)) {
+            $depts=array_filter(array_map('trim', explode(',', $access)));
+            foreach($depts as $deptId) {
+                $sql='INSERT INTO '.GROUP_DEPT_TABLE
+                    .' SET dept_id='.db_input($deptId).', group_id='.db_input($groupId);
+                db_query($sql);
+            }
+        }
+
+        return 0;
+
+
+
+    }
 }
 ?>
diff --git a/include/mysql.php b/include/mysql.php
index 06489242a71d78d7e8fae590ed8960ddfa74dee8..65adb6298a632ebe0d8c0a127d2c0af8982bf546 100644
--- a/include/mysql.php
+++ b/include/mysql.php
@@ -38,12 +38,12 @@
         return $dblink;	
     }
 
-    function db_close(){
+    function db_close() {
         global $dblink;
         return @mysql_close($dblink);
     }
 
-    function db_version(){
+    function db_version() {
 
         $version=0;
         if(preg_match('/(\d{1,2}\.\d{1,2}\.\d{1,2})/', 
@@ -59,7 +59,7 @@
     }
 
     function db_get_variable($variable, $type='session') {
-        $sql =sprintf('SELECT @@%s.%s',$type,$variable);
+        $sql =sprintf('SELECT @@%s.%s', $type, $variable);
         return db_result(db_query($sql));
     }
 
@@ -74,112 +74,105 @@
     }
 
     function db_create_database($database, $charset='utf8', $collate='utf8_unicode_ci') {
-        return @mysql_query(sprintf('CREATE DATABASE %s DEFAULT CHARACTER SET %s COLLATE %s',$database,$charset,$collate));
+        return @mysql_query(sprintf('CREATE DATABASE %s DEFAULT CHARACTER SET %s COLLATE %s', $database, $charset, $collate));
     }
    
 	// execute sql query
-	function db_query($query, $database="", $conn=""){
+	function db_query($query, $database="", $conn="") {
         global $ost;
        
 		if($conn) { /* connection is provided*/
-            $result = ($database)?mysql_db_query($database, $query, $conn):mysql_query($query, $conn);
+            $res = ($database)?mysql_db_query($database, $query, $conn):mysql_query($query, $conn);
    	    } else {
-            $result = ($database)?mysql_db_query($database, $query):mysql_query($query);
+            $res = ($database)?mysql_db_query($database, $query):mysql_query($query);
    	    }
                 
-        if(!$result && $ost) { //error reporting
+        if(!$res && $ost) { //error reporting
             $msg='['.$query.']'."\n\n".db_error();
             $ost->logDBError('DB Error #'.db_errno(), $msg);
             //echo $msg; #uncomment during debuging or dev.
         }
 
-        return $result;
+        return $res;
 	}
 
-	function db_squery($query){ //smart db query...utilizing args and sprintf
+	function db_squery($query) { //smart db query...utilizing args and sprintf
 	
 		$args  = func_get_args();
   		$query = array_shift($args);
   		$query = str_replace("?", "%s", $query);
   		$args  = array_map('db_real_escape', $args);
-  		array_unshift($args,$query);
-  		$query = call_user_func_array('sprintf',$args);
+  		array_unshift($args, $query);
+  		$query = call_user_func_array('sprintf', $args);
 		return db_query($query);
 	}
 
-	function db_count($query){		
+	function db_count($query) {		
         return db_result(db_query($query));
 	}
 
-    function db_result($result,$row=0) {
-        return ($result)?mysql_result($result,$row):NULL;
+    function db_result($res, $row=0) {
+        return ($res)?mysql_result($res, $row):NULL;
     }
 
-	function db_fetch_array($result,$mode=false) {
-   	    return ($result)?db_output(mysql_fetch_array($result,($mode)?$mode:MYSQL_ASSOC)):NULL;
+	function db_fetch_array($res, $mode=false) {
+   	    return ($res)?db_output(mysql_fetch_array($res, ($mode)?$mode:MYSQL_ASSOC)):NULL;
   	}
 
-    function db_fetch_row($result) {
-        return ($result)?db_output(mysql_fetch_row($result)):NULL;
+    function db_fetch_row($res) {
+        return ($res)?db_output(mysql_fetch_row($res)):NULL;
     }
 
-    function db_fetch_field($result) {
-        return ($result)?mysql_fetch_field($result):NULL;
+    function db_fetch_field($res) {
+        return ($res)?mysql_fetch_field($res):NULL;
     }   
 
-    function db_assoc_array($result,$mode=false) {
-	    if($result && db_num_rows($result)) {
-      	    while ($row=db_fetch_array($result,$mode))
-         	    $results[]=$row;
+    function db_assoc_array($res, $mode=false) {
+	    if($res && db_num_rows($res)) {
+      	    while ($row=db_fetch_array($res, $mode))
+         	    $result[]=$row;
         }
-        return $results;
+        return $result;
     }
 
-    function db_num_rows($result) {
-   	    return ($result)?mysql_num_rows($result):0;
+    function db_num_rows($res) {
+   	    return ($res)?mysql_num_rows($res):0;
     }
 
 	function db_affected_rows() {
       return mysql_affected_rows();
     }
 
-  	function db_data_seek($result, $row_number) {
-   	    return mysql_data_seek($result, $row_number);
+  	function db_data_seek($res, $row_number) {
+   	    return mysql_data_seek($res, $row_number);
   	}
 
-  	function db_data_reset($result) {
-   	    return mysql_data_seek($result,0);
+  	function db_data_reset($res) {
+   	    return mysql_data_seek($res,0);
   	}
 
   	function db_insert_id() {
    	    return mysql_insert_id();
   	}
 
-	function db_free_result($result) {
-   	    return mysql_free_result($result);
+	function db_free_result($res) {
+   	    return mysql_free_result($res);
   	}
   
-	function db_output($param) {
+	function db_output($var) {
 
         if(!function_exists('get_magic_quotes_runtime') || !get_magic_quotes_runtime()) //Sucker is NOT on - thanks.
-            return $param;
+            return $var;
 
-        if (is_array($param)) {
-      	    reset($param);
-      	    while(list($key, $value) = each($param))
-        	    $param[$key] = db_output($value);
+        if (is_array($var)) 
+            return array_map('db_output', $var);
 
-      	    return $param;
+        return (!is_numeric($var))?stripslashes($var):$var;
 
-    	}elseif(!is_numeric($param)) {
-            $param=trim(stripslashes($param));
-        }
-
-        return $param;
-  	}
+    }
 
     //Do not call this function directly...use db_input
-    function db_real_escape($val,$quote=false){
+    function db_real_escape($val, $quote=false) {
 
         //Magic quotes crap is taken care of in main.inc.php
         $val=mysql_real_escape_string($val);
@@ -187,29 +180,21 @@
         return ($quote)?"'$val'":$val;
     }
 
-    function db_input($param,$quote=true) {
-
-        //is_numeric doesn't work all the time...9e8 is considered numeric..which is correct...but not expected.
-        if($param && preg_match("/^\d+(\.\d+)?$/",$param))
-            return $param;
+    function db_input($var, $quote=true) {
 
-        if($param && is_array($param)) {
-            reset($param);
-            while (list($key, $value) = each($param)) {
-                $param[$key] = db_input($value,$quote);
-            }
-
-            return $param;
-        }
+        if(is_array($var))
+            return array_map('db_input', $var, array_fill(0, count($var), $quote));
+        elseif($var && preg_match("/^\d+(\.\d+)?$/", $var))
+            return $var;
 
-        return db_real_escape($param,$quote);
+        return db_real_escape($var, $quote);
     }
 
-	function db_error(){
+	function db_error() {
    	    return mysql_error();   
 	}
    
-    function db_errno(){
+    function db_errno() {
         return mysql_errno();
     }
 ?>
diff --git a/include/staff/department.inc.php b/include/staff/department.inc.php
index 943bfc90bd08d5a46632bcf5b62034e2bbf7ac91..2c1ff86ca75f3b6467e44fa3b86fe98652a808e7 100644
--- a/include/staff/department.inc.php
+++ b/include/staff/department.inc.php
@@ -2,15 +2,17 @@
 if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
 $info=array();
 $qstr='';
-if($dept && $_REQUEST['a']!='add'){
+if($dept && $_REQUEST['a']!='add') {
     //Editing Department.
     $title='Update Department';
     $action='update';
     $submit_text='Save Changes';
     $info=$dept->getInfo();
     $info['id']=$dept->getId();
+    $info['groups'] = $dept->getAllowedGroups();
+
     $qstr.='&id='.$dept->getId();
-}else {
+} else {
     $title='Add New Department';
     $action='create';
     $submit_text='Create Dept';
@@ -129,8 +131,9 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                     <option value="0">&mdash; None &mdash;</option>
                     <option value="0" disabled="disabled">Select Department Manager (Optional)</option>
                     <?php
-                    $sql='SELECT staff_id,CONCAT_WS(" ",firstname,lastname) as name FROM '.STAFF_TABLE.' staff '.
-                         'WHERE dept_id='.db_input($dept->getId()).' ORDER by name';
+                    $sql='SELECT staff_id,CONCAT_WS(", ",lastname, firstname) as name '
+                        .' FROM '.STAFF_TABLE.' staff '
+                        .' ORDER by name';
                     if(($res=db_query($sql)) && db_num_rows($res)){
                         while(list($id,$name)=db_fetch_row($res)){
                             $selected=($info['manager_id'] && $id==$info['manager_id'])?'selected="selected"':'';
@@ -142,7 +145,18 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                 &nbsp;<span class="error">&nbsp;<?php echo $errors['manager_id']; ?></span>
             </td>
         </tr>
-        <?php } ?>
+        <?php 
+        } ?>
+
+        <tr>
+            <td width="180">
+                Group Membership:
+            </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>
+            </td>
+        </tr>
         <tr>
             <th colspan="2">
                 <em><strong>Auto Response Settings</strong>: Overwrite global auto-response settings for tickets routed to the Dept.</em>
@@ -190,6 +204,29 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                 &nbsp;<span class="error">&nbsp;<?php echo $errors['autoresp_email_id']; ?></span>
             </td>
         </tr>
+        <tr>
+            <th colspan="2">
+                <em><strong>Department Access</strong>: Check all groups allowed to access department.</em>
+            </th>
+        </tr>
+        <tr><td colspan=2><em>Primary department members and manager will always have access regarless of group selection or assignment.</em></td></tr>
+        <?php
+         $sql='SELECT group_id, group_name, count(staff.staff_id) as members '
+             .' FROM '.GROUP_TABLE.' grp '
+             .' LEFT JOIN '.STAFF_TABLE. ' staff USING(group_id) '
+             .' GROUP by grp.group_id '
+             .' ORDER BY group_name';
+         if(($res=db_query($sql)) && db_num_rows($res)){
+            while(list($id, $name, $members) = db_fetch_row($res)) {
+                if($members>0) 
+                    $members=sprintf('<a href="staff.php?a=filter&gid=%d">%d</a>', $id, $members);
+
+                $ck=($info['groups'] && in_array($id,$info['groups']))?'checked="checked"':'';
+                echo sprintf('<tr><td colspan=2>&nbsp;&nbsp;<label><input type="checkbox" name="groups[]" value="%d" %s>&nbsp;%s</label> (%s)</td></tr>',
+                        $id, $ck, $name, $members);
+            }
+         }
+        ?>
         <tr>
             <th colspan="2">
                 <em><strong>Department Signature</strong>: Optional signature used on outgoing emails. &nbsp;<span class="error">&nbsp;<?php echo $errors['signature']; ?></span></em>
@@ -198,7 +235,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
         <tr>
             <td colspan=2>
                 <textarea name="signature" cols="21" rows="5" style="width: 60%;"><?php echo $info['signature']; ?></textarea>
-                <br><em>Signature is made available as a choice, on ticket reply, for public departments.</em>
+                <br><em>Signature is made available as a choice, for public departments, on ticket reply.</em>
             </td>
         </tr>
     </tbody>
diff --git a/include/staff/group.inc.php b/include/staff/group.inc.php
index 8e2e992430fee1bbb0f373a034a478efba2e44a8..a442c3ce02e91c249636d4c762cd9a9ed54b6c89 100644
--- a/include/staff/group.inc.php
+++ b/include/staff/group.inc.php
@@ -8,7 +8,7 @@ if($group && $_REQUEST['a']!='add'){
     $submit_text='Save Changes';
     $info=$group->getInfo();
     $info['id']=$group->getId();
-    $info['depts']=$info['dept_access']?explode(',',$info['dept_access']):array();
+    $info['depts']=$group->getDepartments();
     $qstr.='&id='.$group->getId();
 }else {
     $title='Add New Group';
diff --git a/include/staff/groups.inc.php b/include/staff/groups.inc.php
index 95745e70cd98defcd512cc8c20d97daab56dc591..ccb16257bf74660ae43d4a6abad2013984323221 100644
--- a/include/staff/groups.inc.php
+++ b/include/staff/groups.inc.php
@@ -3,10 +3,13 @@ if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access
 
 $qstr='';
 
-$sql='SELECT grp.*,count(staff.staff_id) as users '
-     .' FROM '.GROUP_TABLE.' grp LEFT JOIN '.STAFF_TABLE.' staff USING(group_id) ';
-$sql.=' WHERE 1';
-$sortOptions=array('name'=>'grp.group_name','status'=>'grp.group_enabled','users'=>'users','created'=>'grp.created','updated'=>'grp.updated');
+$sql='SELECT grp.*,count(staff.staff_id) as users, count(dept.dept_id) as depts '
+     .' FROM '.GROUP_TABLE.' grp '
+     .' LEFT JOIN '.STAFF_TABLE.' staff ON(staff.group_id=grp.group_id) '
+     .' LEFT JOIN '.GROUP_DEPT_TABLE.' dept ON(dept.group_id=grp.group_id) '
+     .' WHERE 1';
+$sortOptions=array('name'=>'grp.group_name','status'=>'grp.group_enabled', 
+                   'users'=>'users', 'depts'=>'depts', 'created'=>'grp.created','updated'=>'grp.updated');
 $orderWays=array('DESC'=>'DESC','ASC'=>'ASC');
 $sort=($_REQUEST['sort'] && $sortOptions[strtolower($_REQUEST['sort'])])?strtolower($_REQUEST['sort']):'name';
 //Sorting options...
@@ -50,9 +53,10 @@ else
     <thead>
         <tr>
             <th width="7px">&nbsp;</th>        
-            <th width="250"><a <?php echo $name_sort; ?> href="groups.php?<?php echo $qstr; ?>&sort=name">Group Name</a></th>
-            <th width="80"><a  <?php echo $status_sort; ?> href="groups.php?<?php echo $qstr; ?>&sort=status">Group Status</a></th>
+            <th width="200"><a <?php echo $name_sort; ?> href="groups.php?<?php echo $qstr; ?>&sort=name">Group Name</a></th>
+            <th width="80"><a  <?php echo $status_sort; ?> href="groups.php?<?php echo $qstr; ?>&sort=status">Status</a></th>
             <th width="80" style="text-align:center;"><a  <?php echo $users_sort; ?>href="groups.php?<?php echo $qstr; ?>&sort=users">Members</a></th>
+            <th width="80" style="text-align:center;"><a  <?php echo $depts_sort; ?>href="groups.php?<?php echo $qstr; ?>&sort=depts">Departments</a></th>
             <th width="100"><a  <?php echo $created_sort; ?> href="groups.php?<?php echo $qstr; ?>&sort=created">Created On</a></th>
             <th width="120"><a  <?php echo $updated_sort; ?> href="groups.php?<?php echo $qstr; ?>&sort=updated">Last Updated</a></th>
         </tr>
@@ -82,6 +86,9 @@ else
                     <?php } ?>
                     &nbsp;
                 </td>
+                <td style="text-align:right;padding-right:30px">&nbsp;&nbsp;
+                    <?php echo $row['depts']; ?>
+                </td>
                 <td><?php echo Format::db_date($row['created']); ?>&nbsp;</td>
                 <td><?php echo Format::db_datetime($row['updated']); ?>&nbsp;</td>
             </tr>
diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php
index 63f2fb31c4a871f60ca13d3fff0f66e5a2c11ae9..8397a4988d504f7394afa6a6ba0a05da7584eb16 100644
--- a/include/staff/tickets.inc.php
+++ b/include/staff/tickets.inc.php
@@ -63,6 +63,7 @@ $qwhere ='';
 $depts=$thisstaff->getDepts();    
 $qwhere =' WHERE ( '
         .'  ticket.staff_id='.db_input($thisstaff->getId());
+
 if(!$thisstaff->showAssignedOnly())
     $qwhere.=' OR ticket.dept_id IN ('.($depts?implode(',',$depts):0).')';
 
diff --git a/include/upgrader/done.inc.php b/include/upgrader/done.inc.php
index ddd5cab75e09b7d5c654b41284860038d5d6387b..f4a55538991d4b8fd6f6814bcb7f08c31e390b7f 100644
--- a/include/upgrader/done.inc.php
+++ b/include/upgrader/done.inc.php
@@ -1,5 +1,7 @@
 <?php
 if(!defined('OSTSCPINC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
+//Destroy the upgrader - we're done! 
+$_SESSION['ost_upgrader']=null;
 ?> 
 <div id="upgrader">
     <div id="main">
diff --git a/include/upgrader/patches/435c62c3-6007d45b.cleanup.sql b/include/upgrader/patches/435c62c3-6007d45b.cleanup.sql
new file mode 100644
index 0000000000000000000000000000000000000000..75192e141510d052fda52b338170ea7b8bc52e4c
--- /dev/null
+++ b/include/upgrader/patches/435c62c3-6007d45b.cleanup.sql
@@ -0,0 +1 @@
+ALTER TABLE `%TABLE_PREFIX%groups` DROP `dept_access`;
diff --git a/include/upgrader/patches/435c62c3-6007d45b.patch.sql b/include/upgrader/patches/435c62c3-6007d45b.patch.sql
new file mode 100644
index 0000000000000000000000000000000000000000..a973c9b25b2bdaa343997df09f5ac3914f0fb64b
--- /dev/null
+++ b/include/upgrader/patches/435c62c3-6007d45b.patch.sql
@@ -0,0 +1,30 @@
+/**
+ *  Move dept_access from group table to group_dept_access table.
+ *
+ * @version 1.7-rc1 Dept_Access
+ */
+
+-- Group department access table
+CREATE TABLE `%TABLE_PREFIX%group_dept_access` (
+  `group_id` int(10) unsigned NOT NULL default '0',
+  `dept_id` int(10) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`group_id`,`dept_id`)
+) ENGINE=MyISAM;
+
+-- Extend membership to groups
+ALTER TABLE `%TABLE_PREFIX%department`
+    ADD `group_membership` tinyint( 1 ) unsigned NOT NULL DEFAULT '0' AFTER `ispublic`;
+
+-- Fix teams dates...
+UPDATE `%TABLE_PREFIX%team` 
+    SET `created`=IF(TO_DAYS(`created`), `created`, IF(TO_DAYS(`updated`), `updated`, NOW())),
+        `updated`=IF(TO_DAYS(`updated`), `updated`, NOW());
+
+-- Fix groups dates... 
+UPDATE `%TABLE_PREFIX%groups` 
+    SET `created`=IF(TO_DAYS(`created`), `created`, IF(TO_DAYS(`updated`), `updated`, NOW())),
+        `updated`=IF(TO_DAYS(`updated`), `updated`, NOW());
+
+-- Finished with patch
+UPDATE `%TABLE_PREFIX%config`
+    SET `schema_signature`='6007d45b580c6ac0206514dbed0f28a6';
diff --git a/main.inc.php b/main.inc.php
index 1de9c91a3185d6a740cf9832069be71c0a29a805..fb720f7cc1bf49710229d7bd0075d9571091c18d 100644
--- a/main.inc.php
+++ b/main.inc.php
@@ -63,7 +63,7 @@
 
     #Current version && schema signature (Changes from version to version)
     define('THIS_VERSION','1.7-DPR4'); //Shown on admin panel
-    define('SCHEMA_SIGNATURE','435c62c3b23795529bcfae7e7371d82e'); //MD5 signature of the db schema. (used to trigger upgrades)
+    define('SCHEMA_SIGNATURE','6007d45b580c6ac0206514dbed0f28a6'); //MD5 signature of the db schema. (used to trigger upgrades)
 
     #load config info
     $configfile='';
@@ -136,6 +136,7 @@
     define('DEPT_TABLE',TABLE_PREFIX.'department');
     define('TOPIC_TABLE',TABLE_PREFIX.'help_topic');
     define('GROUP_TABLE',TABLE_PREFIX.'groups');
+    define('GROUP_DEPT_TABLE', TABLE_PREFIX.'group_dept_access');
     define('TEAM_TABLE',TABLE_PREFIX.'team');
     define('TEAM_MEMBER_TABLE',TABLE_PREFIX.'team_member');
 
diff --git a/scp/groups.php b/scp/groups.php
index 4deefd48ca056e1a6ed8fab71bfa3fbef221c2f5..aa2ee2d11332ab850207e4941447d2ef477fcc03 100644
--- a/scp/groups.php
+++ b/scp/groups.php
@@ -66,7 +66,7 @@ if($_POST){
                     }
                 }elseif($_POST['delete']){
                     foreach($_POST['ids'] as $k=>$v) {
-                        if(($t=Group::lookup($v)) && $t->delete())
+                        if(($g=Group::lookup($v)) && $g->delete())
                             $i++;
                     }
 
diff --git a/setup/inc/sql/osticket-v1.7-mysql.sql b/setup/inc/sql/osticket-v1.7-mysql.sql
index ed6ea688e34b1e00a2adb0cbebdfe22a02e6f3d1..662d749b16b3825ec20afd866cb516d77fb92b3e 100644
--- a/setup/inc/sql/osticket-v1.7-mysql.sql
+++ b/setup/inc/sql/osticket-v1.7-mysql.sql
@@ -175,6 +175,7 @@ CREATE TABLE `%TABLE_PREFIX%department` (
   `dept_name` varchar(32) NOT NULL default '',
   `dept_signature` tinytext NOT NULL,
   `ispublic` tinyint(1) unsigned NOT NULL default '1',
+  `group_membership` tinyint(1) NOT NULL default '0',
   `ticket_auto_response` tinyint(1) NOT NULL default '1',
   `message_auto_response` tinyint(1) NOT NULL default '0',
   `updated` datetime NOT NULL,
@@ -339,7 +340,6 @@ CREATE TABLE `%TABLE_PREFIX%groups` (
   `group_id` int(10) unsigned NOT NULL auto_increment,
   `group_enabled` tinyint(1) unsigned NOT NULL default '1',
   `group_name` varchar(50) NOT NULL default '',
-  `dept_access` varchar(255) NOT NULL default '',
   `can_create_tickets` tinyint(1) unsigned NOT NULL default '1',
   `can_edit_tickets` tinyint(1) unsigned NOT NULL default '1',
   `can_delete_tickets` tinyint(1) unsigned NOT NULL default '0',
@@ -356,10 +356,20 @@ CREATE TABLE `%TABLE_PREFIX%groups` (
   KEY `group_active` (`group_enabled`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%groups` (`group_id`, `group_enabled`, `group_name`, `dept_access`, `can_create_tickets`, `can_edit_tickets`, `can_delete_tickets`, `can_close_tickets`, `can_assign_tickets`, `can_transfer_tickets`, `can_ban_emails`, `can_manage_premade`, `can_manage_faq`, `notes`) VALUES
-    (1, 1, 'Admins', '2,1', 1, 1, 1, 1, 1, 1, 1, 1, 1, 'overlords'),
-    (2, 1, 'Managers', '2,1', 1, 1, 1, 1, 1, 1, 1, 1, 1, ''),
-    (3, 1, 'Staff', '2,1', 1, 1, 0, 1, 1, 1, 0, 0, 0, '');
+INSERT INTO `%TABLE_PREFIX%groups` (`group_id`, `group_enabled`, `group_name`, `can_create_tickets`, `can_edit_tickets`, `can_delete_tickets`, `can_close_tickets`, `can_assign_tickets`, `can_transfer_tickets`, `can_ban_emails`, `can_manage_premade`, `can_manage_faq`, `notes`, `created`, `updated`) VALUES
+    (1, 1, 'Admins', 1, 1, 1, 1, 1, 1, 1, 1, 1, 'overlords', NOW(), NOW()),
+    (2, 1, 'Managers', 1, 1, 1, 1, 1, 1, 1, 1, 1, '', NOW(), NOW()),
+    (3, 1, 'Staff', 1, 1, 0, 1, 1, 1, 0, 0, 0, '', NOW(), NOW());
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%group_dept_access`;
+CREATE TABLE `%TABLE_PREFIX%group_dept_access` (
+  `group_id` int(10) unsigned NOT NULL default '0',
+  `dept_id` int(10) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`group_id`,`dept_id`)
+) ENGINE=MyISAM;
+
+INSERT INTO `%TABLE_PREFIX%group_dept_access` (`group_id`, `dept_id`) VALUES
+    (1, 1), (1, 2), (2, 1), (2, 2), (3, 1), (3, 2);
 
 DROP TABLE IF EXISTS `%TABLE_PREFIX%help_topic`;
 CREATE TABLE `%TABLE_PREFIX%help_topic` (
@@ -520,8 +530,8 @@ CREATE TABLE `%TABLE_PREFIX%team` (
   KEY `lead_id` (`lead_id`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%team` (`lead_id`, `isenabled`, `noalerts`, `name`, `notes`)
-    VALUES (0, 1, 0, 'Level I Support', '');
+INSERT INTO `%TABLE_PREFIX%team` (`lead_id`, `isenabled`, `noalerts`, `name`, `notes`, `created`, `updated`)
+    VALUES (0, 1, 0, 'Level I Support', '', NOW(), NOW());
 
 DROP TABLE IF EXISTS `%TABLE_PREFIX%team_member`;
 CREATE TABLE `%TABLE_PREFIX%team_member` (
diff --git a/setup/inc/sql/osticket-v1.7-mysql.sql.md5 b/setup/inc/sql/osticket-v1.7-mysql.sql.md5
index c3f03508703f6860c9628810c3b59ef8af0ce864..bb0024a2a154824e26573a2133737345cadb433a 100644
--- a/setup/inc/sql/osticket-v1.7-mysql.sql.md5
+++ b/setup/inc/sql/osticket-v1.7-mysql.sql.md5
@@ -1 +1 @@
-435c62c3b23795529bcfae7e7371d82e
+6007d45b580c6ac0206514dbed0f28a6