NotificationUtils.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows;
  6. using Comal.Classes;
  7. using InABox.Clients;
  8. using InABox.Core;
  9. using InABox.DynamicGrid;
  10. using InABox.WPF;
  11. namespace PRSDesktop
  12. {
  13. public static class NotificationUtils
  14. {
  15. private static Entity LoadEntity(Type type, Guid id, params string[] columnnames)
  16. {
  17. var filter = Activator.CreateInstance(typeof(Filter<>).MakeGenericType(type), "ID", Operator.IsEqualTo, id);
  18. IColumns? columns = null;
  19. if (columnnames.Any())
  20. {
  21. columns = Columns.Create(type);
  22. foreach (var columnname in columnnames)
  23. columns.Add(columnname);
  24. }
  25. var table = ClientFactory.CreateClient(type).Query(filter, columns);
  26. var result = table.Rows.FirstOrDefault()?.ToObject(type) as Entity;
  27. return result;
  28. }
  29. private static IDynamicGrid FindDataGrid(Type type)
  30. {
  31. var gridtypes = CoreUtils.TypeList(
  32. AppDomain.CurrentDomain.GetAssemblies(),
  33. myType =>
  34. myType.IsClass
  35. && !myType.IsAbstract
  36. && !myType.IsGenericType
  37. && myType.BaseType != null
  38. && myType.BaseType.Name == typeof(DynamicDataGrid<>).Name
  39. && myType.ContainsInheritedGenericType(type)
  40. ).ToArray();
  41. var gridtype = gridtypes.Any() ? gridtypes.First() : typeof(DynamicDataGrid<>).MakeGenericType(type);
  42. var grid = Activator.CreateInstance(gridtype) as IDynamicGrid;
  43. return grid;
  44. }
  45. private static bool PerformAction(Guid[] ids, Func<Notification, bool> action)
  46. {
  47. if (!ids.Any())
  48. //if (Notifications.SelectedRows?.FirstOrDefault() == null)
  49. {
  50. MessageBox.Show("Please select a message first!");
  51. return false;
  52. }
  53. var updates = new List<Notification>();
  54. Notification[] notifications = { };
  55. var columns = new Columns<Notification>().Default(ColumnType.IncludeForeignKeys);
  56. columns.Add(x => x.EntityID);
  57. columns.Add(x => x.EntityType);
  58. columns.Add(x => x.Closed);
  59. columns.Add(x => x.Sender.Name);
  60. columns.Add(x => x.Description);
  61. using (new WaitCursor())
  62. {
  63. notifications = new Client<Notification>().Query(
  64. new Filter<Notification>(x => x.ID).InList(ids),
  65. columns
  66. ).Rows.Select(x => x.ToObject<Notification>()).ToArray();
  67. }
  68. foreach (var notification in notifications)
  69. if (action.Invoke(notification))
  70. updates.Add(notification);
  71. if (updates.Any())
  72. {
  73. using (new WaitCursor())
  74. {
  75. new Client<Notification>().Save(updates, "");
  76. }
  77. return true;
  78. }
  79. return false;
  80. }
  81. public static bool IsDigitalForm(string name)
  82. {
  83. if (string.IsNullOrWhiteSpace(name))
  84. return false;
  85. var type = CoreUtils.GetEntity(name);
  86. var result = type.GetInterfaces().Contains(typeof(IDigitalFormInstance));
  87. return result;
  88. }
  89. public static Type? GetEntityType(string name)
  90. {
  91. if (string.IsNullOrWhiteSpace(name))
  92. return null;
  93. if (!IsDigitalForm(name))
  94. return CoreUtils.GetEntityOrNull(name);
  95. var form = CoreUtils.GetEntityOrNull(name);
  96. if (form is null)
  97. return null;
  98. var parent = CoreUtils.GetProperty(form, "Parent");
  99. var type = parent.PropertyType.GetInheritedGenericTypeArguments().FirstOrDefault();
  100. return type;
  101. }
  102. public static bool MakeVisible(FrameworkElement element, float left, float right, params bool[] visibleconditions)
  103. {
  104. var visible = true;
  105. foreach (var condition in visibleconditions)
  106. visible = visible && condition;
  107. element.Visibility = visible ? Visibility.Visible : Visibility.Collapsed;
  108. element.Margin = new Thickness(left, element.Margin.Top, right, element.Margin.Bottom);
  109. return visible;
  110. }
  111. public static bool ViewEntity(Guid[] ids)
  112. {
  113. return PerformAction(ids, notification =>
  114. {
  115. var type = GetEntityType(notification.EntityType);
  116. var id = notification.EntityID;
  117. if (IsDigitalForm(notification.EntityType))
  118. {
  119. var form = (LoadEntity(
  120. CoreUtils.GetEntity(notification.EntityType),
  121. notification.EntityID,
  122. "ID", "Parent.ID") as IDigitalFormInstance)!;
  123. id = form.ParentID();
  124. }
  125. var entity = LoadEntity(type, id);
  126. var grid = FindDataGrid(type);
  127. return grid.EditItems(new object[] { entity });
  128. });
  129. }
  130. public static bool ViewForm(Guid[] ids)
  131. {
  132. return PerformAction(ids, notification =>
  133. {
  134. var type = CoreUtils.GetEntity(notification.EntityType);
  135. var form = LoadEntity(type, notification.EntityID);
  136. if(form is IDigitalFormInstance formInstance)
  137. {
  138. if(DynamicFormEditWindow.EditDigitalForm(formInstance, out var dataModel)){
  139. dataModel.Update(null);
  140. return true;
  141. }
  142. }
  143. return false;
  144. });
  145. }
  146. public static bool ReplyOrForward(Guid[] ids, string prefix, bool selectrecipient, bool sentfolder)
  147. {
  148. return PerformAction(ids, notification =>
  149. {
  150. var sb = new StringBuilder(string.Format("\n\nAt {0:HH:mmtt} on {0:dd MMM yy}, {1} wrote:\n", notification.Created,
  151. notification.Sender.Name));
  152. var desc = string.IsNullOrWhiteSpace(notification.Description) ? "" : CoreUtils.StripHTML(notification.Description);
  153. foreach (var line in desc.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrWhiteSpace(x)))
  154. sb.AppendFormat("> {0}\n", line.Trim());
  155. var form = new NotificationForm
  156. {
  157. Subject = string.Format("{0} {1}", prefix, notification.Title),
  158. Recipient = selectrecipient ? sentfolder ? notification.Employee.ID : notification.Sender.ID : Guid.Empty,
  159. JobID = notification.Job.ID,
  160. Description = sb.ToString()
  161. };
  162. if (form.ShowDialog() == true)
  163. {
  164. notification.Description = string.Format("{0}\nReplied to Message", notification.Description);
  165. if (MessageBox.Show("Do you want to dismiss this message?", "Task Created", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
  166. notification.Closed = DateTime.Now;
  167. return true;
  168. }
  169. return false;
  170. });
  171. }
  172. public static bool CreateTask(Guid[] ids, Guid employeeid)
  173. {
  174. return PerformAction(ids, notification =>
  175. {
  176. var task = new Kanban
  177. {
  178. Title = notification.Title,
  179. Notes = new[] { notification.Description },
  180. Category = "Open"
  181. };
  182. task.JobLink.ID = notification.Job.ID;
  183. task.EmployeeLink.ID = employeeid;
  184. task.ManagerLink.ID = notification.Sender.ID;
  185. var kg = new KanbanGrid();
  186. if (kg.EditItems(new[] { task }))
  187. {
  188. using (new WaitCursor())
  189. {
  190. task = new Client<Kanban>().Load(new Filter<Kanban>(x => x.ID).IsEqualTo(task.ID)).FirstOrDefault();
  191. }
  192. notification.Description = string.Format("{0}\nCreated Task for {1}", notification.Description, task.EmployeeLink.Name);
  193. //notification.Kanban.ID = task.ID;
  194. if (MessageBox.Show("Do you want to dismiss this message?", "Task Created", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
  195. notification.Closed = DateTime.Now;
  196. return true;
  197. }
  198. return false;
  199. });
  200. }
  201. public static bool CreateRequi(Guid[] ids, Guid employeeid)
  202. {
  203. return PerformAction(ids, notification =>
  204. {
  205. var requi = new Requisition
  206. {
  207. Title = notification.Title,
  208. Notes = new[] { notification.Description }
  209. };
  210. requi.JobLink.ID = notification.Job.ID;
  211. requi.Employee.ID = employeeid;
  212. requi.RequestedBy.ID = notification.Sender.ID;
  213. var grid = new DynamicDataGrid<Requisition>();
  214. if (grid.EditItems(new[] { requi }))
  215. {
  216. notification.Description = string.Format("{0}\nCreated Requi# {1}", notification.Description, requi.Number);
  217. //notification.Requisition.ID = requi.ID;
  218. if (MessageBox.Show("Do you want to dismiss this message?", "Requisition Created", MessageBoxButton.YesNo) ==
  219. MessageBoxResult.Yes)
  220. notification.Closed = DateTime.Now;
  221. return true;
  222. }
  223. return false;
  224. });
  225. }
  226. public static bool CreateDelivery(Guid[] ids)
  227. {
  228. return PerformAction(ids, notification =>
  229. {
  230. var delivery = new Delivery
  231. {
  232. Notes = notification.Description,
  233. Due = DateTime.Today.AddDays(1)
  234. };
  235. delivery.Employee.ID = notification.Sender.ID;
  236. delivery.Job.ID = notification.Job.ID;
  237. var grid = new DynamicDataGrid<Delivery>();
  238. if (grid.EditItems(new[] { delivery }))
  239. {
  240. notification.Description = string.Format("{0}\nCreated Delivery# {1}", notification.Description, delivery.Number);
  241. //notification.Delivery.ID = delivery.ID;
  242. if (MessageBox.Show("Do you want to dismiss this message?", "Delivery Created", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
  243. notification.Closed = DateTime.Now;
  244. return true;
  245. }
  246. return false;
  247. });
  248. }
  249. public static bool AttachToJob(Guid[] ids)
  250. {
  251. return PerformAction(ids, notification =>
  252. {
  253. var jobs = new MultiSelectDialog<Job>(
  254. null,
  255. new Columns<Job>(x => x.ID), //new System.Linq.Expressions.Expression<Func<Job, object>>[] { x=>x.ID },
  256. false
  257. );
  258. if (jobs.ShowDialog() != true)
  259. return false;
  260. notification.Job.ID = jobs.IDs().First();
  261. return true;
  262. });
  263. }
  264. public static bool ViewJob(Guid[] ids)
  265. {
  266. return PerformAction(ids, notification =>
  267. {
  268. var job = new Client<Job>().Load(new Filter<Job>(x => x.ID).IsEqualTo(notification.Job.ID)).FirstOrDefault();
  269. if (job != null)
  270. FindDataGrid(typeof(Job)).EditItems(new[] { job });
  271. return false;
  272. });
  273. }
  274. public static bool CreateSetout(Guid[] ids)
  275. {
  276. return PerformAction(ids, notification =>
  277. {
  278. var templates = new MultiSelectDialog<ManufacturingTemplate>(
  279. null,
  280. new Columns<ManufacturingTemplate>(x =>
  281. x.ID), //new System.Linq.Expressions.Expression<Func<ManufacturingTemplate, object>>[] { x=>x.ID },
  282. false
  283. );
  284. if (templates.ShowDialog() != true)
  285. return false;
  286. var template = templates.Items().FirstOrDefault();
  287. Setout setout = null;
  288. ManufacturingPacket packet = null;
  289. var pstages = new List<ManufacturingPacketStage>();
  290. using (new WaitCursor())
  291. {
  292. var setoutnumber = string.Format("{0}-{1:yyMMdd}-", notification.Job.JobNumber, DateTime.Today);
  293. var setouts = new Client<Setout>().Query(
  294. new Filter<Setout>(x => x.JobLink.ID).IsEqualTo(notification.Job.ID).And(x => x.Number).BeginsWith(setoutnumber),
  295. new Columns<Setout>(x => x.Number),
  296. new SortOrder<Setout>(x => x.Number)
  297. ).Rows;
  298. var i = 1;
  299. while (setouts.Any(r => r.Get<Setout, string>(c => c.Number).Equals(string.Format("{0}{1:D3}", setoutnumber, i))))
  300. i++;
  301. setout = new Setout
  302. {
  303. Description = notification.Description,
  304. Reference = notification.Title,
  305. Number = string.Format("{0}{1:D2}", setoutnumber, i)
  306. };
  307. setout.JobLink.ID = notification.Job.ID;
  308. new Client<Setout>().Save(setout, "Created from Notification");
  309. packet = new ManufacturingPacket();
  310. packet.SetoutLink.ID = setout.ID;
  311. //packet.JobLink.ID = notification.Job.ID;
  312. packet.Serial = string.Format("{0}-001", setout.Number);
  313. packet.Group = template.Factory.Name;
  314. packet.ManufacturingTemplateLink.ID = template.ID;
  315. packet.ManufacturingTemplateLink.Code = template.Code;
  316. packet.Title = notification.Title;
  317. packet.Quantity = 1;
  318. new Client<ManufacturingPacket>().Save(packet, "Created from Notification");
  319. var tstages = new Client<ManufacturingTemplateStage>().Load(
  320. new Filter<ManufacturingTemplateStage>(x => x.Template.ID).IsEqualTo(packet.ManufacturingTemplateLink.ID),
  321. new SortOrder<ManufacturingTemplateStage>(x => x.Sequence)
  322. );
  323. foreach (var tstage in tstages)
  324. {
  325. var pstage = new ManufacturingPacketStage
  326. {
  327. Time = tstage.Time,
  328. Sequence = tstage.Sequence,
  329. SequenceType = tstage.SequenceType,
  330. Started = DateTime.MinValue,
  331. PercentageComplete = 0.0F,
  332. Completed = DateTime.MinValue,
  333. QualityChecks = tstage.QualityChecks,
  334. QualityStatus = QualityStatus.NotChecked,
  335. QualityNotes = ""
  336. };
  337. var section = new Client<ManufacturingSection>()
  338. .Load(new Filter<ManufacturingSection>(x => x.ID).IsEqualTo(tstage.Section.ID))
  339. .FirstOrDefault();
  340. if (section != null)
  341. {
  342. pstage.ManufacturingSectionLink.ID = tstage.Section.ID;
  343. pstage.ManufacturingSectionLink.Name = tstage.Section.Name;
  344. }
  345. pstages.Add(pstage);
  346. }
  347. new Client<ManufacturingPacketStage>().Save(pstages, "Created from Notification");
  348. }
  349. var grid = new DynamicDataGrid<Setout>();
  350. if (grid.EditItems(new[] { setout }))
  351. {
  352. notification.Description = string.Format("{0}\nCreated Setout# {1}", notification.Description, setout.Number);
  353. //notification.Setout.ID = setout.ID;
  354. if (MessageBox.Show("Do you want to dismiss this message?", "Setout Created", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
  355. notification.Closed = DateTime.Now;
  356. return true;
  357. }
  358. using (new WaitCursor())
  359. {
  360. // Cascade on PAcket / PacketStage should** take care of the child records
  361. // Be good to keep an eye on that!
  362. new Client<Setout>().Delete(setout, "");
  363. }
  364. return false;
  365. });
  366. }
  367. public static bool Archive(Guid[] ids)
  368. {
  369. return PerformAction(ids, notification =>
  370. {
  371. notification.Closed = DateTime.Now;
  372. return true;
  373. });
  374. }
  375. public static bool Reopen(Guid[] ids)
  376. {
  377. return PerformAction(ids, notification =>
  378. {
  379. notification.Closed = DateTime.MinValue;
  380. return true;
  381. });
  382. }
  383. }
  384. }