using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using Comal.Classes;
using InABox.Clients;
using InABox.Configuration;
using InABox.Core;
using InABox.DynamicGrid;
using InABox.DynamicGrid.Spreadsheet;
using InABox.WPF;
using Microsoft.Office.Interop.Outlook;
using Selection = InABox.Core.Selection;
namespace PRSDesktop
{
public class JobPanelSettings : BaseObject, IGlobalConfigurationSettings
{
[Caption("Milestone Task",IncludePath = false)]
public KanbanTypeLink DocumentMilestoneKanbanType { get; set; }
public JobPanelSettings()
{
DocumentMilestoneKanbanType = new KanbanTypeLink();
}
}
///
/// Interaction logic for JobPanel.xaml
///
public partial class JobPanel : UserControl, IPanel
{
private enum PageIndex
{
Details = 00,
Financials,
Documents,
Stages,
ITPs,
BOM,
Requisitions,
Orders,
Designs,
Manufacturing,
Dispatch,
Delivery,
Onsite,
Kanban,
Equipment,
Employee,
Tracker,
Assignment,
Timesheet,
Form,
Invoice,
Spreadsheets,
Summary
}
private int CurrentPage = -1;
private JobDetails JobDetailsPage;
private JobFinancialGrid JobFinancialPage;
private JobDocumentSetPanel JobDocumentsPage;
private JobStagesPanel JobPlanningPage;
private JobITPGrid JobITPPage;
private JobBillOfMaterialsPanel JobBillOfMaterialsPage;
private JobRequisitionPanel JobRequisitionsPage;
private JobDesignList JobDesignsPage;
private JobOrderGrid JobOrderPage;
private ManufacturingGrid JobManufacturingPage;
private ReadyToGoGrid JobReadyToGoPage;
private DeliveryPanel JobDeliveriesPage;
private DeliveredOnSiteGrid JobOnSitePage;
private TaskPanel JobTasksPage;
private JobEquipmentGrid JobEquipmentPage;
private JobEmployeePanel JobEmployeePage;
private JobTrackerGrid JobTrackerPage;
private JobAssignmentPanel JobActivitiesPage;
private JobTimesheetGrid JobTimeSheetsPage;
private JobFormGrid JobFormsPage;
private InvoicePanel JobInvoicePage;
private JobSpreadsheetGrid JobSpreadsheetPage;
private JobSummaryPanel JobSummaryPage;
private DateTime lastselection = DateTime.MaxValue;
private IDataModelSource modelsource;
// User Settings
private JobScreenSettings settings;
// Global Settings
private JobPanelSettings _settings = null;
private DispatcherTimer timer;
public JobPanel()
{
InitializeComponent();
}
public bool IsReady { get; set; }
public Dictionary Selected()
{
return (PageIndex)JobPages.SelectedIndex switch
{
PageIndex.Details => JobDetailsPage.Selected(),
PageIndex.Financials => JobFinancialPage.Selected(),
PageIndex.Documents => JobDocumentsPage.Selected(),
PageIndex.Stages => JobPlanningPage.Selected(),
PageIndex.ITPs => new Dictionary { { typeof(JobITP).EntityName(), JobITPPage.SelectedRows } },
PageIndex.BOM => new Dictionary
{ { typeof(JobBillOfMaterials).EntityName(), JobBillOfMaterialsPage.SelectedRows } },
PageIndex.Designs => JobDesignsPage.Selected(),
PageIndex.Orders => new Dictionary { { typeof(PurchaseOrderItem).EntityName(), JobOrderPage.SelectedRows } },
PageIndex.Requisitions => new Dictionary
{ { typeof(JobRequisition).EntityName(), JobRequisitionsPage.Requisitions.SelectedRows } },
PageIndex.Manufacturing => new Dictionary
{ { typeof(ManufacturingPacket).EntityName(), JobManufacturingPage.SelectedRows } },
PageIndex.Dispatch => new Dictionary { { typeof(DeliveryItem).EntityName(), JobReadyToGoPage.SelectedRows } },
PageIndex.Delivery => new Dictionary
{ { typeof(Delivery).EntityName(), JobDeliveriesPage.Deliveries.SelectedRows } },
PageIndex.Onsite => new Dictionary { { typeof(DeliveryItem).EntityName(), JobOnSitePage.SelectedRows } },
PageIndex.Kanban => JobTasksPage.Selected(),
PageIndex.Equipment => new Dictionary { { typeof(Equipment).EntityName(), JobEquipmentPage.SelectedRows } },
PageIndex.Employee => new Dictionary
{ { typeof(Employee).EntityName(), JobEmployeePage.Employees.SelectedRows } },
PageIndex.Tracker => new Dictionary { { typeof(GPSTracker).EntityName(), JobTrackerPage.SelectedRows } },
PageIndex.Assignment => new Dictionary
{ { typeof(Assignment).EntityName(), JobActivitiesPage.Assignments.SelectedRows } },
PageIndex.Timesheet => new Dictionary { { typeof(TimeSheet).EntityName(), JobTimeSheetsPage.SelectedRows } },
PageIndex.Form => new Dictionary { { typeof(JobForm).EntityName(), JobFormsPage.SelectedRows } },
PageIndex.Invoice => new Dictionary { { typeof(Invoice).EntityName(), JobInvoicePage.Invoices.SelectedRows } },
PageIndex.Spreadsheets => new Dictionary { { typeof(JobSpreadsheet).EntityName(), JobSpreadsheetPage.SelectedRows } },
PageIndex.Summary => new Dictionary { { typeof(JobMaterial).EntityName(), JobSummaryPage.Summary.SelectedRows } },
_ => new Dictionary {{ typeof(Job).EntityName(), JobGrid.SelectedRows}}
};
}
public void Setup()
{
Task[] settingstasks = new Task[]
{
Task.Run(() =>
{
_settings = new GlobalConfiguration().Load();
}),
Task.Run(() =>
{
settings = new UserConfiguration().Load();
})
};
Task.WaitAll(settingstasks);
SplitPanel.View = settings.ViewType == ScreenViewType.Register ? DynamicSplitPanelView.Master :
settings.ViewType == ScreenViewType.Details ? DynamicSplitPanelView.Detail : DynamicSplitPanelView.Combined;
SplitPanel.AnchorWidth = settings.AnchorWidth;
var sc = new Dictionary { { Guid.Empty, "All Jobs" } };
var statuses = new Client().Query();
foreach (var row in statuses.Rows)
sc[row.Get(x => x.ID)] = row.Get(x => x.Description);
JobStatus.ItemsSource = sc;
if (sc.ContainsKey(settings.JobStatus))
JobStatus.SelectedValue = settings.JobStatus;
else
JobStatus.SelectedValue = sc.Keys.First();
JobGrid.OnSelectItem += JobGrid_OnSelectItem;
Financials.Visibility = Security.CanView() ? Visibility.Visible : Visibility.Collapsed;
Documents.Visibility = Security.CanView() ? Visibility.Visible : Visibility.Collapsed;
Stages.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
ITPs.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
BOM.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Requisitions.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Orders.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Setouts.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Manufacturing.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Dispatch.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Deliveries.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
OnSite.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Tasks.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
EquipmentTab.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Employees.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Trackers.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Assignments.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Timesheets.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
Forms.Visibility = Security.CanView() ? Visibility.Visible : Visibility.Collapsed;
Invoices.Visibility = Security.CanView() ? Visibility.Visible : Visibility.Collapsed;
Spreadsheets.Visibility = Security.CanView() ? Visibility.Visible : Visibility.Collapsed;
Summary.Visibility = ClientFactory.IsSupported() ? Visibility.Visible : Visibility.Collapsed;
JobGrid.ColumnsTag = settings.ViewType == ScreenViewType.Register ? settings.ViewType.ToString() : "";
JobGrid.Refresh(true, false);
timer = new DispatcherTimer();
timer.Tick += Timer_Tick;
timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
timer.IsEnabled = true;
}
public void Shutdown()
{
timer.IsEnabled = false;
timer = null;
Details.Content = null;
JobDetailsPage = null;
Financials.Content = null;
JobFinancialPage = null;
Documents.Content = null;
JobDocumentsPage = null;
Stages.Content = null;
JobPlanningPage = null;
//Levels.Content = null;
//LevelGrid = null;
//Zones.Content = null;
//ZoneGrid = null;
ITPs.Content = null;
JobITPPage = null;
BOM.Content = null;
JobBillOfMaterialsPage = null;
Setouts.Content = null;
JobDesignsPage = null;
Requisitions.Content = null;
JobRequisitionsPage = null;
Orders.Content = null;
JobOrderPage = null;
Manufacturing.Content = null;
JobManufacturingPage = null;
Dispatch.Content = null;
JobReadyToGoPage = null;
Deliveries.Content = null;
JobDeliveriesPage = null;
OnSite.Content = null;
JobOnSitePage = null;
Tasks.Content = null;
JobTasksPage = null;
EquipmentTab.Content = null;
JobEquipmentPage = null;
Employees.Content = null;
JobEmployeePage = null;
Trackers.Content = null;
JobTrackerPage = null;
Assignments.Content = null;
JobActivitiesPage = null;
Timesheets.Content = null;
JobTimeSheetsPage = null;
Forms.Content = null;
JobFormsPage = null;
Invoices.Content = null;
JobInvoicePage = null;
Spreadsheets.Content = null;
JobSpreadsheetPage = null;
Summary.Content = null;
JobSummaryPage = null;
}
public void Refresh()
{
JobGrid.StatusID = (Guid)JobStatus.SelectedValue; // Refresh(false, true);
lastselection = DateTime.MinValue;
}
public void CreateToolbarButtons(IPanelHost host)
{
host.CreateSetupAction(new PanelAction() { Caption = "Job Settings", Image = PRSDesktop.Resources.specifications, OnExecute = JobSettingsClick });
}
private void JobSettingsClick(PanelAction obj)
{
var pages = new DynamicEditorPages();
var buttons = new DynamicEditorButtons();
buttons.Add(
"",
PRSDesktop.Resources.help.AsBitmapImage(),
_settings,
(f, i) =>
{
Process.Start(new ProcessStartInfo("https://prsdigital.com.au/wiki/index.php/" + typeof(Equipment).Name.SplitCamelCase().Replace(" ", "_"))
{ UseShellExecute = true });
}
);
var propertyEditor = new DynamicEditorForm(typeof(JobPanelSettings), pages, buttons);
propertyEditor.OnDefineLookups += sender =>
{
var editor = sender.EditorDefinition as ILookupEditor;
var colname = sender.ColumnName;
var values = editor.Values(colname, new [] { _settings });
sender.LoadLookups(values);
};
propertyEditor.OnEditorValueChanged += (sender, name, value) =>
{
CoreUtils.SetPropertyValue(_settings, name, value);
return new Dictionary();
};
propertyEditor.Items = new BaseObject[] { _settings };
if (propertyEditor.ShowDialog() == true)
{
new GlobalConfiguration().Save(_settings);
}
}
public event DataModelUpdateEvent? OnUpdateDataModel;
public string SectionName => modelsource?.SectionName ?? "Job Details";
public DataModel DataModel(Selection selection)
{
if (modelsource == null)
{
var row = JobGrid.SelectedRows.FirstOrDefault();
var jobid = row != null ? row.Get(x => x.ID) : CoreUtils.FullGuid;
return new JobDetailsDataModel(new Filter(x => x.ID).IsEqualTo(jobid));
}
return modelsource.DataModel(selection);
}
public void Heartbeat(TimeSpan time)
{
}
private void Timer_Tick(object sender, EventArgs e)
{
if (lastselection < DateTime.Now.AddMilliseconds(-500))
{
lastselection = DateTime.MaxValue;
var row = JobGrid.SelectedRows.FirstOrDefault();
var jobid = row != null ? row.Get(x => x.ID) : CoreUtils.FullGuid;
//Guid customerid = row != null ? row.Get(x => x.Customer.ID) : Guid.Empty;
var page = (PageIndex)JobPages.SelectedIndex;
switch (page)
{
case PageIndex.Details :
RefreshPanel(Details, ref JobDetailsPage, jobid, row != null);
break;
case PageIndex.Financials : RefreshGrid(Financials, ref JobFinancialPage, jobid, row != null);
break;
case PageIndex.Documents : RefreshPanel(Documents, ref JobDocumentsPage, jobid, row != null);
break;
case PageIndex.Stages : RefreshPanel(Stages, ref JobPlanningPage, jobid, row != null);
break;
case PageIndex.ITPs : RefreshGrid(ITPs, ref JobITPPage, jobid, row != null);
break;
case PageIndex.BOM : RefreshPanel(BOM, ref JobBillOfMaterialsPage, jobid, row != null);
break;
case PageIndex.Requisitions : RefreshPanel(Requisitions, ref JobRequisitionsPage, jobid, row != null);
break;
case PageIndex.Orders : RefreshGrid(Orders, ref JobOrderPage, jobid, row != null);
break;
case PageIndex.Designs : RefreshPanel(Setouts, ref JobDesignsPage, jobid, row != null);
break;
case PageIndex.Manufacturing : RefreshGrid(Manufacturing, ref JobManufacturingPage, jobid, row != null);
break;
case PageIndex.Dispatch :
RefreshGrid(Dispatch, ref JobReadyToGoPage, jobid, row != null);
break;
case PageIndex.Delivery :
RefreshPanel(Deliveries, ref JobDeliveriesPage, jobid, row != null);
break;
case PageIndex.Onsite :
RefreshGrid(OnSite, ref JobOnSitePage, jobid, row != null);
break;
case PageIndex.Kanban :
RefreshPanel(Tasks, ref JobTasksPage, jobid, row != null);
break;
case PageIndex.Equipment :
RefreshGrid(EquipmentTab, ref JobEquipmentPage, jobid, row != null);
break;
case PageIndex.Employee :
RefreshPanel(Employees, ref JobEmployeePage, jobid, row != null);
break;
case PageIndex.Tracker :
RefreshGrid(Trackers, ref JobTrackerPage, jobid, row != null);
break;
case PageIndex.Assignment :
RefreshPanel(Assignments, ref JobActivitiesPage, jobid, row != null);
break;
case PageIndex.Timesheet :
RefreshGrid(Timesheets, ref JobTimeSheetsPage, jobid, row != null);
break;
case PageIndex.Form :
RefreshGrid(Forms, ref JobFormsPage, jobid, row != null);
break;
case PageIndex.Invoice :
RefreshPanel(Invoices, ref JobInvoicePage, jobid, row != null);
break;
case PageIndex.Spreadsheets :
RefreshGrid(Spreadsheets, ref JobSpreadsheetPage, jobid, row != null);
break;
case PageIndex.Summary :
RefreshPanel(Summary, ref JobSummaryPage, jobid, row != null);
break;
}
}
}
private void RefreshPanel(TabItem container, ref T panel, Guid jobid, bool data) where T : IBasePanel, IJobControl, new()
{
if (panel == null)
{
panel = new T();
panel.IsReady = false;
panel.ParentID = CoreUtils.FullGuid;
panel.Settings = _settings;
panel.Setup();
panel.IsReady = true;
container.Content = panel;
}
if (JobPages.SelectedIndex != CurrentPage)
{
modelsource = panel;
OnUpdateDataModel?.Invoke(panel.SectionName, panel.DataModel(Selection.None));
CurrentPage = JobPages.SelectedIndex;
}
panel.ParentID = jobid;
panel.Settings = _settings;
panel.Refresh();
}
private void RefreshGrid(TabItem container, ref T grid, Guid jobid, bool data) where T : IDynamicGrid, IJobControl, IDataModelSource, new()
{
var bInitialised = false;
if (grid == null)
{
grid = new T();
container.Content = grid;
}
else
{
bInitialised = true;
}
if (JobPages.SelectedIndex != CurrentPage)
{
modelsource = grid;
OnUpdateDataModel?.Invoke(grid.SectionName, grid.DataModel(Selection.None));
CurrentPage = JobPages.SelectedIndex;
}
grid.ParentID = jobid;
grid.Settings = _settings;
grid.Refresh(!bInitialised, true);
}
private void JobGrid_OnSelectItem(object sender, DynamicGridSelectionEventArgs e)
{
lastselection = DateTime.Now;
}
private void ShowEmailInterface(PanelAction obj)
{
var form = new EmailInterfaceForm();
form.ShowDialog();
}
private MAPIFolder? FindFolder(NameSpace oNS, string foldername)
{
var folder = oNS.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
if (string.IsNullOrEmpty(foldername))
return folder;
var comps = foldername.Split('/');
foreach (var comp in comps)
{
var curfolder = folder;
var bFound = false;
foreach (MAPIFolder subfolder in folder.Folders)
if (subfolder.Name.Equals(comp))
{
curfolder = subfolder;
bFound = true;
break;
}
if (bFound)
folder = curfolder;
else
return null;
}
return folder;
}
private string ConstructReply(string job, string name, string body, bool html)
{
var emp = new Client().Load(new Filter(x => x.UserLink.ID).IsEqualTo(ClientFactory.UserGuid)).FirstOrDefault();
var template = html
? "Dear {0}
Thankyou for your email.
It has been allocated Job #{1}, and will be attended to as soon as possible.
Job Description:
{2}
Regards,
{3}"
: "Dear {0}\n\nThankyou for your email.\n\nIt has been allocated Job #{1}, and will be attended to as soon as possible.\n\nJob Description:\n================\n{2}\n\nRegards,\n\n{3}";
return string.Format(template, name.Split(' ').First(), job, body, emp != null ? emp.Name : "Frog Software");
}
private void CheckMailbox(PanelAction obj)
{
Progress.SetMessage("Connecting to Mail Service");
var mailer = ClientFactory.CreateMailer();
if (!mailer.Connect())
{
Progress.Close();
MessageBox.Show("Unable to Connect to Mail System!");
return;
}
Progress.SetMessage("Locating PRS Folder");
var prs = mailer.FindFolder(null, "PRS");
if (prs == null)
{
Progress.Close();
MessageBox.Show("Unable to Find PRS Folder");
return;
}
Progress.SetMessage("Locating Archive Folder");
var archive = mailer.FindFolder(prs, "Archive");
if (archive == null)
{
Progress.Close();
MessageBox.Show("Unable to Find PRS/Archive Folder");
return;
}
var me = new Client().Load(new Filter(x => x.UserLink.ID).IsEqualTo(ClientFactory.UserGuid)).FirstOrDefault();
if (me == null)
{
Progress.Close();
MessageBox.Show(string.Format("Employee [{0}] does not have a valid email address", me.Name));
return;
}
//Outlook.Application app = new Outlook.Application();
//Outlook.NameSpace ns = app.GetNamespace("mapi");
//ns.Logon(Missing.Value, Missing.Value, false, true);
//Outlook.MAPIFolder inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
//Outlook.MAPIFolder folder = FindFolder(ns,"PRS");
//if (folder == null)
// folder = (Outlook.Folder)inbox.Folders.Add("PRS",Outlook.OlDefaultFolders.olFolderInbox);
//Outlook.MAPIFolder archive = FindFolder(ns, "PRS/Archive");
//if (archive == null)
// archive = (Outlook.Folder)folder.Folders.Add("Archive", Outlook.OlDefaultFolders.olFolderInbox);
JobGrid jg = null;
Customer[] customers = null;
Progress.SetMessage("Scanning PRS Folder");
var items = mailer.GetMessages(prs);
foreach (var item in items)
{
if (customers == null)
{
Progress.SetMessage("Loading Customer Details");
customers = new Client().Load();
}
var cust = customers.FirstOrDefault(x => x.Email.Equals(item.From));
if (cust != null)
{
if (jg == null)
jg = new JobGrid();
var job = new Job();
jg.OnCustomiseEditor += Jg_OnCustomiseEditor;
job.Name = item.Subject;
job.Notes = new[] { item.Body };
job.Customer.ID = cust.ID;
job.Customer.Synchronise(cust);
job.Account.ID = !cust.Account.IsValid() ? cust.ID : cust.Account.ID;
var defstatus = new Client().Query(new Filter(x => x.Default).IsEqualTo(true));
if (defstatus.Rows.Any())
job.JobStatus.ID = defstatus.Rows.First().Get(x => x.ID);
Progress.Close();
if (jg.EditItems(new[] { job }))
{
item.Subject = string.Format("{0} (PRS #{1})", job.Name, job.JobNumber);
item.Save();
mailer.MoveMessage(item, archive);
//item.Move(archive);
var message = mailer.CreateMessage();
message.From = me.Email;
message.Subject = string.Format("RE: {0}", item.Subject);
message.Body = ConstructReply(job.JobNumber, cust.Name, string.Join("\n\n", job.Notes), false);
message.To = new[] { cust.Email };
mailer.SendMessage(message);
//Outlook.MailItem replyMail = item.ReplyAll();
//replyMail.To = cust.Email;
//replyMail.Body = ConstructReply(job.JobNumber, cust.Name, String.Join("\n\n",job.Notes), false);
//replyMail.Send();
}
Progress.Show("Scanning PRS Folder");
}
}
items = null;
Progress.SetMessage("Refreshing");
Refresh();
Progress.Close();
MessageBox.Show("All Done");
//ns.Logoff();
//folder = null;
//ns = null;
//app = null;
}
private void Jg_OnCustomiseEditor(IDynamicEditorForm sender, Job[]? items, DynamicGridColumn column, BaseEditor editor)
{
if (column.ColumnName.Equals("Notes"))
{
if (editor is NotesEditor notes)
notes.AlwaysEnabled = true;
}
}
public Dictionary DataEnvironment()
{
var env = new Dictionary();
env[typeof(Job)] = JobGrid.Data;
return env;
}
private void JobPages_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.Source == JobPages)
lastselection = DateTime.MinValue;
}
private void JobStatus_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (IsReady)
{
settings.JobStatus = (Guid)JobStatus.SelectedValue;
new UserConfiguration().Save(settings);
JobGrid.StatusID = (Guid)JobStatus.SelectedValue;
}
}
private void SplitPanel_OnChanged(object sender, DynamicSplitPanelSettings e)
{
settings.ViewType = SplitPanel.View == DynamicSplitPanelView.Master ? ScreenViewType.Register :
SplitPanel.View == DynamicSplitPanelView.Detail ? ScreenViewType.Details : ScreenViewType.Combined;
settings.AnchorWidth = SplitPanel.AnchorWidth;
new UserConfiguration().Save(settings);
var newTag = settings.ViewType == ScreenViewType.Register ? settings.ViewType.ToString() : "";
if (JobGrid.ColumnsTag != newTag)
{
JobGrid.ColumnsTag = newTag;
JobGrid.Refresh(true, true);
}
}
}
}