diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index bb834578064358a26e77c2a1a6ec82f5df6eba9f..1d887f04349241327a324d43b8a2d31545c45cf1 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -85,10 +85,10 @@ class TicketsAjaxAPI extends AjaxController { } function search() { - global $thisstaff; + global $thisstaff, $cfg; $result=array(); - $select = 'SELECT count(ticket.ticket_id) as tickets '; + $select = 'SELECT count( DISTINCT ticket.ticket_id) as tickets '; $from = ' FROM '.TICKET_TABLE.' ticket '; $where = ' WHERE 1 '; @@ -107,11 +107,18 @@ class TicketsAjaxAPI extends AjaxController { if($_REQUEST['deptId']) $where.=' AND ticket.dept_id='.db_input($_REQUEST['deptId']); + //Help topic + if($_REQUEST['topicId']) + $where.=' AND ticket.topic_id='.db_input($_REQUEST['topicId']); + //Status switch(strtolower($_REQUEST['status'])) { - case 'open'; + case 'open': $where.=' AND ticket.status="open" '; break; + case 'answered': + $where.=' AND ticket.status="open" AND ticket.isanswered=1 '; + break; case 'overdue': $where.=' AND ticket.status="open" AND ticket.isoverdue=1 '; break; @@ -121,19 +128,23 @@ class TicketsAjaxAPI extends AjaxController { } //Assignee - if($_REQUEST['assignee'] && strcasecmp($_REQUEST['status'], 'closed')) { + if(isset($_REQUEST['assignee']) && strcasecmp($_REQUEST['status'], 'closed')) { $id=preg_replace("/[^0-9]/", "", $_REQUEST['assignee']); $assignee = $_REQUEST['assignee']; - $where.= ' AND ( '; + $where.= ' AND ( ( ticket.status="open" '; if($assignee[0]=='t') - $where.=' (ticket.team_id='.db_input($id). ' AND ticket.status="open") '; + $where.=' AND ticket.team_id='.db_input($id); elseif($assignee[0]=='s') - $where.=' (ticket.staff_id='.db_input($id). ' AND ticket.status="open") '; - else - $where.=' (ticket.staff_id='.db_input($id). ' AND ticket.status="open") '; + $where.=' AND ticket.staff_id='.db_input($id); + elseif(is_numeric($id)) + $where.=' AND ticket.staff_id='.db_input($id); + + $where.=')'; if($_REQUEST['staffId'] && !$_REQUEST['status']) //Assigned TO + Closed By - $where.= ' OR (ticket.staff_id='.db_input($_REQUEST['staffId']). ' AND ticket.status="closed") '; + $where.= ' OR (ticket.staff_id='.db_input($_REQUEST['staffId']). ' AND ticket.status="closed") '; + elseif(isset($_REQUEST['staffId'])) // closed by any + $where.= ' OR ticket.status="closed" '; $where.= ' ) '; } elseif($_REQUEST['staffId']) { @@ -163,7 +174,6 @@ class TicketsAjaxAPI extends AjaxController { ." OR thread.title LIKE '%$queryterm%'" ." OR thread.body LIKE '%$queryterm%'" .' )'; - $groupby = 'GROUP BY ticket.ticket_id '; } $sql="$select $from $where $groupby"; diff --git a/include/class.export.php b/include/class.export.php index 3c289550121366e8fd53e59c51e8715f0db27385..372cf62e2d6c55f09e25c59be29ba9691f075df5 100644 --- a/include/class.export.php +++ b/include/class.export.php @@ -41,6 +41,7 @@ class Export { 'name' => 'From', 'priority_desc' => 'Priority', 'dept_name' => 'Department', + 'helptopic' => 'Help Topic', 'source' => 'Source', 'status' => 'Current Status' ), diff --git a/include/class.ticket.php b/include/class.ticket.php index a7a16e4644ba357db5f619ec50760de71de60a20..d94a3818e1247a1b699bdfd2825787d3f5c2cb9c 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -2013,20 +2013,31 @@ class Ticket { if(!$staff || (!is_object($staff) && !($staff=Staff::lookup($staff))) || !$staff->isStaff() || $cfg->getDBVersion()) return null; - $sql='SELECT count(open.ticket_id) as open, count(answered.ticket_id) as answered ' .' ,count(overdue.ticket_id) as overdue, count(assigned.ticket_id) as assigned, count(closed.ticket_id) as closed ' .' FROM '.TICKET_TABLE.' ticket ' .' LEFT JOIN '.TICKET_TABLE.' open - ON (open.ticket_id=ticket.ticket_id AND open.status=\'open\' AND open.isanswered=0) ' + ON (open.ticket_id=ticket.ticket_id + AND open.status=\'open\' + AND open.isanswered=0 + '.((!($cfg->showAssignedTickets() || $staff->showAssignedTickets()))? + ' AND open.staff_id=0 ':'').') ' .' LEFT JOIN '.TICKET_TABLE.' answered - ON (answered.ticket_id=ticket.ticket_id AND answered.status=\'open\' AND answered.isanswered=1) ' + ON (answered.ticket_id=ticket.ticket_id + AND answered.status=\'open\' + AND answered.isanswered=1) ' .' LEFT JOIN '.TICKET_TABLE.' overdue - ON (overdue.ticket_id=ticket.ticket_id AND overdue.status=\'open\' AND overdue.isoverdue=1) ' + ON (overdue.ticket_id=ticket.ticket_id + AND overdue.status=\'open\' + AND overdue.isoverdue=1) ' .' LEFT JOIN '.TICKET_TABLE.' assigned - ON (assigned.ticket_id=ticket.ticket_id AND assigned.status=\'open\' AND assigned.staff_id='.db_input($staff->getId()).')' + ON (assigned.ticket_id=ticket.ticket_id + AND assigned.status=\'open\' + AND assigned.staff_id='.db_input($staff->getId()).')' .' LEFT JOIN '.TICKET_TABLE.' closed - ON (closed.ticket_id=ticket.ticket_id AND closed.status=\'closed\' AND closed.staff_id='.db_input($staff->getId()).')' + ON (closed.ticket_id=ticket.ticket_id + AND closed.status=\'closed\' + AND closed.staff_id='.db_input($staff->getId()).')' .' WHERE (ticket.staff_id='.db_input($staff->getId()); if(($teams=$staff->getTeams())) @@ -2037,10 +2048,6 @@ class Ticket { $sql.=')'; - if(!$cfg || !($cfg->showAssignedTickets() || $staff->showAssignedTickets())) - $sql.=' AND (ticket.staff_id=0 OR ticket.staff_id='.db_input($staff->getId()).') '; - - return db_fetch_array(db_query($sql)); } diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php index ecbedfc668bda09277ebd21ef71e4bd921391ebb..ed5916196bcbb731cd1ced3ed4db19e4a2ea80bb 100644 --- a/include/staff/tickets.inc.php +++ b/include/staff/tickets.inc.php @@ -19,10 +19,9 @@ if($search) { $searchTerm=''; } } -$showoverdue=$showanswered=$showassigned=false; +$showoverdue=$showanswered=false; $staffId=0; //Nothing for now...TODO: Allow admin and manager to limit tickets to single staff level. -//show Assigned To column, if enabled. Admins and managers can overwrite system settings! -$showassigned=(($cfg->showAssignedTickets() || $thisstaff->showAssignedTickets()) && !$search); +$showassigned= true; //show Assigned To column - defaults to true //Get status we are actually going to use on the query...making sure it is clean! $status=null; @@ -32,7 +31,7 @@ switch(strtolower($_REQUEST['status'])){ //Status is overloaded break; case 'closed': $status='closed'; - $showassigned=false; + $showassigned=true; //closed by. break; case 'overdue': $status='open'; @@ -51,7 +50,7 @@ switch(strtolower($_REQUEST['status'])){ //Status is overloaded break; default: if(!$search) - $status='open'; + $_REQUEST['status']=$status='open'; } $qwhere =''; @@ -77,8 +76,8 @@ if($status) { $qwhere.=' AND status='.db_input(strtolower($status)); } -//Overloaded sub-statuses - you've got to just have faith! -if($staffId && ($staffId==$thisstaff->getId())) { //Staff's assigned tickets. +//Queues: Overloaded sub-statuses - you've got to just have faith! +if($staffId && ($staffId==$thisstaff->getId())) { //My tickets $results_type='Assigned Tickets'; $qwhere.=' AND ticket.staff_id='.db_input($staffId); $showassigned=false; //My tickets...already assigned to the staff. @@ -86,14 +85,20 @@ if($staffId && ($staffId==$thisstaff->getId())) { //Staff's assigned tickets. $qwhere.=' AND isoverdue=1 '; }elseif($showanswered) { ////Answered $qwhere.=' AND isanswered=1 '; -}elseif(!$search && !$cfg->showAnsweredTickets() && !strcasecmp($status,'open')) { - $qwhere.=' AND isanswered=0 '; +}elseif(!strcasecmp($status, 'open') && !$search) { //Open queue (on search OPEN means all open tickets - regardless of state). + //Showing answered tickets on open queue?? + if(!$cfg->showAnsweredTickets()) + $qwhere.=' AND isanswered=0 '; + + /* Showing assigned tickets on open queue? + Don't confuse it with show assigned To column -> F'it it's confusing - just trust me! + */ + if(!($cfg->showAssignedTickets() || $thisstaff->showAssignedTickets())) { + $qwhere.=' AND ticket.staff_id=0 '; //XXX: NOT factoring in team assignments - only staff assignments. + $showassigned=false; //Not showing Assigned To column since assigned tickets are not part of open queue + } } -//******* Showing assigned tickets? (don't confuse it with show assigned To column). F'it it's confusing - just trust me! ***/ -if(!($cfg->showAssignedTickets() || $thisstaff->showAssignedTickets()) && strcasecmp($status,'closed') && !$search) - $sql.=' AND (ticket.staff_id=0 OR ticket.staff_id='.db_input($thisstaff->getId()).') '; - //Search?? Somebody...get me some coffee $deep_search=false; if($search): @@ -137,25 +142,36 @@ if($search): $qwhere.=' AND ticket.dept_id='.db_input($_REQUEST['deptId']); $qstr.='&deptId='.urlencode($_REQUEST['deptId']); } + + //Help topic + if($_REQUEST['topicId']) { + $qwhere.=' AND ticket.topic_id='.db_input($_REQUEST['topicId']); + $qstr.='&topicId='.urlencode($_REQUEST['topicId']); + } //Assignee - if($_REQUEST['assignee'] && strcasecmp($_REQUEST['status'], 'closed')) { + if(isset($_REQUEST['assignee']) && strcasecmp($_REQUEST['status'], 'closed')) { $id=preg_replace("/[^0-9]/", "", $_REQUEST['assignee']); $assignee = $_REQUEST['assignee']; $qstr.='&assignee='.urlencode($_REQUEST['assignee']); - $qwhere.= ' AND ( '; + $qwhere.= ' AND ( + ( ticket.status="open" '; if($assignee[0]=='t') - $qwhere.=' (ticket.team_id='.db_input($id). ' AND ticket.status="open") '; + $qwhere.=' AND ticket.team_id='.db_input($id); elseif($assignee[0]=='s') - $qwhere.=' (ticket.staff_id='.db_input($id). ' AND ticket.status="open") '; - else - $qwhere.=' (ticket.staff_id='.db_input($id). ' AND ticket.status="open") '; + $qwhere.=' AND ticket.staff_id='.db_input($id); + elseif(is_numeric($id)) + $qwhere.=' AND ticket.staff_id='.db_input($id); + $qwhere.=' ) '; if($_REQUEST['staffId'] && !$_REQUEST['status']) { //Assigned TO + Closed By $qwhere.= ' OR (ticket.staff_id='.db_input($_REQUEST['staffId']). ' AND ticket.status="closed") '; $qstr.='&staffId='.urlencode($_REQUEST['staffId']); + }elseif(isset($_REQUEST['staffId'])) { + $qwhere.= ' OR ticket.status="closed" '; + $qstr.='&staffId='.urlencode($_REQUEST['staffId']); } $qwhere.= ' ) '; @@ -263,7 +279,8 @@ $qselect.=' ,count(attach.attach_id) as attachments ' .' ,IF(ticket.duedate IS NULL,IF(sla.id IS NULL, NULL, DATE_ADD(ticket.created, INTERVAL sla.grace_period HOUR)), ticket.duedate) as duedate ' .' ,IF(ticket.reopened is NULL,IF(ticket.lastmessage is NULL,ticket.created,ticket.lastmessage),ticket.reopened) as effective_date ' .' ,CONCAT_WS(" ", staff.firstname, staff.lastname) as staff, team.name as team ' - .' ,IF(staff.staff_id IS NULL,team.name,CONCAT_WS(" ", staff.lastname, staff.firstname)) as assigned '; + .' ,IF(staff.staff_id IS NULL,team.name,CONCAT_WS(" ", staff.lastname, staff.firstname)) as assigned ' + .' ,IF(ptopic.topic_pid IS NULL, topic.topic, CONCAT_WS(" / ", ptopic.topic, topic.topic)) as helptopic '; $qfrom.=' LEFT JOIN '.TICKET_PRIORITY_TABLE.' pri ON (ticket.priority_id=pri.priority_id) ' .' LEFT JOIN '.TICKET_LOCK_TABLE.' tlock ON (ticket.ticket_id=tlock.ticket_id AND tlock.expire>NOW() @@ -272,7 +289,10 @@ $qfrom.=' LEFT JOIN '.TICKET_PRIORITY_TABLE.' pri ON (ticket.priority_id=pri.pri .' LEFT JOIN '.TICKET_THREAD_TABLE.' thread ON ( ticket.ticket_id=thread.ticket_id) ' .' LEFT JOIN '.STAFF_TABLE.' staff ON (ticket.staff_id=staff.staff_id) ' .' LEFT JOIN '.TEAM_TABLE.' team ON (ticket.team_id=team.team_id) ' - .' LEFT JOIN '.SLA_TABLE.' sla ON (ticket.sla_id=sla.id AND sla.isactive=1) '; + .' LEFT JOIN '.SLA_TABLE.' sla ON (ticket.sla_id=sla.id AND sla.isactive=1) ' + .' LEFT JOIN '.TOPIC_TABLE.' topic ON (ticket.topic_id=topic.topic_id) ' + .' LEFT JOIN '.TOPIC_TABLE.' ptopic ON (ptopic.topic_id=topic.topic_pid) '; + $query="$qselect $qfrom $qwhere $qgroup ORDER BY $order_by $order LIMIT ".$pageNav->getStart().",".$pageNav->getLimit(); //echo $query; @@ -346,20 +366,23 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting.. <?php } - if($showassigned){ ?> - <th width="150"> - <a <?php echo $assignee_sort; ?> href="tickets.php?sort=assignee&order=<?php echo $negorder; ?><?php echo $qstr; ?>" - title="Sort By Assignee <?php echo $negorder;?>">Assigned To</a></th> - <?php - } elseif(!strcasecmp($status,'closed')) { ?> - <th width="150"> - <a <?php echo $staff_sort; ?> href="tickets.php?sort=staff&order=<?php echo $negorder; ?><?php echo $qstr; ?>" - title="Sort By Closing Staff Name <?php echo $negorder; ?>">Closed By</a></th> - <?php + if($showassigned ) { + //Closed by + if(!strcasecmp($status,'closed')) { ?> + <th width="150"> + <a <?php echo $staff_sort; ?> href="tickets.php?sort=staff&order=<?php echo $negorder; ?><?php echo $qstr; ?>" + title="Sort By Closing Staff Name <?php echo $negorder; ?>">Closed By</a></th> + <?php + } else { //assigned to ?> + <th width="150"> + <a <?php echo $assignee_sort; ?> href="tickets.php?sort=assignee&order=<?php echo $negorder; ?><?php echo $qstr; ?>" + title="Sort By Assignee <?php echo $negorder;?>">Assigned To</a></th> + <?php + } } else { ?> - <th width="150"> - <a <?php echo $dept_sort; ?> href="tickets.php?sort=dept&order=<?php echo $negorder;?><?php echo $qstr; ?>" - title="Sort By Department <?php echo $negorder; ?>">Department</a></th> + <th width="150"> + <a <?php echo $dept_sort; ?> href="tickets.php?sort=dept&order=<?php echo $negorder;?><?php echo $qstr; ?>" + title="Sort By Department <?php echo $negorder; ?>">Department</a></th> <?php } ?> </tr> @@ -379,7 +402,7 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting.. $flag='overdue'; $lc=''; - if($showassigned || !strcasecmp($status,'closed')) { + if($showassigned) { if($row['staff_id']) $lc=sprintf('<span class="Icon staffAssigned">%s</span>',Format::truncate($row['staff'],40)); elseif($row['team_id']) @@ -544,6 +567,11 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting.. <select id="status" name="status"> <option value="">— Any Status —</option> <option value="open">Open</option> + <?php + if(!$cfg->showAnsweredTickets()) {?> + <option value="answered">Answered</option> + <?php + } ?> <option value="overdue">Overdue</option> <option value="closed">Closed</option> </select> @@ -563,7 +591,9 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting.. <fieldset class="owner"> <label for="assignee">Assigned To:</label> <select id="assignee" name="assignee"> - <option value="0">— Anyone —</option> + <option value="">— Anyone —</option> + <option value="0">— Unassigned —</option> + <option value="<?php echo $thisstaff->getId(); ?>">Me</option> <?php if(($users=Staff::getStaffMembers())) { echo '<OPTGROUP label="Staff Members ('.count($users).')">'; @@ -587,6 +617,7 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting.. <label for="staffId">Closed By:</label> <select id="staffId" name="staffId"> <option value="0">— Anyone —</option> + <option value="<?php echo $thisstaff->getId(); ?>">Me</option> <?php if(($users=Staff::getStaffMembers())) { foreach($users as $id => $name) @@ -595,6 +626,18 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting.. ?> </select> </fieldset> + <fieldset> + <label for="topicId">Help Topic:</label> + <select id="topicId" name="topicId"> + <option value="" selected >— All Help Topics —</option> + <?php + if($topics=Topic::getHelpTopics()) { + foreach($topics as $id =>$name) + echo sprintf('<option value="%d" >%s</option>', $id, $name); + } + ?> + </select> + </fieldset> <fieldset class="date_range"> <label>Date Range:</label> <input class="dp" type="input" size="20" name="startDate"> diff --git a/scp/js/scp.js b/scp/js/scp.js index cf32e42d8b638ff1b465cb23eb9a196e72be31ba..8ce35149ee3909130fa8d1a42ff202246ccb8981 100644 --- a/scp/js/scp.js +++ b/scp/js/scp.js @@ -369,6 +369,7 @@ $(document).ready(function(){ break; case 'open': case 'overdue': + case 'answered': $('select#staffId').find('option:first').attr('selected', 'selected').parent('select'); $('select#staffId').attr('disabled','disabled'); $('select#assignee').removeAttr('disabled'); diff --git a/scp/tickets.php b/scp/tickets.php index 9e436f200fe08f3348423d46f0118ba101fa0813..37683eabfc7adc13ed2a7580ea35fdbdb34ce496 100644 --- a/scp/tickets.php +++ b/scp/tickets.php @@ -450,7 +450,7 @@ $stats= $thisstaff->getTicketsStats(); //Navigation $nav->setTabActive('tickets'); if($cfg->showAnsweredTickets()) { - $nav->addSubMenu(array('desc'=>'Open ('.($stats['open']+$stats['answered']).')', + $nav->addSubMenu(array('desc'=>'Open ('.number_format($stats['open']+$stats['answered']).')', 'title'=>'Open Tickets', 'href'=>'tickets.php', 'iconclass'=>'Ticket'), @@ -458,7 +458,7 @@ if($cfg->showAnsweredTickets()) { } else { if($stats) { - $nav->addSubMenu(array('desc'=>'Open ('.$stats['open'].')', + $nav->addSubMenu(array('desc'=>'Open ('.number_format($stats['open']).')', 'title'=>'Open Tickets', 'href'=>'tickets.php', 'iconclass'=>'Ticket'), @@ -466,7 +466,7 @@ if($cfg->showAnsweredTickets()) { } if($stats['answered']) { - $nav->addSubMenu(array('desc'=>'Answered ('.$stats['answered'].')', + $nav->addSubMenu(array('desc'=>'Answered ('.number_format($stats['answered']).')', 'title'=>'Answered Tickets', 'href'=>'tickets.php?status=answered', 'iconclass'=>'answeredTickets'), @@ -478,7 +478,7 @@ if($stats['assigned']) { if(!$ost->getWarning() && $stats['assigned']>10) $ost->setWarning($stats['assigned'].' tickets assigned to you! Do something about it!'); - $nav->addSubMenu(array('desc'=>'My Tickets ('.$stats['assigned'].')', + $nav->addSubMenu(array('desc'=>'My Tickets ('.number_format($stats['assigned']).')', 'title'=>'Assigned Tickets', 'href'=>'tickets.php?status=assigned', 'iconclass'=>'assignedTickets'), @@ -486,7 +486,7 @@ if($stats['assigned']) { } if($stats['overdue']) { - $nav->addSubMenu(array('desc'=>'Overdue ('.$stats['overdue'].')', + $nav->addSubMenu(array('desc'=>'Overdue ('.number_format($stats['overdue']).')', 'title'=>'Stale Tickets', 'href'=>'tickets.php?status=overdue', 'iconclass'=>'overdueTickets'), @@ -497,14 +497,14 @@ if($stats['overdue']) { } if($thisstaff->showAssignedOnly() && $stats['closed']) { - $nav->addSubMenu(array('desc'=>'My Closed Tickets ('.$stats['closed'].')', + $nav->addSubMenu(array('desc'=>'My Closed Tickets ('.number_format($stats['closed']).')', 'title'=>'My Closed Tickets', 'href'=>'tickets.php?status=closed', 'iconclass'=>'closedTickets'), ($_REQUEST['status']=='closed')); } else { - $nav->addSubMenu(array('desc'=>'Closed Tickets', + $nav->addSubMenu(array('desc'=>'Closed Tickets ('.number_format($stats['closed']).')', 'title'=>'Closed Tickets', 'href'=>'tickets.php?status=closed', 'iconclass'=>'closedTickets'),