예제 #1
0
 private static void UpdateBusinessPausedTimes(LoginUser loginUser, Dictionary <int, double> businessPausedTimes)
 {
     foreach (KeyValuePair <int, double> pair in businessPausedTimes)
     {
         SlaPausedTimes.UpdateBusinessPausedTime(loginUser, pair.Key, pair.Value);
     }
 }
예제 #2
0
        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));
            }
        }