diff --git a/InvenTree/barcodes/barcode.py b/InvenTree/barcodes/barcode.py index 51f8a1ffa1..bca27590e8 100644 --- a/InvenTree/barcodes/barcode.py +++ b/InvenTree/barcodes/barcode.py @@ -1,139 +1,19 @@ # -*- coding: utf-8 -*- +import warnings -import string -import hashlib -import logging +import plugin.builtin.barcode.mixins as mixin +import plugin.integration -from stock.models import StockItem -from stock.serializers import StockItemSerializer, LocationSerializer -from part.serializers import PartSerializer +hash_barcode = mixin.hash_barcode - -logger = logging.getLogger('inventree') - - -def hash_barcode(barcode_data): +class BarcodePlugin(mixin.BarcodeMixin, plugin.integration.IntegrationPluginBase): """ - Calculate an MD5 hash of barcode data. - - HACK: Remove any 'non printable' characters from the hash, - as it seems browers will remove special control characters... - - TODO: Work out a way around this! + Legacy barcode plugin definition - will be replaced + Please use the new Integration Plugin API and the BarcodeMixin """ - - barcode_data = str(barcode_data).strip() - - printable_chars = filter(lambda x: x in string.printable, barcode_data) - - barcode_data = ''.join(list(printable_chars)) - - hash = hashlib.md5(str(barcode_data).encode()) - return str(hash.hexdigest()) - - -class BarcodePlugin: - """ - Base class for barcode handling. - Custom barcode plugins should extend this class as necessary. - """ - - # Override the barcode plugin name for each sub-class - PLUGIN_NAME = "" - - @property - def name(self): - return self.PLUGIN_NAME - - def __init__(self, barcode_data): - """ - Initialize the BarcodePlugin instance - - Args: - barcode_data - The raw barcode data - """ - - self.data = barcode_data - - def getStockItem(self): - """ - Attempt to retrieve a StockItem associated with this barcode. - Default implementation returns None - """ - - return None - - def getStockItemByHash(self): - """ - Attempt to retrieve a StockItem associated with this barcode, - based on the barcode hash. - """ - - try: - item = StockItem.objects.get(uid=self.hash()) - return item - except StockItem.DoesNotExist: - return None - - def renderStockItem(self, item): - """ - Render a stock item to JSON response - """ - - serializer = StockItemSerializer(item, part_detail=True, location_detail=True, supplier_part_detail=True) - return serializer.data - - def getStockLocation(self): - """ - Attempt to retrieve a StockLocation associated with this barcode. - Default implementation returns None - """ - - return None - - def renderStockLocation(self, loc): - """ - Render a stock location to a JSON response - """ - - serializer = LocationSerializer(loc) - return serializer.data - - def getPart(self): - """ - Attempt to retrieve a Part associated with this barcode. - Default implementation returns None - """ - - return None - - def renderPart(self, part): - """ - Render a part to JSON response - """ - - serializer = PartSerializer(part) - return serializer.data - - def hash(self): - """ - Calculate a hash for the barcode data. - This is supposed to uniquely identify the barcode contents, - at least within the bardcode sub-type. - - The default implementation simply returns an MD5 hash of the barcode data, - encoded to a string. - - This may be sufficient for most applications, but can obviously be overridden - by a subclass. - - """ - - return hash_barcode(self.data) - - def validate(self): - """ - Default implementation returns False - """ - return False + # TODO @matmair remove this with InvenTree 0.7.0 + def __init__(self, barcode_data=None): + warnings.warn("using the BarcodePlugin is depreceated", DeprecationWarning) + super().__init__() + self.init(barcode_data) diff --git a/InvenTree/plugin/builtin/barcode/__init__.py b/InvenTree/plugin/builtin/barcode/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/InvenTree/plugin/builtin/barcode/mixins.py b/InvenTree/plugin/builtin/barcode/mixins.py new file mode 100644 index 0000000000..904c260275 --- /dev/null +++ b/InvenTree/plugin/builtin/barcode/mixins.py @@ -0,0 +1,147 @@ +""" +Plugin mixin classes for barcode plugin +""" +import string +import hashlib + +from stock.models import StockItem +from stock.serializers import StockItemSerializer, LocationSerializer +from part.serializers import PartSerializer + + +def hash_barcode(barcode_data): + """ + Calculate an MD5 hash of barcode data. + + HACK: Remove any 'non printable' characters from the hash, + as it seems browers will remove special control characters... + + TODO: Work out a way around this! + """ + + barcode_data = str(barcode_data).strip() + + printable_chars = filter(lambda x: x in string.printable, barcode_data) + + barcode_data = ''.join(list(printable_chars)) + + hash = hashlib.md5(str(barcode_data).encode()) + return str(hash.hexdigest()) + + +class BarcodeMixin: + """ + Mixin that enables barcode handeling + Custom barcode plugins should use and extend this mixin as necessary. + """ + ACTION_NAME = "" + + class MixinMeta: + """ + meta options for this mixin + """ + MIXIN_NAME = 'Barcode' + + def __init__(self): + super().__init__() + self.add_mixin('barcode', 'has_barcode', __class__) + + @property + def has_barcode(self): + """ + Does this plugin have everything needed to process a barcode + """ + return True + + def init(self, barcode_data): + """ + Initialize the BarcodePlugin instance + + Args: + barcode_data - The raw barcode data + """ + + self.data = barcode_data + + + def getStockItem(self): + """ + Attempt to retrieve a StockItem associated with this barcode. + Default implementation returns None + """ + + return None + + def getStockItemByHash(self): + """ + Attempt to retrieve a StockItem associated with this barcode, + based on the barcode hash. + """ + + try: + item = StockItem.objects.get(uid=self.hash()) + return item + except StockItem.DoesNotExist: + return None + + def renderStockItem(self, item): + """ + Render a stock item to JSON response + """ + + serializer = StockItemSerializer(item, part_detail=True, location_detail=True, supplier_part_detail=True) + return serializer.data + + def getStockLocation(self): + """ + Attempt to retrieve a StockLocation associated with this barcode. + Default implementation returns None + """ + + return None + + def renderStockLocation(self, loc): + """ + Render a stock location to a JSON response + """ + + serializer = LocationSerializer(loc) + return serializer.data + + def getPart(self): + """ + Attempt to retrieve a Part associated with this barcode. + Default implementation returns None + """ + + return None + + def renderPart(self, part): + """ + Render a part to JSON response + """ + + serializer = PartSerializer(part) + return serializer.data + + def hash(self): + """ + Calculate a hash for the barcode data. + This is supposed to uniquely identify the barcode contents, + at least within the bardcode sub-type. + + The default implementation simply returns an MD5 hash of the barcode data, + encoded to a string. + + This may be sufficient for most applications, but can obviously be overridden + by a subclass. + + """ + + return hash_barcode(self.data) + + def validate(self): + """ + Default implementation returns False + """ + return False diff --git a/InvenTree/plugin/mixins/__init__.py b/InvenTree/plugin/mixins/__init__.py index 389258a99a..03b6f48971 100644 --- a/InvenTree/plugin/mixins/__init__.py +++ b/InvenTree/plugin/mixins/__init__.py @@ -4,6 +4,7 @@ Utility class to enable simpler imports from ..builtin.integration.mixins import AppMixin, SettingsMixin, ScheduleMixin, UrlsMixin, NavigationMixin from ..builtin.action.mixins import ActionMixin +from ..builtin.barcode.mixins import BarcodeMixin __all__ = [ 'AppMixin', @@ -12,4 +13,5 @@ __all__ = [ 'SettingsMixin', 'UrlsMixin', 'ActionMixin', + 'BarcodeMixin', ]