diff --git a/admin/post/sla.php b/admin/post/sla.php index 837fb71a..efcf30a9 100644 --- a/admin/post/sla.php +++ b/admin/post/sla.php @@ -109,6 +109,9 @@ if (isset($_POST['edit_sla_settings'])) { mysqli_query($mysqli, "UPDATE settings SET config_business_days = '$business_days', config_business_hours_start = '$business_hours_start', config_business_hours_end = '$business_hours_end', config_sla_warning_percent = $warning_percent, config_sla_notification_email = '$notification_email' WHERE company_id = 1"); + // Drop the cached copy so the restamp below uses the hours just saved + getSlaSettings(true); + // Business hours feed the due date math - re-stamp open SLA tickets $restamped = 0; $sql_tickets = mysqli_query($mysqli, "SELECT ticket_id, ticket_sla_id FROM tickets WHERE ticket_sla_id > 0 AND ticket_closed_at IS NULL AND ticket_archived_at IS NULL"); diff --git a/agent/reports/sla_by_client.php b/agent/reports/sla_by_client.php index ee4f7962..5bbe800e 100644 --- a/agent/reports/sla_by_client.php +++ b/agent/reports/sla_by_client.php @@ -27,18 +27,31 @@ $sql_ticket_years = mysqli_query($mysqli, "SELECT DISTINCT YEAR(ticket_created_a $sql_clients = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients WHERE client_archived_at IS NULL ORDER BY client_name ASC"); -function slaPercentDisplay($percent) -{ - if (is_null($percent)) { - return "-"; + +// Clock time spent on resolved tickets, gathered for every client at once +// rather than per ticket. Tickets with no interval rows - response-only plans, +// or anything resolved before SLA pausing existed - fall back to the business +// time that elapsed between being raised and resolved. +$resolve_totals = []; +$sql_resolve_times = mysqli_query($mysqli, "SELECT ticket_client_id, ticket_id, ticket_created_at, ticket_resolved_at, SUM(sla_history_minutes) AS logged_minutes + FROM tickets + LEFT JOIN sla_history ON sla_history_ticket_id = ticket_id + WHERE ticket_sla_id > 0 + AND ticket_resolved_at IS NOT NULL + AND $period_query + GROUP BY ticket_id, ticket_client_id, ticket_created_at, ticket_resolved_at" +); +while ($resolve_row = mysqli_fetch_assoc($sql_resolve_times)) { + $resolve_client_id = intval($resolve_row['ticket_client_id']); + $resolve_minutes = is_null($resolve_row['logged_minutes']) + ? businessMinutesBetween($resolve_row['ticket_created_at'], $resolve_row['ticket_resolved_at']) + : intval($resolve_row['logged_minutes']); + + if (!isset($resolve_totals[$resolve_client_id])) { + $resolve_totals[$resolve_client_id] = ['minutes' => 0, 'count' => 0]; } - if ($percent >= 95) { - return "$percent%"; - } - if ($percent >= 80) { - return "$percent%"; - } - return "$percent%"; + $resolve_totals[$resolve_client_id]['minutes'] += $resolve_minutes; + $resolve_totals[$resolve_client_id]['count']++; } ?> @@ -125,18 +138,11 @@ function slaPercentDisplay($percent) $avg_time_to_respond = is_null($stats['avg_response_seconds']) ? '-' : secondsToTime($stats['avg_response_seconds']); - // Resolution time is measured in clock time actually spent - - // paused spells are excluded, which is what the SLA judged on + // Clock time actually spent - paused spells excluded, which is + // what the SLA itself judged on $avg_time_to_resolve = '-'; - $resolved_minutes_total = 0; - $resolved_count = 0; - $sql_resolved = mysqli_query($mysqli, "SELECT ticket_id FROM tickets WHERE ticket_sla_id > 0 AND ticket_client_id = $client_id AND ticket_resolved_at IS NOT NULL AND $period_query"); - while ($resolved_row = mysqli_fetch_assoc($sql_resolved)) { - $resolved_minutes_total += getTicketSlaConsumedMinutes($resolved_row['ticket_id']); - $resolved_count++; - } - if ($resolved_count > 0) { - $avg_time_to_resolve = secondsToTime(($resolved_minutes_total / $resolved_count) * 60); + if (!empty($resolve_totals[$client_id]['count'])) { + $avg_time_to_resolve = secondsToTime(($resolve_totals[$client_id]['minutes'] / $resolve_totals[$client_id]['count']) * 60); } ?>