mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-15 19:45:46 +00:00
* Fix barcode scanning in web interface * Improve error handling for barcode scan dialog * JS linting
117 lines
3.5 KiB
Python
117 lines
3.5 KiB
Python
"""The InvenTreeBarcodePlugin validates barcodes generated by InvenTree itself. It can be used as a template for developing third-party barcode plugins.
|
|
|
|
The data format is very simple, and maps directly to database objects,
|
|
via the "id" parameter.
|
|
|
|
Parsing an InvenTree barcode simply involves validating that the
|
|
references model objects actually exist in the database.
|
|
"""
|
|
|
|
import json
|
|
|
|
from company.models import SupplierPart
|
|
from InvenTree.helpers import hash_barcode
|
|
from part.models import Part
|
|
from plugin import InvenTreePlugin
|
|
from plugin.mixins import BarcodeMixin
|
|
from stock.models import StockItem, StockLocation
|
|
|
|
|
|
class InvenTreeBarcodePlugin(BarcodeMixin, InvenTreePlugin):
|
|
"""Generic base class for handling InvenTree barcodes"""
|
|
|
|
@staticmethod
|
|
def get_supported_barcode_models():
|
|
"""Returns a list of database models which support barcode functionality"""
|
|
|
|
return [
|
|
Part,
|
|
StockItem,
|
|
StockLocation,
|
|
SupplierPart,
|
|
]
|
|
|
|
def format_matched_response(self, label, model, instance):
|
|
"""Format a response for the scanned data"""
|
|
|
|
data = {
|
|
'pk': instance.pk
|
|
}
|
|
|
|
# Add in the API URL if available
|
|
if hasattr(model, 'get_api_url'):
|
|
data['api_url'] = f"{model.get_api_url()}{instance.pk}/"
|
|
|
|
# Add in the web URL if available
|
|
if hasattr(instance, 'get_absolute_url'):
|
|
url = instance.get_absolute_url()
|
|
data['web_url'] = url
|
|
else:
|
|
url = None
|
|
|
|
response = {
|
|
label: data
|
|
}
|
|
|
|
if url is not None:
|
|
response['url'] = url
|
|
|
|
return response
|
|
|
|
|
|
class InvenTreeInternalBarcodePlugin(InvenTreeBarcodePlugin):
|
|
"""Builtin BarcodePlugin for matching and generating internal barcodes."""
|
|
|
|
NAME = "InvenTreeInternalBarcode"
|
|
|
|
def scan(self, barcode_data):
|
|
"""Scan a barcode against this plugin.
|
|
|
|
Here we are looking for a dict object which contains a reference to a particular InvenTree database object
|
|
"""
|
|
|
|
if type(barcode_data) is dict:
|
|
pass
|
|
elif type(barcode_data) is str:
|
|
try:
|
|
barcode_data = json.loads(barcode_data)
|
|
except json.JSONDecodeError:
|
|
return None
|
|
else:
|
|
return None
|
|
|
|
if type(barcode_data) is not dict:
|
|
return None
|
|
|
|
# Look for various matches. First good match will be returned
|
|
for model in self.get_supported_barcode_models():
|
|
label = model.barcode_model_type()
|
|
if label in barcode_data:
|
|
try:
|
|
instance = model.objects.get(pk=barcode_data[label])
|
|
return self.format_matched_response(label, model, instance)
|
|
except (ValueError, model.DoesNotExist):
|
|
pass
|
|
|
|
|
|
class InvenTreeExternalBarcodePlugin(InvenTreeBarcodePlugin):
|
|
"""Builtin BarcodePlugin for matching arbitrary external barcodes."""
|
|
|
|
NAME = "InvenTreeExternalBarcode"
|
|
|
|
def scan(self, barcode_data):
|
|
"""Scan a barcode against this plugin.
|
|
|
|
Here we are looking for a dict object which contains a reference to a particular InvenTree databse object
|
|
"""
|
|
|
|
for model in self.get_supported_barcode_models():
|
|
label = model.barcode_model_type()
|
|
|
|
barcode_hash = hash_barcode(barcode_data)
|
|
|
|
instance = model.lookup_barcode(barcode_hash)
|
|
|
|
if instance is not None:
|
|
return self.format_matched_response(label, model, instance)
|