|
|
@@ -0,0 +1,269 @@
|
|
|
+using Comal.Classes;
|
|
|
+using InABox.Clients;
|
|
|
+using InABox.Core;
|
|
|
+using javax.smartcardio;
|
|
|
+using PRSDesktop.WidgetGroups;
|
|
|
+using Syncfusion.UI.Xaml.Grid;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Data;
|
|
|
+using System.Linq;
|
|
|
+using System.Runtime.CompilerServices;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using System.Windows;
|
|
|
+using System.Windows.Controls;
|
|
|
+using System.Windows.Data;
|
|
|
+using System.Windows.Documents;
|
|
|
+using System.Windows.Input;
|
|
|
+using System.Windows.Media;
|
|
|
+using System.Windows.Media.Imaging;
|
|
|
+using System.Windows.Navigation;
|
|
|
+using System.Windows.Shapes;
|
|
|
+using DataRow = System.Data.DataRow;
|
|
|
+
|
|
|
+namespace PRSDesktop.Dashboards.Manufacturing
|
|
|
+{
|
|
|
+ public class HeaderModel
|
|
|
+ {
|
|
|
+ public string Name { get; set; }
|
|
|
+
|
|
|
+ public HeaderModel(string name)
|
|
|
+ {
|
|
|
+ Name = name;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public class CardModel
|
|
|
+ {
|
|
|
+ private bool _empty;
|
|
|
+
|
|
|
+ public int NPackets { get; set; }
|
|
|
+ public double NHours { get; set; }
|
|
|
+ public bool Empty
|
|
|
+ {
|
|
|
+ get => _empty || NPackets == 0;
|
|
|
+ set => _empty = value;
|
|
|
+ }
|
|
|
+
|
|
|
+ public CardModel(int nPackets, int nHours)
|
|
|
+ {
|
|
|
+ NPackets = nPackets;
|
|
|
+ NHours = nHours;
|
|
|
+ Empty = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public CardModel()
|
|
|
+ {
|
|
|
+ NPackets = 0;
|
|
|
+ NHours = 0.0;
|
|
|
+ Empty = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public class JobManufacturingSummaryProperties : IDashboardProperties
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public class JobManufacturingSummaryElement : DashboardElement<JobManufacturingSummary, WidgetGroups.Manufacturing, JobManufacturingSummaryProperties>
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Interaction logic for JobManufacturingSummary.xaml
|
|
|
+ /// </summary>
|
|
|
+ public partial class JobManufacturingSummary : UserControl, IDashboardWidget<WidgetGroups.Manufacturing, JobManufacturingSummaryProperties>
|
|
|
+ {
|
|
|
+ private class SectionColumn
|
|
|
+ {
|
|
|
+ public string ColumnName { get; set; }
|
|
|
+ public string DisplayName { get; set; }
|
|
|
+
|
|
|
+ public SolidColorBrush Background { get; set; }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private readonly Dictionary<Guid, SectionColumn> SectionColumns = new();
|
|
|
+ private List<Job> Jobs { get; set; } = new();
|
|
|
+ private List<ManufacturingFactory> Factories { get; set; } = new();
|
|
|
+ private Dictionary<Guid, List<ManufacturingSection>> Sections { get; set; } = new();
|
|
|
+ private List<FrameworkElement> Cards { get; set; } = new();
|
|
|
+ private DataTable Data { get; set; }
|
|
|
+
|
|
|
+ public JobManufacturingSummary()
|
|
|
+ {
|
|
|
+ InitializeComponent();
|
|
|
+ }
|
|
|
+
|
|
|
+ public JobManufacturingSummaryProperties Properties { get; set; }
|
|
|
+
|
|
|
+ public void Setup()
|
|
|
+ {
|
|
|
+ Jobs = new Client<Job>()
|
|
|
+ .Query(
|
|
|
+ LookupFactory.DefineFilter<Job>(),
|
|
|
+ new Columns<Job>(x => x.ID)
|
|
|
+ .Add(x => x.JobNumber)
|
|
|
+ .Add(x => x.Name)
|
|
|
+ .Add(x => x.Color))
|
|
|
+ .ToList<Job>();
|
|
|
+
|
|
|
+ Factories = new Client<ManufacturingFactory>()
|
|
|
+ .Query(null, new Columns<ManufacturingFactory>(x => x.ID).Add(x => x.Name), new SortOrder<ManufacturingFactory>(x => x.Sequence))
|
|
|
+ .ToList<ManufacturingFactory>();
|
|
|
+
|
|
|
+ Sections = new Client<ManufacturingSection>()
|
|
|
+ .Query(
|
|
|
+ new Filter<ManufacturingSection>(x => x.Hidden).IsEqualTo(false),
|
|
|
+ new Columns<ManufacturingSection>(x => x.ID)
|
|
|
+ .Add(x => x.Factory.ID)
|
|
|
+ .Add(x => x.Name),
|
|
|
+ new SortOrder<ManufacturingSection>(x => x.Sequence))
|
|
|
+ .ToObjects<ManufacturingSection>()
|
|
|
+ .GroupBy(x => x.Factory.ID).ToDictionary(x => x.Key, x => x.ToList());
|
|
|
+
|
|
|
+ SetupGrid();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void SetupGrid()
|
|
|
+ {
|
|
|
+ DataGrid.HeaderTemplate = Resources["HeaderTemplate"] as DataTemplate;
|
|
|
+
|
|
|
+ Data = new DataTable();
|
|
|
+
|
|
|
+ Data.Columns.Add("Job", typeof(object));
|
|
|
+
|
|
|
+ var stackedHeaderRow = new StackedHeaderRow();
|
|
|
+ var factoryIdx = 0;
|
|
|
+ foreach (var factory in Factories)
|
|
|
+ {
|
|
|
+ if (!Sections.TryGetValue(factory.ID, out var sections)) continue;
|
|
|
+
|
|
|
+ foreach (var section in sections)
|
|
|
+ {
|
|
|
+ var columnName = section.ID.ToString();
|
|
|
+ SectionColumns.Add(section.ID, new SectionColumn
|
|
|
+ {
|
|
|
+ ColumnName = columnName,
|
|
|
+ DisplayName = section.Name,
|
|
|
+ Background = factoryIdx % 2 == 0 ? new SolidColorBrush(Colors.WhiteSmoke) : new SolidColorBrush(Colors.LightGray)
|
|
|
+ });
|
|
|
+ Data.Columns.Add(columnName, typeof(object));
|
|
|
+ }
|
|
|
+ stackedHeaderRow.StackedColumns.Add(new StackedColumn
|
|
|
+ {
|
|
|
+ ChildColumns = string.Join(',', sections.Select(x => x.ID)),
|
|
|
+ HeaderText = factory.Name
|
|
|
+ });
|
|
|
+ ++factoryIdx;
|
|
|
+ }
|
|
|
+ DataGrid.StackedHeaderRows.Add(stackedHeaderRow);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void SetPosition(FrameworkElement element, int row, int rowSpan, int column, int columnSpan)
|
|
|
+ {
|
|
|
+ element.SetValue(Grid.RowProperty, row);
|
|
|
+ element.SetValue(Grid.RowSpanProperty, rowSpan);
|
|
|
+ element.SetValue(Grid.ColumnProperty, column);
|
|
|
+ element.SetValue(Grid.ColumnSpanProperty, columnSpan);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Refresh()
|
|
|
+ {
|
|
|
+ Data.Rows.Clear();
|
|
|
+
|
|
|
+ var packets = new Client<ManufacturingPacket>()
|
|
|
+ .Query(
|
|
|
+ new Filter<ManufacturingPacket>(x => x.Archived).IsEqualTo(DateTime.MinValue)
|
|
|
+ .And(x => x.Completed).IsEqualTo(DateTime.MinValue)
|
|
|
+ .And(x => x.SetoutLink.JobLink.ID).InList(Jobs.Select(x => x.ID).ToArray()),
|
|
|
+ new Columns<ManufacturingPacket>(x => x.ID)
|
|
|
+ .Add(x => x.SetoutLink.JobLink.ID)
|
|
|
+ .Add(x => x.StageLink.SectionID)
|
|
|
+ .Add(x => x.TimeRemaining))
|
|
|
+ .ToObjects<ManufacturingPacket>()
|
|
|
+ .GroupBy(x => x.StageLink.SectionID)
|
|
|
+ .ToDictionary(
|
|
|
+ x => x.Key,
|
|
|
+ x => x.GroupBy(x => x.SetoutLink.JobLink.ID)
|
|
|
+ .ToDictionary(x => x.Key, x => x.Aggregate(new CardModel(0, 0), (c, p) =>
|
|
|
+ {
|
|
|
+ c.NHours += p.TimeRemaining.TotalHours;
|
|
|
+ ++c.NPackets;
|
|
|
+ return c;
|
|
|
+ })));
|
|
|
+
|
|
|
+ var rows = new Dictionary<Guid, DataRow>();
|
|
|
+ foreach (var job in Jobs)
|
|
|
+ {
|
|
|
+ var row = Data.NewRow();
|
|
|
+ Data.Rows.Add(row);
|
|
|
+ row["Job"] = job;
|
|
|
+ rows[job.ID] = row;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var (sectionID, column) in SectionColumns)
|
|
|
+ {
|
|
|
+ var sectionPackets = packets.GetValueOrDefault(sectionID);
|
|
|
+ foreach (var job in Jobs)
|
|
|
+ {
|
|
|
+ if (!rows.TryGetValue(job.ID, out var row))
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sectionPackets is null || !sectionPackets.TryGetValue(job.ID, out var model))
|
|
|
+ {
|
|
|
+ model = new CardModel();
|
|
|
+ }
|
|
|
+ row[column.ColumnName] = model;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ DataGrid.ItemsSource = Data;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Shutdown()
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ private void DataGrid_AutoGeneratingColumn(object sender, Syncfusion.UI.Xaml.Grid.AutoGeneratingColumnArgs e)
|
|
|
+ {
|
|
|
+ if(Guid.TryParse(e.Column.MappingName, out var id))
|
|
|
+ {
|
|
|
+ var column = SectionColumns[id];
|
|
|
+ var style = new Style();
|
|
|
+ style.Setters.Add(new Setter(GridCell.BackgroundProperty, column.Background));
|
|
|
+
|
|
|
+ e.Column = new GridTemplateColumn
|
|
|
+ {
|
|
|
+ HeaderText = column.DisplayName,
|
|
|
+ CellStyle = style,
|
|
|
+ MappingName = e.Column.MappingName,
|
|
|
+ CellTemplate = Resources["CardTemplate"] as DataTemplate,
|
|
|
+ SetCellBoundValue = true,
|
|
|
+ ColumnSizer = GridLengthUnitType.Auto
|
|
|
+ };
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ e.Column = new GridTemplateColumn
|
|
|
+ {
|
|
|
+ CellTemplate = Resources["JobHeaderTemplate"] as DataTemplate,
|
|
|
+ HeaderText = e.Column.HeaderText,
|
|
|
+ MappingName = e.Column.MappingName,
|
|
|
+ SetCellBoundValue = true,
|
|
|
+ ColumnSizer = GridLengthUnitType.Auto
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void DataGrid_QueryRowHeight(object sender, QueryRowHeightEventArgs e)
|
|
|
+ {
|
|
|
+ if(DataGrid.GridColumnSizer.GetAutoRowHeight(e.RowIndex, new GridRowSizingOptions(), out var height))
|
|
|
+ {
|
|
|
+ e.Height = height;
|
|
|
+ e.Handled = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|