private void ProcessTicket(TicketSlaInfo ticket) { UpdateHealth(); bool isPaused = false; bool isPending = false; int? slaTriggerId = null; Logs.WriteEvent("Getting SlaTicket record"); SlaTicket slaTicket = SlaTickets.GetSlaTicket(LoginUser, ticket.TicketId); if (slaTicket != null) { isPaused = ticket.IsSlaPaused(slaTicket.SlaTriggerId, ticket.OrganizationId); isPending = slaTicket.IsPending; slaTriggerId = slaTicket.SlaTriggerId; } Logs.WriteEventFormat("IsPaused: {0}; IsPending: {1}", isPaused.ToString(), isPending.ToString()); if (!isPaused && !isPending) { SlaTriggersView triggers = new SlaTriggersView(LoginUser); triggers.LoadByTicketId(ticket.TicketId); bool warnGroup = false; bool warnUser = false; bool vioGroup = false; bool vioUser = false; foreach (SlaTriggersViewItem item in triggers) { warnGroup = item.NotifyGroupOnWarning || warnGroup; warnUser = item.NotifyUserOnWarning || warnUser; vioGroup = item.NotifyGroupOnViolation || vioGroup; vioUser = item.NotifyUserOnViolation || vioUser; } SlaNotification notification = SlaNotifications.GetSlaNotification(LoginUser, ticket.TicketId); if (notification == null) { notification = (new SlaNotifications(LoginUser)).AddNewSlaNotification(); notification.TicketID = ticket.TicketId; } DateTime notifyTime; if (ticket.SlaViolationInitialResponse != null && ticket.SlaViolationInitialResponse <= DateTime.UtcNow) { notifyTime = (DateTime)ticket.SlaViolationInitialResponse; if (!IsTooOld(notifyTime)) { if (notification.InitialResponseViolationDate == null || Math.Abs(((DateTime)notification.InitialResponseViolationDateUtc - notifyTime).TotalMinutes) > 5) { NotifyViolation(ticket.TicketId, vioUser, vioGroup, false, SlaViolationType.InitialResponse, notification, slaTriggerId); notification.InitialResponseViolationDate = notifyTime; } } } else if (ticket.SlaWarningInitialResponse != null && ticket.SlaWarningInitialResponse <= DateTime.UtcNow) { notifyTime = (DateTime)ticket.SlaWarningInitialResponse; if (!IsTooOld(notifyTime)) { if (notification.InitialResponseWarningDate == null || Math.Abs(((DateTime)notification.InitialResponseWarningDateUtc - notifyTime).TotalMinutes) > 5) { NotifyViolation(ticket.TicketId, warnUser, warnGroup, true, SlaViolationType.InitialResponse, notification, slaTriggerId); notification.InitialResponseWarningDate = notifyTime; } } } if (ticket.SlaViolationLastAction != null && ticket.SlaViolationLastAction <= DateTime.UtcNow) { notifyTime = (DateTime)ticket.SlaViolationLastAction; if (!IsTooOld(notifyTime)) { if (notification.LastActionViolationDate == null || Math.Abs(((DateTime)notification.LastActionViolationDateUtc - notifyTime).TotalMinutes) > 5) { NotifyViolation(ticket.TicketId, vioUser, vioGroup, false, SlaViolationType.LastAction, notification, slaTriggerId); notification.LastActionViolationDate = notifyTime; } } } else if (ticket.SlaWarningLastAction != null && ticket.SlaWarningLastAction <= DateTime.UtcNow) { notifyTime = (DateTime)ticket.SlaWarningLastAction; if (!IsTooOld(notifyTime)) { if (notification.LastActionWarningDate == null || Math.Abs(((DateTime)notification.LastActionWarningDateUtc - notifyTime).TotalMinutes) > 5) { NotifyViolation(ticket.TicketId, warnUser, warnGroup, true, SlaViolationType.LastAction, notification, slaTriggerId); notification.LastActionWarningDate = notifyTime; } } } if (ticket.SlaViolationTimeClosed != null && ticket.SlaViolationTimeClosed <= DateTime.UtcNow) { notifyTime = (DateTime)ticket.SlaViolationTimeClosed; if (!IsTooOld(notifyTime)) { if (notification.TimeClosedViolationDate == null || Math.Abs(((DateTime)notification.TimeClosedViolationDateUtc - notifyTime).TotalMinutes) > 5) { NotifyViolation(ticket.TicketId, vioUser, vioGroup, false, SlaViolationType.TimeClosed, notification, slaTriggerId); notification.TimeClosedViolationDate = notifyTime; } } } else if (ticket.SlaWarningTimeClosed != null && ticket.SlaWarningTimeClosed <= DateTime.UtcNow) { notifyTime = (DateTime)ticket.SlaWarningTimeClosed; if (!IsTooOld(notifyTime)) { if (notification.TimeClosedWarningDate == null || Math.Abs(((DateTime)notification.TimeClosedWarningDateUtc - notifyTime).TotalMinutes) > 5) { NotifyViolation(ticket.TicketId, warnUser, warnGroup, true, SlaViolationType.TimeClosed, notification, slaTriggerId); notification.TimeClosedWarningDate = notifyTime; } } } notification.Collection.Save(); } }
protected void Page_Load(object sender, EventArgs e) { if (Request["TicketID"] == null) { EndResponse("Invalid Ticket"); } LoginUser loginUser = TSAuthentication.GetLoginUser(); int ticketID = int.Parse(Request["TicketID"]); Ticket ticket = Tickets.GetTicket(loginUser, ticketID); if (ticket == null) { EndResponse("Invalid Ticket"); } tipNumber.InnerText = "Ticket #" + ticket.TicketNumber.ToString(); tipNumber.Attributes.Add("onclick", "top.Ts.MainPage.openTicket(" + ticket.TicketNumber + "); return false;"); tipName.InnerHtml = ticket.Name; bool isStatusPaused = false; SlaTicket slaTicket = SlaTickets.GetSlaTicket(loginUser, ticket.TicketID); if (slaTicket != null) { SlaTrigger slaTrigger = SlaTriggers.GetSlaTrigger(loginUser, slaTicket.SlaTriggerId); if (slaTrigger != null) { isStatusPaused = ticket.IsSlaStatusPaused(); string slaName = new SlaLevels(TSAuthentication.GetLoginUser()).GetSlaveLevelName(slaTicket.SlaTriggerId); wslaName.InnerText = slaName; } else { ticket.SlaViolationInitialResponse = null; ticket.SlaViolationTimeClosed = null; ticket.SlaViolationLastAction = null; ticket.SlaWarningInitialResponse = null; ticket.SlaWarningTimeClosed = null; ticket.SlaWarningLastAction = null; ticket.Collection.Save(); } } if (isStatusPaused) { wClose.InnerText = "Paused"; vClose.InnerText = "Paused"; wLast.InnerText = "Paused"; vLast.InnerText = "Paused"; wInit.InnerText = "Paused"; vInit.InnerText = "Paused"; wNext.InnerText = "Paused"; vNext.InnerText = "Paused"; } else { DateTime?nextViolation = GetUtcDate(ticket, "SlaViolationInitialResponse"); nextViolation = GetMinDate(loginUser, nextViolation, GetUtcDate(ticket, "SlaViolationLastAction")); nextViolation = GetMinDate(loginUser, nextViolation, GetUtcDate(ticket, "SlaViolationTimeClosed")); DateTime?nextWarning = GetUtcDate(ticket, "SlaWarningInitialResponse"); nextWarning = GetMinDate(loginUser, nextWarning, GetUtcDate(ticket, "SlaWarningLastAction")); nextWarning = GetMinDate(loginUser, nextWarning, GetUtcDate(ticket, "SlaWarningTimeClosed")); if (nextViolation != null && nextViolation < DateTime.UtcNow) { tipSla.Attributes.Add("class", "ts-icon ts-icon-sla-bad"); } else if (nextWarning != null && nextWarning < DateTime.UtcNow) { tipSla.Attributes.Add("class", "ts-icon ts-icon-sla-warning"); } else { tipSla.Attributes.Add("class", "ts-icon ts-icon-sla-good"); } wClose.InnerText = GetDateString(loginUser, GetUtcDate(ticket, "SlaWarningTimeClosed")); vClose.InnerText = GetDateString(loginUser, GetUtcDate(ticket, "SlaViolationTimeClosed")); wLast.InnerText = GetDateString(loginUser, GetUtcDate(ticket, "SlaWarningLastAction")); vLast.InnerText = GetDateString(loginUser, GetUtcDate(ticket, "SlaViolationLastAction")); wInit.InnerText = GetDateString(loginUser, GetUtcDate(ticket, "SlaWarningInitialResponse")); vInit.InnerText = GetDateString(loginUser, GetUtcDate(ticket, "SlaViolationInitialResponse")); wNext.InnerText = GetDateString(loginUser, nextWarning); vNext.InnerText = GetDateString(loginUser, nextViolation); } }
public override void Run() { try { SlaTickets slaTickets = new SlaTickets(LoginUser); slaTickets.LoadPending(); if (slaTickets != null && slaTickets.Count > 0) { Logs.WriteEvent(string.Format("{0} pending tickets to calculate the SLA values for.", slaTickets.Count)); } foreach (SlaTicket slaTicket in slaTickets) { if (IsStopped) { break; } UpdateHealth(); try { Ticket ticket = Tickets.GetTicket(LoginUser, slaTicket.TicketId); if (ticket != null) { bool isStatusPaused = ticket.IsSlaStatusPaused(); bool isClosed = ticket.DateClosed != null; DateTime?newSlaViolationTimeClosed = null; DateTime?newSlaWarningTimeClosed = null; DateTime?newSlaViolationLastAction = null; DateTime?newSlaWarningLastAction = null; DateTime?newSlaViolationInitialResponse = null; DateTime?newSlaWarningInitialResponse = null; if (!isClosed && !isStatusPaused) { DateTime?lastActionDateCreated = Actions.GetLastActionDateCreated(LoginUser, ticket.TicketID); int totalActions = Actions.TotalActionsForSla(LoginUser, ticket.TicketID, ticket.OrganizationID); Organization organization = Organizations.GetOrganization(LoginUser, ticket.OrganizationID); SlaTrigger slaTrigger = SlaTriggers.GetSlaTrigger(LoginUser, slaTicket.SlaTriggerId); if (slaTrigger == null) { Logs.WriteEventFormat("Trigger {0} not found.", slaTicket.SlaTriggerId); } SlaTickets.BusinessHours businessHours = new SlaTickets.BusinessHours() { DayStartUtc = organization.BusinessDayStartUtc, DayEndUtc = organization.BusinessDayEndUtc, BusinessDays = organization.BusinessDays }; //Check if we should use SLA's business hours instead of Account's if (!slaTrigger.UseBusinessHours && !slaTrigger.NoBusinessHours && slaTrigger.DayStartUtc.HasValue && slaTrigger.DayEndUtc.HasValue) { businessHours.DayStartUtc = slaTrigger.DayStartUtc.Value; businessHours.DayEndUtc = slaTrigger.DayEndUtc.Value; businessHours.BusinessDays = slaTrigger.Weekdays; } else if (!slaTrigger.UseBusinessHours && !slaTrigger.NoBusinessHours) { Logs.WriteEventFormat("Using Account's business hours {0} to {1} because while the trigger is set to use sla's business hours one of them has no value. Sla DayStartUtc {2}, Sla DayEndUtc {3}", organization.BusinessDayStartUtc.ToShortTimeString(), organization.BusinessDayEndUtc.ToShortTimeString(), slaTrigger.DayStartUtc.HasValue ? slaTrigger.DayStartUtc.Value.ToShortTimeString() : "NULL", slaTrigger.DayEndUtc.HasValue ? slaTrigger.DayEndUtc.Value.ToShortTimeString() : "NULL"); } Logs.WriteEvent(string.Format("Ticket #{0} id {1}. LastAction: {2}, TotalActions: {3}, Org({4}) {5}, SlaTriggerId {6}.", ticket.TicketNumber, ticket.TicketID, lastActionDateCreated == null ? "none" : lastActionDateCreated.Value.ToString(), totalActions, organization.OrganizationID, organization.Name, slaTrigger.SlaTriggerID)); List <DateTime> daysToPause = SlaTriggers.GetSpecificDaysToPause(slaTrigger.SlaTriggerID); bool pauseOnHoliday = slaTrigger.PauseOnHoliday; CalendarEvents holidays = new CalendarEvents(LoginUser); if (pauseOnHoliday) { holidays.LoadHolidays(organization.OrganizationID); } Dictionary <int, double> businessPausedTimes = new Dictionary <int, double>(); //We need to have two calculations for the paused time, one for the Time To Close and Initial Response which should count the paused time since the Ticket creation //and another one for Last Action where it should only count starting from the last action added TimeSpan totalPausedTimeSpan = SlaTickets.CalculatePausedTime(ticket.TicketID, organization, businessHours, slaTrigger, daysToPause, holidays, LoginUser, businessPausedTimes, Logs); Logs.WriteEventFormat("Total Paused Time: {0}", totalPausedTimeSpan.ToString()); UpdateBusinessPausedTimes(LoginUser, businessPausedTimes); newSlaViolationTimeClosed = SlaTickets.CalculateSLA(ticket.DateCreatedUtc, businessHours, slaTrigger, slaTrigger.TimeToClose, totalPausedTimeSpan, daysToPause, holidays); if (newSlaViolationTimeClosed != null) { newSlaWarningTimeClosed = SlaTickets.CalculateSLAWarning(newSlaViolationTimeClosed.Value, businessHours, slaTrigger.NoBusinessHours, slaTrigger.TimeToClose, slaTrigger.WarningTime, daysToPause, holidays); } TimeSpan pausedTimeSpanSinceLastAction = SlaTickets.CalculatePausedTime(ticket.TicketID, organization, businessHours, slaTrigger, daysToPause, holidays, LoginUser, businessPausedTimes, Logs, false, lastActionDateCreated.HasValue ? lastActionDateCreated.Value : (DateTime?)null); Logs.WriteEventFormat("Total Paused Time: {0}", pausedTimeSpanSinceLastAction.ToString()); if (lastActionDateCreated == null) { newSlaViolationLastAction = null; newSlaWarningLastAction = null; } else { newSlaViolationLastAction = SlaTickets.CalculateSLA(lastActionDateCreated.Value, businessHours, slaTrigger, slaTrigger.TimeLastAction, pausedTimeSpanSinceLastAction, daysToPause, holidays); if (newSlaViolationLastAction != null) { newSlaWarningLastAction = SlaTickets.CalculateSLAWarning((DateTime)newSlaViolationLastAction.Value, businessHours, slaTrigger.NoBusinessHours, slaTrigger.TimeLastAction, slaTrigger.WarningTime, daysToPause, holidays); } } if (slaTrigger.TimeInitialResponse < 1 || totalActions > 0) { newSlaViolationInitialResponse = null; newSlaWarningInitialResponse = null; } else { newSlaViolationInitialResponse = SlaTickets.CalculateSLA(ticket.DateCreatedUtc, businessHours, slaTrigger, slaTrigger.TimeInitialResponse, totalPausedTimeSpan, daysToPause, holidays); if (newSlaViolationInitialResponse != null) { newSlaWarningInitialResponse = SlaTickets.CalculateSLAWarning((DateTime)newSlaViolationInitialResponse.Value, businessHours, slaTrigger.NoBusinessHours, slaTrigger.TimeInitialResponse, slaTrigger.WarningTime, daysToPause, holidays); } } } else { Logs.WriteEventFormat("Ticket is {0}, clearing its SLA values.", isClosed ? "Closed" : "Status Paused"); } if (HasAnySlaChanges(ticket, newSlaViolationTimeClosed, newSlaWarningTimeClosed, newSlaViolationLastAction, newSlaWarningLastAction, newSlaViolationInitialResponse, newSlaWarningInitialResponse)) { ticket.SlaViolationTimeClosed = newSlaViolationTimeClosed; ticket.SlaWarningTimeClosed = newSlaWarningTimeClosed; ticket.SlaViolationLastAction = newSlaViolationLastAction; ticket.SlaWarningLastAction = newSlaWarningLastAction; ticket.SlaViolationInitialResponse = newSlaViolationInitialResponse; ticket.SlaWarningInitialResponse = newSlaWarningInitialResponse; Tickets.UpdateTicketSla(LoginUser, ticket.TicketID, newSlaViolationInitialResponse, newSlaViolationLastAction, newSlaViolationTimeClosed, newSlaWarningInitialResponse, newSlaWarningLastAction, newSlaWarningTimeClosed); Logs.WriteEvent("Ticket SLA calculation completed."); string signalRUrl = Settings.ReadString("SignalRUrl"); if (!string.IsNullOrEmpty(signalRUrl)) { //Dictionary<string, string> queryStringData = new Dictionary<string, string>(); //queryStringData.Add("userID", "-1"); //queryStringData.Add("organizationID", ticket.OrganizationID.ToString()); //HubConnection connection = new HubConnection(signalRUrl, queryStringData); //IHubProxy signalRConnection = connection.CreateHubProxy("TicketSocket"); //try //{ // connection.Start().Wait(); // signalRConnection.Invoke("RefreshSLA", ticket.TicketNumber); //} //catch (Exception ex) //{ // Logs.WriteEvent("Could not send signalR to refresh the SLA. Message: " + ex.Message); //} } } else { Logs.WriteEvent("Ticket SLA calculation completed. SLA values did not change, ticket was not updated."); } slaTicket.IsPending = false; slaTicket.Collection.Save(); } else { SlaPausedTimes slaPausedTimes = new SlaPausedTimes(LoginUser); slaPausedTimes.LoadByTicketId(slaTicket.TicketId); slaPausedTimes.DeleteAll(); slaPausedTimes.Save(); slaTicket.Delete(); slaTicket.Collection.Save(); Logs.WriteEventFormat("Ticket id {0} does not exist anymore, deleted from SlaTickets.", slaTicket.TicketId); } System.Threading.Thread.Sleep(100); } catch (System.Data.SqlClient.SqlException sqlEx) { //Handle the deadlock exception, any other bubble up. if (sqlEx.Number == 1205 || sqlEx.Message.Contains("deadlocked")) { ExceptionLogs.LogException(LoginUser, sqlEx, "SLA Calculator", "Sync"); Logs.WriteEventFormat("Exception. Message {0}{1}StackTrace {2}", sqlEx.Message, Environment.NewLine, sqlEx.StackTrace); slaTicket.IsPending = true; slaTicket.Collection.Save(); Logs.WriteEventFormat("SlaTicket: TicketId {0} TriggerId {1} still pending.", slaTicket.TicketId, slaTicket.SlaTriggerId); } else { throw; } } catch (Exception ex) { ExceptionLogs.LogException(LoginUser, ex, "SLA Calculator", "Sync"); Logs.WriteEventFormat("Exception. Message {0}{1}StackTrace {2}", ex.Message, Environment.NewLine, ex.StackTrace); slaTicket.IsPending = false; slaTicket.Collection.Save(); Logs.WriteEventFormat("SlaTicket: TicketId {0} TriggerId {1} set to not pending.", slaTicket.TicketId, slaTicket.SlaTriggerId); } } if (slaTickets != null && slaTickets.Count > 0) { Logs.WriteEvent(string.Format("Completed processing the {0} pending tickets to calculate the SLA values for.", slaTickets.Count)); } } catch (Exception ex) { ExceptionLogs.LogException(LoginUser, ex, "SLA Calculator", "Sync"); Logs.WriteEvent(string.Format("Exception. Message {0}{1}StackTrace {2}", ex.Message, Environment.NewLine, ex.StackTrace)); } }