using System; using System.Collections.Generic; using System.Linq; using System.Text; using AyaNova.PlugIn; using GZTW.AyaNova.BLL; using System.ComponentModel; using System.Windows.Forms; using System.Reflection; using System.Data; using Infragistics.Documents.Excel; namespace AyaNova.Plugin.RepairTek { class RepairTek : IAyaNovaPlugin { //Keep all the object types we want to deal with in a collection //so that we can quickly check it when asked private static List ObjectsWeCanDealWith = null; //Holds the image resources from AyaNova //so we can display the correct icons in our plugin System.Resources.ResourceManager resman = null; //Holds the current logged in user's localized text //lookup object LocalizedTextTable LocaleText = null; #region IAyaNovaPlugin Members #region interface properties public string PluginName { get { return "RepairTek"; } } public string PluginVersion { get { return "7.2.0.0"; } } public string About { get { return "AyaNova RepairTek plugin\r\n" + "Copyright 2009-2017 Ground Zero Tech-Works Inc."; } } public Guid PluginID { get { return new Guid("{06EDD53C-50C5-4eb0-8CE4-1C265CBC04F8}"); } } public System.Drawing.Image PluginSmallIcon { get { return null; } } public System.Drawing.Image PluginLargeIcon { get { return null; } } public System.Resources.ResourceManager AyaNovaResourceManager { set { resman = value; } get { return resman; } } #endregion interface properties #region Initialization and Close public bool Initialize(Version AyaNovaVersion, LocalizedTextTable localizedText) { LocaleText = localizedText; ObjectsWeCanDealWith = new List(); ObjectsWeCanDealWith.Add(RootObjectTypes.Nothing); return true; } public void Close() { ; } #endregion Initialization and close #region ShowMenu? public bool SingleObjectMenuShow(RootObjectTypes objectType) { return (ObjectsWeCanDealWith.Contains(objectType)); } public bool MultipleObjectsMenuShow(RootObjectTypes objectType) { return false; } #endregion show menu? #region Menu options public List SingleObjectMenuOptions(RootObjectTypes objectType, object ayaNovaObject) { if (!ObjectsWeCanDealWith.Contains(objectType)) return null; List list = new List(); list.Add(new AyaNovaPluginMenuItem("REPAIRTEK", "RepairTek - Update workorders from spreadsheet", null, null)); return list; } public List MultipleObjectsMenuOptions(RootObjectTypes objectType) { return null; } #endregion #region Menu Commands #region LIST OBJECT COMMAND /// /// LIST OBJECT /// /// /// /// /// /// public bool CommandSelectedForList(string commandKey, RootObjectTypes objectType, List objectIDList, object listObject) { return false; } #endregion list object command #region SINGLE OBJECT COMMAND /// /// SINGLE OBJECT /// /// /// /// public void CommandSelectedForSingleObject(string commandKey, RootObjectTypes objectType, object ayaNovaObject) { switch (commandKey) { case "REPAIRTEK": { Update(); } break; } } #endregion single object command #endregion menu commands #endregion /* THIS IS THE "REPAIRTEK" PLUGIN - REPAIRTEK2 */ #region Update workorders from spreadsheet /* * * 11:22:54 AM: frank has purchased - #1 - all workorders stated in the xls file to have Onsite unchecked (whether any of the other fields are updated or not) #2 - all workorders stated in the xls file to have Workorder Status set to Received - Ready To be Assigned (whether any of the other fields are updated or not) 11:22:59 AM: let me know if any questions 11:23:37 AM: so that's the *exact* status spelling? 11:23:57 AM: yes 11:24:00 AM: k 11:24:02 AM: Received - Ready To be Assigned * */ /// /// Update workorders /// private void Update() { //track ops to report upon completion System.Text.StringBuilder sb = new StringBuilder(); sb.Append("Results:\r\n"); #region Open the xls file OpenFileDialog ofd = new OpenFileDialog(); ofd.Multiselect = false; ofd.Title = ""; ofd.DefaultExt = "xls"; ofd.FileName = "*.xls"; if (ofd.ShowDialog() != DialogResult.OK) return; Infragistics.Documents.Excel.Workbook workbook; try { workbook = Infragistics.Documents.Excel.Workbook.Load(ofd.FileName); sb.Append("Workbook " + ofd.FileName + " opened for processing\r\n"); } catch (Exception ex) { MessageBox.Show("Error opening workbook:\r\n" + ex.ToString()); return; } ofd.Dispose(); #endregion open the xls //fetch priority list PriorityPickList ppl = PriorityPickList.GetList(); #region check all expected priorities are in ayanova Guid g2DayDepot = GetMatchingPriority(ppl, "2 DAY DEPOT"); Guid g5DayDepot = GetMatchingPriority(ppl, "5 DAY DEPOT"); Guid g15DayFlat = GetMatchingPriority(ppl, "15 DAY/FLAT RATE"); Guid g15DayWarr = GetMatchingPriority(ppl, "15 DAY/WARR"); if (g2DayDepot == Guid.Empty) { sb.Append("ERROR: expected priority not found in AyaNova: \"2 DAY DEPOT\". Can not proceed until this priority exists in AyaNova.\r\n"); ReportResults(sb); return; } if (g5DayDepot == Guid.Empty) { sb.Append("ERROR: expected priority not found in AyaNova: \"5 DAY DEPOT\". Can not proceed until this priority exists in AyaNova.\r\n"); ReportResults(sb); return; } if (g15DayFlat == Guid.Empty) { sb.Append("ERROR: expected priority not found in AyaNova: \"15 DAY/FLAT RATE\". Can not proceed until this priority exists in AyaNova.\r\n"); ReportResults(sb); return; } if (g15DayWarr == Guid.Empty) { sb.Append("ERROR: expected priority not found in AyaNova: \"15 DAY/WARR\". Can not proceed until this priority exists in AyaNova.\r\n"); ReportResults(sb); return; } #endregion #region find received status //dec 15th 2009 additional Guid gRecievedStatus = Guid.Empty; WorkorderStatusPickList wsp = WorkorderStatusPickList.GetList(); foreach (WorkorderStatusPickList.WorkorderStatusPickListInfo i in wsp) { if (i.Name.Equals("Received - Ready To be Assigned", StringComparison.InvariantCultureIgnoreCase)) { gRecievedStatus = i.ID; break; } } wsp = null; if (gRecievedStatus == Guid.Empty) { sb.Append("ERROR: expected Work order status not found in AyaNova: \"Received - Ready To be Assigned\". Can not proceed until this work order status exists in AyaNova.\r\n"); ReportResults(sb); return; } #endregion find received status //Iterate the workorders int nRow = 0; foreach (WorksheetRow r in workbook.Worksheets[0].Rows) { nRow++; Workorder w; string sWorkorderNumber = SafeGetCellValue(r, 0); #region fetch workorder //skip over empty rows if (string.IsNullOrEmpty(sWorkorderNumber)) { sb.Append("[Row " + nRow.ToString() + "] skipped empty row \r\n"); continue; } //skip over the title row if(sWorkorderNumber.StartsWith("AyaNova")) { sb.Append("[Row " + nRow.ToString() + "] skipped title row \"" + sWorkorderNumber + "\"\r\n"); continue; } int nWo = 0; if (!System.Int32.TryParse(sWorkorderNumber, out nWo)) { sb.Append("[Row "+nRow.ToString() + "] Workorder number not found in value \"" + sWorkorderNumber + "\"\r\n"); continue; } Guid woID = WorkorderInternalIDFetcher.GetItem(nWo.ToString(), WorkorderTypes.Service); if (woID == Guid.Empty) { sb.Append("[Row "+nRow.ToString() +"] Error: workorder with number \"" + sWorkorderNumber + "\" not found in AyaNova\r\n"); continue; } w = Workorder.GetItem(woID); #endregion get workorder #region get spreadsheet values #region Priority and service days string sPriority = SafeGetCellValue(r, 6); if (string.IsNullOrEmpty(sPriority)) { sb.Append("[Row " + nRow.ToString() + "] Priority in spreadsheet is empty for workorder \"" + sWorkorderNumber + "\" using default \"5 DAY DEPOT\"\r\n"); sPriority="5 DAY DEPOT"; } //confirm priority is one of the values we expect //and get the days to add value int nDaysToServiceDate = 5; Guid gSetPriority = Guid.Empty; if (sPriority.Equals("2 DAY DEPOT", StringComparison.InvariantCultureIgnoreCase)) { gSetPriority = g2DayDepot; nDaysToServiceDate = 2; } else if (sPriority.Equals("5 DAY DEPOT", StringComparison.InvariantCultureIgnoreCase)) { gSetPriority = g5DayDepot; nDaysToServiceDate = 5; } else if (sPriority.Equals("15 DAY/FLAT RATE", StringComparison.InvariantCultureIgnoreCase)) { gSetPriority = g15DayFlat; nDaysToServiceDate = 15; } else if (sPriority.Equals("15 DAY/WARR", StringComparison.InvariantCultureIgnoreCase)) { gSetPriority = g15DayWarr; nDaysToServiceDate = 15; } else //default { //Is it possible to set the priority as a default to 5 DAY DEPOT (I highlighted in yellow in attached) for each workorder when created, just as a safety. This is the priority over 95% of the time. The plug –in would overwrite this field if different. Or will this create possible errors. sb.Append("[Row " + nRow.ToString() + "] workorder \"" + sWorkorderNumber + "\" priority:\"" + sPriority + "\" unexpected. Using default \"5 DAY DEPOT\" \r\n"); gSetPriority = g5DayDepot; nDaysToServiceDate = 5; } #endregion priority string sIntRef = SafeGetCellValue(r, 7); if (string.IsNullOrEmpty(sIntRef)) { sb.Append("[Row " + nRow.ToString() + "] Skipping Workorder \"" + sWorkorderNumber + "\" Internal Reference in spreadsheet is empty!\r\n"); continue; } string sSummary = SafeGetCellValue(r, 8); if (string.IsNullOrEmpty(sSummary)) { sb.Append("[Row " + nRow.ToString() + "] Skipping Workorder \"" + sWorkorderNumber + "\" Summary in spreadsheet is empty!\r\n"); continue; } #endregion get spreadsheet values #region Can / should workorder be updated? //Has the workorder already been updated? if (!string.IsNullOrEmpty(w.InternalReferenceNumber)) { if (w.InternalReferenceNumber == sIntRef) { sb.Append("[Row " + nRow.ToString() + "] Skipping Workorder \"" + sWorkorderNumber + "\" was previously updated in AyaNova (matching int. ref#).\r\n"); } else { sb.Append("[Row " + nRow.ToString() + "] Skipping Workorder \"" + sWorkorderNumber + "\" has int. ref# (\"" + w.InternalReferenceNumber + "\") however it doesn't match the one in the spreadsheet(\"" + sIntRef + "\")!\r\n"); } continue; } //can the workorder be updated? if (!w.IsEditable) { sb.Append("[Row " + nRow.ToString() + "] Skipping Workorder \"" + sWorkorderNumber + "\" - Workorder is not editable (closed, service completed or insufficient rights)!\r\n"); continue; } #endregion can / should workorder be updated //Ok, we have all the data we need, the workorder is updateable so get updatin'... //Judging by info provided these workorders will have only one workorder item but to be safe //will iterate in case... foreach (WorkorderItem wi in w.WorkorderItems) { wi.Summary = sSummary; wi.PriorityID = gSetPriority; } w.InternalReferenceNumber = sIntRef; #region Set service date DateTime dtService = DateTime.Parse(w.Created); dtService = AddXBusinessDays(dtService,nDaysToServiceDate); w.WorkorderService.ServiceDate = dtService; #endregion set service date //Additional Dec 15 2009 w.Onsite = false; w.WorkorderService.WorkorderStatusID = gRecievedStatus; if (w.IsSavable) { w.Save(); sb.Append("[Row " + nRow.ToString() + "] Workorder \"" + sWorkorderNumber + "\" updated in AyaNova\r\n"); } else { sb.Append("[Row " + nRow.ToString() + "] Workorder \"" + sWorkorderNumber + "\" couldn't be saved due to broken rules, error was:\r\n----------------------------------\r\n" + w.BrokenRulesText + "\r\n----------------------------------\r\n"); } } sb.Append("All rows in spreadsheet processed!"); //Report results ReportResults(sb); } //Note: assumption that workorders are never created on weekends private DateTime AddXBusinessDays(DateTime dateToIncrement, int days) { DateTime dt = dateToIncrement; for (int x = 0; x < days; x++) { do { dt = dt.AddDays(1.0); } while (dt.DayOfWeek == DayOfWeek.Saturday || dt.DayOfWeek == DayOfWeek.Sunday); } return dt; } private void ReportResults(StringBuilder sb) { CopyableMessageBox dlgCMB = new CopyableMessageBox(sb.ToString()); dlgCMB.ShowDialog(); } //safe get cell value private string SafeGetCellValue(WorksheetRow r, int nColumn) { object o=r.Cells[nColumn].Value; if (o == null) return ""; else return o.ToString(); } /// /// Attempt to match priority from text in spreadsheet /// if no match return guid empty /// /// /// /// Guid GetMatchingPriority(PriorityPickList ppl, string sToMatch) { foreach (PriorityPickList.PriorityPickListInfo i in ppl) { if(i.Name.Equals(sToMatch, StringComparison.InvariantCultureIgnoreCase)) { return i.ID; } } return Guid.Empty; } #endregion update } }