diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index 37a8bf82e1..6b76c7d41b 100644 --- a/InvenTree/InvenTree/helpers.py +++ b/InvenTree/InvenTree/helpers.py @@ -12,7 +12,7 @@ from decimal import Decimal from wsgiref.util import FileWrapper from django.http import StreamingHttpResponse -from django.core.exceptions import ValidationError +from django.core.exceptions import ValidationError, FieldError from django.utils.translation import ugettext as _ from django.contrib.auth.models import Permission @@ -414,7 +414,7 @@ def extract_serial_numbers(serials, expected_quantity): return numbers -def validateFilterString(value): +def validateFilterString(value, model=None): """ Validate that a provided filter string looks like a list of comma-separated key=value pairs @@ -464,6 +464,15 @@ def validateFilterString(value): results[k] = v + # If a model is provided, verify that the provided filters can be used against it + if model is not None: + try: + model.objects.filter(**results) + except FieldError as e: + raise ValidationError( + str(e), + ) + return results diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index 79c662182e..d8a64708a9 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -28,6 +28,7 @@ from company.api import company_api_urls from stock.api import stock_api_urls from build.api import build_api_urls from order.api import order_api_urls +from label.api import label_api_urls from django.conf import settings from django.conf.urls.static import static @@ -58,6 +59,7 @@ apipatterns = [ url(r'^stock/', include(stock_api_urls)), url(r'^build/', include(build_api_urls)), url(r'^order/', include(order_api_urls)), + url(r'^label/', include(label_api_urls)), # User URLs url(r'^user/', include(user_urls)), @@ -90,6 +92,7 @@ settings_urls = [ # Some javascript files are served 'dynamically', allowing them to pass through the Django translation layer dynamic_javascript_urls = [ + url(r'^modals.js', DynamicJsView.as_view(template_name='js/modals.js'), name='modals.js'), url(r'^barcode.js', DynamicJsView.as_view(template_name='js/barcode.js'), name='barcode.js'), url(r'^bom.js', DynamicJsView.as_view(template_name='js/bom.js'), name='bom.js'), url(r'^build.js', DynamicJsView.as_view(template_name='js/build.js'), name='build.js'), @@ -97,6 +100,7 @@ dynamic_javascript_urls = [ url(r'^company.js', DynamicJsView.as_view(template_name='js/company.js'), name='company.js'), url(r'^order.js', DynamicJsView.as_view(template_name='js/order.js'), name='order.js'), url(r'^part.js', DynamicJsView.as_view(template_name='js/part.js'), name='part.js'), + url(r'^label.js', DynamicJsView.as_view(template_name='js/label.js'), name='label.js'), url(r'^stock.js', DynamicJsView.as_view(template_name='js/stock.js'), name='stock.js'), url(r'^table_filters.js', DynamicJsView.as_view(template_name='js/table_filters.js'), name='table_filters.js'), ] diff --git a/InvenTree/label/admin.py b/InvenTree/label/admin.py index 71399efabb..2e4967ffc2 100644 --- a/InvenTree/label/admin.py +++ b/InvenTree/label/admin.py @@ -3,12 +3,13 @@ from __future__ import unicode_literals from django.contrib import admin -from .models import StockItemLabel +from .models import StockItemLabel, StockLocationLabel -class StockItemLabelAdmin(admin.ModelAdmin): +class LabelAdmin(admin.ModelAdmin): list_display = ('name', 'description', 'label', 'filters', 'enabled') -admin.site.register(StockItemLabel, StockItemLabelAdmin) +admin.site.register(StockItemLabel, LabelAdmin) +admin.site.register(StockLocationLabel, LabelAdmin) diff --git a/InvenTree/label/api.py b/InvenTree/label/api.py new file mode 100644 index 0000000000..48ead2f443 --- /dev/null +++ b/InvenTree/label/api.py @@ -0,0 +1,375 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import sys + +from django.utils.translation import ugettext as _ +from django.conf.urls import url, include + +from django_filters.rest_framework import DjangoFilterBackend + +from rest_framework import generics, filters +from rest_framework.response import Response + +import InvenTree.helpers + +from stock.models import StockItem, StockLocation + +from .models import StockItemLabel, StockLocationLabel +from .serializers import StockItemLabelSerializer, StockLocationLabelSerializer + + +class LabelListView(generics.ListAPIView): + """ + Generic API class for label templates + """ + + filter_backends = [ + DjangoFilterBackend, + filters.SearchFilter + ] + + filter_fields = [ + 'enabled', + ] + + search_fields = [ + 'name', + 'description', + ] + + +class StockItemLabelMixin: + """ + Mixin for extracting stock items from query params + """ + + def get_items(self): + """ + Return a list of requested stock items + """ + + items = [] + + params = self.request.query_params + + if 'items[]' in params: + items = params.getlist('items[]', []) + elif 'item' in params: + items = [params.get('item', None)] + + if type(items) not in [list, tuple]: + items = [items] + + valid_ids = [] + + for item in items: + try: + valid_ids.append(int(item)) + except (ValueError): + pass + + # List of StockItems which match provided values + valid_items = StockItem.objects.filter(pk__in=valid_ids) + + return valid_items + + +class StockItemLabelList(LabelListView, StockItemLabelMixin): + """ + API endpoint for viewing list of StockItemLabel objects. + + Filterable by: + + - enabled: Filter by enabled / disabled status + - item: Filter by single stock item + - items: Filter by list of stock items + + """ + + queryset = StockItemLabel.objects.all() + serializer_class = StockItemLabelSerializer + + def filter_queryset(self, queryset): + """ + Filter the StockItem label queryset. + """ + + queryset = super().filter_queryset(queryset) + + # List of StockItem objects to match against + items = self.get_items() + + # We wish to filter by stock items + if len(items) > 0: + """ + At this point, we are basically forced to be inefficient, + as we need to compare the 'filters' string of each label, + and see if it matches against each of the requested items. + + TODO: In the future, if this becomes excessively slow, it + will need to be readdressed. + """ + + # Keep track of which labels match every specified stockitem + valid_label_ids = set() + + for label in queryset.all(): + + matches = True + + # Filter string defined for the StockItemLabel object + filters = InvenTree.helpers.validateFilterString(label.filters) + + for item in items: + + item_query = StockItem.objects.filter(pk=item.pk) + + if not item_query.filter(**filters).exists(): + matches = False + break + + # Matched all items + if matches: + valid_label_ids.add(label.pk) + else: + continue + + # Reduce queryset to only valid matches + queryset = queryset.filter(pk__in=[pk for pk in valid_label_ids]) + + return queryset + + +class StockItemLabelDetail(generics.RetrieveUpdateDestroyAPIView): + """ + API endpoint for a single StockItemLabel object + """ + + queryset = StockItemLabel.objects.all() + serializer_class = StockItemLabelSerializer + + +class StockItemLabelPrint(generics.RetrieveAPIView, StockItemLabelMixin): + """ + API endpoint for printing a StockItemLabel object + """ + + queryset = StockItemLabel.objects.all() + serializer_class = StockItemLabelSerializer + + def get(self, request, *args, **kwargs): + """ + Check if valid stock item(s) have been provided. + """ + + items = self.get_items() + + if len(items) == 0: + # No valid items provided, return an error message + data = { + 'error': _('Must provide valid StockItem(s)'), + } + + return Response(data, status=400) + + label = self.get_object() + + try: + pdf = label.render(items) + except: + + e = sys.exc_info()[1] + + data = { + 'error': _('Error during label rendering'), + 'message': str(e), + } + + return Response(data, status=400) + + return InvenTree.helpers.DownloadFile( + pdf.getbuffer(), + 'stock_item_label.pdf', + content_type='application/pdf' + ) + + +class StockLocationLabelMixin: + """ + Mixin for extracting stock locations from query params + """ + + def get_locations(self): + """ + Return a list of requested stock locations + """ + + locations = [] + + params = self.request.query_params + + if 'locations[]' in params: + locations = params.getlist('locations[]', []) + elif 'location' in params: + locations = [params.get('location', None)] + + if type(locations) not in [list, tuple]: + locations = [locations] + + valid_ids = [] + + for loc in locations: + try: + valid_ids.append(int(loc)) + except (ValueError): + pass + + # List of StockLocation objects which match provided values + valid_locations = StockLocation.objects.filter(pk__in=valid_ids) + + return valid_locations + + +class StockLocationLabelList(LabelListView, StockLocationLabelMixin): + """ + API endpoint for viewiing list of StockLocationLabel objects. + + Filterable by: + + - enabled: Filter by enabled / disabled status + - location: Filter by a single stock location + - locations: Filter by list of stock locations + """ + + queryset = StockLocationLabel.objects.all() + serializer_class = StockLocationLabelSerializer + + def filter_queryset(self, queryset): + """ + Filter the StockLocationLabel queryset + """ + + queryset = super().filter_queryset(queryset) + + # List of StockLocation objects to match against + locations = self.get_locations() + + # We wish to filter by stock location(s) + if len(locations) > 0: + """ + At this point, we are basically forced to be inefficient, + as we need to compare the 'filters' string of each label, + and see if it matches against each of the requested items. + + TODO: In the future, if this becomes excessively slow, it + will need to be readdressed. + """ + + valid_label_ids = set() + + for label in queryset.all(): + + matches = True + + # Filter string defined for the StockLocationLabel object + filters = InvenTree.helpers.validateFilterString(label.filters) + + for loc in locations: + + loc_query = StockLocation.objects.filter(pk=loc.pk) + + if not loc_query.filter(**filters).exists(): + matches = False + break + + # Matched all items + if matches: + valid_label_ids.add(label.pk) + else: + continue + + # Reduce queryset to only valid matches + queryset = queryset.filter(pk__in=[pk for pk in valid_label_ids]) + + return queryset + + +class StockLocationLabelDetail(generics.RetrieveUpdateDestroyAPIView): + """ + API endpoint for a single StockLocationLabel object + """ + + queryset = StockLocationLabel.objects.all() + serializer_class = StockLocationLabelSerializer + + +class StockLocationLabelPrint(generics.RetrieveAPIView, StockLocationLabelMixin): + """ + API endpoint for printing a StockLocationLabel object + """ + + queryset = StockLocationLabel.objects.all() + seiralizers_class = StockLocationLabelSerializer + + def get(self, request, *args, **kwargs): + + locations = self.get_locations() + + if len(locations) == 0: + # No valid locations provided - return an error message + + return Response( + { + 'error': _('Must provide valid StockLocation(s)'), + }, + status=400, + ) + + label = self.get_object() + + try: + pdf = label.render(locations) + except: + e = sys.exc_info()[1] + + data = { + 'error': _('Error during label rendering'), + 'message': str(e), + } + + return Response(data, status=400) + + return InvenTree.helpers.DownloadFile( + pdf.getbuffer(), + 'stock_location_label.pdf', + content_type='application/pdf' + ) + + +label_api_urls = [ + + # Stock item labels + url(r'stock/', include([ + # Detail views + url(r'^(?P\d+)/', include([ + url(r'print/?', StockItemLabelPrint.as_view(), name='api-stockitem-label-print'), + url(r'^.*$', StockItemLabelDetail.as_view(), name='api-stockitem-label-detail'), + ])), + + # List view + url(r'^.*$', StockItemLabelList.as_view(), name='api-stockitem-label-list'), + ])), + + # Stock location labels + url(r'location/', include([ + # Detail views + url(r'^(?P\d+)/', include([ + url(r'print/?', StockLocationLabelPrint.as_view(), name='api-stocklocation-label-print'), + url(r'^.*$', StockLocationLabelDetail.as_view(), name='api-stocklocation-label-detail'), + ])), + + # List view + url(r'^.*$', StockLocationLabelList.as_view(), name='api-stocklocation-label-list'), + ])), +] diff --git a/InvenTree/label/apps.py b/InvenTree/label/apps.py index ea4fa152ff..321047a551 100644 --- a/InvenTree/label/apps.py +++ b/InvenTree/label/apps.py @@ -1,5 +1,168 @@ +import os +import shutil +import logging + from django.apps import AppConfig +from django.conf import settings + + +logger = logging.getLogger(__name__) class LabelConfig(AppConfig): name = 'label' + + def ready(self): + """ + This function is called whenever the label app is loaded + """ + + self.create_stock_item_labels() + self.create_stock_location_labels() + + def create_stock_item_labels(self): + """ + Create database entries for the default StockItemLabel templates, + if they do not already exist + """ + + try: + from .models import StockItemLabel + except: + # Database might not by ready yet + return + + src_dir = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + 'templates', + 'stockitem', + ) + + dst_dir = os.path.join( + settings.MEDIA_ROOT, + 'label', + 'inventree', + 'stockitem', + ) + + if not os.path.exists(dst_dir): + logger.info(f"Creating missing directory: '{dst_dir}'") + os.makedirs(dst_dir, exist_ok=True) + + labels = [ + { + 'file': 'qr.html', + 'name': 'QR Code', + 'description': 'Simple QR code label', + }, + ] + + for label in labels: + + filename = os.path.join( + 'label', + 'inventree', + 'stockitem', + label['file'], + ) + + # Check if the file exists in the media directory + src_file = os.path.join(src_dir, label['file']) + dst_file = os.path.join(settings.MEDIA_ROOT, filename) + + if not os.path.exists(dst_file): + logger.info(f"Copying label template '{dst_file}'") + shutil.copyfile(src_file, dst_file) + + try: + # Check if a label matching the template already exists + if StockItemLabel.objects.filter(label=filename).exists(): + continue + + logger.info(f"Creating entry for StockItemLabel '{label['name']}'") + + StockItemLabel.objects.create( + name=label['name'], + description=label['description'], + label=filename, + filters='', + enabled=True + ) + except: + pass + + def create_stock_location_labels(self): + """ + Create database entries for the default StockItemLocation templates, + if they do not already exist + """ + + try: + from .models import StockLocationLabel + except: + # Database might not yet be ready + return + + src_dir = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + 'templates', + 'stocklocation', + ) + + dst_dir = os.path.join( + settings.MEDIA_ROOT, + 'label', + 'inventree', + 'stocklocation', + ) + + if not os.path.exists(dst_dir): + logger.info(f"Creating missing directory: '{dst_dir}'") + os.makedirs(dst_dir, exist_ok=True) + + labels = [ + { + 'file': 'qr.html', + 'name': 'QR Code', + 'description': 'Simple QR code label', + }, + { + 'file': 'qr_and_text.html', + 'name': 'QR and text', + 'description': 'Label with QR code and name of location', + } + ] + + for label in labels: + + filename = os.path.join( + 'label', + 'inventree', + 'stocklocation', + label['file'], + ) + + # Check if the file exists in the media directory + src_file = os.path.join(src_dir, label['file']) + dst_file = os.path.join(settings.MEDIA_ROOT, filename) + + if not os.path.exists(dst_file): + logger.info(f"Copying label template '{dst_file}'") + shutil.copyfile(src_file, dst_file) + + try: + # Check if a label matching the template already exists + if StockLocationLabel.objects.filter(label=filename).exists(): + continue + + logger.info(f"Creating entry for StockLocationLabel '{label['name']}'") + + StockLocationLabel.objects.create( + name=label['name'], + description=label['description'], + label=filename, + filters='', + enabled=True + ) + except: + pass diff --git a/InvenTree/label/migrations/0003_stocklocationlabel.py b/InvenTree/label/migrations/0003_stocklocationlabel.py new file mode 100644 index 0000000000..d15fcfa396 --- /dev/null +++ b/InvenTree/label/migrations/0003_stocklocationlabel.py @@ -0,0 +1,30 @@ +# Generated by Django 3.0.7 on 2021-01-08 12:06 + +import InvenTree.helpers +import django.core.validators +from django.db import migrations, models +import label.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('label', '0002_stockitemlabel_enabled'), + ] + + operations = [ + migrations.CreateModel( + name='StockLocationLabel', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(help_text='Label name', max_length=100, unique=True)), + ('description', models.CharField(blank=True, help_text='Label description', max_length=250, null=True)), + ('label', models.FileField(help_text='Label template file', upload_to=label.models.rename_label, validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['html'])])), + ('filters', models.CharField(blank=True, help_text='Query filters (comma-separated list of key=value pairs', max_length=250, validators=[InvenTree.helpers.validateFilterString])), + ('enabled', models.BooleanField(default=True, help_text='Label template is enabled', verbose_name='Enabled')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/InvenTree/label/migrations/0004_auto_20210111_2302.py b/InvenTree/label/migrations/0004_auto_20210111_2302.py new file mode 100644 index 0000000000..5194a4bda1 --- /dev/null +++ b/InvenTree/label/migrations/0004_auto_20210111_2302.py @@ -0,0 +1,56 @@ +# Generated by Django 3.0.7 on 2021-01-11 12:02 + +import InvenTree.helpers +import django.core.validators +from django.db import migrations, models +import label.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('label', '0003_stocklocationlabel'), + ] + + operations = [ + migrations.AlterField( + model_name='stockitemlabel', + name='description', + field=models.CharField(blank=True, help_text='Label description', max_length=250, null=True, verbose_name='Description'), + ), + migrations.AlterField( + model_name='stockitemlabel', + name='filters', + field=models.CharField(blank=True, help_text='Query filters (comma-separated list of key=value pairs', max_length=250, validators=[InvenTree.helpers.validateFilterString], verbose_name='Filters'), + ), + migrations.AlterField( + model_name='stockitemlabel', + name='label', + field=models.FileField(help_text='Label template file', unique=True, upload_to=label.models.rename_label, validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['html'])], verbose_name='Label'), + ), + migrations.AlterField( + model_name='stockitemlabel', + name='name', + field=models.CharField(help_text='Label name', max_length=100, verbose_name='Name'), + ), + migrations.AlterField( + model_name='stocklocationlabel', + name='description', + field=models.CharField(blank=True, help_text='Label description', max_length=250, null=True, verbose_name='Description'), + ), + migrations.AlterField( + model_name='stocklocationlabel', + name='filters', + field=models.CharField(blank=True, help_text='Query filters (comma-separated list of key=value pairs', max_length=250, validators=[InvenTree.helpers.validateFilterString], verbose_name='Filters'), + ), + migrations.AlterField( + model_name='stocklocationlabel', + name='label', + field=models.FileField(help_text='Label template file', unique=True, upload_to=label.models.rename_label, validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['html'])], verbose_name='Label'), + ), + migrations.AlterField( + model_name='stocklocationlabel', + name='name', + field=models.CharField(help_text='Label name', max_length=100, verbose_name='Name'), + ), + ] diff --git a/InvenTree/label/migrations/0005_auto_20210113_2302.py b/InvenTree/label/migrations/0005_auto_20210113_2302.py new file mode 100644 index 0000000000..ad256412ac --- /dev/null +++ b/InvenTree/label/migrations/0005_auto_20210113_2302.py @@ -0,0 +1,24 @@ +# Generated by Django 3.0.7 on 2021-01-13 12:02 + +from django.db import migrations, models +import label.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('label', '0004_auto_20210111_2302'), + ] + + operations = [ + migrations.AlterField( + model_name='stockitemlabel', + name='filters', + field=models.CharField(blank=True, help_text='Query filters (comma-separated list of key=value pairs', max_length=250, validators=[label.models.validate_stock_item_filters], verbose_name='Filters'), + ), + migrations.AlterField( + model_name='stocklocationlabel', + name='filters', + field=models.CharField(blank=True, help_text='Query filters (comma-separated list of key=value pairs', max_length=250, validators=[label.models.validate_stock_location_filters], verbose_name='Filters'), + ), + ] diff --git a/InvenTree/label/models.py b/InvenTree/label/models.py index 49b07572a8..a34aa3831d 100644 --- a/InvenTree/label/models.py +++ b/InvenTree/label/models.py @@ -17,7 +17,7 @@ from django.utils.translation import gettext_lazy as _ from InvenTree.helpers import validateFilterString, normalize -from stock.models import StockItem +import stock.models def rename_label(instance, filename): @@ -28,6 +28,20 @@ def rename_label(instance, filename): return os.path.join('label', 'template', instance.SUBDIR, filename) +def validate_stock_item_filters(filters): + + filters = validateFilterString(filters, model=stock.models.StockItem) + + return filters + + +def validate_stock_location_filters(filters): + + filters = validateFilterString(filters, model=stock.models.StockLocation) + + return filters + + class LabelTemplate(models.Model): """ Base class for generic, filterable labels. @@ -50,30 +64,31 @@ class LabelTemplate(models.Model): ) name = models.CharField( - unique=True, blank=False, max_length=100, + verbose_name=_('Name'), help_text=_('Label name'), ) - description = models.CharField(max_length=250, help_text=_('Label description'), blank=True, null=True) + description = models.CharField( + max_length=250, + blank=True, null=True, + verbose_name=_('Description'), + help_text=_('Label description'), + ) label = models.FileField( upload_to=rename_label, + unique=True, blank=False, null=False, + verbose_name=_('Label'), help_text=_('Label template file'), validators=[FileExtensionValidator(allowed_extensions=['html'])], ) - filters = models.CharField( - blank=True, max_length=250, - help_text=_('Query filters (comma-separated list of key=value pairs'), - validators=[validateFilterString] - ) - enabled = models.BooleanField( default=True, + verbose_name=_('Enabled'), help_text=_('Label template is enabled'), - verbose_name=_('Enabled') ) def get_record_data(self, items): @@ -117,6 +132,14 @@ class StockItemLabel(LabelTemplate): SUBDIR = "stockitem" + filters = models.CharField( + blank=True, max_length=250, + help_text=_('Query filters (comma-separated list of key=value pairs'), + verbose_name=_('Filters'), + validators=[ + validate_stock_item_filters] + ) + def matches_stock_item(self, item): """ Test if this label template matches a given StockItem object @@ -124,7 +147,7 @@ class StockItemLabel(LabelTemplate): filters = validateFilterString(self.filters) - items = StockItem.objects.filter(**filters) + items = stock.models.StockItem.objects.filter(**filters) items = items.filter(pk=item.pk) @@ -153,3 +176,47 @@ class StockItemLabel(LabelTemplate): }) return records + + +class StockLocationLabel(LabelTemplate): + """ + Template for printing StockLocation labels + """ + + SUBDIR = "stocklocation" + + filters = models.CharField( + blank=True, max_length=250, + help_text=_('Query filters (comma-separated list of key=value pairs'), + verbose_name=_('Filters'), + validators=[ + validate_stock_location_filters] + ) + + def matches_stock_location(self, location): + """ + Test if this label template matches a given StockLocation object + """ + + filters = validateFilterString(self.filters) + + locs = stock.models.StockLocation.objects.filter(**filters) + + locs = locs.filter(pk=location.pk) + + return locs.exists() + + def get_record_data(self, locations): + """ + Generate context data for each provided StockLocation + """ + + records = [] + + for loc in locations: + + records.append({ + 'location': loc, + }) + + return records diff --git a/InvenTree/label/serializers.py b/InvenTree/label/serializers.py new file mode 100644 index 0000000000..c9d487af23 --- /dev/null +++ b/InvenTree/label/serializers.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from InvenTree.serializers import InvenTreeModelSerializer +from InvenTree.serializers import InvenTreeAttachmentSerializerField + +from .models import StockItemLabel, StockLocationLabel + + +class StockItemLabelSerializer(InvenTreeModelSerializer): + """ + Serializes a StockItemLabel object. + """ + + label = InvenTreeAttachmentSerializerField(required=True) + + class Meta: + model = StockItemLabel + fields = [ + 'pk', + 'name', + 'description', + 'label', + 'filters', + 'enabled', + ] + + +class StockLocationLabelSerializer(InvenTreeModelSerializer): + """ + Serializes a StockLocationLabel object + """ + + label = InvenTreeAttachmentSerializerField(required=True) + + class Meta: + model = StockLocationLabel + fields = [ + 'pk', + 'name', + 'description', + 'label', + 'filters', + 'enabled', + ] diff --git a/InvenTree/label/templates/stockitem/qr.html b/InvenTree/label/templates/stockitem/qr.html new file mode 100644 index 0000000000..9cd9d20769 --- /dev/null +++ b/InvenTree/label/templates/stockitem/qr.html @@ -0,0 +1,16 @@ + + + diff --git a/InvenTree/label/templates/stocklocation/qr.html b/InvenTree/label/templates/stocklocation/qr.html new file mode 100644 index 0000000000..8fb22fbb40 --- /dev/null +++ b/InvenTree/label/templates/stocklocation/qr.html @@ -0,0 +1,16 @@ + + + diff --git a/InvenTree/label/templates/stocklocation/qr_and_text.html b/InvenTree/label/templates/stocklocation/qr_and_text.html new file mode 100644 index 0000000000..9a555aca15 --- /dev/null +++ b/InvenTree/label/templates/stocklocation/qr_and_text.html @@ -0,0 +1,43 @@ + + + + +
+ {{ location.name }} +
+
+
+ Location ID: {{ location.pk }} +
+ + \ No newline at end of file diff --git a/InvenTree/label/tests.py b/InvenTree/label/tests.py index a39b155ac3..dcb051c929 100644 --- a/InvenTree/label/tests.py +++ b/InvenTree/label/tests.py @@ -1 +1,76 @@ -# Create your tests here. +# Tests for Part Parameters + +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import os + +from django.test import TestCase +from django.conf import settings +from django.core.exceptions import ValidationError + +from InvenTree.helpers import validateFilterString + +from .models import StockItemLabel, StockLocationLabel +from stock.models import StockItem + + +class LabelTest(TestCase): + + # TODO - Implement this test properly. Looks like apps.py is not run first + def _test_default_labels(self): + """ + Test that the default label templates are copied across + """ + + labels = StockItemLabel.objects.all() + + self.assertTrue(labels.count() > 0) + + labels = StockLocationLabel.objects.all() + + self.assertTrue(labels.count() > 0) + + # TODO - Implement this test properly. Looks like apps.py is not run first + def _test_default_files(self): + """ + Test that label files exist in the MEDIA directory + """ + + item_dir = os.path.join( + settings.MEDIA_ROOT, + 'label', + 'inventree', + 'stockitem', + ) + + files = os.listdir(item_dir) + + self.assertTrue(len(files) > 0) + + loc_dir = os.path.join( + settings.MEDIA_ROOT, + 'label', + 'inventree', + 'stocklocation', + ) + + files = os.listdir(loc_dir) + + self.assertTrue(len(files) > 0) + + def test_filters(self): + """ + Test the label filters + """ + + filter_string = "part__pk=10" + + filters = validateFilterString(filter_string, model=StockItem) + + self.assertEqual(type(filters), dict) + + bad_filter_string = "part_pk=10" + + with self.assertRaises(ValidationError): + validateFilterString(bad_filter_string, model=StockItem) diff --git a/InvenTree/locale/de/LC_MESSAGES/django.po b/InvenTree/locale/de/LC_MESSAGES/django.po index dd0eb2089c..76931db8fa 100644 --- a/InvenTree/locale/de/LC_MESSAGES/django.po +++ b/InvenTree/locale/de/LC_MESSAGES/django.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-01-14 17:54+1100\n" +"POT-Creation-Date: 2021-01-14 23:57+1100\n" "PO-Revision-Date: 2020-05-03 11:32+0200\n" "Last-Translator: Christian Schlüter \n" "Language-Team: C \n" @@ -61,8 +61,8 @@ msgstr "" msgid "Select Category" msgstr "Teilkategorie auswählen" -#: InvenTree/helpers.py:361 order/models.py:233 order/models.py:331 -#: stock/views.py:1660 +#: InvenTree/helpers.py:361 order/models.py:232 order/models.py:330 +#: stock/views.py:1573 msgid "Invalid quantity provided" msgstr "Keine gültige Menge" @@ -105,11 +105,11 @@ msgstr "Datei zum Anhängen auswählen" msgid "File comment" msgstr "Datei-Kommentar" -#: InvenTree/models.py:68 templates/js/stock.js:861 +#: InvenTree/models.py:68 templates/js/stock.js:873 msgid "User" msgstr "Benutzer" -#: InvenTree/models.py:106 part/models.py:647 +#: InvenTree/models.py:106 label/models.py:68 part/models.py:647 #: part/templates/part/params.html:24 templates/js/part.js:129 msgid "Name" msgstr "Name" @@ -120,19 +120,19 @@ msgstr "Name" msgid "Description (optional)" msgstr "Firmenbeschreibung" -#: InvenTree/settings.py:422 +#: InvenTree/settings.py:439 msgid "English" msgstr "Englisch" -#: InvenTree/settings.py:423 +#: InvenTree/settings.py:440 msgid "German" msgstr "Deutsch" -#: InvenTree/settings.py:424 +#: InvenTree/settings.py:441 msgid "French" msgstr "Französisch" -#: InvenTree/settings.py:425 +#: InvenTree/settings.py:442 msgid "Polish" msgstr "Polnisch" @@ -351,8 +351,8 @@ msgstr "" #: stock/templates/stock/item_base.html:46 #: stock/templates/stock/item_base.html:214 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:338 -#: templates/js/bom.js:195 templates/js/build.js:420 templates/js/stock.js:852 -#: templates/js/stock.js:1091 +#: templates/js/bom.js:195 templates/js/build.js:420 templates/js/stock.js:864 +#: templates/js/stock.js:1103 msgid "Quantity" msgstr "Anzahl" @@ -455,7 +455,7 @@ msgstr "Referenz" #: build/models.py:116 build/templates/build/detail.html:19 #: company/models.py:359 company/templates/company/detail.html:23 #: company/templates/company/supplier_part_base.html:61 -#: company/templates/company/supplier_part_detail.html:27 +#: company/templates/company/supplier_part_detail.html:27 label/models.py:75 #: order/templates/order/purchase_order_detail.html:161 part/models.py:671 #: part/templates/part/detail.html:51 part/templates/part/set_category.html:14 #: templates/InvenTree/search.html:147 @@ -463,7 +463,7 @@ msgstr "Referenz" #: templates/js/bom.js:549 templates/js/build.js:664 templates/js/company.js:56 #: templates/js/order.js:180 templates/js/order.js:274 templates/js/part.js:188 #: templates/js/part.js:271 templates/js/part.js:391 templates/js/part.js:572 -#: templates/js/stock.js:511 templates/js/stock.js:833 +#: templates/js/stock.js:511 templates/js/stock.js:845 msgid "Description" msgstr "Beschreibung" @@ -484,7 +484,7 @@ msgstr "Bestellung, die diesem Bau zugwiesen ist" #: build/models.py:134 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:78 -#: build/templates/build/detail.html:24 order/models.py:652 +#: build/templates/build/detail.html:24 order/models.py:651 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:148 #: order/templates/order/receive_parts.html:19 part/models.py:316 @@ -493,7 +493,7 @@ msgstr "Bestellung, die diesem Bau zugwiesen ist" #: templates/js/barcode.js:336 templates/js/bom.js:153 templates/js/bom.js:534 #: templates/js/build.js:669 templates/js/company.js:138 #: templates/js/part.js:252 templates/js/part.js:357 templates/js/stock.js:485 -#: templates/js/stock.js:1163 +#: templates/js/stock.js:1175 msgid "Part" msgstr "Teil" @@ -561,7 +561,7 @@ msgstr "Bau-Status" msgid "Build status code" msgstr "Bau-Statuscode" -#: build/models.py:194 stock/models.py:397 +#: build/models.py:194 stock/models.py:412 msgid "Batch Code" msgstr "Losnummer" @@ -569,7 +569,7 @@ msgstr "Losnummer" msgid "Batch code for this build output" msgstr "Chargennummer für diese Bau-Ausgabe" -#: build/models.py:205 order/models.py:437 +#: build/models.py:205 order/models.py:436 msgid "Target completion date" msgstr "" @@ -577,11 +577,11 @@ msgstr "" #: company/templates/company/supplier_part_base.html:68 #: company/templates/company/supplier_part_detail.html:24 #: part/templates/part/detail.html:80 part/templates/part/part_base.html:102 -#: stock/models.py:391 stock/templates/stock/item_base.html:297 +#: stock/models.py:406 stock/templates/stock/item_base.html:297 msgid "External Link" msgstr "Externer Link" -#: build/models.py:220 part/models.py:705 stock/models.py:393 +#: build/models.py:220 part/models.py:705 stock/models.py:408 msgid "Link to external URL" msgstr "Link zu einer externen URL" @@ -590,7 +590,7 @@ msgstr "Link zu einer externen URL" #: order/templates/order/purchase_order_detail.html:213 #: order/templates/order/so_tabs.html:23 part/models.py:831 #: part/templates/part/tabs.html:73 stock/forms.py:313 stock/forms.py:345 -#: stock/forms.py:373 stock/models.py:463 stock/models.py:1512 +#: stock/forms.py:373 stock/models.py:478 stock/models.py:1544 #: stock/templates/stock/tabs.html:26 templates/js/barcode.js:391 #: templates/js/bom.js:295 templates/js/stock.js:127 templates/js/stock.js:618 msgid "Notes" @@ -643,11 +643,11 @@ msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" "zugewiesene Anzahl ({n}) darf nicht die verfügbare ({q}) Anzahl überschreiten" -#: build/models.py:971 order/models.py:736 +#: build/models.py:971 order/models.py:735 msgid "StockItem is over-allocated" msgstr "Zu viele Lagerobjekte zugewiesen" -#: build/models.py:975 order/models.py:739 +#: build/models.py:975 order/models.py:738 msgid "Allocation quantity must be greater than zero" msgstr "Anzahl muss größer null sein" @@ -837,7 +837,7 @@ msgstr "Bau-Status" #: stock/templates/stock/item_base.html:343 templates/InvenTree/search.html:175 #: templates/js/barcode.js:42 templates/js/build.js:697 #: templates/js/order.js:185 templates/js/order.js:279 -#: templates/js/stock.js:584 templates/js/stock.js:1099 +#: templates/js/stock.js:584 templates/js/stock.js:1111 msgid "Status" msgstr "Status" @@ -861,7 +861,7 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:120 -#: build/templates/build/detail.html:82 order/models.py:650 +#: build/templates/build/detail.html:82 order/models.py:649 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_notes.html:10 @@ -1002,7 +1002,7 @@ msgstr "Hat dieses Teil Tracking für einzelne Objekte?" #: build/templates/build/detail.html:68 #: stock/templates/stock/item_base.html:262 templates/js/stock.js:592 -#: templates/js/stock.js:1106 templates/js/table_filters.js:80 +#: templates/js/stock.js:1118 templates/js/table_filters.js:80 #: templates/js/table_filters.js:161 msgid "Batch" msgstr "Los" @@ -1118,7 +1118,7 @@ msgstr "Lagerbestand dem Bau zuweisen" msgid "Create Build Output" msgstr "Bau-Ausgabe" -#: build/views.py:207 stock/models.py:872 stock/views.py:1681 +#: build/views.py:207 stock/models.py:887 stock/views.py:1594 #, fuzzy #| msgid "Serial numbers already exist: " msgid "Serial numbers already exist" @@ -1140,7 +1140,7 @@ msgstr "Bau entfernt" msgid "Confirm unallocation of build stock" msgstr "Zuweisungsaufhebung bestätigen" -#: build/views.py:303 build/views.py:388 stock/views.py:417 +#: build/views.py:303 build/views.py:388 stock/views.py:330 msgid "Check the confirmation box" msgstr "Bestätigungsbox bestätigen" @@ -1266,7 +1266,7 @@ msgid "Add Build Order Attachment" msgstr "Auftragsanhang hinzufügen" #: build/views.py:1060 order/views.py:113 order/views.py:166 part/views.py:170 -#: stock/views.py:180 +#: stock/views.py:179 msgid "Added attachment" msgstr "Anhang hinzugefügt" @@ -1282,7 +1282,7 @@ msgstr "Anhang aktualisiert" msgid "Delete Attachment" msgstr "Anhang löschen" -#: build/views.py:1123 order/views.py:242 order/views.py:257 stock/views.py:238 +#: build/views.py:1123 order/views.py:242 order/views.py:257 stock/views.py:237 msgid "Deleted attachment" msgstr "Anhang gelöscht" @@ -1710,7 +1710,7 @@ msgstr "Produziert diese Firma Teile?" msgid "Currency" msgstr "Währung bearbeiten" -#: company/models.py:313 stock/models.py:345 +#: company/models.py:313 stock/models.py:360 #: stock/templates/stock/item_base.html:194 msgid "Base Part" msgstr "Basisteil" @@ -1828,8 +1828,8 @@ msgid "Uses default currency" msgstr "Währung entfernen" #: company/templates/company/detail.html:62 -#: order/templates/order/sales_order_base.html:89 stock/models.py:380 -#: stock/models.py:381 stock/templates/stock/item_base.html:221 +#: order/templates/order/sales_order_base.html:89 stock/models.py:395 +#: stock/models.py:396 stock/templates/stock/item_base.html:221 #: templates/js/company.js:40 templates/js/order.js:261 msgid "Customer" msgstr "Kunde" @@ -1845,7 +1845,7 @@ msgstr "Neues Zuliefererteil anlegen" #: company/templates/company/detail_part.html:18 #: order/templates/order/purchase_order_detail.html:68 -#: part/templates/part/supplier.html:14 templates/js/stock.js:983 +#: part/templates/part/supplier.html:14 templates/js/stock.js:995 msgid "New Supplier Part" msgstr "Neues Zulieferer-Teil" @@ -1873,7 +1873,7 @@ msgid "Delete Parts" msgstr "Teile löschen" #: company/templates/company/detail_part.html:63 -#: part/templates/part/category.html:116 templates/js/stock.js:977 +#: part/templates/part/category.html:116 templates/js/stock.js:989 msgid "New Part" msgstr "Neues Teil" @@ -1966,7 +1966,7 @@ msgid "New Sales Order" msgstr "Neuer Auftrag" #: company/templates/company/supplier_part_base.html:6 -#: company/templates/company/supplier_part_base.html:19 stock/models.py:354 +#: company/templates/company/supplier_part_base.html:19 stock/models.py:369 #: stock/templates/stock/item_base.html:309 templates/js/company.js:180 msgid "Supplier Part" msgstr "Zulieferer-Teil" @@ -2127,7 +2127,7 @@ msgstr "Firma gelöscht" msgid "Edit Supplier Part" msgstr "Zuliefererteil bearbeiten" -#: company/views.py:295 templates/js/stock.js:984 +#: company/views.py:295 templates/js/stock.js:996 msgid "Create new Supplier Part" msgstr "Neues Zuliefererteil anlegen" @@ -2149,32 +2149,54 @@ msgstr "Preisstaffel bearbeiten" msgid "Delete Price Break" msgstr "Preisstaffel löschen" -#: label/models.py:55 +#: label/api.py:171 +#, fuzzy +#| msgid "Move Stock Items" +msgid "Must provide valid StockItem(s)" +msgstr "Lagerobjekte bewegen" + +#: label/api.py:185 label/api.py:337 +msgid "Error during label rendering" +msgstr "" + +#: label/api.py:324 +msgid "Must provide valid StockLocation(s)" +msgstr "" + +#: label/models.py:69 #, fuzzy #| msgid "Part name" msgid "Label name" msgstr "Name des Teils" -#: label/models.py:58 +#: label/models.py:76 #, fuzzy #| msgid "Part description" msgid "Label description" msgstr "Beschreibung des Teils" -#: label/models.py:63 +#: label/models.py:83 stock/forms.py:198 +msgid "Label" +msgstr "" + +#: label/models.py:84 msgid "Label template file" msgstr "" -#: label/models.py:69 -msgid "Query filters (comma-separated list of key=value pairs" +#: label/models.py:90 report/models.py:162 +msgid "Enabled" msgstr "" -#: label/models.py:75 +#: label/models.py:91 msgid "Label template is enabled" msgstr "" -#: label/models.py:76 report/models.py:162 -msgid "Enabled" +#: label/models.py:137 label/models.py:190 +msgid "Query filters (comma-separated list of key=value pairs" +msgstr "" + +#: label/models.py:138 label/models.py:191 +msgid "Filters" msgstr "" #: order/forms.py:25 order/templates/order/order_base.html:44 @@ -2214,7 +2236,7 @@ msgstr "" msgid "Enter sales order number" msgstr "Auftrag stornieren" -#: order/forms.py:140 order/models.py:438 +#: order/forms.py:140 order/models.py:437 msgid "" "Target date for order completion. Order will be overdue after this date." msgstr "" @@ -2235,138 +2257,138 @@ msgstr "Link auf externe Seite" msgid "Order notes" msgstr "Bestell-Notizen" -#: order/models.py:172 order/models.py:431 +#: order/models.py:171 order/models.py:430 #, fuzzy #| msgid "Purchase Order Details" msgid "Purchase order status" msgstr "Bestelldetails" -#: order/models.py:180 +#: order/models.py:179 msgid "Company from which the items are being ordered" msgstr "" -#: order/models.py:183 +#: order/models.py:182 msgid "Supplier order reference code" msgstr "Bestellreferenz" -#: order/models.py:194 +#: order/models.py:193 #, fuzzy #| msgid "Issue Order" msgid "Issue Date" msgstr "Bestellung aufgeben" -#: order/models.py:195 +#: order/models.py:194 msgid "Date order was issued" msgstr "" -#: order/models.py:200 +#: order/models.py:199 #, fuzzy #| msgid "Shipment Date" msgid "Target Delivery Date" msgstr "Versanddatum" -#: order/models.py:201 +#: order/models.py:200 msgid "" "Expected date for order delivery. Order will be overdue after this date." msgstr "" -#: order/models.py:206 +#: order/models.py:205 #, fuzzy #| msgid "Creation Date" msgid "Completion Date" msgstr "Erstelldatum" -#: order/models.py:207 +#: order/models.py:206 #, fuzzy #| msgid "Mark order as complete" msgid "Date order was completed" msgstr "Bestellung als vollständig markieren" -#: order/models.py:231 order/models.py:329 part/views.py:1504 -#: stock/models.py:251 stock/models.py:856 +#: order/models.py:230 order/models.py:328 part/views.py:1504 +#: stock/models.py:259 stock/models.py:871 msgid "Quantity must be greater than zero" msgstr "Anzahl muss größer Null sein" -#: order/models.py:236 +#: order/models.py:235 msgid "Part supplier must match PO supplier" msgstr "Teile-Zulieferer muss dem Zulieferer des Kaufvertrags entsprechen" -#: order/models.py:324 +#: order/models.py:323 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "Nur Teile aufgegebener Bestllungen können empfangen werden" -#: order/models.py:427 +#: order/models.py:426 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:433 +#: order/models.py:432 msgid "Customer order reference code" msgstr "Bestellreferenz" -#: order/models.py:491 +#: order/models.py:490 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "Bestellung kann nicht versendet werden weil sie nicht anhängig ist" -#: order/models.py:578 +#: order/models.py:577 msgid "Item quantity" msgstr "Anzahl" -#: order/models.py:580 +#: order/models.py:579 msgid "Line item reference" msgstr "Position - Referenz" -#: order/models.py:582 +#: order/models.py:581 msgid "Line item notes" msgstr "Position - Notizen" -#: order/models.py:608 order/templates/order/order_base.html:9 +#: order/models.py:607 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: stock/templates/stock/item_base.html:276 templates/js/order.js:145 msgid "Purchase Order" msgstr "Kaufvertrag" -#: order/models.py:621 +#: order/models.py:620 msgid "Supplier part" msgstr "Zulieferer-Teil" -#: order/models.py:624 +#: order/models.py:623 msgid "Number of items received" msgstr "Empfangene Objekt-Anzahl" -#: order/models.py:631 stock/models.py:473 +#: order/models.py:630 stock/models.py:488 #: stock/templates/stock/item_base.html:283 #, fuzzy #| msgid "Purchase Order" msgid "Purchase Price" msgstr "Kaufvertrag" -#: order/models.py:632 +#: order/models.py:631 #, fuzzy #| msgid "Purchase Order" msgid "Unit purchase price" msgstr "Kaufvertrag" -#: order/models.py:727 +#: order/models.py:726 msgid "Cannot allocate stock item to a line with a different part" msgstr "Kann Lagerobjekt keiner Zeile mit einem anderen Teil hinzufügen" -#: order/models.py:729 +#: order/models.py:728 msgid "Cannot allocate stock to a line without a part" msgstr "Kann Lagerobjekt keiner Zeile ohne Teil hinzufügen" -#: order/models.py:732 +#: order/models.py:731 msgid "Allocation quantity cannot exceed stock quantity" msgstr "zugewiesene Anzahl darf nicht die verfügbare Anzahl überschreiten" -#: order/models.py:742 +#: order/models.py:741 msgid "Quantity must be 1 for serialized stock item" msgstr "Anzahl muss 1 für Objekte mit Seriennummer sein" -#: order/models.py:758 +#: order/models.py:757 msgid "Select stock item to allocate" msgstr "Lagerobjekt für Zuordnung auswählen" -#: order/models.py:761 +#: order/models.py:760 msgid "Enter stock allocation quantity" msgstr "Zuordnungsanzahl eingeben" @@ -2509,7 +2531,7 @@ msgstr "Bestellpositionen" #: order/templates/order/purchase_order_detail.html:39 #: order/templates/order/purchase_order_detail.html:119 #: part/templates/part/category.html:173 part/templates/part/category.html:215 -#: templates/js/stock.js:642 templates/js/stock.js:989 +#: templates/js/stock.js:642 templates/js/stock.js:1001 msgid "New Location" msgstr "Neuer Standort" @@ -2598,7 +2620,7 @@ msgid "Sales Order Items" msgstr "Auftragspositionen" #: order/templates/order/sales_order_detail.html:72 -#: order/templates/order/sales_order_detail.html:154 stock/models.py:385 +#: order/templates/order/sales_order_detail.html:154 stock/models.py:400 #: stock/templates/stock/item_base.html:208 templates/js/build.js:418 msgid "Serial Number" msgstr "Seriennummer" @@ -3315,7 +3337,7 @@ msgid "BOM line checksum" msgstr "Prüfsumme der Stückliste" #: part/models.py:1963 part/views.py:1510 part/views.py:1562 -#: stock/models.py:241 +#: stock/models.py:249 #, fuzzy #| msgid "Overage must be an integer value or a percentage" msgid "Quantity must be integer value for trackable parts" @@ -3362,7 +3384,7 @@ msgstr "Bestellung" #: stock/templates/stock/item_base.html:72 #: stock/templates/stock/item_base.html:291 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:751 -#: templates/js/stock.js:822 templates/js/stock.js:1082 +#: templates/js/stock.js:834 templates/js/stock.js:1094 msgid "Stock Item" msgstr "Lagerobjekt" @@ -3649,7 +3671,7 @@ msgstr "Teilkategorie anlegen" msgid "Create new Part Category" msgstr "Teilkategorie anlegen" -#: part/templates/part/category.html:216 stock/views.py:1363 +#: part/templates/part/category.html:216 stock/views.py:1276 msgid "Create new Stock Location" msgstr "Neuen Lager-Standort erstellen" @@ -3795,13 +3817,13 @@ msgstr "Parameter hinzufügen" msgid "New Parameter" msgstr "Neuer Parameter" -#: part/templates/part/params.html:25 stock/models.py:1499 +#: part/templates/part/params.html:25 stock/models.py:1531 #: templates/InvenTree/settings/header.html:8 templates/js/stock.js:123 msgid "Value" msgstr "Wert" #: part/templates/part/params.html:41 part/templates/part/related.html:41 -#: part/templates/part/supplier.html:19 users/models.py:158 +#: part/templates/part/supplier.html:19 users/models.py:159 msgid "Delete" msgstr "Löschen" @@ -4126,7 +4148,7 @@ msgstr "Teil kopiert" msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:594 templates/js/stock.js:978 +#: part/views.py:594 templates/js/stock.js:990 msgid "Create New Part" msgstr "Neues Teil anlegen" @@ -4336,10 +4358,6 @@ msgstr "Einstellungs-Beschreibung" msgid "Enter unique serial numbers (or leave blank)" msgstr "Eindeutige Seriennummern eingeben (oder leer lassen)" -#: stock/forms.py:198 -msgid "Label" -msgstr "" - #: stock/forms.py:199 stock/forms.py:255 #, fuzzy #| msgid "Select stock item to allocate" @@ -4400,7 +4418,7 @@ msgstr "Ziel-Lagerbestand" msgid "Add note (required)" msgstr "" -#: stock/forms.py:377 stock/views.py:935 stock/views.py:1133 +#: stock/forms.py:377 stock/views.py:848 stock/views.py:1046 msgid "Confirm stock adjustment" msgstr "Bestands-Anpassung bestätigen" @@ -4418,272 +4436,272 @@ msgstr "Standard-Lagerort" msgid "Set the destination as the default location for selected parts" msgstr "Setze das Ziel als Standard-Ziel für ausgewählte Teile" -#: stock/models.py:186 +#: stock/models.py:194 #, fuzzy #| msgid "Created new stock item" msgid "Created stock item" msgstr "Neues Lagerobjekt erstellt" -#: stock/models.py:222 +#: stock/models.py:230 #, fuzzy #| msgid "A stock item with this serial number already exists" msgid "StockItem with this serial number already exists" msgstr "Ein Teil mit dieser Seriennummer existiert bereits" -#: stock/models.py:258 +#: stock/models.py:266 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "Teile-Typ ('{pf}') muss {pe} sein" -#: stock/models.py:268 stock/models.py:277 +#: stock/models.py:276 stock/models.py:285 msgid "Quantity must be 1 for item with a serial number" msgstr "Anzahl muss für Objekte mit Seriennummer \"1\" sein" -#: stock/models.py:269 +#: stock/models.py:277 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" "Seriennummer kann nicht gesetzt werden wenn die Anzahl größer als \"1\" ist" -#: stock/models.py:291 +#: stock/models.py:299 msgid "Item cannot belong to itself" msgstr "Teil kann nicht zu sich selbst gehören" -#: stock/models.py:297 +#: stock/models.py:305 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:304 +#: stock/models.py:312 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:337 +#: stock/models.py:352 msgid "Parent Stock Item" msgstr "Eltern-Lagerobjekt" -#: stock/models.py:346 +#: stock/models.py:361 msgid "Base part" msgstr "Basis-Teil" -#: stock/models.py:355 +#: stock/models.py:370 msgid "Select a matching supplier part for this stock item" msgstr "Passenden Zulieferer für dieses Lagerobjekt auswählen" -#: stock/models.py:360 stock/templates/stock/stock_app_base.html:7 +#: stock/models.py:375 stock/templates/stock/stock_app_base.html:7 msgid "Stock Location" msgstr "Lagerort" -#: stock/models.py:363 +#: stock/models.py:378 msgid "Where is this stock item located?" msgstr "Wo wird dieses Teil normalerweise gelagert?" -#: stock/models.py:368 stock/templates/stock/item_base.html:229 +#: stock/models.py:383 stock/templates/stock/item_base.html:229 msgid "Installed In" msgstr "Installiert in" -#: stock/models.py:371 +#: stock/models.py:386 msgid "Is this item installed in another item?" msgstr "Ist dieses Teil in einem anderen verbaut?" -#: stock/models.py:387 +#: stock/models.py:402 msgid "Serial number for this item" msgstr "Seriennummer für dieses Teil" -#: stock/models.py:399 +#: stock/models.py:414 msgid "Batch code for this stock item" msgstr "Losnummer für dieses Lagerobjekt" -#: stock/models.py:403 +#: stock/models.py:418 msgid "Stock Quantity" msgstr "Bestand" -#: stock/models.py:412 +#: stock/models.py:427 msgid "Source Build" msgstr "Quellbau" -#: stock/models.py:414 +#: stock/models.py:429 msgid "Build for this stock item" msgstr "Bau für dieses Lagerobjekt" -#: stock/models.py:425 +#: stock/models.py:440 msgid "Source Purchase Order" msgstr "Quellbestellung" -#: stock/models.py:428 +#: stock/models.py:443 msgid "Purchase order for this stock item" msgstr "Bestellung für dieses Teil" -#: stock/models.py:434 +#: stock/models.py:449 msgid "Destination Sales Order" msgstr "Zielauftrag" -#: stock/models.py:440 stock/templates/stock/item_base.html:316 +#: stock/models.py:455 stock/templates/stock/item_base.html:316 #: templates/js/stock.js:612 #, fuzzy #| msgid "Export" msgid "Expiry Date" msgstr "Exportieren" -#: stock/models.py:441 +#: stock/models.py:456 msgid "" "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:454 +#: stock/models.py:469 msgid "Delete this Stock Item when stock is depleted" msgstr "Objekt löschen wenn Lagerbestand aufgebraucht" -#: stock/models.py:464 stock/templates/stock/item_notes.html:14 +#: stock/models.py:479 stock/templates/stock/item_notes.html:14 #: stock/templates/stock/item_notes.html:30 msgid "Stock Item Notes" msgstr "Lagerobjekt-Notizen" -#: stock/models.py:474 +#: stock/models.py:489 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:574 +#: stock/models.py:589 #, fuzzy #| msgid "Item assigned to customer?" msgid "Assigned to Customer" msgstr "Ist dieses Objekt einem Kunden zugeteilt?" -#: stock/models.py:576 +#: stock/models.py:591 #, fuzzy #| msgid "Item assigned to customer?" msgid "Manually assigned to customer" msgstr "Ist dieses Objekt einem Kunden zugeteilt?" -#: stock/models.py:589 +#: stock/models.py:604 #, fuzzy #| msgid "Item assigned to customer?" msgid "Returned from customer" msgstr "Ist dieses Objekt einem Kunden zugeteilt?" -#: stock/models.py:591 +#: stock/models.py:606 #, fuzzy #| msgid "Create new stock location" msgid "Returned to location" msgstr "Neuen Lagerort anlegen" -#: stock/models.py:716 +#: stock/models.py:731 #, fuzzy #| msgid "Installed in Stock Item" msgid "Installed into stock item" msgstr "In Lagerobjekt installiert" -#: stock/models.py:724 +#: stock/models.py:739 #, fuzzy #| msgid "Installed in Stock Item" msgid "Installed stock item" msgstr "In Lagerobjekt installiert" -#: stock/models.py:748 +#: stock/models.py:763 #, fuzzy #| msgid "Installed in Stock Item" msgid "Uninstalled stock item" msgstr "In Lagerobjekt installiert" -#: stock/models.py:767 +#: stock/models.py:782 #, fuzzy #| msgid "Include sublocations" msgid "Uninstalled into location" msgstr "Unterlagerorte einschließen" -#: stock/models.py:847 +#: stock/models.py:862 #, fuzzy #| msgid "Part is not a virtual part" msgid "Part is not set as trackable" msgstr "Teil ist nicht virtuell" -#: stock/models.py:853 +#: stock/models.py:868 msgid "Quantity must be integer" msgstr "Anzahl muss eine Ganzzahl sein" -#: stock/models.py:859 +#: stock/models.py:874 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "Anzahl darf nicht die verfügbare Anzahl überschreiten ({n})" -#: stock/models.py:862 +#: stock/models.py:877 msgid "Serial numbers must be a list of integers" msgstr "Seriennummern muss eine Liste von Ganzzahlen sein" -#: stock/models.py:865 +#: stock/models.py:880 msgid "Quantity does not match serial numbers" msgstr "Anzahl stimmt nicht mit den Seriennummern überein" -#: stock/models.py:897 +#: stock/models.py:912 msgid "Add serial number" msgstr "Seriennummer hinzufügen" -#: stock/models.py:900 +#: stock/models.py:915 #, python-brace-format msgid "Serialized {n} items" msgstr "{n} Teile serialisiert" -#: stock/models.py:1011 +#: stock/models.py:1026 msgid "StockItem cannot be moved as it is not in stock" msgstr "Lagerobjekt kann nicht bewegt werden, da kein Bestand vorhanden ist" -#: stock/models.py:1400 +#: stock/models.py:1432 msgid "Tracking entry title" msgstr "Name des Eintrags-Trackings" -#: stock/models.py:1402 +#: stock/models.py:1434 msgid "Entry notes" msgstr "Eintrags-Notizen" -#: stock/models.py:1404 +#: stock/models.py:1436 msgid "Link to external page for further information" msgstr "Link auf externe Seite für weitere Informationen" -#: stock/models.py:1464 +#: stock/models.py:1496 #, fuzzy #| msgid "Serial number for this item" msgid "Value must be provided for this test" msgstr "Seriennummer für dieses Teil" -#: stock/models.py:1470 +#: stock/models.py:1502 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1487 +#: stock/models.py:1519 msgid "Test" msgstr "" -#: stock/models.py:1488 +#: stock/models.py:1520 #, fuzzy #| msgid "Part name" msgid "Test name" msgstr "Name des Teils" -#: stock/models.py:1493 +#: stock/models.py:1525 #, fuzzy #| msgid "Search Results" msgid "Result" msgstr "Suchergebnisse" -#: stock/models.py:1494 templates/js/table_filters.js:172 +#: stock/models.py:1526 templates/js/table_filters.js:172 msgid "Test result" msgstr "" -#: stock/models.py:1500 +#: stock/models.py:1532 msgid "Test output value" msgstr "" -#: stock/models.py:1506 +#: stock/models.py:1538 #, fuzzy #| msgid "Attachments" msgid "Attachment" msgstr "Anhänge" -#: stock/models.py:1507 +#: stock/models.py:1539 #, fuzzy #| msgid "Delete attachment" msgid "Test result attachment" msgstr "Anhang löschen" -#: stock/models.py:1513 +#: stock/models.py:1545 #, fuzzy #| msgid "Edit notes" msgid "Test notes" @@ -4785,15 +4803,15 @@ msgid "Stock adjustment actions" msgstr "Bestands-Anpassung bestätigen" #: stock/templates/stock/item_base.html:141 -#: stock/templates/stock/location.html:41 templates/stock_table.html:23 +#: stock/templates/stock/location.html:41 templates/stock_table.html:24 msgid "Count stock" msgstr "Bestand zählen" -#: stock/templates/stock/item_base.html:142 templates/stock_table.html:21 +#: stock/templates/stock/item_base.html:142 templates/stock_table.html:22 msgid "Add stock" msgstr "Bestand hinzufügen" -#: stock/templates/stock/item_base.html:143 templates/stock_table.html:22 +#: stock/templates/stock/item_base.html:143 templates/stock_table.html:23 msgid "Remove stock" msgstr "Bestand entfernen" @@ -4821,7 +4839,7 @@ msgstr "Ist dieses Objekt einem Kunden zugeteilt?" msgid "Return to stock" msgstr "Bestand zählen" -#: stock/templates/stock/item_base.html:158 templates/js/stock.js:1119 +#: stock/templates/stock/item_base.html:158 templates/js/stock.js:1131 #, fuzzy #| msgid "Installed in Stock Item" msgid "Uninstall stock item" @@ -5048,7 +5066,7 @@ msgstr "Sind Sie sicher, dass Sie diesen Anhang löschen wollen?" msgid "The following stock items will be uninstalled" msgstr "Die folgenden Objekte werden erstellt" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1335 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1248 #, fuzzy #| msgid "Count Stock Items" msgid "Convert Stock Item" @@ -5086,243 +5104,231 @@ msgstr "Kinder" msgid "Installed Items" msgstr "Installiert in" -#: stock/views.py:123 +#: stock/views.py:122 msgid "Edit Stock Location" msgstr "Lagerobjekt-Standort bearbeiten" -#: stock/views.py:148 +#: stock/views.py:147 msgid "Stock Location QR code" msgstr "QR-Code für diesen Standort" -#: stock/views.py:167 +#: stock/views.py:166 #, fuzzy #| msgid "Add Attachment" msgid "Add Stock Item Attachment" msgstr "Anhang hinzufügen" -#: stock/views.py:214 +#: stock/views.py:213 #, fuzzy #| msgid "Edit Stock Item" msgid "Edit Stock Item Attachment" msgstr "Lagerobjekt bearbeiten" -#: stock/views.py:231 +#: stock/views.py:230 #, fuzzy #| msgid "Delete Part Attachment" msgid "Delete Stock Item Attachment" msgstr "Teilanhang löschen" -#: stock/views.py:248 +#: stock/views.py:247 #, fuzzy #| msgid "Item assigned to customer?" msgid "Assign to Customer" msgstr "Ist dieses Objekt einem Kunden zugeteilt?" -#: stock/views.py:258 +#: stock/views.py:257 msgid "Customer must be specified" msgstr "" -#: stock/views.py:282 +#: stock/views.py:281 #, fuzzy #| msgid "Part Stock" msgid "Return to Stock" msgstr "Teilbestand" -#: stock/views.py:292 +#: stock/views.py:291 #, fuzzy #| msgid "Include sublocations" msgid "Specify a valid location" msgstr "Unterlagerorte einschließen" -#: stock/views.py:303 +#: stock/views.py:302 msgid "Stock item returned from customer" msgstr "" #: stock/views.py:313 #, fuzzy -#| msgid "Select valid part" -msgid "Select Label Template" -msgstr "Bitte ein gültiges Teil auswählen" - -#: stock/views.py:336 -#, fuzzy -#| msgid "Select valid part" -msgid "Select valid label" -msgstr "Bitte ein gültiges Teil auswählen" - -#: stock/views.py:400 -#, fuzzy #| msgid "Delete Template" msgid "Delete All Test Data" msgstr "Vorlage löschen" -#: stock/views.py:416 +#: stock/views.py:329 #, fuzzy #| msgid "Confirm Part Deletion" msgid "Confirm test data deletion" msgstr "Löschen des Teils bestätigen" -#: stock/views.py:436 +#: stock/views.py:349 msgid "Add Test Result" msgstr "" -#: stock/views.py:477 +#: stock/views.py:390 #, fuzzy #| msgid "Edit Template" msgid "Edit Test Result" msgstr "Vorlage bearbeiten" -#: stock/views.py:495 +#: stock/views.py:408 #, fuzzy #| msgid "Delete Template" msgid "Delete Test Result" msgstr "Vorlage löschen" -#: stock/views.py:507 +#: stock/views.py:420 #, fuzzy #| msgid "Delete Template" msgid "Select Test Report Template" msgstr "Vorlage löschen" -#: stock/views.py:537 +#: stock/views.py:450 #, fuzzy #| msgid "Select valid part" msgid "Select valid template" msgstr "Bitte ein gültiges Teil auswählen" -#: stock/views.py:590 +#: stock/views.py:503 msgid "Stock Export Options" msgstr "Lagerbestandsexportoptionen" -#: stock/views.py:712 +#: stock/views.py:625 msgid "Stock Item QR Code" msgstr "Lagerobjekt-QR-Code" -#: stock/views.py:738 +#: stock/views.py:651 #, fuzzy #| msgid "Installed in Stock Item" msgid "Install Stock Item" msgstr "In Lagerobjekt installiert" -#: stock/views.py:838 +#: stock/views.py:751 #, fuzzy #| msgid "Installed in Stock Item" msgid "Uninstall Stock Items" msgstr "In Lagerobjekt installiert" -#: stock/views.py:946 +#: stock/views.py:859 #, fuzzy #| msgid "Installed in Stock Item" msgid "Uninstalled stock items" msgstr "In Lagerobjekt installiert" -#: stock/views.py:971 +#: stock/views.py:884 msgid "Adjust Stock" msgstr "Lagerbestand anpassen" -#: stock/views.py:1081 +#: stock/views.py:994 msgid "Move Stock Items" msgstr "Lagerobjekte bewegen" -#: stock/views.py:1082 +#: stock/views.py:995 msgid "Count Stock Items" msgstr "Lagerobjekte zählen" -#: stock/views.py:1083 +#: stock/views.py:996 msgid "Remove From Stock" msgstr "Aus Lagerbestand entfernen" -#: stock/views.py:1084 +#: stock/views.py:997 msgid "Add Stock Items" msgstr "Lagerobjekte hinzufügen" -#: stock/views.py:1085 +#: stock/views.py:998 msgid "Delete Stock Items" msgstr "Lagerobjekte löschen" -#: stock/views.py:1113 +#: stock/views.py:1026 msgid "Must enter integer value" msgstr "Nur Ganzzahl eingeben" -#: stock/views.py:1118 +#: stock/views.py:1031 msgid "Quantity must be positive" msgstr "Anzahl muss positiv sein" -#: stock/views.py:1125 +#: stock/views.py:1038 #, python-brace-format msgid "Quantity must not exceed {x}" msgstr "Anzahl darf {x} nicht überschreiten" -#: stock/views.py:1204 +#: stock/views.py:1117 #, python-brace-format msgid "Added stock to {n} items" msgstr "Vorrat zu {n} Lagerobjekten hinzugefügt" -#: stock/views.py:1219 +#: stock/views.py:1132 #, python-brace-format msgid "Removed stock from {n} items" msgstr "Vorrat von {n} Lagerobjekten entfernt" -#: stock/views.py:1232 +#: stock/views.py:1145 #, python-brace-format msgid "Counted stock for {n} items" msgstr "Bestand für {n} Objekte erfasst" -#: stock/views.py:1260 +#: stock/views.py:1173 msgid "No items were moved" msgstr "Keine Lagerobjekte wurden bewegt" -#: stock/views.py:1263 +#: stock/views.py:1176 #, python-brace-format msgid "Moved {n} items to {dest}" msgstr "{n} Teile nach {dest} bewegt" -#: stock/views.py:1282 +#: stock/views.py:1195 #, python-brace-format msgid "Deleted {n} stock items" msgstr "{n} Teile im Lager gelöscht" -#: stock/views.py:1294 +#: stock/views.py:1207 msgid "Edit Stock Item" msgstr "Lagerobjekt bearbeiten" -#: stock/views.py:1385 +#: stock/views.py:1298 msgid "Serialize Stock" msgstr "Lagerbestand erfassen" -#: stock/views.py:1479 templates/js/build.js:210 +#: stock/views.py:1392 templates/js/build.js:210 msgid "Create new Stock Item" msgstr "Neues Lagerobjekt hinzufügen" -#: stock/views.py:1587 +#: stock/views.py:1500 #, fuzzy #| msgid "Count stock items" msgid "Duplicate Stock Item" msgstr "Lagerobjekte zählen" -#: stock/views.py:1664 +#: stock/views.py:1577 #, fuzzy #| msgid "Quantity must be greater than zero" msgid "Quantity cannot be negative" msgstr "Anzahl muss größer Null sein" -#: stock/views.py:1750 +#: stock/views.py:1663 msgid "Delete Stock Location" msgstr "Standort löschen" -#: stock/views.py:1764 +#: stock/views.py:1677 msgid "Delete Stock Item" msgstr "Lagerobjekt löschen" -#: stock/views.py:1776 +#: stock/views.py:1689 msgid "Delete Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag löschen" -#: stock/views.py:1795 +#: stock/views.py:1708 msgid "Edit Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag bearbeiten" -#: stock/views.py:1805 +#: stock/views.py:1718 msgid "Add Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag hinzufügen" @@ -5720,7 +5726,7 @@ msgstr "Quell-Standort" msgid "Enter barcode data" msgstr "Keine Strichcodedaten bereitgestellt" -#: templates/js/barcode.js:42 +#: templates/js/barcode.js:42 templates/js/modals.js:856 msgid "Invalid server response" msgstr "" @@ -5905,7 +5911,7 @@ msgstr "Anzahl" msgid "Build stock" msgstr "Baue" -#: templates/js/build.js:582 templates/stock_table.html:25 +#: templates/js/build.js:582 templates/stock_table.html:26 msgid "Order stock" msgstr "Bestand bestellen" @@ -5955,6 +5961,162 @@ msgstr "Vorlagenteil" msgid "Assembled part" msgstr "Baugruppe" +#: templates/js/label.js:10 +#, fuzzy +#| msgid "Delete Stock Items" +msgid "Select Stock Items" +msgstr "Lagerobjekte löschen" + +#: templates/js/label.js:11 +#, fuzzy +#| msgid "StockItem has been allocated" +msgid "Stock item(s) must be selected before printing labels" +msgstr "Lagerobjekt wurde zugewiesen" + +#: templates/js/label.js:29 templates/js/label.js:79 +#, fuzzy +#| msgid "No parts found" +msgid "No Labels Found" +msgstr "Keine Teile gefunden" + +#: templates/js/label.js:30 +#, fuzzy +#| msgid "Remove selected BOM items" +msgid "No labels found which match selected stock item(s)" +msgstr "Ausgewählte Stücklistenpositionen entfernen" + +#: templates/js/label.js:61 +#, fuzzy +#| msgid "Delete Stock Location" +msgid "Select Stock Locations" +msgstr "Standort löschen" + +#: templates/js/label.js:62 +msgid "Stock location(s) must be selected before printing labels" +msgstr "" + +#: templates/js/label.js:80 +msgid "No labels found which match selected stock location(s)" +msgstr "" + +#: templates/js/label.js:141 +#, fuzzy +#| msgid "Select valid part" +msgid "Select Label" +msgstr "Bitte ein gültiges Teil auswählen" + +#: templates/js/label.js:156 +#, fuzzy +#| msgid "Select valid part" +msgid "Select Label Template" +msgstr "Bitte ein gültiges Teil auswählen" + +#: templates/js/modals.js:406 +#, fuzzy +#| msgid "Show pricing information" +msgid "Show Error Information" +msgstr "Kosteninformationen ansehen" + +#: templates/js/modals.js:473 +msgid "Accept" +msgstr "" + +#: templates/js/modals.js:474 +#, fuzzy +#| msgid "Cancelled" +msgid "Cancel" +msgstr "Storniert" + +#: templates/js/modals.js:538 +msgid "Loading Data" +msgstr "" + +#: templates/js/modals.js:549 templates/js/modals.js:807 +#: templates/modals.html:19 templates/modals.html:41 +#, fuzzy +#| msgid "Edit BOM" +msgid "Submit" +msgstr "Stückliste bearbeiten" + +#: templates/js/modals.js:550 templates/js/modals.js:808 +#: templates/modals.html:18 templates/modals.html:40 +msgid "Close" +msgstr "" + +#: templates/js/modals.js:759 +#, fuzzy +#| msgid "Unknown barcode format" +msgid "Invalid response from server" +msgstr "Unbekanntes Strichcode-Format" + +#: templates/js/modals.js:759 +msgid "Form data missing from server response" +msgstr "" + +#: templates/js/modals.js:772 +msgid "Error posting form data" +msgstr "" + +#: templates/js/modals.js:856 +msgid "JSON response missing form data" +msgstr "" + +#: templates/js/modals.js:866 +msgid "No Response" +msgstr "" + +#: templates/js/modals.js:867 +#, fuzzy +#| msgid "Unknown barcode format" +msgid "No response from the InvenTree server" +msgstr "Unbekanntes Strichcode-Format" + +#: templates/js/modals.js:871 +msgid "Error 400: Bad Request" +msgstr "" + +#: templates/js/modals.js:872 +msgid "Server returned error code 400" +msgstr "" + +#: templates/js/modals.js:876 +msgid "Error 401: Not Authenticated" +msgstr "" + +#: templates/js/modals.js:877 +#, fuzzy +#| msgid "Does this part have tracking for unique items?" +msgid "Authentication credentials not supplied" +msgstr "Hat dieses Teil Tracking für einzelne Objekte?" + +#: templates/js/modals.js:881 +msgid "Error 403: Permission Denied" +msgstr "" + +#: templates/js/modals.js:882 +msgid "You do not have the required permissions to access this function" +msgstr "" + +#: templates/js/modals.js:886 +msgid "Error 404: Resource Not Found" +msgstr "" + +#: templates/js/modals.js:887 +msgid "The requested resource could not be located on the server" +msgstr "" + +#: templates/js/modals.js:891 +msgid "Error 408: Timeout" +msgstr "" + +#: templates/js/modals.js:892 +msgid "Connection timeout while requesting data from server" +msgstr "" + +#: templates/js/modals.js:895 +msgid "Error requesting form data" +msgstr "" + #: templates/js/order.js:135 msgid "No purchase orders found" msgstr "Keine Bestellungen gefunden" @@ -5965,7 +6127,7 @@ msgstr "Keine Bestellungen gefunden" msgid "Order is overdue" msgstr "Bau-Zuweisung ist vollständig" -#: templates/js/order.js:193 templates/js/stock.js:804 +#: templates/js/order.js:193 templates/js/stock.js:816 msgid "Date" msgstr "Datum" @@ -6008,7 +6170,7 @@ msgid "No parts found" msgstr "Keine Teile gefunden" #: templates/js/part.js:343 templates/js/stock.js:473 -#: templates/js/stock.js:1151 +#: templates/js/stock.js:1163 msgid "Select" msgstr "Auswählen" @@ -6182,51 +6344,51 @@ msgstr "Löschen" msgid "Stocktake" msgstr "Letzte Inventur" -#: templates/js/stock.js:720 +#: templates/js/stock.js:732 #, fuzzy #| msgid "Stock status" msgid "Stock Status" msgstr "Bestandsstatus" -#: templates/js/stock.js:735 +#: templates/js/stock.js:747 #, fuzzy #| msgid "Stock status" msgid "Set Stock Status" msgstr "Bestandsstatus" -#: templates/js/stock.js:749 +#: templates/js/stock.js:761 #, fuzzy #| msgid "Select part to build" msgid "Select Status Code" msgstr "Teil für den Bau wählen" -#: templates/js/stock.js:750 +#: templates/js/stock.js:762 #, fuzzy #| msgid "StockItem has been allocated" msgid "Status code must be selected" msgstr "Lagerobjekt wurde zugewiesen" -#: templates/js/stock.js:870 +#: templates/js/stock.js:882 msgid "No user information" msgstr "Keine Benutzerinformation" -#: templates/js/stock.js:990 +#: templates/js/stock.js:1002 msgid "Create New Location" msgstr "Neuen Standort anlegen" -#: templates/js/stock.js:1089 +#: templates/js/stock.js:1101 #, fuzzy #| msgid "Serial Number" msgid "Serial" msgstr "Seriennummer" -#: templates/js/stock.js:1182 templates/js/table_filters.js:131 +#: templates/js/stock.js:1194 templates/js/table_filters.js:131 #, fuzzy #| msgid "Installed In" msgid "Installed" msgstr "Installiert in" -#: templates/js/stock.js:1207 +#: templates/js/stock.js:1219 #, fuzzy #| msgid "Installed In" msgid "Install item" @@ -6415,16 +6577,6 @@ msgstr "Käuflich" msgid "Form errors exist" msgstr "" -#: templates/modals.html:18 templates/modals.html:40 -msgid "Close" -msgstr "" - -#: templates/modals.html:19 templates/modals.html:41 -#, fuzzy -#| msgid "Edit BOM" -msgid "Submit" -msgstr "Stückliste bearbeiten" - #: templates/navbar.html:29 msgid "Buy" msgstr "Kaufen" @@ -6491,59 +6643,63 @@ msgstr "Bestellung aufgeben" msgid "Export Stock Information" msgstr "Lagerobjekt-Standort bearbeiten" -#: templates/stock_table.html:21 +#: templates/stock_table.html:20 +msgid "Print labels" +msgstr "" + +#: templates/stock_table.html:22 #, fuzzy #| msgid "Added stock to {n} items" msgid "Add to selected stock items" msgstr "Vorrat zu {n} Lagerobjekten hinzugefügt" -#: templates/stock_table.html:22 +#: templates/stock_table.html:23 #, fuzzy #| msgid "Remove selected BOM items" msgid "Remove from selected stock items" msgstr "Ausgewählte Stücklistenpositionen entfernen" -#: templates/stock_table.html:23 +#: templates/stock_table.html:24 #, fuzzy #| msgid "Delete Stock Item" msgid "Stocktake selected stock items" msgstr "Lagerobjekt löschen" -#: templates/stock_table.html:24 +#: templates/stock_table.html:25 #, fuzzy #| msgid "Delete Stock Item" msgid "Move selected stock items" msgstr "Lagerobjekt löschen" -#: templates/stock_table.html:24 +#: templates/stock_table.html:25 msgid "Move stock" msgstr "Bestand bewegen" -#: templates/stock_table.html:25 +#: templates/stock_table.html:26 #, fuzzy #| msgid "Remove selected BOM items" msgid "Order selected items" msgstr "Ausgewählte Stücklistenpositionen entfernen" -#: templates/stock_table.html:26 +#: templates/stock_table.html:27 #, fuzzy #| msgid "Settings" msgid "Change status" msgstr "Einstellungen" -#: templates/stock_table.html:26 +#: templates/stock_table.html:27 #, fuzzy #| msgid "Stock status" msgid "Change stock status" msgstr "Bestandsstatus" -#: templates/stock_table.html:29 +#: templates/stock_table.html:30 #, fuzzy #| msgid "Delete line item" msgid "Delete selected items" msgstr "Position löschen" -#: templates/stock_table.html:29 +#: templates/stock_table.html:30 msgid "Delete Stock" msgstr "Bestand löschen" @@ -6579,41 +6735,41 @@ msgstr "Revision" msgid "Important dates" msgstr "Stückliste importieren" -#: users/models.py:141 +#: users/models.py:142 msgid "Permission set" msgstr "" -#: users/models.py:149 +#: users/models.py:150 msgid "Group" msgstr "" -#: users/models.py:152 +#: users/models.py:153 msgid "View" msgstr "" -#: users/models.py:152 +#: users/models.py:153 msgid "Permission to view items" msgstr "" -#: users/models.py:154 +#: users/models.py:155 #, fuzzy #| msgid "Address" msgid "Add" msgstr "Adresse" -#: users/models.py:154 +#: users/models.py:155 msgid "Permission to add items" msgstr "" -#: users/models.py:156 +#: users/models.py:157 msgid "Change" msgstr "" -#: users/models.py:156 +#: users/models.py:157 msgid "Permissions to edit items" msgstr "" -#: users/models.py:158 +#: users/models.py:159 #, fuzzy #| msgid "Remove selected BOM items" msgid "Permission to delete items" diff --git a/InvenTree/locale/en/LC_MESSAGES/django.po b/InvenTree/locale/en/LC_MESSAGES/django.po index e5967684a0..7389af937b 100644 --- a/InvenTree/locale/en/LC_MESSAGES/django.po +++ b/InvenTree/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-01-14 17:54+1100\n" +"POT-Creation-Date: 2021-01-14 23:57+1100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -54,8 +54,8 @@ msgstr "" msgid "Select Category" msgstr "" -#: InvenTree/helpers.py:361 order/models.py:233 order/models.py:331 -#: stock/views.py:1660 +#: InvenTree/helpers.py:361 order/models.py:232 order/models.py:330 +#: stock/views.py:1573 msgid "Invalid quantity provided" msgstr "" @@ -95,11 +95,11 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 templates/js/stock.js:861 +#: InvenTree/models.py:68 templates/js/stock.js:873 msgid "User" msgstr "" -#: InvenTree/models.py:106 part/models.py:647 +#: InvenTree/models.py:106 label/models.py:68 part/models.py:647 #: part/templates/part/params.html:24 templates/js/part.js:129 msgid "Name" msgstr "" @@ -108,19 +108,19 @@ msgstr "" msgid "Description (optional)" msgstr "" -#: InvenTree/settings.py:422 +#: InvenTree/settings.py:439 msgid "English" msgstr "" -#: InvenTree/settings.py:423 +#: InvenTree/settings.py:440 msgid "German" msgstr "" -#: InvenTree/settings.py:424 +#: InvenTree/settings.py:441 msgid "French" msgstr "" -#: InvenTree/settings.py:425 +#: InvenTree/settings.py:442 msgid "Polish" msgstr "" @@ -315,8 +315,8 @@ msgstr "" #: stock/templates/stock/item_base.html:46 #: stock/templates/stock/item_base.html:214 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:338 -#: templates/js/bom.js:195 templates/js/build.js:420 templates/js/stock.js:852 -#: templates/js/stock.js:1091 +#: templates/js/bom.js:195 templates/js/build.js:420 templates/js/stock.js:864 +#: templates/js/stock.js:1103 msgid "Quantity" msgstr "" @@ -397,7 +397,7 @@ msgstr "" #: build/models.py:116 build/templates/build/detail.html:19 #: company/models.py:359 company/templates/company/detail.html:23 #: company/templates/company/supplier_part_base.html:61 -#: company/templates/company/supplier_part_detail.html:27 +#: company/templates/company/supplier_part_detail.html:27 label/models.py:75 #: order/templates/order/purchase_order_detail.html:161 part/models.py:671 #: part/templates/part/detail.html:51 part/templates/part/set_category.html:14 #: templates/InvenTree/search.html:147 @@ -405,7 +405,7 @@ msgstr "" #: templates/js/bom.js:549 templates/js/build.js:664 templates/js/company.js:56 #: templates/js/order.js:180 templates/js/order.js:274 templates/js/part.js:188 #: templates/js/part.js:271 templates/js/part.js:391 templates/js/part.js:572 -#: templates/js/stock.js:511 templates/js/stock.js:833 +#: templates/js/stock.js:511 templates/js/stock.js:845 msgid "Description" msgstr "" @@ -424,7 +424,7 @@ msgstr "" #: build/models.py:134 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:78 -#: build/templates/build/detail.html:24 order/models.py:652 +#: build/templates/build/detail.html:24 order/models.py:651 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:148 #: order/templates/order/receive_parts.html:19 part/models.py:316 @@ -433,7 +433,7 @@ msgstr "" #: templates/js/barcode.js:336 templates/js/bom.js:153 templates/js/bom.js:534 #: templates/js/build.js:669 templates/js/company.js:138 #: templates/js/part.js:252 templates/js/part.js:357 templates/js/stock.js:485 -#: templates/js/stock.js:1163 +#: templates/js/stock.js:1175 msgid "Part" msgstr "" @@ -491,7 +491,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:194 stock/models.py:397 +#: build/models.py:194 stock/models.py:412 msgid "Batch Code" msgstr "" @@ -499,7 +499,7 @@ msgstr "" msgid "Batch code for this build output" msgstr "" -#: build/models.py:205 order/models.py:437 +#: build/models.py:205 order/models.py:436 msgid "Target completion date" msgstr "" @@ -507,11 +507,11 @@ msgstr "" #: company/templates/company/supplier_part_base.html:68 #: company/templates/company/supplier_part_detail.html:24 #: part/templates/part/detail.html:80 part/templates/part/part_base.html:102 -#: stock/models.py:391 stock/templates/stock/item_base.html:297 +#: stock/models.py:406 stock/templates/stock/item_base.html:297 msgid "External Link" msgstr "" -#: build/models.py:220 part/models.py:705 stock/models.py:393 +#: build/models.py:220 part/models.py:705 stock/models.py:408 msgid "Link to external URL" msgstr "" @@ -520,7 +520,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:213 #: order/templates/order/so_tabs.html:23 part/models.py:831 #: part/templates/part/tabs.html:73 stock/forms.py:313 stock/forms.py:345 -#: stock/forms.py:373 stock/models.py:463 stock/models.py:1512 +#: stock/forms.py:373 stock/models.py:478 stock/models.py:1544 #: stock/templates/stock/tabs.html:26 templates/js/barcode.js:391 #: templates/js/bom.js:295 templates/js/stock.js:127 templates/js/stock.js:618 msgid "Notes" @@ -564,11 +564,11 @@ msgstr "" msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:971 order/models.py:736 +#: build/models.py:971 order/models.py:735 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:975 order/models.py:739 +#: build/models.py:975 order/models.py:738 msgid "Allocation quantity must be greater than zero" msgstr "" @@ -724,7 +724,7 @@ msgstr "" #: stock/templates/stock/item_base.html:343 templates/InvenTree/search.html:175 #: templates/js/barcode.js:42 templates/js/build.js:697 #: templates/js/order.js:185 templates/js/order.js:279 -#: templates/js/stock.js:584 templates/js/stock.js:1099 +#: templates/js/stock.js:584 templates/js/stock.js:1111 msgid "Status" msgstr "" @@ -746,7 +746,7 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:120 -#: build/templates/build/detail.html:82 order/models.py:650 +#: build/templates/build/detail.html:82 order/models.py:649 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_notes.html:10 @@ -854,7 +854,7 @@ msgstr "" #: build/templates/build/detail.html:68 #: stock/templates/stock/item_base.html:262 templates/js/stock.js:592 -#: templates/js/stock.js:1106 templates/js/table_filters.js:80 +#: templates/js/stock.js:1118 templates/js/table_filters.js:80 #: templates/js/table_filters.js:161 msgid "Batch" msgstr "" @@ -953,7 +953,7 @@ msgstr "" msgid "Create Build Output" msgstr "" -#: build/views.py:207 stock/models.py:872 stock/views.py:1681 +#: build/views.py:207 stock/models.py:887 stock/views.py:1594 msgid "Serial numbers already exist" msgstr "" @@ -969,7 +969,7 @@ msgstr "" msgid "Confirm unallocation of build stock" msgstr "" -#: build/views.py:303 build/views.py:388 stock/views.py:417 +#: build/views.py:303 build/views.py:388 stock/views.py:330 msgid "Check the confirmation box" msgstr "" @@ -1063,7 +1063,7 @@ msgid "Add Build Order Attachment" msgstr "" #: build/views.py:1060 order/views.py:113 order/views.py:166 part/views.py:170 -#: stock/views.py:180 +#: stock/views.py:179 msgid "Added attachment" msgstr "" @@ -1079,7 +1079,7 @@ msgstr "" msgid "Delete Attachment" msgstr "" -#: build/views.py:1123 order/views.py:242 order/views.py:257 stock/views.py:238 +#: build/views.py:1123 order/views.py:242 order/views.py:257 stock/views.py:237 msgid "Deleted attachment" msgstr "" @@ -1427,7 +1427,7 @@ msgstr "" msgid "Currency" msgstr "" -#: company/models.py:313 stock/models.py:345 +#: company/models.py:313 stock/models.py:360 #: stock/templates/stock/item_base.html:194 msgid "Base Part" msgstr "" @@ -1537,8 +1537,8 @@ msgid "Uses default currency" msgstr "" #: company/templates/company/detail.html:62 -#: order/templates/order/sales_order_base.html:89 stock/models.py:380 -#: stock/models.py:381 stock/templates/stock/item_base.html:221 +#: order/templates/order/sales_order_base.html:89 stock/models.py:395 +#: stock/models.py:396 stock/templates/stock/item_base.html:221 #: templates/js/company.js:40 templates/js/order.js:261 msgid "Customer" msgstr "" @@ -1554,7 +1554,7 @@ msgstr "" #: company/templates/company/detail_part.html:18 #: order/templates/order/purchase_order_detail.html:68 -#: part/templates/part/supplier.html:14 templates/js/stock.js:983 +#: part/templates/part/supplier.html:14 templates/js/stock.js:995 msgid "New Supplier Part" msgstr "" @@ -1578,7 +1578,7 @@ msgid "Delete Parts" msgstr "" #: company/templates/company/detail_part.html:63 -#: part/templates/part/category.html:116 templates/js/stock.js:977 +#: part/templates/part/category.html:116 templates/js/stock.js:989 msgid "New Part" msgstr "" @@ -1670,7 +1670,7 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:6 -#: company/templates/company/supplier_part_base.html:19 stock/models.py:354 +#: company/templates/company/supplier_part_base.html:19 stock/models.py:369 #: stock/templates/stock/item_base.html:309 templates/js/company.js:180 msgid "Supplier Part" msgstr "" @@ -1825,7 +1825,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:295 templates/js/stock.js:984 +#: company/views.py:295 templates/js/stock.js:996 msgid "Create new Supplier Part" msgstr "" @@ -1845,28 +1845,48 @@ msgstr "" msgid "Delete Price Break" msgstr "" -#: label/models.py:55 -msgid "Label name" +#: label/api.py:171 +msgid "Must provide valid StockItem(s)" msgstr "" -#: label/models.py:58 -msgid "Label description" +#: label/api.py:185 label/api.py:337 +msgid "Error during label rendering" msgstr "" -#: label/models.py:63 -msgid "Label template file" +#: label/api.py:324 +msgid "Must provide valid StockLocation(s)" msgstr "" #: label/models.py:69 -msgid "Query filters (comma-separated list of key=value pairs" +msgid "Label name" msgstr "" -#: label/models.py:75 +#: label/models.py:76 +msgid "Label description" +msgstr "" + +#: label/models.py:83 stock/forms.py:198 +msgid "Label" +msgstr "" + +#: label/models.py:84 +msgid "Label template file" +msgstr "" + +#: label/models.py:90 report/models.py:162 +msgid "Enabled" +msgstr "" + +#: label/models.py:91 msgid "Label template is enabled" msgstr "" -#: label/models.py:76 report/models.py:162 -msgid "Enabled" +#: label/models.py:137 label/models.py:190 +msgid "Query filters (comma-separated list of key=value pairs" +msgstr "" + +#: label/models.py:138 label/models.py:191 +msgid "Filters" msgstr "" #: order/forms.py:25 order/templates/order/order_base.html:44 @@ -1902,7 +1922,7 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:140 order/models.py:438 +#: order/forms.py:140 order/models.py:437 msgid "" "Target date for order completion. Order will be overdue after this date." msgstr "" @@ -1923,124 +1943,124 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:172 order/models.py:431 +#: order/models.py:171 order/models.py:430 msgid "Purchase order status" msgstr "" -#: order/models.py:180 +#: order/models.py:179 msgid "Company from which the items are being ordered" msgstr "" -#: order/models.py:183 +#: order/models.py:182 msgid "Supplier order reference code" msgstr "" -#: order/models.py:194 +#: order/models.py:193 msgid "Issue Date" msgstr "" -#: order/models.py:195 +#: order/models.py:194 msgid "Date order was issued" msgstr "" -#: order/models.py:200 +#: order/models.py:199 msgid "Target Delivery Date" msgstr "" -#: order/models.py:201 +#: order/models.py:200 msgid "" "Expected date for order delivery. Order will be overdue after this date." msgstr "" -#: order/models.py:206 +#: order/models.py:205 msgid "Completion Date" msgstr "" -#: order/models.py:207 +#: order/models.py:206 msgid "Date order was completed" msgstr "" -#: order/models.py:231 order/models.py:329 part/views.py:1504 -#: stock/models.py:251 stock/models.py:856 +#: order/models.py:230 order/models.py:328 part/views.py:1504 +#: stock/models.py:259 stock/models.py:871 msgid "Quantity must be greater than zero" msgstr "" -#: order/models.py:236 +#: order/models.py:235 msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:324 +#: order/models.py:323 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:427 +#: order/models.py:426 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:433 +#: order/models.py:432 msgid "Customer order reference code" msgstr "" -#: order/models.py:491 +#: order/models.py:490 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:578 +#: order/models.py:577 msgid "Item quantity" msgstr "" -#: order/models.py:580 +#: order/models.py:579 msgid "Line item reference" msgstr "" -#: order/models.py:582 +#: order/models.py:581 msgid "Line item notes" msgstr "" -#: order/models.py:608 order/templates/order/order_base.html:9 +#: order/models.py:607 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: stock/templates/stock/item_base.html:276 templates/js/order.js:145 msgid "Purchase Order" msgstr "" -#: order/models.py:621 +#: order/models.py:620 msgid "Supplier part" msgstr "" -#: order/models.py:624 +#: order/models.py:623 msgid "Number of items received" msgstr "" -#: order/models.py:631 stock/models.py:473 +#: order/models.py:630 stock/models.py:488 #: stock/templates/stock/item_base.html:283 msgid "Purchase Price" msgstr "" -#: order/models.py:632 +#: order/models.py:631 msgid "Unit purchase price" msgstr "" -#: order/models.py:727 +#: order/models.py:726 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:729 +#: order/models.py:728 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:732 +#: order/models.py:731 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:742 +#: order/models.py:741 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:758 +#: order/models.py:757 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:761 +#: order/models.py:760 msgid "Enter stock allocation quantity" msgstr "" @@ -2170,7 +2190,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:39 #: order/templates/order/purchase_order_detail.html:119 #: part/templates/part/category.html:173 part/templates/part/category.html:215 -#: templates/js/stock.js:642 templates/js/stock.js:989 +#: templates/js/stock.js:642 templates/js/stock.js:1001 msgid "New Location" msgstr "" @@ -2255,7 +2275,7 @@ msgid "Sales Order Items" msgstr "" #: order/templates/order/sales_order_detail.html:72 -#: order/templates/order/sales_order_detail.html:154 stock/models.py:385 +#: order/templates/order/sales_order_detail.html:154 stock/models.py:400 #: stock/templates/stock/item_base.html:208 templates/js/build.js:418 msgid "Serial Number" msgstr "" @@ -2898,7 +2918,7 @@ msgid "BOM line checksum" msgstr "" #: part/models.py:1963 part/views.py:1510 part/views.py:1562 -#: stock/models.py:241 +#: stock/models.py:249 msgid "Quantity must be integer value for trackable parts" msgstr "" @@ -2937,7 +2957,7 @@ msgstr "" #: stock/templates/stock/item_base.html:72 #: stock/templates/stock/item_base.html:291 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:751 -#: templates/js/stock.js:822 templates/js/stock.js:1082 +#: templates/js/stock.js:834 templates/js/stock.js:1094 msgid "Stock Item" msgstr "" @@ -3170,7 +3190,7 @@ msgstr "" msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:216 stock/views.py:1363 +#: part/templates/part/category.html:216 stock/views.py:1276 msgid "Create new Stock Location" msgstr "" @@ -3296,13 +3316,13 @@ msgstr "" msgid "New Parameter" msgstr "" -#: part/templates/part/params.html:25 stock/models.py:1499 +#: part/templates/part/params.html:25 stock/models.py:1531 #: templates/InvenTree/settings/header.html:8 templates/js/stock.js:123 msgid "Value" msgstr "" #: part/templates/part/params.html:41 part/templates/part/related.html:41 -#: part/templates/part/supplier.html:19 users/models.py:158 +#: part/templates/part/supplier.html:19 users/models.py:159 msgid "Delete" msgstr "" @@ -3575,7 +3595,7 @@ msgstr "" msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:594 templates/js/stock.js:978 +#: part/views.py:594 templates/js/stock.js:990 msgid "Create New Part" msgstr "" @@ -3759,10 +3779,6 @@ msgstr "" msgid "Enter unique serial numbers (or leave blank)" msgstr "" -#: stock/forms.py:198 -msgid "Label" -msgstr "" - #: stock/forms.py:199 stock/forms.py:255 msgid "Select test report template" msgstr "" @@ -3807,7 +3823,7 @@ msgstr "" msgid "Add note (required)" msgstr "" -#: stock/forms.py:377 stock/views.py:935 stock/views.py:1133 +#: stock/forms.py:377 stock/views.py:848 stock/views.py:1046 msgid "Confirm stock adjustment" msgstr "" @@ -3823,237 +3839,237 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:186 +#: stock/models.py:194 msgid "Created stock item" msgstr "" -#: stock/models.py:222 +#: stock/models.py:230 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:258 +#: stock/models.py:266 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:268 stock/models.py:277 +#: stock/models.py:276 stock/models.py:285 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:269 +#: stock/models.py:277 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:291 +#: stock/models.py:299 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:297 +#: stock/models.py:305 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:304 +#: stock/models.py:312 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:337 +#: stock/models.py:352 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:346 +#: stock/models.py:361 msgid "Base part" msgstr "" -#: stock/models.py:355 +#: stock/models.py:370 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:360 stock/templates/stock/stock_app_base.html:7 +#: stock/models.py:375 stock/templates/stock/stock_app_base.html:7 msgid "Stock Location" msgstr "" -#: stock/models.py:363 +#: stock/models.py:378 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:368 stock/templates/stock/item_base.html:229 +#: stock/models.py:383 stock/templates/stock/item_base.html:229 msgid "Installed In" msgstr "" -#: stock/models.py:371 +#: stock/models.py:386 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:387 +#: stock/models.py:402 msgid "Serial number for this item" msgstr "" -#: stock/models.py:399 +#: stock/models.py:414 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:403 +#: stock/models.py:418 msgid "Stock Quantity" msgstr "" -#: stock/models.py:412 +#: stock/models.py:427 msgid "Source Build" msgstr "" -#: stock/models.py:414 +#: stock/models.py:429 msgid "Build for this stock item" msgstr "" -#: stock/models.py:425 +#: stock/models.py:440 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:428 +#: stock/models.py:443 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:434 +#: stock/models.py:449 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:440 stock/templates/stock/item_base.html:316 +#: stock/models.py:455 stock/templates/stock/item_base.html:316 #: templates/js/stock.js:612 msgid "Expiry Date" msgstr "" -#: stock/models.py:441 +#: stock/models.py:456 msgid "" "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:454 +#: stock/models.py:469 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:464 stock/templates/stock/item_notes.html:14 +#: stock/models.py:479 stock/templates/stock/item_notes.html:14 #: stock/templates/stock/item_notes.html:30 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:474 +#: stock/models.py:489 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:574 +#: stock/models.py:589 msgid "Assigned to Customer" msgstr "" -#: stock/models.py:576 +#: stock/models.py:591 msgid "Manually assigned to customer" msgstr "" -#: stock/models.py:589 +#: stock/models.py:604 msgid "Returned from customer" msgstr "" -#: stock/models.py:591 +#: stock/models.py:606 msgid "Returned to location" msgstr "" -#: stock/models.py:716 +#: stock/models.py:731 msgid "Installed into stock item" msgstr "" -#: stock/models.py:724 +#: stock/models.py:739 msgid "Installed stock item" msgstr "" -#: stock/models.py:748 +#: stock/models.py:763 msgid "Uninstalled stock item" msgstr "" -#: stock/models.py:767 +#: stock/models.py:782 msgid "Uninstalled into location" msgstr "" -#: stock/models.py:847 +#: stock/models.py:862 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:853 +#: stock/models.py:868 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:859 +#: stock/models.py:874 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:862 +#: stock/models.py:877 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:865 +#: stock/models.py:880 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:897 +#: stock/models.py:912 msgid "Add serial number" msgstr "" -#: stock/models.py:900 +#: stock/models.py:915 #, python-brace-format msgid "Serialized {n} items" msgstr "" -#: stock/models.py:1011 +#: stock/models.py:1026 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1400 +#: stock/models.py:1432 msgid "Tracking entry title" msgstr "" -#: stock/models.py:1402 +#: stock/models.py:1434 msgid "Entry notes" msgstr "" -#: stock/models.py:1404 +#: stock/models.py:1436 msgid "Link to external page for further information" msgstr "" -#: stock/models.py:1464 +#: stock/models.py:1496 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1470 +#: stock/models.py:1502 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1487 +#: stock/models.py:1519 msgid "Test" msgstr "" -#: stock/models.py:1488 +#: stock/models.py:1520 msgid "Test name" msgstr "" -#: stock/models.py:1493 +#: stock/models.py:1525 msgid "Result" msgstr "" -#: stock/models.py:1494 templates/js/table_filters.js:172 +#: stock/models.py:1526 templates/js/table_filters.js:172 msgid "Test result" msgstr "" -#: stock/models.py:1500 +#: stock/models.py:1532 msgid "Test output value" msgstr "" -#: stock/models.py:1506 +#: stock/models.py:1538 msgid "Attachment" msgstr "" -#: stock/models.py:1507 +#: stock/models.py:1539 msgid "Test result attachment" msgstr "" -#: stock/models.py:1513 +#: stock/models.py:1545 msgid "Test notes" msgstr "" @@ -4137,15 +4153,15 @@ msgid "Stock adjustment actions" msgstr "" #: stock/templates/stock/item_base.html:141 -#: stock/templates/stock/location.html:41 templates/stock_table.html:23 +#: stock/templates/stock/location.html:41 templates/stock_table.html:24 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:142 templates/stock_table.html:21 +#: stock/templates/stock/item_base.html:142 templates/stock_table.html:22 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:143 templates/stock_table.html:22 +#: stock/templates/stock/item_base.html:143 templates/stock_table.html:23 msgid "Remove stock" msgstr "" @@ -4165,7 +4181,7 @@ msgstr "" msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:158 templates/js/stock.js:1119 +#: stock/templates/stock/item_base.html:158 templates/js/stock.js:1131 msgid "Uninstall stock item" msgstr "" @@ -4348,7 +4364,7 @@ msgstr "" msgid "The following stock items will be uninstalled" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1335 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1248 msgid "Convert Stock Item" msgstr "" @@ -4380,205 +4396,197 @@ msgstr "" msgid "Installed Items" msgstr "" -#: stock/views.py:123 +#: stock/views.py:122 msgid "Edit Stock Location" msgstr "" -#: stock/views.py:148 +#: stock/views.py:147 msgid "Stock Location QR code" msgstr "" -#: stock/views.py:167 +#: stock/views.py:166 msgid "Add Stock Item Attachment" msgstr "" -#: stock/views.py:214 +#: stock/views.py:213 msgid "Edit Stock Item Attachment" msgstr "" -#: stock/views.py:231 +#: stock/views.py:230 msgid "Delete Stock Item Attachment" msgstr "" -#: stock/views.py:248 +#: stock/views.py:247 msgid "Assign to Customer" msgstr "" -#: stock/views.py:258 +#: stock/views.py:257 msgid "Customer must be specified" msgstr "" -#: stock/views.py:282 +#: stock/views.py:281 msgid "Return to Stock" msgstr "" -#: stock/views.py:292 +#: stock/views.py:291 msgid "Specify a valid location" msgstr "" -#: stock/views.py:303 +#: stock/views.py:302 msgid "Stock item returned from customer" msgstr "" #: stock/views.py:313 -msgid "Select Label Template" -msgstr "" - -#: stock/views.py:336 -msgid "Select valid label" -msgstr "" - -#: stock/views.py:400 msgid "Delete All Test Data" msgstr "" -#: stock/views.py:416 +#: stock/views.py:329 msgid "Confirm test data deletion" msgstr "" -#: stock/views.py:436 +#: stock/views.py:349 msgid "Add Test Result" msgstr "" -#: stock/views.py:477 +#: stock/views.py:390 msgid "Edit Test Result" msgstr "" -#: stock/views.py:495 +#: stock/views.py:408 msgid "Delete Test Result" msgstr "" -#: stock/views.py:507 +#: stock/views.py:420 msgid "Select Test Report Template" msgstr "" -#: stock/views.py:537 +#: stock/views.py:450 msgid "Select valid template" msgstr "" -#: stock/views.py:590 +#: stock/views.py:503 msgid "Stock Export Options" msgstr "" -#: stock/views.py:712 +#: stock/views.py:625 msgid "Stock Item QR Code" msgstr "" -#: stock/views.py:738 +#: stock/views.py:651 msgid "Install Stock Item" msgstr "" -#: stock/views.py:838 +#: stock/views.py:751 msgid "Uninstall Stock Items" msgstr "" -#: stock/views.py:946 +#: stock/views.py:859 msgid "Uninstalled stock items" msgstr "" -#: stock/views.py:971 +#: stock/views.py:884 msgid "Adjust Stock" msgstr "" -#: stock/views.py:1081 +#: stock/views.py:994 msgid "Move Stock Items" msgstr "" -#: stock/views.py:1082 +#: stock/views.py:995 msgid "Count Stock Items" msgstr "" -#: stock/views.py:1083 +#: stock/views.py:996 msgid "Remove From Stock" msgstr "" -#: stock/views.py:1084 +#: stock/views.py:997 msgid "Add Stock Items" msgstr "" -#: stock/views.py:1085 +#: stock/views.py:998 msgid "Delete Stock Items" msgstr "" -#: stock/views.py:1113 +#: stock/views.py:1026 msgid "Must enter integer value" msgstr "" -#: stock/views.py:1118 +#: stock/views.py:1031 msgid "Quantity must be positive" msgstr "" -#: stock/views.py:1125 +#: stock/views.py:1038 #, python-brace-format msgid "Quantity must not exceed {x}" msgstr "" -#: stock/views.py:1204 +#: stock/views.py:1117 #, python-brace-format msgid "Added stock to {n} items" msgstr "" -#: stock/views.py:1219 +#: stock/views.py:1132 #, python-brace-format msgid "Removed stock from {n} items" msgstr "" -#: stock/views.py:1232 +#: stock/views.py:1145 #, python-brace-format msgid "Counted stock for {n} items" msgstr "" -#: stock/views.py:1260 +#: stock/views.py:1173 msgid "No items were moved" msgstr "" -#: stock/views.py:1263 +#: stock/views.py:1176 #, python-brace-format msgid "Moved {n} items to {dest}" msgstr "" -#: stock/views.py:1282 +#: stock/views.py:1195 #, python-brace-format msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:1294 +#: stock/views.py:1207 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1385 +#: stock/views.py:1298 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1479 templates/js/build.js:210 +#: stock/views.py:1392 templates/js/build.js:210 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1587 +#: stock/views.py:1500 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1664 +#: stock/views.py:1577 msgid "Quantity cannot be negative" msgstr "" -#: stock/views.py:1750 +#: stock/views.py:1663 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1764 +#: stock/views.py:1677 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1776 +#: stock/views.py:1689 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1795 +#: stock/views.py:1708 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1805 +#: stock/views.py:1718 msgid "Add Stock Tracking Entry" msgstr "" @@ -4888,7 +4896,7 @@ msgstr "" msgid "Enter barcode data" msgstr "" -#: templates/js/barcode.js:42 +#: templates/js/barcode.js:42 templates/js/modals.js:856 msgid "Invalid server response" msgstr "" @@ -5033,7 +5041,7 @@ msgstr "" msgid "Build stock" msgstr "" -#: templates/js/build.js:582 templates/stock_table.html:25 +#: templates/js/build.js:582 templates/stock_table.html:26 msgid "Order stock" msgstr "" @@ -5077,6 +5085,136 @@ msgstr "" msgid "Assembled part" msgstr "" +#: templates/js/label.js:10 +msgid "Select Stock Items" +msgstr "" + +#: templates/js/label.js:11 +msgid "Stock item(s) must be selected before printing labels" +msgstr "" + +#: templates/js/label.js:29 templates/js/label.js:79 +msgid "No Labels Found" +msgstr "" + +#: templates/js/label.js:30 +msgid "No labels found which match selected stock item(s)" +msgstr "" + +#: templates/js/label.js:61 +msgid "Select Stock Locations" +msgstr "" + +#: templates/js/label.js:62 +msgid "Stock location(s) must be selected before printing labels" +msgstr "" + +#: templates/js/label.js:80 +msgid "No labels found which match selected stock location(s)" +msgstr "" + +#: templates/js/label.js:141 +msgid "Select Label" +msgstr "" + +#: templates/js/label.js:156 +msgid "Select Label Template" +msgstr "" + +#: templates/js/modals.js:406 +msgid "Show Error Information" +msgstr "" + +#: templates/js/modals.js:473 +msgid "Accept" +msgstr "" + +#: templates/js/modals.js:474 +msgid "Cancel" +msgstr "" + +#: templates/js/modals.js:538 +msgid "Loading Data" +msgstr "" + +#: templates/js/modals.js:549 templates/js/modals.js:807 +#: templates/modals.html:19 templates/modals.html:41 +msgid "Submit" +msgstr "" + +#: templates/js/modals.js:550 templates/js/modals.js:808 +#: templates/modals.html:18 templates/modals.html:40 +msgid "Close" +msgstr "" + +#: templates/js/modals.js:759 +msgid "Invalid response from server" +msgstr "" + +#: templates/js/modals.js:759 +msgid "Form data missing from server response" +msgstr "" + +#: templates/js/modals.js:772 +msgid "Error posting form data" +msgstr "" + +#: templates/js/modals.js:856 +msgid "JSON response missing form data" +msgstr "" + +#: templates/js/modals.js:866 +msgid "No Response" +msgstr "" + +#: templates/js/modals.js:867 +msgid "No response from the InvenTree server" +msgstr "" + +#: templates/js/modals.js:871 +msgid "Error 400: Bad Request" +msgstr "" + +#: templates/js/modals.js:872 +msgid "Server returned error code 400" +msgstr "" + +#: templates/js/modals.js:876 +msgid "Error 401: Not Authenticated" +msgstr "" + +#: templates/js/modals.js:877 +msgid "Authentication credentials not supplied" +msgstr "" + +#: templates/js/modals.js:881 +msgid "Error 403: Permission Denied" +msgstr "" + +#: templates/js/modals.js:882 +msgid "You do not have the required permissions to access this function" +msgstr "" + +#: templates/js/modals.js:886 +msgid "Error 404: Resource Not Found" +msgstr "" + +#: templates/js/modals.js:887 +msgid "The requested resource could not be located on the server" +msgstr "" + +#: templates/js/modals.js:891 +msgid "Error 408: Timeout" +msgstr "" + +#: templates/js/modals.js:892 +msgid "Connection timeout while requesting data from server" +msgstr "" + +#: templates/js/modals.js:895 +msgid "Error requesting form data" +msgstr "" + #: templates/js/order.js:135 msgid "No purchase orders found" msgstr "" @@ -5085,7 +5223,7 @@ msgstr "" msgid "Order is overdue" msgstr "" -#: templates/js/order.js:193 templates/js/stock.js:804 +#: templates/js/order.js:193 templates/js/stock.js:816 msgid "Date" msgstr "" @@ -5122,7 +5260,7 @@ msgid "No parts found" msgstr "" #: templates/js/part.js:343 templates/js/stock.js:473 -#: templates/js/stock.js:1151 +#: templates/js/stock.js:1163 msgid "Select" msgstr "" @@ -5254,39 +5392,39 @@ msgstr "" msgid "Stocktake" msgstr "" -#: templates/js/stock.js:720 +#: templates/js/stock.js:732 msgid "Stock Status" msgstr "" -#: templates/js/stock.js:735 +#: templates/js/stock.js:747 msgid "Set Stock Status" msgstr "" -#: templates/js/stock.js:749 +#: templates/js/stock.js:761 msgid "Select Status Code" msgstr "" -#: templates/js/stock.js:750 +#: templates/js/stock.js:762 msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:870 +#: templates/js/stock.js:882 msgid "No user information" msgstr "" -#: templates/js/stock.js:990 +#: templates/js/stock.js:1002 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1089 +#: templates/js/stock.js:1101 msgid "Serial" msgstr "" -#: templates/js/stock.js:1182 templates/js/table_filters.js:131 +#: templates/js/stock.js:1194 templates/js/table_filters.js:131 msgid "Installed" msgstr "" -#: templates/js/stock.js:1207 +#: templates/js/stock.js:1219 msgid "Install item" msgstr "" @@ -5439,14 +5577,6 @@ msgstr "" msgid "Form errors exist" msgstr "" -#: templates/modals.html:18 templates/modals.html:40 -msgid "Close" -msgstr "" - -#: templates/modals.html:19 templates/modals.html:41 -msgid "Submit" -msgstr "" - #: templates/navbar.html:29 msgid "Buy" msgstr "" @@ -5507,43 +5637,47 @@ msgstr "" msgid "Export Stock Information" msgstr "" -#: templates/stock_table.html:21 -msgid "Add to selected stock items" +#: templates/stock_table.html:20 +msgid "Print labels" msgstr "" #: templates/stock_table.html:22 -msgid "Remove from selected stock items" +msgid "Add to selected stock items" msgstr "" #: templates/stock_table.html:23 +msgid "Remove from selected stock items" +msgstr "" + +#: templates/stock_table.html:24 msgid "Stocktake selected stock items" msgstr "" -#: templates/stock_table.html:24 +#: templates/stock_table.html:25 msgid "Move selected stock items" msgstr "" -#: templates/stock_table.html:24 +#: templates/stock_table.html:25 msgid "Move stock" msgstr "" -#: templates/stock_table.html:25 +#: templates/stock_table.html:26 msgid "Order selected items" msgstr "" -#: templates/stock_table.html:26 +#: templates/stock_table.html:27 msgid "Change status" msgstr "" -#: templates/stock_table.html:26 +#: templates/stock_table.html:27 msgid "Change stock status" msgstr "" -#: templates/stock_table.html:29 +#: templates/stock_table.html:30 msgid "Delete selected items" msgstr "" -#: templates/stock_table.html:29 +#: templates/stock_table.html:30 msgid "Delete Stock" msgstr "" @@ -5571,38 +5705,38 @@ msgstr "" msgid "Important dates" msgstr "" -#: users/models.py:141 +#: users/models.py:142 msgid "Permission set" msgstr "" -#: users/models.py:149 +#: users/models.py:150 msgid "Group" msgstr "" -#: users/models.py:152 +#: users/models.py:153 msgid "View" msgstr "" -#: users/models.py:152 +#: users/models.py:153 msgid "Permission to view items" msgstr "" -#: users/models.py:154 +#: users/models.py:155 msgid "Add" msgstr "" -#: users/models.py:154 +#: users/models.py:155 msgid "Permission to add items" msgstr "" -#: users/models.py:156 +#: users/models.py:157 msgid "Change" msgstr "" -#: users/models.py:156 +#: users/models.py:157 msgid "Permissions to edit items" msgstr "" -#: users/models.py:158 +#: users/models.py:159 msgid "Permission to delete items" msgstr "" diff --git a/InvenTree/locale/es/LC_MESSAGES/django.po b/InvenTree/locale/es/LC_MESSAGES/django.po index e5967684a0..7389af937b 100644 --- a/InvenTree/locale/es/LC_MESSAGES/django.po +++ b/InvenTree/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-01-14 17:54+1100\n" +"POT-Creation-Date: 2021-01-14 23:57+1100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -54,8 +54,8 @@ msgstr "" msgid "Select Category" msgstr "" -#: InvenTree/helpers.py:361 order/models.py:233 order/models.py:331 -#: stock/views.py:1660 +#: InvenTree/helpers.py:361 order/models.py:232 order/models.py:330 +#: stock/views.py:1573 msgid "Invalid quantity provided" msgstr "" @@ -95,11 +95,11 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 templates/js/stock.js:861 +#: InvenTree/models.py:68 templates/js/stock.js:873 msgid "User" msgstr "" -#: InvenTree/models.py:106 part/models.py:647 +#: InvenTree/models.py:106 label/models.py:68 part/models.py:647 #: part/templates/part/params.html:24 templates/js/part.js:129 msgid "Name" msgstr "" @@ -108,19 +108,19 @@ msgstr "" msgid "Description (optional)" msgstr "" -#: InvenTree/settings.py:422 +#: InvenTree/settings.py:439 msgid "English" msgstr "" -#: InvenTree/settings.py:423 +#: InvenTree/settings.py:440 msgid "German" msgstr "" -#: InvenTree/settings.py:424 +#: InvenTree/settings.py:441 msgid "French" msgstr "" -#: InvenTree/settings.py:425 +#: InvenTree/settings.py:442 msgid "Polish" msgstr "" @@ -315,8 +315,8 @@ msgstr "" #: stock/templates/stock/item_base.html:46 #: stock/templates/stock/item_base.html:214 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.js:338 -#: templates/js/bom.js:195 templates/js/build.js:420 templates/js/stock.js:852 -#: templates/js/stock.js:1091 +#: templates/js/bom.js:195 templates/js/build.js:420 templates/js/stock.js:864 +#: templates/js/stock.js:1103 msgid "Quantity" msgstr "" @@ -397,7 +397,7 @@ msgstr "" #: build/models.py:116 build/templates/build/detail.html:19 #: company/models.py:359 company/templates/company/detail.html:23 #: company/templates/company/supplier_part_base.html:61 -#: company/templates/company/supplier_part_detail.html:27 +#: company/templates/company/supplier_part_detail.html:27 label/models.py:75 #: order/templates/order/purchase_order_detail.html:161 part/models.py:671 #: part/templates/part/detail.html:51 part/templates/part/set_category.html:14 #: templates/InvenTree/search.html:147 @@ -405,7 +405,7 @@ msgstr "" #: templates/js/bom.js:549 templates/js/build.js:664 templates/js/company.js:56 #: templates/js/order.js:180 templates/js/order.js:274 templates/js/part.js:188 #: templates/js/part.js:271 templates/js/part.js:391 templates/js/part.js:572 -#: templates/js/stock.js:511 templates/js/stock.js:833 +#: templates/js/stock.js:511 templates/js/stock.js:845 msgid "Description" msgstr "" @@ -424,7 +424,7 @@ msgstr "" #: build/models.py:134 build/templates/build/auto_allocate.html:16 #: build/templates/build/build_base.html:78 -#: build/templates/build/detail.html:24 order/models.py:652 +#: build/templates/build/detail.html:24 order/models.py:651 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:148 #: order/templates/order/receive_parts.html:19 part/models.py:316 @@ -433,7 +433,7 @@ msgstr "" #: templates/js/barcode.js:336 templates/js/bom.js:153 templates/js/bom.js:534 #: templates/js/build.js:669 templates/js/company.js:138 #: templates/js/part.js:252 templates/js/part.js:357 templates/js/stock.js:485 -#: templates/js/stock.js:1163 +#: templates/js/stock.js:1175 msgid "Part" msgstr "" @@ -491,7 +491,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:194 stock/models.py:397 +#: build/models.py:194 stock/models.py:412 msgid "Batch Code" msgstr "" @@ -499,7 +499,7 @@ msgstr "" msgid "Batch code for this build output" msgstr "" -#: build/models.py:205 order/models.py:437 +#: build/models.py:205 order/models.py:436 msgid "Target completion date" msgstr "" @@ -507,11 +507,11 @@ msgstr "" #: company/templates/company/supplier_part_base.html:68 #: company/templates/company/supplier_part_detail.html:24 #: part/templates/part/detail.html:80 part/templates/part/part_base.html:102 -#: stock/models.py:391 stock/templates/stock/item_base.html:297 +#: stock/models.py:406 stock/templates/stock/item_base.html:297 msgid "External Link" msgstr "" -#: build/models.py:220 part/models.py:705 stock/models.py:393 +#: build/models.py:220 part/models.py:705 stock/models.py:408 msgid "Link to external URL" msgstr "" @@ -520,7 +520,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:213 #: order/templates/order/so_tabs.html:23 part/models.py:831 #: part/templates/part/tabs.html:73 stock/forms.py:313 stock/forms.py:345 -#: stock/forms.py:373 stock/models.py:463 stock/models.py:1512 +#: stock/forms.py:373 stock/models.py:478 stock/models.py:1544 #: stock/templates/stock/tabs.html:26 templates/js/barcode.js:391 #: templates/js/bom.js:295 templates/js/stock.js:127 templates/js/stock.js:618 msgid "Notes" @@ -564,11 +564,11 @@ msgstr "" msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:971 order/models.py:736 +#: build/models.py:971 order/models.py:735 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:975 order/models.py:739 +#: build/models.py:975 order/models.py:738 msgid "Allocation quantity must be greater than zero" msgstr "" @@ -724,7 +724,7 @@ msgstr "" #: stock/templates/stock/item_base.html:343 templates/InvenTree/search.html:175 #: templates/js/barcode.js:42 templates/js/build.js:697 #: templates/js/order.js:185 templates/js/order.js:279 -#: templates/js/stock.js:584 templates/js/stock.js:1099 +#: templates/js/stock.js:584 templates/js/stock.js:1111 msgid "Status" msgstr "" @@ -746,7 +746,7 @@ msgid "Progress" msgstr "" #: build/templates/build/build_base.html:120 -#: build/templates/build/detail.html:82 order/models.py:650 +#: build/templates/build/detail.html:82 order/models.py:649 #: order/templates/order/sales_order_base.html:9 #: order/templates/order/sales_order_base.html:33 #: order/templates/order/sales_order_notes.html:10 @@ -854,7 +854,7 @@ msgstr "" #: build/templates/build/detail.html:68 #: stock/templates/stock/item_base.html:262 templates/js/stock.js:592 -#: templates/js/stock.js:1106 templates/js/table_filters.js:80 +#: templates/js/stock.js:1118 templates/js/table_filters.js:80 #: templates/js/table_filters.js:161 msgid "Batch" msgstr "" @@ -953,7 +953,7 @@ msgstr "" msgid "Create Build Output" msgstr "" -#: build/views.py:207 stock/models.py:872 stock/views.py:1681 +#: build/views.py:207 stock/models.py:887 stock/views.py:1594 msgid "Serial numbers already exist" msgstr "" @@ -969,7 +969,7 @@ msgstr "" msgid "Confirm unallocation of build stock" msgstr "" -#: build/views.py:303 build/views.py:388 stock/views.py:417 +#: build/views.py:303 build/views.py:388 stock/views.py:330 msgid "Check the confirmation box" msgstr "" @@ -1063,7 +1063,7 @@ msgid "Add Build Order Attachment" msgstr "" #: build/views.py:1060 order/views.py:113 order/views.py:166 part/views.py:170 -#: stock/views.py:180 +#: stock/views.py:179 msgid "Added attachment" msgstr "" @@ -1079,7 +1079,7 @@ msgstr "" msgid "Delete Attachment" msgstr "" -#: build/views.py:1123 order/views.py:242 order/views.py:257 stock/views.py:238 +#: build/views.py:1123 order/views.py:242 order/views.py:257 stock/views.py:237 msgid "Deleted attachment" msgstr "" @@ -1427,7 +1427,7 @@ msgstr "" msgid "Currency" msgstr "" -#: company/models.py:313 stock/models.py:345 +#: company/models.py:313 stock/models.py:360 #: stock/templates/stock/item_base.html:194 msgid "Base Part" msgstr "" @@ -1537,8 +1537,8 @@ msgid "Uses default currency" msgstr "" #: company/templates/company/detail.html:62 -#: order/templates/order/sales_order_base.html:89 stock/models.py:380 -#: stock/models.py:381 stock/templates/stock/item_base.html:221 +#: order/templates/order/sales_order_base.html:89 stock/models.py:395 +#: stock/models.py:396 stock/templates/stock/item_base.html:221 #: templates/js/company.js:40 templates/js/order.js:261 msgid "Customer" msgstr "" @@ -1554,7 +1554,7 @@ msgstr "" #: company/templates/company/detail_part.html:18 #: order/templates/order/purchase_order_detail.html:68 -#: part/templates/part/supplier.html:14 templates/js/stock.js:983 +#: part/templates/part/supplier.html:14 templates/js/stock.js:995 msgid "New Supplier Part" msgstr "" @@ -1578,7 +1578,7 @@ msgid "Delete Parts" msgstr "" #: company/templates/company/detail_part.html:63 -#: part/templates/part/category.html:116 templates/js/stock.js:977 +#: part/templates/part/category.html:116 templates/js/stock.js:989 msgid "New Part" msgstr "" @@ -1670,7 +1670,7 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:6 -#: company/templates/company/supplier_part_base.html:19 stock/models.py:354 +#: company/templates/company/supplier_part_base.html:19 stock/models.py:369 #: stock/templates/stock/item_base.html:309 templates/js/company.js:180 msgid "Supplier Part" msgstr "" @@ -1825,7 +1825,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:295 templates/js/stock.js:984 +#: company/views.py:295 templates/js/stock.js:996 msgid "Create new Supplier Part" msgstr "" @@ -1845,28 +1845,48 @@ msgstr "" msgid "Delete Price Break" msgstr "" -#: label/models.py:55 -msgid "Label name" +#: label/api.py:171 +msgid "Must provide valid StockItem(s)" msgstr "" -#: label/models.py:58 -msgid "Label description" +#: label/api.py:185 label/api.py:337 +msgid "Error during label rendering" msgstr "" -#: label/models.py:63 -msgid "Label template file" +#: label/api.py:324 +msgid "Must provide valid StockLocation(s)" msgstr "" #: label/models.py:69 -msgid "Query filters (comma-separated list of key=value pairs" +msgid "Label name" msgstr "" -#: label/models.py:75 +#: label/models.py:76 +msgid "Label description" +msgstr "" + +#: label/models.py:83 stock/forms.py:198 +msgid "Label" +msgstr "" + +#: label/models.py:84 +msgid "Label template file" +msgstr "" + +#: label/models.py:90 report/models.py:162 +msgid "Enabled" +msgstr "" + +#: label/models.py:91 msgid "Label template is enabled" msgstr "" -#: label/models.py:76 report/models.py:162 -msgid "Enabled" +#: label/models.py:137 label/models.py:190 +msgid "Query filters (comma-separated list of key=value pairs" +msgstr "" + +#: label/models.py:138 label/models.py:191 +msgid "Filters" msgstr "" #: order/forms.py:25 order/templates/order/order_base.html:44 @@ -1902,7 +1922,7 @@ msgstr "" msgid "Enter sales order number" msgstr "" -#: order/forms.py:140 order/models.py:438 +#: order/forms.py:140 order/models.py:437 msgid "" "Target date for order completion. Order will be overdue after this date." msgstr "" @@ -1923,124 +1943,124 @@ msgstr "" msgid "Order notes" msgstr "" -#: order/models.py:172 order/models.py:431 +#: order/models.py:171 order/models.py:430 msgid "Purchase order status" msgstr "" -#: order/models.py:180 +#: order/models.py:179 msgid "Company from which the items are being ordered" msgstr "" -#: order/models.py:183 +#: order/models.py:182 msgid "Supplier order reference code" msgstr "" -#: order/models.py:194 +#: order/models.py:193 msgid "Issue Date" msgstr "" -#: order/models.py:195 +#: order/models.py:194 msgid "Date order was issued" msgstr "" -#: order/models.py:200 +#: order/models.py:199 msgid "Target Delivery Date" msgstr "" -#: order/models.py:201 +#: order/models.py:200 msgid "" "Expected date for order delivery. Order will be overdue after this date." msgstr "" -#: order/models.py:206 +#: order/models.py:205 msgid "Completion Date" msgstr "" -#: order/models.py:207 +#: order/models.py:206 msgid "Date order was completed" msgstr "" -#: order/models.py:231 order/models.py:329 part/views.py:1504 -#: stock/models.py:251 stock/models.py:856 +#: order/models.py:230 order/models.py:328 part/views.py:1504 +#: stock/models.py:259 stock/models.py:871 msgid "Quantity must be greater than zero" msgstr "" -#: order/models.py:236 +#: order/models.py:235 msgid "Part supplier must match PO supplier" msgstr "" -#: order/models.py:324 +#: order/models.py:323 msgid "Lines can only be received against an order marked as 'Placed'" msgstr "" -#: order/models.py:427 +#: order/models.py:426 msgid "Company to which the items are being sold" msgstr "" -#: order/models.py:433 +#: order/models.py:432 msgid "Customer order reference code" msgstr "" -#: order/models.py:491 +#: order/models.py:490 msgid "SalesOrder cannot be shipped as it is not currently pending" msgstr "" -#: order/models.py:578 +#: order/models.py:577 msgid "Item quantity" msgstr "" -#: order/models.py:580 +#: order/models.py:579 msgid "Line item reference" msgstr "" -#: order/models.py:582 +#: order/models.py:581 msgid "Line item notes" msgstr "" -#: order/models.py:608 order/templates/order/order_base.html:9 +#: order/models.py:607 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:24 #: stock/templates/stock/item_base.html:276 templates/js/order.js:145 msgid "Purchase Order" msgstr "" -#: order/models.py:621 +#: order/models.py:620 msgid "Supplier part" msgstr "" -#: order/models.py:624 +#: order/models.py:623 msgid "Number of items received" msgstr "" -#: order/models.py:631 stock/models.py:473 +#: order/models.py:630 stock/models.py:488 #: stock/templates/stock/item_base.html:283 msgid "Purchase Price" msgstr "" -#: order/models.py:632 +#: order/models.py:631 msgid "Unit purchase price" msgstr "" -#: order/models.py:727 +#: order/models.py:726 msgid "Cannot allocate stock item to a line with a different part" msgstr "" -#: order/models.py:729 +#: order/models.py:728 msgid "Cannot allocate stock to a line without a part" msgstr "" -#: order/models.py:732 +#: order/models.py:731 msgid "Allocation quantity cannot exceed stock quantity" msgstr "" -#: order/models.py:742 +#: order/models.py:741 msgid "Quantity must be 1 for serialized stock item" msgstr "" -#: order/models.py:758 +#: order/models.py:757 msgid "Select stock item to allocate" msgstr "" -#: order/models.py:761 +#: order/models.py:760 msgid "Enter stock allocation quantity" msgstr "" @@ -2170,7 +2190,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:39 #: order/templates/order/purchase_order_detail.html:119 #: part/templates/part/category.html:173 part/templates/part/category.html:215 -#: templates/js/stock.js:642 templates/js/stock.js:989 +#: templates/js/stock.js:642 templates/js/stock.js:1001 msgid "New Location" msgstr "" @@ -2255,7 +2275,7 @@ msgid "Sales Order Items" msgstr "" #: order/templates/order/sales_order_detail.html:72 -#: order/templates/order/sales_order_detail.html:154 stock/models.py:385 +#: order/templates/order/sales_order_detail.html:154 stock/models.py:400 #: stock/templates/stock/item_base.html:208 templates/js/build.js:418 msgid "Serial Number" msgstr "" @@ -2898,7 +2918,7 @@ msgid "BOM line checksum" msgstr "" #: part/models.py:1963 part/views.py:1510 part/views.py:1562 -#: stock/models.py:241 +#: stock/models.py:249 msgid "Quantity must be integer value for trackable parts" msgstr "" @@ -2937,7 +2957,7 @@ msgstr "" #: stock/templates/stock/item_base.html:72 #: stock/templates/stock/item_base.html:291 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.js:751 -#: templates/js/stock.js:822 templates/js/stock.js:1082 +#: templates/js/stock.js:834 templates/js/stock.js:1094 msgid "Stock Item" msgstr "" @@ -3170,7 +3190,7 @@ msgstr "" msgid "Create new Part Category" msgstr "" -#: part/templates/part/category.html:216 stock/views.py:1363 +#: part/templates/part/category.html:216 stock/views.py:1276 msgid "Create new Stock Location" msgstr "" @@ -3296,13 +3316,13 @@ msgstr "" msgid "New Parameter" msgstr "" -#: part/templates/part/params.html:25 stock/models.py:1499 +#: part/templates/part/params.html:25 stock/models.py:1531 #: templates/InvenTree/settings/header.html:8 templates/js/stock.js:123 msgid "Value" msgstr "" #: part/templates/part/params.html:41 part/templates/part/related.html:41 -#: part/templates/part/supplier.html:19 users/models.py:158 +#: part/templates/part/supplier.html:19 users/models.py:159 msgid "Delete" msgstr "" @@ -3575,7 +3595,7 @@ msgstr "" msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:594 templates/js/stock.js:978 +#: part/views.py:594 templates/js/stock.js:990 msgid "Create New Part" msgstr "" @@ -3759,10 +3779,6 @@ msgstr "" msgid "Enter unique serial numbers (or leave blank)" msgstr "" -#: stock/forms.py:198 -msgid "Label" -msgstr "" - #: stock/forms.py:199 stock/forms.py:255 msgid "Select test report template" msgstr "" @@ -3807,7 +3823,7 @@ msgstr "" msgid "Add note (required)" msgstr "" -#: stock/forms.py:377 stock/views.py:935 stock/views.py:1133 +#: stock/forms.py:377 stock/views.py:848 stock/views.py:1046 msgid "Confirm stock adjustment" msgstr "" @@ -3823,237 +3839,237 @@ msgstr "" msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:186 +#: stock/models.py:194 msgid "Created stock item" msgstr "" -#: stock/models.py:222 +#: stock/models.py:230 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:258 +#: stock/models.py:266 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:268 stock/models.py:277 +#: stock/models.py:276 stock/models.py:285 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:269 +#: stock/models.py:277 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:291 +#: stock/models.py:299 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:297 +#: stock/models.py:305 msgid "Item must have a build reference if is_building=True" msgstr "" -#: stock/models.py:304 +#: stock/models.py:312 msgid "Build reference does not point to the same part object" msgstr "" -#: stock/models.py:337 +#: stock/models.py:352 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:346 +#: stock/models.py:361 msgid "Base part" msgstr "" -#: stock/models.py:355 +#: stock/models.py:370 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:360 stock/templates/stock/stock_app_base.html:7 +#: stock/models.py:375 stock/templates/stock/stock_app_base.html:7 msgid "Stock Location" msgstr "" -#: stock/models.py:363 +#: stock/models.py:378 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:368 stock/templates/stock/item_base.html:229 +#: stock/models.py:383 stock/templates/stock/item_base.html:229 msgid "Installed In" msgstr "" -#: stock/models.py:371 +#: stock/models.py:386 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:387 +#: stock/models.py:402 msgid "Serial number for this item" msgstr "" -#: stock/models.py:399 +#: stock/models.py:414 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:403 +#: stock/models.py:418 msgid "Stock Quantity" msgstr "" -#: stock/models.py:412 +#: stock/models.py:427 msgid "Source Build" msgstr "" -#: stock/models.py:414 +#: stock/models.py:429 msgid "Build for this stock item" msgstr "" -#: stock/models.py:425 +#: stock/models.py:440 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:428 +#: stock/models.py:443 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:434 +#: stock/models.py:449 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:440 stock/templates/stock/item_base.html:316 +#: stock/models.py:455 stock/templates/stock/item_base.html:316 #: templates/js/stock.js:612 msgid "Expiry Date" msgstr "" -#: stock/models.py:441 +#: stock/models.py:456 msgid "" "Expiry date for stock item. Stock will be considered expired after this date" msgstr "" -#: stock/models.py:454 +#: stock/models.py:469 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:464 stock/templates/stock/item_notes.html:14 +#: stock/models.py:479 stock/templates/stock/item_notes.html:14 #: stock/templates/stock/item_notes.html:30 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:474 +#: stock/models.py:489 msgid "Single unit purchase price at time of purchase" msgstr "" -#: stock/models.py:574 +#: stock/models.py:589 msgid "Assigned to Customer" msgstr "" -#: stock/models.py:576 +#: stock/models.py:591 msgid "Manually assigned to customer" msgstr "" -#: stock/models.py:589 +#: stock/models.py:604 msgid "Returned from customer" msgstr "" -#: stock/models.py:591 +#: stock/models.py:606 msgid "Returned to location" msgstr "" -#: stock/models.py:716 +#: stock/models.py:731 msgid "Installed into stock item" msgstr "" -#: stock/models.py:724 +#: stock/models.py:739 msgid "Installed stock item" msgstr "" -#: stock/models.py:748 +#: stock/models.py:763 msgid "Uninstalled stock item" msgstr "" -#: stock/models.py:767 +#: stock/models.py:782 msgid "Uninstalled into location" msgstr "" -#: stock/models.py:847 +#: stock/models.py:862 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:853 +#: stock/models.py:868 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:859 +#: stock/models.py:874 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:862 +#: stock/models.py:877 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:865 +#: stock/models.py:880 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:897 +#: stock/models.py:912 msgid "Add serial number" msgstr "" -#: stock/models.py:900 +#: stock/models.py:915 #, python-brace-format msgid "Serialized {n} items" msgstr "" -#: stock/models.py:1011 +#: stock/models.py:1026 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1400 +#: stock/models.py:1432 msgid "Tracking entry title" msgstr "" -#: stock/models.py:1402 +#: stock/models.py:1434 msgid "Entry notes" msgstr "" -#: stock/models.py:1404 +#: stock/models.py:1436 msgid "Link to external page for further information" msgstr "" -#: stock/models.py:1464 +#: stock/models.py:1496 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1470 +#: stock/models.py:1502 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1487 +#: stock/models.py:1519 msgid "Test" msgstr "" -#: stock/models.py:1488 +#: stock/models.py:1520 msgid "Test name" msgstr "" -#: stock/models.py:1493 +#: stock/models.py:1525 msgid "Result" msgstr "" -#: stock/models.py:1494 templates/js/table_filters.js:172 +#: stock/models.py:1526 templates/js/table_filters.js:172 msgid "Test result" msgstr "" -#: stock/models.py:1500 +#: stock/models.py:1532 msgid "Test output value" msgstr "" -#: stock/models.py:1506 +#: stock/models.py:1538 msgid "Attachment" msgstr "" -#: stock/models.py:1507 +#: stock/models.py:1539 msgid "Test result attachment" msgstr "" -#: stock/models.py:1513 +#: stock/models.py:1545 msgid "Test notes" msgstr "" @@ -4137,15 +4153,15 @@ msgid "Stock adjustment actions" msgstr "" #: stock/templates/stock/item_base.html:141 -#: stock/templates/stock/location.html:41 templates/stock_table.html:23 +#: stock/templates/stock/location.html:41 templates/stock_table.html:24 msgid "Count stock" msgstr "" -#: stock/templates/stock/item_base.html:142 templates/stock_table.html:21 +#: stock/templates/stock/item_base.html:142 templates/stock_table.html:22 msgid "Add stock" msgstr "" -#: stock/templates/stock/item_base.html:143 templates/stock_table.html:22 +#: stock/templates/stock/item_base.html:143 templates/stock_table.html:23 msgid "Remove stock" msgstr "" @@ -4165,7 +4181,7 @@ msgstr "" msgid "Return to stock" msgstr "" -#: stock/templates/stock/item_base.html:158 templates/js/stock.js:1119 +#: stock/templates/stock/item_base.html:158 templates/js/stock.js:1131 msgid "Uninstall stock item" msgstr "" @@ -4348,7 +4364,7 @@ msgstr "" msgid "The following stock items will be uninstalled" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1335 +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1248 msgid "Convert Stock Item" msgstr "" @@ -4380,205 +4396,197 @@ msgstr "" msgid "Installed Items" msgstr "" -#: stock/views.py:123 +#: stock/views.py:122 msgid "Edit Stock Location" msgstr "" -#: stock/views.py:148 +#: stock/views.py:147 msgid "Stock Location QR code" msgstr "" -#: stock/views.py:167 +#: stock/views.py:166 msgid "Add Stock Item Attachment" msgstr "" -#: stock/views.py:214 +#: stock/views.py:213 msgid "Edit Stock Item Attachment" msgstr "" -#: stock/views.py:231 +#: stock/views.py:230 msgid "Delete Stock Item Attachment" msgstr "" -#: stock/views.py:248 +#: stock/views.py:247 msgid "Assign to Customer" msgstr "" -#: stock/views.py:258 +#: stock/views.py:257 msgid "Customer must be specified" msgstr "" -#: stock/views.py:282 +#: stock/views.py:281 msgid "Return to Stock" msgstr "" -#: stock/views.py:292 +#: stock/views.py:291 msgid "Specify a valid location" msgstr "" -#: stock/views.py:303 +#: stock/views.py:302 msgid "Stock item returned from customer" msgstr "" #: stock/views.py:313 -msgid "Select Label Template" -msgstr "" - -#: stock/views.py:336 -msgid "Select valid label" -msgstr "" - -#: stock/views.py:400 msgid "Delete All Test Data" msgstr "" -#: stock/views.py:416 +#: stock/views.py:329 msgid "Confirm test data deletion" msgstr "" -#: stock/views.py:436 +#: stock/views.py:349 msgid "Add Test Result" msgstr "" -#: stock/views.py:477 +#: stock/views.py:390 msgid "Edit Test Result" msgstr "" -#: stock/views.py:495 +#: stock/views.py:408 msgid "Delete Test Result" msgstr "" -#: stock/views.py:507 +#: stock/views.py:420 msgid "Select Test Report Template" msgstr "" -#: stock/views.py:537 +#: stock/views.py:450 msgid "Select valid template" msgstr "" -#: stock/views.py:590 +#: stock/views.py:503 msgid "Stock Export Options" msgstr "" -#: stock/views.py:712 +#: stock/views.py:625 msgid "Stock Item QR Code" msgstr "" -#: stock/views.py:738 +#: stock/views.py:651 msgid "Install Stock Item" msgstr "" -#: stock/views.py:838 +#: stock/views.py:751 msgid "Uninstall Stock Items" msgstr "" -#: stock/views.py:946 +#: stock/views.py:859 msgid "Uninstalled stock items" msgstr "" -#: stock/views.py:971 +#: stock/views.py:884 msgid "Adjust Stock" msgstr "" -#: stock/views.py:1081 +#: stock/views.py:994 msgid "Move Stock Items" msgstr "" -#: stock/views.py:1082 +#: stock/views.py:995 msgid "Count Stock Items" msgstr "" -#: stock/views.py:1083 +#: stock/views.py:996 msgid "Remove From Stock" msgstr "" -#: stock/views.py:1084 +#: stock/views.py:997 msgid "Add Stock Items" msgstr "" -#: stock/views.py:1085 +#: stock/views.py:998 msgid "Delete Stock Items" msgstr "" -#: stock/views.py:1113 +#: stock/views.py:1026 msgid "Must enter integer value" msgstr "" -#: stock/views.py:1118 +#: stock/views.py:1031 msgid "Quantity must be positive" msgstr "" -#: stock/views.py:1125 +#: stock/views.py:1038 #, python-brace-format msgid "Quantity must not exceed {x}" msgstr "" -#: stock/views.py:1204 +#: stock/views.py:1117 #, python-brace-format msgid "Added stock to {n} items" msgstr "" -#: stock/views.py:1219 +#: stock/views.py:1132 #, python-brace-format msgid "Removed stock from {n} items" msgstr "" -#: stock/views.py:1232 +#: stock/views.py:1145 #, python-brace-format msgid "Counted stock for {n} items" msgstr "" -#: stock/views.py:1260 +#: stock/views.py:1173 msgid "No items were moved" msgstr "" -#: stock/views.py:1263 +#: stock/views.py:1176 #, python-brace-format msgid "Moved {n} items to {dest}" msgstr "" -#: stock/views.py:1282 +#: stock/views.py:1195 #, python-brace-format msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:1294 +#: stock/views.py:1207 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1385 +#: stock/views.py:1298 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1479 templates/js/build.js:210 +#: stock/views.py:1392 templates/js/build.js:210 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1587 +#: stock/views.py:1500 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1664 +#: stock/views.py:1577 msgid "Quantity cannot be negative" msgstr "" -#: stock/views.py:1750 +#: stock/views.py:1663 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1764 +#: stock/views.py:1677 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1776 +#: stock/views.py:1689 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1795 +#: stock/views.py:1708 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1805 +#: stock/views.py:1718 msgid "Add Stock Tracking Entry" msgstr "" @@ -4888,7 +4896,7 @@ msgstr "" msgid "Enter barcode data" msgstr "" -#: templates/js/barcode.js:42 +#: templates/js/barcode.js:42 templates/js/modals.js:856 msgid "Invalid server response" msgstr "" @@ -5033,7 +5041,7 @@ msgstr "" msgid "Build stock" msgstr "" -#: templates/js/build.js:582 templates/stock_table.html:25 +#: templates/js/build.js:582 templates/stock_table.html:26 msgid "Order stock" msgstr "" @@ -5077,6 +5085,136 @@ msgstr "" msgid "Assembled part" msgstr "" +#: templates/js/label.js:10 +msgid "Select Stock Items" +msgstr "" + +#: templates/js/label.js:11 +msgid "Stock item(s) must be selected before printing labels" +msgstr "" + +#: templates/js/label.js:29 templates/js/label.js:79 +msgid "No Labels Found" +msgstr "" + +#: templates/js/label.js:30 +msgid "No labels found which match selected stock item(s)" +msgstr "" + +#: templates/js/label.js:61 +msgid "Select Stock Locations" +msgstr "" + +#: templates/js/label.js:62 +msgid "Stock location(s) must be selected before printing labels" +msgstr "" + +#: templates/js/label.js:80 +msgid "No labels found which match selected stock location(s)" +msgstr "" + +#: templates/js/label.js:141 +msgid "Select Label" +msgstr "" + +#: templates/js/label.js:156 +msgid "Select Label Template" +msgstr "" + +#: templates/js/modals.js:406 +msgid "Show Error Information" +msgstr "" + +#: templates/js/modals.js:473 +msgid "Accept" +msgstr "" + +#: templates/js/modals.js:474 +msgid "Cancel" +msgstr "" + +#: templates/js/modals.js:538 +msgid "Loading Data" +msgstr "" + +#: templates/js/modals.js:549 templates/js/modals.js:807 +#: templates/modals.html:19 templates/modals.html:41 +msgid "Submit" +msgstr "" + +#: templates/js/modals.js:550 templates/js/modals.js:808 +#: templates/modals.html:18 templates/modals.html:40 +msgid "Close" +msgstr "" + +#: templates/js/modals.js:759 +msgid "Invalid response from server" +msgstr "" + +#: templates/js/modals.js:759 +msgid "Form data missing from server response" +msgstr "" + +#: templates/js/modals.js:772 +msgid "Error posting form data" +msgstr "" + +#: templates/js/modals.js:856 +msgid "JSON response missing form data" +msgstr "" + +#: templates/js/modals.js:866 +msgid "No Response" +msgstr "" + +#: templates/js/modals.js:867 +msgid "No response from the InvenTree server" +msgstr "" + +#: templates/js/modals.js:871 +msgid "Error 400: Bad Request" +msgstr "" + +#: templates/js/modals.js:872 +msgid "Server returned error code 400" +msgstr "" + +#: templates/js/modals.js:876 +msgid "Error 401: Not Authenticated" +msgstr "" + +#: templates/js/modals.js:877 +msgid "Authentication credentials not supplied" +msgstr "" + +#: templates/js/modals.js:881 +msgid "Error 403: Permission Denied" +msgstr "" + +#: templates/js/modals.js:882 +msgid "You do not have the required permissions to access this function" +msgstr "" + +#: templates/js/modals.js:886 +msgid "Error 404: Resource Not Found" +msgstr "" + +#: templates/js/modals.js:887 +msgid "The requested resource could not be located on the server" +msgstr "" + +#: templates/js/modals.js:891 +msgid "Error 408: Timeout" +msgstr "" + +#: templates/js/modals.js:892 +msgid "Connection timeout while requesting data from server" +msgstr "" + +#: templates/js/modals.js:895 +msgid "Error requesting form data" +msgstr "" + #: templates/js/order.js:135 msgid "No purchase orders found" msgstr "" @@ -5085,7 +5223,7 @@ msgstr "" msgid "Order is overdue" msgstr "" -#: templates/js/order.js:193 templates/js/stock.js:804 +#: templates/js/order.js:193 templates/js/stock.js:816 msgid "Date" msgstr "" @@ -5122,7 +5260,7 @@ msgid "No parts found" msgstr "" #: templates/js/part.js:343 templates/js/stock.js:473 -#: templates/js/stock.js:1151 +#: templates/js/stock.js:1163 msgid "Select" msgstr "" @@ -5254,39 +5392,39 @@ msgstr "" msgid "Stocktake" msgstr "" -#: templates/js/stock.js:720 +#: templates/js/stock.js:732 msgid "Stock Status" msgstr "" -#: templates/js/stock.js:735 +#: templates/js/stock.js:747 msgid "Set Stock Status" msgstr "" -#: templates/js/stock.js:749 +#: templates/js/stock.js:761 msgid "Select Status Code" msgstr "" -#: templates/js/stock.js:750 +#: templates/js/stock.js:762 msgid "Status code must be selected" msgstr "" -#: templates/js/stock.js:870 +#: templates/js/stock.js:882 msgid "No user information" msgstr "" -#: templates/js/stock.js:990 +#: templates/js/stock.js:1002 msgid "Create New Location" msgstr "" -#: templates/js/stock.js:1089 +#: templates/js/stock.js:1101 msgid "Serial" msgstr "" -#: templates/js/stock.js:1182 templates/js/table_filters.js:131 +#: templates/js/stock.js:1194 templates/js/table_filters.js:131 msgid "Installed" msgstr "" -#: templates/js/stock.js:1207 +#: templates/js/stock.js:1219 msgid "Install item" msgstr "" @@ -5439,14 +5577,6 @@ msgstr "" msgid "Form errors exist" msgstr "" -#: templates/modals.html:18 templates/modals.html:40 -msgid "Close" -msgstr "" - -#: templates/modals.html:19 templates/modals.html:41 -msgid "Submit" -msgstr "" - #: templates/navbar.html:29 msgid "Buy" msgstr "" @@ -5507,43 +5637,47 @@ msgstr "" msgid "Export Stock Information" msgstr "" -#: templates/stock_table.html:21 -msgid "Add to selected stock items" +#: templates/stock_table.html:20 +msgid "Print labels" msgstr "" #: templates/stock_table.html:22 -msgid "Remove from selected stock items" +msgid "Add to selected stock items" msgstr "" #: templates/stock_table.html:23 +msgid "Remove from selected stock items" +msgstr "" + +#: templates/stock_table.html:24 msgid "Stocktake selected stock items" msgstr "" -#: templates/stock_table.html:24 +#: templates/stock_table.html:25 msgid "Move selected stock items" msgstr "" -#: templates/stock_table.html:24 +#: templates/stock_table.html:25 msgid "Move stock" msgstr "" -#: templates/stock_table.html:25 +#: templates/stock_table.html:26 msgid "Order selected items" msgstr "" -#: templates/stock_table.html:26 +#: templates/stock_table.html:27 msgid "Change status" msgstr "" -#: templates/stock_table.html:26 +#: templates/stock_table.html:27 msgid "Change stock status" msgstr "" -#: templates/stock_table.html:29 +#: templates/stock_table.html:30 msgid "Delete selected items" msgstr "" -#: templates/stock_table.html:29 +#: templates/stock_table.html:30 msgid "Delete Stock" msgstr "" @@ -5571,38 +5705,38 @@ msgstr "" msgid "Important dates" msgstr "" -#: users/models.py:141 +#: users/models.py:142 msgid "Permission set" msgstr "" -#: users/models.py:149 +#: users/models.py:150 msgid "Group" msgstr "" -#: users/models.py:152 +#: users/models.py:153 msgid "View" msgstr "" -#: users/models.py:152 +#: users/models.py:153 msgid "Permission to view items" msgstr "" -#: users/models.py:154 +#: users/models.py:155 msgid "Add" msgstr "" -#: users/models.py:154 +#: users/models.py:155 msgid "Permission to add items" msgstr "" -#: users/models.py:156 +#: users/models.py:157 msgid "Change" msgstr "" -#: users/models.py:156 +#: users/models.py:157 msgid "Permissions to edit items" msgstr "" -#: users/models.py:158 +#: users/models.py:159 msgid "Permission to delete items" msgstr "" diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 807d6644ca..0fa4247cd1 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -32,6 +32,7 @@ from InvenTree import helpers import common.models import report.models +import label.models from InvenTree.status_codes import StockStatus from InvenTree.models import InvenTreeTree, InvenTreeAttachment @@ -63,6 +64,13 @@ class StockLocation(InvenTreeTree): **kwargs ) + @property + def barcode(self): + """ + Brief payload data (e.g. for labels) + """ + return self.format_barcode(brief=True) + def get_stock_items(self, cascade=True): """ Return a queryset for all stock items under this category. @@ -330,6 +338,13 @@ class StockItem(MPTTModel): **kwargs ) + @property + def barcode(self): + """ + Brief payload data (e.g. for labels) + """ + return self.format_barcode(brief=True) + uid = models.CharField(blank=True, max_length=128, help_text=("Unique identifier field")) parent = TreeForeignKey( @@ -1333,14 +1348,31 @@ class StockItem(MPTTModel): return len(self.available_test_reports()) > 0 + def available_labels(self): + """ + Return a list of Label objects which match this StockItem + """ + + labels = [] + + item_query = StockItem.objects.filter(pk=self.pk) + + for lbl in label.models.StockItemLabel.objects.filter(enabled=True): + + filters = helpers.validateFilterString(lbl.filters) + + if item_query.filter(**filters).exists(): + labels.append(lbl) + + return labels + @property def has_labels(self): """ Return True if there are any label templates available for this stock item """ - # TODO - Implement this - return True + return len(self.available_labels()) > 0 @receiver(pre_delete, sender=StockItem, dispatch_uid='stock_item_pre_delete_log') diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html index bea7057351..8e4693cbc1 100644 --- a/InvenTree/stock/templates/stock/item_base.html +++ b/InvenTree/stock/templates/stock/item_base.html @@ -403,12 +403,7 @@ $("#stock-test-report").click(function() { }); $("#print-label").click(function() { - launchModalForm( - "{% url 'stock-item-label-select' item.id %}", - { - follow: true, - } - ) + printStockItemLabels([{{ item.pk }}]); }); $("#stock-duplicate").click(function() { diff --git a/InvenTree/stock/templates/stock/location.html b/InvenTree/stock/templates/stock/location.html index 765a4bd903..d613a26b22 100644 --- a/InvenTree/stock/templates/stock/location.html +++ b/InvenTree/stock/templates/stock/location.html @@ -29,7 +29,7 @@ @@ -205,6 +205,15 @@ } }); }); + + $('#print-label').click(function() { + + var locs = [{{ location.pk }}]; + + printStockLocationLabels(locs); + + }); + {% endif %} $('#show-qr-code').click(function() { diff --git a/InvenTree/stock/urls.py b/InvenTree/stock/urls.py index 7ad8bc4f7f..6aeb1f5b73 100644 --- a/InvenTree/stock/urls.py +++ b/InvenTree/stock/urls.py @@ -30,7 +30,6 @@ stock_item_detail_urls = [ url(r'^add_tracking/', views.StockItemTrackingCreate.as_view(), name='stock-tracking-create'), url(r'^test-report-select/', views.StockItemTestReportSelect.as_view(), name='stock-item-test-report-select'), - url(r'^label-select/', views.StockItemSelectLabels.as_view(), name='stock-item-label-select'), url(r'^test/', views.StockItemDetail.as_view(template_name='stock/item_tests.html'), name='stock-item-test-results'), url(r'^children/', views.StockItemDetail.as_view(template_name='stock/item_childs.html'), name='stock-item-children'), @@ -64,7 +63,6 @@ stock_urls = [ url(r'^item/uninstall/', views.StockItemUninstall.as_view(), name='stock-item-uninstall'), url(r'^item/test-report-download/', views.StockItemTestReportDownload.as_view(), name='stock-item-test-report-download'), - url(r'^item/print-stock-labels/', views.StockItemPrintLabels.as_view(), name='stock-item-print-labels'), # URLs for StockItem attachments url(r'^item/attachment/', include([ diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index 5d505b5280..163d1ed112 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -31,7 +31,6 @@ from datetime import datetime, timedelta from company.models import Company, SupplierPart from part.models import Part from report.models import TestReport -from label.models import StockItemLabel from .models import StockItem, StockLocation, StockItemTracking, StockItemAttachment, StockItemTestResult import common.settings @@ -304,92 +303,6 @@ class StockItemReturnToStock(AjaxUpdateView): } -class StockItemSelectLabels(AjaxView): - """ - View for selecting a template for printing labels for one (or more) StockItem objects - """ - - model = StockItem - ajax_form_title = _('Select Label Template') - role_required = 'stock.view' - - def get_form(self): - - item = StockItem.objects.get(pk=self.kwargs['pk']) - - labels = [] - - # Construct a list of StockItemLabel objects which are enabled, and the filters match the selected StockItem - for label in StockItemLabel.objects.filter(enabled=True): - if label.matches_stock_item(item): - labels.append(label) - - return StockForms.StockItemLabelSelectForm(labels) - - def post(self, request, *args, **kwargs): - - label = request.POST.get('label', None) - - try: - label = StockItemLabel.objects.get(pk=label) - except (ValueError, StockItemLabel.DoesNotExist): - raise ValidationError({'label': _("Select valid label")}) - - stock_item = StockItem.objects.get(pk=self.kwargs['pk']) - - url = reverse('stock-item-print-labels') - - url += '?label={pk}'.format(pk=label.pk) - url += '&items[]={pk}'.format(pk=stock_item.pk) - - data = { - 'form_valid': True, - 'url': url, - } - - return self.renderJsonResponse(request, self.get_form(), data=data) - - -class StockItemPrintLabels(AjaxView): - """ - View for printing labels and returning a PDF - - Requires the following arguments to be passed as URL params: - - items: List of valid StockItem pk values - label: Valid pk of a StockItemLabel template - """ - - role_required = 'stock.view' - - def get(self, request, *args, **kwargs): - - label = request.GET.get('label', None) - - try: - label = StockItemLabel.objects.get(pk=label) - except (ValueError, StockItemLabel.DoesNotExist): - raise ValidationError({'label': 'Invalid label ID'}) - - item_pks = request.GET.getlist('items[]') - - items = [] - - for pk in item_pks: - try: - item = StockItem.objects.get(pk=pk) - items.append(item) - except (ValueError, StockItem.DoesNotExist): - pass - - if len(items) == 0: - raise ValidationError({'items': 'Must provide valid stockitems'}) - - pdf = label.render(items).getbuffer() - - return DownloadFile(pdf, 'stock_labels.pdf', content_type='application/pdf') - - class StockItemDeleteTestData(AjaxUpdateView): """ View for deleting all test data diff --git a/InvenTree/templates/base.html b/InvenTree/templates/base.html index c025919936..36f4974816 100644 --- a/InvenTree/templates/base.html +++ b/InvenTree/templates/base.html @@ -112,7 +112,6 @@ InvenTree - @@ -120,6 +119,8 @@ InvenTree + + diff --git a/InvenTree/templates/js/label.js b/InvenTree/templates/js/label.js new file mode 100644 index 0000000000..93eb1c60c5 --- /dev/null +++ b/InvenTree/templates/js/label.js @@ -0,0 +1,173 @@ +{% load i18n %} + +function printStockItemLabels(items, options={}) { + /** + * Print stock item labels for the given stock items + */ + + if (items.length == 0) { + showAlertDialog( + '{% trans "Select Stock Items" %}', + '{% trans "Stock item(s) must be selected before printing labels" %}' + ); + + return; + } + + // Request available labels from the server + inventreeGet( + '{% url "api-stockitem-label-list" %}', + { + enabled: true, + items: items, + }, + { + success: function(response) { + + if (response.length == 0) { + showAlertDialog( + '{% trans "No Labels Found" %}', + '{% trans "No labels found which match selected stock item(s)" %}', + ); + + return; + } + + // Select label to print + selectLabel( + response, + items, + { + success: function(pk) { + var href = `/api/label/stock/${pk}/print/?`; + + items.forEach(function(item) { + href += `items[]=${item}&`; + }); + + window.location.href = href; + } + } + ); + } + } + ); +} + +function printStockLocationLabels(locations, options={}) { + + if (locations.length == 0) { + showAlertDialog( + '{% trans "Select Stock Locations" %}', + '{% trans "Stock location(s) must be selected before printing labels" %}' + ); + + return; + } + + // Request available labels from the server + inventreeGet( + '{% url "api-stocklocation-label-list" %}', + { + enabled: true, + locations: locations, + }, + { + success: function(response) { + if (response.length == 0) { + showAlertDialog( + '{% trans "No Labels Found" %}', + '{% trans "No labels found which match selected stock location(s)" %}', + ); + + return; + } + + // Select label to print + selectLabel( + response, + locations, + { + success: function(pk) { + var href = `/api/label/location/${pk}/print/?`; + + locations.forEach(function(location) { + href += `locations[]=${location}&`; + }); + + window.location.href = href; + } + } + ); + } + } + ) +} + + +function selectLabel(labels, items, options={}) { + /** + * Present the user with the available labels, + * and allow them to select which label to print. + * + * The intent is that the available labels have been requested + * (via AJAX) from the server. + */ + + var modal = options.modal || '#modal-form'; + + var label_list = makeOptionsList( + labels, + function(item) { + var text = item.name; + + if (item.description) { + text += ` - ${item.description}`; + } + + return text; + }, + function(item) { + return item.pk; + } + ); + + // Construct form + var html = ` + +
+
+ +
+ +
+
+
`; + + openModal({ + modal: modal, + }); + + modalEnable(modal, true); + modalSetTitle(modal, '{% trans "Select Label Template" %}'); + modalSetContent(modal, html); + + attachSelect(modal); + + modalSubmit(modal, function() { + + var label = $(modal).find('#id_label'); + + var pk = label.val(); + + closeModal(modal); + + if (options.success) { + options.success(pk); + } + }); +} \ No newline at end of file diff --git a/InvenTree/InvenTree/static/script/inventree/modals.js b/InvenTree/templates/js/modals.js similarity index 92% rename from InvenTree/InvenTree/static/script/inventree/modals.js rename to InvenTree/templates/js/modals.js index 12a496c481..33be851d83 100644 --- a/InvenTree/InvenTree/static/script/inventree/modals.js +++ b/InvenTree/templates/js/modals.js @@ -1,3 +1,5 @@ +{% load i18n %} + function makeOption(text, value, title) { /* Format an option for a select element */ @@ -164,6 +166,15 @@ function setFieldValue(fieldName, value, options={}) { field.val(value); } +function getFieldValue(fieldName, options={}) { + + var modal = options.modal || '#modal-form'; + + var field = getFieldByName(modal, fieldName); + + return field.val(); +} + function partialMatcher(params, data) { /* Replacement function for the 'matcher' parameter for a select2 dropdown. @@ -392,7 +403,7 @@ function renderErrorMessage(xhr) {
@@ -459,8 +470,8 @@ function showQuestionDialog(title, content, options={}) { modalSetTitle(modal, title); modalSetContent(modal, content); - var accept_text = options.accept_text || 'Accept'; - var cancel_text = options.cancel_text || 'Cancel'; + var accept_text = options.accept_text || '{% trans "Accept" %}'; + var cancel_text = options.cancel_text || '{% trans "Cancel" %}'; $(modal).find('#modal-form-cancel').html(cancel_text); $(modal).find('#modal-form-accept').html(accept_text); @@ -524,7 +535,7 @@ function openModal(options) { if (options.title) { modalSetTitle(modal, options.title); } else { - modalSetTitle(modal, 'Loading Data...'); + modalSetTitle(modal, '{% trans "Loading Data" %}...'); } // Unless the content is explicitly set, display loading message @@ -535,8 +546,8 @@ function openModal(options) { } // Default labels for 'Submit' and 'Close' buttons in the form - var submit_text = options.submit_text || 'Submit'; - var close_text = options.close_text || 'Close'; + var submit_text = options.submit_text || '{% trans "Submit" %}'; + var close_text = options.close_text || '{% trans "Close" %}'; modalSetButtonText(modal, submit_text, close_text); @@ -745,7 +756,7 @@ function handleModalForm(url, options) { } else { $(modal).modal('hide'); - showAlertDialog('Invalid response from server', 'Form data missing from server response'); + showAlertDialog('{% trans "Invalid response from server" %}', '{% trans "Form data missing from server response" %}'); } } } @@ -758,7 +769,7 @@ function handleModalForm(url, options) { // There was an error submitting form data via POST $(modal).modal('hide'); - showAlertDialog('Error posting form data', renderErrorMessage(xhr)); + showAlertDialog('{% trans "Error posting form data" %}', renderErrorMessage(xhr)); }, complete: function(xhr) { //TODO @@ -793,8 +804,8 @@ function launchModalForm(url, options = {}) { var modal = options.modal || '#modal-form'; // Default labels for 'Submit' and 'Close' buttons in the form - var submit_text = options.submit_text || 'Submit'; - var close_text = options.close_text || 'Close'; + var submit_text = options.submit_text || '{% trans "Submit" %}'; + var close_text = options.close_text || '{% trans "Close" %}'; // Form the ajax request to retrieve the django form data ajax_data = { @@ -842,7 +853,7 @@ function launchModalForm(url, options = {}) { } else { $(modal).modal('hide'); - showAlertDialog('Invalid server response', 'JSON response missing form data'); + showAlertDialog('{% trans "Invalid server response" %}', '{% trans "JSON response missing form data" %}'); } }, error: function (xhr, ajaxOptions, thrownError) { @@ -852,36 +863,36 @@ function launchModalForm(url, options = {}) { if (xhr.status == 0) { // No response from the server showAlertDialog( - "No Response", - "No response from the InvenTree server", + '{% trans "No Response" %}', + '{% trans "No response from the InvenTree server" %}', ); } else if (xhr.status == 400) { showAlertDialog( - "Error 400: Bad Request", - "Server returned error code 400" + '{% trans "Error 400: Bad Request" %}', + '{% trans "Server returned error code 400" %}', ); } else if (xhr.status == 401) { showAlertDialog( - "Error 401: Not Authenticated", - "Authentication credentials not supplied" + '{% trans "Error 401: Not Authenticated" %}', + '{% trans "Authentication credentials not supplied" %}', ); } else if (xhr.status == 403) { showAlertDialog( - "Error 403: Permission Denied", - "You do not have the required permissions to access this function" + '{% trans "Error 403: Permission Denied" %}', + '{% trans "You do not have the required permissions to access this function" %}', ); } else if (xhr.status == 404) { showAlertDialog( - "Error 404: Resource Not Found", - "The requested resource could not be located on the server" + '{% trans "Error 404: Resource Not Found" %}', + '{% trans "The requested resource could not be located on the server" %}', ); } else if (xhr.status == 408) { showAlertDialog( - "Error 408: Timeout", - "Connection timeout while requesting data from server" + '{% trans "Error 408: Timeout" %}', + '{% trans "Connection timeout while requesting data from server" %}', ); } else { - showAlertDialog('Error requesting form data', renderErrorMessage(xhr)); + showAlertDialog('{% trans "Error requesting form data" %}', renderErrorMessage(xhr)); } console.log("Modal form error: " + xhr.status); diff --git a/InvenTree/templates/js/stock.js b/InvenTree/templates/js/stock.js index e9cb5e2696..836fa0e242 100644 --- a/InvenTree/templates/js/stock.js +++ b/InvenTree/templates/js/stock.js @@ -660,6 +660,18 @@ function loadStockTable(table, options) { } // Automatically link button callbacks + $('#multi-item-print-label').click(function() { + var selections = $('#stock-table').bootstrapTable('getSelections'); + + var items = []; + + selections.forEach(function(item) { + items.push(item.pk); + }); + + printStockItemLabels(items); + }); + $('#multi-item-stocktake').click(function() { stockAdjustment('count'); }); diff --git a/InvenTree/templates/stock_table.html b/InvenTree/templates/stock_table.html index f39f9c733a..6731f8f69c 100644 --- a/InvenTree/templates/stock_table.html +++ b/InvenTree/templates/stock_table.html @@ -17,6 +17,7 @@