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.
6.0 KiB
Stock Tool GUI v2 - Fixes Applied
Summary
Fixed three critical issues in stock_tool_gui_v2.py:
- ✅ Encoding issue with barcode part numbers
- ✅ API response handling causing "'list' object has no attribute 'get'" errors
- ✅ Duplicate stock items being created when adding to existing location
Issue 1: Encoding Problem with Part Numbers
Problem
Raw scan data contained: pm:STHW4-DU-HS24041¡
The non-ASCII characters (¡) were being included in the parsed part number.
Root Cause
The parse_scan() function was not cleaning/sanitizing the extracted part codes.
Fix Applied
Added clean_part_code() helper function that:
- Filters out all non-ASCII characters
- Keeps only printable ASCII characters (codes 32-126)
- Removes encoding artifacts like
¡
Location
File: stock_tool_gui_v2.py
Function: parse_scan() (lines 294-348)
Result
- Before:
STHW4-DU-HS24041¡ - After:
STHW4-DU-HS24041✓
Issue 2: API Response Handling Error
Problem
Error: 'list' object has no attribute 'get'
- Stock not being added to InvenTree
- Stock levels not updating after adding items
Root Cause
The InvenTree API POST response can return either:
- A dictionary:
{'pk': 123, 'quantity': 150, ...} - A list:
[{'pk': 123, 'quantity': 150, ...}]
The code was assuming it would always be a dict and calling .get() directly on the response, which failed when the API returned a list.
Locations with the Bug
_add_stock()function - line 806 (original)_update_stock()function - line 865 (original)- Misplaced
get_stock_level()function at top of file
Fixes Applied
1. Fixed _add_stock() function (lines 797-827)
Before:
r.raise_for_status()
sid = r.json().get('pk', r.json().get('id')) # ❌ Fails if response is list
After:
r.raise_for_status()
# Handle response - might be list or dict
response_data = r.json()
if isinstance(response_data, list):
stock_item = response_data[0] if response_data else {}
else:
stock_item = response_data
sid = stock_item.get('pk', stock_item.get('id')) # ✓ Works for both
2. Fixed _update_stock() function (lines 858-875)
Applied the same fix for consistency.
3. Moved get_stock_level() function (lines 256-270)
- Removed misplaced definition from top of file (before imports)
- Re-added in correct location after
find_stock_item()function
Issue 3: Duplicate Stock Items Created
Problem
When scanning a part that already exists at a storage location, the tool was creating a duplicate stock item instead of adding to the existing quantity.
Example:
- Location C64_PSU has 150x STHW4-DU-HS24041
- Scan barcode to add 100 more
- Bug: Creates second stock item with 100 (now have two separate items)
- Expected: Updates existing item to 250
Root Cause
The _add_stock() function was always creating a new stock item via POST without checking if one already existed at that location.
Fix Applied (lines 791-845)
Before:
def _add_stock(self, part_id: int, part_code: str, quantity: Optional[int]):
# Always creates new stock item - WRONG!
r = requests.post(f"{self.host}/api/stock/", ...)
After:
def _add_stock(self, part_id: int, part_code: str, quantity: Optional[int]):
# Check if stock item already exists at this location
existing = find_stock_item(self.host, self.token, part_id, self.current_loc)
if existing:
# Stock exists - update the quantity by adding to it
sid = existing.get('pk', existing.get('id'))
new_stock = current_stock + quantity
r = requests.patch(f"{self.host}/api/stock/{sid}/",
json={'quantity': new_stock})
# Updates existing item ✓
else:
# No existing stock - create new stock item
r = requests.post(f"{self.host}/api/stock/", ...)
# Creates new item ✓
Behavior Now
- Same part + same location = Updates existing stock item (no duplicate)
- Same part + different location = Creates new stock item (correct)
- New part = Creates new stock item (correct)
Testing
Test Files Created
test_parse_fix.py- Verifies encoding fixtest_stock_level.py- Verifies stock level retrievaltest_add_stock.py- Verifies API response handlingtest_duplicate_handling.py- Verifies duplicate prevention logic
Test Results
All tests pass ✓
Expected Behavior Now
When scanning barcode:
{pbn:PICK251017100019,on:WM2510170196,pc:C18548292,pm:STHW4-DU-HS24041¡,qty:150,mc:,cc:1,pdi:180368458,hp:null,wc:JS}
The tool will:
- ✅ Extract clean part number:
STHW4-DU-HS24041 - ✅ Extract quantity:
150 - ✅ Check if part already exists at current location
- ✅ If exists: Add to existing stock (no duplicate created)
- ✅ If new: Create new stock item
- ✅ Display updated stock levels
- ✅ Handle both dict and list API responses correctly
Example Workflows
Scenario 1: First time adding part to location
- Scan: Part STHW4-DU-HS24041, Qty: 150
- Result: Creates new stock item
- Log:
✔ Created new stock item for 'STHW4-DU-HS24041' → StockItem #123 - Log:
📊 Stock: 0 → 150 (+150)
Scenario 2: Adding more of same part to same location
- Scan: Part STHW4-DU-HS24041, Qty: 100
- Result: Updates existing stock item #123
- Log:
✔ Added 100× to existing 'STHW4-DU-HS24041' (StockItem #123) - Log:
📊 Stock: 150 → 250 (+100) - No duplicate created! ✓
Scenario 3: Adding same part to different location
- Change location to C65_PSU
- Scan: Part STHW4-DU-HS24041, Qty: 75
- Result: Creates new stock item #124 at the new location
- Log:
✔ Created new stock item for 'STHW4-DU-HS24041' → StockItem #124 - Log:
📊 Stock: 0 → 75 (+75)
Files Modified
stock_tool_gui_v2.py- Main application file
Files Created
test_parse_fix.py- Test for encoding fixtest_stock_level.py- Test for stock level retrievaltest_add_stock.py- Test for API response handlingFIXES_APPLIED.md- This document