__('Priority + Most Recently Updated'),
'updated' => __('Most Recently Updated'),
'priority,created' => __('Priority + Most Recently Created'),
'due' => __('Due Date'),
'priority,due' => __('Priority + Due Date'),
'number' => __('Ticket Number'),
'answered' => __('Most Recently Answered'),
'closed' => __('Most Recently Closed'),
'hot' => __('Longest Thread'),
'relevance' => __('Relevance'),
'time' => __('Time'),
'trafficlights' => __('Due Date'),
);
// Queues columns
$queue_columns = array(
'number' => array(
'width' => '7.4%',
'heading' => __('Number'),
),
'trafficlights' => array(// Anpassung Fälligkeitsampel
'width' => '2%',
'heading' => '
',
'sort_col' => 'est_duedate',
),
'date' => array(
'width' => '14.6%',
'heading' => __('Date Created'),
'sort_col' => 'created',
),
'time' => array(// Anpassung timesheet
'width' => '7%',
'heading' => __('Time'),
'sort_col' => 'thread__timeTotal',
),
'subject' => array(
'width' => '29.8%',
'heading' => __('Subject'),
'sort_col' => 'cdata__subject',
),
'dept' => array(
'width' => '16%',
'heading' => __('Department'),
'sort_col' => 'dept__name',
),
'name' => array(
'width' => '18.1%',
'heading' => __('From'),
'sort_col' => 'user__name',
),
'status' => array(
'width' => '8.4%',
'heading' => __('Status'),
'sort_col' => 'status_id',
),
'priority' => array(
'width' => '8.4%',
'heading' => __('Priority'),
'sort_col' => 'cdata__:priority__priority_urgency',
),
'assignee' => array(
'width' => '16%',
'heading' => __('Agent'),
),
);
$use_subquery = true;
// Figure out the queue we're viewing
$queue_key = sprintf('::Q:%s', ObjectModel::OBJECT_TYPE_TICKET);
$queue_name = $_SESSION[$queue_key] ?: '';
switch ($queue_name) {
case 'closed':
$status='closed';
$results_type=__('Closed Tickets');
$showassigned=true; //closed by.
$queue_sort_options = array('closed', 'priority,due', 'due',
'priority,updated', 'priority,created', 'answered', 'number', 'hot',
'time', 'trafficlights');
break;
case 'overdue':
$status='open';
$results_type=__('Overdue Tickets');
$tickets->filter(array('isoverdue'=>1));
$queue_sort_options = array('priority,due', 'due', 'priority,updated',
'updated', 'answered', 'priority,created', 'number', 'hot', 'time',
'trafficlights');
break;
case 'assigned':
$status='open';
$staffId=$thisstaff->getId();
$results_type=__('My Tickets');
$tickets->filter(Q::any(array(
'staff_id'=>$thisstaff->getId(),
Q::all(array('staff_id' => 0, 'team_id__gt' => 0)),
)));
$queue_sort_options = array('updated', 'priority,updated',
'priority,created', 'priority,due', 'due', 'answered', 'number',
'hot', 'time', 'trafficlights');
break;
case 'answered':
$status='open';
$showanswered=true;
$results_type=__('Answered Tickets');
$tickets->filter(array('isanswered'=>1));
$queue_sort_options = array('answered', 'priority,updated', 'updated',
'priority,created', 'priority,due', 'due', 'number', 'hot',
'time', 'trafficlights');
break;
default:
case 'search':
$queue_sort_options = array('priority,updated', 'priority,created',
'priority,due', 'due', 'updated', 'answered',
'closed', 'number', 'hot', 'time', 'trafficlights');
// Consider basic search
if ($_REQUEST['query']) {
$results_type=__('Search Results');
// Use an index if possible
if ($_REQUEST['search-type'] == 'typeahead') {
if (Validator::is_email($_REQUEST['query'])) {
$tickets = $tickets->filter(array(
'user__emails__address' => $_REQUEST['query'],
));
}
elseif ($_REQUEST['query']) {
$tickets = $tickets->filter(array(
'number' => $_REQUEST['query'],
));
}
}
elseif (isset($_REQUEST['query'])
&& ($q = trim($_REQUEST['query']))
&& strlen($q) > 2
) {
// [Search] click, consider keywords
$__tickets = $ost->searcher->find($q, $tickets);
if (!count($__tickets) && preg_match('`\w$`u', $q)) {
// Do wildcard search if no hits
$__tickets = $ost->searcher->find($q.'*', $tickets);
}
$tickets = $__tickets;
$has_relevance = true;
}
// Clear sticky search queue
unset($_SESSION[$queue_key]);
break;
}
// Apply user filter
elseif (isset($_GET['uid']) && ($user = User::lookup($_GET['uid']))) {
$tickets->filter(array('user__id'=>$_GET['uid']));
$results_type = sprintf('%s — %s', __('Search Results'),
$user->getName());
if (isset($_GET['status']))
$status = $_GET['status'];
// Don't apply normal open ticket
break;
}
elseif (isset($_GET['orgid']) && ($org = Organization::lookup($_GET['orgid']))) {
$tickets->filter(array('user__org_id'=>$_GET['orgid']));
$results_type = sprintf('%s — %s', __('Search Results'),
$org->getName());
if (isset($_GET['status']))
$status = $_GET['status'];
// Don't apply normal open ticket
break;
} elseif (isset($_SESSION['advsearch'])) {
$form = $search->getFormFromSession('advsearch');
$tickets = $search->mangleQuerySet($tickets, $form);
$view_all_tickets = $thisstaff->hasPerm(SearchBackend::PERM_EVERYTHING);
$results_type=__('Advanced Search')
. ' ' . __('clear') . '';
foreach ($form->getFields() as $sf) {
if ($sf->get('name') == 'keywords' && $sf->getClean()) {
$has_relevance = true;
break;
}
}
break;
}
// Fall-through and show open tickets
case 'open':
$status='open';
$queue_name = $queue_name ?: 'open';
$results_type=__('Open Tickets');
if (!$cfg->showAnsweredTickets())
$tickets->filter(array('isanswered'=>0));
$queue_sort_options = array('priority,updated', 'updated',
'priority,due', 'due', 'priority,created', 'answered', 'number',
'hot', 'time', 'trafficlights');
break;
}
// Open queues _except_ assigned should respect showAssignedTickets()
// settings
if ($status != 'closed' && $queue_name != 'assigned') {
$hideassigned = ($cfg && !$cfg->showAssignedTickets()) && !$thisstaff->showAssignedTickets();
$showassigned = !$hideassigned;
if ($queue_name == 'open' && $hideassigned)
$tickets->filter(array('staff_id'=>0, 'team_id'=>0));
}
// Apply primary ticket status
if ($status)
$tickets->filter(array('status__state'=>$status));
//
if($ds['deptId'] > 0)
$tickets->filter(array('dept_id'=>$ds['deptId']));
//
// Impose visibility constraints
// ------------------------------------------------------------
if (!$view_all_tickets) {
// -- Open and assigned to me
$assigned = Q::any(array(
'staff_id' => $thisstaff->getId(),
));
// -- Open and assigned to a team of mine
if ($teams = array_filter($thisstaff->getTeams()))
$assigned->add(array('team_id__in' => $teams));
$visibility = Q::any(new Q(array('status__state'=>'open', $assigned)));
// -- Routed to a department of mine
if (!$thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts()))
$visibility->add(array('dept_id__in' => $depts));
// Anpassung MAs mit limited Access zeige Geschlossene Anfang
if ($thisstaff->showAssignedOnly() && ($depts=$thisstaff->getDepts()))
$visibility->add(Q::all(new Q(array('dept_id__in' => $depts, 'staff_id' => $thisstaff->getId()))));
// Anpassung MAs mit limited Access zeige Geschlossene Ende
$tickets->filter(Q::any($visibility));
}
// TODO :: Apply requested quick filter
// Apply requested pagination
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
$count = $tickets->count();
$pageNav = new Pagenate($count, $page, PAGE_LIMIT);
$pageNav->setURL('tickets.php', $args);
$tickets = $pageNav->paginate($tickets);
// Apply requested sorting
$queue_sort_key = sprintf(':Q%s:%s:sort', ObjectModel::OBJECT_TYPE_TICKET, $queue_name);
// If relevance is available, use it as the default
if ($has_relevance) {
array_unshift($queue_sort_options, 'relevance');
}
elseif ($_SESSION[$queue_sort_key][0] == 'relevance') {
unset($_SESSION[$queue_sort_key]);
}
if (isset($_GET['sort'])) {
$_SESSION[$queue_sort_key] = array($_GET['sort'], $_GET['dir']);
}
elseif (!isset($_SESSION[$queue_sort_key])) {
$_SESSION[$queue_sort_key] = array($queue_sort_options[0], 0);
}
list($sort_cols, $sort_dir) = $_SESSION[$queue_sort_key];
$orm_dir = $sort_dir ? QuerySet::ASC : QuerySet::DESC;
$orm_dir_r = $sort_dir ? QuerySet::DESC : QuerySet::ASC;
switch ($sort_cols) {
case 'number':
$queue_columns['number']['sort_dir'] = $sort_dir;
$tickets->extra(array(
'order_by'=>array(
array(SqlExpression::times(new SqlField('number'), 1), $orm_dir)
)
));
break;
case 'priority,created':
$tickets->order_by(($sort_dir ? '-' : '') . 'cdata__:priority__priority_urgency');
// Fall through to columns for `created`
case 'created':
$queue_columns['date']['heading'] = __('Date Created');
$queue_columns['date']['sort_col'] = $date_col = 'created';
$tickets->values('created');
$tickets->order_by($sort_dir ? 'created' : '-created');
break;
case 'time':
$queue_columns['time']['heading'] = __('Time');
$queue_columns['time']['sort'] = 'time';
$queue_columns['time']['sort_col'] = 'time';
$queue_columns['time']['sort_dir'] = $sort_dir;
$tickets->order_by($sort_dir ? 'thread__timeTotal' : '-thread__timeTotal');
break;
case 'trafficlights':// Anpassung Fälligkeitsampel
$queue_columns['trafficlights']['heading'] = ($sort_dir)?'
':
'
';
$queue_columns['trafficlights']['sort'] = 'trafficlights';
$queue_columns['trafficlights']['sort_col'] = 'est_duedate';
$queue_columns['trafficlights']['sort_dir'] = $sort_dir;
//$tickets->values('est_duedate');// Anpassung Fälligkeitsampel
$tickets->order_by(SqlFunction::COALESCE(new SqlField('est_duedate'), 'zzz'), $orm_dir_r);
break;
case 'priority,due':
$tickets->order_by('cdata__:priority__priority_urgency', $orm_dir_r);
// Fall through to add in due date filter
case 'due':
$queue_columns['date']['heading'] = __('Due Date');
$queue_columns['date']['sort'] = 'due';
$queue_columns['date']['sort_col'] = $date_col = 'est_duedate';
//$tickets->values('est_duedate');// Anpassung Fälligkeitsampel
$tickets->order_by(SqlFunction::COALESCE(new SqlField('est_duedate'), 'zzz'), $orm_dir_r);
break;
case 'closed':
$queue_columns['date']['heading'] = __('Date Closed');
$queue_columns['date']['sort'] = $sort_cols;
$queue_columns['date']['sort_col'] = $date_col = 'closed';
$queue_columns['date']['sort_dir'] = $sort_dir;
$tickets->values('closed');
$tickets->order_by('closed', $orm_dir);
break;
case 'answered':
$queue_columns['date']['heading'] = __('Last Response');
$queue_columns['date']['sort'] = $sort_cols;
$queue_columns['date']['sort_col'] = $date_col = 'thread__lastresponse';
$queue_columns['date']['sort_dir'] = $sort_dir;
$date_fallback = ''.__('unanswered').'';
$tickets->order_by('thread__lastresponse', $orm_dir);
$tickets->values('thread__lastresponse');
break;
case 'hot':
$tickets->order_by('thread_count', $orm_dir);
$tickets->annotate(array(
'thread_count' => SqlAggregate::COUNT('thread__entries'),
));
break;
case 'relevance':
$tickets->order_by(new SqlCode('__relevance__'), $orm_dir);
break;
case 'assignee':
$tickets->order_by('staff__lastname', $orm_dir);
$tickets->order_by('staff__firstname', $orm_dir);
$tickets->order_by('team__name', $orm_dir);
$queue_columns['assignee']['sort_dir'] = $sort_dir;
break;
default:
if ($sort_cols && isset($queue_columns[$sort_cols])) {
$queue_columns[$sort_cols]['sort_dir'] = $sort_dir;
if (isset($queue_columns[$sort_cols]['sort_col']))
$sort_cols = $queue_columns[$sort_cols]['sort_col'];
$tickets->order_by($sort_cols, $orm_dir);
break;
}
case 'priority,updated':
$tickets->order_by('cdata__:priority__priority_urgency', $orm_dir_r);
// Fall through for columns defined for `updated`
case 'updated':
$queue_columns['date']['heading'] = __('Last Updated');
$queue_columns['date']['sort'] = $sort_cols;
$queue_columns['date']['sort_col'] = $date_col = 'lastupdate';
$tickets->order_by('lastupdate', $orm_dir);
break;
}
// Anpassung Fälligkeitsampel Anfang
$tickets->values('sla');
$tickets->values('duedate');
$tickets->values('est_duedate');
// Anpassung Timesheet
$tickets->values('thread__timeTotal');
// Anpassung Fälligkeitsampel Ende
if (in_array($sort_cols, array('created', 'due', 'updated')))
$queue_columns['date']['sort_dir'] = $sort_dir;
// Rewrite $tickets to use a nested query, which will include the LIMIT part
// in order to speed the result
$orig_tickets = clone $tickets;
$tickets2 = TicketModel::objects();
$tickets2->values = $tickets->values;
$tickets2->filter(array('ticket_id__in' => $tickets->values_flat('ticket_id')));
// Transfer the order_by from the original tickets
$tickets2->order_by($orig_tickets->getSortFields());
$tickets = $tickets2;
// Save the query to the session for exporting
$_SESSION[':Q:tickets'] = $tickets;
TicketForm::ensureDynamicDataView();
// Select pertinent columns
// ------------------------------------------------------------
$tickets->values('lock__staff_id', 'staff_id', 'isoverdue', 'team_id', 'thread__timeTotal', 'thread__id',
'ticket_id', 'number', 'cdata__subject', 'user__default_email__address',
'source', 'cdata__:priority__priority_color', 'cdata__:priority__priority_desc', 'status_id', 'status__name', 'status__state', 'dept_id', 'dept__name', 'user__name', 'lastupdate', 'isanswered', 'staff__firstname', 'staff__lastname', 'team__name');
// Add in annotations
$tickets->annotate(array(
'collab_count' => TicketThread::objects()
->filter(array('ticket__ticket_id' => new SqlField('ticket_id', 1)))
->aggregate(array('count' => SqlAggregate::COUNT('collaborators__id'))),
'attachment_count' => TicketThread::objects()
->filter(array('ticket__ticket_id' => new SqlField('ticket_id', 1)))
->filter(array('entries__attachments__inline' => 0))
->aggregate(array('count' => SqlAggregate::COUNT('entries__attachments__id'))),
'thread_count' => TicketThread::objects()
->filter(array('ticket__ticket_id' => new SqlField('ticket_id', 1)))
->exclude(array('entries__flags__hasbit' => ThreadEntry::FLAG_HIDDEN))
->aggregate(array('count' => SqlAggregate::COUNT('entries__id'))),
));
// Make sure we're only getting active locks
$tickets->constrain(array('lock' => array(
'lock__expire__gt' => SqlFunction::NOW())));
?>