public bool IsSlaPaused(int triggerId, int organizationId) { bool isPaused = false; TicketStatuses statuses = new TicketStatuses(_loginUser); statuses.LoadByStatusIDs(organizationId, new int[] { TicketStatusId }); if (statuses != null && statuses.Any()) { isPaused = statuses[0].PauseSLA; } //check if "Pause on Specific Dates" if (!isPaused) { List <DateTime> daysToPause = SlaTriggers.GetSpecificDaysToPause(triggerId); isPaused = daysToPause.Where(p => DateTime.Compare(p.Date, DateTime.UtcNow.Date) == 0).Any(); } //If Pause on Company Holidays is selected SlaTrigger slaTrigger = SlaTriggers.GetSlaTrigger(_loginUser, triggerId); if (!isPaused && slaTrigger.PauseOnHoliday) { isPaused = SlaTriggers.IsOrganizationHoliday(organizationId, DateTime.UtcNow); } return(isPaused); }
private void LoadTrigger(SlaTrigger trigger) { SetTimes(trigger.WarningTime, trigger.TimeInitialResponse, trigger.TimeLastAction, trigger.TimeToClose); cbGroupViolations.Checked = trigger.NotifyGroupOnViolation; cbGroupWarnings.Checked = trigger.NotifyGroupOnWarning; cbUserViolations.Checked = trigger.NotifyUserOnViolation; cbUserWarnings.Checked = trigger.NotifyUserOnWarning; rbNoBusinessHours.Checked = trigger.NoBusinessHours; rbBusinessHours.Checked = trigger.UseBusinessHours; timeSLAStart.SelectedDate = (trigger.DayStartUtc != null ? TimeZoneInfo.ConvertTimeFromUtc(trigger.DayStartUtc.Value, TimeZoneInfo.FindSystemTimeZoneById(trigger.TimeZone)) : new DateTime?()); timeSLAEnd.SelectedDate = (trigger.DayEndUtc != null ? TimeZoneInfo.ConvertTimeFromUtc(trigger.DayEndUtc.Value, TimeZoneInfo.FindSystemTimeZoneById(trigger.TimeZone)) : new DateTime?()); cbTimeZones.SelectedValue = trigger.TimeZone; cbSLASunday.Checked = ((int)trigger.Weekdays & (int)Math.Pow(2, (int)DayOfWeek.Sunday)) > 0; cbSLAMonday.Checked = ((int)trigger.Weekdays & (int)Math.Pow(2, (int)DayOfWeek.Monday)) > 0; cbSLATuesday.Checked = ((int)trigger.Weekdays & (int)Math.Pow(2, (int)DayOfWeek.Tuesday)) > 0; cbSLAWednesday.Checked = ((int)trigger.Weekdays & (int)Math.Pow(2, (int)DayOfWeek.Wednesday)) > 0; cbSLAThursday.Checked = ((int)trigger.Weekdays & (int)Math.Pow(2, (int)DayOfWeek.Thursday)) > 0; cbSLAFriday.Checked = ((int)trigger.Weekdays & (int)Math.Pow(2, (int)DayOfWeek.Friday)) > 0; cbSLASaturday.Checked = ((int)trigger.Weekdays & (int)Math.Pow(2, (int)DayOfWeek.Saturday)) > 0; DisableEnableCustomBusinessHours(trigger.UseBusinessHours, trigger.NoBusinessHours); cbPauseOnOrganizationHolidays.Checked = trigger.PauseOnHoliday; List <DateTime> daysToPause = SlaTriggers.GetSpecificDaysToPause(trigger.SlaTriggerID); DaysToPauseHidden.Value = string.Join(",", daysToPause.Select(p => DataUtils.DateToLocal(UserSession.LoginUser, p).ToString("d"))); LoginUser loginUser = TSAuthentication.GetLoginUser(); foreach (DateTime dayToPause in daysToPause.OrderBy(p => p)) { daysToPauseList.Items.Add(new ListItem { Value = DataUtils.DateToLocal(UserSession.LoginUser, dayToPause).ToString("d"), Text = DataUtils.DateToLocal(UserSession.LoginUser, dayToPause).ToString("d", loginUser.CultureInfo) }); } }
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)); } }