def onTagChange(initialChange, newValue, previousValue, event, executionCount):
	# ============================================================================
	# Gateway Tag Change Script - Scanner Statistics
	# Triggers on: Scanner_X/* tags (diScanner_* statistics)
	# Logic:
	#   - Only act when:
	#       * not initialChange
	#       * quality is good
	#       * quality transition from bad to good is ignored
	#   - Then:
	#       * Read scanner name
	#       * INSERT into scanner_reads with appropriate column
	# ============================================================================
	
	DB_NAME = "MariaDB"
	import system
	
	# ============================================================================
	# ENTRY BLOCK – runs on every configured tag change
	# Objects: event, initialChange, currentValue, previousValue, executionCount
	# ============================================================================
	
	tagPath = str(event.getTagPath())
	
	# Extract tag name from path (e.g., "diScanner_bad_reads" from full path)
	tagName = tagPath.split("/")[-1]
	
	# Handle diScanner_bad_reads
	if tagName == "diScanner_bad_reads":
	    if not (initialChange or not currentValue.quality.isGood() or (not previousValue.quality.isGood() and currentValue.quality.isGood())):
	        try:
	            parentPath = "/".join(tagPath.split("/")[:-1])
	            namePath = parentPath + "/sScanner_Name"
	            name = system.tag.readBlocking([namePath])[0].value
            
	            system.db.runPrepUpdate("""
	                INSERT INTO scanner_reads (t_stamp, sScanner_Name, diScanner_bad_reads)
	                VALUES (NOW(), ?, 1)
	            """, [name], DB_NAME)
	        except Exception as e:
	            system.util.getLogger("ScannerStatistics").error("bad_reads: %s" % e)
	
	# Handle diScanner_comm_fault
	if tagName == "diScanner_comm_fault":
	    if not (initialChange or not currentValue.quality.isGood() or (not previousValue.quality.isGood() and currentValue.quality.isGood())):
	        try:
	            parentPath = "/".join(tagPath.split("/")[:-1])
	            namePath = parentPath + "/sScanner_Name"
	            name = system.tag.readBlocking([namePath])[0].value
            
	            system.db.runPrepUpdate("""
	                INSERT INTO scanner_reads (t_stamp, sScanner_Name, diScanner_comm_fault)
	                VALUES (NOW(), ?, 1)
	            """, [name], DB_NAME)
	        except Exception as e:
	            system.util.getLogger("ScannerStatistics").error("comm_fault: %s" % e)
	
	# Handle diScanner_good_reads
	if tagName == "diScanner_good_reads":
	    if not (initialChange or not currentValue.quality.isGood() or (not previousValue.quality.isGood() and currentValue.quality.isGood())):
	        try:
	            parentPath = "/".join(tagPath.split("/")[:-1])
	            namePath = parentPath + "/sScanner_Name"
	            name = system.tag.readBlocking([namePath])[0].value
            
	            system.db.runPrepUpdate("""
	                INSERT INTO scanner_reads (t_stamp, sScanner_Name, diScanner_good_reads)
	                VALUES (NOW(), ?, 1)
	            """, [name], DB_NAME)
	        except Exception as e:
	            system.util.getLogger("ScannerStatistics").error("good_reads: %s" % e)
	
	# Handle diScanner_multi_items
	if tagName == "diScanner_multi_items":
	    if not (initialChange or not currentValue.quality.isGood() or (not previousValue.quality.isGood() and currentValue.quality.isGood())):
	        try:
	            parentPath = "/".join(tagPath.split("/")[:-1])
	            namePath = parentPath + "/sScanner_Name"
	            name = system.tag.readBlocking([namePath])[0].value
            
	            system.db.runPrepUpdate("""
	                INSERT INTO scanner_reads (t_stamp, sScanner_Name, diScanner_multi_items)
	                VALUES (NOW(), ?, 1)
	            """, [name], DB_NAME)
	        except Exception as e:
	            system.util.getLogger("ScannerStatistics").error("multi_items: %s" % e)
	
	# Handle diScanner_multi_reads
	if tagName == "diScanner_multi_reads":
	    if not (initialChange or not currentValue.quality.isGood() or (not previousValue.quality.isGood() and currentValue.quality.isGood())):
	        try:
	            parentPath = "/".join(tagPath.split("/")[:-1])
	            namePath = parentPath + "/sScanner_Name"
	            name = system.tag.readBlocking([namePath])[0].value
            
	            system.db.runPrepUpdate("""
	                INSERT INTO scanner_reads (t_stamp, sScanner_Name, diScanner_multi_reads)
	                VALUES (NOW(), ?, 1)
	            """, [name], DB_NAME)
	        except Exception as e:
	            system.util.getLogger("ScannerStatistics").error("multi_reads: %s" % e)
	
	# Handle diScanner_no_data
	if tagName == "diScanner_no_data":
	    if not (initialChange or not currentValue.quality.isGood() or (not previousValue.quality.isGood() and currentValue.quality.isGood())):
	        try:
	            parentPath = "/".join(tagPath.split("/")[:-1])
	            namePath = parentPath + "/sScanner_Name"
	            name = system.tag.readBlocking([namePath])[0].value
            
	            system.db.runPrepUpdate("""
	                INSERT INTO scanner_reads (t_stamp, sScanner_Name, diScanner_no_data)
	                VALUES (NOW(), ?, 1)
	            """, [name], DB_NAME)
	        except Exception as e:
	            system.util.getLogger("ScannerStatistics").error("no_data: %s" % e)
	
	# Handle diScanner_no_reads
	if tagName == "diScanner_no_reads":
	    if not (initialChange or not currentValue.quality.isGood() or (not previousValue.quality.isGood() and currentValue.quality.isGood())):
	        try:
	            parentPath = "/".join(tagPath.split("/")[:-1])
	            namePath = parentPath + "/sScanner_Name"
	            name = system.tag.readBlocking([namePath])[0].value
            
	            system.db.runPrepUpdate("""
	                INSERT INTO scanner_reads (t_stamp, sScanner_Name, diScanner_no_reads)
	                VALUES (NOW(), ?, 1)
	            """, [name], DB_NAME)
	        except Exception as e:
	            system.util.getLogger("ScannerStatistics").error("no_reads: %s" % e)
	
	