diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index 295937af08..2843dc4eb8 100644 --- a/InvenTree/InvenTree/helpers.py +++ b/InvenTree/InvenTree/helpers.py @@ -3,6 +3,8 @@ Provides helper functions used throughout the InvenTree project """ import io +import json +from datetime import datetime from wsgiref.util import FileWrapper from django.http import StreamingHttpResponse @@ -44,6 +46,29 @@ def WrapWithQuotes(text, quote='"'): return text +def MakeBarcode(object_type, object_id, object_url, data={}): + """ Generate a string for a barcode. Adds some global InvenTree parameters. + + Args: + object_type: string describing the object type e.g. 'StockItem' + object_id: ID (Primary Key) of the object in the database + object_url: url for JSON API detail view of the object + data: Python dict object containing extra datawhich will be rendered to string (must only contain stringable values) + + Returns: + json string of the supplied data plus some other data + """ + + # Add in some generic InvenTree data + data['type'] = object_type + data['id'] = object_id + data['url'] = object_url + data['tool'] = 'InvenTree' + data['generated'] = str(datetime.now().date()) + + return json.dumps(data, sort_keys=True) + + def DownloadFile(data, filename, content_type='application/text'): """ Create a dynamic file for the user to download. diff --git a/InvenTree/part/migrations/0014_auto_20190502_2039.py b/InvenTree/part/migrations/0014_auto_20190502_2039.py new file mode 100644 index 0000000000..c32c3afe32 --- /dev/null +++ b/InvenTree/part/migrations/0014_auto_20190502_2039.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2 on 2019-05-02 10:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0013_auto_20190429_2229'), + ] + + operations = [ + migrations.AlterField( + model_name='part', + name='URL', + field=models.URLField(blank=True, help_text='Link to extenal URL'), + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 820df63955..7bce91c26c 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -21,6 +21,7 @@ from django.core.validators import MinValueValidator from django.db.models.signals import pre_delete from django.dispatch import receiver +from InvenTree import helpers from InvenTree.models import InvenTreeTree from company.models import Company @@ -179,6 +180,16 @@ class Part(models.Model): def __str__(self): return "{n} - {d}".format(n=self.name, d=self.description) + @property + def format_barcode(self): + """ Return a JSON string for formatting a barcode for this Part object """ + + return helpers.MakeBarcode( + "Part", + self.id, + reverse('api-part-detail', kwargs={'pk': self.id}), + ) + class Meta: verbose_name = "Part" verbose_name_plural = "Parts" diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index 7b148318c9..f5941a7870 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -1,5 +1,6 @@ {% extends "part/part_base.html" %} {% load static %} +{% load qr_code %} {% block details %} {% include 'part/tabs.html' with tab='detail' %} @@ -115,6 +116,8 @@ {% endif %} +{% qr_from_text part.format_barcode size="s" image_format="png" error_correction="L" %} + {% endblock %} {% block js_load %} diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index 8604f54c8f..2690207f05 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -272,7 +272,6 @@ class StockList(generics.ListCreateAPIView): filter_fields = [ 'part', - 'uuid', 'supplier_part', 'customer', 'belongs_to', @@ -346,11 +345,11 @@ class LocationDetail(generics.RetrieveUpdateDestroyAPIView): stock_endpoints = [ - url(r'^$', StockDetail.as_view(), name='stockitem-detail'), + url(r'^$', StockDetail.as_view(), name='api-stock-detail'), ] location_endpoints = [ - url(r'^$', LocationDetail.as_view(), name='stocklocation-detail'), + url(r'^$', LocationDetail.as_view(), name='api-location-detail'), ] stock_api_urls = [ diff --git a/InvenTree/stock/migrations/0013_remove_stockitem_uuid.py b/InvenTree/stock/migrations/0013_remove_stockitem_uuid.py new file mode 100644 index 0000000000..79184862ed --- /dev/null +++ b/InvenTree/stock/migrations/0013_remove_stockitem_uuid.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2 on 2019-05-02 10:39 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0012_auto_20190502_0058'), + ] + + operations = [ + migrations.RemoveField( + model_name='stockitem', + name='uuid', + ), + ] diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index a2ccff16a6..7cdc45b7bc 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -17,7 +17,7 @@ from django.db.models.signals import pre_delete from django.dispatch import receiver from datetime import datetime -import uuid +from InvenTree import helpers from InvenTree.models import InvenTreeTree @@ -36,6 +36,19 @@ class StockLocation(InvenTreeTree): def has_items(self): return self.stock_items.count() > 0 + @property + def format_barcode(self): + """ Return a JSON string for formatting a barcode for this StockLocation object """ + + return helpers.MakeBarcode( + 'StockLocation', + self.id, + reverse('api-location-detail', kwargs={'pk': self.id}), + { + 'name': self.name, + } + ) + @receiver(pre_delete, sender=StockLocation, dispatch_uid='stocklocation_delete_log') def before_delete_stock_location(sender, instance, using, **kwargs): @@ -126,8 +139,27 @@ class StockItem(models.Model): ('part', 'serial'), ] - # UUID for generating QR codes - uuid = models.UUIDField(default=uuid.uuid4, blank=True, editable=False, help_text='Unique ID for the StockItem') + @property + def format_barcode(self): + """ Return a JSON string for formatting a barcode for this StockItem. + Can be used to perform lookup of a stockitem using barcode + + Contains the following data: + + { type: 'StockItem', stock_id: , part_id: } + + Voltagile data (e.g. stock quantity) should be looked up using the InvenTree API (as it may change) + """ + + return helpers.MakeBarcode( + 'StockItem', + self.id, + reverse('api-stock-detail', kwargs={'pk': self.id}), + { + 'part_id': self.part.id, + 'part_name': self.part.name + } + ) # The 'master' copy of the part of which this stock item is an instance part = models.ForeignKey('part.Part', on_delete=models.CASCADE, related_name='locations', help_text='Base part') diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index 269e3b4e78..fe8462b16c 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -38,7 +38,6 @@ class StockItemSerializerBrief(serializers.ModelSerializer): model = StockItem fields = [ 'pk', - 'uuid', 'part', 'part_name', 'supplier_part', @@ -65,7 +64,6 @@ class StockItemSerializer(serializers.ModelSerializer): model = StockItem fields = [ 'pk', - 'uuid', 'url', 'part', 'supplier_part', diff --git a/InvenTree/stock/templates/stock/item.html b/InvenTree/stock/templates/stock/item.html index cd2de3bf0d..30b7902886 100644 --- a/InvenTree/stock/templates/stock/item.html +++ b/InvenTree/stock/templates/stock/item.html @@ -39,10 +39,6 @@ Part {{ item.part.name }} - - UUID - {{ item.uuid }} - {% if item.belongs_to %} Belongs To @@ -114,7 +110,7 @@
- {% qr_from_text item.uuid size="s" image_format="png" error_correction="L" %} + {% qr_from_text item.format_barcode size="s" image_format="png" error_correction="L" %}
diff --git a/InvenTree/stock/templates/stock/location.html b/InvenTree/stock/templates/stock/location.html index 76891ad4cd..015a6673b4 100644 --- a/InvenTree/stock/templates/stock/location.html +++ b/InvenTree/stock/templates/stock/location.html @@ -1,5 +1,6 @@ {% extends "stock/stock_app_base.html" %} {% load static %} +{% load qr_code %} {% block content %}
+ {% qr_from_text location.format_barcode size="s" image_format="png" error_correction="L" %} {% endif %}