JobPanel.xaml.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Threading;
  9. using Comal.Classes;
  10. using InABox.Clients;
  11. using InABox.Configuration;
  12. using InABox.Core;
  13. using InABox.DynamicGrid;
  14. using InABox.DynamicGrid.Spreadsheet;
  15. using InABox.WPF;
  16. using Microsoft.Office.Interop.Outlook;
  17. using Selection = InABox.Core.Selection;
  18. namespace PRSDesktop
  19. {
  20. public class JobPanelSettings : BaseObject, IGlobalConfigurationSettings
  21. {
  22. [Caption("Milestone Task",IncludePath = false)]
  23. public KanbanTypeLink DocumentMilestoneKanbanType { get; set; }
  24. public JobPanelSettings()
  25. {
  26. DocumentMilestoneKanbanType = new KanbanTypeLink();
  27. }
  28. }
  29. /// <summary>
  30. /// Interaction logic for JobPanel.xaml
  31. /// </summary>
  32. public partial class JobPanel : UserControl, IPanel<Job>
  33. {
  34. private enum PageIndex
  35. {
  36. Details = 00,
  37. Financials,
  38. Documents,
  39. Stages,
  40. ITPs,
  41. BOM,
  42. Requisitions,
  43. Orders,
  44. Designs,
  45. Manufacturing,
  46. Dispatch,
  47. Delivery,
  48. Onsite,
  49. Kanban,
  50. Equipment,
  51. Employee,
  52. Tracker,
  53. Assignment,
  54. Timesheet,
  55. Form,
  56. Invoice,
  57. Spreadsheets,
  58. Summary
  59. }
  60. private int CurrentPage = -1;
  61. private JobDetails JobDetailsPage;
  62. private JobFinancialGrid JobFinancialPage;
  63. private JobDocumentSetPanel JobDocumentsPage;
  64. private JobStagesPanel JobPlanningPage;
  65. private JobITPGrid JobITPPage;
  66. private JobBillOfMaterialsPanel JobBillOfMaterialsPage;
  67. private JobRequisitionPanel JobRequisitionsPage;
  68. private JobDesignList JobDesignsPage;
  69. private JobOrderGrid JobOrderPage;
  70. private ManufacturingGrid JobManufacturingPage;
  71. private ReadyToGoGrid JobReadyToGoPage;
  72. private DeliveryPanel JobDeliveriesPage;
  73. private DeliveredOnSiteGrid JobOnSitePage;
  74. private TaskPanel JobTasksPage;
  75. private JobEquipmentGrid JobEquipmentPage;
  76. private JobEmployeePanel JobEmployeePage;
  77. private JobTrackerGrid JobTrackerPage;
  78. private JobAssignmentPanel JobActivitiesPage;
  79. private JobTimesheetGrid JobTimeSheetsPage;
  80. private JobFormGrid JobFormsPage;
  81. private InvoicePanel JobInvoicePage;
  82. private JobSpreadsheetGrid JobSpreadsheetPage;
  83. private JobSummaryPanel JobSummaryPage;
  84. private DateTime lastselection = DateTime.MaxValue;
  85. private IDataModelSource modelsource;
  86. // User Settings
  87. private JobScreenSettings settings;
  88. // Global Settings
  89. private JobPanelSettings _settings = null;
  90. private DispatcherTimer timer;
  91. public JobPanel()
  92. {
  93. InitializeComponent();
  94. }
  95. public bool IsReady { get; set; }
  96. public Dictionary<string, object[]> Selected()
  97. {
  98. return (PageIndex)JobPages.SelectedIndex switch
  99. {
  100. PageIndex.Details => JobDetailsPage.Selected(),
  101. PageIndex.Financials => JobFinancialPage.Selected(),
  102. PageIndex.Documents => JobDocumentsPage.Selected(),
  103. PageIndex.Stages => JobPlanningPage.Selected(),
  104. PageIndex.ITPs => new Dictionary<string, object[]> { { typeof(JobITP).EntityName(), JobITPPage.SelectedRows } },
  105. PageIndex.BOM => new Dictionary<string, object[]>
  106. { { typeof(JobBillOfMaterials).EntityName(), JobBillOfMaterialsPage.SelectedRows } },
  107. PageIndex.Designs => JobDesignsPage.Selected(),
  108. PageIndex.Orders => new Dictionary<string, object[]> { { typeof(PurchaseOrderItem).EntityName(), JobOrderPage.SelectedRows } },
  109. PageIndex.Requisitions => new Dictionary<string, object[]>
  110. { { typeof(JobRequisition).EntityName(), JobRequisitionsPage.Requisitions.SelectedRows } },
  111. PageIndex.Manufacturing => new Dictionary<string, object[]>
  112. { { typeof(ManufacturingPacket).EntityName(), JobManufacturingPage.SelectedRows } },
  113. PageIndex.Dispatch => new Dictionary<string, object[]> { { typeof(DeliveryItem).EntityName(), JobReadyToGoPage.SelectedRows } },
  114. PageIndex.Delivery => new Dictionary<string, object[]>
  115. { { typeof(Delivery).EntityName(), JobDeliveriesPage.Deliveries.SelectedRows } },
  116. PageIndex.Onsite => new Dictionary<string, object[]> { { typeof(DeliveryItem).EntityName(), JobOnSitePage.SelectedRows } },
  117. PageIndex.Kanban => JobTasksPage.Selected(),
  118. PageIndex.Equipment => new Dictionary<string, object[]> { { typeof(Equipment).EntityName(), JobEquipmentPage.SelectedRows } },
  119. PageIndex.Employee => new Dictionary<string, object[]>
  120. { { typeof(Employee).EntityName(), JobEmployeePage.Employees.SelectedRows } },
  121. PageIndex.Tracker => new Dictionary<string, object[]> { { typeof(GPSTracker).EntityName(), JobTrackerPage.SelectedRows } },
  122. PageIndex.Assignment => new Dictionary<string, object[]>
  123. { { typeof(Assignment).EntityName(), JobActivitiesPage.Assignments.SelectedRows } },
  124. PageIndex.Timesheet => new Dictionary<string, object[]> { { typeof(TimeSheet).EntityName(), JobTimeSheetsPage.SelectedRows } },
  125. PageIndex.Form => new Dictionary<string, object[]> { { typeof(JobForm).EntityName(), JobFormsPage.SelectedRows } },
  126. PageIndex.Invoice => new Dictionary<string, object[]> { { typeof(Invoice).EntityName(), JobInvoicePage.Invoices.SelectedRows } },
  127. PageIndex.Spreadsheets => new Dictionary<string, object[]> { { typeof(JobSpreadsheet).EntityName(), JobSpreadsheetPage.SelectedRows } },
  128. PageIndex.Summary => new Dictionary<string, object[]> { { typeof(JobMaterial).EntityName(), JobSummaryPage.Summary.SelectedRows } },
  129. _ => new Dictionary<string,object[]> {{ typeof(Job).EntityName(), JobGrid.SelectedRows}}
  130. };
  131. }
  132. public void Setup()
  133. {
  134. Task[] settingstasks = new Task[]
  135. {
  136. Task.Run(() =>
  137. {
  138. _settings = new GlobalConfiguration<JobPanelSettings>().Load();
  139. }),
  140. Task.Run(() =>
  141. {
  142. settings = new UserConfiguration<JobScreenSettings>().Load();
  143. })
  144. };
  145. Task.WaitAll(settingstasks);
  146. SplitPanel.View = settings.ViewType == ScreenViewType.Register ? DynamicSplitPanelView.Master :
  147. settings.ViewType == ScreenViewType.Details ? DynamicSplitPanelView.Detail : DynamicSplitPanelView.Combined;
  148. SplitPanel.AnchorWidth = settings.AnchorWidth;
  149. var sc = new Dictionary<Guid, string> { { Guid.Empty, "All Jobs" } };
  150. var statuses = new Client<JobStatus>().Query();
  151. foreach (var row in statuses.Rows)
  152. sc[row.Get<JobStatus, Guid>(x => x.ID)] = row.Get<JobStatus, string>(x => x.Description);
  153. JobStatus.ItemsSource = sc;
  154. if (sc.ContainsKey(settings.JobStatus))
  155. JobStatus.SelectedValue = settings.JobStatus;
  156. else
  157. JobStatus.SelectedValue = sc.Keys.First();
  158. JobGrid.OnSelectItem += JobGrid_OnSelectItem;
  159. Financials.Visibility = Security.CanView<JobFinancial>() ? Visibility.Visible : Visibility.Collapsed;
  160. Documents.Visibility = Security.CanView<JobDocumentSet>() ? Visibility.Visible : Visibility.Collapsed;
  161. Stages.Visibility = ClientFactory.IsSupported<JobStage>() ? Visibility.Visible : Visibility.Collapsed;
  162. ITPs.Visibility = ClientFactory.IsSupported<JobITP>() ? Visibility.Visible : Visibility.Collapsed;
  163. BOM.Visibility = ClientFactory.IsSupported<JobBillOfMaterials>() ? Visibility.Visible : Visibility.Collapsed;
  164. Requisitions.Visibility = ClientFactory.IsSupported<JobRequisition>() ? Visibility.Visible : Visibility.Collapsed;
  165. Orders.Visibility = ClientFactory.IsSupported<PurchaseOrderItem>() ? Visibility.Visible : Visibility.Collapsed;
  166. Setouts.Visibility = ClientFactory.IsSupported<Setout>() ? Visibility.Visible : Visibility.Collapsed;
  167. Manufacturing.Visibility = ClientFactory.IsSupported<ManufacturingPacket>() ? Visibility.Visible : Visibility.Collapsed;
  168. Dispatch.Visibility = ClientFactory.IsSupported<DeliveryItem>() ? Visibility.Visible : Visibility.Collapsed;
  169. Deliveries.Visibility = ClientFactory.IsSupported<Delivery>() ? Visibility.Visible : Visibility.Collapsed;
  170. OnSite.Visibility = ClientFactory.IsSupported<DeliveryItem>() ? Visibility.Visible : Visibility.Collapsed;
  171. Tasks.Visibility = ClientFactory.IsSupported<Kanban>() ? Visibility.Visible : Visibility.Collapsed;
  172. EquipmentTab.Visibility = ClientFactory.IsSupported<Equipment>() ? Visibility.Visible : Visibility.Collapsed;
  173. Employees.Visibility = ClientFactory.IsSupported<Employee>() ? Visibility.Visible : Visibility.Collapsed;
  174. Trackers.Visibility = ClientFactory.IsSupported<GPSTracker>() ? Visibility.Visible : Visibility.Collapsed;
  175. Assignments.Visibility = ClientFactory.IsSupported<Assignment>() ? Visibility.Visible : Visibility.Collapsed;
  176. Timesheets.Visibility = ClientFactory.IsSupported<TimeSheet>() ? Visibility.Visible : Visibility.Collapsed;
  177. Forms.Visibility = Security.CanView<JobForm>() ? Visibility.Visible : Visibility.Collapsed;
  178. Invoices.Visibility = Security.CanView<Invoice>() ? Visibility.Visible : Visibility.Collapsed;
  179. Spreadsheets.Visibility = Security.CanView<JobSpreadsheet>() ? Visibility.Visible : Visibility.Collapsed;
  180. Summary.Visibility = ClientFactory.IsSupported<JobMaterial>() ? Visibility.Visible : Visibility.Collapsed;
  181. JobGrid.ColumnsTag = settings.ViewType == ScreenViewType.Register ? settings.ViewType.ToString() : "";
  182. JobGrid.Refresh(true, false);
  183. timer = new DispatcherTimer();
  184. timer.Tick += Timer_Tick;
  185. timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
  186. timer.IsEnabled = true;
  187. }
  188. public void Shutdown()
  189. {
  190. timer.IsEnabled = false;
  191. timer = null;
  192. Details.Content = null;
  193. JobDetailsPage = null;
  194. Financials.Content = null;
  195. JobFinancialPage = null;
  196. Documents.Content = null;
  197. JobDocumentsPage = null;
  198. Stages.Content = null;
  199. JobPlanningPage = null;
  200. //Levels.Content = null;
  201. //LevelGrid = null;
  202. //Zones.Content = null;
  203. //ZoneGrid = null;
  204. ITPs.Content = null;
  205. JobITPPage = null;
  206. BOM.Content = null;
  207. JobBillOfMaterialsPage = null;
  208. Setouts.Content = null;
  209. JobDesignsPage = null;
  210. Requisitions.Content = null;
  211. JobRequisitionsPage = null;
  212. Orders.Content = null;
  213. JobOrderPage = null;
  214. Manufacturing.Content = null;
  215. JobManufacturingPage = null;
  216. Dispatch.Content = null;
  217. JobReadyToGoPage = null;
  218. Deliveries.Content = null;
  219. JobDeliveriesPage = null;
  220. OnSite.Content = null;
  221. JobOnSitePage = null;
  222. Tasks.Content = null;
  223. JobTasksPage = null;
  224. EquipmentTab.Content = null;
  225. JobEquipmentPage = null;
  226. Employees.Content = null;
  227. JobEmployeePage = null;
  228. Trackers.Content = null;
  229. JobTrackerPage = null;
  230. Assignments.Content = null;
  231. JobActivitiesPage = null;
  232. Timesheets.Content = null;
  233. JobTimeSheetsPage = null;
  234. Forms.Content = null;
  235. JobFormsPage = null;
  236. Invoices.Content = null;
  237. JobInvoicePage = null;
  238. Spreadsheets.Content = null;
  239. JobSpreadsheetPage = null;
  240. Summary.Content = null;
  241. JobSummaryPage = null;
  242. }
  243. public void Refresh()
  244. {
  245. JobGrid.StatusID = (Guid)JobStatus.SelectedValue; // Refresh(false, true);
  246. lastselection = DateTime.MinValue;
  247. }
  248. public void CreateToolbarButtons(IPanelHost host)
  249. {
  250. host.CreateSetupAction(new PanelAction() { Caption = "Job Settings", Image = PRSDesktop.Resources.specifications, OnExecute = JobSettingsClick });
  251. }
  252. private void JobSettingsClick(PanelAction obj)
  253. {
  254. var pages = new DynamicEditorPages();
  255. var buttons = new DynamicEditorButtons();
  256. buttons.Add(
  257. "",
  258. PRSDesktop.Resources.help.AsBitmapImage(),
  259. _settings,
  260. (f, i) =>
  261. {
  262. Process.Start(new ProcessStartInfo("https://prsdigital.com.au/wiki/index.php/" + typeof(Equipment).Name.SplitCamelCase().Replace(" ", "_"))
  263. { UseShellExecute = true });
  264. }
  265. );
  266. var propertyEditor = new DynamicEditorForm(typeof(JobPanelSettings), pages, buttons);
  267. propertyEditor.OnDefineLookups += sender =>
  268. {
  269. var editor = sender.EditorDefinition as ILookupEditor;
  270. var colname = sender.ColumnName;
  271. var values = editor.Values(colname, new [] { _settings });
  272. sender.LoadLookups(values);
  273. };
  274. propertyEditor.OnEditorValueChanged += (sender, name, value) =>
  275. {
  276. CoreUtils.SetPropertyValue(_settings, name, value);
  277. return new Dictionary<string, object?>();
  278. };
  279. propertyEditor.Items = new BaseObject[] { _settings };
  280. if (propertyEditor.ShowDialog() == true)
  281. {
  282. new GlobalConfiguration<JobPanelSettings>().Save(_settings);
  283. }
  284. }
  285. public event DataModelUpdateEvent? OnUpdateDataModel;
  286. public string SectionName => modelsource?.SectionName ?? "Job Details";
  287. public DataModel DataModel(Selection selection)
  288. {
  289. if (modelsource == null)
  290. {
  291. var row = JobGrid.SelectedRows.FirstOrDefault();
  292. var jobid = row != null ? row.Get<Job, Guid>(x => x.ID) : CoreUtils.FullGuid;
  293. return new JobDetailsDataModel(new Filter<Job>(x => x.ID).IsEqualTo(jobid));
  294. }
  295. return modelsource.DataModel(selection);
  296. }
  297. public void Heartbeat(TimeSpan time)
  298. {
  299. }
  300. private void Timer_Tick(object sender, EventArgs e)
  301. {
  302. if (lastselection < DateTime.Now.AddMilliseconds(-500))
  303. {
  304. lastselection = DateTime.MaxValue;
  305. var row = JobGrid.SelectedRows.FirstOrDefault();
  306. var jobid = row != null ? row.Get<Job, Guid>(x => x.ID) : CoreUtils.FullGuid;
  307. //Guid customerid = row != null ? row.Get<Job, Guid>(x => x.Customer.ID) : Guid.Empty;
  308. var page = (PageIndex)JobPages.SelectedIndex;
  309. switch (page)
  310. {
  311. case PageIndex.Details :
  312. RefreshPanel(Details, ref JobDetailsPage, jobid, row != null);
  313. break;
  314. case PageIndex.Financials : RefreshGrid(Financials, ref JobFinancialPage, jobid, row != null);
  315. break;
  316. case PageIndex.Documents : RefreshPanel(Documents, ref JobDocumentsPage, jobid, row != null);
  317. break;
  318. case PageIndex.Stages : RefreshPanel(Stages, ref JobPlanningPage, jobid, row != null);
  319. break;
  320. case PageIndex.ITPs : RefreshGrid(ITPs, ref JobITPPage, jobid, row != null);
  321. break;
  322. case PageIndex.BOM : RefreshPanel(BOM, ref JobBillOfMaterialsPage, jobid, row != null);
  323. break;
  324. case PageIndex.Requisitions : RefreshPanel(Requisitions, ref JobRequisitionsPage, jobid, row != null);
  325. break;
  326. case PageIndex.Orders : RefreshGrid(Orders, ref JobOrderPage, jobid, row != null);
  327. break;
  328. case PageIndex.Designs : RefreshPanel(Setouts, ref JobDesignsPage, jobid, row != null);
  329. break;
  330. case PageIndex.Manufacturing : RefreshGrid(Manufacturing, ref JobManufacturingPage, jobid, row != null);
  331. break;
  332. case PageIndex.Dispatch :
  333. RefreshGrid(Dispatch, ref JobReadyToGoPage, jobid, row != null);
  334. break;
  335. case PageIndex.Delivery :
  336. RefreshPanel(Deliveries, ref JobDeliveriesPage, jobid, row != null);
  337. break;
  338. case PageIndex.Onsite :
  339. RefreshGrid(OnSite, ref JobOnSitePage, jobid, row != null);
  340. break;
  341. case PageIndex.Kanban :
  342. RefreshPanel(Tasks, ref JobTasksPage, jobid, row != null);
  343. break;
  344. case PageIndex.Equipment :
  345. RefreshGrid(EquipmentTab, ref JobEquipmentPage, jobid, row != null);
  346. break;
  347. case PageIndex.Employee :
  348. RefreshPanel(Employees, ref JobEmployeePage, jobid, row != null);
  349. break;
  350. case PageIndex.Tracker :
  351. RefreshGrid(Trackers, ref JobTrackerPage, jobid, row != null);
  352. break;
  353. case PageIndex.Assignment :
  354. RefreshPanel(Assignments, ref JobActivitiesPage, jobid, row != null);
  355. break;
  356. case PageIndex.Timesheet :
  357. RefreshGrid(Timesheets, ref JobTimeSheetsPage, jobid, row != null);
  358. break;
  359. case PageIndex.Form :
  360. RefreshGrid(Forms, ref JobFormsPage, jobid, row != null);
  361. break;
  362. case PageIndex.Invoice :
  363. RefreshPanel(Invoices, ref JobInvoicePage, jobid, row != null);
  364. break;
  365. case PageIndex.Spreadsheets :
  366. RefreshGrid(Spreadsheets, ref JobSpreadsheetPage, jobid, row != null);
  367. break;
  368. case PageIndex.Summary :
  369. RefreshPanel(Summary, ref JobSummaryPage, jobid, row != null);
  370. break;
  371. }
  372. }
  373. }
  374. private void RefreshPanel<T>(TabItem container, ref T panel, Guid jobid, bool data) where T : IBasePanel, IJobControl, new()
  375. {
  376. if (panel == null)
  377. {
  378. panel = new T();
  379. panel.IsReady = false;
  380. panel.ParentID = CoreUtils.FullGuid;
  381. panel.Settings = _settings;
  382. panel.Setup();
  383. panel.IsReady = true;
  384. container.Content = panel;
  385. }
  386. if (JobPages.SelectedIndex != CurrentPage)
  387. {
  388. modelsource = panel;
  389. OnUpdateDataModel?.Invoke(panel.SectionName, panel.DataModel(Selection.None));
  390. CurrentPage = JobPages.SelectedIndex;
  391. }
  392. panel.ParentID = jobid;
  393. panel.Settings = _settings;
  394. panel.Refresh();
  395. }
  396. private void RefreshGrid<T>(TabItem container, ref T grid, Guid jobid, bool data) where T : IDynamicGrid, IJobControl, IDataModelSource, new()
  397. {
  398. var bInitialised = false;
  399. if (grid == null)
  400. {
  401. grid = new T();
  402. container.Content = grid;
  403. }
  404. else
  405. {
  406. bInitialised = true;
  407. }
  408. if (JobPages.SelectedIndex != CurrentPage)
  409. {
  410. modelsource = grid;
  411. OnUpdateDataModel?.Invoke(grid.SectionName, grid.DataModel(Selection.None));
  412. CurrentPage = JobPages.SelectedIndex;
  413. }
  414. grid.ParentID = jobid;
  415. grid.Settings = _settings;
  416. grid.Refresh(!bInitialised, true);
  417. }
  418. private void JobGrid_OnSelectItem(object sender, DynamicGridSelectionEventArgs e)
  419. {
  420. lastselection = DateTime.Now;
  421. }
  422. private void ShowEmailInterface(PanelAction obj)
  423. {
  424. var form = new EmailInterfaceForm();
  425. form.ShowDialog();
  426. }
  427. private MAPIFolder? FindFolder(NameSpace oNS, string foldername)
  428. {
  429. var folder = oNS.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
  430. if (string.IsNullOrEmpty(foldername))
  431. return folder;
  432. var comps = foldername.Split('/');
  433. foreach (var comp in comps)
  434. {
  435. var curfolder = folder;
  436. var bFound = false;
  437. foreach (MAPIFolder subfolder in folder.Folders)
  438. if (subfolder.Name.Equals(comp))
  439. {
  440. curfolder = subfolder;
  441. bFound = true;
  442. break;
  443. }
  444. if (bFound)
  445. folder = curfolder;
  446. else
  447. return null;
  448. }
  449. return folder;
  450. }
  451. private string ConstructReply(string job, string name, string body, bool html)
  452. {
  453. var emp = new Client<Employee>().Load(new Filter<Employee>(x => x.UserLink.ID).IsEqualTo(ClientFactory.UserGuid)).FirstOrDefault();
  454. var template = html
  455. ? "<p>Dear {0}</p>Thankyou for your email.</p><p>It has been allocated Job #{1}, and will be attended to as soon as possible.</p><p><b><u>Job Description:</u></b><br>{2}</p><p>Regards,</p><p>{3}"
  456. : "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}";
  457. return string.Format(template, name.Split(' ').First(), job, body, emp != null ? emp.Name : "Frog Software");
  458. }
  459. private void CheckMailbox(PanelAction obj)
  460. {
  461. Progress.SetMessage("Connecting to Mail Service");
  462. var mailer = ClientFactory.CreateMailer();
  463. if (!mailer.Connect())
  464. {
  465. Progress.Close();
  466. MessageBox.Show("Unable to Connect to Mail System!");
  467. return;
  468. }
  469. Progress.SetMessage("Locating PRS Folder");
  470. var prs = mailer.FindFolder(null, "PRS");
  471. if (prs == null)
  472. {
  473. Progress.Close();
  474. MessageBox.Show("Unable to Find PRS Folder");
  475. return;
  476. }
  477. Progress.SetMessage("Locating Archive Folder");
  478. var archive = mailer.FindFolder(prs, "Archive");
  479. if (archive == null)
  480. {
  481. Progress.Close();
  482. MessageBox.Show("Unable to Find PRS/Archive Folder");
  483. return;
  484. }
  485. var me = new Client<Employee>().Load(new Filter<Employee>(x => x.UserLink.ID).IsEqualTo(ClientFactory.UserGuid)).FirstOrDefault();
  486. if (me == null)
  487. {
  488. Progress.Close();
  489. MessageBox.Show(string.Format("Employee [{0}] does not have a valid email address", me.Name));
  490. return;
  491. }
  492. //Outlook.Application app = new Outlook.Application();
  493. //Outlook.NameSpace ns = app.GetNamespace("mapi");
  494. //ns.Logon(Missing.Value, Missing.Value, false, true);
  495. //Outlook.MAPIFolder inbox = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
  496. //Outlook.MAPIFolder folder = FindFolder(ns,"PRS");
  497. //if (folder == null)
  498. // folder = (Outlook.Folder)inbox.Folders.Add("PRS",Outlook.OlDefaultFolders.olFolderInbox);
  499. //Outlook.MAPIFolder archive = FindFolder(ns, "PRS/Archive");
  500. //if (archive == null)
  501. // archive = (Outlook.Folder)folder.Folders.Add("Archive", Outlook.OlDefaultFolders.olFolderInbox);
  502. JobGrid jg = null;
  503. Customer[] customers = null;
  504. Progress.SetMessage("Scanning PRS Folder");
  505. var items = mailer.GetMessages(prs);
  506. foreach (var item in items)
  507. {
  508. if (customers == null)
  509. {
  510. Progress.SetMessage("Loading Customer Details");
  511. customers = new Client<Customer>().Load();
  512. }
  513. var cust = customers.FirstOrDefault(x => x.Email.Equals(item.From));
  514. if (cust != null)
  515. {
  516. if (jg == null)
  517. jg = new JobGrid();
  518. var job = new Job();
  519. jg.OnCustomiseEditor += Jg_OnCustomiseEditor;
  520. job.Name = item.Subject;
  521. job.Notes = new[] { item.Body };
  522. job.Customer.ID = cust.ID;
  523. job.Customer.Synchronise(cust);
  524. job.Account.ID = !cust.Account.IsValid() ? cust.ID : cust.Account.ID;
  525. var defstatus = new Client<JobStatus>().Query(new Filter<JobStatus>(x => x.Default).IsEqualTo(true));
  526. if (defstatus.Rows.Any())
  527. job.JobStatus.ID = defstatus.Rows.First().Get<JobStatus, Guid>(x => x.ID);
  528. Progress.Close();
  529. if (jg.EditItems(new[] { job }))
  530. {
  531. item.Subject = string.Format("{0} (PRS #{1})", job.Name, job.JobNumber);
  532. item.Save();
  533. mailer.MoveMessage(item, archive);
  534. //item.Move(archive);
  535. var message = mailer.CreateMessage();
  536. message.From = me.Email;
  537. message.Subject = string.Format("RE: {0}", item.Subject);
  538. message.Body = ConstructReply(job.JobNumber, cust.Name, string.Join("\n\n", job.Notes), false);
  539. message.To = new[] { cust.Email };
  540. mailer.SendMessage(message);
  541. //Outlook.MailItem replyMail = item.ReplyAll();
  542. //replyMail.To = cust.Email;
  543. //replyMail.Body = ConstructReply(job.JobNumber, cust.Name, String.Join("\n\n",job.Notes), false);
  544. //replyMail.Send();
  545. }
  546. Progress.Show("Scanning PRS Folder");
  547. }
  548. }
  549. items = null;
  550. Progress.SetMessage("Refreshing");
  551. Refresh();
  552. Progress.Close();
  553. MessageBox.Show("All Done");
  554. //ns.Logoff();
  555. //folder = null;
  556. //ns = null;
  557. //app = null;
  558. }
  559. private void Jg_OnCustomiseEditor(IDynamicEditorForm sender, Job[]? items, DynamicGridColumn column, BaseEditor editor)
  560. {
  561. if (column.ColumnName.Equals("Notes"))
  562. {
  563. if (editor is NotesEditor notes)
  564. notes.AlwaysEnabled = true;
  565. }
  566. }
  567. public Dictionary<Type, CoreTable> DataEnvironment()
  568. {
  569. var env = new Dictionary<Type, CoreTable>();
  570. env[typeof(Job)] = JobGrid.Data;
  571. return env;
  572. }
  573. private void JobPages_SelectionChanged(object sender, SelectionChangedEventArgs e)
  574. {
  575. if (e.Source == JobPages)
  576. lastselection = DateTime.MinValue;
  577. }
  578. private void JobStatus_SelectionChanged(object sender, SelectionChangedEventArgs e)
  579. {
  580. if (IsReady)
  581. {
  582. settings.JobStatus = (Guid)JobStatus.SelectedValue;
  583. new UserConfiguration<JobScreenSettings>().Save(settings);
  584. JobGrid.StatusID = (Guid)JobStatus.SelectedValue;
  585. }
  586. }
  587. private void SplitPanel_OnChanged(object sender, DynamicSplitPanelSettings e)
  588. {
  589. settings.ViewType = SplitPanel.View == DynamicSplitPanelView.Master ? ScreenViewType.Register :
  590. SplitPanel.View == DynamicSplitPanelView.Detail ? ScreenViewType.Details : ScreenViewType.Combined;
  591. settings.AnchorWidth = SplitPanel.AnchorWidth;
  592. new UserConfiguration<JobScreenSettings>().Save(settings);
  593. var newTag = settings.ViewType == ScreenViewType.Register ? settings.ViewType.ToString() : "";
  594. if (JobGrid.ColumnsTag != newTag)
  595. {
  596. JobGrid.ColumnsTag = newTag;
  597. JobGrid.Refresh(true, true);
  598. }
  599. }
  600. }
  601. }