|
@@ -38,6 +38,31 @@ namespace PRSDesktop.Dashboards.Manufacturing
|
|
|
Name = name;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ public class JobModel
|
|
|
+ {
|
|
|
+ public string JobNumber { get; set; }
|
|
|
+
|
|
|
+ public string Name { get; set; }
|
|
|
+
|
|
|
+ public Guid ID { get; set; }
|
|
|
+
|
|
|
+ public double NHours { get; set; }
|
|
|
+
|
|
|
+ public int NPackets { get; set; }
|
|
|
+
|
|
|
+ public Visibility HoursVisibility;
|
|
|
+
|
|
|
+ public JobModel(string jobNumber, string name, Guid ID, double nHours, int nPackets)
|
|
|
+ {
|
|
|
+ JobNumber = jobNumber;
|
|
|
+ Name = name;
|
|
|
+ this.ID = ID;
|
|
|
+ NHours = nHours;
|
|
|
+ NPackets = nPackets;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public class CardModel
|
|
|
{
|
|
|
private bool _empty;
|
|
@@ -49,6 +74,7 @@ namespace PRSDesktop.Dashboards.Manufacturing
|
|
|
get => _empty || NPackets == 0;
|
|
|
set => _empty = value;
|
|
|
}
|
|
|
+ public Visibility HoursVisibility;
|
|
|
|
|
|
public CardModel(int nPackets, int nHours)
|
|
|
{
|
|
@@ -68,6 +94,10 @@ namespace PRSDesktop.Dashboards.Manufacturing
|
|
|
public class JobManufacturingSummaryProperties : UserConfigurationSettings, IDashboardProperties
|
|
|
{
|
|
|
public Guid JobStatus;
|
|
|
+
|
|
|
+ public bool ShowEmptyJobs;
|
|
|
+
|
|
|
+ public bool IncludeTimeRemaining;
|
|
|
}
|
|
|
|
|
|
public class JobManufacturingSummaryElement : DashboardElement<JobManufacturingSummary, WidgetGroups.Manufacturing, JobManufacturingSummaryProperties>
|
|
@@ -185,7 +215,47 @@ namespace PRSDesktop.Dashboards.Manufacturing
|
|
|
: null) ?? statuses.FirstOrDefault(x => x.Default) ?? statuses.FirstOrDefault();
|
|
|
JobStatusBox.SelectionChanged += StatusBox_SelectionChanged;
|
|
|
|
|
|
- Header.Add(JobStatusBox);
|
|
|
+ var showEmptyJobsLabel = new Label { Content = "Show Empty Jobs?" };
|
|
|
+ var emptyJobsCheckBox = new CheckBox
|
|
|
+ {
|
|
|
+ IsChecked = Properties.ShowEmptyJobs,
|
|
|
+ VerticalAlignment = VerticalAlignment.Center
|
|
|
+ };
|
|
|
+ emptyJobsCheckBox.Checked += EmptyJobsCheckBox_Checked;
|
|
|
+ emptyJobsCheckBox.Unchecked += EmptyJobsCheckBox_Checked;
|
|
|
+
|
|
|
+ var includeRemainingLabel = new Label { Content = "Include Remaining Time?" };
|
|
|
+ var includeRemainingCheckBox = new CheckBox
|
|
|
+ {
|
|
|
+ IsChecked = Properties.IncludeTimeRemaining,
|
|
|
+ VerticalAlignment = VerticalAlignment.Center
|
|
|
+ };
|
|
|
+ includeRemainingCheckBox.Checked += IncludeRemainingCheckBox_Checked;
|
|
|
+ includeRemainingCheckBox.Unchecked += IncludeRemainingCheckBox_Checked;
|
|
|
+
|
|
|
+ Header.Add(JobStatusBox)
|
|
|
+ .Add(showEmptyJobsLabel)
|
|
|
+ .Add(emptyJobsCheckBox)
|
|
|
+ .Add(includeRemainingLabel)
|
|
|
+ .Add(includeRemainingCheckBox);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void IncludeRemainingCheckBox_Checked(object sender, RoutedEventArgs e)
|
|
|
+ {
|
|
|
+ if (sender is not CheckBox checkBox) return;
|
|
|
+
|
|
|
+ Properties.IncludeTimeRemaining = checkBox.IsChecked == true;
|
|
|
+
|
|
|
+ Refresh();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void EmptyJobsCheckBox_Checked(object sender, RoutedEventArgs e)
|
|
|
+ {
|
|
|
+ if (sender is not CheckBox checkBox) return;
|
|
|
+
|
|
|
+ Properties.ShowEmptyJobs = checkBox.IsChecked == true;
|
|
|
+
|
|
|
+ Refresh();
|
|
|
}
|
|
|
|
|
|
private void RefreshJobs()
|
|
@@ -287,7 +357,10 @@ namespace PRSDesktop.Dashboards.Manufacturing
|
|
|
.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) =>
|
|
|
+ .ToDictionary(x => x.Key, x => x.Aggregate(new CardModel(0, 0)
|
|
|
+ {
|
|
|
+ HoursVisibility = Properties.IncludeTimeRemaining ? Visibility.Visible : Visibility.Collapsed
|
|
|
+ }, (c, p) =>
|
|
|
{
|
|
|
c.NHours += p.TimeRemaining.TotalHours;
|
|
|
++c.NPackets;
|
|
@@ -314,6 +387,8 @@ namespace PRSDesktop.Dashboards.Manufacturing
|
|
|
|
|
|
public void Refresh()
|
|
|
{
|
|
|
+ using var profiler = new Profiler(true);
|
|
|
+
|
|
|
Data.Rows.Clear();
|
|
|
var rows = new Dictionary<Guid, DataRow>();
|
|
|
foreach (var job in Jobs)
|
|
@@ -324,6 +399,19 @@ namespace PRSDesktop.Dashboards.Manufacturing
|
|
|
rows[job.ID] = row;
|
|
|
}
|
|
|
|
|
|
+ var sectionColumns = new Columns<ManufacturingPacket>(x => x.ID)
|
|
|
+ .Add(x => x.SetoutLink.JobLink.ID)
|
|
|
+ .Add(x => x.StageLink.SectionID);
|
|
|
+ var factoryColumns = new Columns<ManufacturingPacket>(x => x.ID)
|
|
|
+ .Add(x => x.SetoutLink.JobLink.ID)
|
|
|
+ .Add(x => x.ManufacturingTemplateLink.Factory.ID);
|
|
|
+ if (Properties.IncludeTimeRemaining)
|
|
|
+ {
|
|
|
+ sectionColumns.Add(x => x.TimeRemaining);
|
|
|
+ factoryColumns.Add(x => x.TimeRemaining);
|
|
|
+ }
|
|
|
+
|
|
|
+ profiler.Log("Setup");
|
|
|
LoadPackets(
|
|
|
new Client<ManufacturingPacket>()
|
|
|
.Query(
|
|
@@ -331,14 +419,12 @@ namespace PRSDesktop.Dashboards.Manufacturing
|
|
|
.And(x => x.StageLink.SectionID).IsNotEqualTo(Guid.Empty)
|
|
|
.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))
|
|
|
+ sectionColumns)
|
|
|
.ToObjects<ManufacturingPacket>()
|
|
|
.GroupBy(x => x.StageLink.SectionID),
|
|
|
SectionColumns,
|
|
|
rows);
|
|
|
+ profiler.Log("Section");
|
|
|
LoadPackets(
|
|
|
new Client<ManufacturingPacket>()
|
|
|
.Query(
|
|
@@ -346,14 +432,54 @@ namespace PRSDesktop.Dashboards.Manufacturing
|
|
|
.And(x => x.StageLink.SectionID).IsEqualTo(Guid.Empty)
|
|
|
.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.TimeRemaining)
|
|
|
- .Add(x => x.ManufacturingTemplateLink.Factory.ID))
|
|
|
+ factoryColumns)
|
|
|
.ToObjects<ManufacturingPacket>()
|
|
|
.GroupBy(x => x.ManufacturingTemplateLink.Factory.ID),
|
|
|
FactoryColumns,
|
|
|
rows);
|
|
|
+ profiler.Log("Factory");
|
|
|
+
|
|
|
+ var removes = new List<Guid>();
|
|
|
+ foreach(var (jobID, row) in rows)
|
|
|
+ {
|
|
|
+ var any = false;
|
|
|
+
|
|
|
+ var nHours = 0.0;
|
|
|
+ var nPackets = 0;
|
|
|
+ foreach (var (id, column) in FactoryColumns.Concat(SectionColumns))
|
|
|
+ {
|
|
|
+ if (row[column.ColumnName] is CardModel model && !model.Empty)
|
|
|
+ {
|
|
|
+ any = true;
|
|
|
+ nHours += model.NHours;
|
|
|
+ nPackets += model.NPackets;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!any)
|
|
|
+ {
|
|
|
+ removes.Add(jobID);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if(row["Job"] is Job job)
|
|
|
+ {
|
|
|
+ row["Job"] = new JobModel(job.JobNumber, job.Name, job.ID, nHours, nPackets)
|
|
|
+ {
|
|
|
+ HoursVisibility = Properties.IncludeTimeRemaining ? Visibility.Visible : Visibility.Collapsed,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!Properties.ShowEmptyJobs)
|
|
|
+ {
|
|
|
+ foreach(var remove in removes)
|
|
|
+ {
|
|
|
+ if(rows.Remove(remove, out var row))
|
|
|
+ {
|
|
|
+ Data.Rows.Remove(row);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
var totals = new Dictionary<Guid, ManufacturingTotal>();
|
|
|
foreach(var column in Data.Columns)
|
|
@@ -389,7 +515,14 @@ namespace PRSDesktop.Dashboards.Manufacturing
|
|
|
foreach(var (factoryID, total) in totals)
|
|
|
{
|
|
|
var header = FactoryColumnHeaders[factoryID];
|
|
|
- header.HeaderText = $"Packets: {total.NPackets}, Hours: {total.NHours:f2}";
|
|
|
+ if (Properties.IncludeTimeRemaining)
|
|
|
+ {
|
|
|
+ header.HeaderText = $"Packets: {total.NPackets}, Hours: {total.NHours:f2}";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ header.HeaderText = $"Packets: {total.NPackets}";
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
DataGrid.ItemsSource = Data;
|