JobPanel.xaml.cs 29 KB

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