diff --git a/ReportingServices.API/Controllers/ScrapeDBController.cs b/ReportingServices.API/Controllers/ScrapeDBController.cs index e748e23..7495d43 100644 --- a/ReportingServices.API/Controllers/ScrapeDBController.cs +++ b/ReportingServices.API/Controllers/ScrapeDBController.cs @@ -1,8 +1,8 @@ -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; using ReportingServices.Shared.Models.PlanningReport; using ReportingServices.Shared.Models.ProductionReport; using ReportingServices.Shared.Repositories; +using ReportingServices.Shared.ViewModels.ProductionReport; namespace ReportingServices.API.Controllers { @@ -17,6 +17,19 @@ namespace ReportingServices.API.Controllers _scrapeDBRepository = scrapeDBRepository; } + [HttpGet("ReactorOuts")] + public YieldInformation GetReactorOuts(string startDate, string endDate) + { + List outs = _scrapeDBRepository.GetRDSRunBetweenDates(startDate, endDate); + YieldInformation yieldInformation = new() + { + Outs = outs, + Scrap = _scrapeDBRepository.GetScrapByDay(outs) + }; + + return yieldInformation; + } + [HttpGet("PSNWO")] public List GetReactorPSNWORuns(string startDate, string endDate) { @@ -46,5 +59,17 @@ namespace ReportingServices.API.Controllers { return _scrapeDBRepository.GetRDSForLastDay(date); } + + [HttpGet("ReactorEvents")] + public List GetReactorEvents(string startDate, string endDate, string reactorNumber) + { + return _scrapeDBRepository.GetReactorEvents(startDate, endDate, reactorNumber); + } + + [HttpGet("ToolEvents")] + public ToolEvent GetLatestToolEvent(string toolID) + { + return _scrapeDBRepository.GetLatestToolEvent(toolID); + } } } diff --git a/ReportingServices.Desktop/DailyReport.Designer.cs b/ReportingServices.Desktop/DailyReport.Designer.cs new file mode 100644 index 0000000..6ff5541 --- /dev/null +++ b/ReportingServices.Desktop/DailyReport.Designer.cs @@ -0,0 +1,137 @@ +namespace ReportingServices.Desktop +{ + partial class DailyReport + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.btnPrevious = new System.Windows.Forms.Button(); + this.btnNext = new System.Windows.Forms.Button(); + this.dgvCurrentWeek = new System.Windows.Forms.DataGridView(); + this.rtbManualEntries = new System.Windows.Forms.RichTextBox(); + this.dgvPreviousWeek = new System.Windows.Forms.DataGridView(); + ((System.ComponentModel.ISupportInitialize)(this.dgvCurrentWeek)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.dgvPreviousWeek)).BeginInit(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Segoe UI", 20F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + this.label1.Location = new System.Drawing.Point(786, 5); + this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(271, 37); + this.label1.TabIndex = 0; + this.label1.Text = "Production Passdown"; + // + // btnPrevious + // + this.btnPrevious.Location = new System.Drawing.Point(64, 37); + this.btnPrevious.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.btnPrevious.Name = "btnPrevious"; + this.btnPrevious.Size = new System.Drawing.Size(179, 56); + this.btnPrevious.TabIndex = 1; + this.btnPrevious.Text = "Previous Button"; + this.btnPrevious.UseVisualStyleBackColor = true; + this.btnPrevious.Click += new System.EventHandler(this.btnPrevious_Click); + // + // btnNext + // + this.btnNext.Location = new System.Drawing.Point(1651, 37); + this.btnNext.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.btnNext.Name = "btnNext"; + this.btnNext.Size = new System.Drawing.Size(179, 56); + this.btnNext.TabIndex = 2; + this.btnNext.Text = "Next Button"; + this.btnNext.UseVisualStyleBackColor = true; + this.btnNext.Visible = false; + this.btnNext.Click += new System.EventHandler(this.btnNext_Click); + // + // dgvCurrentWeek + // + this.dgvCurrentWeek.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dgvCurrentWeek.Location = new System.Drawing.Point(64, 119); + this.dgvCurrentWeek.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.dgvCurrentWeek.Name = "dgvCurrentWeek"; + this.dgvCurrentWeek.RowHeadersWidth = 62; + this.dgvCurrentWeek.RowTemplate.Height = 33; + this.dgvCurrentWeek.Size = new System.Drawing.Size(1765, 378); + this.dgvCurrentWeek.TabIndex = 3; + // + // rtbManualEntries + // + this.rtbManualEntries.Location = new System.Drawing.Point(64, 527); + this.rtbManualEntries.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.rtbManualEntries.Name = "rtbManualEntries"; + this.rtbManualEntries.Size = new System.Drawing.Size(576, 395); + this.rtbManualEntries.TabIndex = 4; + this.rtbManualEntries.Text = ""; + // + // dgvPreviousWeek + // + this.dgvPreviousWeek.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dgvPreviousWeek.Location = new System.Drawing.Point(64, 119); + this.dgvPreviousWeek.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.dgvPreviousWeek.Name = "dgvPreviousWeek"; + this.dgvPreviousWeek.RowHeadersWidth = 62; + this.dgvPreviousWeek.RowTemplate.Height = 33; + this.dgvPreviousWeek.Size = new System.Drawing.Size(1765, 378); + this.dgvPreviousWeek.TabIndex = 5; + this.dgvPreviousWeek.Visible = false; + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1925, 853); + this.Controls.Add(this.dgvPreviousWeek); + this.Controls.Add(this.rtbManualEntries); + this.Controls.Add(this.dgvCurrentWeek); + this.Controls.Add(this.btnNext); + this.Controls.Add(this.btnPrevious); + this.Controls.Add(this.label1); + this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.Name = "Form1"; + this.Text = "Form1"; + ((System.ComponentModel.ISupportInitialize)(this.dgvCurrentWeek)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.dgvPreviousWeek)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private Label label1; + private Button btnPrevious; + private Button btnNext; + private DataGridView dgvCurrentWeek; + private RichTextBox rtbManualEntries; + private DataGridView dgvPreviousWeek; + } +} \ No newline at end of file diff --git a/ReportingServices.Desktop/DailyReport.cs b/ReportingServices.Desktop/DailyReport.cs new file mode 100644 index 0000000..cdf16ff --- /dev/null +++ b/ReportingServices.Desktop/DailyReport.cs @@ -0,0 +1,344 @@ +using Microsoft.Extensions.Logging; +using ReportingServices.Shared.HelperClasses; +using ReportingServices.Shared.ViewModels.ProductionReport; +using System.Data; +using System.Reflection; + +namespace ReportingServices.Desktop +{ + public partial class DailyReport : Form + { + + private DataTable currentWeek = new(); + private DataTable previousWeek = new(); + + private readonly ILogger _logger; + private readonly string _dailyRptFilePath = "wwwroot/Assets/DailyReportInfo.json"; + private readonly string _toolStateOwnerFilePath = "wwwroot/Assets/ToolStates.json"; + private readonly string _baseFTUrl; + private readonly string _baseDBUrl; + + public DailyReport(ILogger logger) + { + _logger = logger; + _baseFTUrl = "http://mestsa008:50201/api/"; + _baseDBUrl = "https://localhost:7196/api/"; + + _logger.LogInformation("Base FabTime Address: {baseUrl}", _baseFTUrl); + _logger.LogInformation("Base Database Address: {baseUrl}", _baseDBUrl); + + InitializeComponent(); + + string baseFabTimeUrl = _baseFTUrl + "FabTime/"; + string baseScrapeDbUrl = _baseDBUrl + "ScrapeDB/"; + + try + { + Shared.ViewModels.ProductionReport.DailyReport dailyReport = DailyReportHelper.SetUpDailyReport(_logger, baseFabTimeUrl, baseScrapeDbUrl); + Dictionary> toolStateOwners = JsonFileHandler.LoadJSONFile>>(_toolStateOwnerFilePath); + + dailyReport.ToolStatesByOwner = toolStateOwners; + + SetupWeekView(dailyReport.CurrentWeek, currentWeek); + SetupWeekView(dailyReport.PreviousWeek, previousWeek); + + dgvCurrentWeek.DataSource = currentWeek; + dgvPreviousWeek.DataSource = previousWeek; + } + catch (Exception ex) + { + _logger.LogCritical(ex, "Failed to load report"); + } + } + + public void SetupWeekView(YieldStatistics rpt, DataTable dt) + { + dt.Columns.Add("SIOperations"); + dt.Columns.Add("Monday"); + dt.Columns.Add("Tuesday"); + dt.Columns.Add("Wednesday"); + dt.Columns.Add("Thursday"); + dt.Columns.Add("Friday"); + dt.Columns.Add("Saturday"); + dt.Columns.Add("Sunday"); + dt.Columns.Add("Weekly Total"); + dt.Columns.Add("Comment"); + + AddDates(rpt, dt); + AddTargets(rpt, dt); + AddOuts(rpt, dt); + AddYieldedWafers(rpt, dt); + AddCustomerScrap(rpt, dt); + AddManufacturingScrap(rpt, dt); + AddProductionScrap(rpt, dt); + AddYield(rpt, dt); + AddDeltaToCommit(rpt, dt); + AddDeltaToTarget(rpt, dt); + AddNeededTarget(rpt, dt); + } + + public void AddDates(YieldStatistics rpt, DataTable dt) + { + DataRow dr = dt.NewRow(); + + for (int i = 0; i < 7; i++) + { + dr[1 + i] = rpt.StartDate.AddDays(i).ToString("MM/dd/yyyy"); + } + + dt.Rows.Add(dr); + } + + public void AddTargets(YieldStatistics rpt, DataTable dt) + { + DataRow dr = dt.NewRow(); + + dr["SIOperations"] = "Commited Target to meet Shipment Requirements"; + + for (int i = 0; i < 7; i++) + { + dr[1 + i] = string.Format("{0:#,###}", rpt.DailyPlanWafers); + } + + dr["WeeklyTotal"] = string.Format("{0:##,###}", rpt.DailyPlanWafers * 7); + dr["Comment"] = "Number updated quarterly"; + + dt.Rows.Add(dr); + } + + public void AddOuts(YieldStatistics rpt, DataTable dt) + { + int counter = 0; + + DataRow dr = dt.NewRow(); + + dr["SIOperations"] = "Actual Reactor Out"; + + for (int i = 0; i < 7; i++) + { + if (i < rpt.OutsByDay.Count) + { + dr[1 + i] = string.Format("{0:#,###}", rpt.OutsByDay[i].TotalWafers); + + counter += rpt.OutsByDay[i].TotalWafers; + } + } + + dr["WeeklyTotal"] = string.Format("{0:##,###}", counter); + dr["Comment"] = "Before Scrap"; + + dt.Rows.Add(dr); + } + + public void AddYieldedWafers(YieldStatistics rpt, DataTable dt) + { + int counter = 0; + + DataRow dr = dt.NewRow(); + + dr["SIOperations"] = "Actual Yielded Wafers Out"; + + for (int i = 0; i < 7; i++) + { + if (i < rpt.OutsByDay.Count) + { + dr[1 + i] = string.Format("{0:#,###}", rpt.OutsByDay[i].TotalWafers - rpt.ScrapByDay[i].TOT_REJ_WFRS - rpt.ScrapByDay[i].TW_PROD); + + counter += rpt.OutsByDay[i].TotalWafers - rpt.ScrapByDay[i].TOT_REJ_WFRS - rpt.ScrapByDay[i].TW_PROD; + } + } + + dr["WeeklyTotal"] = string.Format("{0:##,###}", counter); + dr["Comment"] = "After Scrap"; + + dt.Rows.Add(dr); + } + + public void AddCustomerScrap(YieldStatistics rpt, DataTable dt) + { + int counter = 0; + + DataRow dr = dt.NewRow(); + + dr["SIOperations"] = "Customer Scrap"; + + for (int i = 0; i < 7; i++) + { + if (i < rpt.OutsByDay.Count) + { + dr[1 + i] = string.Format("{0:#,###}", rpt.ScrapByDay[i].TOT_REJ_CUST); + + counter += rpt.ScrapByDay[i].TOT_REJ_CUST; + } + } + + dr["WeeklyTotal"] = string.Format("{0:##,###}", counter); + + dt.Rows.Add(dr); + } + + public void AddManufacturingScrap(YieldStatistics rpt, DataTable dt) + { + int counter = 0; + + DataRow dr = dt.NewRow(); + + dr["SIOperations"] = "Manufacturing Scrap"; + + for (int i = 0; i < 7; i++) + { + if (i < rpt.OutsByDay.Count) + { + dr[1 + i] = string.Format("{0:#,###}", rpt.ScrapByDay[i].TOT_REJ_MANU); + + counter += rpt.ScrapByDay[i].TOT_REJ_MANU; + } + } + + dr["WeeklyTotal"] = string.Format("{0:##,###}", counter); + + dt.Rows.Add(dr); + } + + public void AddProductionScrap(YieldStatistics rpt, DataTable dt) + { + int counter = 0; + + DataRow dr = dt.NewRow(); + + dr["SIOperations"] = "Production Scrap"; + + for (int i = 0; i < 7; i++) + { + if (i < rpt.OutsByDay.Count) + { + dr[1 + i] = string.Format("{0:#,###}", rpt.ScrapByDay[i].TW_PROD); + + counter += rpt.ScrapByDay[i].TW_PROD; + } + } + + dr["WeeklyTotal"] = string.Format("{0:##,###}", counter); + + dt.Rows.Add(dr); + } + + public void AddYield(YieldStatistics rpt, DataTable dt) + { + int totalOuts = 0; + int totalScrap = 0; + + DataRow dr = dt.NewRow(); + + dr["SIOperations"] = "Yield"; + + for (int i = 0; i < 7; i++) + { + if (i < rpt.OutsByDay.Count) + { + float yield = ((float)rpt.OutsByDay[i].TotalWafers - (float)rpt.ScrapByDay[i].TOT_REJ_WFRS) / (float)rpt.OutsByDay[i].TotalWafers; + + dr[1 + i] = string.Format("{0:P2}", rpt.ScrapByDay[i].TW_PROD); + + totalOuts += rpt.OutsByDay[i].TotalWafers; + totalScrap += rpt.ScrapByDay[i].TOT_REJ_CUST + rpt.ScrapByDay[i].TOT_REJ_MANU; + } + } + + dr["WeeklyTotal"] = string.Format("{0:P2}", (float)(totalOuts - totalScrap) / (float)totalOuts); + dr["Comment"] = "After Scrap"; + + dt.Rows.Add(dr); + } + + public void AddDeltaToCommit(YieldStatistics rpt, DataTable dt) + { + int counter = 0; + + DataRow dr = dt.NewRow(); + + dr["SIOperations"] = "Delta to commit"; + + for (int i = 0; i < 7; i++) + { + if (i < rpt.OutsByDay.Count) + { + int delta = rpt.OutsByDay[i].TotalWafers - rpt.ScrapByDay[i].TOT_REJ_WFRS - rpt.DailyPlanWafers; + + dr[1 + i] = string.Format("{0:#,###}", delta); + + counter += delta; + } + } + + dr["WeeklyTotal"] = string.Format("{0:##,###}", counter); + dr["Comment"] = "Difference to commitment"; + + dt.Rows.Add(dr); + } + + public void AddDeltaToTarget(YieldStatistics rpt, DataTable dt) + { + int counter = 0; + + DataRow dr = dt.NewRow(); + + dr["SIOperations"] = "Delta to the Plan"; + + for (int i = 0; i < 7; i++) + { + if (i < rpt.OutsByDay.Count) + { + int delta = rpt.OutsByDay[i].TotalWafers - rpt.ScrapByDay[i].TOT_REJ_WFRS - rpt.DailyPlanWafers; + + dr[1 + i] = string.Format("{0:#,###}", delta); + + counter += delta; + } + } + + dr["WeeklyTotal"] = string.Format("{0:##,###}", counter); + dr["Comment"] = "Difference to Target"; + + dt.Rows.Add(dr); + } + + public void AddNeededTarget(YieldStatistics rpt, DataTable dt) + { + DataRow dr = dt.NewRow(); + + dr["SIOperations"] = "Wafers Needed to make QTR"; + + for (int i = 0; i < 7; i++) + { + if (i < rpt.OutsByDay.Count) + { + dr[1 + i] = string.Format("{0:#,###}", rpt.DailyPlanWafers); + } + } + + dr["WeeklyTotal"] = string.Format("{0:##,###}", rpt.DailyPlanWafers * 7); + dr["Comment"] = "Number updated Weekly"; + + dt.Rows.Add(dr); + } + + private void btnPrevious_Click(object sender, EventArgs e) + { + btnNext.Visible = true; + btnPrevious.Visible = false; + + dgvCurrentWeek.Visible = false; + dgvPreviousWeek.Visible = true; + } + + private void btnNext_Click(object sender, EventArgs e) + { + btnNext.Visible = false; + btnPrevious.Visible = true; + + dgvCurrentWeek.Visible = true; + dgvPreviousWeek.Visible = false; + } + } +} \ No newline at end of file diff --git a/ReportingServices.Desktop/DailyReport.resx b/ReportingServices.Desktop/DailyReport.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/ReportingServices.Desktop/DailyReport.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ReportingServices.Desktop/Form1.Designer.cs b/ReportingServices.Desktop/Form1.Designer.cs new file mode 100644 index 0000000..9a5f116 --- /dev/null +++ b/ReportingServices.Desktop/Form1.Designer.cs @@ -0,0 +1,60 @@ +namespace ReportingServices.Desktop +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.btnDailyReport = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // btnDailyReport + // + this.btnDailyReport.Location = new System.Drawing.Point(98, 12); + this.btnDailyReport.Name = "btnDailyReport"; + this.btnDailyReport.Size = new System.Drawing.Size(140, 65); + this.btnDailyReport.TabIndex = 0; + this.btnDailyReport.Text = "Daily Report"; + this.btnDailyReport.UseVisualStyleBackColor = true; + this.btnDailyReport.Click += new System.EventHandler(this.btnDailyReport_Click); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.btnDailyReport); + this.Name = "Form1"; + this.Text = "Form1"; + this.ResumeLayout(false); + + } + + #endregion + + private Button btnDailyReport; + } +} \ No newline at end of file diff --git a/ReportingServices.Desktop/Form1.cs b/ReportingServices.Desktop/Form1.cs new file mode 100644 index 0000000..94a12a2 --- /dev/null +++ b/ReportingServices.Desktop/Form1.cs @@ -0,0 +1,31 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace ReportingServices.Desktop +{ + public partial class Form1 : Form + { + ILogger _logger; + + public Form1(ILogger logger) + { + _logger = logger; + InitializeComponent(); + } + + private void btnDailyReport_Click(object sender, EventArgs e) + { + DailyReport report = new DailyReport(_logger); + this.Hide(); + report.Show(); + } + } +} diff --git a/ReportingServices.Desktop/Form1.resx b/ReportingServices.Desktop/Form1.resx new file mode 100644 index 0000000..f298a7b --- /dev/null +++ b/ReportingServices.Desktop/Form1.resx @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ReportingServices.Desktop/Program.cs b/ReportingServices.Desktop/Program.cs new file mode 100644 index 0000000..91a5ca8 --- /dev/null +++ b/ReportingServices.Desktop/Program.cs @@ -0,0 +1,32 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace ReportingServices.Desktop +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + var services = new ServiceCollection(); + ConfigureServices(services); + using (ServiceProvider serviceProvider = services.BuildServiceProvider()) + { + var form1 = serviceProvider.GetRequiredService(); + Application.Run(form1); + } + } + + private static void ConfigureServices(ServiceCollection services) + { + services.AddSingleton() + .AddLogging(configure => configure.AddConsole()); + } + } +} \ No newline at end of file diff --git a/ReportingServices.Desktop/ReportingServices.Desktop.csproj b/ReportingServices.Desktop/ReportingServices.Desktop.csproj new file mode 100644 index 0000000..ec5cd8b --- /dev/null +++ b/ReportingServices.Desktop/ReportingServices.Desktop.csproj @@ -0,0 +1,15 @@ + + + + WinExe + net6.0-windows + enable + true + enable + + + + + + + \ No newline at end of file diff --git a/ReportingServices.Shared/HelperClasses/ApiCaller.cs b/ReportingServices.Shared/HelperClasses/ApiCaller.cs index e9e230e..25000ad 100644 --- a/ReportingServices.Shared/HelperClasses/ApiCaller.cs +++ b/ReportingServices.Shared/HelperClasses/ApiCaller.cs @@ -8,12 +8,19 @@ namespace ReportingServices.Shared.HelperClasses { public static async Task GetApi(string url) { - T deserializedJson; + T deserializedJson = default(T); - using (HttpClient client = new()) + try { - string apiResponse = await client.GetStringAsync(url); - deserializedJson = JsonSerializer.Deserialize(apiResponse); + using (HttpClient client = new()) + { + string apiResponse = await client.GetStringAsync(url); + deserializedJson = JsonSerializer.Deserialize(apiResponse); + } + } + catch (Exception ex) + { + } return deserializedJson; diff --git a/ReportingServices.Shared/HelperClasses/DailyReportHelper.cs b/ReportingServices.Shared/HelperClasses/DailyReportHelper.cs index 8945f6b..991749b 100644 --- a/ReportingServices.Shared/HelperClasses/DailyReportHelper.cs +++ b/ReportingServices.Shared/HelperClasses/DailyReportHelper.cs @@ -11,10 +11,67 @@ namespace ReportingServices.Shared.HelperClasses public static DailyReport SetUpDailyReport(ILogger logger, string baseUrlFabtime, string baseUrlScrapeDb) { + List cleanTools = new() + { + "AHPS", + "AKRION1", + "CB3", + "MES", + "SRD 1", + "SRD 2" + }; + + List metrologyTools = new() + { + "ASET", + "BIORAD2", + "BIORAD3", + "BIORAD4", + "BIORAD5", + "CDE2", + "CDE3", + "CDE5", + "FLEXUS", + "HGCV1", + "HGCV2", + "HGCV3", + "SRP" + }; + List>> tasksEQState = new(); List>> tasksState = new(); DailyReport report = new(); + List reactors = ApiCaller.GetApi>(baseUrlScrapeDb + "Reactors").Result; + + List>> toolEvents = new(); + List> cleanEvents = new(); + List> metrologyEvents = new(); + + try + { + foreach (Reactor reactor in reactors) + { + toolEvents.Add(ApiCaller.GetApi>(baseUrlScrapeDb + "ReactorEvents?startDate=" + report.StartDate.ToString() + + "&endDate=" + DateTime.Now.ToString() + "&reactorNumber=" + reactor.ReactorNumber + "&reactorType=" + reactor.Type)); + } + + foreach (string tool in cleanTools) + { + cleanEvents.Add(ApiCaller.GetApi(baseUrlScrapeDb + "ToolEvents?toolID=" + tool)); + } + + foreach (string tool in metrologyTools) + { + metrologyEvents.Add(ApiCaller.GetApi(baseUrlScrapeDb + "ToolEvents?toolID=" + tool)); + } + } + catch (Exception ex) + { + + } + + try { report.SLLTools = JsonFileHandler.LoadJSONFile>(_SLLFilePath); @@ -34,8 +91,8 @@ namespace ReportingServices.Shared.HelperClasses try { - task1 = ApiCaller.GetApi(baseUrlFabtime + "ReactorOuts?startDate=" + report.StartDate.ToString() + "&endDate=" + DateTime.Now.ToString()); - task2 = ApiCaller.GetApi(baseUrlFabtime + "ReactorOuts?startDate=" + report.StartDate.AddDays(-7).ToString() + "&endDate=" + report.StartDate.ToString()); + task1 = ApiCaller.GetApi(baseUrlScrapeDb + "ReactorOuts?startDate=" + report.StartDate.ToString() + "&endDate=" + DateTime.Now.ToString()); + task2 = ApiCaller.GetApi(baseUrlScrapeDb + "ReactorOuts?startDate=" + report.StartDate.AddDays(-7).ToString() + "&endDate=" + report.StartDate.ToString()); tasksEQState.Add(ApiCaller.GetApi>(baseUrlFabtime + "ToolStateTrend?toolType=ASM")); tasksEQState.Add(ApiCaller.GetApi>(baseUrlFabtime + "ToolStateTrend?toolType=EPP")); @@ -53,13 +110,12 @@ namespace ReportingServices.Shared.HelperClasses Task targets = null; Task> rds = null; - Task> reactors = null; try { targets = ApiCaller.GetApi(baseUrlScrapeDb + "Targets"); rds = ApiCaller.GetApi>(baseUrlScrapeDb + "RDS?date=" + report.StartDate.ToString()); - reactors = ApiCaller.GetApi>(baseUrlScrapeDb + "Reactors"); + } catch (Exception ex) { @@ -86,9 +142,29 @@ namespace ReportingServices.Shared.HelperClasses try { report.QuarterlyTargets = targets.Result; - report.SetRDSInfo(rds.Result); - report.SetReactorInfo(reactors.Result, GetUnscheduledReactors(report)); + report.SetReactorInfo(reactors, GetUnscheduledReactors(report)); + + foreach (var task in toolEvents) + { + report.ToolEvents.Add(new ToolEventView(task.Result, + report.StartDate.ToString(), DateTime.Now.ToString(), task.Result[0].REACT_NO, + reactors.FirstOrDefault(x => x.ReactorNumber == int.Parse(task.Result[0].REACT_NO)).Type)); + } + + report.ToolEvents = report.ToolEvents + .Where(x => x.Reactor != "100" && x.Reactor != "101" && x.Reactor != "47") + .OrderBy(x => x.Reactor) + .ToList(); + + foreach (Task task in cleanEvents) + report.CleanEvents.Add(task.Result); + + foreach (Task task in metrologyEvents) + report.MetrologyEvents.Add(task.Result); + + report.CleanEvents = report.CleanEvents.Where(x => (x.TOOL_MODE != "PROD" || x.TOOL_MODE_DESC != "Production") && x.TOOL_MODE != "OUT").ToList(); + report.MetrologyEvents = report.MetrologyEvents.Where(x => (x.TOOL_MODE != "PROD" || x.TOOL_MODE_DESC != "Production") && x.TOOL_MODE != "OUT").ToList(); } catch (Exception ex) { diff --git a/ReportingServices.Shared/Models/ProductionReport/ReactorEvent.cs b/ReportingServices.Shared/Models/ProductionReport/ReactorEvent.cs new file mode 100644 index 0000000..9e1b948 --- /dev/null +++ b/ReportingServices.Shared/Models/ProductionReport/ReactorEvent.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; + +namespace ReportingServices.Shared.Models.ProductionReport +{ + public class ReactorEvent + { + [JsonPropertyName("REACT_NO")] + public string REACT_NO { get; set; } + [JsonPropertyName("EVENT_DTM")] + public string EVENT_DTM { get; set; } + [JsonPropertyName("COMMENT")] + public string COMMENT { get; set; } + [JsonPropertyName("REACT_MODE")] + public string REACT_MODE { get; set; } + } +} diff --git a/ReportingServices.Shared/Models/ProductionReport/ToolEvent.cs b/ReportingServices.Shared/Models/ProductionReport/ToolEvent.cs new file mode 100644 index 0000000..632a404 --- /dev/null +++ b/ReportingServices.Shared/Models/ProductionReport/ToolEvent.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; + +namespace ReportingServices.Shared.Models.ProductionReport +{ + public class ToolEvent + { + [JsonPropertyName("TOOL_ID")] + public string TOOL_ID { get; set; } + [JsonPropertyName("START_DTM")] + public string START_DTM { get; set; } + [JsonPropertyName("TOOL_MODE")] + public string TOOL_MODE { get; set; } + [JsonPropertyName("TOOL_MODE_DESC")] + public string TOOL_MODE_DESC { get; set; } + } +} diff --git a/ReportingServices.Shared/Models/ProductionReport/ToolUptimeData.cs b/ReportingServices.Shared/Models/ProductionReport/ToolUptimeData.cs new file mode 100644 index 0000000..6e0d726 --- /dev/null +++ b/ReportingServices.Shared/Models/ProductionReport/ToolUptimeData.cs @@ -0,0 +1,8 @@ +namespace ReportingServices.Shared.Models.ProductionReport +{ + public class ToolUptimeData + { + public string Date { get; set; } + public double UptimePercentage { get; set; } + } +} diff --git a/ReportingServices.Shared/Repositories/Implementations/ScrapeDatabaseRepository.cs b/ReportingServices.Shared/Repositories/Implementations/ScrapeDatabaseRepository.cs index 35d2766..72d7c8f 100644 --- a/ReportingServices.Shared/Repositories/Implementations/ScrapeDatabaseRepository.cs +++ b/ReportingServices.Shared/Repositories/Implementations/ScrapeDatabaseRepository.cs @@ -269,5 +269,133 @@ namespace ReportingServices.Shared.Repositories return rdsList; } + + public List GetRDSRunBetweenDates(string startDate, string endDate) + { + List outs = new(); + + OpenConnection(); + + SqlCommand cmd = _connection.CreateCommand(); + + string query = "SELECT SEQ, WFRS_OUT, DATE_OUT " + + " FROM RDS " + + " WHERE DATE_OUT >= @startDate " + + " AND DATE_OUT < @endDate " + + "ORDER BY DATE_OUT ASC"; + + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@startDate", startDate); + cmd.Parameters.AddWithValue("@endDate", endDate); + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + outs.Add(new ReactorOutsByRDS + { + RDS_NO = reader[0].ToString(), + Units = reader[1].ToString(), + EndProcessTime = reader[2].ToString() + }); + } + + cmd.Dispose(); + + CloseConnection(); + + return outs; + } + + public List GetReactorEvents(string startDate, string endDate, string reactorNumber) + { + List events = new(); + + OpenConnection(); + + SqlCommand cmd = _connection.CreateCommand(); + + string query = "SELECT " + + " REACT_NO, " + + " EVENT_DTM, " + + " COMMENT, " + + " REACT_MODE " + + " FROM REACT_EVENT " + + " WHERE EVENT_DTM > @startDate " + + " AND EVENT_DTM < @endDate " + + " AND REACT_NO = @reactorNumber " + + "UNION ALL " + + "SELECT " + + " REACT_NO, " + + " EVENT_DTM, " + + " COMMENT, " + + " REACT_MODE " + + " FROM " + + " (SELECT TOP 1 * FROM REACT_EVENT " + + " WHERE EVENT_DTM < @startDate " + + " AND REACT_NO = @reactorNumber ORDER BY EVENT_DTM DESC) AS tbl1 " + + "ORDER BY EVENT_DTM ASC;"; + + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@startDate", startDate); + cmd.Parameters.AddWithValue("@endDate", endDate); + cmd.Parameters.AddWithValue("@reactorNumber", reactorNumber); + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + events.Add(new ReactorEvent + { + REACT_NO = reader[0].ToString(), + EVENT_DTM = reader[1].ToString(), + COMMENT = reader[2].ToString(), + REACT_MODE = reader[3].ToString() + }); + } + + cmd.Dispose(); + + CloseConnection(); + + return events; + } + + public ToolEvent GetLatestToolEvent(string toolID) + { + ToolEvent evnt = new(); + + OpenConnection(); + + SqlCommand cmd = _connection.CreateCommand(); + + string query = "SELECT TOP 1 " + + " TOOL_ID, " + + " START_DTM, " + + " TOOL_MODE, " + + " TOOL_MODE_DESC " + + " FROM TOOL_LOG " + + " WHERE TOOL_ID = @toolID " + + "ORDER BY START_DTM DESC;"; + + cmd.CommandText = query; + cmd.Parameters.AddWithValue("@toolID", toolID); + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + evnt = new ToolEvent + { + TOOL_ID = reader[0].ToString(), + START_DTM = reader[1].ToString(), + TOOL_MODE = reader[2].ToString(), + TOOL_MODE_DESC = reader[3].ToString() + }; + } + + cmd.Dispose(); + + CloseConnection(); + + return evnt; + } } } diff --git a/ReportingServices.Shared/Repositories/Interfaces/IScrapeDatabaseRepository.cs b/ReportingServices.Shared/Repositories/Interfaces/IScrapeDatabaseRepository.cs index 4b2d746..8c14a7f 100644 --- a/ReportingServices.Shared/Repositories/Interfaces/IScrapeDatabaseRepository.cs +++ b/ReportingServices.Shared/Repositories/Interfaces/IScrapeDatabaseRepository.cs @@ -13,5 +13,8 @@ namespace ReportingServices.Shared.Repositories public QuarterlyTargets GetQuarterlyTargets(); public List GetReactors(); public List GetRDSForLastDay(string date); + public List GetRDSRunBetweenDates(string startDate, string endDate); + public List GetReactorEvents(string startDate, string endDate, string reactorNumber); + public ToolEvent GetLatestToolEvent(string toolID); } } diff --git a/ReportingServices.Shared/ViewModels/ProductionReport/DailyReport.cs b/ReportingServices.Shared/ViewModels/ProductionReport/DailyReport.cs index 516f7f6..6b0e842 100644 --- a/ReportingServices.Shared/ViewModels/ProductionReport/DailyReport.cs +++ b/ReportingServices.Shared/ViewModels/ProductionReport/DailyReport.cs @@ -1,6 +1,5 @@ using ReportingServices.Shared.HelperClasses; using ReportingServices.Shared.Models.ProductionReport; -using ReportingServices.Shared.ViewModels.ProductionReport; namespace ReportingServices.Shared.ViewModels.ProductionReport { @@ -9,8 +8,11 @@ namespace ReportingServices.Shared.ViewModels.ProductionReport public DateTime StartDate { get; set; } public YieldStatistics CurrentWeek { get; set; } public YieldStatistics PreviousWeek { get; set; } + public List ToolEvents { get; set; } public Dictionary> ToolAvailibilityByType { get; set; } public Dictionary ToolStateByType { get; set; } + public List CleanEvents { get; set; } + public List MetrologyEvents { get; set; } public Dictionary> ToolStatesByOwner { get; set; } public Dictionary> DualLayerReactors { get; set; } public ManualReportEntries ManualReportEntries { get; set; } @@ -26,8 +28,11 @@ namespace ReportingServices.Shared.ViewModels.ProductionReport { ToolAvailibilityByType = new(); ToolStateByType = new(); + CleanEvents = new(); + MetrologyEvents = new(); DualLayerReactors = new(); UnloadTempsByDay = new(); + ToolEvents = new(); StartDate = DateTime.Parse(APIHelperFunctions.GetBeginningOfWeekAsAPIString()); CurrentWeek = new(StartDate, true); PreviousWeek = new(StartDate.AddDays(-7), false); diff --git a/ReportingServices.Shared/ViewModels/ProductionReport/ToolEventView.cs b/ReportingServices.Shared/ViewModels/ProductionReport/ToolEventView.cs new file mode 100644 index 0000000..fbeb651 --- /dev/null +++ b/ReportingServices.Shared/ViewModels/ProductionReport/ToolEventView.cs @@ -0,0 +1,187 @@ +using ReportingServices.Shared.Models.ProductionReport; +using System.Data; + +namespace ReportingServices.Shared.ViewModels.ProductionReport +{ + public class ToolEventView + { + public string Reactor { get; set; } + public string Type { get; set; } + public bool DownMoreThanTwelveHours { get; set; } + public string StartDate { get; set; } + public string EndDate { get; set; } + public bool IsInProduction { get; set; } + public List Events { get; set; } + public ReactorEvent MostRecentEvent { get; set; } + public List Uptime { get; set; } + + public ToolEventView(List events, string startDate, string endDate, string reactor, string type) + { + Events = events; + StartDate = startDate; + EndDate = endDate; + Reactor = reactor; + Type = type; + MostRecentEvent = events[events.Count - 1]; + IsInProduction = EventIsProduction(MostRecentEvent.REACT_MODE); + DownMoreThanTwelveHours = DetermineIfExtendedDowntime(); + Uptime = DetermineToolUptimeData(); + } + + private bool DetermineIfExtendedDowntime() + { + double numberOfHours = 0; + + for (int i = Events.Count - 1; i >= 0; i--) + { + if (EventIsProduction(Events[i].REACT_MODE)) + return false; + + if (i == Events.Count - 1) + numberOfHours = (DateTime.Now - DateTime.Parse(Events[i].EVENT_DTM)).TotalHours; + else + numberOfHours += (DateTime.Parse(Events[i + 1].EVENT_DTM) - DateTime.Parse(Events[i].EVENT_DTM)).TotalHours; + + if (numberOfHours > 12) + return true; + } + + return false; + } + + public List DetermineToolUptimeData() + { + List data = new(); + + bool currentModeIsUp; + double uptime = 0; + DateTime compareDate = DateTime.Parse(StartDate).Date; + DateTime previousTransaction = DateTime.Parse(StartDate).Date; + + currentModeIsUp = EventIsProduction(Events[0].REACT_MODE); + + if (Events.Count == 1) + data = LoadUptimeData(currentModeIsUp); + + for (int i = 1; i < Events.Count; i++) + { + DateTime currentTransaction = DateTime.Parse(Events[i].EVENT_DTM); + + if (currentTransaction.Date == compareDate) + { + if (currentModeIsUp) + uptime += (DateTime.Parse(Events[i].EVENT_DTM) - previousTransaction).TotalMinutes; + + currentModeIsUp = EventIsProduction(Events[i].REACT_MODE); + previousTransaction = DateTime.Parse(Events[i].EVENT_DTM); + } + + if ((currentTransaction.Date - compareDate).TotalHours == 24) + { + if (currentModeIsUp) + uptime += (currentTransaction.Date - previousTransaction).TotalMinutes; + + data.Add(new ToolUptimeData + { + Date = compareDate.ToString(), + UptimePercentage = uptime / 1440 + }); + + if (currentModeIsUp) + uptime = (currentTransaction - currentTransaction.Date).TotalMinutes; + else + uptime = 0; + + compareDate = compareDate.AddDays(1); + currentModeIsUp = EventIsProduction(Events[i].REACT_MODE); + previousTransaction = DateTime.Parse(Events[i].EVENT_DTM); + } + + if ((currentTransaction.Date - compareDate).TotalHours > 24) + { + while (currentTransaction.Date != compareDate) + { + if (currentModeIsUp) + uptime += (compareDate.AddDays(1) - previousTransaction).TotalMinutes; + + data.Add(new ToolUptimeData + { + Date = compareDate.ToString(), + UptimePercentage = uptime / 1440 + }); + + uptime = 0; + + compareDate = compareDate.AddDays(1); + previousTransaction = compareDate; + } + } + + if (i == Events.Count - 1) + { + if ((DateTime.Parse(EndDate).Date != compareDate)) + { + while (DateTime.Parse(EndDate).Date != compareDate) + { + if (currentModeIsUp) + uptime += (compareDate.AddDays(1) - previousTransaction).TotalMinutes; + + data.Add(new ToolUptimeData + { + Date = compareDate.ToString(), + UptimePercentage = uptime / 1440 + }); + + uptime = 0; + + compareDate = compareDate.AddDays(1); + previousTransaction = compareDate; + } + } + + if (currentModeIsUp) + uptime += (DateTime.Parse(EndDate) - previousTransaction).TotalMinutes; + + data.Add(new ToolUptimeData + { + Date = DateTime.Now.Date.ToString(), + UptimePercentage = uptime / (DateTime.Parse(EndDate) - DateTime.Parse(EndDate).Date).TotalMinutes + }); + + } + } + + return data; + } + + private List LoadUptimeData(bool currentModeIsUp) + { + List data = new(); + + double days = (DateTime.Parse(EndDate) - DateTime.Parse(StartDate)).TotalDays; + + for (int i = 0; i < days; i++) + { + data.Add(new ToolUptimeData + { + Date = DateTime.Parse(StartDate).Date.AddDays(i).ToString(), + UptimePercentage = currentModeIsUp ? 1 : 0 + }); + } + + return data; + } + + private bool EventIsProduction(string evnt) + { + if (evnt.ToUpper() == "UP") + return true; + + if (evnt.ToUpper() == "UP_WITH_INCREASED_SAMPLING") + return true; + + return false; + } + + } +} diff --git a/ReportingServices.UI/Controllers/PlanningReportController.cs b/ReportingServices.UI/Controllers/PlanningReportController.cs index d7a60d9..96c8505 100644 --- a/ReportingServices.UI/Controllers/PlanningReportController.cs +++ b/ReportingServices.UI/Controllers/PlanningReportController.cs @@ -1,7 +1,6 @@ using Microsoft.AspNetCore.Mvc; using ReportingServices.Shared.Models.PlanningReport; using ReportingServices.Shared.HelperClasses; -using static System.Net.WebRequestMethods; namespace ReportingServices.UI.Controllers { @@ -13,7 +12,7 @@ namespace ReportingServices.UI.Controllers public PlanningReportController(ILogger logger) { _logger = logger; - _baseUrl = "http://localhost:50201/api/" + "ScrapeDB/"; + _baseUrl = "https://localhost:7196/api/" + "ScrapeDB/"; _logger.LogInformation("Base API Address: {baseUrl}", _baseUrl); } diff --git a/ReportingServices.UI/Controllers/ProductionReportController.cs b/ReportingServices.UI/Controllers/ProductionReportController.cs index a51677b..6f9362e 100644 --- a/ReportingServices.UI/Controllers/ProductionReportController.cs +++ b/ReportingServices.UI/Controllers/ProductionReportController.cs @@ -16,8 +16,8 @@ namespace ReportingServices.UI.Controllers public ProductionReportController(ILogger logger) { _logger = logger; - _baseFTUrl = "http://mestsa008:50201/api/"; - _baseDBUrl = "http://localhost:50201/api/"; + _baseFTUrl = "https://localhost:7196/api/"; + _baseDBUrl = "https://localhost:7196/api/"; _logger.LogInformation("Base FabTime Address: {baseUrl}", _baseFTUrl); _logger.LogInformation("Base Database Address: {baseUrl}", _baseDBUrl); diff --git a/ReportingServices.UI/Views/ProductionReport/DailyReport.cshtml b/ReportingServices.UI/Views/ProductionReport/DailyReport.cshtml index 1b8fc99..cb04acb 100644 --- a/ReportingServices.UI/Views/ProductionReport/DailyReport.cshtml +++ b/ReportingServices.UI/Views/ProductionReport/DailyReport.cshtml @@ -1,8 +1,8 @@ @model DailyReport @{ - int ASMAvailablePct = 0; - int EPPAvailablePct = 0; - int HTRAvailablePct = 0; + double ASMAvailablePct = 0; + double EPPAvailablePct = 0; + double HTRAvailablePct = 0; int ASMSLL = 0; int HTRSLL = 0; @@ -17,15 +17,8 @@ ManualReportEntries rpt = Model.ManualReportEntries; string myClass; - List toolsDownGreaterThan12Hours = new(); - foreach (KeyValuePair state in Model.ToolStateByType) - { - if (state.Key != "Metrology" && state.Key != "Cleans") - toolsDownGreaterThan12Hours.AddRange(state.Value.ToolsDownGreaterThan12Hours); - } - - toolsDownGreaterThan12Hours.Sort(); + List toolsExtendedDown = Model.ToolEvents.Where(x => x.DownMoreThanTwelveHours).Select(x => x.Reactor).ToList(); } @{ @@ -77,10 +70,13 @@
Edit

-
Current Reactors Down(@(Model.ToolStateByType["ASM"].DownTools + Model.ToolStateByType["EPP"].DownTools + Model.ToolStateByType["HTR"].DownTools)):
+
Current Reactors Down(@Model.ToolEvents.Where(x => x.IsInProduction == false).Count()):
- ASM(@Model.ToolStateByType["ASM"].DownTools) + @{ + List asmTools = Model.ToolEvents.Where(x => x.IsInProduction == false && x.Type.Contains("ASM")).ToList(); + } + ASM(@asmTools.Count()) @@ -90,25 +86,22 @@ - @foreach (ToolStateCurrent tool in Model.ToolStateByType["ASM"].ToolStateCurrents) + @foreach (ToolEventView tool in asmTools) { - if (tool.BasicStateDescription != "Productive" && tool.ReactorStatus != "Out of Service") - { - string owner = ""; + string owner = ""; - if (Model.ToolStatesByOwner["Maintenance"].Contains(tool.ReactorStatus)) - owner = "Maint"; - else if (Model.ToolStatesByOwner["Engineering"].Contains(tool.ReactorStatus)) - owner = "Eng"; - else - owner = "Prod"; + if (Model.ToolStatesByOwner["Maintenance"].Contains(tool.MostRecentEvent.REACT_MODE)) + owner = "Maint"; + else if (Model.ToolStatesByOwner["Engineering"].Contains(tool.MostRecentEvent.REACT_MODE)) + owner = "Eng"; + else + owner = "Prod"; - - - - - - } + + + + + }
@tool.Tool@owner@tool.Comment
@tool.Reactor@owner@tool.MostRecentEvent.COMMENT
@@ -116,7 +109,10 @@
- EPP(@Model.ToolStateByType["EPP"].DownTools) + @{ + List eppTools = Model.ToolEvents.Where(x => x.IsInProduction == false && x.Type.Contains("EPP")).ToList(); + } + EPP(@eppTools.Count()) @@ -126,25 +122,22 @@ - @foreach (ToolStateCurrent tool in Model.ToolStateByType["EPP"].ToolStateCurrents) + @foreach (ToolEventView tool in eppTools) { - if (tool.BasicStateDescription != "Productive" && tool.ReactorStatus != "Out of Service") - { - string owner = ""; + string owner = ""; - if (Model.ToolStatesByOwner["Maintenance"].Contains(tool.ReactorStatus)) - owner = "Maint"; - else if (Model.ToolStatesByOwner["Engineering"].Contains(tool.ReactorStatus)) - owner = "Eng"; - else - owner = "Prod"; + if (Model.ToolStatesByOwner["Maintenance"].Contains(tool.MostRecentEvent.REACT_MODE)) + owner = "Maint"; + else if (Model.ToolStatesByOwner["Engineering"].Contains(tool.MostRecentEvent.REACT_MODE)) + owner = "Eng"; + else + owner = "Prod"; - - - - - - } + + + + + }
@tool.Tool@owner@tool.Comment
@tool.Reactor@owner@tool.MostRecentEvent.COMMENT
@@ -152,7 +145,10 @@
- HTR(@Model.ToolStateByType["HTR"].DownTools) + @{ + List htrTools = Model.ToolEvents.Where(x => x.IsInProduction == false && x.Type.Contains("HTR")).ToList(); + } + EPP(@htrTools.Count()) @@ -162,25 +158,22 @@ - @foreach (ToolStateCurrent tool in Model.ToolStateByType["HTR"].ToolStateCurrents) + @foreach (ToolEventView tool in htrTools) { - if (tool.BasicStateDescription != "Productive" && tool.ReactorStatus != "Out of Service") - { - string owner = ""; + string owner = ""; - if (Model.ToolStatesByOwner["Maintenance"].Contains(tool.ReactorStatus)) - owner = "Maint"; - else if (Model.ToolStatesByOwner["Engineering"].Contains(tool.ReactorStatus)) - owner = "Eng"; - else - owner = "Prod"; + if (Model.ToolStatesByOwner["Maintenance"].Contains(tool.MostRecentEvent.REACT_MODE)) + owner = "Maint"; + else if (Model.ToolStatesByOwner["Engineering"].Contains(tool.MostRecentEvent.REACT_MODE)) + owner = "Eng"; + else + owner = "Prod"; - - - - - - } + + + + + }
@tool.Tool@owner@tool.Comment
@tool.Reactor@owner@tool.MostRecentEvent.COMMENT
@@ -209,34 +202,27 @@
  • Engineering Focus Tools (Down > 12 hours)
      -
    • @string.Join(",", toolsDownGreaterThan12Hours)
    • +
    • @string.Join(",", toolsExtendedDown)
  • -
  • Metrology Down (@Model.ToolStateByType["Metrology"].DownTools): - @if (Model.ToolStateByType["Metrology"].DownTools > 0) +
  • Metrology Down (@Model.MetrologyEvents.Count()): + @if (@Model.MetrologyEvents.Count() > 0) {
      - @foreach (ToolStateCurrent tool in Model.ToolStateByType["Metrology"].ToolStateCurrents) + @foreach (ToolEvent tool in @Model.MetrologyEvents) { - if (tool.BasicStateDescription != "Productive" && tool.ReactorStatus != "Out of Service") - { -
    • @tool.Tool
    • - } +
    • @tool.TOOL_ID
    • }
    }
  • -
  • - Cleans (@Model.ToolStateByType["Cleans"].DownTools): - @if (Model.ToolStateByType["Cleans"].DownTools > 0) +
  • Cleans (@Model.CleanEvents.Count()): + @if (@Model.CleanEvents.Count() > 0) {
      - @foreach (ToolStateCurrent tool in Model.ToolStateByType["Cleans"].ToolStateCurrents) + @foreach (ToolEvent tool in @Model.CleanEvents) { - if (tool.BasicStateDescription != "Productive" && tool.ReactorStatus != "Out of Service") - { -
    • @tool.Tool
    • - } +
    • @tool.TOOL_ID
    • }
    } @@ -273,75 +259,96 @@ ASMs Uptime @for (int i = 0; i < 7; i++) { - if (i < Model.ToolAvailibilityByType["ASM"].Count) - { - int availiblePct = (int)Math.Round(float.Parse(Model.ToolAvailibilityByType["ASM"][i].AvailablePct)); + asmTools = Model.ToolEvents.Where(x => x.Type.Contains("ASM")).ToList(); - if (availiblePct < 82) + double availablePct = 0; + + if (i < asmTools[0].Uptime.Count) + { + for (int j = 0; j < asmTools.Count; j++) + { + availablePct += asmTools[j].Uptime[i].UptimePercentage; + } + + if (availablePct / asmTools.Count < .82) myClass = "table-danger text-danger"; else myClass = ""; - @(availiblePct + "%") + @string.Format("{0:P2}", availablePct / asmTools.Count) - ASMAvailablePct += availiblePct; + ASMAvailablePct += availablePct / asmTools.Count; } else { } } - @(ASMAvailablePct / numberOfDaysInWeek + "%") + @string.Format("{0:P2}", ASMAvailablePct / numberOfDaysInWeek) 82% EPPs Uptime @for (int i = 0; i < 7; i++) { - if (i < Model.ToolAvailibilityByType["EPP"].Count) - { - int availiblePct = (int)Math.Round(float.Parse(Model.ToolAvailibilityByType["EPP"][i].AvailablePct)); + eppTools = Model.ToolEvents.Where(x => x.Type.Contains("EPP")).ToList(); - if (availiblePct < 60) + double availablePct = 0; + + if (i < eppTools[0].Uptime.Count) + { + for (int j = 0; j < eppTools.Count; j++) + { + availablePct += eppTools[j].Uptime[i].UptimePercentage; + } + + if (availablePct / eppTools.Count < .60) myClass = "table-danger text-danger"; else myClass = ""; - @(availiblePct + "%") + @string.Format("{0:P2}", availablePct / eppTools.Count) - EPPAvailablePct += availiblePct; + EPPAvailablePct += availablePct / eppTools.Count; } else { } } - @(EPPAvailablePct / numberOfDaysInWeek + "%") + @string.Format("{0:P2}", EPPAvailablePct / numberOfDaysInWeek) 60% HTRs Uptime @for (int i = 0; i < 7; i++) { - if (i < Model.ToolAvailibilityByType["HTR"].Count) - { - int availiblePct = (int)Math.Round(float.Parse(Model.ToolAvailibilityByType["HTR"][i].AvailablePct)); + htrTools = Model.ToolEvents.Where(x => x.Type.Contains("HTR")).ToList(); - if (availiblePct < 78) + double availablePct = 0; + + if (i < htrTools[0].Uptime.Count) + { + for (int j = 0; j < htrTools.Count; j++) + { + availablePct += htrTools[j].Uptime[i].UptimePercentage; + } + + if (availablePct / htrTools.Count < .78) myClass = "table-danger text-danger"; else myClass = ""; - @(availiblePct + "%") + @string.Format("{0:P2}", availablePct / htrTools.Count) - HTRAvailablePct += availiblePct; + HTRAvailablePct += availablePct / htrTools.Count; } else { } } - @(HTRAvailablePct / numberOfDaysInWeek + "%") + @string.Format("{0:P2}", HTRAvailablePct / numberOfDaysInWeek) 78% diff --git a/ReportingServices.UI/wwwroot/Assets/SLLTools.json b/ReportingServices.UI/wwwroot/Assets/SLLTools.json index c02f3ef..7af0e1a 100644 --- a/ReportingServices.UI/wwwroot/Assets/SLLTools.json +++ b/ReportingServices.UI/wwwroot/Assets/SLLTools.json @@ -1 +1,17 @@ -[{"Date":"2023-01-02T00:00:00","ASM":5,"HTR":12},{"Date":"2023-01-03T00:00:00","ASM":6,"HTR":14},{"Date":"2023-01-04T00:00:00","ASM":7,"HTR":15},{"Date":"2023-01-05T00:00:00-07:00","ASM":7,"HTR":16}] \ No newline at end of file +[ + { + "Date": "2023-01-09T00:00:00-07:00", + "ASM": 8, + "HTR": 16 + }, + { + "Date": "2023-01-10T00:00:00-07:00", + "ASM": 8, + "HTR": 16 + }, + { + "Date": "2023-01-11T00:00:00-07:00", + "ASM": 8, + "HTR": 16 + } +] \ No newline at end of file