/// /// Copyright (c) 2020-2023 Sensus Slovensko a.s. /// using System; using System.Collections.Generic; using System.Windows.Forms; using log4net; using NHibernate; using Common; using Config.Entities; using Config.CalendarEvent; using TBF.Resources; namespace TBF.UI.Calendar { public partial class CalendarTabPageCtrl : UserControl { static readonly ILog log = LogManager.GetLogger(typeof(CalendarTabPageCtrl)); public IList EventsFromComponents; Timer timer; DateTime LastTimeCalendarEventsServed; public CalendarTabPageCtrl() { InitializeComponent(); EventsFromComponents = new List(); Localize(); } void Localize() { newEventButton.Text = Strings.New_event; calendarEventsListViewEx.Columns.Add(Strings.Date_and_time, 100); calendarEventsListViewEx.Columns.Add(Strings.Frequency, 70); calendarEventsListViewEx.Columns.Add(Strings.Source, 50); calendarEventsListViewEx.Columns.Add(Strings.Title, 200); calendarEventsListViewEx.Columns.Add(Strings.Action); calendarEventsListViewEx.Columns.Add(Strings.Parameters); calendarEventsListViewEx.Columns.Add(Strings.On_exact_day); calendarEventsListViewEx.Columns.Add(Strings.Read_only); } void AddOne(ICalendarEvent evnt) { ListViewItem lvi = new ListViewItem(evnt.Date.ToString(evnt.AllDay ? Constants.DateFormat : Constants.DateTimeFormat)); lvi.SubItems.Add(Config.CalendarEvent.Utils.Freq2String(evnt.Frequency)); lvi.SubItems.Add(evnt.Source); lvi.SubItems.Add(evnt.Title); lvi.SubItems.Add(Config.CalendarEvent.Utils.Action2String(evnt.AutoAction)); lvi.SubItems.Add(evnt.Parameters); lvi.SubItems.Add(evnt.TriggerOnExactDayOnly ? Strings.yes : Strings.no); lvi.SubItems.Add(evnt.ReadOnly ? Strings.yes : Strings.no); lvi.Tag = evnt; calendarEventsListViewEx.Items.Add(lvi); } /// /// Initializes 'public IList<...> EventsFromComponents. /// /// /// /// public void StartCalendar(IList eventsFromComponents, ISession session = null) { this.EventsFromComponents = eventsFromComponents; bool openAndCloseSession = (session == null); try { /// Read custom events from the database if (openAndCloseSession) session = TBF.DB.ConfigDBSessionFactory.OpenSession(); var customEvents = session.QueryOver().List(); TripplicateShiftCustomEvents(customEvents); /// Calendar foreach (var evnt in eventsFromComponents) calendarCtrl1.AddEvent(evnt); foreach (var evnt in customEvents) calendarCtrl1.AddEvent(evnt); /// List view in the right pane calendarEventsListViewEx.Items.Clear(); foreach (var e in customEvents) AddOne(e); foreach (var e in eventsFromComponents) if (!e.Hidden) AddOne(e); /// Serve events (determine if any event was triggered) ServeCalendarEventsNotifWarnErrorFatal(DateTime.Now, session, customEvents); } catch (Exception) { log.ErrorFormat("Failed to load custom events from the LOCAL config database"); } finally { if (openAndCloseSession && session != null && session.IsOpen) session.Close(); } calendarCtrl1.CalendarView = CalendarViews.Month; timer = new System.Windows.Forms.Timer(); timer.Interval = 300000; /// 300000 ms = 300 s = 5 min timer.Tick += new EventHandler(timer_Tick); timer.Start(); } /// /// After StartCalendar() was called this function is invoked every 5 minutes /// /// /// void timer_Tick(object sender, EventArgs args) { DateTime dateTimeNow = DateTime.Now; if ((dateTimeNow.Hour != LastTimeCalendarEventsServed.Hour) || (dateTimeNow.Minute % 30) != (LastTimeCalendarEventsServed.Minute % 30)) { /// Serve events at the beginning of each half hour ServeCalendarEventsNotifWarnErrorFatal(dateTimeNow); } } /// /// Triggers events corresponding to triggered motification.warning/error calendar events. /// /// Current time void ServeCalendarEventsNotifWarnErrorFatal(DateTime dateTimeNow, ISession session = null, IList customEventsFromDB = null) { LastTimeCalendarEventsServed = dateTimeNow; var eventsToTrigger = new List(); for (int i = EventsFromComponents.Count - 1; i >= 0; i--) { ICalendarEvent calEvent = EventsFromComponents[i]; AutoAction a = calEvent.AutoAction; if (a == AutoAction.Notification || a == AutoAction.Warning || a == AutoAction.Error || a == AutoAction.FatalErr) { if (Config.CalendarEvent.Utils.IsCalendarEventTrigerred(calEvent, dateTimeNow)) { eventsToTrigger.Add(new Events.Entities.Event(null, calEvent.Source, EventClass.Metrology, ToSeverity(calEvent.AutoAction), calEvent.Title, calEvent.Parameters, null, SubscriberGroup.Metrology | SubscriberGroup.Maintenance | SubscriberGroup.Production | SubscriberGroup.Management)); if (calEvent.Frequency == Frequency.Once) { EventsFromComponents.Remove(calEvent); } else { Config.CalendarEvent.Utils.UpdateRecurringDate(calEvent, dateTimeNow); } } } } bool openAndCloseSession = (session == null); /// try { if (openAndCloseSession) session = TBF.DB.ConfigDBSessionFactory.OpenSession(); var customEvents = (customEventsFromDB != null) ? customEventsFromDB : session.QueryOver().List(); for (int i = customEvents.Count - 1; i >= 0; i--) { CustomEvent calEvent = customEvents[i]; AutoAction a = calEvent.AutoAction; if (a == AutoAction.Notification || a == AutoAction.Warning || a == AutoAction.Error || a == AutoAction.FatalErr) { if (Config.CalendarEvent.Utils.IsCalendarEventTrigerred(calEvent, dateTimeNow)) { eventsToTrigger.Add(new Events.Entities.Event(null, calEvent.Source, EventClass.Undefined, ToSeverity(calEvent.AutoAction), calEvent.Title, calEvent.Parameters, null, SubscriberGroup.Metrology | SubscriberGroup.Maintenance | SubscriberGroup.Production | SubscriberGroup.Management)); if (calEvent.Frequency == Frequency.Once) { session.Delete(calEvent); } else if (calEvent.UpdateRecurringDate(dateTimeNow)) { session.SaveOrUpdate(calEvent); } } } } session.Flush(); } catch (Exception exc) { log.ErrorFormat("Failed to load or update CustomEvent-s in ServeTriggerEvtCalendarEvents(): {0}", exc.Message); } finally { if (openAndCloseSession && session != null && session.IsOpen) session.Close(); } if (eventsToTrigger.Count > 0 && TBF.DB.EventsDBSessionFactory != null) { using (ISession evtDBSession = TBF.DB.EventsDBSessionFactory.OpenSession()) { global::Events.DB.LoadSubscribers(evtDBSession); foreach (var e in eventsToTrigger) { TBF.UiBridge.Bridge.TriggerEvent(evtDBSession, e); } evtDBSession.Flush(); evtDBSession.Close(); } } } /// /// Returns an array of parameters of selected actions. /// This function is not invoked from UI thread. /// /// Selected AutoAction /// Max. number of calendar events served /// List of strings of triggered actions public static IList ServeCalendarEventsInvokeXY(AutoAction selectedAction, int maxCount = 1) { DateTime currentTime = DateTime.Now; IList parametersList = new List(); if (maxCount <= 0) return parametersList; ISession session = null; try { session = TBF.DB.ConfigDBSessionFactory.OpenSession(); var customEventsFromDB = session.QueryOver().List(); for (int i = customEventsFromDB.Count - 1; i >= 0; i--) { CustomEvent calEvent = customEventsFromDB[i]; if (calEvent.AutoAction == selectedAction && Config.CalendarEvent.Utils.IsCalendarEventTrigerred(calEvent, currentTime)) { parametersList.Add(calEvent.Parameters); if (calEvent.Frequency == Frequency.Once) { session.Delete(calEvent); } else if (calEvent.UpdateRecurringDate(currentTime)) { session.SaveOrUpdate(calEvent); } if (parametersList.Count >= maxCount) break; } } session.Flush(); } catch (Exception exc) { log.ErrorFormat("Failed to load or update CustomEvent-s in ServeSelectedCalendarEvents(): {0}", exc.Message); } finally { if (session != null && session.IsOpen) session.Close(); } if (parametersList.Count > 0) { /// TODO: Invoke calendar redraw in UI thread } return parametersList; } /// /// Convert calendar event AutoAction to event Severity /// /// AutoAction enum value /// Severity enum value Severity ToSeverity(AutoAction action) { switch (action) { default: case AutoAction.Notification: return Severity.Notification; case AutoAction.Warning: return Severity.Warning; case AutoAction.Error: return Severity.Error; case AutoAction.FatalErr: return Severity.FatalError; } } void TripplicateShiftCustomEvents(IList customEvents) { /// Tripplicate each custom event with frequency 'EveryShift' for (int i = customEvents.Count - 1; i >= 0; i--) { if (customEvents[i].Frequency == Frequency.EveryShift) { DateTime dt = customEvents[i].Date; var ev2 = (CustomEvent)customEvents[i].Clone(); ev2.Date = new DateTime(dt.Year, dt.Month, dt.Day, (dt.Hour + 8) % 24, dt.Minute, 0); ev2.ReadOnly = true; customEvents.Insert(i + 1, ev2); var ev3 = (CustomEvent)customEvents[i].Clone(); ev3.Date = new DateTime(dt.Year, dt.Month, dt.Day, (dt.Hour + 16) % 24, dt.Minute, 0); ev3.ReadOnly = true; customEvents.Insert(i + 2, ev3); } } } private void newEventButton_Click(object sender, EventArgs ea) { EventDetailsForm dlg = new EventDetailsForm(); if (dlg.ShowDialog() == DialogResult.OK && dlg.NewEvent is CustomEvent) { ISession session = null; try { session = TBF.DB.ConfigDBSessionFactory.OpenSession(); session.SaveOrUpdate(dlg.NewEvent as CustomEvent); session.Flush(); var customEvents = session.QueryOver().List(); TripplicateShiftCustomEvents(customEvents); /// Calendar calendarCtrl1.ClearEvents(); foreach (var e in EventsFromComponents) calendarCtrl1.AddEvent(e); foreach (var e in customEvents) calendarCtrl1.AddEvent(e); /// List view in the right pane calendarEventsListViewEx.Items.Clear(); foreach (var e in customEvents) AddOne(e); foreach (var e in EventsFromComponents) if (!e.Hidden) AddOne(e); } catch (Exception) { MessageBox.Show("Cannot save the change to the database", Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } finally { if (session != null && session.IsOpen) session.Close(); } } } private void calendarEventsListViewEx_MouseDoubleClick(object sender, MouseEventArgs mea) { if (calendarEventsListViewEx.SelectedIndices.Count != 1) return; CustomEvent evnt = calendarEventsListViewEx.SelectedItems[0].Tag as CustomEvent; if (evnt == null || evnt.ReadOnly) return; EventDetailsForm dlg = new EventDetailsForm { Event = evnt }; if (dlg.ShowDialog() != DialogResult.OK) return; ISession session = null; try { /// Re-read selected custom event from the database session = TBF.DB.ConfigDBSessionFactory.OpenSession(); var cEvents = session.QueryOver() .Where(x => (x.Id == evnt.Id)) .List(); if (cEvents.Count == 1) { cEvents[0].Date = dlg.NewEvent.Date; cEvents[0].Frequency = dlg.NewEvent.Frequency; cEvents[0].AllDay = dlg.NewEvent.AllDay; cEvents[0].TriggerOnExactDayOnly = dlg.NewEvent.TriggerOnExactDayOnly; cEvents[0].Source = dlg.NewEvent.Source; cEvents[0].Title = dlg.NewEvent.Title; cEvents[0].AutoAction = dlg.NewEvent.AutoAction; cEvents[0].Parameters = dlg.NewEvent.Parameters; cEvents[0].Rank = dlg.NewEvent.Rank; cEvents[0].Hidden = dlg.NewEvent.Hidden; cEvents[0].ReadOnly = dlg.NewEvent.ReadOnly; cEvents[0].BackColor = dlg.NewEvent.BackColor; cEvents[0].TextColor = dlg.NewEvent.TextColor; cEvents[0].TooltipEnabled = dlg.NewEvent.TooltipEnabled; cEvents[0].CustomRecurringFunction = null; session.SaveOrUpdate(cEvents[0]); session.Flush(); var customEvents = session.QueryOver().List(); TripplicateShiftCustomEvents(customEvents); /// Calendar calendarCtrl1.ClearEvents(); foreach (var e in EventsFromComponents) calendarCtrl1.AddEvent(e); foreach (var e in customEvents) calendarCtrl1.AddEvent(e); /// List view in the right pane calendarEventsListViewEx.Items.Clear(); foreach (var e in customEvents) AddOne(e); foreach (var e in EventsFromComponents) if (!e.Hidden) AddOne(e); } } catch (Exception) { MessageBox.Show("Cannot save the change to the database", Strings.Error, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } finally { if (session != null && session.IsOpen) session.Close(); } } } }