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:
355
tonerreport.asp
355
tonerreport.asp
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<!--#include file="./includes/header.asp"-->
|
||||
<!--#include file="./includes/sql.asp"-->
|
||||
<!--#include file="./includes/printer_supplies.asp"-->
|
||||
<!--#include file="./includes/zabbix_all_supplies_cached.asp"-->
|
||||
</head>
|
||||
|
||||
@@ -206,13 +207,70 @@
|
||||
' Xerox VersaLink B7025/B7030/B7035 Monochrome (WorkCentre 7800 series)
|
||||
ElseIf oem = "006R01756" Then
|
||||
marketing = "Xerox Black Toner"
|
||||
' Xerox VersaLink C415
|
||||
ElseIf oem = "006R04677" Then
|
||||
marketing = "C415 Black Toner"
|
||||
ElseIf oem = "006R04678" Then
|
||||
marketing = "C415 Cyan Toner"
|
||||
ElseIf oem = "006R04679" Then
|
||||
marketing = "C415 Magenta Toner"
|
||||
ElseIf oem = "006R04680" Then
|
||||
marketing = "C415 Yellow Toner"
|
||||
ElseIf oem = "006R04681" Then
|
||||
marketing = "C415 Black Toner (Metered)"
|
||||
ElseIf oem = "006R04682" Then
|
||||
marketing = "C415 Cyan Toner (Metered)"
|
||||
ElseIf oem = "006R04683" Then
|
||||
marketing = "C415 Magenta Toner (Metered)"
|
||||
ElseIf oem = "006R04684" Then
|
||||
marketing = "C415 Yellow Toner (Metered)"
|
||||
ElseIf oem = "008R13335" Then
|
||||
marketing = "C415 Waste Cartridge"
|
||||
ElseIf oem = "013R00701" Then
|
||||
marketing = "C415 Drum/Imaging Unit"
|
||||
' Xerox VersaLink C405
|
||||
ElseIf oem = "106R03500" Then
|
||||
marketing = "C405 Black Toner"
|
||||
ElseIf oem = "106R03501" Then
|
||||
marketing = "C405 Cyan Toner"
|
||||
ElseIf oem = "106R03502" Then
|
||||
marketing = "C405 Magenta Toner"
|
||||
ElseIf oem = "106R03503" Then
|
||||
marketing = "C405 Yellow Toner"
|
||||
ElseIf oem = "108R01124" Then
|
||||
marketing = "C405 Waste Container"
|
||||
ElseIf oem = "101R00555" Then
|
||||
marketing = "C405 Drum Cartridge"
|
||||
' Xerox VersaLink C7125/C7100
|
||||
ElseIf oem = "006R01824" Then
|
||||
marketing = "C7125 Black Toner"
|
||||
ElseIf oem = "006R01825" Then
|
||||
marketing = "C7125 Cyan Toner"
|
||||
ElseIf oem = "006R01826" Then
|
||||
marketing = "C7125 Magenta Toner"
|
||||
ElseIf oem = "006R01827" Then
|
||||
marketing = "C7125 Yellow Toner"
|
||||
ElseIf oem = "006R01820" Then
|
||||
marketing = "C7125 Black Toner (Metered)"
|
||||
ElseIf oem = "006R01821" Then
|
||||
marketing = "C7125 Cyan Toner (Metered)"
|
||||
ElseIf oem = "006R01822" Then
|
||||
marketing = "C7125 Magenta Toner (Metered)"
|
||||
ElseIf oem = "006R01823" Then
|
||||
marketing = "C7125 Yellow Toner (Metered)"
|
||||
ElseIf oem = "115R00129" Then
|
||||
marketing = "VersaLink Waste Container"
|
||||
ElseIf oem = "013R00688" Then
|
||||
marketing = "C7125 Drum Cartridge"
|
||||
' Xerox VersaLink B7125/B7130/B7135 Monochrome
|
||||
ElseIf oem = "006R01817" Then
|
||||
marketing = "Xerox Black Toner (Standard)"
|
||||
marketing = "B7125 Black Toner (Standard)"
|
||||
ElseIf oem = "006R01818" Then
|
||||
marketing = "Xerox Black Toner (High Capacity)"
|
||||
marketing = "B7125 Black Toner (High Capacity)"
|
||||
ElseIf oem = "006R01819" Then
|
||||
marketing = "Xerox Black Toner (DMO)"
|
||||
marketing = "B7125 Black Toner (Metered)"
|
||||
ElseIf oem = "013R00687" Then
|
||||
marketing = "B7125 Drum Cartridge"
|
||||
' Xerox VersaLink C7000 series
|
||||
ElseIf oem = "106R03536" Then
|
||||
marketing = "Xerox Black Toner"
|
||||
@@ -252,15 +310,36 @@
|
||||
' Xerox Phaser 4600/4620 series
|
||||
ElseIf oem = "006R01817" Then
|
||||
marketing = "Xerox Black Toner"
|
||||
' Xerox (legacy - keeping for compatibility)
|
||||
' Xerox AltaLink EC8036/C8036 - WC7800 series compatible
|
||||
ElseIf oem = "006R01509" Then
|
||||
marketing = "WC7800 Black"
|
||||
ElseIf oem = "006R01512" Then
|
||||
marketing = "WC7800 Cyan"
|
||||
ElseIf oem = "006R01511" Then
|
||||
marketing = "WC7800 Magenta"
|
||||
ElseIf oem = "006R01510" Then
|
||||
marketing = "WC7800 Yellow"
|
||||
' Xerox AltaLink EC8036/C8036 - AltaLink C80xx series
|
||||
ElseIf oem = "006R01697" Then
|
||||
marketing = "Xerox Black Toner"
|
||||
marketing = "AltaLink Black"
|
||||
ElseIf oem = "006R01698" Then
|
||||
marketing = "Xerox Cyan Toner"
|
||||
marketing = "AltaLink Cyan"
|
||||
ElseIf oem = "006R01699" Then
|
||||
marketing = "Xerox Yellow Toner"
|
||||
marketing = "AltaLink Magenta"
|
||||
ElseIf oem = "006R01700" Then
|
||||
marketing = "Xerox Magenta Toner"
|
||||
marketing = "AltaLink Yellow"
|
||||
ElseIf oem = "006R01701" Then
|
||||
marketing = "AltaLink Black (Met)"
|
||||
ElseIf oem = "006R01702" Then
|
||||
marketing = "AltaLink Cyan (Met)"
|
||||
ElseIf oem = "006R01703" Then
|
||||
marketing = "AltaLink Magenta (Met)"
|
||||
ElseIf oem = "006R01704" Then
|
||||
marketing = "AltaLink Yellow (Met)"
|
||||
ElseIf oem = "008R13061" Then
|
||||
marketing = "EC8036 Waste Container"
|
||||
ElseIf oem = "013R00677" Then
|
||||
marketing = "EC8036 Drum Cartridge"
|
||||
|
||||
Else
|
||||
marketing = "" ' No mapping found - will display OEM number only
|
||||
@@ -290,7 +369,7 @@
|
||||
<div>
|
||||
<h5 class="card-title"><i class='zmdi zmdi-collection-image text-yellow'></i> Supplies Alert Report</h5>
|
||||
<p class="text-muted" style="font-size:13px; margin-top:5px; margin-bottom:0;">
|
||||
Monitors: Toner/Ink ≤5%, Drums ≤5%, Maintenance Kits ≤5%, Waste ≥95% (Xerox EC series: ≤5% inverted)
|
||||
Monitors: Toner/Ink ≤5%, Drums ≤5%, Maintenance Kits ≤5%, Waste ≥95% (Xerox: ≤5% inverted)
|
||||
</p>
|
||||
</div>
|
||||
<div style="display:flex; gap:10px; align-items:center;">
|
||||
@@ -340,6 +419,7 @@
|
||||
Dim typeMatches, colorMatches
|
||||
Dim urgencyScore, alertItem, alertItems(1000), alertCount, i, j, tempAlert, k, outputItem
|
||||
Dim isXeroxPrinter
|
||||
Dim stdPartNumber, metPartNumber, altPartNumber, stdMarketing, metMarketing, altMarketing, partNumberResult, partNumberParts
|
||||
|
||||
lowSuppliesFound = False
|
||||
alertCount = 0
|
||||
@@ -364,9 +444,10 @@
|
||||
machineid = rs("machineid")
|
||||
vendor = rs("vendor")
|
||||
|
||||
' Detect if this is a Xerox EC series printer (EC8036, etc.) for vendor-specific logic
|
||||
' These enterprise models report waste cartridges inverted from standard behavior
|
||||
isXeroxPrinter = (InStr(1, vendor, "Xerox", 1) > 0 And InStr(1, modelnumber, "EC", 1) > 0)
|
||||
' Detect if this is a Xerox printer for vendor-specific waste cartridge logic
|
||||
' Xerox printers (VersaLink, AltaLink, EC series) report waste inverted:
|
||||
' 100% = empty (capacity remaining), 0% = full (no capacity remaining)
|
||||
isXeroxPrinter = (InStr(1, vendor, "Xerox", 1) > 0)
|
||||
|
||||
' Use alias if available, otherwise machinenumber
|
||||
If NOT IsNull(rs("alias")) AND rs("alias") <> "" Then
|
||||
@@ -617,137 +698,66 @@
|
||||
End If
|
||||
End If
|
||||
|
||||
' Look up part number for this item
|
||||
partNumber = "-"
|
||||
If partNumbers.Count > 0 Then
|
||||
' Extract base name for lookup - remove " Level" suffix
|
||||
lookupName = Replace(itemName, " Level", "")
|
||||
lookupName = Trim(lookupName)
|
||||
' Look up part numbers from hardcoded list (SNMP is unreliable)
|
||||
' Returns "standard|metered" or "standard|alt|metered" or just "standard"
|
||||
partNumberResult = GetSupplyPartNumbers(modelnumber, itemName)
|
||||
stdPartNumber = ""
|
||||
metPartNumber = ""
|
||||
altPartNumber = ""
|
||||
|
||||
' Comprehensive matching strategy for all template versions
|
||||
foundMatch = False
|
||||
|
||||
' Strategy 1: EXACT match - NEW template format (preferred)
|
||||
' "Black Toner Level" → "Black Toner Part Number"
|
||||
' "Cyan Ink Level" → "Cyan Ink Part Number"
|
||||
' "Black Drum Level" → "Black Drum Part Number"
|
||||
partKeyName = lookupName & " Part Number"
|
||||
If partNumbers.Exists(partKeyName) Then
|
||||
partNumber = partNumbers(partKeyName)
|
||||
foundMatch = True
|
||||
End If
|
||||
|
||||
' Strategy 2: Add " Cartridge" - OLD Xerox template format
|
||||
' "Black Drum Level" → "Black Drum Cartridge Part Number"
|
||||
' "Black Toner Level" → "Black Toner Cartridge Part Number"
|
||||
If Not foundMatch Then
|
||||
tryName = lookupName & " Cartridge Part Number"
|
||||
If partNumbers.Exists(tryName) Then
|
||||
partNumber = partNumbers(tryName)
|
||||
foundMatch = True
|
||||
End If
|
||||
End If
|
||||
|
||||
' Strategy 3: Replace supply type with "Cartridge" - OLD HP template format
|
||||
' "Black Toner Level" → "Black Cartridge Part Number"
|
||||
' "Cyan Ink Level" → "Cyan Cartridge Part Number"
|
||||
If Not foundMatch Then
|
||||
' Replace common supply types with "Cartridge"
|
||||
If InStr(1, lookupName, "Toner", 1) > 0 Then
|
||||
tryName = Replace(lookupName, "Toner", "Cartridge", 1, -1, 1) & " Part Number"
|
||||
ElseIf InStr(1, lookupName, "Ink", 1) > 0 Then
|
||||
tryName = Replace(lookupName, "Ink", "Cartridge", 1, -1, 1) & " Part Number"
|
||||
ElseIf InStr(1, lookupName, "Drum", 1) > 0 Then
|
||||
tryName = Replace(lookupName, "Drum", "Cartridge", 1, -1, 1) & " Part Number"
|
||||
Else
|
||||
tryName = ""
|
||||
End If
|
||||
|
||||
If tryName <> "" And partNumbers.Exists(tryName) Then
|
||||
partNumber = partNumbers(tryName)
|
||||
foundMatch = True
|
||||
End If
|
||||
End If
|
||||
|
||||
' Strategy 4: Check for "Standard MIB" suffix variation
|
||||
' "Maintenance Kit Level" → "Maintenance Kit Part Number (Standard MIB)"
|
||||
If Not foundMatch Then
|
||||
tryName = lookupName & " Part Number (Standard MIB)"
|
||||
If partNumbers.Exists(tryName) Then
|
||||
partNumber = partNumbers(tryName)
|
||||
foundMatch = True
|
||||
End If
|
||||
End If
|
||||
|
||||
' Strategy 5: Intelligent fuzzy match by type and color
|
||||
If Not foundMatch Then
|
||||
' Extract primary identifier (first significant word)
|
||||
primaryWord = ""
|
||||
supplyType = ""
|
||||
|
||||
' Determine supply type
|
||||
If InStr(1, lookupName, "Toner", 1) > 0 Then
|
||||
supplyType = "Toner"
|
||||
ElseIf InStr(1, lookupName, "Ink", 1) > 0 Then
|
||||
supplyType = "Ink"
|
||||
ElseIf InStr(1, lookupName, "Drum", 1) > 0 Then
|
||||
supplyType = "Drum"
|
||||
ElseIf InStr(1, lookupName, "Waste", 1) > 0 Then
|
||||
supplyType = "Waste"
|
||||
ElseIf InStr(1, lookupName, "Fuser", 1) > 0 Then
|
||||
supplyType = "Fuser"
|
||||
ElseIf InStr(1, lookupName, "Maintenance", 1) > 0 Then
|
||||
supplyType = "Maintenance"
|
||||
End If
|
||||
|
||||
' Extract color/identifier (first word before supply type)
|
||||
If supplyType <> "" Then
|
||||
colorPos = InStr(1, lookupName, supplyType, 1)
|
||||
If colorPos > 1 Then
|
||||
primaryWord = Trim(Left(lookupName, colorPos - 1))
|
||||
End If
|
||||
End If
|
||||
|
||||
' Search all keys for matching type and color
|
||||
For Each partKey In partNumbers.Keys
|
||||
If InStr(1, partKey, "Part Number", 1) > 0 Then
|
||||
' Must match supply type
|
||||
typeMatches = False
|
||||
If supplyType <> "" Then
|
||||
typeMatches = (InStr(1, partKey, supplyType, 1) > 0) Or (InStr(1, partKey, "Cartridge", 1) > 0)
|
||||
Else
|
||||
' For items without obvious type, just look for any match
|
||||
typeMatches = True
|
||||
End If
|
||||
|
||||
' Must match color/identifier if present
|
||||
colorMatches = True
|
||||
If primaryWord <> "" Then
|
||||
colorMatches = (InStr(1, partKey, primaryWord, 1) > 0)
|
||||
End If
|
||||
|
||||
If typeMatches And colorMatches Then
|
||||
partNumber = partNumbers(partKey)
|
||||
foundMatch = True
|
||||
Exit For
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
If InStr(partNumberResult, "|") > 0 Then
|
||||
partNumberParts = Split(partNumberResult, "|")
|
||||
stdPartNumber = partNumberParts(0)
|
||||
If UBound(partNumberParts) >= 2 Then
|
||||
' 3 options: std|alt|met
|
||||
altPartNumber = partNumberParts(1)
|
||||
metPartNumber = partNumberParts(2)
|
||||
Else
|
||||
' 2 options: std|met
|
||||
metPartNumber = partNumberParts(1)
|
||||
End If
|
||||
Else
|
||||
stdPartNumber = partNumberResult
|
||||
End If
|
||||
|
||||
' Replace generic Xerox part numbers with actual model-specific part numbers
|
||||
partNumber = GetActualPartNumber(partNumber, modelnumber, itemName)
|
||||
If stdPartNumber = "" Then stdPartNumber = "-"
|
||||
|
||||
' Get marketing name for this part number
|
||||
marketingName = GetMarketingName(partNumber)
|
||||
' Get marketing names
|
||||
stdMarketing = GetMarketingName(stdPartNumber)
|
||||
metMarketing = ""
|
||||
altMarketing = ""
|
||||
If metPartNumber <> "" Then metMarketing = GetMarketingName(metPartNumber)
|
||||
If altPartNumber <> "" Then altMarketing = GetMarketingName(altPartNumber)
|
||||
|
||||
If marketingName <> "" Then
|
||||
' Show marketing name prominently with OEM number in smaller text
|
||||
displayPartNumber = "<strong>" & Server.HTMLEncode(marketingName) & "</strong><br><small style='color:#999;'>" & Server.HTMLEncode(partNumber) & "</small>"
|
||||
' Build display string showing all options
|
||||
If altPartNumber <> "" Then
|
||||
' 3 options (EC8036 style)
|
||||
displayPartNumber = "<div style='line-height:1.3; font-size:12px;'>"
|
||||
displayPartNumber = displayPartNumber & "<strong>WC:</strong> " & Server.HTMLEncode(stdPartNumber) & "<br>"
|
||||
displayPartNumber = displayPartNumber & "<strong>Alt:</strong> " & Server.HTMLEncode(altPartNumber) & "<br>"
|
||||
displayPartNumber = displayPartNumber & "<strong>Met:</strong> " & Server.HTMLEncode(metPartNumber)
|
||||
displayPartNumber = displayPartNumber & "</div>"
|
||||
ElseIf metPartNumber <> "" Then
|
||||
' 2 options
|
||||
displayPartNumber = "<div style='line-height:1.4;'>"
|
||||
If stdMarketing <> "" Then
|
||||
displayPartNumber = displayPartNumber & "<strong>Std:</strong> " & Server.HTMLEncode(stdMarketing) & " <small style='color:#999;'>(" & Server.HTMLEncode(stdPartNumber) & ")</small><br>"
|
||||
Else
|
||||
displayPartNumber = displayPartNumber & "<strong>Std:</strong> " & Server.HTMLEncode(stdPartNumber) & "<br>"
|
||||
End If
|
||||
If metMarketing <> "" Then
|
||||
displayPartNumber = displayPartNumber & "<strong>Met:</strong> " & Server.HTMLEncode(metMarketing) & " <small style='color:#999;'>(" & Server.HTMLEncode(metPartNumber) & ")</small>"
|
||||
Else
|
||||
displayPartNumber = displayPartNumber & "<strong>Met:</strong> " & Server.HTMLEncode(metPartNumber)
|
||||
End If
|
||||
displayPartNumber = displayPartNumber & "</div>"
|
||||
Else
|
||||
' No mapping found, just show OEM number
|
||||
displayPartNumber = Server.HTMLEncode(partNumber)
|
||||
' Single option
|
||||
If stdMarketing <> "" Then
|
||||
displayPartNumber = "<strong>" & Server.HTMLEncode(stdMarketing) & "</strong><br><small style='color:#999;'>" & Server.HTMLEncode(stdPartNumber) & "</small>"
|
||||
Else
|
||||
displayPartNumber = Server.HTMLEncode(stdPartNumber)
|
||||
End If
|
||||
End If
|
||||
|
||||
' Calculate urgency score for sorting
|
||||
@@ -851,7 +861,7 @@
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<small class="text-muted">
|
||||
<i class="zmdi zmdi-info-outline"></i> This report shows printers with low supplies (≤5%) or waste cartridges near full (≥95%, Xerox EC series inverted ≤5%).
|
||||
<i class="zmdi zmdi-info-outline"></i> This report shows printers with low supplies (≤5%) or waste cartridges near full (≥95%, Xerox inverted ≤5%).
|
||||
Data refreshed from Zabbix every 5 minutes.
|
||||
</small>
|
||||
</div>
|
||||
@@ -919,6 +929,77 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Print styles for readable printouts -->
|
||||
<style>
|
||||
@media print {
|
||||
/* Reset dark theme for printing */
|
||||
body, .bg-theme, .content-wrapper, .card, .card-body {
|
||||
background: white !important;
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
/* Make all text black and readable - override inline styles */
|
||||
h1, h2, h3, h4, h5, h6, p, span, td, th, a, strong, small, div {
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
/* Force small text (part numbers) to be dark and readable */
|
||||
small, small[style], td small {
|
||||
color: #333 !important;
|
||||
font-size: 11px !important;
|
||||
}
|
||||
|
||||
/* Location link styling for print */
|
||||
.location-link, .location-link i {
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
/* Table styling for print */
|
||||
.table {
|
||||
border-collapse: collapse !important;
|
||||
}
|
||||
.table th, .table td {
|
||||
border: 1px solid #333 !important;
|
||||
padding: 8px !important;
|
||||
color: black !important;
|
||||
background: white !important;
|
||||
}
|
||||
.table thead th {
|
||||
background: #eee !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
.table-striped tbody tr:nth-of-type(odd) {
|
||||
background: #f5f5f5 !important;
|
||||
}
|
||||
|
||||
/* Keep status colors visible but darker for print */
|
||||
strong[style*="color:#ff0000"] { color: #cc0000 !important; }
|
||||
strong[style*="color:#ff6600"] { color: #cc5500 !important; }
|
||||
|
||||
/* Hide non-essential elements */
|
||||
#sidebar-wrapper, .topbar-nav, .back-to-top, .footer,
|
||||
#pageloader-overlay, #vendorFilter, #refreshBtn,
|
||||
.location-popup, .location-popup-overlay {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Expand content to full width */
|
||||
.content-wrapper {
|
||||
margin-left: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.card {
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* Part number styling */
|
||||
.card-body small {
|
||||
color: #666 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Location map popup modal -->
|
||||
<style>
|
||||
/* Theme-specific styling for location links */
|
||||
|
||||
Reference in New Issue
Block a user