using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Linq; using System.Text.RegularExpressions; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using Comal.Classes; using InABox.Clients; using InABox.Configuration; using InABox.Core; using InABox.WPF; using InABox.Wpf; using PRSDesktop.WidgetGroups; using Syncfusion.UI.Xaml.Grid; using Syncfusion.UI.Xaml.Grid.Cells; using SelectionChangedEventArgs = System.Windows.Controls.SelectionChangedEventArgs; using Columns = InABox.Core.Columns; namespace PRSDesktop { public class ManufacturingTemplateAnalysisProperties : IUserConfigurationSettings, IDashboardProperties { } public class ManufacturingTemplateAnalysisElement : DashboardElement { } /// /// Interaction logic for ManufacturingTemplateAnalysis.xaml /// public partial class ManufacturingTemplateAnalysis : UserControl, IPanel, IDashboardWidget { private bool _activeonly; private DateTime _from; private string _search = ""; private DateTime _to; private DataTable data; private readonly Dictionary SectionDisplayNames = new() { { "Total", "Total" } }; private ManufacturingSection[] sections; private Dictionary stages; private ManufacturingTemplate[] templates; public ManufacturingTemplateAnalysis() { _from = DateTime.Today.AddDays(0 - WeekDay(DateTime.Today)); _to = DateTime.Today; _activeonly = true; InitializeComponent(); dataGrid.CellRenderers.Remove("StackedHeader"); dataGrid.CellRenderers.Add("StackedHeader", new GridCustomStackedRenderer(Resources)); } public bool IsReady { get; set; } public void CreateToolbarButtons(IPanelHost host) { } public string SectionName => "Manufacturing Template Analysis"; public ManufacturingTemplateAnalysisProperties Properties { get; set; } public event LoadSettings? LoadSettings; public event SaveSettings? SaveSettings; public DataModel DataModel(Selection selection) { return new AutoDataModel(null); } public void Refresh() { Progress.ShowModal("Loading Data", (progress) => { data.Rows.Clear(); MultiQuery query = new MultiQuery(); query.Add( new Filter(x => x.ID).IsNotEqualTo(Guid.Empty).TextSearch(_search, x => x.Code, x => x.Name), Columns.None().Add(x => x.ID) .Add(x => x.Name) .Add(x => x.Code), new SortOrder(x => x.Code) ); query.Add( new Filter(x => x.Completed).IsGreaterThanOrEqualTo(_from).And(x => x.Completed).IsLessThan(_to.AddDays(1)), Columns.None().Add( x => x.ID, x => x.ManufacturingTemplateLink.ID, x => x.Quantity ) ); query.Add( new Filter(x => x.Packet.Completed).IsGreaterThanOrEqualTo(_from).And(x => x.Packet.Completed) .IsLessThan(_to.AddDays(1)), Columns.None().Add( x => x.Packet.ID, x => x.Section.ID, x => x.QADuration, x => x.WorkDuration ) ); query.Query(); templates = query.Get().ToObjects().ToArray(); var packets = query.Get().ToObjects(); ; var history = query.Get().ToObjects() .GroupBy(x => x.Packet.ID) .ToDictionary(x => x.Key, x => x.ToList()); foreach (var template in templates) { progress.Report(string.Format("Processing {0}: {1}", template.Code, template.Name)); var templateStageSections = (stages.GetValueOrDefault(template.ID) ?? Enumerable.Empty()) .Select(x => x.Section.ID).Where(x => sections.Any(y => x == y.ID)); var values = new List(); values.Add(template.Code); values.Add(template.Name); var times = new Dictionary(); foreach (var section in sections) times[section.ID] = 0L; var qty = 0; var pkts = packets.Where(p => p.ManufacturingTemplateLink.ID.Equals(template.ID)); foreach (var p in pkts) { var thisqty = p.Quantity; if (thisqty > 0) { qty += thisqty; if (history.TryGetValue(p.ID, out var histories)) { foreach (var section in templateStageSections) foreach (var hist in histories.Where(x => x.Section.ID == section)) times[section] += hist.QADuration.Ticks + hist.WorkDuration.Ticks; } } } if (qty > 0) values.Add(qty); else values.Add(null); var total = 0L; foreach (var section in sections) { total += times[section.ID]; if (qty > 0 && times[section.ID] > 0) values.Add(Math.Truncate(new TimeSpan(times[section.ID] / qty).TotalHours * 100.0F) / 100.0F); else values.Add(null); } if (qty > 0 && total > 0) values.Add(Math.Truncate(new TimeSpan(total / qty).TotalHours * 100.0F) / 100.0F); else values.Add(null); if (!_activeonly || qty > 0) data.Rows.Add(values.ToArray()); } }); } public Dictionary Selected() { return new Dictionary(); } public void Setup() { FromDate.SelectedDate = _from; ToDate.SelectedDate = _to; dataGrid.ScrollMode = ScrollMode.Async; sections = new Client().Load( new Filter(x => x.Hidden).IsEqualTo(false), new SortOrder(x => x.Factory.Sequence).ThenBy(x => x.Sequence) ); stages = new Client().Load().GroupBy(x => x.Template.ID).ToDictionary(x => x.Key, x => x.ToArray()); data = new DataTable(); data.Columns.Add("Code", typeof(string)); data.Columns.Add("Description", typeof(string)); data.Columns.Add("Qty", typeof(int)); var columns = new Dictionary>(); foreach (var section in sections) { if (!columns.ContainsKey(section.Factory.Name)) columns[section.Factory.Name] = new List(); var columnname = string.Format("{0}:{1}", section.Factory.Name, Regex.Replace(section.Name, "[^a-zA-Z0-9]", "")); columns[section.Factory.Name].Add(columnname); data.Columns.Add(columnname, typeof(double)); SectionDisplayNames[columnname] = section.Name; } data.Columns.Add("Total", typeof(double)); dataGrid.ItemsSource = data; var stackedHeaderRow1 = new StackedHeaderRow(); stackedHeaderRow1.StackedColumns.Add(new StackedColumn { ChildColumns = "Code,Description,Qty", HeaderText = "Template Details", MappingName = "TemplateDetails" }); foreach (var key in columns.Keys) stackedHeaderRow1.StackedColumns.Add(new StackedColumn { ChildColumns = string.Join(",", columns[key]), HeaderText = key, MappingName = key }); stackedHeaderRow1.StackedColumns.Add(new StackedColumn { ChildColumns = "Total", HeaderText = "", MappingName = "Total" }); dataGrid.StackedHeaderRows.Add(stackedHeaderRow1); } public void Shutdown(CancelEventArgs? cancel) { } public void Heartbeat(TimeSpan time) { } private void DataGrid_AutoGeneratingColumn(object sender, AutoGeneratingColumnArgs e) { e.Column.TextAlignment = TextAlignment.Center; e.Column.HorizontalHeaderContentAlignment = HorizontalAlignment.Center; e.Column.ColumnSizer = GridLengthUnitType.None; var value = e.Column.ValueBinding as Binding; if (value.Path.Path.Equals("Code")) { e.Column.Width = 100; e.Column.HeaderStyle = Application.Current.Resources["TemplateHeaderStyle"] as Style; } else if (value.Path.Path.Equals("Description")) { e.Column.Width = 300; e.Column.HeaderStyle = Application.Current.Resources["TemplateHeaderStyle"] as Style; } else if (value.Path.Path.Equals("Qty")) { e.Column.Width = 60; e.Column.HeaderStyle = Application.Current.Resources["TemplateHeaderStyle"] as Style; } else { var style = new Style(typeof(GridCell)); //style.Setters.Add(new Setter(GridCell.BackgroundProperty, new Binding(value.Path.Path) { Converter = new LeaveBackgroundConverter() { Colors = activityColors } })); //style.Setters.Add(new Setter(GridCell.ForegroundProperty, new Binding(value.Path.Path) { Converter = new LeaveForegroundConverter() })); //style.Setters.Add(new Setter(GridCell.FontStyleProperty, new Binding(value.Path.Path) { Converter = new LeaveFontStyleConverter() })); //style.Setters.Add(new Setter(GridCell.FontWeightProperty, new Binding(value.Path.Path) { Converter = new LeaveFontWeightConverter() })); e.Column.CellStyle = style; e.Column.Width = 50; e.Column.HeaderStyle = Application.Current.Resources["TemplateHeaderStyle"] as Style; // e.Column.HeaderStyle = Resources["DataHeaderStyle"] as Style; e.Column.HeaderText = SectionDisplayNames[value.Path.Path]; } } private void DataGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e) { } private void DataGrid_QueryRowHeight(object sender, QueryRowHeightEventArgs e) { e.Height = e.RowIndex == 1 ? 150 : 30; e.Handled = true; } private void ActiveItems_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (IsReady && !_changing) { _activeonly = ActiveItems.SelectedIndex == 1; Refresh(); } } private void Search_KeyUp(object sender, KeyEventArgs e) { if (string.IsNullOrWhiteSpace(Search.Text) || e.Key == Key.Return) { _search = Search.Text; Refresh(); } } private void Export_Click(object sender, RoutedEventArgs e) { } private class GridCustomStackedRenderer : GridStackedHeaderCellRenderer { private readonly ResourceDictionary _resources; public GridCustomStackedRenderer(ResourceDictionary resources) { _resources = resources; } public override void OnInitializeEditElement(DataColumnBase dataColumn, GridStackedHeaderCellControl uiElement, object dataContext) { uiElement.Style = _resources["GroupHeaderStyle"] as Style; base.OnInitializeEditElement(dataColumn, uiElement, dataContext); } } #region Date Handling private bool _changing; public event DataModelUpdateEvent? OnUpdateDataModel; private void SetDates(DateTime from, DateTime to, bool enable) { if (_changing) return; _changing = true; _from = from; FromDate.SelectedDate = from; FromDate.IsEnabled = enable; _to = to; ToDate.SelectedDate = to; ToDate.IsEnabled = enable; _changing = false; if (!enable) Refresh(); } private int WeekDay(DateTime date) { if (date.DayOfWeek == DayOfWeek.Sunday) return 7; return (int)date.DayOfWeek - 1; } private void DateRange_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (!IsReady) return; if (DateRange.SelectedIndex == 0) // Week To Date SetDates(DateTime.Today.AddDays(0 - WeekDay(DateTime.Today)), DateTime.Today, false); else if (DateRange.SelectedIndex == 1) // Last 7 Days SetDates(DateTime.Today.AddDays(-6), DateTime.Today, false); else if (DateRange.SelectedIndex == 2) // Month To Date SetDates(new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1), DateTime.Today, false); else if (DateRange.SelectedIndex == 3) // Last 30 days SetDates(DateTime.Today.AddDays(-29), DateTime.Today, false); else if (DateRange.SelectedIndex == 4) // Year To Date SetDates(new DateTime(DateTime.Today.Year, 1, 1), DateTime.Today, false); else if (DateRange.SelectedIndex == 5) // Last 12 Months SetDates(DateTime.Today.AddYears(-1).AddDays(1), DateTime.Today, false); else if (DateRange.SelectedIndex == 6) // Custom SetDates(FromDate.SelectedDate.Value, ToDate.SelectedDate.Value, true); } private void FromDate_SelectedDateChanged(object sender, SelectionChangedEventArgs e) { if (IsReady && !_changing) { _from = FromDate.SelectedDate.Value.Date; Refresh(); } } private void ToDate_SelectedDateChanged(object sender, SelectionChangedEventArgs e) { if (IsReady && !_changing) { _to = ToDate.SelectedDate.Value.Date; Refresh(); } } #endregion } }