2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-15 19:45:46 +00:00
Files
InvenTree/InvenTree/plugin/builtin/barcodes/inventree_barcode.py
Oliver 8bcf72fbb2 Barcode scan fix (#3727)
* Fix barcode scanning in web interface

* Improve error handling for barcode scan dialog

* JS linting
2022-09-28 10:28:39 +10:00

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)