fix: Add support for ANSI MH10.8.2 barcode format

Fixes barcode parsing for ANSI MH10.8.2 format barcodes that don't use GS/RS separators.

Problem:
- Barcodes like [)>06PSAM9019-ND1PJL-100-25-T... were not being parsed
- Only separator-based and JSON formats were supported
- User's real-world barcodes were being added to queue as raw strings

Solution:
- Added ANSI MH10.8.2 format detection ([)>06 prefix)
- Extract part code between P and first field marker (1P, 30P)
- Extract quantity from Q<digits> pattern
- Updated both desktop and web app parsing logic

Tested with real barcode:
- Input: [)>06PSAM9019-ND1PJL-100-25-T30PSAM9019-NDK1...Q1811...
- Parsed: Part=SAM9019-ND, Qty=1811 

Files Changed:
- src/stocktool/stock_tool_gui_v2.py - Enhanced parse_scan()
- src/stocktool/web/static/js/app.js - Enhanced parseBarcode()
- test_barcode_parsing.py - Test script for validation
- test_barcode_analyze.py - Barcode structure analysis tool
- QUICKSTART_WEB.md - Quick start guide for web app

Supported Formats Now:
1. JSON-like: {PM:PART-CODE,QTY:10}
2. Separator-based: GS/RS (\x1D, \x1E) separated fields
3. ANSI MH10.8.2: [)>06P<part>...Q<qty>... (NEW!)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-29 11:29:20 +07:00
parent 03b7a4b0c8
commit 8dadd66f45
5 changed files with 353 additions and 8 deletions
+35
View File
@@ -416,6 +416,11 @@ def parse_scan(raw: str) -> Tuple[Optional[str], Optional[int]]:
"""
Parse scanned barcode to extract part code and quantity.
Supports multiple formats:
- JSON-like: {PM:PART-CODE,QTY:10}
- Separator-based: Fields separated by GS/RS (\x1D, \x1E)
- ANSI MH10.8.2: [)>06P<part>...Q<qty>...
Args:
raw: Raw barcode string
@@ -451,6 +456,36 @@ def parse_scan(raw: str) -> Tuple[Optional[str], Optional[int]]:
pass
return part, qty
# Handle ANSI MH10.8.2 format: [)>06P<part>...
if raw.startswith('[)>06'):
part = None
qty = None
# Extract part number - it's after [)>06P and before the next field marker
# Look for common field markers: 1P, 30P (these are explicit markers)
if len(raw) > 6 and raw[5] == 'P':
after_p = raw[6:]
# Find the next explicit field marker
markers_to_find = ['1P', '30P']
end_idx = len(after_p)
for marker in markers_to_find:
idx = after_p.find(marker)
if idx != -1 and idx < end_idx:
end_idx = idx
part = clean_part_code(after_p[:end_idx])
# Extract quantity after Q
if 'Q' in raw:
q_matches = re.findall(r'Q(\d+)', raw)
if q_matches:
qty = int(q_matches[0])
if part or qty:
return part, qty
# Handle separator-based format
part = None
qty = None