- Add displayudc.asp with Dashboard tab containing: - Production Trend chart (daily parts) - OOT Rate Trend chart (daily OOT %) - Machine Utilization chart (top 10 by runtime hours) - Top Operators chart (top 10 by parts produced) - Add tabs for drill-down: Live Activity, Operators, Machines, Parts, Quality/OOT, Timing, Activity Log, Tool Health, Uptime, IT Diagnostics - Add Tool Health section to displaymachine.asp UDC tab: - Summary cards (tools monitored, measurements, OOT count) - Tool status table with health indicators - Recent OOT events display - Add UDC API endpoints in api.asp: - getUDCPartRuns, getUDCOperatorStats, getUDCMachineStats, getUDCManualTiming - Add sql/udctables.sql schema for UDC data storage - Update docs/API.md with UDC endpoint documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2174 lines
91 KiB
Plaintext
2174 lines
91 KiB
Plaintext
<%@ Language=VBScript %>
|
|
<%
|
|
Option Explicit
|
|
Response.Expires = -1
|
|
Response.ExpiresAbsolute = Now() - 1
|
|
Response.AddHeader "pragma", "no-cache"
|
|
Response.AddHeader "cache-control", "private, no-cache, must-revalidate"
|
|
'=============================================================================
|
|
' FILE: displayudc.asp
|
|
' PURPOSE: UDC (Universal Data Collector) Management Dashboard
|
|
' SECURITY: Parameterized queries, HTML encoding, input validation
|
|
' CREATED: 2025-12-12
|
|
'=============================================================================
|
|
Dim theme, strSQL, rs, objConn
|
|
%>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<!--#include file="./includes/header.asp"-->
|
|
<!--#include file="./includes/sql.asp"-->
|
|
<title>UDC Dashboard - ShopDB</title>
|
|
</head>
|
|
|
|
<%
|
|
theme = Request.Cookies("theme")
|
|
If theme = "" Then theme = "bg-theme1"
|
|
|
|
' Get filter parameters
|
|
Dim filterMachine, filterBadge, filterPart, filterStart, filterEnd, periodFilter, filterBU
|
|
filterMachine = Trim(Request.QueryString("machine") & "")
|
|
filterBadge = Trim(Request.QueryString("badge") & "")
|
|
filterPart = Trim(Request.QueryString("part") & "")
|
|
filterStart = Trim(Request.QueryString("startdate") & "")
|
|
filterEnd = Trim(Request.QueryString("enddate") & "")
|
|
periodFilter = Trim(Request.QueryString("period") & "")
|
|
filterBU = Trim(Request.QueryString("bu") & "")
|
|
|
|
' Tab persistence
|
|
Dim activeTab
|
|
activeTab = Trim(Request.QueryString("tab") & "")
|
|
If activeTab = "" Then activeTab = "dashboard"
|
|
|
|
' Shift-span filter for manual response times
|
|
Dim excludeShiftSpan, shiftFilter
|
|
excludeShiftSpan = (Request.QueryString("excludeshift") = "1")
|
|
shiftFilter = ""
|
|
If excludeShiftSpan Then
|
|
shiftFilter = " AND mr.responseseconds < 1800"
|
|
End If
|
|
|
|
' Default date range: last 30 days
|
|
If filterStart = "" Then filterStart = Year(DateAdd("d", -30, Date())) & "-" & Right("0" & Month(DateAdd("d", -30, Date())), 2) & "-" & Right("0" & Day(DateAdd("d", -30, Date())), 2)
|
|
If filterEnd = "" Then filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
|
|
|
|
' Period shortcuts
|
|
Dim periodLabel
|
|
If periodFilter = "today" Then
|
|
filterStart = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
|
|
filterEnd = filterStart
|
|
periodLabel = "Today"
|
|
ElseIf periodFilter = "week" Then
|
|
filterStart = Year(DateAdd("d", -7, Date())) & "-" & Right("0" & Month(DateAdd("d", -7, Date())), 2) & "-" & Right("0" & Day(DateAdd("d", -7, Date())), 2)
|
|
filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
|
|
periodLabel = "This Week"
|
|
ElseIf periodFilter = "month" Then
|
|
filterStart = Year(DateAdd("d", -30, Date())) & "-" & Right("0" & Month(DateAdd("d", -30, Date())), 2) & "-" & Right("0" & Day(DateAdd("d", -30, Date())), 2)
|
|
filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
|
|
periodLabel = "This Month"
|
|
Else
|
|
periodLabel = "Custom Range"
|
|
End If
|
|
%>
|
|
<body class="bg-theme <%=Server.HTMLEncode(theme)%>">
|
|
|
|
<!-- start loader -->
|
|
<div id="pageloader-overlay" class="visible incoming"><div class="loader-wrapper-outer"><div class="loader-wrapper-inner"><div class="loader"></div></div></div></div>
|
|
|
|
<div id="wrapper">
|
|
<!--#include file="./includes/leftsidebar.asp"-->
|
|
<!--#include file="./includes/topbarheader.asp"-->
|
|
<div class="clearfix"></div>
|
|
|
|
<div class="content-wrapper">
|
|
<div class="container-fluid">
|
|
|
|
<!-- Page Header -->
|
|
<div class="row mt-3">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header" style="background: linear-gradient(45deg, #667eea 0%, #764ba2 100%); color: white;">
|
|
<h5 class="mb-0">UDC Performance Dashboard</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<!-- Filter Controls -->
|
|
<form id="udcFilterForm" method="get" class="mb-0">
|
|
<div class="row">
|
|
<div class="col-md-2">
|
|
<label class="small">Quick Range</label>
|
|
<select name="period" class="form-control form-control-sm" onchange="this.form.submit()">
|
|
<option value="">Custom</option>
|
|
<option value="today" <%If periodFilter="today" Then Response.Write("selected")%>>Today</option>
|
|
<option value="week" <%If periodFilter="week" Then Response.Write("selected")%>>This Week</option>
|
|
<option value="month" <%If periodFilter="month" Then Response.Write("selected")%>>This Month</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="small">Start Date</label>
|
|
<input type="date" name="startdate" class="form-control form-control-sm" value="<%=Server.HTMLEncode(filterStart)%>">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="small">End Date</label>
|
|
<input type="date" name="enddate" class="form-control form-control-sm" value="<%=Server.HTMLEncode(filterEnd)%>">
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="small">Business Unit</label>
|
|
<select name="bu" id="buFilter" class="form-control form-control-sm" onchange="this.form.submit()">
|
|
<option value="">All BUs</option>
|
|
<%
|
|
' Get list of business units with UDC machines
|
|
Dim rsBUs
|
|
Set rsBUs = objConn.Execute("SELECT DISTINCT b.businessunitid, b.businessunit FROM businessunits b " & _
|
|
"JOIN machines m ON m.businessunitid = b.businessunitid " & _
|
|
"JOIN udcsessions s ON m.machinenumber = s.machinenumber " & _
|
|
"ORDER BY b.businessunit")
|
|
Do While Not rsBUs.EOF
|
|
Response.Write("<option value=""" & Server.HTMLEncode(rsBUs("businessunitid") & "") & """")
|
|
If filterBU = rsBUs("businessunitid") & "" Then Response.Write(" selected")
|
|
Response.Write(">" & Server.HTMLEncode(rsBUs("businessunit") & "") & "</option>")
|
|
rsBUs.MoveNext
|
|
Loop
|
|
rsBUs.Close
|
|
Set rsBUs = Nothing
|
|
%>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="small">Machine</label>
|
|
<select name="machine" class="form-control form-control-sm">
|
|
<option value="">All Machines</option>
|
|
<%
|
|
' Get list of machines with UDC data, filtered by BU if selected
|
|
Dim rsMachines, machineSQL
|
|
machineSQL = "SELECT DISTINCT s.machinenumber FROM udcsessions s " & _
|
|
"JOIN machines m ON m.machinenumber = s.machinenumber "
|
|
If filterBU <> "" Then
|
|
machineSQL = machineSQL & "WHERE m.businessunitid = " & CLng(filterBU) & " "
|
|
End If
|
|
machineSQL = machineSQL & "ORDER BY s.machinenumber"
|
|
Set rsMachines = objConn.Execute(machineSQL)
|
|
Do While Not rsMachines.EOF
|
|
Response.Write("<option value=""" & Server.HTMLEncode(rsMachines("machinenumber") & "") & """")
|
|
If filterMachine = rsMachines("machinenumber") & "" Then Response.Write(" selected")
|
|
Response.Write(">" & Server.HTMLEncode(rsMachines("machinenumber") & "") & "</option>")
|
|
rsMachines.MoveNext
|
|
Loop
|
|
rsMachines.Close
|
|
Set rsMachines = Nothing
|
|
%>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="small">Operator Badge</label>
|
|
<select name="badge" class="form-control form-control-sm">
|
|
<option value="">All Operators</option>
|
|
<%
|
|
' Get list of operators
|
|
Dim rsBadges
|
|
Set rsBadges = objConn.Execute("SELECT DISTINCT badgenumber FROM udcparts WHERE badgenumber IS NOT NULL AND badgenumber != '' ORDER BY badgenumber")
|
|
Do While Not rsBadges.EOF
|
|
Response.Write("<option value=""" & Server.HTMLEncode(rsBadges("badgenumber") & "") & """")
|
|
If filterBadge = rsBadges("badgenumber") & "" Then Response.Write(" selected")
|
|
Response.Write(">" & Server.HTMLEncode(rsBadges("badgenumber") & "") & "</option>")
|
|
rsBadges.MoveNext
|
|
Loop
|
|
rsBadges.Close
|
|
Set rsBadges = Nothing
|
|
%>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2 d-flex align-items-end">
|
|
<button type="submit" class="btn btn-primary btn-sm mr-2">Filter</button>
|
|
<a href="displayudc.asp" class="btn btn-secondary btn-sm">Clear</a>
|
|
</div>
|
|
</div>
|
|
<div class="row mt-2">
|
|
<div class="col-12">
|
|
<div class="form-check form-check-inline">
|
|
<input type="checkbox" class="form-check-input" id="excludeshift" name="excludeshift" value="1" <%If excludeShiftSpan Then Response.Write("checked")%>>
|
|
<label class="form-check-label small" for="excludeshift">Exclude idle time (removes responses over 30 min)</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<input type="hidden" name="tab" id="activeTabInput" value="<%=Server.HTMLEncode(activeTab)%>">
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Summary Cards Row -->
|
|
<%
|
|
' Build WHERE clause for filters
|
|
Dim whereClause
|
|
whereClause = " WHERE p.programstart >= '" & Replace(filterStart, "'", "''") & "' " & _
|
|
" AND p.programstart <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
|
|
|
|
If filterMachine <> "" Then
|
|
whereClause = whereClause & " AND s.machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
|
|
End If
|
|
If filterBU <> "" Then
|
|
whereClause = whereClause & " AND s.machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
|
|
End If
|
|
If filterBadge <> "" Then
|
|
whereClause = whereClause & " AND p.badgenumber = '" & Replace(filterBadge, "'", "''") & "'"
|
|
End If
|
|
If filterPart <> "" Then
|
|
whereClause = whereClause & " AND p.partnumber LIKE '%" & Replace(filterPart, "'", "''") & "%'"
|
|
End If
|
|
|
|
' Get summary statistics
|
|
Dim rsSummary, totalParts, totalOOT, partsWithOOT, avgCycleTime, avgManualTime, ootRate, strSQL2, ootCardClass
|
|
strSQL2 = "SELECT COUNT(*) as totalparts, " & _
|
|
"SUM(ootcount) as totaloot, " & _
|
|
"SUM(CASE WHEN ootcount > 0 THEN 1 ELSE 0 END) as partswithoot, " & _
|
|
"AVG(cycletime) as avgcycle, " & _
|
|
"SUM(manualcount) as totalmanual " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & whereClause
|
|
|
|
Set rsSummary = objConn.Execute(strSQL2)
|
|
If Not rsSummary.EOF Then
|
|
If IsNull(rsSummary("totalparts")) Then totalParts = 0 Else totalParts = CLng(rsSummary("totalparts"))
|
|
If IsNull(rsSummary("totaloot")) Then totalOOT = 0 Else totalOOT = CLng(rsSummary("totaloot"))
|
|
If IsNull(rsSummary("partswithoot")) Then partsWithOOT = 0 Else partsWithOOT = CLng(rsSummary("partswithoot"))
|
|
If Not IsNull(rsSummary("avgcycle")) Then
|
|
avgCycleTime = FormatNumber(CDbl(rsSummary("avgcycle")) / 60, 1)
|
|
Else
|
|
avgCycleTime = "0"
|
|
End If
|
|
If totalParts > 0 Then
|
|
ootRate = FormatNumber(CDbl(partsWithOOT) / CDbl(totalParts) * 100, 1)
|
|
Else
|
|
ootRate = "0"
|
|
End If
|
|
Else
|
|
totalParts = 0
|
|
totalOOT = 0
|
|
partsWithOOT = 0
|
|
avgCycleTime = "0"
|
|
ootRate = "0"
|
|
End If
|
|
rsSummary.Close
|
|
Set rsSummary = Nothing
|
|
|
|
' Get avg manual response time
|
|
Dim rsManual, avgManualResp
|
|
strSQL2 = "SELECT AVG(mr.responseseconds) as avgresponse " & _
|
|
"FROM udcmanualrequests mr " & _
|
|
"JOIN udcparts p ON mr.partrunid = p.partrunid " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & whereClause & shiftFilter
|
|
Set rsManual = objConn.Execute(strSQL2)
|
|
If Not rsManual.EOF And Not IsNull(rsManual("avgresponse")) Then
|
|
avgManualResp = FormatNumber(CDbl(rsManual("avgresponse")), 0)
|
|
Else
|
|
avgManualResp = "0"
|
|
End If
|
|
rsManual.Close
|
|
Set rsManual = Nothing
|
|
|
|
%>
|
|
|
|
<!-- Summary Cards -->
|
|
<div class="row mt-3">
|
|
<div class="col-lg-3 col-md-6">
|
|
<div class="card bg-success text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="media-body">
|
|
<h4 class="mb-0"><%=totalParts%></h4>
|
|
<span>Total Parts Produced</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-3 col-md-6">
|
|
<div class="card bg-info text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="media-body">
|
|
<h4 class="mb-0"><%=avgCycleTime%>m</h4>
|
|
<span>Avg Cycle Time</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-3 col-md-6">
|
|
<%
|
|
If CDbl(ootRate) > 5 Then
|
|
ootCardClass = "bg-danger"
|
|
ElseIf CDbl(ootRate) > 0 Then
|
|
ootCardClass = "bg-warning"
|
|
Else
|
|
ootCardClass = "bg-success"
|
|
End If
|
|
%>
|
|
<div class="card <%=ootCardClass%> text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="media-body">
|
|
<h4 class="mb-0"><%=ootRate%>%</h4>
|
|
<span>Parts with OOT (<%=partsWithOOT%> of <%=totalParts%>)</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-3 col-md-6">
|
|
<div class="card bg-primary text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<div class="media-body">
|
|
<h4 class="mb-0"><%=avgManualResp%>s</h4>
|
|
<span>Avg Manual Response</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<%
|
|
' ============================================================================
|
|
' DASHBOARD CHARTS DATA QUERIES
|
|
' ============================================================================
|
|
|
|
' Chart 1: Production Trend (daily parts for date range)
|
|
Dim rsProductionTrend, prodLabels, prodData, prodDate
|
|
prodLabels = ""
|
|
prodData = ""
|
|
strSQL2 = "SELECT DATE_FORMAT(DATE(p.programstart), '%m/%d') as day_label, COUNT(*) as parts " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" GROUP BY DATE(p.programstart) ORDER BY DATE(p.programstart) ASC"
|
|
Set rsProductionTrend = objConn.Execute(strSQL2)
|
|
Do While Not rsProductionTrend.EOF
|
|
prodDate = rsProductionTrend("day_label") & ""
|
|
If prodLabels <> "" Then prodLabels = prodLabels & ","
|
|
If prodData <> "" Then prodData = prodData & ","
|
|
prodLabels = prodLabels & """" & prodDate & """"
|
|
prodData = prodData & rsProductionTrend("parts")
|
|
rsProductionTrend.MoveNext
|
|
Loop
|
|
rsProductionTrend.Close
|
|
Set rsProductionTrend = Nothing
|
|
If prodLabels = "" Then prodLabels = """No Data"""
|
|
If prodData = "" Then prodData = "0"
|
|
|
|
' Chart 2: OOT Rate Trend (daily OOT rate for date range)
|
|
Dim rsOOTTrend, ootLabels, ootRateData, ootCountData, ootDay, dayRate
|
|
ootLabels = ""
|
|
ootRateData = ""
|
|
ootCountData = ""
|
|
strSQL2 = "SELECT DATE_FORMAT(DATE(p.programstart), '%m/%d') as day_label, " & _
|
|
"SUM(p.ootcount) as oot_count, COUNT(*) as total_parts, " & _
|
|
"ROUND(SUM(p.ootcount)*100.0/COUNT(*), 1) as oot_rate " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" GROUP BY DATE(p.programstart) ORDER BY DATE(p.programstart) ASC"
|
|
Set rsOOTTrend = objConn.Execute(strSQL2)
|
|
Do While Not rsOOTTrend.EOF
|
|
ootDay = rsOOTTrend("day_label") & ""
|
|
If ootLabels <> "" Then ootLabels = ootLabels & ","
|
|
If ootRateData <> "" Then ootRateData = ootRateData & ","
|
|
If ootCountData <> "" Then ootCountData = ootCountData & ","
|
|
ootLabels = ootLabels & """" & ootDay & """"
|
|
If IsNull(rsOOTTrend("oot_rate")) Then
|
|
dayRate = "0"
|
|
Else
|
|
dayRate = rsOOTTrend("oot_rate") & ""
|
|
End If
|
|
ootRateData = ootRateData & dayRate
|
|
ootCountData = ootCountData & (rsOOTTrend("oot_count") & "0")
|
|
rsOOTTrend.MoveNext
|
|
Loop
|
|
rsOOTTrend.Close
|
|
Set rsOOTTrend = Nothing
|
|
If ootLabels = "" Then ootLabels = """No Data"""
|
|
If ootRateData = "" Then ootRateData = "0"
|
|
If ootCountData = "" Then ootCountData = "0"
|
|
|
|
' Chart 3: Machine Utilization (top 10 by runtime hours)
|
|
Dim rsMachineUtil, machLabels, machData, machHours
|
|
machLabels = ""
|
|
machData = ""
|
|
strSQL2 = "SELECT s.machinenumber, ROUND(SUM(p.cycletime)/3600, 1) as runtime_hours " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" AND p.cycletime IS NOT NULL AND p.cycletime > 0 " & _
|
|
"GROUP BY s.machinenumber ORDER BY runtime_hours DESC LIMIT 10"
|
|
Set rsMachineUtil = objConn.Execute(strSQL2)
|
|
Do While Not rsMachineUtil.EOF
|
|
If machLabels <> "" Then machLabels = machLabels & ","
|
|
If machData <> "" Then machData = machData & ","
|
|
machLabels = machLabels & """" & (rsMachineUtil("machinenumber") & "") & """"
|
|
If IsNull(rsMachineUtil("runtime_hours")) Then
|
|
machHours = "0"
|
|
Else
|
|
machHours = rsMachineUtil("runtime_hours") & ""
|
|
End If
|
|
machData = machData & machHours
|
|
rsMachineUtil.MoveNext
|
|
Loop
|
|
rsMachineUtil.Close
|
|
Set rsMachineUtil = Nothing
|
|
If machLabels = "" Then machLabels = """No Data"""
|
|
If machData = "" Then machData = "0"
|
|
|
|
' Chart 4: Top Operators (top 10 by parts produced)
|
|
Dim rsTopOps, opLabels, opData
|
|
opLabels = ""
|
|
opData = ""
|
|
strSQL2 = "SELECT p.badgenumber, COUNT(*) as parts_count " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" AND p.badgenumber IS NOT NULL AND p.badgenumber != '' " & _
|
|
"GROUP BY p.badgenumber ORDER BY parts_count DESC LIMIT 10"
|
|
Set rsTopOps = objConn.Execute(strSQL2)
|
|
Do While Not rsTopOps.EOF
|
|
If opLabels <> "" Then opLabels = opLabels & ","
|
|
If opData <> "" Then opData = opData & ","
|
|
opLabels = opLabels & """" & (rsTopOps("badgenumber") & "") & """"
|
|
opData = opData & rsTopOps("parts_count")
|
|
rsTopOps.MoveNext
|
|
Loop
|
|
rsTopOps.Close
|
|
Set rsTopOps = Nothing
|
|
If opLabels = "" Then opLabels = """No Data"""
|
|
If opData = "" Then opData = "0"
|
|
%>
|
|
|
|
<!-- Tabbed Content Area -->
|
|
<div class="row mt-3">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<ul class="nav nav-tabs nav-tabs-primary" id="udcTabs">
|
|
<li class="nav-item">
|
|
<a href="#dashboard" data-toggle="tab" class="nav-link<%If activeTab="dashboard" Then Response.Write(" active")%>" onclick="setActiveTab('dashboard')"><i class="zmdi zmdi-chart"></i> Dashboard</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#liveactivity" data-toggle="tab" class="nav-link<%If activeTab="liveactivity" Then Response.Write(" active")%>" onclick="setActiveTab('liveactivity')"><i class="zmdi zmdi-dot-circle text-success"></i> Live Activity</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#operators" data-toggle="tab" class="nav-link<%If activeTab="operators" Then Response.Write(" active")%>" onclick="setActiveTab('operators')">Operators</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#machines" data-toggle="tab" class="nav-link<%If activeTab="machines" Then Response.Write(" active")%>" onclick="setActiveTab('machines')">Machines</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#parts" data-toggle="tab" class="nav-link<%If activeTab="parts" Then Response.Write(" active")%>" onclick="setActiveTab('parts')">Parts</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#quality" data-toggle="tab" class="nav-link<%If activeTab="quality" Then Response.Write(" active")%>" onclick="setActiveTab('quality')">Quality/OOT</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#timing" data-toggle="tab" class="nav-link<%If activeTab="timing" Then Response.Write(" active")%>" onclick="setActiveTab('timing')">Timing</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#activitylog" data-toggle="tab" class="nav-link<%If activeTab="activitylog" Then Response.Write(" active")%>" onclick="setActiveTab('activitylog')">Activity Log</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#toolhealth" data-toggle="tab" class="nav-link<%If activeTab="toolhealth" Then Response.Write(" active")%>" onclick="setActiveTab('toolhealth')">Tool Health</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#uptime" data-toggle="tab" class="nav-link<%If activeTab="uptime" Then Response.Write(" active")%>" onclick="setActiveTab('uptime')">Uptime</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a href="#itdiagnostics" data-toggle="tab" class="nav-link<%If activeTab="itdiagnostics" Then Response.Write(" active")%>" onclick="setActiveTab('itdiagnostics')">IT Diagnostics</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<div class="tab-content p-3">
|
|
<!-- Tab: Dashboard (Charts) -->
|
|
<div class="tab-pane<%If activeTab="dashboard" Then Response.Write(" active")%>" id="dashboard">
|
|
<h5 class="mb-3"><i class="zmdi zmdi-chart"></i> UDC Performance Dashboard</h5>
|
|
|
|
<!-- Charts Row 1 -->
|
|
<div class="row">
|
|
<div class="col-lg-6 mb-3">
|
|
<div class="card">
|
|
<div class="card-header bg-gradient-primary text-white py-2">
|
|
<i class="zmdi zmdi-trending-up"></i> Production Trend
|
|
</div>
|
|
<div class="card-body">
|
|
<div style="height: 220px;">
|
|
<canvas id="productionChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6 mb-3">
|
|
<div class="card">
|
|
<div class="card-header bg-gradient-danger text-white py-2">
|
|
<i class="zmdi zmdi-alert-triangle"></i> OOT Rate Trend
|
|
</div>
|
|
<div class="card-body">
|
|
<div style="height: 220px;">
|
|
<canvas id="ootChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Charts Row 2 -->
|
|
<div class="row">
|
|
<div class="col-lg-6 mb-3">
|
|
<div class="card">
|
|
<div class="card-header bg-gradient-info text-white py-2">
|
|
<i class="zmdi zmdi-time"></i> Machine Utilization (Hours)
|
|
</div>
|
|
<div class="card-body">
|
|
<div style="height: 220px;">
|
|
<canvas id="machineChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6 mb-3">
|
|
<div class="card">
|
|
<div class="card-header bg-gradient-success text-white py-2">
|
|
<i class="zmdi zmdi-accounts"></i> Top Operators (Parts)
|
|
</div>
|
|
<div class="card-body">
|
|
<div style="height: 220px;">
|
|
<canvas id="operatorChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab: Live Activity -->
|
|
<div class="tab-pane<%If activeTab="liveactivity" Then Response.Write(" active")%>" id="liveactivity">
|
|
<h5 class="mb-3"><i class="zmdi zmdi-dot-circle text-success"></i> Active Machines <span class="badge badge-success">Live</span></h5>
|
|
<p class="text-muted small mb-3">Machines currently running jobs. Data refreshes when page loads.</p>
|
|
<%
|
|
' Get active sessions with optional machine/BU filter
|
|
Dim rsActive, activeCount, activeWhereClause
|
|
activeWhereClause = ""
|
|
If filterMachine <> "" Then
|
|
activeWhereClause = " WHERE a.machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
|
|
ElseIf filterBU <> "" Then
|
|
activeWhereClause = " WHERE a.machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
|
|
End If
|
|
strSQL2 = "SELECT a.machinenumber, a.partnumber, a.badgenumber, a.partsrun, a.lastupdate, a.sessionstart, " & _
|
|
"TIMESTAMPDIFF(MINUTE, a.sessionstart, NOW()) as runtime_minutes " & _
|
|
"FROM udcactivesessions a" & activeWhereClause & " ORDER BY a.lastupdate DESC"
|
|
Set rsActive = objConn.Execute(strSQL2)
|
|
activeCount = 0
|
|
|
|
If rsActive.EOF Then
|
|
%>
|
|
<div class="alert alert-secondary text-center">
|
|
<i class="zmdi zmdi-info-outline"></i> No active jobs detected
|
|
</div>
|
|
<%
|
|
Else
|
|
%>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped" id="activeTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Machine</th>
|
|
<th>Part Number</th>
|
|
<th>Operator Badge</th>
|
|
<th>Parts Run</th>
|
|
<th>Runtime</th>
|
|
<th>Session Start</th>
|
|
<th>Last Activity</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
Dim runtimeMinutes, runtimeDisplay
|
|
Do While Not rsActive.EOF
|
|
activeCount = activeCount + 1
|
|
runtimeMinutes = rsActive("runtime_minutes")
|
|
If IsNull(runtimeMinutes) Or runtimeMinutes = "" Then
|
|
runtimeDisplay = "-"
|
|
ElseIf CLng(runtimeMinutes) >= 60 Then
|
|
runtimeDisplay = Int(CLng(runtimeMinutes) / 60) & "h " & (CLng(runtimeMinutes) Mod 60) & "m"
|
|
Else
|
|
runtimeDisplay = CLng(runtimeMinutes) & "m"
|
|
End If
|
|
Response.Write("<tr>")
|
|
Response.Write("<td><a href='displaymachine.asp?machinenumber=" & Server.URLEncode(rsActive("machinenumber") & "") & "'><strong>" & Server.HTMLEncode(rsActive("machinenumber") & "") & "</strong></a></td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsActive("partnumber") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsActive("badgenumber") & "") & "</td>")
|
|
Response.Write("<td><span class='badge badge-info'>" & rsActive("partsrun") & "</span></td>")
|
|
Response.Write("<td>" & runtimeDisplay & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsActive("sessionstart") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsActive("lastupdate") & "") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsActive.MoveNext
|
|
Loop
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<p class="text-muted small mt-2 mb-0"><strong><%=activeCount%></strong> machine(s) currently active</p>
|
|
<%
|
|
End If
|
|
rsActive.Close
|
|
Set rsActive = Nothing
|
|
%>
|
|
</div>
|
|
|
|
<!-- Tab: Operator Performance -->
|
|
<div class="tab-pane<%If activeTab="operators" Then Response.Write(" active")%>" id="operators">
|
|
<h5 class="mb-3">Operator Performance Leaderboard</h5>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped" id="operatorTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Badge #</th>
|
|
<th>Parts Run</th>
|
|
<th>Avg Cycle (min)</th>
|
|
<th>Avg Manual Response (sec)</th>
|
|
<th>Last Active</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get operator stats
|
|
Dim rsOperators, opCycle, opManual, opRowNum, opRowStyle
|
|
strSQL2 = "SELECT p.badgenumber, COUNT(*) as partsrun, " & _
|
|
"AVG(p.cycletime) as avgcycle, " & _
|
|
"MAX(p.programend) as lastactive, " & _
|
|
"(SELECT AVG(mr.responseseconds) FROM udcmanualrequests mr " & _
|
|
" JOIN udcparts p2 ON mr.partrunid = p2.partrunid WHERE p2.badgenumber = p.badgenumber) as avgmanual " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" AND p.badgenumber IS NOT NULL AND p.badgenumber != '' " & _
|
|
"GROUP BY p.badgenumber ORDER BY partsrun DESC, p.badgenumber ASC"
|
|
Set rsOperators = objConn.Execute(strSQL2)
|
|
opRowNum = 0
|
|
If rsOperators.EOF Then
|
|
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No operator data found</td></tr>")
|
|
Else
|
|
Do While Not rsOperators.EOF
|
|
opRowNum = opRowNum + 1
|
|
If Not IsNull(rsOperators("avgcycle")) Then
|
|
opCycle = FormatNumber(CDbl(rsOperators("avgcycle")) / 60, 1)
|
|
Else
|
|
opCycle = "-"
|
|
End If
|
|
If Not IsNull(rsOperators("avgmanual")) Then
|
|
opManual = FormatNumber(CDbl(rsOperators("avgmanual")), 0)
|
|
Else
|
|
opManual = "-"
|
|
End If
|
|
|
|
' Highlight top 3 performers
|
|
opRowStyle = ""
|
|
If opRowNum = 1 Then
|
|
opRowStyle = "background-color:#28a745; color:#fff;"
|
|
ElseIf opRowNum = 2 Then
|
|
opRowStyle = "background-color:#20c997; color:#fff;"
|
|
ElseIf opRowNum = 3 Then
|
|
opRowStyle = "background-color:#17a2b8; color:#fff;"
|
|
End If
|
|
|
|
Response.Write("<tr style='" & opRowStyle & "'>")
|
|
Response.Write("<td><a href='displayudc.asp?badge=" & Server.URLEncode(rsOperators("badgenumber") & "") & "' style='color:inherit;'>" & Server.HTMLEncode(rsOperators("badgenumber") & "") & "</a></td>")
|
|
Response.Write("<td>" & rsOperators("partsrun") & "</td>")
|
|
Response.Write("<td>" & opCycle & "</td>")
|
|
Response.Write("<td>" & opManual & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsOperators("lastactive") & "") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsOperators.MoveNext
|
|
Loop
|
|
End If
|
|
rsOperators.Close
|
|
Set rsOperators = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab 2: Machine Performance -->
|
|
<div class="tab-pane<%If activeTab="machines" Then Response.Write(" active")%>" id="machines">
|
|
<h5 class="mb-3">Machine Performance Comparison</h5>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped" id="machineTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Machine #</th>
|
|
<th>Parts Run</th>
|
|
<th>Avg Cycle (min)</th>
|
|
<th>Avg Changeover (min)</th>
|
|
<th>Parts with OOT</th>
|
|
<th>OOT Rate</th>
|
|
<th>Last Run</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get machine stats
|
|
Dim rsMachStats, machCycle, machChange, machOOTRate, machOOTBadge, machPartsWithOOT
|
|
strSQL2 = "SELECT s.machinenumber, COUNT(*) as partsrun, " & _
|
|
"AVG(p.cycletime) as avgcycle, " & _
|
|
"AVG(p.changeover) as avgchangeover, " & _
|
|
"SUM(CASE WHEN p.ootcount > 0 THEN 1 ELSE 0 END) as partswithoot, " & _
|
|
"MAX(p.programend) as lastrun " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" GROUP BY s.machinenumber ORDER BY partsrun DESC, s.machinenumber ASC"
|
|
Set rsMachStats = objConn.Execute(strSQL2)
|
|
If rsMachStats.EOF Then
|
|
Response.Write("<tr><td colspan='7' class='text-muted text-center'>No machine data found</td></tr>")
|
|
Else
|
|
Do While Not rsMachStats.EOF
|
|
If Not IsNull(rsMachStats("avgcycle")) Then
|
|
machCycle = FormatNumber(CDbl(rsMachStats("avgcycle")) / 60, 1)
|
|
Else
|
|
machCycle = "-"
|
|
End If
|
|
If Not IsNull(rsMachStats("avgchangeover")) Then
|
|
machChange = FormatNumber(CDbl(rsMachStats("avgchangeover")) / 60, 1)
|
|
Else
|
|
machChange = "-"
|
|
End If
|
|
machPartsWithOOT = CLng("0" & rsMachStats("partswithoot"))
|
|
If CLng("0" & rsMachStats("partsrun")) > 0 Then
|
|
machOOTRate = FormatNumber(CDbl(machPartsWithOOT) / CDbl(rsMachStats("partsrun")) * 100, 2)
|
|
Else
|
|
machOOTRate = "0"
|
|
End If
|
|
If CDbl(machOOTRate) > 5 Then
|
|
machOOTBadge = "<span class='badge badge-danger'>" & machOOTRate & "%</span>"
|
|
ElseIf CDbl(machOOTRate) > 0 Then
|
|
machOOTBadge = "<span class='badge badge-warning'>" & machOOTRate & "%</span>"
|
|
Else
|
|
machOOTBadge = "<span class='badge badge-success'>" & machOOTRate & "%</span>"
|
|
End If
|
|
|
|
Response.Write("<tr>")
|
|
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsMachStats("machinenumber") & "") & "'>" & Server.HTMLEncode(rsMachStats("machinenumber") & "") & "</a></td>")
|
|
Response.Write("<td>" & rsMachStats("partsrun") & "</td>")
|
|
Response.Write("<td>" & machCycle & "</td>")
|
|
Response.Write("<td>" & machChange & "</td>")
|
|
Response.Write("<td>" & machPartsWithOOT & "</td>")
|
|
Response.Write("<td>" & machOOTBadge & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsMachStats("lastrun") & "") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsMachStats.MoveNext
|
|
Loop
|
|
End If
|
|
rsMachStats.Close
|
|
Set rsMachStats = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab 3: Part Analysis -->
|
|
<div class="tab-pane<%If activeTab="parts" Then Response.Write(" active")%>" id="parts">
|
|
<h5 class="mb-3">Part Number Analysis</h5>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped" id="partsTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Part #</th>
|
|
<th>Count</th>
|
|
<th>Avg Cycle (min)</th>
|
|
<th>Parts with OOT</th>
|
|
<th>OOT Rate</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get part stats
|
|
Dim rsPartStats, partCycle, partOOTRate, partOOTBadge, partPartsWithOOT
|
|
strSQL2 = "SELECT p.partnumber, COUNT(*) as cnt, " & _
|
|
"AVG(p.cycletime) as avgcycle, " & _
|
|
"SUM(CASE WHEN p.ootcount > 0 THEN 1 ELSE 0 END) as partswithoot " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" AND p.partnumber IS NOT NULL AND p.partnumber != '' " & _
|
|
"GROUP BY p.partnumber ORDER BY partswithoot DESC, cnt DESC, p.partnumber ASC LIMIT 50"
|
|
Set rsPartStats = objConn.Execute(strSQL2)
|
|
If rsPartStats.EOF Then
|
|
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No part data found</td></tr>")
|
|
Else
|
|
Do While Not rsPartStats.EOF
|
|
If Not IsNull(rsPartStats("avgcycle")) Then
|
|
partCycle = FormatNumber(CDbl(rsPartStats("avgcycle")) / 60, 1)
|
|
Else
|
|
partCycle = "-"
|
|
End If
|
|
partPartsWithOOT = CLng("0" & rsPartStats("partswithoot"))
|
|
If CLng("0" & rsPartStats("cnt")) > 0 Then
|
|
partOOTRate = FormatNumber(CDbl(partPartsWithOOT) / CDbl(rsPartStats("cnt")) * 100, 2)
|
|
Else
|
|
partOOTRate = "0"
|
|
End If
|
|
If CDbl(partOOTRate) > 5 Then
|
|
partOOTBadge = "<span class='badge badge-danger'>" & partOOTRate & "%</span>"
|
|
ElseIf CDbl(partOOTRate) > 0 Then
|
|
partOOTBadge = "<span class='badge badge-warning'>" & partOOTRate & "%</span>"
|
|
Else
|
|
partOOTBadge = "<span class='badge badge-success'>0%</span>"
|
|
End If
|
|
|
|
Response.Write("<tr>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsPartStats("partnumber") & "") & "</td>")
|
|
Response.Write("<td>" & rsPartStats("cnt") & "</td>")
|
|
Response.Write("<td>" & partCycle & "</td>")
|
|
Response.Write("<td>" & partPartsWithOOT & "</td>")
|
|
Response.Write("<td>" & partOOTBadge & "</td>")
|
|
Response.Write("</tr>")
|
|
rsPartStats.MoveNext
|
|
Loop
|
|
End If
|
|
rsPartStats.Close
|
|
Set rsPartStats = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab 4: Quality/OOT Analysis -->
|
|
<div class="tab-pane<%If activeTab="quality" Then Response.Write(" active")%>" id="quality">
|
|
<h5 class="mb-3">Out-of-Tolerance Analysis</h5>
|
|
|
|
<!-- OOT Summary by Machine -->
|
|
<h6 class="mt-3 mb-2">OOT by Machine</h6>
|
|
<div class="table-responsive mb-4">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Machine</th>
|
|
<th>Parts with OOT</th>
|
|
<th>Parts Run</th>
|
|
<th>OOT Rate</th>
|
|
<th style="width:40%">Bar</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get OOT by Machine
|
|
Dim rsOOTMach, maxOOT, ootMachRate, barWidth, ootMachParts
|
|
maxOOT = 1
|
|
strSQL2 = "SELECT s.machinenumber, SUM(CASE WHEN p.ootcount > 0 THEN 1 ELSE 0 END) as partswithoot, COUNT(*) as partsrun " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" GROUP BY s.machinenumber ORDER BY partswithoot DESC, s.machinenumber ASC LIMIT 10"
|
|
Set rsOOTMach = objConn.Execute(strSQL2)
|
|
If rsOOTMach.EOF Then
|
|
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No OOT data found</td></tr>")
|
|
Else
|
|
' Find max for bar scaling
|
|
Do While Not rsOOTMach.EOF
|
|
If CLng("0" & rsOOTMach("partswithoot")) > maxOOT Then maxOOT = CLng("0" & rsOOTMach("partswithoot"))
|
|
rsOOTMach.MoveNext
|
|
Loop
|
|
rsOOTMach.Close
|
|
Set rsOOTMach = objConn.Execute(strSQL2)
|
|
|
|
Do While Not rsOOTMach.EOF
|
|
ootMachParts = CLng("0" & rsOOTMach("partswithoot"))
|
|
If CLng("0" & rsOOTMach("partsrun")) > 0 Then
|
|
ootMachRate = FormatNumber(CDbl(ootMachParts) / CDbl(rsOOTMach("partsrun")) * 100, 2)
|
|
Else
|
|
ootMachRate = "0"
|
|
End If
|
|
barWidth = Int((ootMachParts / maxOOT) * 100)
|
|
|
|
Response.Write("<tr>")
|
|
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsOOTMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsOOTMach("machinenumber") & "") & "</a></td>")
|
|
Response.Write("<td>" & ootMachParts & "</td>")
|
|
Response.Write("<td>" & rsOOTMach("partsrun") & "</td>")
|
|
Response.Write("<td>" & ootMachRate & "%</td>")
|
|
Response.Write("<td><div style='background:#dc3545;height:20px;width:" & barWidth & "%;border-radius:3px;'></div></td>")
|
|
Response.Write("</tr>")
|
|
rsOOTMach.MoveNext
|
|
Loop
|
|
End If
|
|
rsOOTMach.Close
|
|
Set rsOOTMach = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Recent OOT Measurements -->
|
|
<h6 class="mt-4 mb-2">Recent OOT Measurements</h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Time</th>
|
|
<th>Machine</th>
|
|
<th>Part #</th>
|
|
<th>Dimension</th>
|
|
<th>Min</th>
|
|
<th>Actual</th>
|
|
<th>Max</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get recent OOT measurements
|
|
Dim rsOOT
|
|
strSQL2 = "SELECT m.eventtime, s.machinenumber, p.partnumber, m.dimid, m.description, " & _
|
|
"m.minval, m.actualval, m.maxval " & _
|
|
"FROM udcmeasurements m " & _
|
|
"JOIN udcparts p ON m.partrunid = p.partrunid " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" AND m.oot = 1 " & _
|
|
"ORDER BY m.eventtime DESC LIMIT 50"
|
|
Set rsOOT = objConn.Execute(strSQL2)
|
|
If rsOOT.EOF Then
|
|
Response.Write("<tr><td colspan='7' class='text-muted text-center'>No OOT measurements found</td></tr>")
|
|
Else
|
|
Do While Not rsOOT.EOF
|
|
Response.Write("<tr style='background-color:#dc3545; color:#fff;'>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsOOT("eventtime") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsOOT("machinenumber") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsOOT("partnumber") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsOOT("dimid") & "") & " - " & Server.HTMLEncode(rsOOT("description") & "") & "</td>")
|
|
Response.Write("<td>" & rsOOT("minval") & "</td>")
|
|
Response.Write("<td><strong>" & rsOOT("actualval") & "</strong></td>")
|
|
Response.Write("<td>" & rsOOT("maxval") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsOOT.MoveNext
|
|
Loop
|
|
End If
|
|
rsOOT.Close
|
|
Set rsOOT = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Best Performing Machines -->
|
|
<h6 class="mt-4 mb-2">Best Performing Machines (Lowest OOT Rates)</h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Machine</th>
|
|
<th>Parts Run</th>
|
|
<th>OOT Count</th>
|
|
<th>OOT Rate</th>
|
|
<th style="width:40%">Quality Bar</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get best performing machines (lowest OOT rate, min 10 parts)
|
|
Dim rsBestMach, bestRate, bestStyle, qualityWidth, bestPartsWithOOT
|
|
strSQL2 = "SELECT s.machinenumber, COUNT(*) as partsrun, " & _
|
|
"SUM(CASE WHEN p.ootcount > 0 THEN 1 ELSE 0 END) as partswithoot, " & _
|
|
"ROUND(SUM(CASE WHEN p.ootcount > 0 THEN 1 ELSE 0 END)/COUNT(*)*100, 2) as ootrate " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" GROUP BY s.machinenumber HAVING COUNT(*) >= 10 ORDER BY ootrate ASC, partsrun DESC, s.machinenumber ASC LIMIT 10"
|
|
Set rsBestMach = objConn.Execute(strSQL2)
|
|
If rsBestMach.EOF Then
|
|
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No machine data found (min 10 parts required)</td></tr>")
|
|
Else
|
|
Do While Not rsBestMach.EOF
|
|
bestPartsWithOOT = CLng("0" & rsBestMach("partswithoot"))
|
|
bestRate = CDbl("0" & rsBestMach("ootrate"))
|
|
qualityWidth = 100 - Int(bestRate)
|
|
If qualityWidth < 0 Then qualityWidth = 0
|
|
If qualityWidth > 100 Then qualityWidth = 100
|
|
|
|
If bestRate = 0 Then
|
|
bestStyle = "background-color:#28a745; color:#fff;"
|
|
ElseIf bestRate < 5 Then
|
|
bestStyle = "background-color:#20c997; color:#fff;"
|
|
Else
|
|
bestStyle = ""
|
|
End If
|
|
|
|
Response.Write("<tr style='" & bestStyle & "'>")
|
|
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsBestMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsBestMach("machinenumber") & "") & "</a></td>")
|
|
Response.Write("<td>" & rsBestMach("partsrun") & "</td>")
|
|
Response.Write("<td>" & bestPartsWithOOT & "</td>")
|
|
Response.Write("<td>" & bestRate & "%</td>")
|
|
Response.Write("<td><div style='background:#28a745;height:20px;width:" & qualityWidth & "%;border-radius:3px;'></div></td>")
|
|
Response.Write("</tr>")
|
|
rsBestMach.MoveNext
|
|
Loop
|
|
End If
|
|
rsBestMach.Close
|
|
Set rsBestMach = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab 5: Timing Analysis -->
|
|
<div class="tab-pane<%If activeTab="timing" Then Response.Write(" active")%>" id="timing">
|
|
<h5 class="mb-3">Timing Analysis</h5>
|
|
|
|
<!-- Manual Response Time by Operator -->
|
|
<h6 class="mt-3 mb-2">Manual Response Time by Operator</h6>
|
|
<div class="table-responsive mb-4">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Badge #</th>
|
|
<th>Requests</th>
|
|
<th>Avg Response (sec)</th>
|
|
<th>Max Response (sec)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get manual response time by operator
|
|
Dim rsManualOp, manAvg, manMax
|
|
strSQL2 = "SELECT p.badgenumber, COUNT(*) as requests, " & _
|
|
"AVG(mr.responseseconds) as avgresponse, " & _
|
|
"MAX(mr.responseseconds) as maxresponse " & _
|
|
"FROM udcmanualrequests mr " & _
|
|
"JOIN udcparts p ON mr.partrunid = p.partrunid " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" AND p.badgenumber IS NOT NULL AND p.badgenumber != ''" & shiftFilter & _
|
|
" GROUP BY p.badgenumber ORDER BY avgresponse ASC, p.badgenumber ASC"
|
|
Set rsManualOp = objConn.Execute(strSQL2)
|
|
If rsManualOp.EOF Then
|
|
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No manual request data found</td></tr>")
|
|
Else
|
|
Do While Not rsManualOp.EOF
|
|
If Not IsNull(rsManualOp("avgresponse")) Then
|
|
manAvg = FormatNumber(CDbl(rsManualOp("avgresponse")), 0)
|
|
Else
|
|
manAvg = "-"
|
|
End If
|
|
manMax = CLng("0" & rsManualOp("maxresponse"))
|
|
|
|
Response.Write("<tr>")
|
|
Response.Write("<td><a href='displayudc.asp?badge=" & Server.URLEncode(rsManualOp("badgenumber") & "") & "'>" & Server.HTMLEncode(rsManualOp("badgenumber") & "") & "</a></td>")
|
|
Response.Write("<td>" & rsManualOp("requests") & "</td>")
|
|
Response.Write("<td>" & manAvg & "</td>")
|
|
Response.Write("<td>" & manMax & "</td>")
|
|
Response.Write("</tr>")
|
|
rsManualOp.MoveNext
|
|
Loop
|
|
End If
|
|
rsManualOp.Close
|
|
Set rsManualOp = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Slowest Manual Responses -->
|
|
<h6 class="mt-4 mb-2">Slowest Manual Responses</h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Request Time</th>
|
|
<th>Machine</th>
|
|
<th>Badge</th>
|
|
<th>Description</th>
|
|
<th>Response Time (sec)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get slowest manual responses
|
|
Dim rsSlow, rowStyle
|
|
strSQL2 = "SELECT mr.requesttime, s.machinenumber, p.badgenumber, mr.description, mr.responseseconds " & _
|
|
"FROM udcmanualrequests mr " & _
|
|
"JOIN udcparts p ON mr.partrunid = p.partrunid " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & shiftFilter & _
|
|
" ORDER BY mr.responseseconds DESC LIMIT 25"
|
|
Set rsSlow = objConn.Execute(strSQL2)
|
|
If rsSlow.EOF Then
|
|
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No manual requests found</td></tr>")
|
|
Else
|
|
Do While Not rsSlow.EOF
|
|
If CLng("0" & rsSlow("responseseconds")) > 300 Then
|
|
rowStyle = "background-color:#dc3545; color:#fff;"
|
|
ElseIf CLng("0" & rsSlow("responseseconds")) > 120 Then
|
|
rowStyle = "background-color:#ffc107; color:#333;"
|
|
Else
|
|
rowStyle = ""
|
|
End If
|
|
Response.Write("<tr style='" & rowStyle & "'>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsSlow("requesttime") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsSlow("machinenumber") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsSlow("badgenumber") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsSlow("description") & "") & "</td>")
|
|
Response.Write("<td>" & rsSlow("responseseconds") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsSlow.MoveNext
|
|
Loop
|
|
End If
|
|
rsSlow.Close
|
|
Set rsSlow = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Fastest Manual Responses -->
|
|
<h6 class="mt-4 mb-2">Fastest Responses (Top Performers)</h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Request Time</th>
|
|
<th>Machine</th>
|
|
<th>Badge</th>
|
|
<th>Description</th>
|
|
<th>Response Time (sec)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get fastest manual responses
|
|
Dim rsFast, fastStyle
|
|
strSQL2 = "SELECT mr.requesttime, s.machinenumber, p.badgenumber, mr.description, mr.responseseconds " & _
|
|
"FROM udcmanualrequests mr " & _
|
|
"JOIN udcparts p ON mr.partrunid = p.partrunid " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & shiftFilter & _
|
|
" AND mr.responseseconds > 0 ORDER BY mr.responseseconds ASC LIMIT 25"
|
|
Set rsFast = objConn.Execute(strSQL2)
|
|
If rsFast.EOF Then
|
|
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No manual requests found</td></tr>")
|
|
Else
|
|
Do While Not rsFast.EOF
|
|
If CLng("0" & rsFast("responseseconds")) < 30 Then
|
|
fastStyle = "background-color:#28a745; color:#fff;"
|
|
ElseIf CLng("0" & rsFast("responseseconds")) < 60 Then
|
|
fastStyle = "background-color:#20c997; color:#fff;"
|
|
Else
|
|
fastStyle = ""
|
|
End If
|
|
Response.Write("<tr style='" & fastStyle & "'>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsFast("requesttime") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsFast("machinenumber") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsFast("badgenumber") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsFast("description") & "") & "</td>")
|
|
Response.Write("<td>" & rsFast("responseseconds") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsFast.MoveNext
|
|
Loop
|
|
End If
|
|
rsFast.Close
|
|
Set rsFast = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab 6: Activity Log (Violations & Badge Changes) -->
|
|
<div class="tab-pane<%If activeTab="activitylog" Then Response.Write(" active")%>" id="activitylog">
|
|
<h5 class="mb-3">Activity Log</h5>
|
|
<p class="text-muted small mb-3">Badge changes and item crossing violations recorded during part runs.</p>
|
|
|
|
<!-- Item Violations Summary -->
|
|
<h6 class="mt-3 mb-2">Item Crossing Violations</h6>
|
|
<p class="text-muted small">When operators modify item crossing values during a program run.</p>
|
|
<div class="table-responsive mb-4">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Time</th>
|
|
<th>Machine</th>
|
|
<th>Badge</th>
|
|
<th>Crossing</th>
|
|
<th>Item#</th>
|
|
<th>Previous</th>
|
|
<th>Current</th>
|
|
<th>Change</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get recent violations
|
|
Dim rsViolations, violWhereClause, violPrev, violCurr, violChange, violStyle
|
|
violWhereClause = " WHERE eventtime >= '" & Replace(filterStart, "'", "''") & "' " & _
|
|
" AND eventtime <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
|
|
If filterMachine <> "" Then
|
|
violWhereClause = violWhereClause & " AND machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
|
|
End If
|
|
If filterBU <> "" Then
|
|
violWhereClause = violWhereClause & " AND machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
|
|
End If
|
|
If filterBadge <> "" Then
|
|
violWhereClause = violWhereClause & " AND badgenumber = '" & Replace(filterBadge, "'", "''") & "'"
|
|
End If
|
|
|
|
strSQL2 = "SELECT eventtime, machinenumber, badgenumber, crossingdesc, itemno, previousval, currentval " & _
|
|
"FROM udcviolations " & violWhereClause & _
|
|
" ORDER BY eventtime DESC LIMIT 50"
|
|
Set rsViolations = objConn.Execute(strSQL2)
|
|
If rsViolations.EOF Then
|
|
Response.Write("<tr><td colspan='8' class='text-muted text-center'>No item violations found in date range</td></tr>")
|
|
Else
|
|
Do While Not rsViolations.EOF
|
|
violPrev = CDbl("0" & rsViolations("previousval"))
|
|
violCurr = CDbl("0" & rsViolations("currentval"))
|
|
violChange = violCurr - violPrev
|
|
|
|
' Color code based on change magnitude
|
|
If Abs(violChange) > 10 Then
|
|
violStyle = "background-color:#dc3545; color:#fff;"
|
|
ElseIf Abs(violChange) > 1 Then
|
|
violStyle = "background-color:#ffc107; color:#333;"
|
|
Else
|
|
violStyle = ""
|
|
End If
|
|
|
|
Response.Write("<tr style='" & violStyle & "'>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsViolations("eventtime") & "") & "</td>")
|
|
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsViolations("machinenumber") & "") & "'>" & Server.HTMLEncode(rsViolations("machinenumber") & "") & "</a></td>")
|
|
Response.Write("<td><a href='displayudc.asp?badge=" & Server.URLEncode(rsViolations("badgenumber") & "") & "'>" & Server.HTMLEncode(rsViolations("badgenumber") & "") & "</a></td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsViolations("crossingdesc") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsViolations("itemno") & "") & "</td>")
|
|
Response.Write("<td>" & FormatNumber(violPrev, 2) & "</td>")
|
|
Response.Write("<td><strong>" & FormatNumber(violCurr, 2) & "</strong></td>")
|
|
If violChange > 0 Then
|
|
Response.Write("<td><span class='text-success'>+" & FormatNumber(violChange, 2) & "</span></td>")
|
|
ElseIf violChange < 0 Then
|
|
Response.Write("<td><span class='text-danger'>" & FormatNumber(violChange, 2) & "</span></td>")
|
|
Else
|
|
Response.Write("<td>0</td>")
|
|
End If
|
|
Response.Write("</tr>")
|
|
rsViolations.MoveNext
|
|
Loop
|
|
End If
|
|
rsViolations.Close
|
|
Set rsViolations = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Violations by Machine -->
|
|
<h6 class="mt-4 mb-2">Violations by Machine</h6>
|
|
<div class="table-responsive mb-4">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Machine</th>
|
|
<th>Total Violations</th>
|
|
<th>Unique Crossings</th>
|
|
<th>Last Violation</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get violations summary by machine
|
|
Dim rsViolMach, violMachStyle
|
|
strSQL2 = "SELECT machinenumber, COUNT(*) as cnt, COUNT(DISTINCT crossingdesc) as crossings, MAX(eventtime) as lasttime " & _
|
|
"FROM udcviolations " & violWhereClause & _
|
|
" GROUP BY machinenumber ORDER BY cnt DESC, machinenumber ASC LIMIT 10"
|
|
Set rsViolMach = objConn.Execute(strSQL2)
|
|
If rsViolMach.EOF Then
|
|
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No violations found</td></tr>")
|
|
Else
|
|
Do While Not rsViolMach.EOF
|
|
If CLng("0" & rsViolMach("cnt")) > 100 Then
|
|
violMachStyle = "background-color:#dc3545; color:#fff;"
|
|
ElseIf CLng("0" & rsViolMach("cnt")) > 25 Then
|
|
violMachStyle = "background-color:#ffc107; color:#333;"
|
|
Else
|
|
violMachStyle = ""
|
|
End If
|
|
Response.Write("<tr style='" & violMachStyle & "'>")
|
|
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsViolMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsViolMach("machinenumber") & "") & "</a></td>")
|
|
Response.Write("<td>" & rsViolMach("cnt") & "</td>")
|
|
Response.Write("<td>" & rsViolMach("crossings") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsViolMach("lasttime") & "") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsViolMach.MoveNext
|
|
Loop
|
|
End If
|
|
rsViolMach.Close
|
|
Set rsViolMach = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Badge Changes -->
|
|
<h6 class="mt-4 mb-2">Badge Changes</h6>
|
|
<p class="text-muted small">Operator badge scans and changes during part runs.</p>
|
|
<div class="table-responsive mb-4">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Time</th>
|
|
<th>Machine</th>
|
|
<th>Badge</th>
|
|
<th>Details</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get recent badge changes
|
|
Dim rsBadgeChanges, badgeWhereClause
|
|
badgeWhereClause = " WHERE eventtime >= '" & Replace(filterStart, "'", "''") & "' " & _
|
|
" AND eventtime <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
|
|
If filterMachine <> "" Then
|
|
badgeWhereClause = badgeWhereClause & " AND machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
|
|
End If
|
|
If filterBU <> "" Then
|
|
badgeWhereClause = badgeWhereClause & " AND machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
|
|
End If
|
|
If filterBadge <> "" Then
|
|
badgeWhereClause = badgeWhereClause & " AND badgenumber = '" & Replace(filterBadge, "'", "''") & "'"
|
|
End If
|
|
|
|
strSQL2 = "SELECT eventtime, machinenumber, badgenumber, details, description " & _
|
|
"FROM udcheaderupdates " & badgeWhereClause & _
|
|
" ORDER BY eventtime DESC LIMIT 50"
|
|
Set rsBadgeChanges = objConn.Execute(strSQL2)
|
|
If rsBadgeChanges.EOF Then
|
|
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No badge changes found in date range</td></tr>")
|
|
Else
|
|
Do While Not rsBadgeChanges.EOF
|
|
Response.Write("<tr>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsBadgeChanges("eventtime") & "") & "</td>")
|
|
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsBadgeChanges("machinenumber") & "") & "'>" & Server.HTMLEncode(rsBadgeChanges("machinenumber") & "") & "</a></td>")
|
|
Response.Write("<td><a href='displayudc.asp?badge=" & Server.URLEncode(rsBadgeChanges("badgenumber") & "") & "'><span class='badge badge-info'>" & Server.HTMLEncode(rsBadgeChanges("badgenumber") & "") & "</span></a></td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsBadgeChanges("description") & "") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsBadgeChanges.MoveNext
|
|
Loop
|
|
End If
|
|
rsBadgeChanges.Close
|
|
Set rsBadgeChanges = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Badge Activity by Operator -->
|
|
<h6 class="mt-4 mb-2">Badge Activity by Operator</h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Badge #</th>
|
|
<th>Badge Scans</th>
|
|
<th>Machines Used</th>
|
|
<th>Last Activity</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get badge activity summary
|
|
Dim rsBadgeSum
|
|
strSQL2 = "SELECT badgenumber, COUNT(*) as cnt, COUNT(DISTINCT machinenumber) as machines, MAX(eventtime) as lasttime " & _
|
|
"FROM udcheaderupdates " & badgeWhereClause & _
|
|
" AND badgenumber IS NOT NULL AND badgenumber != '' " & _
|
|
" GROUP BY badgenumber ORDER BY cnt DESC, badgenumber ASC LIMIT 15"
|
|
Set rsBadgeSum = objConn.Execute(strSQL2)
|
|
If rsBadgeSum.EOF Then
|
|
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No badge activity found</td></tr>")
|
|
Else
|
|
Do While Not rsBadgeSum.EOF
|
|
Response.Write("<tr>")
|
|
Response.Write("<td><a href='displayudc.asp?badge=" & Server.URLEncode(rsBadgeSum("badgenumber") & "") & "'><span class='badge badge-info'>" & Server.HTMLEncode(rsBadgeSum("badgenumber") & "") & "</span></a></td>")
|
|
Response.Write("<td>" & rsBadgeSum("cnt") & "</td>")
|
|
Response.Write("<td>" & rsBadgeSum("machines") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsBadgeSum("lasttime") & "") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsBadgeSum.MoveNext
|
|
Loop
|
|
End If
|
|
rsBadgeSum.Close
|
|
Set rsBadgeSum = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab 7: Tool Health -->
|
|
<div class="tab-pane<%If activeTab="toolhealth" Then Response.Write(" active")%>" id="toolhealth">
|
|
<h5 class="mb-3">Tool Health</h5>
|
|
<p class="text-muted small mb-3">Tool offset measurements and wear tracking.</p>
|
|
|
|
<!-- Tool Summary by Machine -->
|
|
<h6 class="mt-3 mb-2">Tool Measurements by Machine</h6>
|
|
<div class="table-responsive mb-4">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Machine</th>
|
|
<th>Measurements</th>
|
|
<th>Unique Tools</th>
|
|
<th>OOT Count</th>
|
|
<th>Last Measurement</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get tool data summary by machine
|
|
Dim rsToolMach, toolWhereClause, toolMachStyle
|
|
toolWhereClause = " WHERE t.eventtime >= '" & Replace(filterStart, "'", "''") & "' " & _
|
|
" AND t.eventtime <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
|
|
If filterMachine <> "" Then
|
|
toolWhereClause = toolWhereClause & " AND s.machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
|
|
End If
|
|
If filterBU <> "" Then
|
|
toolWhereClause = toolWhereClause & " AND s.machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
|
|
End If
|
|
|
|
strSQL2 = "SELECT s.machinenumber, COUNT(*) as cnt, COUNT(DISTINCT t.toolnumber) as tools, " & _
|
|
"SUM(t.oot) as ootcount, MAX(t.eventtime) as lasttime " & _
|
|
"FROM udctooldata t " & _
|
|
"JOIN udcsessions s ON t.sessionid = s.sessionid " & _
|
|
toolWhereClause & _
|
|
" GROUP BY s.machinenumber ORDER BY cnt DESC, s.machinenumber ASC LIMIT 15"
|
|
Set rsToolMach = objConn.Execute(strSQL2)
|
|
If rsToolMach.EOF Then
|
|
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No tool data found in date range</td></tr>")
|
|
Else
|
|
Do While Not rsToolMach.EOF
|
|
If CLng("0" & rsToolMach("ootcount")) > 0 Then
|
|
toolMachStyle = "background-color:#ffc107; color:#333;"
|
|
Else
|
|
toolMachStyle = ""
|
|
End If
|
|
Response.Write("<tr style='" & toolMachStyle & "'>")
|
|
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsToolMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsToolMach("machinenumber") & "") & "</a></td>")
|
|
Response.Write("<td>" & rsToolMach("cnt") & "</td>")
|
|
Response.Write("<td>" & rsToolMach("tools") & "</td>")
|
|
Response.Write("<td>")
|
|
If CLng("0" & rsToolMach("ootcount")) > 0 Then
|
|
Response.Write("<span class='badge badge-danger'>" & rsToolMach("ootcount") & "</span>")
|
|
Else
|
|
Response.Write("<span class='badge badge-success'>0</span>")
|
|
End If
|
|
Response.Write("</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsToolMach("lasttime") & "") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsToolMach.MoveNext
|
|
Loop
|
|
End If
|
|
rsToolMach.Close
|
|
Set rsToolMach = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Tool Usage by Tool Number - Only shown when machine filter selected -->
|
|
<%
|
|
If filterMachine <> "" Then
|
|
%>
|
|
<h6 class="mt-4 mb-2">Most Used Tools on Machine <%=Server.HTMLEncode(filterMachine)%></h6>
|
|
<div class="table-responsive mb-4">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Tool #</th>
|
|
<th>Description</th>
|
|
<th>Measurements</th>
|
|
<th>Avg Deviation</th>
|
|
<th>OOT Count</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get tool usage by tool number for this specific machine
|
|
Dim rsToolNum, toolNumStyle, avgDev
|
|
strSQL2 = "SELECT t.toolnumber, MAX(t.description) as description, COUNT(*) as cnt, " & _
|
|
"AVG(ABS(t.deviation)) as avgdev, SUM(t.oot) as ootcount " & _
|
|
"FROM udctooldata t " & _
|
|
"JOIN udcsessions s ON t.sessionid = s.sessionid " & _
|
|
toolWhereClause & _
|
|
" AND t.toolnumber IS NOT NULL " & _
|
|
" GROUP BY t.toolnumber ORDER BY cnt DESC, t.toolnumber ASC LIMIT 20"
|
|
Set rsToolNum = objConn.Execute(strSQL2)
|
|
If rsToolNum.EOF Then
|
|
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No tool data found</td></tr>")
|
|
Else
|
|
Do While Not rsToolNum.EOF
|
|
If CLng("0" & rsToolNum("ootcount")) > 0 Then
|
|
toolNumStyle = "background-color:#ffc107; color:#333;"
|
|
Else
|
|
toolNumStyle = ""
|
|
End If
|
|
If Not IsNull(rsToolNum("avgdev")) Then
|
|
avgDev = FormatNumber(CDbl(rsToolNum("avgdev")), 4)
|
|
Else
|
|
avgDev = "-"
|
|
End If
|
|
Response.Write("<tr style='" & toolNumStyle & "'>")
|
|
Response.Write("<td><strong>Tool " & rsToolNum("toolnumber") & "</strong></td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(Trim(rsToolNum("description") & "")) & "</td>")
|
|
Response.Write("<td>" & rsToolNum("cnt") & "</td>")
|
|
Response.Write("<td>" & avgDev & "</td>")
|
|
Response.Write("<td>")
|
|
If CLng("0" & rsToolNum("ootcount")) > 0 Then
|
|
Response.Write("<span class='badge badge-danger'>" & rsToolNum("ootcount") & "</span>")
|
|
Else
|
|
Response.Write("<span class='badge badge-success'>0</span>")
|
|
End If
|
|
Response.Write("</td>")
|
|
Response.Write("</tr>")
|
|
rsToolNum.MoveNext
|
|
Loop
|
|
End If
|
|
rsToolNum.Close
|
|
Set rsToolNum = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<%
|
|
End If ' filterMachine
|
|
%>
|
|
|
|
<!-- Recent Tool Measurements -->
|
|
<h6 class="mt-4 mb-2">Recent Tool Measurements</h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Time</th>
|
|
<th>Machine</th>
|
|
<th>Tool #</th>
|
|
<th>Description</th>
|
|
<th>Min</th>
|
|
<th>Actual</th>
|
|
<th>Max</th>
|
|
<th>Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get recent tool measurements
|
|
Dim rsToolRecent, toolRecentStyle
|
|
strSQL2 = "SELECT t.eventtime, s.machinenumber, t.toolnumber, t.description, " & _
|
|
"t.minval, t.actualval, t.maxval, t.oot " & _
|
|
"FROM udctooldata t " & _
|
|
"JOIN udcsessions s ON t.sessionid = s.sessionid " & _
|
|
toolWhereClause & _
|
|
" ORDER BY t.eventtime DESC LIMIT 30"
|
|
Set rsToolRecent = objConn.Execute(strSQL2)
|
|
If rsToolRecent.EOF Then
|
|
Response.Write("<tr><td colspan='8' class='text-muted text-center'>No tool measurements found</td></tr>")
|
|
Else
|
|
Do While Not rsToolRecent.EOF
|
|
If CLng("0" & rsToolRecent("oot")) > 0 Then
|
|
toolRecentStyle = "background-color:#dc3545; color:#fff;"
|
|
Else
|
|
toolRecentStyle = ""
|
|
End If
|
|
Response.Write("<tr style='" & toolRecentStyle & "'>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsToolRecent("eventtime") & "") & "</td>")
|
|
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsToolRecent("machinenumber") & "") & "'>" & Server.HTMLEncode(rsToolRecent("machinenumber") & "") & "</a></td>")
|
|
Response.Write("<td>Tool " & rsToolRecent("toolnumber") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsToolRecent("description") & "") & "</td>")
|
|
Response.Write("<td>" & rsToolRecent("minval") & "</td>")
|
|
Response.Write("<td><strong>" & rsToolRecent("actualval") & "</strong></td>")
|
|
Response.Write("<td>" & rsToolRecent("maxval") & "</td>")
|
|
If CLng("0" & rsToolRecent("oot")) > 0 Then
|
|
Response.Write("<td><span class='badge badge-danger'>OOT</span></td>")
|
|
Else
|
|
Response.Write("<td><span class='badge badge-success'>OK</span></td>")
|
|
End If
|
|
Response.Write("</tr>")
|
|
rsToolRecent.MoveNext
|
|
Loop
|
|
End If
|
|
rsToolRecent.Close
|
|
Set rsToolRecent = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab 8: Uptime -->
|
|
<div class="tab-pane<%If activeTab="uptime" Then Response.Write(" active")%>" id="uptime">
|
|
<h5 class="mb-3">Machine Uptime</h5>
|
|
<p class="text-muted small mb-3">Runtime calculated from actual part cycle times within the selected date range.</p>
|
|
|
|
<!-- Uptime Summary Cards -->
|
|
<div class="row mb-4">
|
|
<%
|
|
' Calculate uptime summary
|
|
Dim rsUptimeSummary, totalRuntimeHours, totalMachines, avgUtilization
|
|
strSQL2 = "SELECT COUNT(DISTINCT s.machinenumber) as machines, " & _
|
|
"ROUND(SUM(p.cycletime)/3600, 1) as total_hours, " & _
|
|
"ROUND(AVG(p.cycletime)/60, 1) as avg_cycle " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" AND p.cycletime IS NOT NULL AND p.cycletime > 0"
|
|
Set rsUptimeSummary = objConn.Execute(strSQL2)
|
|
If Not rsUptimeSummary.EOF Then
|
|
totalMachines = CLng("0" & rsUptimeSummary("machines"))
|
|
If Not IsNull(rsUptimeSummary("total_hours")) Then
|
|
totalRuntimeHours = FormatNumber(CDbl(rsUptimeSummary("total_hours")), 1)
|
|
Else
|
|
totalRuntimeHours = "0"
|
|
End If
|
|
Else
|
|
totalMachines = 0
|
|
totalRuntimeHours = "0"
|
|
End If
|
|
rsUptimeSummary.Close
|
|
Set rsUptimeSummary = Nothing
|
|
%>
|
|
<div class="col-md-4">
|
|
<div class="card bg-info text-white">
|
|
<div class="card-body text-center">
|
|
<h3 class="mb-0"><%=totalRuntimeHours%></h3>
|
|
<small>Total Runtime Hours</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="card bg-success text-white">
|
|
<div class="card-body text-center">
|
|
<h3 class="mb-0"><%=totalMachines%></h3>
|
|
<small>Active Machines</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="card bg-primary text-white">
|
|
<div class="card-body text-center">
|
|
<h3 class="mb-0"><%=totalParts%></h3>
|
|
<small>Parts Produced</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Machine Uptime Table -->
|
|
<h6 class="mt-3 mb-2">Runtime by Machine</h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped" id="uptimeTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Machine</th>
|
|
<th>Runtime (hrs)</th>
|
|
<th>Parts Run</th>
|
|
<th>Avg Cycle (min)</th>
|
|
<th>Days Active</th>
|
|
<th>Utilization</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get uptime by machine
|
|
Dim rsUptime, uptimeHours, uptimeCycle, uptimeDays, uptimeUtil, uptimeUtilClass
|
|
strSQL2 = "SELECT s.machinenumber, " & _
|
|
"ROUND(SUM(p.cycletime)/3600, 1) as runtime_hours, " & _
|
|
"COUNT(*) as parts_run, " & _
|
|
"ROUND(AVG(p.cycletime)/60, 1) as avg_cycle_min, " & _
|
|
"DATEDIFF(MAX(p.programend), MIN(p.programstart)) + 1 as days_active, " & _
|
|
"MIN(p.programstart) as first_run, " & _
|
|
"MAX(p.programend) as last_run " & _
|
|
"FROM udcparts p " & _
|
|
"JOIN udcsessions s ON p.sessionid = s.sessionid " & _
|
|
whereClause & _
|
|
" AND p.cycletime IS NOT NULL AND p.cycletime > 0 " & _
|
|
"GROUP BY s.machinenumber ORDER BY runtime_hours DESC"
|
|
Set rsUptime = objConn.Execute(strSQL2)
|
|
If rsUptime.EOF Then
|
|
Response.Write("<tr><td colspan='6' class='text-muted text-center'>No uptime data found</td></tr>")
|
|
Else
|
|
Do While Not rsUptime.EOF
|
|
If Not IsNull(rsUptime("runtime_hours")) Then
|
|
uptimeHours = FormatNumber(CDbl(rsUptime("runtime_hours")), 1)
|
|
Else
|
|
uptimeHours = "0"
|
|
End If
|
|
If Not IsNull(rsUptime("avg_cycle_min")) Then
|
|
uptimeCycle = FormatNumber(CDbl(rsUptime("avg_cycle_min")), 1)
|
|
Else
|
|
uptimeCycle = "-"
|
|
End If
|
|
uptimeDays = CLng("0" & rsUptime("days_active"))
|
|
If uptimeDays < 1 Then uptimeDays = 1
|
|
|
|
' Calculate utilization (runtime hours / (days * 16 hours for 2 shifts) * 100)
|
|
If uptimeDays > 0 And Not IsNull(rsUptime("runtime_hours")) Then
|
|
uptimeUtil = Round((CDbl(rsUptime("runtime_hours")) / (uptimeDays * 16)) * 100, 1)
|
|
If uptimeUtil > 100 Then uptimeUtil = 100
|
|
Else
|
|
uptimeUtil = 0
|
|
End If
|
|
|
|
' Color code utilization
|
|
If uptimeUtil >= 70 Then
|
|
uptimeUtilClass = "badge badge-success"
|
|
ElseIf uptimeUtil >= 40 Then
|
|
uptimeUtilClass = "badge badge-warning"
|
|
Else
|
|
uptimeUtilClass = "badge badge-danger"
|
|
End If
|
|
|
|
Response.Write("<tr>")
|
|
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsUptime("machinenumber") & "") & "'>" & Server.HTMLEncode(rsUptime("machinenumber") & "") & "</a></td>")
|
|
Response.Write("<td><strong>" & uptimeHours & "</strong></td>")
|
|
Response.Write("<td>" & rsUptime("parts_run") & "</td>")
|
|
Response.Write("<td>" & uptimeCycle & "</td>")
|
|
Response.Write("<td>" & uptimeDays & "</td>")
|
|
Response.Write("<td><span class='" & uptimeUtilClass & "'>" & uptimeUtil & "%</span></td>")
|
|
Response.Write("</tr>")
|
|
rsUptime.MoveNext
|
|
Loop
|
|
End If
|
|
rsUptime.Close
|
|
Set rsUptime = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab 9: IT Diagnostics -->
|
|
<div class="tab-pane<%If activeTab="itdiagnostics" Then Response.Write(" active")%>" id="itdiagnostics">
|
|
<h5 class="mb-3">IT Diagnostics</h5>
|
|
|
|
<!-- Error Summary by Type -->
|
|
<h6 class="mt-3 mb-2">Error Summary by Type</h6>
|
|
<div class="table-responsive mb-4">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Error Type</th>
|
|
<th>Count</th>
|
|
<th>Machines Affected</th>
|
|
<th>Last Occurrence</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get error summary by type
|
|
Dim rsErrSummary, errWhereClause, errRowStyle
|
|
errWhereClause = " WHERE eventtime >= '" & Replace(filterStart, "'", "''") & "' " & _
|
|
" AND eventtime <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
|
|
If filterMachine <> "" Then
|
|
errWhereClause = errWhereClause & " AND machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
|
|
End If
|
|
If filterBU <> "" Then
|
|
errWhereClause = errWhereClause & " AND machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
|
|
End If
|
|
|
|
strSQL2 = "SELECT errortype, COUNT(*) as cnt, COUNT(DISTINCT machinenumber) as machines, MAX(eventtime) as lasttime " & _
|
|
"FROM udcerrors " & errWhereClause & _
|
|
" GROUP BY errortype ORDER BY cnt DESC, errortype ASC LIMIT 10"
|
|
Set rsErrSummary = objConn.Execute(strSQL2)
|
|
If rsErrSummary.EOF Then
|
|
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No errors found in date range</td></tr>")
|
|
Else
|
|
Do While Not rsErrSummary.EOF
|
|
If CLng("0" & rsErrSummary("cnt")) > 50 Then
|
|
errRowStyle = "background-color:#dc3545; color:#fff;"
|
|
ElseIf CLng("0" & rsErrSummary("cnt")) > 10 Then
|
|
errRowStyle = "background-color:#ffc107; color:#333;"
|
|
Else
|
|
errRowStyle = ""
|
|
End If
|
|
Response.Write("<tr style='" & errRowStyle & "'>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsErrSummary("errortype") & "") & "</td>")
|
|
Response.Write("<td>" & rsErrSummary("cnt") & "</td>")
|
|
Response.Write("<td>" & rsErrSummary("machines") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsErrSummary("lasttime") & "") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsErrSummary.MoveNext
|
|
Loop
|
|
End If
|
|
rsErrSummary.Close
|
|
Set rsErrSummary = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Error Summary by Machine -->
|
|
<h6 class="mt-4 mb-2">Errors by Machine</h6>
|
|
<div class="table-responsive mb-4">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Machine</th>
|
|
<th>Total Errors</th>
|
|
<th>Error Types</th>
|
|
<th>Last Error</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get errors by machine
|
|
Dim rsErrMach, errMachStyle
|
|
strSQL2 = "SELECT machinenumber, COUNT(*) as cnt, COUNT(DISTINCT errortype) as types, MAX(eventtime) as lasttime " & _
|
|
"FROM udcerrors " & errWhereClause & _
|
|
" GROUP BY machinenumber ORDER BY cnt DESC, machinenumber ASC LIMIT 10"
|
|
Set rsErrMach = objConn.Execute(strSQL2)
|
|
If rsErrMach.EOF Then
|
|
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No errors found</td></tr>")
|
|
Else
|
|
Do While Not rsErrMach.EOF
|
|
If CLng("0" & rsErrMach("cnt")) > 100 Then
|
|
errMachStyle = "background-color:#dc3545; color:#fff;"
|
|
ElseIf CLng("0" & rsErrMach("cnt")) > 25 Then
|
|
errMachStyle = "background-color:#ffc107; color:#333;"
|
|
Else
|
|
errMachStyle = ""
|
|
End If
|
|
Response.Write("<tr style='" & errMachStyle & "'>")
|
|
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsErrMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsErrMach("machinenumber") & "") & "</a></td>")
|
|
Response.Write("<td>" & rsErrMach("cnt") & "</td>")
|
|
Response.Write("<td>" & rsErrMach("types") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsErrMach("lasttime") & "") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsErrMach.MoveNext
|
|
Loop
|
|
End If
|
|
rsErrMach.Close
|
|
Set rsErrMach = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Recent Errors -->
|
|
<h6 class="mt-4 mb-2">Recent Errors</h6>
|
|
<div class="table-responsive mb-4">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Time</th>
|
|
<th>Machine</th>
|
|
<th>Type</th>
|
|
<th>Message</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get recent errors
|
|
Dim rsRecentErr, recentErrStyle
|
|
strSQL2 = "SELECT eventtime, machinenumber, errortype, errormessage " & _
|
|
"FROM udcerrors " & errWhereClause & _
|
|
" ORDER BY eventtime DESC LIMIT 25"
|
|
Set rsRecentErr = objConn.Execute(strSQL2)
|
|
If rsRecentErr.EOF Then
|
|
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No errors found</td></tr>")
|
|
Else
|
|
Do While Not rsRecentErr.EOF
|
|
If InStr(1, rsRecentErr("errortype") & "", "Exception", 1) > 0 Then
|
|
recentErrStyle = "background-color:#dc3545; color:#fff;"
|
|
Else
|
|
recentErrStyle = ""
|
|
End If
|
|
Response.Write("<tr style='" & recentErrStyle & "'>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsRecentErr("eventtime") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsRecentErr("machinenumber") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsRecentErr("errortype") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(Left(rsRecentErr("errormessage") & "", 100)) & "</td>")
|
|
Response.Write("</tr>")
|
|
rsRecentErr.MoveNext
|
|
Loop
|
|
End If
|
|
rsRecentErr.Close
|
|
Set rsRecentErr = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Connection Events -->
|
|
<h6 class="mt-4 mb-2">Connection Events by Machine</h6>
|
|
<div class="table-responsive mb-4">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Machine</th>
|
|
<th>Total Events</th>
|
|
<th>COM Ports Used</th>
|
|
<th>Last Event</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get connection events by machine
|
|
Dim rsConnMach, connWhereClause
|
|
connWhereClause = " WHERE eventtime >= '" & Replace(filterStart, "'", "''") & "' " & _
|
|
" AND eventtime <= '" & Replace(filterEnd, "'", "''") & " 23:59:59'"
|
|
If filterMachine <> "" Then
|
|
connWhereClause = connWhereClause & " AND machinenumber = '" & Replace(filterMachine, "'", "''") & "'"
|
|
End If
|
|
If filterBU <> "" Then
|
|
connWhereClause = connWhereClause & " AND machinenumber IN (SELECT machinenumber FROM machines WHERE businessunitid = " & CLng(filterBU) & ")"
|
|
End If
|
|
|
|
strSQL2 = "SELECT machinenumber, COUNT(*) as cnt, COUNT(DISTINCT comport) as ports, MAX(eventtime) as lasttime " & _
|
|
"FROM udcconnections " & connWhereClause & _
|
|
" GROUP BY machinenumber ORDER BY cnt DESC, machinenumber ASC LIMIT 10"
|
|
Set rsConnMach = objConn.Execute(strSQL2)
|
|
If rsConnMach.EOF Then
|
|
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No connection events found</td></tr>")
|
|
Else
|
|
Do While Not rsConnMach.EOF
|
|
Response.Write("<tr>")
|
|
Response.Write("<td><a href='displayudc.asp?machine=" & Server.URLEncode(rsConnMach("machinenumber") & "") & "'>" & Server.HTMLEncode(rsConnMach("machinenumber") & "") & "</a></td>")
|
|
Response.Write("<td>" & rsConnMach("cnt") & "</td>")
|
|
Response.Write("<td>" & rsConnMach("ports") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsConnMach("lasttime") & "") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsConnMach.MoveNext
|
|
Loop
|
|
End If
|
|
rsConnMach.Close
|
|
Set rsConnMach = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Recent Connection Events -->
|
|
<h6 class="mt-4 mb-2">Recent Connection Events</h6>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Time</th>
|
|
<th>Machine</th>
|
|
<th>Event</th>
|
|
<th>COM Port</th>
|
|
<th>Details</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%
|
|
' Get recent connection events
|
|
Dim rsRecentConn, connStyle
|
|
strSQL2 = "SELECT eventtime, machinenumber, eventtype, comport, details " & _
|
|
"FROM udcconnections " & connWhereClause & _
|
|
" ORDER BY eventtime DESC LIMIT 25"
|
|
Set rsRecentConn = objConn.Execute(strSQL2)
|
|
If rsRecentConn.EOF Then
|
|
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No connection events found</td></tr>")
|
|
Else
|
|
Do While Not rsRecentConn.EOF
|
|
If rsRecentConn("eventtype") & "" = "OPEN" Then
|
|
connStyle = "background-color:#28a745; color:#fff;"
|
|
ElseIf rsRecentConn("eventtype") & "" = "CLOSE" Then
|
|
connStyle = "background-color:#6c757d; color:#fff;"
|
|
Else
|
|
connStyle = ""
|
|
End If
|
|
Response.Write("<tr style='" & connStyle & "'>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsRecentConn("eventtime") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsRecentConn("machinenumber") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsRecentConn("eventtype") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsRecentConn("comport") & "") & "</td>")
|
|
Response.Write("<td>" & Server.HTMLEncode(rsRecentConn("details") & "") & "</td>")
|
|
Response.Write("</tr>")
|
|
rsRecentConn.MoveNext
|
|
Loop
|
|
End If
|
|
rsRecentConn.Close
|
|
Set rsRecentConn = Nothing
|
|
%>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div><!-- End container-fluid -->
|
|
</div><!-- End content-wrapper -->
|
|
|
|
<a href="javaScript:void();" class="back-to-top"><i class="fa fa-angle-double-up"></i></a>
|
|
|
|
<footer class="footer">
|
|
<div class="container"><div class="text-center"></div></div>
|
|
</footer>
|
|
|
|
</div><!-- End wrapper -->
|
|
|
|
<!-- JavaScript -->
|
|
<script src="assets/js/jquery.min.js"></script>
|
|
<script src="assets/js/popper.min.js"></script>
|
|
<script src="assets/js/bootstrap.min.js"></script>
|
|
<script src="assets/plugins/simplebar/js/simplebar.js"></script>
|
|
<script src="assets/js/sidebar-menu.js"></script>
|
|
<script src="assets/js/app-script.js"></script>
|
|
<script src="assets/plugins/Chart.js/Chart.min.js"></script>
|
|
<script>
|
|
// Tab persistence - update hidden input when tab is clicked
|
|
function setActiveTab(tabName) {
|
|
document.getElementById('activeTabInput').value = tabName;
|
|
}
|
|
|
|
// Dashboard Charts
|
|
$(function() {
|
|
// Chart 1: Production Trend (Line Chart)
|
|
var ctxProd = document.getElementById('productionChart').getContext('2d');
|
|
new Chart(ctxProd, {
|
|
type: 'line',
|
|
data: {
|
|
labels: [<%=prodLabels%>],
|
|
datasets: [{
|
|
label: 'Parts Produced',
|
|
data: [<%=prodData%>],
|
|
backgroundColor: 'rgba(102, 126, 234, 0.2)',
|
|
borderColor: 'rgba(102, 126, 234, 1)',
|
|
borderWidth: 2,
|
|
pointBackgroundColor: 'rgba(102, 126, 234, 1)',
|
|
pointRadius: 4,
|
|
fill: true
|
|
}]
|
|
},
|
|
options: {
|
|
maintainAspectRatio: false,
|
|
legend: { display: false },
|
|
scales: {
|
|
yAxes: [{ ticks: { beginAtZero: true } }],
|
|
xAxes: [{ gridLines: { display: false } }]
|
|
},
|
|
tooltips: {
|
|
callbacks: {
|
|
label: function(tooltipItem) {
|
|
return tooltipItem.yLabel + ' parts';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Chart 2: OOT Rate Trend (Line Chart)
|
|
var ctxOOT = document.getElementById('ootChart').getContext('2d');
|
|
new Chart(ctxOOT, {
|
|
type: 'line',
|
|
data: {
|
|
labels: [<%=ootLabels%>],
|
|
datasets: [{
|
|
label: 'OOT Rate %',
|
|
data: [<%=ootRateData%>],
|
|
backgroundColor: 'rgba(220, 53, 69, 0.2)',
|
|
borderColor: 'rgba(220, 53, 69, 1)',
|
|
borderWidth: 2,
|
|
pointBackgroundColor: 'rgba(220, 53, 69, 1)',
|
|
pointRadius: 4,
|
|
fill: true
|
|
}]
|
|
},
|
|
options: {
|
|
maintainAspectRatio: false,
|
|
legend: { display: false },
|
|
scales: {
|
|
yAxes: [{ ticks: { beginAtZero: true, callback: function(value) { return value + '%'; } } }],
|
|
xAxes: [{ gridLines: { display: false } }]
|
|
},
|
|
tooltips: {
|
|
callbacks: {
|
|
label: function(tooltipItem) {
|
|
return tooltipItem.yLabel + '% OOT';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Chart 3: Machine Utilization (Horizontal Bar Chart)
|
|
var ctxMach = document.getElementById('machineChart').getContext('2d');
|
|
new Chart(ctxMach, {
|
|
type: 'horizontalBar',
|
|
data: {
|
|
labels: [<%=machLabels%>],
|
|
datasets: [{
|
|
label: 'Runtime Hours',
|
|
data: [<%=machData%>],
|
|
backgroundColor: 'rgba(23, 162, 184, 0.7)',
|
|
borderColor: 'rgba(23, 162, 184, 1)',
|
|
borderWidth: 1
|
|
}]
|
|
},
|
|
options: {
|
|
maintainAspectRatio: false,
|
|
legend: { display: false },
|
|
scales: {
|
|
xAxes: [{ ticks: { beginAtZero: true } }],
|
|
yAxes: [{ gridLines: { display: false } }]
|
|
},
|
|
tooltips: {
|
|
callbacks: {
|
|
label: function(tooltipItem) {
|
|
return tooltipItem.xLabel + ' hours';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// Chart 4: Top Operators (Horizontal Bar Chart)
|
|
var ctxOps = document.getElementById('operatorChart').getContext('2d');
|
|
new Chart(ctxOps, {
|
|
type: 'horizontalBar',
|
|
data: {
|
|
labels: [<%=opLabels%>],
|
|
datasets: [{
|
|
label: 'Parts Produced',
|
|
data: [<%=opData%>],
|
|
backgroundColor: 'rgba(40, 167, 69, 0.7)',
|
|
borderColor: 'rgba(40, 167, 69, 1)',
|
|
borderWidth: 1
|
|
}]
|
|
},
|
|
options: {
|
|
maintainAspectRatio: false,
|
|
legend: { display: false },
|
|
scales: {
|
|
xAxes: [{ ticks: { beginAtZero: true } }],
|
|
yAxes: [{ gridLines: { display: false } }]
|
|
},
|
|
tooltips: {
|
|
callbacks: {
|
|
label: function(tooltipItem) {
|
|
return tooltipItem.xLabel + ' parts';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|
|
<%
|
|
objConn.Close
|
|
%>
|