ManufacturingTemplateAnalysis.xaml.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Linq;
  5. using System.Text.RegularExpressions;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Data;
  9. using System.Windows.Input;
  10. using Comal.Classes;
  11. using InABox.Clients;
  12. using InABox.Core;
  13. using InABox.WPF;
  14. using PRSDesktop.WidgetGroups;
  15. using Syncfusion.UI.Xaml.Grid;
  16. using Syncfusion.UI.Xaml.Grid.Cells;
  17. using SelectionChangedEventArgs = System.Windows.Controls.SelectionChangedEventArgs;
  18. namespace PRSDesktop
  19. {
  20. public class ManufacturingTemplateAnalysisProperties : IDashboardProperties { }
  21. public class ManufacturingTemplateAnalysisElement : DashboardElement<ManufacturingTemplateAnalysis, Manufacturing, ManufacturingTemplateAnalysisProperties> { }
  22. /// <summary>
  23. /// Interaction logic for ManufacturingTemplateAnalysis.xaml
  24. /// </summary>
  25. public partial class ManufacturingTemplateAnalysis : UserControl, IPanel<ManufacturingTemplate>, IDashboardWidget<Manufacturing, ManufacturingTemplateAnalysisProperties>
  26. {
  27. private bool _activeonly;
  28. private DateTime _from;
  29. private string _search = "";
  30. private DateTime _to;
  31. private DataTable data;
  32. private readonly Dictionary<string, string> SectionDisplayNames = new() { { "Total", "Total" } };
  33. private ManufacturingSection[] sections;
  34. private ManufacturingTemplateStage[] stages;
  35. private ManufacturingTemplate[] templates;
  36. public ManufacturingTemplateAnalysis()
  37. {
  38. _from = DateTime.Today.AddDays(0 - WeekDay(DateTime.Today));
  39. _to = DateTime.Today;
  40. _activeonly = true;
  41. InitializeComponent();
  42. dataGrid.CellRenderers.Remove("StackedHeader");
  43. dataGrid.CellRenderers.Add("StackedHeader", new GridCustomStackedRenderer(Resources));
  44. }
  45. public bool IsReady { get; set; }
  46. public void CreateToolbarButtons(IPanelHost host)
  47. {
  48. }
  49. public string SectionName => "Manufacturing Template Analysis";
  50. public ManufacturingTemplateAnalysisProperties Properties { get; set; }
  51. public DataModel DataModel(Selection selection)
  52. {
  53. return new AutoDataModel<ManufacturingTemplate>(null);
  54. }
  55. public void Refresh()
  56. {
  57. using (new WaitCursor())
  58. {
  59. Progress.Show("Loading Data");
  60. data.Rows.Clear();
  61. templates = new Client<ManufacturingTemplate>().Load(
  62. new Filter<ManufacturingTemplate>(x => x.ID).IsNotEqualTo(Guid.Empty).TextSearch(_search, x => x.Code, x => x.Name),
  63. new SortOrder<ManufacturingTemplate>(x => x.Code)
  64. );
  65. var packets = new Client<ManufacturingPacket>().Query(
  66. new Filter<ManufacturingPacket>(x => x.Completed).IsGreaterThanOrEqualTo(_from).And(x => x.Completed).IsLessThan(_to.AddDays(1)),
  67. new Columns<ManufacturingPacket>
  68. (
  69. x => x.ID,
  70. x => x.ManufacturingTemplateLink.ID,
  71. x => x.Quantity
  72. )
  73. );
  74. var history = new Client<ManufacturingHistory>().Query(
  75. new Filter<ManufacturingHistory>(x => x.Packet.Completed).IsGreaterThanOrEqualTo(_from).And(x => x.Packet.Completed)
  76. .IsLessThan(_to.AddDays(1)),
  77. new Columns<ManufacturingHistory>
  78. (
  79. x => x.Packet.ID,
  80. x => x.Section.ID,
  81. x => x.QADuration,
  82. x => x.WorkDuration
  83. )
  84. );
  85. foreach (var template in templates)
  86. {
  87. Progress.SetMessage(string.Format("Processing {0}: {1}", template.Code, template.Name));
  88. var values = new List<object>();
  89. values.Add(template.Code);
  90. values.Add(template.Name);
  91. var times = new Dictionary<Guid, long>();
  92. foreach (var section in sections)
  93. times[section.ID] = 0L;
  94. var qty = 0;
  95. var pktrows = packets.Rows.Where(r => r.Get<ManufacturingPacket, Guid>(c => c.ManufacturingTemplateLink.ID).Equals(template.ID));
  96. foreach (var pktrow in pktrows)
  97. {
  98. var thisqty = pktrow.Get<ManufacturingPacket, int>(x => x.Quantity);
  99. if (thisqty > 0)
  100. {
  101. qty += thisqty;
  102. foreach (var section in sections)
  103. if (stages.Any(x => x.Template.ID.Equals(template.ID) && x.Section.ID.Equals(section.ID)))
  104. {
  105. var pktid = pktrow.Get<ManufacturingPacket, Guid>(c => c.ID);
  106. var histrows = history.Rows.Where(r =>
  107. r.Get<ManufacturingHistory, Guid>(c => c.Section.ID).Equals(section.ID) &&
  108. r.Get<ManufacturingHistory, Guid>(c => c.Packet.ID).Equals(pktid));
  109. foreach (var histrow in histrows)
  110. times[section.ID] += histrow.Get<ManufacturingHistory, TimeSpan>(c => c.QADuration).Ticks +
  111. histrow.Get<ManufacturingHistory, TimeSpan>(c => c.WorkDuration).Ticks;
  112. }
  113. }
  114. }
  115. if (qty > 0)
  116. values.Add(qty);
  117. else
  118. values.Add(null);
  119. var total = 0L;
  120. foreach (var section in sections)
  121. {
  122. total += times[section.ID];
  123. if (qty > 0 && times[section.ID] > 0)
  124. values.Add(Math.Truncate(new TimeSpan(times[section.ID] / qty).TotalHours * 100.0F) / 100.0F);
  125. else
  126. values.Add(null);
  127. }
  128. if (qty > 0 && total > 0)
  129. values.Add(Math.Truncate(new TimeSpan(total / qty).TotalHours * 100.0F) / 100.0F);
  130. else
  131. values.Add(null);
  132. if (!_activeonly || qty > 0)
  133. data.Rows.Add(values.ToArray());
  134. }
  135. Progress.Close();
  136. }
  137. }
  138. public Dictionary<string, object[]> Selected()
  139. {
  140. return new Dictionary<string, object[]>();
  141. }
  142. public void Setup()
  143. {
  144. FromDate.SelectedDate = _from;
  145. ToDate.SelectedDate = _to;
  146. dataGrid.ScrollMode = ScrollMode.Async;
  147. sections = new Client<ManufacturingSection>().Load(
  148. new Filter<ManufacturingSection>(x => x.Hidden).IsEqualTo(false),
  149. new SortOrder<ManufacturingSection>(x => x.Factory.Sequence).ThenBy(x => x.Sequence)
  150. );
  151. stages = new Client<ManufacturingTemplateStage>().Load();
  152. data = new DataTable();
  153. data.Columns.Add("Code", typeof(string));
  154. data.Columns.Add("Description", typeof(string));
  155. data.Columns.Add("Qty", typeof(int));
  156. var columns = new Dictionary<string, List<string>>();
  157. foreach (var section in sections)
  158. {
  159. if (!columns.ContainsKey(section.Factory.Name))
  160. columns[section.Factory.Name] = new List<string>();
  161. var columnname = string.Format("{0}:{1}", section.Factory.Name, Regex.Replace(section.Name, "[^a-zA-Z0-9]", string.Empty));
  162. columns[section.Factory.Name].Add(columnname);
  163. data.Columns.Add(columnname, typeof(double));
  164. SectionDisplayNames[columnname] = section.Name;
  165. }
  166. data.Columns.Add("Total", typeof(double));
  167. dataGrid.ItemsSource = data;
  168. var stackedHeaderRow1 = new StackedHeaderRow();
  169. stackedHeaderRow1.StackedColumns.Add(new StackedColumn
  170. { ChildColumns = "Code,Description,Qty", HeaderText = "Template Details", MappingName = "TemplateDetails" });
  171. foreach (var key in columns.Keys)
  172. stackedHeaderRow1.StackedColumns.Add(new StackedColumn
  173. { ChildColumns = string.Join(",", columns[key]), HeaderText = key, MappingName = key });
  174. stackedHeaderRow1.StackedColumns.Add(new StackedColumn { ChildColumns = "Total", HeaderText = "", MappingName = "Total" });
  175. dataGrid.StackedHeaderRows.Add(stackedHeaderRow1);
  176. }
  177. public void Shutdown()
  178. {
  179. }
  180. public void Heartbeat(TimeSpan time)
  181. {
  182. }
  183. private void DataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e)
  184. {
  185. e.Column.TextAlignment = TextAlignment.Center;
  186. e.Column.HorizontalHeaderContentAlignment = HorizontalAlignment.Center;
  187. e.Column.ColumnSizer = GridLengthUnitType.None;
  188. var value = e.Column.ValueBinding as Binding;
  189. if (value.Path.Path.Equals("Code"))
  190. {
  191. e.Column.Width = 100;
  192. e.Column.HeaderStyle = Resources["TemplateHeaderStyle"] as Style;
  193. }
  194. else if (value.Path.Path.Equals("Description"))
  195. {
  196. e.Column.Width = 300;
  197. e.Column.HeaderStyle = Resources["TemplateHeaderStyle"] as Style;
  198. }
  199. else if (value.Path.Path.Equals("Qty"))
  200. {
  201. e.Column.Width = 60;
  202. e.Column.HeaderStyle = Resources["TemplateHeaderStyle"] as Style;
  203. }
  204. else
  205. {
  206. var style = new Style(typeof(GridCell));
  207. //style.Setters.Add(new Setter(GridCell.BackgroundProperty, new Binding(value.Path.Path) { Converter = new LeaveBackgroundConverter() { Colors = activityColors } }));
  208. //style.Setters.Add(new Setter(GridCell.ForegroundProperty, new Binding(value.Path.Path) { Converter = new LeaveForegroundConverter() }));
  209. //style.Setters.Add(new Setter(GridCell.FontStyleProperty, new Binding(value.Path.Path) { Converter = new LeaveFontStyleConverter() }));
  210. //style.Setters.Add(new Setter(GridCell.FontWeightProperty, new Binding(value.Path.Path) { Converter = new LeaveFontWeightConverter() }));
  211. e.Column.CellStyle = style;
  212. e.Column.Width = 50;
  213. e.Column.HeaderStyle = Resources["DataHeaderStyle"] as Style;
  214. e.Column.HeaderText = SectionDisplayNames[value.Path.Path];
  215. }
  216. }
  217. private void DataGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
  218. {
  219. }
  220. private void DataGrid_QueryRowHeight(object sender, QueryRowHeightEventArgs e)
  221. {
  222. e.Height = e.RowIndex == 1 ? 150 : 30;
  223. e.Handled = true;
  224. }
  225. private void ActiveItems_SelectionChanged(object sender, SelectionChangedEventArgs e)
  226. {
  227. if (IsReady && !_changing)
  228. {
  229. _activeonly = ActiveItems.SelectedIndex == 1;
  230. Refresh();
  231. }
  232. }
  233. private void Search_KeyUp(object sender, KeyEventArgs e)
  234. {
  235. if (string.IsNullOrWhiteSpace(Search.Text) || e.Key == Key.Return)
  236. {
  237. _search = Search.Text;
  238. Refresh();
  239. }
  240. }
  241. private void Export_Click(object sender, RoutedEventArgs e)
  242. {
  243. }
  244. private class GridCustomStackedRenderer : GridStackedHeaderCellRenderer
  245. {
  246. private readonly ResourceDictionary _resources;
  247. public GridCustomStackedRenderer(ResourceDictionary resources)
  248. {
  249. _resources = resources;
  250. }
  251. public override void OnInitializeEditElement(DataColumnBase dataColumn, GridStackedHeaderCellControl uiElement, object dataContext)
  252. {
  253. uiElement.Style = _resources["GroupHeaderStyle"] as Style;
  254. base.OnInitializeEditElement(dataColumn, uiElement, dataContext);
  255. }
  256. }
  257. #region Date Handling
  258. private bool _changing;
  259. public event DataModelUpdateEvent OnUpdateDataModel;
  260. private void SetDates(DateTime from, DateTime to, bool enable)
  261. {
  262. if (_changing)
  263. return;
  264. _changing = true;
  265. _from = from;
  266. FromDate.SelectedDate = from;
  267. FromDate.IsEnabled = enable;
  268. _to = to;
  269. ToDate.SelectedDate = to;
  270. ToDate.IsEnabled = enable;
  271. _changing = false;
  272. if (!enable)
  273. Refresh();
  274. }
  275. private int WeekDay(DateTime date)
  276. {
  277. if (date.DayOfWeek == DayOfWeek.Sunday)
  278. return 7;
  279. return (int)date.DayOfWeek - 1;
  280. }
  281. private void DateRange_SelectionChanged(object sender, SelectionChangedEventArgs e)
  282. {
  283. if (!IsReady)
  284. return;
  285. if (DateRange.SelectedIndex == 0) // Week To Date
  286. SetDates(DateTime.Today.AddDays(0 - WeekDay(DateTime.Today)), DateTime.Today, false);
  287. else if (DateRange.SelectedIndex == 1) // Last 7 Days
  288. SetDates(DateTime.Today.AddDays(-6), DateTime.Today, false);
  289. else if (DateRange.SelectedIndex == 2) // Month To Date
  290. SetDates(new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1), DateTime.Today, false);
  291. else if (DateRange.SelectedIndex == 3) // Last 30 days
  292. SetDates(DateTime.Today.AddDays(-29), DateTime.Today, false);
  293. else if (DateRange.SelectedIndex == 4) // Year To Date
  294. SetDates(new DateTime(DateTime.Today.Year, 1, 1), DateTime.Today, false);
  295. else if (DateRange.SelectedIndex == 5) // Last 12 Months
  296. SetDates(DateTime.Today.AddYears(-1).AddDays(1), DateTime.Today, false);
  297. else if (DateRange.SelectedIndex == 6) // Custom
  298. SetDates(FromDate.SelectedDate.Value, ToDate.SelectedDate.Value, true);
  299. }
  300. private void FromDate_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
  301. {
  302. if (IsReady && !_changing)
  303. {
  304. _from = FromDate.SelectedDate.Value.Date;
  305. Refresh();
  306. }
  307. }
  308. private void ToDate_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
  309. {
  310. if (IsReady && !_changing)
  311. {
  312. _to = ToDate.SelectedDate.Value.Date;
  313. Refresh();
  314. }
  315. }
  316. #endregion
  317. }
  318. }