Initial commit: InvenTree Stock Tool v2
A comprehensive barcode scanning application for InvenTree inventory management. Features: - Multi-mode operation (Add/Update/Check/Locate stock) - Smart duplicate prevention when adding stock - Barcode scanning with automatic part code cleaning - Real-time server connection monitoring - Part information display with images - Debug mode for troubleshooting Fixes applied: - Fixed encoding issues with non-ASCII characters in barcodes - Fixed API response handling for list and dict formats - Implemented duplicate prevention using PATCH to update existing stock - Added comprehensive error handling and logging Includes test suite for verification of all fixes.
This commit is contained in:
95
test_parse_fix.py
Normal file
95
test_parse_fix.py
Normal file
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test script to verify parse_scan fix for encoding issues."""
|
||||
|
||||
from typing import Tuple, Optional
|
||||
import re
|
||||
|
||||
SEP_RE = re.compile(r'[\x1D\x1E]')
|
||||
|
||||
def parse_scan(raw: str) -> Tuple[Optional[str], Optional[int]]:
|
||||
"""
|
||||
Parse scanned barcode to extract part code and quantity.
|
||||
|
||||
Args:
|
||||
raw: Raw barcode string
|
||||
|
||||
Returns:
|
||||
Tuple of (part_code, quantity) or (None, None) if parsing fails
|
||||
"""
|
||||
def clean_part_code(code: str) -> str:
|
||||
"""Clean part code by removing non-ASCII and invalid characters."""
|
||||
# Keep only ASCII printable characters (excluding control chars)
|
||||
# This removes characters like ¡ and other encoding artifacts
|
||||
cleaned = ''.join(char for char in code if 32 <= ord(char) <= 126)
|
||||
return cleaned.strip()
|
||||
|
||||
# Handle JSON-like format
|
||||
if raw.startswith('{') and '}' in raw:
|
||||
content = raw.strip()[1:-1]
|
||||
part = None
|
||||
qty = None
|
||||
|
||||
for kv in content.split(','):
|
||||
if ':' not in kv:
|
||||
continue
|
||||
k, v = kv.split(':', 1)
|
||||
key = k.strip().upper()
|
||||
val = v.strip()
|
||||
|
||||
if key == 'PM':
|
||||
part = clean_part_code(val)
|
||||
elif key == 'QTY':
|
||||
try:
|
||||
qty = int(val)
|
||||
except ValueError:
|
||||
pass
|
||||
return part, qty
|
||||
|
||||
# Handle separator-based format
|
||||
part = None
|
||||
qty = None
|
||||
fields = SEP_RE.split(raw)
|
||||
|
||||
for f in fields:
|
||||
if not f:
|
||||
continue
|
||||
if f.startswith('30P'):
|
||||
part = clean_part_code(f[3:])
|
||||
elif f.lower().startswith('1p'):
|
||||
part = clean_part_code(f[2:])
|
||||
elif f.lower().startswith('q') and f[1:].isdigit():
|
||||
qty = int(f[1:])
|
||||
|
||||
return part, qty
|
||||
|
||||
|
||||
# Test with the provided scan data
|
||||
test_scan = "{pbn:PICK251017100019,on:WM2510170196,pc:C18548292,pm:STHW4-DU-HS24041¡,qty:150,mc:,cc:1,pdi:180368458,hp:null,wc:JS}"
|
||||
|
||||
print("Testing parse_scan with problematic barcode data:")
|
||||
print(f"Input: {test_scan}")
|
||||
print()
|
||||
|
||||
part, qty = parse_scan(test_scan)
|
||||
|
||||
print(f"Parsed part code: '{part}'")
|
||||
print(f"Parsed quantity: {qty}")
|
||||
print()
|
||||
|
||||
# Verify the fix
|
||||
expected_part = "STHW4-DU-HS24041"
|
||||
expected_qty = 150
|
||||
|
||||
if part == expected_part and qty == expected_qty:
|
||||
print("✅ SUCCESS! Part code is correctly parsed.")
|
||||
print(f" Expected: '{expected_part}'")
|
||||
print(f" Got: '{part}'")
|
||||
else:
|
||||
print("❌ FAILURE! Parse result doesn't match expected values.")
|
||||
print(f" Expected part: '{expected_part}', Got: '{part}'")
|
||||
print(f" Expected qty: {expected_qty}, Got: {qty}")
|
||||
|
||||
# Show character codes for verification
|
||||
print("\nCharacter analysis of parsed part code:")
|
||||
for i, char in enumerate(part or ""):
|
||||
print(f" [{i}] '{char}' (ASCII {ord(char)})")
|
||||
Reference in New Issue
Block a user