"""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)