Fix dualpath propagation, getShopfloorPCs filtering, USB management, and printer features
- Fix dualpath PC propagation direction (Equipment->PC) in api.asp and db_helpers.asp - Fix early exit in CreatePCMachineRelationship preventing propagation - Fix getShopfloorPCs to filter machinetypeid IN (33,34,35) instead of >= 33 - Fix getShopfloorPCs to show equipment numbers via GROUP_CONCAT subquery - Add detailed PropagateDP logging for dualpath debugging - Default "Show on Shopfloor Dashboard" checkbox to checked in addnotification.asp - Add USB label batch printing, single USB labels, and USB history pages - Add printer supplies tracking and toner report enhancements - Add uptime map visualization page - Add dashboard/lobby display SQL migration - Update CLAUDE.md with IIS 401 workaround documentation - Update TODO.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -302,19 +302,20 @@ Function PropagateControllerToDualpathMachines(conn, equipmentMachineid, pcMachi
|
||||
dualpathMachineId = CLng(rsDP("related_machineid"))
|
||||
|
||||
' Check if this dualpath machine already has a Controls relationship with this PC
|
||||
' Pattern: Equipment -> Controls -> PC (machineid=equipment, related_machineid=PC)
|
||||
Set rsDPCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _
|
||||
"WHERE machineid = " & CLng(pcMachineid) & " " & _
|
||||
"AND related_machineid = " & dualpathMachineId & " " & _
|
||||
"WHERE machineid = " & dualpathMachineId & " " & _
|
||||
"AND related_machineid = " & CLng(pcMachineid) & " " & _
|
||||
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
||||
|
||||
If rsDPCheck.EOF Then
|
||||
' Create Controls relationship: PC -> Dualpath Machine
|
||||
' Create Controls relationship: Dualpath Equipment -> PC (matches existing data pattern)
|
||||
Dim cmdDP
|
||||
Set cmdDP = Server.CreateObject("ADODB.Command")
|
||||
cmdDP.ActiveConnection = conn
|
||||
cmdDP.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)"
|
||||
cmdDP.Parameters.Append cmdDP.CreateParameter("@pcid", 3, 1, , CLng(pcMachineid))
|
||||
cmdDP.Parameters.Append cmdDP.CreateParameter("@equipid", 3, 1, , dualpathMachineId)
|
||||
cmdDP.Parameters.Append cmdDP.CreateParameter("@pcid", 3, 1, , CLng(pcMachineid))
|
||||
cmdDP.Parameters.Append cmdDP.CreateParameter("@reltypeid", 3, 1, , controlsTypeID)
|
||||
cmdDP.Execute
|
||||
Set cmdDP = Nothing
|
||||
@@ -360,28 +361,29 @@ Function PropagateControllerFromDualpathMachine(conn, machineId1, machineId2)
|
||||
Set rsCtrl = Nothing
|
||||
|
||||
' Check if machine1 has a controller, copy to machine2 if machine2 doesn't have one
|
||||
Set rsCtrl = conn.Execute("SELECT machineid FROM machinerelationships " & _
|
||||
"WHERE related_machineid = " & CLng(machineId1) & " " & _
|
||||
' Pattern: Equipment -> Controls -> PC (machineid=equipment, related_machineid=PC)
|
||||
Set rsCtrl = conn.Execute("SELECT related_machineid FROM machinerelationships " & _
|
||||
"WHERE machineid = " & CLng(machineId1) & " " & _
|
||||
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
||||
|
||||
If Not rsCtrl.EOF Then
|
||||
pcMachineid = CLng(rsCtrl("machineid"))
|
||||
pcMachineid = CLng(rsCtrl("related_machineid"))
|
||||
rsCtrl.Close
|
||||
Set rsCtrl = Nothing
|
||||
|
||||
' Check if machine2 already has this controller
|
||||
Set rsCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _
|
||||
"WHERE machineid = " & pcMachineid & " AND related_machineid = " & CLng(machineId2) & " " & _
|
||||
"WHERE machineid = " & CLng(machineId2) & " AND related_machineid = " & pcMachineid & " " & _
|
||||
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
||||
|
||||
If rsCheck.EOF Then
|
||||
' Create: PC -> Controls -> machine2
|
||||
' Create: Equipment -> Controls -> PC
|
||||
Dim cmdCtrl
|
||||
Set cmdCtrl = Server.CreateObject("ADODB.Command")
|
||||
cmdCtrl.ActiveConnection = conn
|
||||
cmdCtrl.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)"
|
||||
cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@pcid", 3, 1, , pcMachineid)
|
||||
cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@equipid", 3, 1, , CLng(machineId2))
|
||||
cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@pcid", 3, 1, , pcMachineid)
|
||||
cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@reltypeid", 3, 1, , controlsTypeID)
|
||||
cmdCtrl.Execute
|
||||
Set cmdCtrl = Nothing
|
||||
@@ -395,28 +397,28 @@ Function PropagateControllerFromDualpathMachine(conn, machineId1, machineId2)
|
||||
End If
|
||||
|
||||
' Now check if machine2 has a controller, copy to machine1 if machine1 doesn't have one
|
||||
Set rsCtrl = conn.Execute("SELECT machineid FROM machinerelationships " & _
|
||||
"WHERE related_machineid = " & CLng(machineId2) & " " & _
|
||||
Set rsCtrl = conn.Execute("SELECT related_machineid FROM machinerelationships " & _
|
||||
"WHERE machineid = " & CLng(machineId2) & " " & _
|
||||
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
||||
|
||||
If Not rsCtrl.EOF Then
|
||||
pcMachineid = CLng(rsCtrl("machineid"))
|
||||
pcMachineid = CLng(rsCtrl("related_machineid"))
|
||||
rsCtrl.Close
|
||||
Set rsCtrl = Nothing
|
||||
|
||||
' Check if machine1 already has this controller
|
||||
Set rsCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _
|
||||
"WHERE machineid = " & pcMachineid & " AND related_machineid = " & CLng(machineId1) & " " & _
|
||||
"WHERE machineid = " & CLng(machineId1) & " AND related_machineid = " & pcMachineid & " " & _
|
||||
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
||||
|
||||
If rsCheck.EOF Then
|
||||
' Create: PC -> Controls -> machine1
|
||||
' Create: Equipment -> Controls -> PC
|
||||
Dim cmdCtrl2
|
||||
Set cmdCtrl2 = Server.CreateObject("ADODB.Command")
|
||||
cmdCtrl2.ActiveConnection = conn
|
||||
cmdCtrl2.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)"
|
||||
cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@pcid", 3, 1, , pcMachineid)
|
||||
cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@equipid", 3, 1, , CLng(machineId1))
|
||||
cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@pcid", 3, 1, , pcMachineid)
|
||||
cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@reltypeid", 3, 1, , controlsTypeID)
|
||||
cmdCtrl2.Execute
|
||||
Set cmdCtrl2 = Nothing
|
||||
|
||||
181
includes/printer_supplies.asp
Normal file
181
includes/printer_supplies.asp
Normal file
@@ -0,0 +1,181 @@
|
||||
<%
|
||||
' Returns both standard and metered part numbers as pipe-delimited string
|
||||
' Format: "standard|metered" or just "standard" if no metered option
|
||||
Function GetSupplyPartNumbers(printerModel, supplyName)
|
||||
On Error Resume Next
|
||||
Dim pn, sn, isDrum, isWaste, stdPN, metPN
|
||||
pn = UCase(printerModel)
|
||||
sn = UCase(supplyName)
|
||||
isDrum = (InStr(sn, "DRUM") > 0 Or InStr(sn, "IMAGING") > 0)
|
||||
isWaste = (InStr(sn, "WASTE") > 0)
|
||||
stdPN = ""
|
||||
metPN = ""
|
||||
|
||||
' VersaLink C415
|
||||
If InStr(pn, "C415") > 0 Then
|
||||
If isWaste Then
|
||||
stdPN = "008R13335"
|
||||
ElseIf isDrum Then
|
||||
stdPN = "013R00701"
|
||||
ElseIf InStr(sn, "BLACK") > 0 Then
|
||||
stdPN = "006R04677"
|
||||
metPN = "006R04681"
|
||||
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||
stdPN = "006R04678"
|
||||
metPN = "006R04682"
|
||||
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||
stdPN = "006R04679"
|
||||
metPN = "006R04683"
|
||||
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||
stdPN = "006R04680"
|
||||
metPN = "006R04684"
|
||||
End If
|
||||
|
||||
' VersaLink C405
|
||||
ElseIf InStr(pn, "C405") > 0 Then
|
||||
If isWaste Then
|
||||
stdPN = "108R01124"
|
||||
ElseIf isDrum Then
|
||||
stdPN = "101R00555"
|
||||
ElseIf InStr(sn, "BLACK") > 0 Then
|
||||
stdPN = "106R03500"
|
||||
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||
stdPN = "106R03501"
|
||||
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||
stdPN = "106R03502"
|
||||
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||
stdPN = "106R03503"
|
||||
End If
|
||||
|
||||
' VersaLink C7125/C7100
|
||||
ElseIf InStr(pn, "C7125") > 0 Or InStr(pn, "C7100") > 0 Then
|
||||
If isWaste Then
|
||||
stdPN = "115R00129"
|
||||
ElseIf isDrum Then
|
||||
stdPN = "013R00688"
|
||||
ElseIf InStr(sn, "BLACK") > 0 Then
|
||||
stdPN = "006R01824"
|
||||
metPN = "006R01820"
|
||||
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||
stdPN = "006R01825"
|
||||
metPN = "006R01821"
|
||||
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||
stdPN = "006R01826"
|
||||
metPN = "006R01822"
|
||||
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||
stdPN = "006R01827"
|
||||
metPN = "006R01823"
|
||||
End If
|
||||
|
||||
' VersaLink B7125
|
||||
ElseIf InStr(pn, "B7125") > 0 Then
|
||||
If isWaste Then
|
||||
stdPN = "115R00129"
|
||||
ElseIf isDrum Then
|
||||
stdPN = "013R00687"
|
||||
ElseIf InStr(sn, "BLACK") > 0 Or InStr(sn, "TONER") > 0 Then
|
||||
stdPN = "006R01818"
|
||||
metPN = "006R01819"
|
||||
End If
|
||||
|
||||
' VersaLink B405
|
||||
ElseIf InStr(pn, "B405") > 0 Then
|
||||
If isWaste Then
|
||||
stdPN = "108R01124"
|
||||
ElseIf isDrum Then
|
||||
stdPN = "101R00554"
|
||||
ElseIf InStr(sn, "BLACK") > 0 Or InStr(sn, "TONER") > 0 Then
|
||||
stdPN = "106R03580"
|
||||
End If
|
||||
|
||||
' AltaLink C8135
|
||||
ElseIf InStr(pn, "C8135") > 0 Then
|
||||
If isWaste Then
|
||||
stdPN = "008R08101"
|
||||
ElseIf isDrum Then
|
||||
stdPN = "013R00681"
|
||||
ElseIf InStr(sn, "BLACK") > 0 Then
|
||||
stdPN = "006R01746"
|
||||
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||
stdPN = "006R01747"
|
||||
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||
stdPN = "006R01748"
|
||||
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||
stdPN = "006R01749"
|
||||
End If
|
||||
|
||||
' Xerox EC8036/AltaLink C8036 (compatible with WC7800 and AltaLink C80xx toner)
|
||||
ElseIf InStr(pn, "EC8036") > 0 Or InStr(pn, "C8036") > 0 Then
|
||||
Dim altPN
|
||||
altPN = ""
|
||||
If isWaste Then
|
||||
stdPN = "008R13061"
|
||||
ElseIf isDrum Then
|
||||
stdPN = "013R00677"
|
||||
ElseIf InStr(sn, "BLACK") > 0 Then
|
||||
stdPN = "006R01509"
|
||||
altPN = "006R01697"
|
||||
metPN = "006R01701"
|
||||
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||
stdPN = "006R01512"
|
||||
altPN = "006R01698"
|
||||
metPN = "006R01702"
|
||||
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||
stdPN = "006R01511"
|
||||
altPN = "006R01699"
|
||||
metPN = "006R01703"
|
||||
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||
stdPN = "006R01510"
|
||||
altPN = "006R01700"
|
||||
metPN = "006R01704"
|
||||
End If
|
||||
' Return all 3 options for EC8036
|
||||
If altPN <> "" Then
|
||||
GetSupplyPartNumbers = stdPN & "|" & altPN & "|" & metPN
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' HP LaserJet Pro M454dw / M454dn / MFP M479fdw / M479fdn (414A/414X series)
|
||||
ElseIf InStr(pn, "M454") > 0 Or InStr(pn, "M479") > 0 Then
|
||||
If InStr(sn, "BLACK") > 0 Then
|
||||
stdPN = "W2020A"
|
||||
metPN = "W2020X"
|
||||
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||
stdPN = "W2021A"
|
||||
metPN = "W2021X"
|
||||
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||
stdPN = "W2023A"
|
||||
metPN = "W2023X"
|
||||
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||
stdPN = "W2022A"
|
||||
metPN = "W2022X"
|
||||
End If
|
||||
|
||||
' HP LaserJet Pro M251nw / M252dw / MFP M277dw (201A/201X series)
|
||||
ElseIf InStr(pn, "M251") > 0 Or InStr(pn, "M252") > 0 Or InStr(pn, "M277") > 0 Then
|
||||
If InStr(sn, "BLACK") > 0 Then
|
||||
stdPN = "CF400A"
|
||||
metPN = "CF400X"
|
||||
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||
stdPN = "CF401A"
|
||||
metPN = "CF401X"
|
||||
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||
stdPN = "CF403A"
|
||||
metPN = "CF403X"
|
||||
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||
stdPN = "CF402A"
|
||||
metPN = "CF402X"
|
||||
End If
|
||||
End If
|
||||
|
||||
If metPN <> "" Then
|
||||
GetSupplyPartNumbers = stdPN & "|" & metPN
|
||||
Else
|
||||
GetSupplyPartNumbers = stdPN
|
||||
End If
|
||||
End Function
|
||||
|
||||
Function IsWasteSupply(supplyName)
|
||||
IsWasteSupply = (InStr(1, UCase(supplyName), "WASTE") > 0)
|
||||
End Function
|
||||
%>
|
||||
@@ -1,10 +1,35 @@
|
||||
<!--#include file="config.asp"-->
|
||||
<%
|
||||
' Employee database connection - uses centralized config
|
||||
Dim objConn
|
||||
Dim objConn, empConnError
|
||||
empConnError = ""
|
||||
Session.Timeout = APP_SESSION_TIMEOUT
|
||||
|
||||
On Error Resume Next
|
||||
Set objConn = Server.CreateObject("ADODB.Connection")
|
||||
objConn.ConnectionString = GetEmployeeConnectionString()
|
||||
objConn.Open
|
||||
If Err.Number <> 0 Then
|
||||
empConnError = "Employee DB Connection Error: " & Err.Number & " - " & Err.Description & " (Source: " & Err.Source & ")"
|
||||
Err.Clear
|
||||
End If
|
||||
On Error Goto 0
|
||||
|
||||
Set rs = Server.CreateObject("ADODB.Recordset")
|
||||
|
||||
' If connection failed, display error and stop
|
||||
If empConnError <> "" Then
|
||||
Dim connType
|
||||
If USE_EMP_DSN Then
|
||||
connType = "DSN-based (wjf_employees)"
|
||||
Else
|
||||
connType = "Direct ODBC"
|
||||
End If
|
||||
Response.Write "<!DOCTYPE html><html><head><title>Database Error</title></head><body>"
|
||||
Response.Write "<h2>Database Connection Error</h2>"
|
||||
Response.Write "<p style='color:red;'>" & Server.HTMLEncode(empConnError) & "</p>"
|
||||
Response.Write "<p>Connection String Type: " & connType & "</p>"
|
||||
Response.Write "</body></html>"
|
||||
Response.End
|
||||
End If
|
||||
%>
|
||||
@@ -1,54 +1,37 @@
|
||||
<%
|
||||
' Cached Zabbix API wrapper for ALL supply levels (toner, ink, drums, maintenance kits, etc.)
|
||||
' Simplified caching - no background refresh, minimal locking
|
||||
%>
|
||||
<!--#include file="./zabbix_all_supplies.asp"-->
|
||||
<%
|
||||
|
||||
' Cached function for all supply levels - returns data immediately, refreshes in background if stale
|
||||
' Cached function for all supply levels - simple 5-minute cache
|
||||
Function GetAllPrinterSuppliesCached(hostIP)
|
||||
Dim cacheKey, cacheAge, forceRefresh
|
||||
On Error Resume Next
|
||||
|
||||
Dim cacheKey, cacheTime, cacheAge, cachedData, forceRefresh
|
||||
cacheKey = "zabbix_all_supplies_" & hostIP
|
||||
|
||||
' Check if manual refresh was requested
|
||||
forceRefresh = (Request.QueryString("refresh") = "1" And Request.QueryString("ip") = hostIP)
|
||||
|
||||
If forceRefresh Then
|
||||
' Clear cache for manual refresh
|
||||
Application.Lock
|
||||
Application(cacheKey) = Empty
|
||||
Application(cacheKey & "_time") = Empty
|
||||
Application(cacheKey & "_refreshing") = "false"
|
||||
Application.Unlock
|
||||
End If
|
||||
' Check if valid cache exists (without locking)
|
||||
If Not forceRefresh Then
|
||||
cachedData = Application(cacheKey)
|
||||
cacheTime = Application(cacheKey & "_time")
|
||||
|
||||
' Check if cache exists
|
||||
If Not IsEmpty(Application(cacheKey)) And Not forceRefresh Then
|
||||
cacheAge = DateDiff("n", Application(cacheKey & "_time"), Now())
|
||||
|
||||
' If cache is stale (>5 min) AND not already refreshing, trigger background update
|
||||
If cacheAge >= 5 And Application(cacheKey & "_refreshing") <> "true" Then
|
||||
' Mark as refreshing
|
||||
Application.Lock
|
||||
Application(cacheKey & "_refreshing") = "true"
|
||||
Application.Unlock
|
||||
|
||||
' Trigger async background refresh (non-blocking)
|
||||
On Error Resume Next
|
||||
Dim http
|
||||
Set http = Server.CreateObject("MSXML2.ServerXMLHTTP.6.0")
|
||||
http.Open "GET", "http://localhost/refresh_all_supplies_cache.asp?ip=" & Server.URLEncode(hostIP), True
|
||||
http.Send
|
||||
Set http = Nothing
|
||||
On Error Goto 0
|
||||
If Not IsEmpty(cachedData) And Not IsEmpty(cacheTime) Then
|
||||
cacheAge = DateDiff("n", cacheTime, Now())
|
||||
If cacheAge < 5 Then
|
||||
' Cache is fresh, return it
|
||||
GetAllPrinterSuppliesCached = cachedData
|
||||
Exit Function
|
||||
End If
|
||||
End If
|
||||
|
||||
' Return cached data immediately
|
||||
GetAllPrinterSuppliesCached = Application(cacheKey)
|
||||
Exit Function
|
||||
End If
|
||||
|
||||
' No cache exists - fetch initial data
|
||||
Dim freshData, zabbixConnected, pingStatus, suppliesJSON
|
||||
' Cache miss or stale - fetch fresh data
|
||||
Dim zabbixConnected, pingStatus, suppliesJSON
|
||||
|
||||
zabbixConnected = ZabbixLogin()
|
||||
|
||||
@@ -66,13 +49,13 @@ Function GetAllPrinterSuppliesCached(hostIP)
|
||||
resultData(1) = pingStatus
|
||||
resultData(2) = suppliesJSON
|
||||
|
||||
' Cache the result
|
||||
' Cache the result (brief lock)
|
||||
Application.Lock
|
||||
Application(cacheKey) = resultData
|
||||
Application(cacheKey & "_time") = Now()
|
||||
Application(cacheKey & "_refreshing") = "false"
|
||||
Application.Unlock
|
||||
|
||||
On Error Goto 0
|
||||
GetAllPrinterSuppliesCached = resultData
|
||||
End Function
|
||||
|
||||
|
||||
Reference in New Issue
Block a user