diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index 9880662e63..28cebbcd3d 100644 --- a/InvenTree/InvenTree/helpers.py +++ b/InvenTree/InvenTree/helpers.py @@ -242,7 +242,7 @@ def WrapWithQuotes(text, quote='"'): return text -def MakeBarcode(object_name, object_data): +def MakeBarcode(object_name, object_pk, object_data, **kwargs): """ Generate a string for a barcode. Adds some global InvenTree parameters. Args: @@ -255,12 +255,20 @@ def MakeBarcode(object_name, object_data): json string of the supplied data plus some other data """ - data = { - 'tool': 'InvenTree', - 'version': inventreeVersion(), - 'instance': inventreeInstanceName(), - object_name: object_data - } + brief = kwargs.get('brief', False) + + data = {} + + if brief: + data[object_name] = object_pk + else: + data['tool'] = 'InvenTree' + data['version'] = inventreeVersion() + data['instance'] = inventreeInstanceName() + + # Ensure PK is included + object_data['id'] = object_pk + data[object_name] = object_data return json.dumps(data, sort_keys=True) @@ -383,3 +391,56 @@ def ExtractSerialNumbers(serials, expected_quantity): raise ValidationError([_("Number of unique serial number ({s}) must match quantity ({q})".format(s=len(numbers), q=expected_quantity))]) return numbers + + +def validateFilterString(value): + """ + Validate that a provided filter string looks like a list of comma-separated key=value pairs + + These should nominally match to a valid database filter based on the model being filtered. + + e.g. "category=6, IPN=12" + e.g. "part__name=widget" + + The ReportTemplate class uses the filter string to work out which items a given report applies to. + For example, an acceptance test report template might only apply to stock items with a given IPN, + so the string could be set to: + + filters = "IPN = ACME0001" + + Returns a map of key:value pairs + """ + + # Empty results map + results = {} + + value = str(value).strip() + + if not value or len(value) == 0: + return results + + groups = value.split(',') + + for group in groups: + group = group.strip() + + pair = group.split('=') + + if not len(pair) == 2: + raise ValidationError( + "Invalid group: {g}".format(g=group) + ) + + k, v = pair + + k = k.strip() + v = v.strip() + + if not k or not v: + raise ValidationError( + "Invalid group: {g}".format(g=group) + ) + + results[k] = v + + return results diff --git a/InvenTree/InvenTree/middleware.py b/InvenTree/InvenTree/middleware.py index 26cbc95bbf..37b9a27c63 100644 --- a/InvenTree/InvenTree/middleware.py +++ b/InvenTree/InvenTree/middleware.py @@ -91,6 +91,8 @@ class QueryCountMiddleware(object): To enable this middleware, set 'log_queries: True' in the local InvenTree config file. Reference: https://www.dabapps.com/blog/logging-sql-queries-django-13/ + + Note: 2020-08-15 - This is no longer used, instead we now rely on the django-debug-toolbar addon """ def __init__(self, get_response): diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index e5b14314b5..d3a5ee919d 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -130,6 +130,7 @@ INSTALLED_APPS = [ 'build.apps.BuildConfig', 'common.apps.CommonConfig', 'company.apps.CompanyConfig', + 'label.apps.LabelConfig', 'order.apps.OrderConfig', 'part.apps.PartConfig', 'report.apps.ReportConfig', @@ -172,11 +173,15 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'InvenTree.middleware.AuthRequiredMiddleware', + + 'InvenTree.middleware.AuthRequiredMiddleware' ] -if CONFIG.get('log_queries', False): - MIDDLEWARE.append('InvenTree.middleware.QueryCountMiddleware') +# If the debug toolbar is enabled, add the modules +if DEBUG and CONFIG.get('debug_toolbar', False): + print("Running with DEBUG_TOOLBAR enabled") + INSTALLED_APPS.append('debug_toolbar') + MIDDLEWARE.append('debug_toolbar.middleware.DebugToolbarMiddleware') ROOT_URLCONF = 'InvenTree.urls' @@ -377,3 +382,8 @@ DBBACKUP_STORAGE = 'django.core.files.storage.FileSystemStorage' DBBACKUP_STORAGE_OPTIONS = { 'location': CONFIG.get('backup_dir', tempfile.gettempdir()), } + +# Internal IP addresses allowed to see the debug toolbar +INTERNAL_IPS = [ + '127.0.0.1', +] diff --git a/InvenTree/InvenTree/status_codes.py b/InvenTree/InvenTree/status_codes.py index f8089cb5de..2032ec75d8 100644 --- a/InvenTree/InvenTree/status_codes.py +++ b/InvenTree/InvenTree/status_codes.py @@ -167,10 +167,6 @@ class StockStatus(StatusCode): # This can be used as a quick check for filtering NOT_IN_STOCK = 100 - SHIPPED = 110 # Item has been shipped to a customer - ASSIGNED_TO_BUILD = 120 - ASSIGNED_TO_OTHER_ITEM = 130 - options = { OK: _("OK"), ATTENTION: _("Attention needed"), @@ -179,9 +175,6 @@ class StockStatus(StatusCode): LOST: _("Lost"), REJECTED: _("Rejected"), RETURNED: _("Returned"), - SHIPPED: _('Shipped'), - ASSIGNED_TO_BUILD: _("Used for Build"), - ASSIGNED_TO_OTHER_ITEM: _("Installed in Stock Item") } colors = { @@ -190,9 +183,6 @@ class StockStatus(StatusCode): DAMAGED: 'red', DESTROYED: 'red', REJECTED: 'red', - SHIPPED: 'green', - ASSIGNED_TO_BUILD: 'blue', - ASSIGNED_TO_OTHER_ITEM: 'blue', } # The following codes correspond to parts that are 'available' or 'in stock' @@ -208,9 +198,6 @@ class StockStatus(StatusCode): DESTROYED, LOST, REJECTED, - SHIPPED, - ASSIGNED_TO_BUILD, - ASSIGNED_TO_OTHER_ITEM, ] # The following codes are available for receiving goods diff --git a/InvenTree/InvenTree/tests.py b/InvenTree/InvenTree/tests.py index 877adab919..c46a059c8d 100644 --- a/InvenTree/InvenTree/tests.py +++ b/InvenTree/InvenTree/tests.py @@ -138,6 +138,7 @@ class TestMakeBarcode(TestCase): bc = helpers.MakeBarcode( "part", + 3, { "id": 3, "url": "www.google.com", diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index c2d0d0f48f..d0076714ae 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -6,6 +6,7 @@ Passes URL lookup downstream to each app as required. from django.conf.urls import url, include +from django.urls import path from django.contrib import admin from django.contrib.auth import views as auth_views from qr_code import urls as qr_code_urls @@ -135,5 +136,12 @@ urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) # Media file access urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) +# Debug toolbar access (if in DEBUG mode) +if settings.DEBUG and 'debug_toolbar' in settings.INSTALLED_APPS: + import debug_toolbar + urlpatterns = [ + path('__debug/', include(debug_toolbar.urls)), + ] + urlpatterns + # Send any unknown URLs to the parts page urlpatterns += [url(r'^.*$', RedirectView.as_view(url='/index/', permanent=False), name='index')] diff --git a/InvenTree/InvenTree/version.py b/InvenTree/InvenTree/version.py index 69de0ddf00..e000f40076 100644 --- a/InvenTree/InvenTree/version.py +++ b/InvenTree/InvenTree/version.py @@ -6,7 +6,7 @@ import subprocess from common.models import InvenTreeSetting import django -INVENTREE_SW_VERSION = "0.1.1 pre" +INVENTREE_SW_VERSION = "0.1.3 pre" def inventreeInstanceName(): diff --git a/InvenTree/barcode/plugins/inventree_barcode.py b/InvenTree/barcode/plugins/inventree_barcode.py index 821cdc9c88..6e4e6937a0 100644 --- a/InvenTree/barcode/plugins/inventree_barcode.py +++ b/InvenTree/barcode/plugins/inventree_barcode.py @@ -47,12 +47,12 @@ class InvenTreeBarcodePlugin(BarcodePlugin): else: return False - for key in ['tool', 'version']: - if key not in self.data.keys(): - return False + # If any of the following keys are in the JSON data, + # let's go ahead and assume that the code is a valid InvenTree one... - if not self.data['tool'] == 'InvenTree': - return False + for key in ['tool', 'version', 'InvenTree', 'stockitem', 'location', 'part']: + if key in self.data.keys(): + return True return True @@ -60,10 +60,22 @@ class InvenTreeBarcodePlugin(BarcodePlugin): for k in self.data.keys(): if k.lower() == 'stockitem': + + data = self.data[k] + + pk = None + + # Initially try casting to an integer try: - pk = self.data[k]['id'] - except (AttributeError, KeyError): - raise ValidationError({k: "id parameter not supplied"}) + pk = int(data) + except (TypeError, ValueError): + pk = None + + if pk is None: + try: + pk = self.data[k]['id'] + except (AttributeError, KeyError): + raise ValidationError({k: "id parameter not supplied"}) try: item = StockItem.objects.get(pk=pk) @@ -77,10 +89,21 @@ class InvenTreeBarcodePlugin(BarcodePlugin): for k in self.data.keys(): if k.lower() == 'stocklocation': + + pk = None + + # First try simple integer lookup try: - pk = self.data[k]['id'] - except (AttributeError, KeyError): - raise ValidationError({k: "id parameter not supplied"}) + pk = int(self.data[k]) + except (TypeError, ValueError): + pk = None + + if pk is None: + # Lookup by 'id' field + try: + pk = self.data[k]['id'] + except (AttributeError, KeyError): + raise ValidationError({k: "id parameter not supplied"}) try: loc = StockLocation.objects.get(pk=pk) @@ -94,10 +117,20 @@ class InvenTreeBarcodePlugin(BarcodePlugin): for k in self.data.keys(): if k.lower() == 'part': + + pk = None + + # Try integer lookup first try: - pk = self.data[k]['id'] - except (AttributeError, KeyError): - raise ValidationError({k, 'id parameter not supplied'}) + pk = int(self.data[k]) + except (TypeError, ValueError): + pk = None + + if pk is None: + try: + pk = self.data[k]['id'] + except (AttributeError, KeyError): + raise ValidationError({k, 'id parameter not supplied'}) try: part = Part.objects.get(pk=pk) diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index 23043d077f..89e79761e8 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -21,7 +21,7 @@ from markdownx.models import MarkdownxField from mptt.models import MPTTModel, TreeForeignKey -from InvenTree.status_codes import BuildStatus, StockStatus +from InvenTree.status_codes import BuildStatus from InvenTree.fields import InvenTreeURLField from InvenTree.helpers import decimal2string @@ -501,7 +501,6 @@ class BuildItem(models.Model): # TODO - If the item__part object is not trackable, delete the stock item here - item.status = StockStatus.ASSIGNED_TO_BUILD item.build_order = self.build item.save() diff --git a/InvenTree/build/test_build.py b/InvenTree/build/test_build.py index c1fb4a5efd..32ad33dab3 100644 --- a/InvenTree/build/test_build.py +++ b/InvenTree/build/test_build.py @@ -211,15 +211,12 @@ class BuildTest(TestCase): # New stock items created and assigned to the build self.assertEqual(StockItem.objects.get(pk=4).quantity, 50) self.assertEqual(StockItem.objects.get(pk=4).build_order, self.build) - self.assertEqual(StockItem.objects.get(pk=4).status, status.StockStatus.ASSIGNED_TO_BUILD) self.assertEqual(StockItem.objects.get(pk=5).quantity, 50) self.assertEqual(StockItem.objects.get(pk=5).build_order, self.build) - self.assertEqual(StockItem.objects.get(pk=5).status, status.StockStatus.ASSIGNED_TO_BUILD) self.assertEqual(StockItem.objects.get(pk=6).quantity, 250) self.assertEqual(StockItem.objects.get(pk=6).build_order, self.build) - self.assertEqual(StockItem.objects.get(pk=6).status, status.StockStatus.ASSIGNED_TO_BUILD) # And a new stock item created for the build output self.assertEqual(StockItem.objects.get(pk=7).quantity, 1) diff --git a/InvenTree/company/migrations/0023_auto_20200808_0715.py b/InvenTree/company/migrations/0023_auto_20200808_0715.py new file mode 100644 index 0000000000..22097e8e2b --- /dev/null +++ b/InvenTree/company/migrations/0023_auto_20200808_0715.py @@ -0,0 +1,17 @@ +# Generated by Django 3.0.7 on 2020-08-08 07:15 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('company', '0022_auto_20200613_1045'), + ] + + operations = [ + migrations.AlterModelOptions( + name='company', + options={'ordering': ['name']}, + ), + ] diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index 2179897263..a06ddd94bf 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -79,6 +79,9 @@ class Company(models.Model): is_manufacturer: boolean value, is this company a manufacturer """ + class Meta: + ordering = ['name', ] + name = models.CharField(max_length=100, blank=False, unique=True, help_text=_('Company name'), verbose_name=_('Company name')) diff --git a/InvenTree/company/serializers.py b/InvenTree/company/serializers.py index 09f2b4dee8..baa618fb28 100644 --- a/InvenTree/company/serializers.py +++ b/InvenTree/company/serializers.py @@ -99,6 +99,10 @@ class SupplierPartSerializer(InvenTreeModelSerializer): if manufacturer_detail is not True: self.fields.pop('manufacturer_detail') + supplier = serializers.PrimaryKeyRelatedField(queryset=Company.objects.filter(is_supplier=True)) + + manufacturer = serializers.PrimaryKeyRelatedField(queryset=Company.objects.filter(is_manufacturer=True)) + class Meta: model = SupplierPart fields = [ diff --git a/InvenTree/company/templates/company/detail_stock.html b/InvenTree/company/templates/company/detail_stock.html index c33179d454..e994d5834b 100644 --- a/InvenTree/company/templates/company/detail_stock.html +++ b/InvenTree/company/templates/company/detail_stock.html @@ -26,7 +26,8 @@ }, buttons: [ '#stock-options', - ] + ], + filterKey: "companystock", }); $("#stock-export").click(function() { diff --git a/InvenTree/config_template.yaml b/InvenTree/config_template.yaml index 5447606337..1c776a6f7a 100644 --- a/InvenTree/config_template.yaml +++ b/InvenTree/config_template.yaml @@ -58,9 +58,10 @@ static_root: '../inventree_static' # - git # - ssh -# Logging options -# If debug mode is enabled, set log_queries to True to show aggregate database queries in the debug console -log_queries: False +# Set debug_toolbar to True to enable a debugging toolbar for InvenTree +# Note: This will only be displayed if DEBUG mode is enabled, +# and only if InvenTree is accessed from a local IP (127.0.0.1) +debug_toolbar: False # Backup options # Set the backup_dir parameter to store backup files in a specific location diff --git a/InvenTree/label/__init__.py b/InvenTree/label/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/InvenTree/label/admin.py b/InvenTree/label/admin.py new file mode 100644 index 0000000000..bc03e122b6 --- /dev/null +++ b/InvenTree/label/admin.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.contrib import admin + +from .models import StockItemLabel + + +class StockItemLabelAdmin(admin.ModelAdmin): + + list_display = ('name', 'description', 'label') + + +admin.site.register(StockItemLabel, StockItemLabelAdmin) diff --git a/InvenTree/label/apps.py b/InvenTree/label/apps.py new file mode 100644 index 0000000000..ea4fa152ff --- /dev/null +++ b/InvenTree/label/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class LabelConfig(AppConfig): + name = 'label' diff --git a/InvenTree/label/migrations/0001_initial.py b/InvenTree/label/migrations/0001_initial.py new file mode 100644 index 0000000000..e960bcef67 --- /dev/null +++ b/InvenTree/label/migrations/0001_initial.py @@ -0,0 +1,30 @@ +# Generated by Django 3.0.7 on 2020-08-15 23:27 + +import InvenTree.helpers +import django.core.validators +from django.db import migrations, models +import label.models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='StockItemLabel', + 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])), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/InvenTree/label/migrations/__init__.py b/InvenTree/label/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/InvenTree/label/models.py b/InvenTree/label/models.py new file mode 100644 index 0000000000..7d481327a9 --- /dev/null +++ b/InvenTree/label/models.py @@ -0,0 +1,149 @@ +""" +Label printing models +""" + +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import os +import io + +from blabel import LabelWriter + +from django.db import models +from django.core.validators import FileExtensionValidator + +from django.utils.translation import gettext_lazy as _ + +from InvenTree.helpers import validateFilterString, normalize + +from stock.models import StockItem + + +def rename_label(instance, filename): + """ Place the label file into the correct subdirectory """ + + filename = os.path.basename(filename) + + return os.path.join('label', 'template', instance.SUBDIR, filename) + + +class LabelTemplate(models.Model): + """ + Base class for generic, filterable labels. + """ + + class Meta: + abstract = True + + # Each class of label files will be stored in a separate subdirectory + SUBDIR = "label" + + @property + def template(self): + return self.label.path + + def __str__(self): + return "{n} - {d}".format( + n=self.name, + d=self.description + ) + + name = models.CharField( + unique=True, + blank=False, max_length=100, + help_text=_('Label name'), + ) + + description = models.CharField(max_length=250, help_text=_('Label description'), blank=True, null=True) + + label = models.FileField( + upload_to=rename_label, + blank=False, null=False, + 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] + ) + + def get_record_data(self, items): + """ + Return a list of dict objects, one for each item. + """ + + return [] + + def render_to_file(self, filename, items, **kwargs): + """ + Render labels to a PDF file + """ + + records = self.get_record_data(items) + + writer = LabelWriter(self.template) + + writer.write_labels(records, filename) + + def render(self, items, **kwargs): + """ + Render labels to an in-memory PDF object, and return it + """ + + records = self.get_record_data(items) + + writer = LabelWriter(self.template) + + buffer = io.BytesIO() + + writer.write_labels(records, buffer) + + return buffer + + +class StockItemLabel(LabelTemplate): + """ + Template for printing StockItem labels + """ + + SUBDIR = "stockitem" + + def matches_stock_item(self, item): + """ + Test if this label template matches a given StockItem object + """ + + filters = validateFilterString(self.filters) + + items = StockItem.objects.filter(**filters) + + items = items.filter(pk=item.pk) + + return items.exists() + + def get_record_data(self, items): + """ + Generate context data for each provided StockItem + """ + records = [] + + for item in items: + + # Add some basic information + records.append({ + 'item': item, + 'part': item.part, + 'name': item.part.name, + 'ipn': item.part.IPN, + 'quantity': normalize(item.quantity), + 'serial': item.serial, + 'uid': item.uid, + 'pk': item.pk, + 'qr_data': item.format_barcode(brief=True), + 'tests': item.testResultMap() + }) + + return records diff --git a/InvenTree/label/tests.py b/InvenTree/label/tests.py new file mode 100644 index 0000000000..a39b155ac3 --- /dev/null +++ b/InvenTree/label/tests.py @@ -0,0 +1 @@ +# Create your tests here. diff --git a/InvenTree/label/views.py b/InvenTree/label/views.py new file mode 100644 index 0000000000..60f00ef0ef --- /dev/null +++ b/InvenTree/label/views.py @@ -0,0 +1 @@ +# Create your views here. diff --git a/InvenTree/locale/de/LC_MESSAGES/django.mo b/InvenTree/locale/de/LC_MESSAGES/django.mo index 93b1affc81..758fa8c4cd 100644 Binary files a/InvenTree/locale/de/LC_MESSAGES/django.mo and b/InvenTree/locale/de/LC_MESSAGES/django.mo differ diff --git a/InvenTree/locale/de/LC_MESSAGES/django.po b/InvenTree/locale/de/LC_MESSAGES/django.po index 18a24b1387..584d9db2a8 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: 2020-06-12 00:43+0000\n" +"POT-Creation-Date: 2020-08-16 02:11+0000\n" "PO-Revision-Date: 2020-05-03 11:32+0200\n" "Last-Translator: Christian Schlüter \n" "Language-Team: C \n" @@ -83,7 +83,7 @@ msgstr "Datei zum Anhängen auswählen" msgid "File comment" msgstr "Datei-Kommentar" -#: InvenTree/models.py:68 templates/js/stock.html:662 +#: InvenTree/models.py:68 templates/js/stock.html:682 msgid "User" msgstr "Benutzer" @@ -97,24 +97,24 @@ msgstr "Name" msgid "Description (optional)" msgstr "Firmenbeschreibung" -#: InvenTree/settings.py:330 +#: InvenTree/settings.py:335 msgid "English" msgstr "Englisch" -#: InvenTree/settings.py:331 +#: InvenTree/settings.py:336 msgid "German" msgstr "Deutsch" -#: InvenTree/settings.py:332 +#: InvenTree/settings.py:337 msgid "French" msgstr "Französisch" -#: InvenTree/settings.py:333 +#: InvenTree/settings.py:338 msgid "Polish" msgstr "Polnisch" #: InvenTree/status_codes.py:94 InvenTree/status_codes.py:135 -#: InvenTree/status_codes.py:235 +#: InvenTree/status_codes.py:222 msgid "Pending" msgstr "Ausstehend" @@ -122,59 +122,50 @@ msgstr "Ausstehend" msgid "Placed" msgstr "Platziert" -#: InvenTree/status_codes.py:96 InvenTree/status_codes.py:238 +#: InvenTree/status_codes.py:96 InvenTree/status_codes.py:225 msgid "Complete" msgstr "Fertig" #: InvenTree/status_codes.py:97 InvenTree/status_codes.py:137 -#: InvenTree/status_codes.py:237 +#: InvenTree/status_codes.py:224 msgid "Cancelled" msgstr "Storniert" #: InvenTree/status_codes.py:98 InvenTree/status_codes.py:138 -#: InvenTree/status_codes.py:179 +#: InvenTree/status_codes.py:175 msgid "Lost" msgstr "Verloren" #: InvenTree/status_codes.py:99 InvenTree/status_codes.py:139 -#: InvenTree/status_codes.py:181 +#: InvenTree/status_codes.py:177 msgid "Returned" msgstr "Zurückgegeben" -#: InvenTree/status_codes.py:136 InvenTree/status_codes.py:182 -#: order/templates/order/sales_order_base.html:98 +#: InvenTree/status_codes.py:136 order/templates/order/sales_order_base.html:98 msgid "Shipped" msgstr "Versendet" -#: InvenTree/status_codes.py:175 +#: InvenTree/status_codes.py:171 msgid "OK" msgstr "OK" -#: InvenTree/status_codes.py:176 +#: InvenTree/status_codes.py:172 msgid "Attention needed" msgstr "erfordert Eingriff" -#: InvenTree/status_codes.py:177 +#: InvenTree/status_codes.py:173 msgid "Damaged" msgstr "Beschädigt" -#: InvenTree/status_codes.py:178 +#: InvenTree/status_codes.py:174 msgid "Destroyed" msgstr "Zerstört" -#: InvenTree/status_codes.py:180 +#: InvenTree/status_codes.py:176 msgid "Rejected" msgstr "" -#: InvenTree/status_codes.py:183 -msgid "Used for Build" -msgstr "Verwendet für Bau" - -#: InvenTree/status_codes.py:184 -msgid "Installed in Stock Item" -msgstr "In Lagerobjekt installiert" - -#: InvenTree/status_codes.py:236 build/templates/build/allocate.html:349 +#: InvenTree/status_codes.py:223 build/templates/build/allocate.html:349 #: order/templates/order/sales_order_detail.html:220 #: part/templates/part/tabs.html:23 templates/js/build.html:120 msgid "Allocated" @@ -265,7 +256,7 @@ msgstr "Standort-Details" msgid "Serial numbers" msgstr "Seriennummer" -#: build/forms.py:64 stock/forms.py:93 +#: build/forms.py:64 stock/forms.py:105 msgid "Enter unique serial numbers (or leave blank)" msgstr "Eindeutige Seriennummern eingeben (oder leer lassen)" @@ -303,9 +294,10 @@ msgstr "Eltern-Bau, dem dieser Bau zugewiesen ist" #: order/templates/order/purchase_order_detail.html:145 #: order/templates/order/receive_parts.html:19 part/models.py:240 #: part/templates/part/part_app_base.html:7 -#: part/templates/part/set_category.html:13 templates/js/bom.html:135 -#: templates/js/build.html:41 templates/js/company.html:109 -#: templates/js/part.html:120 templates/js/stock.html:422 +#: part/templates/part/set_category.html:13 templates/js/barcode.html:336 +#: templates/js/bom.html:135 templates/js/build.html:41 +#: templates/js/company.html:109 templates/js/part.html:120 +#: templates/js/stock.html:425 msgid "Part" msgstr "Teil" @@ -341,7 +333,7 @@ msgstr "Bau-Anzahl" msgid "Number of parts to build" msgstr "Anzahl der zu bauenden Teile" -#: build/models.py:128 part/templates/part/part_base.html:141 +#: build/models.py:128 part/templates/part/part_base.html:139 msgid "Build Status" msgstr "Bau-Status" @@ -349,7 +341,7 @@ msgstr "Bau-Status" msgid "Build status code" msgstr "Bau-Statuscode" -#: build/models.py:136 stock/models.py:374 +#: build/models.py:136 stock/models.py:376 msgid "Batch Code" msgstr "Losnummer" @@ -360,22 +352,22 @@ msgstr "Chargennummer für diese Bau-Ausgabe" #: build/models.py:155 build/templates/build/detail.html:55 #: company/templates/company/supplier_part_base.html:60 #: company/templates/company/supplier_part_detail.html:24 -#: part/templates/part/detail.html:74 part/templates/part/part_base.html:88 -#: stock/models.py:368 stock/templates/stock/item_base.html:230 +#: part/templates/part/detail.html:74 part/templates/part/part_base.html:86 +#: stock/models.py:370 stock/templates/stock/item_base.html:237 msgid "External Link" msgstr "Externer Link" -#: build/models.py:156 stock/models.py:370 +#: build/models.py:156 stock/models.py:372 msgid "Link to external URL" msgstr "Link zu einer externen URL" -#: build/models.py:160 build/templates/build/tabs.html:14 company/models.py:302 +#: build/models.py:160 build/templates/build/tabs.html:14 company/models.py:310 #: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:15 #: order/templates/order/purchase_order_detail.html:200 -#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:73 -#: stock/models.py:436 stock/models.py:1265 stock/templates/stock/tabs.html:26 -#: templates/js/bom.html:229 templates/js/stock.html:113 -#: templates/js/stock.html:506 +#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:64 +#: stock/models.py:438 stock/models.py:1287 stock/templates/stock/tabs.html:26 +#: templates/js/barcode.html:391 templates/js/bom.html:229 +#: templates/js/stock.html:114 templates/js/stock.html:526 msgid "Notes" msgstr "Notizen" @@ -406,15 +398,15 @@ msgstr "Anzahl muss größer null sein" msgid "Quantity must be 1 for serialized stock" msgstr "Anzahl muss 1 für Objekte mit Seriennummer sein" -#: build/models.py:512 +#: build/models.py:511 msgid "Build to allocate parts" msgstr "Bau starten um Teile zuzuweisen" -#: build/models.py:519 +#: build/models.py:518 msgid "Stock Item to allocate to build" msgstr "Lagerobjekt dem Bau zuweisen" -#: build/models.py:532 +#: build/models.py:531 msgid "Stock quantity to allocate to build" msgstr "Lagerobjekt-Anzahl dem Bau zuweisen" @@ -441,8 +433,8 @@ msgstr "Neues Lagerobjekt" #: build/templates/build/allocate.html:161 #: order/templates/order/sales_order_detail.html:68 -#: order/templates/order/sales_order_detail.html:150 stock/models.py:362 -#: stock/templates/stock/item_base.html:189 +#: order/templates/order/sales_order_detail.html:150 stock/models.py:364 +#: stock/templates/stock/item_base.html:153 msgid "Serial Number" msgstr "Seriennummer" @@ -459,16 +451,18 @@ msgstr "Seriennummer" #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:26 #: stock/templates/stock/item_base.html:32 -#: stock/templates/stock/item_base.html:195 -#: stock/templates/stock/stock_adjust.html:18 templates/js/bom.html:172 -#: templates/js/build.html:52 templates/js/stock.html:653 +#: stock/templates/stock/item_base.html:159 +#: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338 +#: templates/js/bom.html:172 templates/js/build.html:52 +#: templates/js/stock.html:673 msgid "Quantity" msgstr "Anzahl" #: build/templates/build/allocate.html:177 #: build/templates/build/auto_allocate.html:20 -#: stock/templates/stock/item_base.html:171 -#: stock/templates/stock/stock_adjust.html:17 templates/js/stock.html:493 +#: stock/templates/stock/item_base.html:191 +#: stock/templates/stock/stock_adjust.html:17 templates/js/barcode.html:337 +#: templates/js/stock.html:508 msgid "Location" msgstr "Standort" @@ -494,7 +488,7 @@ msgstr "Keine BOM-Einträge gefunden" #: templates/js/bom.html:157 templates/js/company.html:60 #: templates/js/order.html:157 templates/js/order.html:230 #: templates/js/part.html:176 templates/js/part.html:355 -#: templates/js/stock.html:443 templates/js/stock.html:634 +#: templates/js/stock.html:440 templates/js/stock.html:654 msgid "Description" msgstr "Beschreibung" @@ -504,8 +498,8 @@ msgstr "Beschreibung" msgid "Reference" msgstr "Referenz" -#: build/templates/build/allocate.html:338 part/models.py:1260 -#: templates/js/part.html:359 templates/js/table_filters.html:63 +#: build/templates/build/allocate.html:338 part/models.py:1270 +#: templates/js/part.html:359 templates/js/table_filters.html:100 msgid "Required" msgstr "benötigt" @@ -549,7 +543,7 @@ msgstr "Keine Lagerobjekt gefunden, die diesem Bau zugewiesen werden können" #: build/templates/build/build_base.html:8 #: build/templates/build/build_base.html:34 #: build/templates/build/complete.html:6 -#: stock/templates/stock/item_base.html:209 templates/js/build.html:33 +#: stock/templates/stock/item_base.html:216 templates/js/build.html:33 #: templates/navbar.html:12 msgid "Build" msgstr "Bau" @@ -569,9 +563,9 @@ msgstr "Bau-Status" #: build/templates/build/build_base.html:80 #: build/templates/build/detail.html:42 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:262 templates/js/build.html:57 -#: templates/js/order.html:162 templates/js/order.html:235 -#: templates/js/stock.html:480 +#: stock/templates/stock/item_base.html:269 templates/js/barcode.html:42 +#: templates/js/build.html:57 templates/js/order.html:162 +#: templates/js/order.html:235 templates/js/stock.html:495 msgid "Status" msgstr "Status" @@ -581,7 +575,7 @@ msgstr "Status" #: order/templates/order/sales_order_notes.html:10 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:27 -#: stock/templates/stock/item_base.html:159 templates/js/order.html:209 +#: stock/templates/stock/item_base.html:179 templates/js/order.html:209 msgid "Sales Order" msgstr "Bestellung" @@ -650,7 +644,7 @@ msgid "Stock can be taken from any available location." msgstr "Bestand kann jedem verfügbaren Lagerort entnommen werden." #: build/templates/build/detail.html:48 -#: stock/templates/stock/item_base.html:202 templates/js/stock.html:488 +#: stock/templates/stock/item_base.html:209 templates/js/stock.html:503 msgid "Batch" msgstr "Los" @@ -754,7 +748,7 @@ msgstr "Zuweisung aufheben" msgid "Confirm unallocation of build stock" msgstr "Zuweisungsaufhebung bestätigen" -#: build/views.py:162 stock/views.py:286 +#: build/views.py:162 stock/views.py:404 msgid "Check the confirmation box" msgstr "Bestätigungsbox bestätigen" @@ -762,7 +756,7 @@ msgstr "Bestätigungsbox bestätigen" msgid "Complete Build" msgstr "Bau fertigstellen" -#: build/views.py:201 stock/views.py:1118 stock/views.py:1232 +#: build/views.py:201 stock/views.py:1236 stock/views.py:1350 msgid "Next available serial number is" msgstr "" @@ -780,7 +774,7 @@ msgstr "Baufertigstellung bestätigen" msgid "Invalid location selected" msgstr "Ungültige Ortsauswahl" -#: build/views.py:300 stock/views.py:1268 +#: build/views.py:300 stock/views.py:1386 #, python-brace-format msgid "The following serial numbers already exist: ({sn})" msgstr "Die folgende Seriennummer existiert bereits: ({sn})" @@ -875,83 +869,117 @@ msgstr "Währung bearbeiten" msgid "Delete Currency" msgstr "Währung entfernen" -#: company/models.py:83 +#: company/models.py:86 company/models.py:87 msgid "Company name" msgstr "Firmenname" -#: company/models.py:85 +#: company/models.py:89 +#, fuzzy +#| msgid "Part description" +msgid "Company description" +msgstr "Beschreibung des Teils" + +#: company/models.py:89 msgid "Description of the company" msgstr "Firmenbeschreibung" -#: company/models.py:87 +#: company/models.py:91 company/templates/company/company_base.html:48 +#: templates/js/company.html:65 +msgid "Website" +msgstr "Website" + +#: company/models.py:91 msgid "Company website URL" msgstr "Firmenwebsite" -#: company/models.py:90 +#: company/models.py:94 company/templates/company/company_base.html:55 +msgid "Address" +msgstr "Adresse" + +#: company/models.py:95 msgid "Company address" msgstr "Firmenadresse" -#: company/models.py:93 +#: company/models.py:98 +#, fuzzy +#| msgid "Contact phone number" +msgid "Phone number" +msgstr "Kontakt-Tel." + +#: company/models.py:99 msgid "Contact phone number" msgstr "Kontakt-Tel." -#: company/models.py:95 +#: company/models.py:101 company/templates/company/company_base.html:69 +msgid "Email" +msgstr "Email" + +#: company/models.py:101 msgid "Contact email address" msgstr "Kontakt-Email" -#: company/models.py:98 +#: company/models.py:104 company/templates/company/company_base.html:76 +msgid "Contact" +msgstr "Kontakt" + +#: company/models.py:105 msgid "Point of contact" msgstr "Anlaufstelle" -#: company/models.py:100 +#: company/models.py:107 msgid "Link to external company information" msgstr "Link auf externe Firmeninformation" -#: company/models.py:112 +#: company/models.py:119 msgid "Do you sell items to this company?" msgstr "Verkaufen Sie Teile an diese Firma?" -#: company/models.py:114 +#: company/models.py:121 msgid "Do you purchase items from this company?" msgstr "Kaufen Sie Teile von dieser Firma?" -#: company/models.py:116 +#: company/models.py:123 msgid "Does this company manufacture parts?" msgstr "Produziert diese Firma Teile?" -#: company/models.py:276 +#: company/models.py:279 stock/models.py:324 +#: stock/templates/stock/item_base.html:145 +msgid "Base Part" +msgstr "Basisteil" + +#: company/models.py:284 msgid "Select part" msgstr "Teil auswählen" -#: company/models.py:282 +#: company/models.py:290 msgid "Select supplier" msgstr "Zulieferer auswählen" -#: company/models.py:285 +#: company/models.py:293 msgid "Supplier stock keeping unit" msgstr "Stock Keeping Units (SKU) des Zulieferers" -#: company/models.py:292 +#: company/models.py:300 msgid "Select manufacturer" msgstr "Hersteller auswählen" -#: company/models.py:296 +#: company/models.py:304 msgid "Manufacturer part number" msgstr "Hersteller-Teilenummer" -#: company/models.py:298 +#: company/models.py:306 msgid "URL for external supplier part link" msgstr "Teil-URL des Zulieferers" -#: company/models.py:300 +#: company/models.py:308 msgid "Supplier part description" msgstr "Zuliefererbeschreibung des Teils" -#: company/models.py:304 +#: company/models.py:312 msgid "Minimum charge (e.g. stocking fee)" msgstr "Mindestpreis" -#: company/models.py:306 +#: company/models.py:314 msgid "Part packaging" msgstr "Teile-Packaging" @@ -972,26 +1000,10 @@ msgstr "Firma" msgid "Company Details" msgstr "Firmendetails" -#: company/templates/company/company_base.html:48 templates/js/company.html:65 -msgid "Website" -msgstr "Website" - -#: company/templates/company/company_base.html:55 -msgid "Address" -msgstr "Adresse" - #: company/templates/company/company_base.html:62 msgid "Phone" msgstr "Telefon" -#: company/templates/company/company_base.html:69 -msgid "Email" -msgstr "Email" - -#: company/templates/company/company_base.html:76 -msgid "Contact" -msgstr "Kontakt" - #: company/templates/company/detail.html:16 #: company/templates/company/supplier_part_base.html:76 #: company/templates/company/supplier_part_detail.html:30 @@ -1004,14 +1016,14 @@ msgstr "Hersteller" #: company/templates/company/supplier_part_detail.html:21 order/models.py:148 #: order/templates/order/order_base.html:74 #: order/templates/order/order_wizard/select_pos.html:30 -#: stock/templates/stock/item_base.html:237 templates/js/company.html:52 +#: stock/templates/stock/item_base.html:244 templates/js/company.html:52 #: templates/js/company.html:134 templates/js/order.html:144 msgid "Supplier" msgstr "Zulieferer" #: company/templates/company/detail.html:26 order/models.py:314 -#: order/templates/order/sales_order_base.html:73 stock/models.py:357 -#: stock/models.py:358 stock/templates/stock/item_base.html:146 +#: order/templates/order/sales_order_base.html:73 stock/models.py:359 +#: stock/models.py:360 stock/templates/stock/item_base.html:166 #: templates/js/company.html:44 templates/js/order.html:217 msgid "Customer" msgstr "Kunde" @@ -1022,7 +1034,7 @@ msgstr "Zulieferer-Teile" #: company/templates/company/detail_part.html:13 #: order/templates/order/purchase_order_detail.html:67 -#: part/templates/part/stock.html:82 part/templates/part/supplier.html:12 +#: part/templates/part/stock.html:81 part/templates/part/supplier.html:12 msgid "New Supplier Part" msgstr "Neues Zulieferer-Teil" @@ -1036,7 +1048,7 @@ msgid "Delete Parts" msgstr "Teile löschen" #: company/templates/company/detail_part.html:43 -#: part/templates/part/stock.html:76 +#: part/templates/part/stock.html:75 msgid "New Part" msgstr "Neues Teil" @@ -1066,9 +1078,9 @@ msgstr "Neuen Hersteller anlegen" msgid "Supplier Stock" msgstr "Zuliefererbestand" -#: company/templates/company/detail_stock.html:34 +#: company/templates/company/detail_stock.html:35 #: company/templates/company/supplier_part_stock.html:33 -#: part/templates/part/stock.html:54 templates/stock_table.html:5 +#: part/templates/part/stock.html:53 templates/stock_table.html:5 msgid "Export" msgstr "Exportieren" @@ -1125,8 +1137,8 @@ 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:331 -#: stock/templates/stock/item_base.html:242 templates/js/company.html:150 +#: company/templates/company/supplier_part_base.html:19 stock/models.py:333 +#: stock/templates/stock/item_base.html:249 templates/js/company.html:150 msgid "Supplier Part" msgstr "Zulieferer-Teil" @@ -1209,12 +1221,12 @@ msgstr "Zuliefererbestand" #: company/templates/company/supplier_part_stock.html:56 #: order/templates/order/purchase_order_detail.html:38 #: order/templates/order/purchase_order_detail.html:118 -#: part/templates/part/stock.html:91 +#: part/templates/part/stock.html:90 msgid "New Location" msgstr "Neuer Standort" #: company/templates/company/supplier_part_stock.html:57 -#: part/templates/part/stock.html:92 +#: part/templates/part/stock.html:91 msgid "Create New Location" msgstr "Neuen Standort anlegen" @@ -1225,7 +1237,7 @@ msgstr "Bepreisung" #: company/templates/company/supplier_part_tabs.html:8 #: company/templates/company/tabs.html:12 part/templates/part/tabs.html:18 #: stock/templates/stock/location.html:12 templates/js/part.html:203 -#: templates/js/stock.html:451 templates/navbar.html:11 +#: templates/js/stock.html:448 templates/navbar.html:11 msgid "Stock" msgstr "Lagerbestand" @@ -1305,7 +1317,7 @@ msgstr "Firma gelöscht" msgid "Edit Supplier Part" msgstr "Zuliefererteil bearbeiten" -#: company/views.py:265 part/templates/part/stock.html:83 +#: company/views.py:265 part/templates/part/stock.html:82 msgid "Create new Supplier Part" msgstr "Neues Zuliefererteil anlegen" @@ -1325,6 +1337,26 @@ msgstr "Preisstaffel bearbeiten" msgid "Delete Price Break" msgstr "Preisstaffel löschen" +#: label/models.py:55 +#, fuzzy +#| msgid "Part name" +msgid "Label name" +msgstr "Name des Teils" + +#: label/models.py:58 +#, fuzzy +#| msgid "Part description" +msgid "Label description" +msgstr "Beschreibung des Teils" + +#: label/models.py:63 +msgid "Label template file" +msgstr "" + +#: label/models.py:69 +msgid "Query filters (comma-separated list of key=value pairs" +msgstr "" + #: order/forms.py:24 msgid "Place order" msgstr "Bestellung aufgeben" @@ -1379,7 +1411,7 @@ msgid "Supplier order reference code" msgstr "Bestellreferenz" #: order/models.py:185 order/models.py:259 part/views.py:1167 -#: stock/models.py:243 stock/models.py:665 stock/views.py:1243 +#: stock/models.py:238 stock/models.py:687 msgid "Quantity must be greater than zero" msgstr "Anzahl muss größer Null sein" @@ -1413,7 +1445,7 @@ msgstr "Position - Notizen" #: order/models.py:466 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:23 -#: stock/templates/stock/item_base.html:216 templates/js/order.html:136 +#: stock/templates/stock/item_base.html:223 templates/js/order.html:136 msgid "Purchase Order" msgstr "Kaufvertrag" @@ -1544,7 +1576,7 @@ msgid "Purchase Order Attachments" msgstr "Bestellanhänge" #: order/templates/order/po_tabs.html:8 order/templates/order/so_tabs.html:16 -#: part/templates/part/tabs.html:70 stock/templates/stock/tabs.html:32 +#: part/templates/part/tabs.html:61 stock/templates/stock/tabs.html:32 msgid "Attachments" msgstr "Anhänge" @@ -1560,7 +1592,7 @@ msgstr "Bestellpositionen" #: order/templates/order/purchase_order_detail.html:39 #: order/templates/order/purchase_order_detail.html:119 -#: stock/templates/stock/location.html:17 +#: stock/templates/stock/location.html:16 msgid "Create new stock location" msgstr "Neuen Lagerort anlegen" @@ -1599,7 +1631,7 @@ msgid "Select parts to receive against this order" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:131 templates/js/part.html:219 +#: part/templates/part/part_base.html:129 templates/js/part.html:219 msgid "On Order" msgstr "bestellt" @@ -1697,7 +1729,7 @@ msgstr "Bestellungspositionen" msgid "Add Purchase Order Attachment" msgstr "Bestellanhang hinzufügen" -#: order/views.py:102 order/views.py:149 part/views.py:85 stock/views.py:166 +#: order/views.py:102 order/views.py:149 part/views.py:85 stock/views.py:167 msgid "Added attachment" msgstr "Anhang hinzugefügt" @@ -1717,7 +1749,7 @@ msgstr "Anhang aktualisiert" msgid "Delete Attachment" msgstr "Anhang löschen" -#: order/views.py:222 order/views.py:236 stock/views.py:222 +#: order/views.py:222 order/views.py:236 stock/views.py:223 msgid "Deleted attachment" msgstr "Anhang gelöscht" @@ -1850,11 +1882,11 @@ msgstr "Fehler beim Lesen der Stückliste (ungültige Daten)" msgid "Error reading BOM file (incorrect row size)" msgstr "Fehler beim Lesen der Stückliste (ungültige Zeilengröße)" -#: part/forms.py:55 stock/forms.py:200 +#: part/forms.py:55 stock/forms.py:243 msgid "File Format" msgstr "Dateiformat" -#: part/forms.py:55 stock/forms.py:200 +#: part/forms.py:55 stock/forms.py:243 msgid "Select output file format" msgstr "Ausgabe-Dateiformat auswählen" @@ -1904,105 +1936,114 @@ msgstr "Standard-Standort für Teile dieser Kategorie" msgid "Default keywords for parts in this category" msgstr "Standard-Stichworte für Teile dieser Kategorie" -#: part/models.py:427 +#: part/models.py:74 part/templates/part/part_app_base.html:9 +msgid "Part Category" +msgstr "Teilkategorie" + +#: part/models.py:75 part/templates/part/category.html:13 +#: part/templates/part/category.html:78 templates/stats.html:12 +msgid "Part Categories" +msgstr "Teile-Kategorien" + +#: part/models.py:428 msgid "Part must be unique for name, IPN and revision" msgstr "Namen, Teile- und Revisionsnummern müssen eindeutig sein" -#: part/models.py:442 part/templates/part/detail.html:19 +#: part/models.py:443 part/templates/part/detail.html:19 msgid "Part name" msgstr "Name des Teils" -#: part/models.py:446 +#: part/models.py:447 msgid "Is this part a template part?" msgstr "Ist dieses Teil eine Vorlage?" -#: part/models.py:455 +#: part/models.py:456 msgid "Is this part a variant of another part?" msgstr "Ist dieses Teil eine Variante eines anderen Teils?" -#: part/models.py:457 +#: part/models.py:458 msgid "Part description" msgstr "Beschreibung des Teils" -#: part/models.py:459 +#: part/models.py:460 msgid "Part keywords to improve visibility in search results" msgstr "Schlüsselworte um die Sichtbarkeit in Suchergebnissen zu verbessern" -#: part/models.py:464 +#: part/models.py:465 msgid "Part category" msgstr "Teile-Kategorie" -#: part/models.py:466 +#: part/models.py:467 msgid "Internal Part Number" msgstr "Interne Teilenummer" -#: part/models.py:468 +#: part/models.py:469 msgid "Part revision or version number" msgstr "Revisions- oder Versionsnummer" -#: part/models.py:470 +#: part/models.py:471 msgid "Link to extenal URL" msgstr "Link zu einer Externen URL" -#: part/models.py:482 +#: part/models.py:483 msgid "Where is this item normally stored?" msgstr "Wo wird dieses Teil normalerweise gelagert?" -#: part/models.py:526 +#: part/models.py:527 msgid "Default supplier part" msgstr "Standard-Zulieferer?" -#: part/models.py:529 +#: part/models.py:530 msgid "Minimum allowed stock level" msgstr "Minimal zulässiger Lagerbestand" -#: part/models.py:531 +#: part/models.py:532 msgid "Stock keeping units for this part" msgstr "Stock Keeping Units (SKU) für dieses Teil" -#: part/models.py:533 +#: part/models.py:534 msgid "Can this part be built from other parts?" msgstr "Kann dieses Teil aus anderen Teilen angefertigt werden?" -#: part/models.py:535 +#: part/models.py:536 msgid "Can this part be used to build other parts?" msgstr "Kann dieses Teil zum Bau von anderen genutzt werden?" -#: part/models.py:537 +#: part/models.py:538 msgid "Does this part have tracking for unique items?" msgstr "Hat dieses Teil Tracking für einzelne Objekte?" -#: part/models.py:539 +#: part/models.py:540 msgid "Can this part be purchased from external suppliers?" msgstr "Kann dieses Teil von externen Zulieferern gekauft werden?" -#: part/models.py:541 +#: part/models.py:542 msgid "Can this part be sold to customers?" msgstr "Kann dieses Teil an Kunden verkauft werden?" -#: part/models.py:543 +#: part/models.py:544 msgid "Is this part active?" msgstr "Ist dieses Teil aktiv?" -#: part/models.py:545 +#: part/models.py:546 msgid "Is this a virtual part, such as a software product or license?" msgstr "Ist dieses Teil virtuell, wie zum Beispiel eine Software oder Lizenz?" -#: part/models.py:547 +#: part/models.py:548 msgid "Part notes - supports Markdown formatting" msgstr "Bemerkungen - unterstüzt Markdown-Formatierung" -#: part/models.py:549 +#: part/models.py:550 msgid "Stored BOM checksum" msgstr "Prüfsumme der Stückliste gespeichert" -#: part/models.py:1212 +#: part/models.py:1222 #, fuzzy #| msgid "Stock item cannot be created for a template Part" msgid "Test templates can only be created for trackable parts" msgstr "Lagerobjekt kann nicht für Vorlagen-Teile angelegt werden" -#: part/models.py:1229 +#: part/models.py:1239 #, fuzzy #| msgid "" #| "A stock item with this serial number already exists for template part " @@ -2012,121 +2053,127 @@ msgstr "" "Ein Teil mit dieser Seriennummer existiert bereits für die Teilevorlage " "{part}" -#: part/models.py:1248 templates/js/part.html:350 templates/js/stock.html:89 +#: part/models.py:1258 templates/js/part.html:350 templates/js/stock.html:90 #, fuzzy #| msgid "Instance Name" msgid "Test Name" msgstr "Instanzname" -#: part/models.py:1249 +#: part/models.py:1259 #, fuzzy #| msgid "Serial number for this item" msgid "Enter a name for the test" msgstr "Seriennummer für dieses Teil" -#: part/models.py:1254 +#: part/models.py:1264 #, fuzzy #| msgid "Description" msgid "Test Description" msgstr "Beschreibung" -#: part/models.py:1255 +#: part/models.py:1265 #, fuzzy #| msgid "Brief description of the build" msgid "Enter description for this test" msgstr "Kurze Beschreibung des Baus" -#: part/models.py:1261 +#: part/models.py:1271 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:1266 templates/js/part.html:367 +#: part/models.py:1276 templates/js/part.html:367 #, fuzzy #| msgid "Required Parts" msgid "Requires Value" msgstr "benötigte Teile" -#: part/models.py:1267 +#: part/models.py:1277 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:1272 templates/js/part.html:374 +#: part/models.py:1282 templates/js/part.html:374 #, fuzzy #| msgid "Delete Attachment" msgid "Requires Attachment" msgstr "Anhang löschen" -#: part/models.py:1273 +#: part/models.py:1283 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:1306 +#: part/models.py:1316 msgid "Parameter template name must be unique" msgstr "Vorlagen-Name des Parameters muss eindeutig sein" -#: part/models.py:1311 +#: part/models.py:1321 msgid "Parameter Name" msgstr "Name des Parameters" -#: part/models.py:1313 +#: part/models.py:1323 msgid "Parameter Units" msgstr "Parameter Einheit" -#: part/models.py:1339 +#: part/models.py:1349 msgid "Parent Part" msgstr "Ausgangsteil" -#: part/models.py:1341 +#: part/models.py:1351 msgid "Parameter Template" msgstr "Parameter Vorlage" -#: part/models.py:1343 +#: part/models.py:1353 msgid "Parameter Value" msgstr "Parameter Wert" -#: part/models.py:1372 +#: part/models.py:1382 msgid "Select parent part" msgstr "Ausgangsteil auswählen" -#: part/models.py:1380 +#: part/models.py:1390 msgid "Select part to be used in BOM" msgstr "Teil für die Nutzung in der Stückliste auswählen" -#: part/models.py:1386 +#: part/models.py:1396 msgid "BOM quantity for this BOM item" msgstr "Stücklisten-Anzahl für dieses Stücklisten-Teil" -#: part/models.py:1389 +#: part/models.py:1399 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "Geschätzter Ausschuss (absolut oder prozentual)" -#: part/models.py:1392 +#: part/models.py:1402 msgid "BOM item reference" msgstr "Referenz des Objekts auf der Stückliste" -#: part/models.py:1395 +#: part/models.py:1405 msgid "BOM item notes" msgstr "Notizen zum Stücklisten-Objekt" -#: part/models.py:1397 +#: part/models.py:1407 msgid "BOM line checksum" msgstr "Prüfsumme der Stückliste" -#: part/models.py:1461 stock/models.py:233 +#: part/models.py:1471 stock/models.py:228 #, fuzzy #| msgid "Overage must be an integer value or a percentage" msgid "Quantity must be integer value for trackable parts" msgstr "Überschuss muss eine Ganzzahl oder ein Prozentwert sein" -#: part/models.py:1470 +#: part/models.py:1480 msgid "Part cannot be added to its own Bill of Materials" msgstr "Teil kann nicht zu seiner eigenen Stückliste hinzugefügt werden" -#: part/models.py:1477 +#: part/models.py:1487 #, python-brace-format msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgstr "Teil '{p1}' wird in Stückliste für Teil '{p2}' benutzt (rekursiv)" +#: part/models.py:1494 +#, fuzzy +#| msgid "New BOM Item" +msgid "BOM Item" +msgstr "Neue Stücklistenposition" + #: part/templates/part/allocation.html:10 msgid "Part Stock Allocations" msgstr "Teilbestandszuordnungen" @@ -2142,14 +2189,14 @@ msgstr "Bestellung" #: part/templates/part/allocation.html:45 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:58 -#: stock/templates/stock/item_base.html:224 +#: stock/templates/stock/item_base.html:231 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106 -#: templates/js/stock.html:623 +#: templates/js/stock.html:643 msgid "Stock Item" msgstr "Lagerobjekt" #: part/templates/part/allocation.html:20 -#: stock/templates/stock/item_base.html:165 +#: stock/templates/stock/item_base.html:185 msgid "Build Order" msgstr "Bauauftrag" @@ -2189,11 +2236,6 @@ msgstr "Stückliste validieren" msgid "Export Bill of Materials" msgstr "Stückliste exportieren" -#: part/templates/part/category.html:13 part/templates/part/category.html:78 -#: templates/stats.html:12 -msgid "Part Categories" -msgstr "Teile-Kategorien" - #: part/templates/part/category.html:14 msgid "All parts" msgstr "Alle Teile" @@ -2230,7 +2272,7 @@ msgstr "Teile (inklusive Unter-Kategorien)" msgid "Part Details" msgstr "Teile-Details" -#: part/templates/part/detail.html:25 part/templates/part/part_base.html:81 +#: part/templates/part/detail.html:25 part/templates/part/part_base.html:79 msgid "IPN" msgstr "IPN (Interne Produktnummer)" @@ -2289,8 +2331,8 @@ msgstr "Teil ist virtuell (kein physisches Teil)" msgid "Part is not a virtual part" msgstr "Teil ist nicht virtuell" -#: part/templates/part/detail.html:139 stock/forms.py:194 -#: templates/js/table_filters.html:122 +#: part/templates/part/detail.html:139 stock/forms.py:237 +#: templates/js/table_filters.html:159 msgid "Template" msgstr "Vorlage" @@ -2306,7 +2348,7 @@ msgstr "Teil kann keine Vorlage sein wenn es Variante eines anderen Teils ist" msgid "Part is not a template part" msgstr "Teil ist nicht virtuell" -#: part/templates/part/detail.html:148 templates/js/table_filters.html:134 +#: part/templates/part/detail.html:148 templates/js/table_filters.html:171 msgid "Assembly" msgstr "Baugruppe" @@ -2318,7 +2360,7 @@ msgstr "Teil kann aus anderen Teilen angefertigt werden" msgid "Part cannot be assembled from other parts" msgstr "Teil kann nicht aus anderen Teilen angefertigt werden" -#: part/templates/part/detail.html:157 templates/js/table_filters.html:138 +#: part/templates/part/detail.html:157 templates/js/table_filters.html:175 msgid "Component" msgstr "Komponente" @@ -2330,7 +2372,7 @@ msgstr "Teil kann in Baugruppen benutzt werden" msgid "Part cannot be used in assemblies" msgstr "Teil kann nicht in Baugruppen benutzt werden" -#: part/templates/part/detail.html:166 templates/js/table_filters.html:150 +#: part/templates/part/detail.html:166 templates/js/table_filters.html:187 msgid "Trackable" msgstr "nachverfolgbar" @@ -2350,7 +2392,7 @@ msgstr "Kaufbar" msgid "Part can be purchased from external suppliers" msgstr "Teil kann von externen Zulieferern gekauft werden" -#: part/templates/part/detail.html:184 templates/js/table_filters.html:146 +#: part/templates/part/detail.html:184 templates/js/table_filters.html:183 msgid "Salable" msgstr "Verkäuflich" @@ -2362,7 +2404,7 @@ msgstr "Teil kann an Kunden verkauft werden" msgid "Part cannot be sold to customers" msgstr "Teil kann nicht an Kunden verkauft werden" -#: part/templates/part/detail.html:193 templates/js/table_filters.html:117 +#: part/templates/part/detail.html:193 templates/js/table_filters.html:154 msgid "Active" msgstr "Aktiv" @@ -2398,8 +2440,8 @@ msgstr "Parameter hinzufügen" msgid "New Parameter" msgstr "Neuer Parameter" -#: part/templates/part/params.html:21 stock/models.py:1252 -#: templates/js/stock.html:109 +#: part/templates/part/params.html:21 stock/models.py:1274 +#: templates/js/stock.html:110 msgid "Value" msgstr "Wert" @@ -2411,10 +2453,6 @@ msgstr "Bearbeiten" msgid "Delete" msgstr "Löschen" -#: part/templates/part/part_app_base.html:9 -msgid "Part Category" -msgstr "Teilkategorie" - #: part/templates/part/part_app_base.html:11 msgid "Part List" msgstr "Teileliste" @@ -2438,35 +2476,81 @@ msgstr "Dieses Teil ist eine Variante von" msgid "Inactive" msgstr "Inaktiv" -#: part/templates/part/part_base.html:41 +#: part/templates/part/part_base.html:39 msgid "Star this part" msgstr "Teil favorisieren" +#: part/templates/part/part_base.html:44 +#: stock/templates/stock/item_base.html:78 +#: stock/templates/stock/location.html:22 +#, fuzzy +#| msgid "Source Location" +msgid "Barcode actions" +msgstr "Quell-Standort" + +#: part/templates/part/part_base.html:46 +#: stock/templates/stock/item_base.html:80 +#: stock/templates/stock/location.html:24 +#, fuzzy +#| msgid "Part QR Code" +msgid "Show QR Code" +msgstr "Teil-QR-Code" + #: part/templates/part/part_base.html:47 +#: stock/templates/stock/item_base.html:81 +#: stock/templates/stock/location.html:25 +msgid "Print Label" +msgstr "" + +#: part/templates/part/part_base.html:51 msgid "Show pricing information" msgstr "Kosteninformationen ansehen" -#: part/templates/part/part_base.html:104 +#: part/templates/part/part_base.html:64 +#, fuzzy +#| msgid "Source Location" +msgid "Part actions" +msgstr "Quell-Standort" + +#: part/templates/part/part_base.html:66 +#, fuzzy +#| msgid "Duplicate Part" +msgid "Duplicate part" +msgstr "Teil duplizieren" + +#: part/templates/part/part_base.html:67 +#, fuzzy +#| msgid "Edit Template" +msgid "Edit part" +msgstr "Vorlage bearbeiten" + +#: part/templates/part/part_base.html:69 +#, fuzzy +#| msgid "Delete Parts" +msgid "Delete part" +msgstr "Teile löschen" + +#: part/templates/part/part_base.html:102 msgid "Available Stock" msgstr "Verfügbarer Lagerbestand" -#: part/templates/part/part_base.html:110 +#: part/templates/part/part_base.html:108 templates/js/table_filters.html:57 msgid "In Stock" msgstr "Auf Lager" -#: part/templates/part/part_base.html:117 +#: part/templates/part/part_base.html:115 msgid "Allocated to Build Orders" msgstr "Zu Bauaufträgen zugeordnet" -#: part/templates/part/part_base.html:124 +#: part/templates/part/part_base.html:122 msgid "Allocated to Sales Orders" msgstr "Zu Aufträgen zugeordnet" -#: part/templates/part/part_base.html:146 +#: part/templates/part/part_base.html:144 msgid "Can Build" msgstr "Herstellbar?" -#: part/templates/part/part_base.html:152 +#: part/templates/part/part_base.html:150 msgid "Underway" msgstr "unterwegs" @@ -2510,7 +2594,7 @@ msgstr "Teil entfernen" msgid "Part Stock" msgstr "Teilbestand" -#: part/templates/part/stock.html:77 +#: part/templates/part/stock.html:76 msgid "Create New Part" msgstr "Neues Teil anlegen" @@ -2563,11 +2647,7 @@ msgstr "Stückliste" msgid "Used In" msgstr "Benutzt in" -#: part/templates/part/tabs.html:57 stock/templates/stock/tabs.html:6 -msgid "Tracking" -msgstr "Tracking" - -#: part/templates/part/tabs.html:64 stock/templates/stock/item_base.html:268 +#: part/templates/part/tabs.html:55 stock/templates/stock/item_base.html:275 msgid "Tests" msgstr "" @@ -2796,240 +2876,252 @@ msgstr "" msgid "Asset file description" msgstr "Einstellungs-Beschreibung" -#: stock/forms.py:194 +#: stock/forms.py:185 +msgid "Label" +msgstr "" + +#: stock/forms.py:186 stock/forms.py:237 #, fuzzy #| msgid "Select stock item to allocate" msgid "Select test report template" msgstr "Lagerobjekt für Zuordnung auswählen" -#: stock/forms.py:202 +#: stock/forms.py:245 msgid "Include stock items in sub locations" msgstr "Lagerobjekte in untergeordneten Lagerorten einschließen" -#: stock/forms.py:235 +#: stock/forms.py:278 msgid "Destination stock location" msgstr "Ziel-Lagerbestand" -#: stock/forms.py:241 +#: stock/forms.py:284 msgid "Confirm movement of stock items" msgstr "Bewegung der Lagerobjekte bestätigen" -#: stock/forms.py:243 +#: stock/forms.py:286 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:208 +#: stock/models.py:209 #, 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:250 +#: stock/models.py:245 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "Teile-Typ ('{pf}') muss {pe} sein" -#: stock/models.py:260 stock/models.py:269 +#: stock/models.py:255 stock/models.py:264 msgid "Quantity must be 1 for item with a serial number" msgstr "Anzahl muss für Objekte mit Seriennummer \"1\" sein" -#: stock/models.py:261 +#: stock/models.py:256 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:282 +#: stock/models.py:277 msgid "Item cannot belong to itself" msgstr "Teil kann nicht zu sich selbst gehören" -#: stock/models.py:314 +#: stock/models.py:316 msgid "Parent Stock Item" msgstr "Eltern-Lagerobjekt" -#: stock/models.py:322 stock/templates/stock/item_base.html:138 -msgid "Base Part" -msgstr "Basisteil" - -#: stock/models.py:323 +#: stock/models.py:325 msgid "Base part" msgstr "Basis-Teil" -#: stock/models.py:332 +#: stock/models.py:334 msgid "Select a matching supplier part for this stock item" msgstr "Passenden Zulieferer für dieses Lagerobjekt auswählen" -#: stock/models.py:337 stock/templates/stock/stock_app_base.html:7 +#: stock/models.py:339 stock/templates/stock/stock_app_base.html:7 msgid "Stock Location" msgstr "Lagerort" -#: stock/models.py:340 +#: stock/models.py:342 msgid "Where is this stock item located?" msgstr "Wo wird dieses Teil normalerweise gelagert?" -#: stock/models.py:345 +#: stock/models.py:347 msgid "Installed In" msgstr "Installiert in" -#: stock/models.py:348 +#: stock/models.py:350 msgid "Is this item installed in another item?" msgstr "Ist dieses Teil in einem anderen verbaut?" -#: stock/models.py:364 +#: stock/models.py:366 msgid "Serial number for this item" msgstr "Seriennummer für dieses Teil" -#: stock/models.py:376 +#: stock/models.py:378 msgid "Batch code for this stock item" msgstr "Losnummer für dieses Lagerobjekt" -#: stock/models.py:380 +#: stock/models.py:382 msgid "Stock Quantity" msgstr "Bestand" -#: stock/models.py:389 +#: stock/models.py:391 msgid "Source Build" msgstr "Quellbau" -#: stock/models.py:391 +#: stock/models.py:393 msgid "Build for this stock item" msgstr "Bau für dieses Lagerobjekt" -#: stock/models.py:398 +#: stock/models.py:400 msgid "Source Purchase Order" msgstr "Quellbestellung" -#: stock/models.py:401 +#: stock/models.py:403 msgid "Purchase order for this stock item" msgstr "Bestellung für dieses Teil" -#: stock/models.py:407 +#: stock/models.py:409 msgid "Destination Sales Order" msgstr "Zielauftrag" -#: stock/models.py:414 +#: stock/models.py:416 msgid "Destination Build Order" msgstr "Zielbauauftrag" -#: stock/models.py:427 +#: stock/models.py:429 msgid "Delete this Stock Item when stock is depleted" msgstr "Objekt löschen wenn Lagerbestand aufgebraucht" -#: stock/models.py:437 stock/templates/stock/item_notes.html:14 +#: stock/models.py:439 stock/templates/stock/item_notes.html:14 #: stock/templates/stock/item_notes.html:30 msgid "Stock Item Notes" msgstr "Lagerobjekt-Notizen" -#: stock/models.py:489 +#: stock/models.py:490 #, fuzzy #| msgid "Item assigned to customer?" msgid "Assigned to Customer" msgstr "Ist dieses Objekt einem Kunden zugeteilt?" -#: stock/models.py:491 +#: stock/models.py:492 #, fuzzy #| msgid "Item assigned to customer?" msgid "Manually assigned to customer" msgstr "Ist dieses Objekt einem Kunden zugeteilt?" -#: stock/models.py:656 +#: stock/models.py:505 +#, fuzzy +#| msgid "Item assigned to customer?" +msgid "Returned from customer" +msgstr "Ist dieses Objekt einem Kunden zugeteilt?" + +#: stock/models.py:507 +#, fuzzy +#| msgid "Create new stock location" +msgid "Returned to location" +msgstr "Neuen Lagerort anlegen" + +#: stock/models.py:678 #, fuzzy #| msgid "Part is not a virtual part" msgid "Part is not set as trackable" msgstr "Teil ist nicht virtuell" -#: stock/models.py:662 +#: stock/models.py:684 msgid "Quantity must be integer" msgstr "Anzahl muss eine Ganzzahl sein" -#: stock/models.py:668 +#: stock/models.py:690 #, 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:671 stock/models.py:674 +#: stock/models.py:693 stock/models.py:696 msgid "Serial numbers must be a list of integers" msgstr "Seriennummern muss eine Liste von Ganzzahlen sein" -#: stock/models.py:677 +#: stock/models.py:699 msgid "Quantity does not match serial numbers" msgstr "Anzahl stimmt nicht mit den Seriennummern überein" -#: stock/models.py:687 +#: stock/models.py:709 msgid "Serial numbers already exist: " msgstr "Seriennummern existieren bereits:" -#: stock/models.py:712 +#: stock/models.py:734 msgid "Add serial number" msgstr "Seriennummer hinzufügen" -#: stock/models.py:715 +#: stock/models.py:737 #, python-brace-format msgid "Serialized {n} items" msgstr "{n} Teile serialisiert" -#: stock/models.py:826 +#: stock/models.py:848 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:1153 +#: stock/models.py:1175 msgid "Tracking entry title" msgstr "Name des Eintrags-Trackings" -#: stock/models.py:1155 +#: stock/models.py:1177 msgid "Entry notes" msgstr "Eintrags-Notizen" -#: stock/models.py:1157 +#: stock/models.py:1179 msgid "Link to external page for further information" msgstr "Link auf externe Seite für weitere Informationen" -#: stock/models.py:1217 +#: stock/models.py:1239 #, fuzzy #| msgid "Serial number for this item" msgid "Value must be provided for this test" msgstr "Seriennummer für dieses Teil" -#: stock/models.py:1223 +#: stock/models.py:1245 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1240 +#: stock/models.py:1262 msgid "Test" msgstr "" -#: stock/models.py:1241 +#: stock/models.py:1263 #, fuzzy #| msgid "Part name" msgid "Test name" msgstr "Name des Teils" -#: stock/models.py:1246 +#: stock/models.py:1268 #, fuzzy #| msgid "Search Results" msgid "Result" msgstr "Suchergebnisse" -#: stock/models.py:1247 templates/js/table_filters.html:53 +#: stock/models.py:1269 templates/js/table_filters.html:90 msgid "Test result" msgstr "" -#: stock/models.py:1253 +#: stock/models.py:1275 msgid "Test output value" msgstr "" -#: stock/models.py:1259 +#: stock/models.py:1281 #, fuzzy #| msgid "Attachments" msgid "Attachment" msgstr "Anhänge" -#: stock/models.py:1260 +#: stock/models.py:1282 #, fuzzy #| msgid "Delete attachment" msgid "Test result attachment" msgstr "Anhang löschen" -#: stock/models.py:1266 +#: stock/models.py:1288 #, fuzzy #| msgid "Edit notes" msgid "Test notes" @@ -3078,24 +3170,8 @@ msgstr "" "Dieses Lagerobjekt wird automatisch gelöscht wenn der Lagerbestand " "aufgebraucht ist." -#: stock/templates/stock/item_base.html:78 -#, fuzzy -#| msgid "Source Location" -msgid "Barcode actions" -msgstr "Quell-Standort" - -#: stock/templates/stock/item_base.html:80 -#, fuzzy -#| msgid "Part QR Code" -msgid "Show QR Code" -msgstr "Teil-QR-Code" - -#: stock/templates/stock/item_base.html:81 -msgid "Print Label" -msgstr "" - -#: stock/templates/stock/item_base.html:83 templates/js/barcode.html:263 -#: templates/js/barcode.html:268 +#: stock/templates/stock/item_base.html:83 templates/js/barcode.html:283 +#: templates/js/barcode.html:288 msgid "Unlink Barcode" msgstr "" @@ -3103,13 +3179,14 @@ msgstr "" msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:92 +#: stock/templates/stock/item_base.html:91 #, fuzzy #| msgid "Confirm stock adjustment" msgid "Stock adjustment actions" msgstr "Bestands-Anpassung bestätigen" -#: stock/templates/stock/item_base.html:95 templates/stock_table.html:14 +#: stock/templates/stock/item_base.html:95 +#: stock/templates/stock/location.html:33 templates/stock_table.html:14 msgid "Count stock" msgstr "Bestand zählen" @@ -3127,83 +3204,94 @@ msgstr "Bestand entfernen" msgid "Transfer stock" msgstr "Bestand bestellen" -#: stock/templates/stock/item_base.html:105 -#, fuzzy -#| msgid "Stock Locations" -msgid "Stock actions" -msgstr "Lagerobjekt-Standorte" - -#: stock/templates/stock/item_base.html:108 +#: stock/templates/stock/item_base.html:101 #, fuzzy #| msgid "Serialize Stock" msgid "Serialize stock" msgstr "Lagerbestand erfassen" -#: stock/templates/stock/item_base.html:111 +#: stock/templates/stock/item_base.html:105 #, fuzzy #| msgid "Item assigned to customer?" msgid "Assign to customer" msgstr "Ist dieses Objekt einem Kunden zugeteilt?" +#: stock/templates/stock/item_base.html:108 +#, fuzzy +#| msgid "Count stock" +msgid "Return to stock" +msgstr "Bestand zählen" + #: stock/templates/stock/item_base.html:114 +#: stock/templates/stock/location.html:30 +#, fuzzy +#| msgid "Stock Locations" +msgid "Stock actions" +msgstr "Lagerobjekt-Standorte" + +#: stock/templates/stock/item_base.html:118 #, fuzzy #| msgid "Count stock items" msgid "Convert to variant" msgstr "Lagerobjekte zählen" -#: stock/templates/stock/item_base.html:116 +#: stock/templates/stock/item_base.html:120 #, fuzzy #| msgid "Count stock items" msgid "Duplicate stock item" msgstr "Lagerobjekte zählen" -#: stock/templates/stock/item_base.html:117 +#: stock/templates/stock/item_base.html:121 #, fuzzy #| msgid "Edit Stock Item" msgid "Edit stock item" msgstr "Lagerobjekt bearbeiten" -#: stock/templates/stock/item_base.html:119 +#: stock/templates/stock/item_base.html:123 #, fuzzy #| msgid "Delete Stock Item" msgid "Delete stock item" msgstr "Lagerobjekt löschen" -#: stock/templates/stock/item_base.html:124 +#: stock/templates/stock/item_base.html:128 msgid "Generate test report" msgstr "" -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:132 +msgid "Print labels" +msgstr "" + +#: stock/templates/stock/item_base.html:140 msgid "Stock Item Details" msgstr "Lagerbestands-Details" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:173 msgid "Belongs To" msgstr "Gehört zu" -#: stock/templates/stock/item_base.html:175 +#: stock/templates/stock/item_base.html:195 #, fuzzy #| msgid "No stock location set" msgid "No location set" msgstr "Kein Lagerort gesetzt" -#: stock/templates/stock/item_base.html:182 +#: stock/templates/stock/item_base.html:202 msgid "Unique Identifier" msgstr "Eindeutiger Bezeichner" -#: stock/templates/stock/item_base.html:223 +#: stock/templates/stock/item_base.html:230 msgid "Parent Item" msgstr "Elternposition" -#: stock/templates/stock/item_base.html:248 +#: stock/templates/stock/item_base.html:255 msgid "Last Updated" msgstr "Zuletzt aktualisiert" -#: stock/templates/stock/item_base.html:253 +#: stock/templates/stock/item_base.html:260 msgid "Last Stocktake" msgstr "Letzte Inventur" -#: stock/templates/stock/item_base.html:257 +#: stock/templates/stock/item_base.html:264 msgid "No stocktake performed" msgstr "Keine Inventur ausgeführt" @@ -3215,6 +3303,12 @@ msgstr "Kind-Lagerobjekte" msgid "This stock item does not have any child items" msgstr "Dieses Lagerobjekt hat keine Kinder" +#: stock/templates/stock/item_delete.html:9 +#, fuzzy +#| msgid "Are you sure you want to delete this attachment?" +msgid "Are you sure you want to delete this stock item?" +msgstr "Sind Sie sicher, dass Sie diesen Anhang löschen wollen?" + #: stock/templates/stock/item_tests.html:10 stock/templates/stock/tabs.html:13 msgid "Test Data" msgstr "" @@ -3237,50 +3331,78 @@ msgstr "" msgid "All stock items" msgstr "Alle Lagerobjekte" -#: stock/templates/stock/location.html:22 -msgid "Count stock items" -msgstr "Lagerobjekte zählen" - -#: stock/templates/stock/location.html:25 -msgid "Edit stock location" -msgstr "Lagerort bearbeiten" - -#: stock/templates/stock/location.html:28 -msgid "Delete stock location" -msgstr "Lagerort löschen" +#: stock/templates/stock/location.html:26 +#, fuzzy +#| msgid "Child Stock Items" +msgid "Check-in Items" +msgstr "Kind-Lagerobjekte" #: stock/templates/stock/location.html:37 +#, fuzzy +#| msgid "Location Description" +msgid "Location actions" +msgstr "Standort-Beschreibung" + +#: stock/templates/stock/location.html:39 +#, fuzzy +#| msgid "Edit stock location" +msgid "Edit location" +msgstr "Lagerort bearbeiten" + +#: stock/templates/stock/location.html:40 +#, fuzzy +#| msgid "Delete stock location" +msgid "Delete location" +msgstr "Lagerort löschen" + +#: stock/templates/stock/location.html:48 msgid "Location Details" msgstr "Standort-Details" -#: stock/templates/stock/location.html:42 +#: stock/templates/stock/location.html:53 msgid "Location Path" msgstr "Standord-Pfad" -#: stock/templates/stock/location.html:47 +#: stock/templates/stock/location.html:58 msgid "Location Description" msgstr "Standort-Beschreibung" -#: stock/templates/stock/location.html:52 +#: stock/templates/stock/location.html:63 msgid "Sublocations" msgstr "Sub-Standorte" -#: stock/templates/stock/location.html:57 -#: stock/templates/stock/location.html:72 templates/stats.html:21 +#: stock/templates/stock/location.html:68 +#: stock/templates/stock/location.html:83 templates/stats.html:21 #: templates/stats.html:30 msgid "Stock Items" msgstr "Lagerobjekte" -#: stock/templates/stock/location.html:62 +#: stock/templates/stock/location.html:73 msgid "Stock Details" msgstr "Objekt-Details" -#: stock/templates/stock/location.html:67 +#: stock/templates/stock/location.html:78 #: templates/InvenTree/search_stock_location.html:6 templates/stats.html:25 msgid "Stock Locations" msgstr "Lagerobjekt-Standorte" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:934 +#: stock/templates/stock/location_delete.html:7 +#, fuzzy +#| msgid "Are you sure you want to delete this attachment?" +msgid "Are you sure you want to delete this stock location?" +msgstr "Sind Sie sicher, dass Sie diesen Anhang löschen wollen?" + +#: stock/templates/stock/stock_adjust.html:35 +#, fuzzy +#| msgid "" +#| "This stock item is serialized - it has a unique serial number and the " +#| "quantity cannot be adjusted." +msgid "Stock item is serialized and quantity cannot be adjusted" +msgstr "" +"Dieses Lagerobjekt ist serialisiert. Es hat eine eindeutige Seriennummer und " +"die Anzahl kann nicht angepasst werden." + +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1052 #, fuzzy #| msgid "Count Stock Items" msgid "Convert Stock Item" @@ -3300,6 +3422,10 @@ msgstr "" msgid "This action cannot be easily undone" msgstr "" +#: stock/templates/stock/tabs.html:6 +msgid "Tracking" +msgstr "Tracking" + #: stock/templates/stock/tabs.html:21 msgid "Builds" msgstr "Baue" @@ -3308,33 +3434,33 @@ msgstr "Baue" msgid "Children" msgstr "Kinder" -#: stock/views.py:113 +#: stock/views.py:114 msgid "Edit Stock Location" msgstr "Lagerobjekt-Standort bearbeiten" -#: stock/views.py:137 +#: stock/views.py:138 msgid "Stock Location QR code" msgstr "QR-Code für diesen Standort" -#: stock/views.py:155 +#: stock/views.py:156 #, fuzzy #| msgid "Add Attachment" msgid "Add Stock Item Attachment" msgstr "Anhang hinzufügen" -#: stock/views.py:200 +#: stock/views.py:201 #, fuzzy #| msgid "Edit Stock Item" msgid "Edit Stock Item Attachment" msgstr "Lagerobjekt bearbeiten" -#: stock/views.py:216 +#: stock/views.py:217 #, fuzzy #| msgid "Delete Part Attachment" msgid "Delete Stock Item Attachment" msgstr "Teilanhang löschen" -#: stock/views.py:232 +#: stock/views.py:233 #, fuzzy #| msgid "Item assigned to customer?" msgid "Assign to Customer" @@ -3342,178 +3468,212 @@ msgstr "Ist dieses Objekt einem Kunden zugeteilt?" #: stock/views.py:270 #, fuzzy +#| msgid "Part Stock" +msgid "Return to Stock" +msgstr "Teilbestand" + +#: stock/views.py:289 +#, fuzzy +#| msgid "Include sublocations" +msgid "Specify a valid location" +msgstr "Unterlagerorte einschließen" + +#: stock/views.py:293 +msgid "Stock item returned from customer" +msgstr "" + +#: stock/views.py:305 +#, fuzzy +#| msgid "Select valid part" +msgid "Select Label Template" +msgstr "Bitte ein gültiges Teil auswählen" + +#: stock/views.py:326 +#, fuzzy +#| msgid "Select valid part" +msgid "Select valid label" +msgstr "Bitte ein gültiges Teil auswählen" + +#: stock/views.py:388 +#, fuzzy #| msgid "Delete Template" msgid "Delete All Test Data" msgstr "Vorlage löschen" -#: stock/views.py:285 +#: stock/views.py:403 #, fuzzy #| msgid "Confirm Part Deletion" msgid "Confirm test data deletion" msgstr "Löschen des Teils bestätigen" -#: stock/views.py:305 +#: stock/views.py:423 msgid "Add Test Result" msgstr "" -#: stock/views.py:342 +#: stock/views.py:460 #, fuzzy #| msgid "Edit Template" msgid "Edit Test Result" msgstr "Vorlage bearbeiten" -#: stock/views.py:359 +#: stock/views.py:477 #, fuzzy #| msgid "Delete Template" msgid "Delete Test Result" msgstr "Vorlage löschen" -#: stock/views.py:370 +#: stock/views.py:488 #, fuzzy #| msgid "Delete Template" msgid "Select Test Report Template" msgstr "Vorlage löschen" -#: stock/views.py:384 +#: stock/views.py:502 #, fuzzy #| msgid "Select valid part" msgid "Select valid template" msgstr "Bitte ein gültiges Teil auswählen" -#: stock/views.py:436 +#: stock/views.py:554 msgid "Stock Export Options" msgstr "Lagerbestandsexportoptionen" -#: stock/views.py:556 +#: stock/views.py:674 msgid "Stock Item QR Code" msgstr "Lagerobjekt-QR-Code" -#: stock/views.py:579 +#: stock/views.py:697 msgid "Adjust Stock" msgstr "Lagerbestand anpassen" -#: stock/views.py:688 +#: stock/views.py:806 msgid "Move Stock Items" msgstr "Lagerobjekte bewegen" -#: stock/views.py:689 +#: stock/views.py:807 msgid "Count Stock Items" msgstr "Lagerobjekte zählen" -#: stock/views.py:690 +#: stock/views.py:808 msgid "Remove From Stock" msgstr "Aus Lagerbestand entfernen" -#: stock/views.py:691 +#: stock/views.py:809 msgid "Add Stock Items" msgstr "Lagerobjekte hinzufügen" -#: stock/views.py:692 +#: stock/views.py:810 msgid "Delete Stock Items" msgstr "Lagerobjekte löschen" -#: stock/views.py:720 +#: stock/views.py:838 msgid "Must enter integer value" msgstr "Nur Ganzzahl eingeben" -#: stock/views.py:725 +#: stock/views.py:843 msgid "Quantity must be positive" msgstr "Anzahl muss positiv sein" -#: stock/views.py:732 +#: stock/views.py:850 #, python-brace-format msgid "Quantity must not exceed {x}" msgstr "Anzahl darf {x} nicht überschreiten" -#: stock/views.py:740 +#: stock/views.py:858 msgid "Confirm stock adjustment" msgstr "Bestands-Anpassung bestätigen" -#: stock/views.py:811 +#: stock/views.py:929 #, python-brace-format msgid "Added stock to {n} items" msgstr "Vorrat zu {n} Lagerobjekten hinzugefügt" -#: stock/views.py:826 +#: stock/views.py:944 #, python-brace-format msgid "Removed stock from {n} items" msgstr "Vorrat von {n} Lagerobjekten entfernt" -#: stock/views.py:839 +#: stock/views.py:957 #, python-brace-format msgid "Counted stock for {n} items" msgstr "Bestand für {n} Objekte erfasst" -#: stock/views.py:867 +#: stock/views.py:985 msgid "No items were moved" msgstr "Keine Lagerobjekte wurden bewegt" -#: stock/views.py:870 +#: stock/views.py:988 #, python-brace-format msgid "Moved {n} items to {dest}" msgstr "{n} Teile nach {dest} bewegt" -#: stock/views.py:889 +#: stock/views.py:1007 #, python-brace-format msgid "Deleted {n} stock items" msgstr "{n} Teile im Lager gelöscht" -#: stock/views.py:901 +#: stock/views.py:1019 msgid "Edit Stock Item" msgstr "Lagerobjekt bearbeiten" -#: stock/views.py:961 +#: stock/views.py:1079 msgid "Create new Stock Location" msgstr "Neuen Lager-Standort erstellen" -#: stock/views.py:982 +#: stock/views.py:1100 msgid "Serialize Stock" msgstr "Lagerbestand erfassen" -#: stock/views.py:1074 +#: stock/views.py:1192 msgid "Create new Stock Item" msgstr "Neues Lagerobjekt hinzufügen" -#: stock/views.py:1167 +#: stock/views.py:1285 #, fuzzy #| msgid "Count stock items" msgid "Duplicate Stock Item" msgstr "Lagerobjekte zählen" -#: stock/views.py:1240 +#: stock/views.py:1358 msgid "Invalid quantity" msgstr "Ungültige Menge" -#: stock/views.py:1247 +#: stock/views.py:1361 +#, fuzzy +#| msgid "Quantity must be greater than zero" +msgid "Quantity cannot be less than zero" +msgstr "Anzahl muss größer Null sein" + +#: stock/views.py:1365 msgid "Invalid part selection" msgstr "Ungültige Teileauswahl" -#: stock/views.py:1296 +#: stock/views.py:1414 #, python-brace-format msgid "Created {n} new stock items" msgstr "{n} neue Lagerobjekte erstellt" -#: stock/views.py:1315 stock/views.py:1331 +#: stock/views.py:1433 stock/views.py:1449 msgid "Created new stock item" msgstr "Neues Lagerobjekt erstellt" -#: stock/views.py:1350 +#: stock/views.py:1468 msgid "Delete Stock Location" msgstr "Standort löschen" -#: stock/views.py:1363 +#: stock/views.py:1481 msgid "Delete Stock Item" msgstr "Lagerobjekt löschen" -#: stock/views.py:1374 +#: stock/views.py:1492 msgid "Delete Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag löschen" -#: stock/views.py:1391 +#: stock/views.py:1509 msgid "Edit Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag bearbeiten" -#: stock/views.py:1400 +#: stock/views.py:1518 msgid "Add Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag hinzufügen" @@ -3603,49 +3763,109 @@ msgstr "" msgid "Delete attachment" msgstr "Anhang löschen" -#: templates/js/barcode.html:28 +#: templates/js/barcode.html:8 #, fuzzy #| msgid "No barcode data provided" msgid "Scan barcode data here using wedge scanner" msgstr "Keine Strichcodedaten bereitgestellt" -#: templates/js/barcode.html:34 +#: templates/js/barcode.html:12 #, fuzzy #| msgid "Source Location" msgid "Barcode" msgstr "Quell-Standort" -#: templates/js/barcode.html:42 +#: templates/js/barcode.html:20 #, fuzzy #| msgid "No barcode data provided" msgid "Enter barcode data" msgstr "Keine Strichcodedaten bereitgestellt" -#: templates/js/barcode.html:140 +#: templates/js/barcode.html:42 +msgid "Invalid server response" +msgstr "" + +#: templates/js/barcode.html:143 #, fuzzy #| msgid "No barcode data provided" msgid "Scan barcode data below" msgstr "Keine Strichcodedaten bereitgestellt" -#: templates/js/barcode.html:195 templates/js/barcode.html:243 +#: templates/js/barcode.html:217 templates/js/barcode.html:263 #, fuzzy #| msgid "Unknown barcode format" msgid "Unknown response from server" msgstr "Unbekanntes Strichcode-Format" -#: templates/js/barcode.html:198 templates/js/barcode.html:247 -msgid "Invalid server response" -msgstr "" +#: templates/js/barcode.html:239 +#, fuzzy +#| msgid "Parent Stock Item" +msgid "Link Barcode to Stock Item" +msgstr "Eltern-Lagerobjekt" -#: templates/js/barcode.html:265 +#: templates/js/barcode.html:285 msgid "" "This will remove the association between this stock item and the barcode" msgstr "" -#: templates/js/barcode.html:271 +#: templates/js/barcode.html:291 msgid "Unlink" msgstr "" +#: templates/js/barcode.html:350 +#, fuzzy +#| msgid "Remove stock" +msgid "Remove stock item" +msgstr "Bestand entfernen" + +#: templates/js/barcode.html:397 +#, fuzzy +#| msgid "Entry notes" +msgid "Enter notes" +msgstr "Eintrags-Notizen" + +#: templates/js/barcode.html:399 +msgid "Enter optional notes for stock transfer" +msgstr "" + +#: templates/js/barcode.html:404 +#, fuzzy +#| msgid "Include stock items in sub locations" +msgid "Check Stock Items into Location" +msgstr "Lagerobjekte in untergeordneten Lagerorten einschließen" + +#: templates/js/barcode.html:408 +msgid "Check In" +msgstr "" + +#: templates/js/barcode.html:466 +msgid "Server error" +msgstr "" + +#: templates/js/barcode.html:485 +#, fuzzy +#| msgid "Stock Item Details" +msgid "Stock Item already scanned" +msgstr "Lagerbestands-Details" + +#: templates/js/barcode.html:489 +#, fuzzy +#| msgid "Include stock items in sub locations" +msgid "Stock Item already in this location" +msgstr "Lagerobjekte in untergeordneten Lagerorten einschließen" + +#: templates/js/barcode.html:496 +#, fuzzy +#| msgid "Added stock to {n} items" +msgid "Added stock item" +msgstr "Vorrat zu {n} Lagerobjekten hinzugefügt" + +#: templates/js/barcode.html:503 +#, fuzzy +#| msgid "Create new Stock Item" +msgid "Barcode does not match Stock Item" +msgstr "Neues Lagerobjekt hinzufügen" + #: templates/js/bom.html:143 msgid "Open subassembly" msgstr "Unterbaugruppe öffnen" @@ -3706,7 +3926,7 @@ msgstr "Link" msgid "No purchase orders found" msgstr "Keine Bestellungen gefunden" -#: templates/js/order.html:170 templates/js/stock.html:605 +#: templates/js/order.html:170 templates/js/stock.html:625 msgid "Date" msgstr "Datum" @@ -3718,7 +3938,7 @@ msgstr "Keine Aufträge gefunden" msgid "Shipment Date" msgstr "Versanddatum" -#: templates/js/part.html:106 templates/js/stock.html:403 +#: templates/js/part.html:106 templates/js/stock.html:406 msgid "Select" msgstr "Auswählen" @@ -3734,7 +3954,7 @@ msgstr "Verkäufliches Teil" msgid "No category" msgstr "Keine Kategorie" -#: templates/js/part.html:214 templates/js/table_filters.html:130 +#: templates/js/part.html:214 templates/js/table_filters.html:167 msgid "Low stock" msgstr "Bestand niedrig" @@ -3760,13 +3980,13 @@ msgstr "" msgid "No test templates matching query" msgstr "Keine zur Anfrage passenden Lagerobjekte" -#: templates/js/part.html:387 templates/js/stock.html:62 +#: templates/js/part.html:387 templates/js/stock.html:63 #, fuzzy #| msgid "Edit Sales Order" msgid "Edit test result" msgstr "Auftrag bearbeiten" -#: templates/js/part.html:388 templates/js/stock.html:63 +#: templates/js/part.html:388 templates/js/stock.html:64 #, fuzzy #| msgid "Delete attachment" msgid "Delete test result" @@ -3776,149 +3996,215 @@ msgstr "Anhang löschen" msgid "This test is defined for a parent part" msgstr "" -#: templates/js/stock.html:25 +#: templates/js/stock.html:26 msgid "PASS" msgstr "" -#: templates/js/stock.html:27 +#: templates/js/stock.html:28 msgid "FAIL" msgstr "" -#: templates/js/stock.html:32 +#: templates/js/stock.html:33 msgid "NO RESULT" msgstr "" -#: templates/js/stock.html:58 +#: templates/js/stock.html:59 #, fuzzy #| msgid "Edit Sales Order" msgid "Add test result" msgstr "Auftrag bearbeiten" -#: templates/js/stock.html:76 +#: templates/js/stock.html:77 #, fuzzy #| msgid "No results found" msgid "No test results found" msgstr "Keine Ergebnisse gefunden" -#: templates/js/stock.html:117 +#: templates/js/stock.html:118 #, fuzzy #| msgid "Shipment Date" msgid "Test Date" msgstr "Versanddatum" -#: templates/js/stock.html:258 +#: templates/js/stock.html:261 msgid "No stock items matching query" msgstr "Keine zur Anfrage passenden Lagerobjekte" -#: templates/js/stock.html:355 templates/js/stock.html:370 +#: templates/js/stock.html:358 templates/js/stock.html:373 #, fuzzy #| msgid "Include sublocations" msgid "Undefined location" msgstr "Unterlagerorte einschließen" -#: templates/js/stock.html:467 -msgid "StockItem has been allocated" +#: templates/js/stock.html:464 +#, fuzzy +#| msgid "StockItem has been allocated" +msgid "Stock item has been allocated" msgstr "Lagerobjekt wurde zugewiesen" +#: templates/js/stock.html:468 +#, fuzzy +#| msgid "StockItem has been allocated" +msgid "Stock item has been assigned to customer" +msgstr "Lagerobjekt wurde zugewiesen" + +#: templates/js/stock.html:470 +#, fuzzy +#| msgid "This stock item is allocated to Sales Order" +msgid "Stock item was assigned to a build order" +msgstr "Dieses Lagerobjekt ist dem Auftrag zugewiesen" + #: templates/js/stock.html:472 -msgid "StockItem is lost" +#, fuzzy +#| msgid "This stock item is allocated to Sales Order" +msgid "Stock item was assigned to a sales order" +msgstr "Dieses Lagerobjekt ist dem Auftrag zugewiesen" + +#: templates/js/stock.html:479 +#, fuzzy +#| msgid "StockItem has been allocated" +msgid "Stock item has been rejected" +msgstr "Lagerobjekt wurde zugewiesen" + +#: templates/js/stock.html:483 +#, fuzzy +#| msgid "StockItem is lost" +msgid "Stock item is lost" msgstr "Lagerobjekt verloren" -#: templates/js/stock.html:500 +#: templates/js/stock.html:487 templates/js/table_filters.html:52 +#, fuzzy +#| msgid "Delete" +msgid "Depleted" +msgstr "Löschen" + +#: templates/js/stock.html:516 +#, fuzzy +#| msgid "Item assigned to customer?" +msgid "Shipped to customer" +msgstr "Ist dieses Objekt einem Kunden zugeteilt?" + +#: templates/js/stock.html:519 msgid "No stock location set" msgstr "Kein Lagerort gesetzt" -#: templates/js/stock.html:671 +#: templates/js/stock.html:691 msgid "No user information" msgstr "Keine Benutzerinformation" -#: templates/js/table_filters.html:19 -msgid "Include sublocations" -msgstr "Unterlagerorte einschließen" +#: templates/js/table_filters.html:19 templates/js/table_filters.html:67 +#, fuzzy +#| msgid "Serialize Stock" +msgid "Is Serialized" +msgstr "Lagerbestand erfassen" -#: templates/js/table_filters.html:20 -msgid "Include stock in sublocations" -msgstr "Bestand in Unterlagerorten einschließen" - -#: templates/js/table_filters.html:24 -msgid "Active parts" -msgstr "Aktive Teile" - -#: templates/js/table_filters.html:25 -msgid "Show stock for active parts" -msgstr "Bestand aktiver Teile anzeigen" - -#: templates/js/table_filters.html:29 templates/js/table_filters.html:30 -msgid "Stock status" -msgstr "Bestandsstatus" - -#: templates/js/table_filters.html:34 -msgid "Is allocated" -msgstr "Ist zugeordnet" - -#: templates/js/table_filters.html:35 -msgid "Item has been alloacted" -msgstr "Position wurde zugeordnet" - -#: templates/js/table_filters.html:38 +#: templates/js/table_filters.html:22 templates/js/table_filters.html:70 #, fuzzy #| msgid "Serial Number" msgid "Serial number GTE" msgstr "Seriennummer" -#: templates/js/table_filters.html:39 +#: templates/js/table_filters.html:23 templates/js/table_filters.html:71 #, fuzzy #| msgid "Serial number for this item" msgid "Serial number greater than or equal to" msgstr "Seriennummer für dieses Teil" -#: templates/js/table_filters.html:42 +#: templates/js/table_filters.html:26 templates/js/table_filters.html:74 #, fuzzy #| msgid "Serial Number" msgid "Serial number LTE" msgstr "Seriennummer" -#: templates/js/table_filters.html:43 +#: templates/js/table_filters.html:27 templates/js/table_filters.html:75 #, fuzzy #| msgid "Serial numbers already exist: " msgid "Serial number less than or equal to" msgstr "Seriennummern existieren bereits:" -#: templates/js/table_filters.html:72 +#: templates/js/table_filters.html:37 +msgid "Active parts" +msgstr "Aktive Teile" + +#: templates/js/table_filters.html:38 +msgid "Show stock for active parts" +msgstr "Bestand aktiver Teile anzeigen" + +#: templates/js/table_filters.html:42 +msgid "Is allocated" +msgstr "Ist zugeordnet" + +#: templates/js/table_filters.html:43 +msgid "Item has been alloacted" +msgstr "Position wurde zugeordnet" + +#: templates/js/table_filters.html:47 +msgid "Include sublocations" +msgstr "Unterlagerorte einschließen" + +#: templates/js/table_filters.html:48 +msgid "Include stock in sublocations" +msgstr "Bestand in Unterlagerorten einschließen" + +#: templates/js/table_filters.html:53 +#, fuzzy +#| msgid "Delete this Stock Item when stock is depleted" +msgid "Show stock items which are depleted" +msgstr "Objekt löschen wenn Lagerbestand aufgebraucht" + +#: templates/js/table_filters.html:58 +msgid "Show items which are in stock" +msgstr "" + +#: templates/js/table_filters.html:62 +#, fuzzy +#| msgid "Item assigned to customer?" +msgid "Sent to customer" +msgstr "Ist dieses Objekt einem Kunden zugeteilt?" + +#: templates/js/table_filters.html:63 +msgid "Show items which have been assigned to a customer" +msgstr "" + +#: templates/js/table_filters.html:79 templates/js/table_filters.html:80 +msgid "Stock status" +msgstr "Bestandsstatus" + +#: templates/js/table_filters.html:109 msgid "Build status" msgstr "Bau-Status" -#: templates/js/table_filters.html:84 templates/js/table_filters.html:97 +#: templates/js/table_filters.html:121 templates/js/table_filters.html:134 msgid "Order status" msgstr "Bestellstatus" -#: templates/js/table_filters.html:89 templates/js/table_filters.html:102 +#: templates/js/table_filters.html:126 templates/js/table_filters.html:139 #, fuzzy #| msgid "Cascading" msgid "Outstanding" msgstr "Kaskadierend" -#: templates/js/table_filters.html:112 +#: templates/js/table_filters.html:149 msgid "Include subcategories" msgstr "Unterkategorien einschließen" -#: templates/js/table_filters.html:113 +#: templates/js/table_filters.html:150 msgid "Include parts in subcategories" msgstr "Teile in Unterkategorien einschließen" -#: templates/js/table_filters.html:118 +#: templates/js/table_filters.html:155 msgid "Show active parts" msgstr "Aktive Teile anzeigen" -#: templates/js/table_filters.html:126 +#: templates/js/table_filters.html:163 msgid "Stock available" msgstr "Bestand verfügbar" -#: templates/js/table_filters.html:142 +#: templates/js/table_filters.html:179 msgid "Starred" msgstr "Favorit" -#: templates/js/table_filters.html:154 +#: templates/js/table_filters.html:191 msgid "Purchasable" msgstr "Käuflich" @@ -3974,6 +4260,15 @@ msgstr "Bestand bestellen" msgid "Delete Stock" msgstr "Bestand löschen" +#~ msgid "Used for Build" +#~ msgstr "Verwendet für Bau" + +#~ msgid "Installed in Stock Item" +#~ msgstr "In Lagerobjekt installiert" + +#~ msgid "Count stock items" +#~ msgstr "Lagerobjekte zählen" + #~ msgid "Barcode successfully decoded" #~ msgstr "Strichcode erfolgreich dekodiert" diff --git a/InvenTree/locale/en/LC_MESSAGES/django.po b/InvenTree/locale/en/LC_MESSAGES/django.po index c539fbcae5..dda559ee7e 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: 2020-06-12 00:43+0000\n" +"POT-Creation-Date: 2020-08-16 02:11+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -78,7 +78,7 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 templates/js/stock.html:662 +#: InvenTree/models.py:68 templates/js/stock.html:682 msgid "User" msgstr "" @@ -90,24 +90,24 @@ msgstr "" msgid "Description (optional)" msgstr "" -#: InvenTree/settings.py:330 +#: InvenTree/settings.py:335 msgid "English" msgstr "" -#: InvenTree/settings.py:331 +#: InvenTree/settings.py:336 msgid "German" msgstr "" -#: InvenTree/settings.py:332 +#: InvenTree/settings.py:337 msgid "French" msgstr "" -#: InvenTree/settings.py:333 +#: InvenTree/settings.py:338 msgid "Polish" msgstr "" #: InvenTree/status_codes.py:94 InvenTree/status_codes.py:135 -#: InvenTree/status_codes.py:235 +#: InvenTree/status_codes.py:222 msgid "Pending" msgstr "" @@ -115,59 +115,50 @@ msgstr "" msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:96 InvenTree/status_codes.py:238 +#: InvenTree/status_codes.py:96 InvenTree/status_codes.py:225 msgid "Complete" msgstr "" #: InvenTree/status_codes.py:97 InvenTree/status_codes.py:137 -#: InvenTree/status_codes.py:237 +#: InvenTree/status_codes.py:224 msgid "Cancelled" msgstr "" #: InvenTree/status_codes.py:98 InvenTree/status_codes.py:138 -#: InvenTree/status_codes.py:179 +#: InvenTree/status_codes.py:175 msgid "Lost" msgstr "" #: InvenTree/status_codes.py:99 InvenTree/status_codes.py:139 -#: InvenTree/status_codes.py:181 +#: InvenTree/status_codes.py:177 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:136 InvenTree/status_codes.py:182 -#: order/templates/order/sales_order_base.html:98 +#: InvenTree/status_codes.py:136 order/templates/order/sales_order_base.html:98 msgid "Shipped" msgstr "" -#: InvenTree/status_codes.py:175 +#: InvenTree/status_codes.py:171 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:176 +#: InvenTree/status_codes.py:172 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:177 +#: InvenTree/status_codes.py:173 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:178 +#: InvenTree/status_codes.py:174 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:180 +#: InvenTree/status_codes.py:176 msgid "Rejected" msgstr "" -#: InvenTree/status_codes.py:183 -msgid "Used for Build" -msgstr "" - -#: InvenTree/status_codes.py:184 -msgid "Installed in Stock Item" -msgstr "" - -#: InvenTree/status_codes.py:236 build/templates/build/allocate.html:349 +#: InvenTree/status_codes.py:223 build/templates/build/allocate.html:349 #: order/templates/order/sales_order_detail.html:220 #: part/templates/part/tabs.html:23 templates/js/build.html:120 msgid "Allocated" @@ -250,7 +241,7 @@ msgstr "" msgid "Serial numbers" msgstr "" -#: build/forms.py:64 stock/forms.py:93 +#: build/forms.py:64 stock/forms.py:105 msgid "Enter unique serial numbers (or leave blank)" msgstr "" @@ -286,9 +277,10 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:145 #: order/templates/order/receive_parts.html:19 part/models.py:240 #: part/templates/part/part_app_base.html:7 -#: part/templates/part/set_category.html:13 templates/js/bom.html:135 -#: templates/js/build.html:41 templates/js/company.html:109 -#: templates/js/part.html:120 templates/js/stock.html:422 +#: part/templates/part/set_category.html:13 templates/js/barcode.html:336 +#: templates/js/bom.html:135 templates/js/build.html:41 +#: templates/js/company.html:109 templates/js/part.html:120 +#: templates/js/stock.html:425 msgid "Part" msgstr "" @@ -322,7 +314,7 @@ msgstr "" msgid "Number of parts to build" msgstr "" -#: build/models.py:128 part/templates/part/part_base.html:141 +#: build/models.py:128 part/templates/part/part_base.html:139 msgid "Build Status" msgstr "" @@ -330,7 +322,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:136 stock/models.py:374 +#: build/models.py:136 stock/models.py:376 msgid "Batch Code" msgstr "" @@ -341,22 +333,22 @@ msgstr "" #: build/models.py:155 build/templates/build/detail.html:55 #: company/templates/company/supplier_part_base.html:60 #: company/templates/company/supplier_part_detail.html:24 -#: part/templates/part/detail.html:74 part/templates/part/part_base.html:88 -#: stock/models.py:368 stock/templates/stock/item_base.html:230 +#: part/templates/part/detail.html:74 part/templates/part/part_base.html:86 +#: stock/models.py:370 stock/templates/stock/item_base.html:237 msgid "External Link" msgstr "" -#: build/models.py:156 stock/models.py:370 +#: build/models.py:156 stock/models.py:372 msgid "Link to external URL" msgstr "" -#: build/models.py:160 build/templates/build/tabs.html:14 company/models.py:302 +#: build/models.py:160 build/templates/build/tabs.html:14 company/models.py:310 #: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:15 #: order/templates/order/purchase_order_detail.html:200 -#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:73 -#: stock/models.py:436 stock/models.py:1265 stock/templates/stock/tabs.html:26 -#: templates/js/bom.html:229 templates/js/stock.html:113 -#: templates/js/stock.html:506 +#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:64 +#: stock/models.py:438 stock/models.py:1287 stock/templates/stock/tabs.html:26 +#: templates/js/barcode.html:391 templates/js/bom.html:229 +#: templates/js/stock.html:114 templates/js/stock.html:526 msgid "Notes" msgstr "" @@ -386,15 +378,15 @@ msgstr "" msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:512 +#: build/models.py:511 msgid "Build to allocate parts" msgstr "" -#: build/models.py:519 +#: build/models.py:518 msgid "Stock Item to allocate to build" msgstr "" -#: build/models.py:532 +#: build/models.py:531 msgid "Stock quantity to allocate to build" msgstr "" @@ -421,8 +413,8 @@ msgstr "" #: build/templates/build/allocate.html:161 #: order/templates/order/sales_order_detail.html:68 -#: order/templates/order/sales_order_detail.html:150 stock/models.py:362 -#: stock/templates/stock/item_base.html:189 +#: order/templates/order/sales_order_detail.html:150 stock/models.py:364 +#: stock/templates/stock/item_base.html:153 msgid "Serial Number" msgstr "" @@ -439,16 +431,18 @@ msgstr "" #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:26 #: stock/templates/stock/item_base.html:32 -#: stock/templates/stock/item_base.html:195 -#: stock/templates/stock/stock_adjust.html:18 templates/js/bom.html:172 -#: templates/js/build.html:52 templates/js/stock.html:653 +#: stock/templates/stock/item_base.html:159 +#: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338 +#: templates/js/bom.html:172 templates/js/build.html:52 +#: templates/js/stock.html:673 msgid "Quantity" msgstr "" #: build/templates/build/allocate.html:177 #: build/templates/build/auto_allocate.html:20 -#: stock/templates/stock/item_base.html:171 -#: stock/templates/stock/stock_adjust.html:17 templates/js/stock.html:493 +#: stock/templates/stock/item_base.html:191 +#: stock/templates/stock/stock_adjust.html:17 templates/js/barcode.html:337 +#: templates/js/stock.html:508 msgid "Location" msgstr "" @@ -474,7 +468,7 @@ msgstr "" #: templates/js/bom.html:157 templates/js/company.html:60 #: templates/js/order.html:157 templates/js/order.html:230 #: templates/js/part.html:176 templates/js/part.html:355 -#: templates/js/stock.html:443 templates/js/stock.html:634 +#: templates/js/stock.html:440 templates/js/stock.html:654 msgid "Description" msgstr "" @@ -484,8 +478,8 @@ msgstr "" msgid "Reference" msgstr "" -#: build/templates/build/allocate.html:338 part/models.py:1260 -#: templates/js/part.html:359 templates/js/table_filters.html:63 +#: build/templates/build/allocate.html:338 part/models.py:1270 +#: templates/js/part.html:359 templates/js/table_filters.html:100 msgid "Required" msgstr "" @@ -528,7 +522,7 @@ msgstr "" #: build/templates/build/build_base.html:8 #: build/templates/build/build_base.html:34 #: build/templates/build/complete.html:6 -#: stock/templates/stock/item_base.html:209 templates/js/build.html:33 +#: stock/templates/stock/item_base.html:216 templates/js/build.html:33 #: templates/navbar.html:12 msgid "Build" msgstr "" @@ -548,9 +542,9 @@ msgstr "" #: build/templates/build/build_base.html:80 #: build/templates/build/detail.html:42 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:262 templates/js/build.html:57 -#: templates/js/order.html:162 templates/js/order.html:235 -#: templates/js/stock.html:480 +#: stock/templates/stock/item_base.html:269 templates/js/barcode.html:42 +#: templates/js/build.html:57 templates/js/order.html:162 +#: templates/js/order.html:235 templates/js/stock.html:495 msgid "Status" msgstr "" @@ -560,7 +554,7 @@ msgstr "" #: order/templates/order/sales_order_notes.html:10 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:27 -#: stock/templates/stock/item_base.html:159 templates/js/order.html:209 +#: stock/templates/stock/item_base.html:179 templates/js/order.html:209 msgid "Sales Order" msgstr "" @@ -627,7 +621,7 @@ msgid "Stock can be taken from any available location." msgstr "" #: build/templates/build/detail.html:48 -#: stock/templates/stock/item_base.html:202 templates/js/stock.html:488 +#: stock/templates/stock/item_base.html:209 templates/js/stock.html:503 msgid "Batch" msgstr "" @@ -730,7 +724,7 @@ msgstr "" msgid "Confirm unallocation of build stock" msgstr "" -#: build/views.py:162 stock/views.py:286 +#: build/views.py:162 stock/views.py:404 msgid "Check the confirmation box" msgstr "" @@ -738,7 +732,7 @@ msgstr "" msgid "Complete Build" msgstr "" -#: build/views.py:201 stock/views.py:1118 stock/views.py:1232 +#: build/views.py:201 stock/views.py:1236 stock/views.py:1350 msgid "Next available serial number is" msgstr "" @@ -754,7 +748,7 @@ msgstr "" msgid "Invalid location selected" msgstr "" -#: build/views.py:300 stock/views.py:1268 +#: build/views.py:300 stock/views.py:1386 #, python-brace-format msgid "The following serial numbers already exist: ({sn})" msgstr "" @@ -847,83 +841,113 @@ msgstr "" msgid "Delete Currency" msgstr "" -#: company/models.py:83 +#: company/models.py:86 company/models.py:87 msgid "Company name" msgstr "" -#: company/models.py:85 +#: company/models.py:89 +msgid "Company description" +msgstr "" + +#: company/models.py:89 msgid "Description of the company" msgstr "" -#: company/models.py:87 +#: company/models.py:91 company/templates/company/company_base.html:48 +#: templates/js/company.html:65 +msgid "Website" +msgstr "" + +#: company/models.py:91 msgid "Company website URL" msgstr "" -#: company/models.py:90 -msgid "Company address" -msgstr "" - -#: company/models.py:93 -msgid "Contact phone number" +#: company/models.py:94 company/templates/company/company_base.html:55 +msgid "Address" msgstr "" #: company/models.py:95 -msgid "Contact email address" +msgid "Company address" msgstr "" #: company/models.py:98 +msgid "Phone number" +msgstr "" + +#: company/models.py:99 +msgid "Contact phone number" +msgstr "" + +#: company/models.py:101 company/templates/company/company_base.html:69 +msgid "Email" +msgstr "" + +#: company/models.py:101 +msgid "Contact email address" +msgstr "" + +#: company/models.py:104 company/templates/company/company_base.html:76 +msgid "Contact" +msgstr "" + +#: company/models.py:105 msgid "Point of contact" msgstr "" -#: company/models.py:100 +#: company/models.py:107 msgid "Link to external company information" msgstr "" -#: company/models.py:112 +#: company/models.py:119 msgid "Do you sell items to this company?" msgstr "" -#: company/models.py:114 +#: company/models.py:121 msgid "Do you purchase items from this company?" msgstr "" -#: company/models.py:116 +#: company/models.py:123 msgid "Does this company manufacture parts?" msgstr "" -#: company/models.py:276 +#: company/models.py:279 stock/models.py:324 +#: stock/templates/stock/item_base.html:145 +msgid "Base Part" +msgstr "" + +#: company/models.py:284 msgid "Select part" msgstr "" -#: company/models.py:282 +#: company/models.py:290 msgid "Select supplier" msgstr "" -#: company/models.py:285 +#: company/models.py:293 msgid "Supplier stock keeping unit" msgstr "" -#: company/models.py:292 +#: company/models.py:300 msgid "Select manufacturer" msgstr "" -#: company/models.py:296 +#: company/models.py:304 msgid "Manufacturer part number" msgstr "" -#: company/models.py:298 +#: company/models.py:306 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:300 +#: company/models.py:308 msgid "Supplier part description" msgstr "" -#: company/models.py:304 +#: company/models.py:312 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:306 +#: company/models.py:314 msgid "Part packaging" msgstr "" @@ -942,26 +966,10 @@ msgstr "" msgid "Company Details" msgstr "" -#: company/templates/company/company_base.html:48 templates/js/company.html:65 -msgid "Website" -msgstr "" - -#: company/templates/company/company_base.html:55 -msgid "Address" -msgstr "" - #: company/templates/company/company_base.html:62 msgid "Phone" msgstr "" -#: company/templates/company/company_base.html:69 -msgid "Email" -msgstr "" - -#: company/templates/company/company_base.html:76 -msgid "Contact" -msgstr "" - #: company/templates/company/detail.html:16 #: company/templates/company/supplier_part_base.html:76 #: company/templates/company/supplier_part_detail.html:30 @@ -974,14 +982,14 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:21 order/models.py:148 #: order/templates/order/order_base.html:74 #: order/templates/order/order_wizard/select_pos.html:30 -#: stock/templates/stock/item_base.html:237 templates/js/company.html:52 +#: stock/templates/stock/item_base.html:244 templates/js/company.html:52 #: templates/js/company.html:134 templates/js/order.html:144 msgid "Supplier" msgstr "" #: company/templates/company/detail.html:26 order/models.py:314 -#: order/templates/order/sales_order_base.html:73 stock/models.py:357 -#: stock/models.py:358 stock/templates/stock/item_base.html:146 +#: order/templates/order/sales_order_base.html:73 stock/models.py:359 +#: stock/models.py:360 stock/templates/stock/item_base.html:166 #: templates/js/company.html:44 templates/js/order.html:217 msgid "Customer" msgstr "" @@ -992,7 +1000,7 @@ msgstr "" #: company/templates/company/detail_part.html:13 #: order/templates/order/purchase_order_detail.html:67 -#: part/templates/part/stock.html:82 part/templates/part/supplier.html:12 +#: part/templates/part/stock.html:81 part/templates/part/supplier.html:12 msgid "New Supplier Part" msgstr "" @@ -1006,7 +1014,7 @@ msgid "Delete Parts" msgstr "" #: company/templates/company/detail_part.html:43 -#: part/templates/part/stock.html:76 +#: part/templates/part/stock.html:75 msgid "New Part" msgstr "" @@ -1036,9 +1044,9 @@ msgstr "" msgid "Supplier Stock" msgstr "" -#: company/templates/company/detail_stock.html:34 +#: company/templates/company/detail_stock.html:35 #: company/templates/company/supplier_part_stock.html:33 -#: part/templates/part/stock.html:54 templates/stock_table.html:5 +#: part/templates/part/stock.html:53 templates/stock_table.html:5 msgid "Export" msgstr "" @@ -1094,8 +1102,8 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:6 -#: company/templates/company/supplier_part_base.html:19 stock/models.py:331 -#: stock/templates/stock/item_base.html:242 templates/js/company.html:150 +#: company/templates/company/supplier_part_base.html:19 stock/models.py:333 +#: stock/templates/stock/item_base.html:249 templates/js/company.html:150 msgid "Supplier Part" msgstr "" @@ -1178,12 +1186,12 @@ msgstr "" #: company/templates/company/supplier_part_stock.html:56 #: order/templates/order/purchase_order_detail.html:38 #: order/templates/order/purchase_order_detail.html:118 -#: part/templates/part/stock.html:91 +#: part/templates/part/stock.html:90 msgid "New Location" msgstr "" #: company/templates/company/supplier_part_stock.html:57 -#: part/templates/part/stock.html:92 +#: part/templates/part/stock.html:91 msgid "Create New Location" msgstr "" @@ -1194,7 +1202,7 @@ msgstr "" #: company/templates/company/supplier_part_tabs.html:8 #: company/templates/company/tabs.html:12 part/templates/part/tabs.html:18 #: stock/templates/stock/location.html:12 templates/js/part.html:203 -#: templates/js/stock.html:451 templates/navbar.html:11 +#: templates/js/stock.html:448 templates/navbar.html:11 msgid "Stock" msgstr "" @@ -1274,7 +1282,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:265 part/templates/part/stock.html:83 +#: company/views.py:265 part/templates/part/stock.html:82 msgid "Create new Supplier Part" msgstr "" @@ -1294,6 +1302,22 @@ msgstr "" msgid "Delete Price Break" msgstr "" +#: label/models.py:55 +msgid "Label name" +msgstr "" + +#: label/models.py:58 +msgid "Label description" +msgstr "" + +#: label/models.py:63 +msgid "Label template file" +msgstr "" + +#: label/models.py:69 +msgid "Query filters (comma-separated list of key=value pairs" +msgstr "" + #: order/forms.py:24 msgid "Place order" msgstr "" @@ -1344,7 +1368,7 @@ msgid "Supplier order reference code" msgstr "" #: order/models.py:185 order/models.py:259 part/views.py:1167 -#: stock/models.py:243 stock/models.py:665 stock/views.py:1243 +#: stock/models.py:238 stock/models.py:687 msgid "Quantity must be greater than zero" msgstr "" @@ -1378,7 +1402,7 @@ msgstr "" #: order/models.py:466 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:23 -#: stock/templates/stock/item_base.html:216 templates/js/order.html:136 +#: stock/templates/stock/item_base.html:223 templates/js/order.html:136 msgid "Purchase Order" msgstr "" @@ -1508,7 +1532,7 @@ msgid "Purchase Order Attachments" msgstr "" #: order/templates/order/po_tabs.html:8 order/templates/order/so_tabs.html:16 -#: part/templates/part/tabs.html:70 stock/templates/stock/tabs.html:32 +#: part/templates/part/tabs.html:61 stock/templates/stock/tabs.html:32 msgid "Attachments" msgstr "" @@ -1524,7 +1548,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:39 #: order/templates/order/purchase_order_detail.html:119 -#: stock/templates/stock/location.html:17 +#: stock/templates/stock/location.html:16 msgid "Create new stock location" msgstr "" @@ -1563,7 +1587,7 @@ msgid "Select parts to receive against this order" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:131 templates/js/part.html:219 +#: part/templates/part/part_base.html:129 templates/js/part.html:219 msgid "On Order" msgstr "" @@ -1655,7 +1679,7 @@ msgstr "" msgid "Add Purchase Order Attachment" msgstr "" -#: order/views.py:102 order/views.py:149 part/views.py:85 stock/views.py:166 +#: order/views.py:102 order/views.py:149 part/views.py:85 stock/views.py:167 msgid "Added attachment" msgstr "" @@ -1675,7 +1699,7 @@ msgstr "" msgid "Delete Attachment" msgstr "" -#: order/views.py:222 order/views.py:236 stock/views.py:222 +#: order/views.py:222 order/views.py:236 stock/views.py:223 msgid "Deleted attachment" msgstr "" @@ -1808,11 +1832,11 @@ msgstr "" msgid "Error reading BOM file (incorrect row size)" msgstr "" -#: part/forms.py:55 stock/forms.py:200 +#: part/forms.py:55 stock/forms.py:243 msgid "File Format" msgstr "" -#: part/forms.py:55 stock/forms.py:200 +#: part/forms.py:55 stock/forms.py:243 msgid "Select output file format" msgstr "" @@ -1860,207 +1884,220 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:427 +#: part/models.py:74 part/templates/part/part_app_base.html:9 +msgid "Part Category" +msgstr "" + +#: part/models.py:75 part/templates/part/category.html:13 +#: part/templates/part/category.html:78 templates/stats.html:12 +msgid "Part Categories" +msgstr "" + +#: part/models.py:428 msgid "Part must be unique for name, IPN and revision" msgstr "" -#: part/models.py:442 part/templates/part/detail.html:19 +#: part/models.py:443 part/templates/part/detail.html:19 msgid "Part name" msgstr "" -#: part/models.py:446 +#: part/models.py:447 msgid "Is this part a template part?" msgstr "" -#: part/models.py:455 +#: part/models.py:456 msgid "Is this part a variant of another part?" msgstr "" -#: part/models.py:457 +#: part/models.py:458 msgid "Part description" msgstr "" -#: part/models.py:459 +#: part/models.py:460 msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:464 +#: part/models.py:465 msgid "Part category" msgstr "" -#: part/models.py:466 +#: part/models.py:467 msgid "Internal Part Number" msgstr "" -#: part/models.py:468 +#: part/models.py:469 msgid "Part revision or version number" msgstr "" -#: part/models.py:470 +#: part/models.py:471 msgid "Link to extenal URL" msgstr "" -#: part/models.py:482 +#: part/models.py:483 msgid "Where is this item normally stored?" msgstr "" -#: part/models.py:526 +#: part/models.py:527 msgid "Default supplier part" msgstr "" -#: part/models.py:529 +#: part/models.py:530 msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:531 +#: part/models.py:532 msgid "Stock keeping units for this part" msgstr "" -#: part/models.py:533 +#: part/models.py:534 msgid "Can this part be built from other parts?" msgstr "" -#: part/models.py:535 +#: part/models.py:536 msgid "Can this part be used to build other parts?" msgstr "" -#: part/models.py:537 +#: part/models.py:538 msgid "Does this part have tracking for unique items?" msgstr "" -#: part/models.py:539 +#: part/models.py:540 msgid "Can this part be purchased from external suppliers?" msgstr "" -#: part/models.py:541 +#: part/models.py:542 msgid "Can this part be sold to customers?" msgstr "" -#: part/models.py:543 +#: part/models.py:544 msgid "Is this part active?" msgstr "" -#: part/models.py:545 +#: part/models.py:546 msgid "Is this a virtual part, such as a software product or license?" msgstr "" -#: part/models.py:547 +#: part/models.py:548 msgid "Part notes - supports Markdown formatting" msgstr "" -#: part/models.py:549 +#: part/models.py:550 msgid "Stored BOM checksum" msgstr "" -#: part/models.py:1212 +#: part/models.py:1222 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:1229 +#: part/models.py:1239 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:1248 templates/js/part.html:350 templates/js/stock.html:89 +#: part/models.py:1258 templates/js/part.html:350 templates/js/stock.html:90 msgid "Test Name" msgstr "" -#: part/models.py:1249 +#: part/models.py:1259 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1254 +#: part/models.py:1264 msgid "Test Description" msgstr "" -#: part/models.py:1255 +#: part/models.py:1265 msgid "Enter description for this test" msgstr "" -#: part/models.py:1261 +#: part/models.py:1271 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:1266 templates/js/part.html:367 +#: part/models.py:1276 templates/js/part.html:367 msgid "Requires Value" msgstr "" -#: part/models.py:1267 +#: part/models.py:1277 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:1272 templates/js/part.html:374 +#: part/models.py:1282 templates/js/part.html:374 msgid "Requires Attachment" msgstr "" -#: part/models.py:1273 +#: part/models.py:1283 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:1306 +#: part/models.py:1316 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:1311 +#: part/models.py:1321 msgid "Parameter Name" msgstr "" -#: part/models.py:1313 +#: part/models.py:1323 msgid "Parameter Units" msgstr "" -#: part/models.py:1339 +#: part/models.py:1349 msgid "Parent Part" msgstr "" -#: part/models.py:1341 +#: part/models.py:1351 msgid "Parameter Template" msgstr "" -#: part/models.py:1343 +#: part/models.py:1353 msgid "Parameter Value" msgstr "" -#: part/models.py:1372 +#: part/models.py:1382 msgid "Select parent part" msgstr "" -#: part/models.py:1380 +#: part/models.py:1390 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:1386 +#: part/models.py:1396 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:1389 +#: part/models.py:1399 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:1392 +#: part/models.py:1402 msgid "BOM item reference" msgstr "" -#: part/models.py:1395 +#: part/models.py:1405 msgid "BOM item notes" msgstr "" -#: part/models.py:1397 +#: part/models.py:1407 msgid "BOM line checksum" msgstr "" -#: part/models.py:1461 stock/models.py:233 +#: part/models.py:1471 stock/models.py:228 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:1470 +#: part/models.py:1480 msgid "Part cannot be added to its own Bill of Materials" msgstr "" -#: part/models.py:1477 +#: part/models.py:1487 #, python-brace-format msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgstr "" +#: part/models.py:1494 +msgid "BOM Item" +msgstr "" + #: part/templates/part/allocation.html:10 msgid "Part Stock Allocations" msgstr "" @@ -2076,14 +2113,14 @@ msgstr "" #: part/templates/part/allocation.html:45 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:58 -#: stock/templates/stock/item_base.html:224 +#: stock/templates/stock/item_base.html:231 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106 -#: templates/js/stock.html:623 +#: templates/js/stock.html:643 msgid "Stock Item" msgstr "" #: part/templates/part/allocation.html:20 -#: stock/templates/stock/item_base.html:165 +#: stock/templates/stock/item_base.html:185 msgid "Build Order" msgstr "" @@ -2123,11 +2160,6 @@ msgstr "" msgid "Export Bill of Materials" msgstr "" -#: part/templates/part/category.html:13 part/templates/part/category.html:78 -#: templates/stats.html:12 -msgid "Part Categories" -msgstr "" - #: part/templates/part/category.html:14 msgid "All parts" msgstr "" @@ -2164,7 +2196,7 @@ msgstr "" msgid "Part Details" msgstr "" -#: part/templates/part/detail.html:25 part/templates/part/part_base.html:81 +#: part/templates/part/detail.html:25 part/templates/part/part_base.html:79 msgid "IPN" msgstr "" @@ -2221,8 +2253,8 @@ msgstr "" msgid "Part is not a virtual part" msgstr "" -#: part/templates/part/detail.html:139 stock/forms.py:194 -#: templates/js/table_filters.html:122 +#: part/templates/part/detail.html:139 stock/forms.py:237 +#: templates/js/table_filters.html:159 msgid "Template" msgstr "" @@ -2234,7 +2266,7 @@ msgstr "" msgid "Part is not a template part" msgstr "" -#: part/templates/part/detail.html:148 templates/js/table_filters.html:134 +#: part/templates/part/detail.html:148 templates/js/table_filters.html:171 msgid "Assembly" msgstr "" @@ -2246,7 +2278,7 @@ msgstr "" msgid "Part cannot be assembled from other parts" msgstr "" -#: part/templates/part/detail.html:157 templates/js/table_filters.html:138 +#: part/templates/part/detail.html:157 templates/js/table_filters.html:175 msgid "Component" msgstr "" @@ -2258,7 +2290,7 @@ msgstr "" msgid "Part cannot be used in assemblies" msgstr "" -#: part/templates/part/detail.html:166 templates/js/table_filters.html:150 +#: part/templates/part/detail.html:166 templates/js/table_filters.html:187 msgid "Trackable" msgstr "" @@ -2278,7 +2310,7 @@ msgstr "" msgid "Part can be purchased from external suppliers" msgstr "" -#: part/templates/part/detail.html:184 templates/js/table_filters.html:146 +#: part/templates/part/detail.html:184 templates/js/table_filters.html:183 msgid "Salable" msgstr "" @@ -2290,7 +2322,7 @@ msgstr "" msgid "Part cannot be sold to customers" msgstr "" -#: part/templates/part/detail.html:193 templates/js/table_filters.html:117 +#: part/templates/part/detail.html:193 templates/js/table_filters.html:154 msgid "Active" msgstr "" @@ -2322,8 +2354,8 @@ msgstr "" msgid "New Parameter" msgstr "" -#: part/templates/part/params.html:21 stock/models.py:1252 -#: templates/js/stock.html:109 +#: part/templates/part/params.html:21 stock/models.py:1274 +#: templates/js/stock.html:110 msgid "Value" msgstr "" @@ -2335,10 +2367,6 @@ msgstr "" msgid "Delete" msgstr "" -#: part/templates/part/part_app_base.html:9 -msgid "Part Category" -msgstr "" - #: part/templates/part/part_app_base.html:11 msgid "Part List" msgstr "" @@ -2360,35 +2388,69 @@ msgstr "" msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:41 +#: part/templates/part/part_base.html:39 msgid "Star this part" msgstr "" +#: part/templates/part/part_base.html:44 +#: stock/templates/stock/item_base.html:78 +#: stock/templates/stock/location.html:22 +msgid "Barcode actions" +msgstr "" + +#: part/templates/part/part_base.html:46 +#: stock/templates/stock/item_base.html:80 +#: stock/templates/stock/location.html:24 +msgid "Show QR Code" +msgstr "" + #: part/templates/part/part_base.html:47 +#: stock/templates/stock/item_base.html:81 +#: stock/templates/stock/location.html:25 +msgid "Print Label" +msgstr "" + +#: part/templates/part/part_base.html:51 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:104 +#: part/templates/part/part_base.html:64 +msgid "Part actions" +msgstr "" + +#: part/templates/part/part_base.html:66 +msgid "Duplicate part" +msgstr "" + +#: part/templates/part/part_base.html:67 +msgid "Edit part" +msgstr "" + +#: part/templates/part/part_base.html:69 +msgid "Delete part" +msgstr "" + +#: part/templates/part/part_base.html:102 msgid "Available Stock" msgstr "" -#: part/templates/part/part_base.html:110 +#: part/templates/part/part_base.html:108 templates/js/table_filters.html:57 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:117 +#: part/templates/part/part_base.html:115 msgid "Allocated to Build Orders" msgstr "" -#: part/templates/part/part_base.html:124 +#: part/templates/part/part_base.html:122 msgid "Allocated to Sales Orders" msgstr "" -#: part/templates/part/part_base.html:146 +#: part/templates/part/part_base.html:144 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:152 +#: part/templates/part/part_base.html:150 msgid "Underway" msgstr "" @@ -2428,7 +2490,7 @@ msgstr "" msgid "Part Stock" msgstr "" -#: part/templates/part/stock.html:77 +#: part/templates/part/stock.html:76 msgid "Create New Part" msgstr "" @@ -2473,11 +2535,7 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/tabs.html:57 stock/templates/stock/tabs.html:6 -msgid "Tracking" -msgstr "" - -#: part/templates/part/tabs.html:64 stock/templates/stock/item_base.html:268 +#: part/templates/part/tabs.html:55 stock/templates/stock/item_base.html:275 msgid "Tests" msgstr "" @@ -2694,219 +2752,227 @@ msgstr "" msgid "Asset file description" msgstr "" -#: stock/forms.py:194 +#: stock/forms.py:185 +msgid "Label" +msgstr "" + +#: stock/forms.py:186 stock/forms.py:237 msgid "Select test report template" msgstr "" -#: stock/forms.py:202 +#: stock/forms.py:245 msgid "Include stock items in sub locations" msgstr "" -#: stock/forms.py:235 +#: stock/forms.py:278 msgid "Destination stock location" msgstr "" -#: stock/forms.py:241 +#: stock/forms.py:284 msgid "Confirm movement of stock items" msgstr "" -#: stock/forms.py:243 +#: stock/forms.py:286 msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:208 +#: stock/models.py:209 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:250 +#: stock/models.py:245 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:260 stock/models.py:269 +#: stock/models.py:255 stock/models.py:264 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:261 +#: stock/models.py:256 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:282 +#: stock/models.py:277 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:314 +#: stock/models.py:316 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:322 stock/templates/stock/item_base.html:138 -msgid "Base Part" -msgstr "" - -#: stock/models.py:323 +#: stock/models.py:325 msgid "Base part" msgstr "" -#: stock/models.py:332 +#: stock/models.py:334 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:337 stock/templates/stock/stock_app_base.html:7 +#: stock/models.py:339 stock/templates/stock/stock_app_base.html:7 msgid "Stock Location" msgstr "" -#: stock/models.py:340 +#: stock/models.py:342 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:345 +#: stock/models.py:347 msgid "Installed In" msgstr "" -#: stock/models.py:348 +#: stock/models.py:350 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:364 +#: stock/models.py:366 msgid "Serial number for this item" msgstr "" -#: stock/models.py:376 +#: stock/models.py:378 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:380 +#: stock/models.py:382 msgid "Stock Quantity" msgstr "" -#: stock/models.py:389 +#: stock/models.py:391 msgid "Source Build" msgstr "" -#: stock/models.py:391 +#: stock/models.py:393 msgid "Build for this stock item" msgstr "" -#: stock/models.py:398 +#: stock/models.py:400 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:401 +#: stock/models.py:403 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:407 +#: stock/models.py:409 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:414 +#: stock/models.py:416 msgid "Destination Build Order" msgstr "" -#: stock/models.py:427 +#: stock/models.py:429 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:437 stock/templates/stock/item_notes.html:14 +#: stock/models.py:439 stock/templates/stock/item_notes.html:14 #: stock/templates/stock/item_notes.html:30 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:489 +#: stock/models.py:490 msgid "Assigned to Customer" msgstr "" -#: stock/models.py:491 +#: stock/models.py:492 msgid "Manually assigned to customer" msgstr "" -#: stock/models.py:656 +#: stock/models.py:505 +msgid "Returned from customer" +msgstr "" + +#: stock/models.py:507 +msgid "Returned to location" +msgstr "" + +#: stock/models.py:678 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:662 +#: stock/models.py:684 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:668 +#: stock/models.py:690 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:671 stock/models.py:674 +#: stock/models.py:693 stock/models.py:696 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:677 +#: stock/models.py:699 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:687 +#: stock/models.py:709 msgid "Serial numbers already exist: " msgstr "" -#: stock/models.py:712 +#: stock/models.py:734 msgid "Add serial number" msgstr "" -#: stock/models.py:715 +#: stock/models.py:737 #, python-brace-format msgid "Serialized {n} items" msgstr "" -#: stock/models.py:826 +#: stock/models.py:848 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1153 +#: stock/models.py:1175 msgid "Tracking entry title" msgstr "" -#: stock/models.py:1155 +#: stock/models.py:1177 msgid "Entry notes" msgstr "" -#: stock/models.py:1157 +#: stock/models.py:1179 msgid "Link to external page for further information" msgstr "" -#: stock/models.py:1217 +#: stock/models.py:1239 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1223 +#: stock/models.py:1245 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1240 +#: stock/models.py:1262 msgid "Test" msgstr "" -#: stock/models.py:1241 +#: stock/models.py:1263 msgid "Test name" msgstr "" -#: stock/models.py:1246 +#: stock/models.py:1268 msgid "Result" msgstr "" -#: stock/models.py:1247 templates/js/table_filters.html:53 +#: stock/models.py:1269 templates/js/table_filters.html:90 msgid "Test result" msgstr "" -#: stock/models.py:1253 +#: stock/models.py:1275 msgid "Test output value" msgstr "" -#: stock/models.py:1259 +#: stock/models.py:1281 msgid "Attachment" msgstr "" -#: stock/models.py:1260 +#: stock/models.py:1282 msgid "Test result attachment" msgstr "" -#: stock/models.py:1266 +#: stock/models.py:1288 msgid "Test notes" msgstr "" @@ -2945,20 +3011,8 @@ msgid "" "This stock item will be automatically deleted when all stock is depleted." msgstr "" -#: stock/templates/stock/item_base.html:78 -msgid "Barcode actions" -msgstr "" - -#: stock/templates/stock/item_base.html:80 -msgid "Show QR Code" -msgstr "" - -#: stock/templates/stock/item_base.html:81 -msgid "Print Label" -msgstr "" - -#: stock/templates/stock/item_base.html:83 templates/js/barcode.html:263 -#: templates/js/barcode.html:268 +#: stock/templates/stock/item_base.html:83 templates/js/barcode.html:283 +#: templates/js/barcode.html:288 msgid "Unlink Barcode" msgstr "" @@ -2966,11 +3020,12 @@ msgstr "" msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:92 +#: stock/templates/stock/item_base.html:91 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:95 templates/stock_table.html:14 +#: stock/templates/stock/item_base.html:95 +#: stock/templates/stock/location.html:33 templates/stock_table.html:14 msgid "Count stock" msgstr "" @@ -2986,67 +3041,76 @@ msgstr "" msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:105 -msgid "Stock actions" -msgstr "" - -#: stock/templates/stock/item_base.html:108 +#: stock/templates/stock/item_base.html:101 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:111 +#: stock/templates/stock/item_base.html:105 msgid "Assign to customer" msgstr "" +#: stock/templates/stock/item_base.html:108 +msgid "Return to stock" +msgstr "" + #: stock/templates/stock/item_base.html:114 +#: stock/templates/stock/location.html:30 +msgid "Stock actions" +msgstr "" + +#: stock/templates/stock/item_base.html:118 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:116 +#: stock/templates/stock/item_base.html:120 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:117 +#: stock/templates/stock/item_base.html:121 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:119 +#: stock/templates/stock/item_base.html:123 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:124 +#: stock/templates/stock/item_base.html:128 msgid "Generate test report" msgstr "" -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:132 +msgid "Print labels" +msgstr "" + +#: stock/templates/stock/item_base.html:140 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:173 msgid "Belongs To" msgstr "" -#: stock/templates/stock/item_base.html:175 +#: stock/templates/stock/item_base.html:195 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:182 +#: stock/templates/stock/item_base.html:202 msgid "Unique Identifier" msgstr "" -#: stock/templates/stock/item_base.html:223 +#: stock/templates/stock/item_base.html:230 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:248 +#: stock/templates/stock/item_base.html:255 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:253 +#: stock/templates/stock/item_base.html:260 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:257 +#: stock/templates/stock/item_base.html:264 msgid "No stocktake performed" msgstr "" @@ -3058,6 +3122,10 @@ msgstr "" msgid "This stock item does not have any child items" msgstr "" +#: stock/templates/stock/item_delete.html:9 +msgid "Are you sure you want to delete this stock item?" +msgstr "" + #: stock/templates/stock/item_tests.html:10 stock/templates/stock/tabs.html:13 msgid "Test Data" msgstr "" @@ -3078,50 +3146,62 @@ msgstr "" msgid "All stock items" msgstr "" -#: stock/templates/stock/location.html:22 -msgid "Count stock items" -msgstr "" - -#: stock/templates/stock/location.html:25 -msgid "Edit stock location" -msgstr "" - -#: stock/templates/stock/location.html:28 -msgid "Delete stock location" +#: stock/templates/stock/location.html:26 +msgid "Check-in Items" msgstr "" #: stock/templates/stock/location.html:37 +msgid "Location actions" +msgstr "" + +#: stock/templates/stock/location.html:39 +msgid "Edit location" +msgstr "" + +#: stock/templates/stock/location.html:40 +msgid "Delete location" +msgstr "" + +#: stock/templates/stock/location.html:48 msgid "Location Details" msgstr "" -#: stock/templates/stock/location.html:42 +#: stock/templates/stock/location.html:53 msgid "Location Path" msgstr "" -#: stock/templates/stock/location.html:47 +#: stock/templates/stock/location.html:58 msgid "Location Description" msgstr "" -#: stock/templates/stock/location.html:52 +#: stock/templates/stock/location.html:63 msgid "Sublocations" msgstr "" -#: stock/templates/stock/location.html:57 -#: stock/templates/stock/location.html:72 templates/stats.html:21 +#: stock/templates/stock/location.html:68 +#: stock/templates/stock/location.html:83 templates/stats.html:21 #: templates/stats.html:30 msgid "Stock Items" msgstr "" -#: stock/templates/stock/location.html:62 +#: stock/templates/stock/location.html:73 msgid "Stock Details" msgstr "" -#: stock/templates/stock/location.html:67 +#: stock/templates/stock/location.html:78 #: templates/InvenTree/search_stock_location.html:6 templates/stats.html:25 msgid "Stock Locations" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:934 +#: stock/templates/stock/location_delete.html:7 +msgid "Are you sure you want to delete this stock location?" +msgstr "" + +#: stock/templates/stock/stock_adjust.html:35 +msgid "Stock item is serialized and quantity cannot be adjusted" +msgstr "" + +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1052 msgid "Convert Stock Item" msgstr "" @@ -3137,6 +3217,10 @@ msgstr "" msgid "This action cannot be easily undone" msgstr "" +#: stock/templates/stock/tabs.html:6 +msgid "Tracking" +msgstr "" + #: stock/templates/stock/tabs.html:21 msgid "Builds" msgstr "" @@ -3145,190 +3229,214 @@ msgstr "" msgid "Children" msgstr "" -#: stock/views.py:113 +#: stock/views.py:114 msgid "Edit Stock Location" msgstr "" -#: stock/views.py:137 +#: stock/views.py:138 msgid "Stock Location QR code" msgstr "" -#: stock/views.py:155 +#: stock/views.py:156 msgid "Add Stock Item Attachment" msgstr "" -#: stock/views.py:200 +#: stock/views.py:201 msgid "Edit Stock Item Attachment" msgstr "" -#: stock/views.py:216 +#: stock/views.py:217 msgid "Delete Stock Item Attachment" msgstr "" -#: stock/views.py:232 +#: stock/views.py:233 msgid "Assign to Customer" msgstr "" #: stock/views.py:270 -msgid "Delete All Test Data" +msgid "Return to Stock" msgstr "" -#: stock/views.py:285 -msgid "Confirm test data deletion" +#: stock/views.py:289 +msgid "Specify a valid location" +msgstr "" + +#: stock/views.py:293 +msgid "Stock item returned from customer" msgstr "" #: stock/views.py:305 +msgid "Select Label Template" +msgstr "" + +#: stock/views.py:326 +msgid "Select valid label" +msgstr "" + +#: stock/views.py:388 +msgid "Delete All Test Data" +msgstr "" + +#: stock/views.py:403 +msgid "Confirm test data deletion" +msgstr "" + +#: stock/views.py:423 msgid "Add Test Result" msgstr "" -#: stock/views.py:342 +#: stock/views.py:460 msgid "Edit Test Result" msgstr "" -#: stock/views.py:359 +#: stock/views.py:477 msgid "Delete Test Result" msgstr "" -#: stock/views.py:370 +#: stock/views.py:488 msgid "Select Test Report Template" msgstr "" -#: stock/views.py:384 +#: stock/views.py:502 msgid "Select valid template" msgstr "" -#: stock/views.py:436 +#: stock/views.py:554 msgid "Stock Export Options" msgstr "" -#: stock/views.py:556 +#: stock/views.py:674 msgid "Stock Item QR Code" msgstr "" -#: stock/views.py:579 +#: stock/views.py:697 msgid "Adjust Stock" msgstr "" -#: stock/views.py:688 +#: stock/views.py:806 msgid "Move Stock Items" msgstr "" -#: stock/views.py:689 +#: stock/views.py:807 msgid "Count Stock Items" msgstr "" -#: stock/views.py:690 +#: stock/views.py:808 msgid "Remove From Stock" msgstr "" -#: stock/views.py:691 +#: stock/views.py:809 msgid "Add Stock Items" msgstr "" -#: stock/views.py:692 +#: stock/views.py:810 msgid "Delete Stock Items" msgstr "" -#: stock/views.py:720 +#: stock/views.py:838 msgid "Must enter integer value" msgstr "" -#: stock/views.py:725 +#: stock/views.py:843 msgid "Quantity must be positive" msgstr "" -#: stock/views.py:732 +#: stock/views.py:850 #, python-brace-format msgid "Quantity must not exceed {x}" msgstr "" -#: stock/views.py:740 +#: stock/views.py:858 msgid "Confirm stock adjustment" msgstr "" -#: stock/views.py:811 +#: stock/views.py:929 #, python-brace-format msgid "Added stock to {n} items" msgstr "" -#: stock/views.py:826 +#: stock/views.py:944 #, python-brace-format msgid "Removed stock from {n} items" msgstr "" -#: stock/views.py:839 +#: stock/views.py:957 #, python-brace-format msgid "Counted stock for {n} items" msgstr "" -#: stock/views.py:867 +#: stock/views.py:985 msgid "No items were moved" msgstr "" -#: stock/views.py:870 +#: stock/views.py:988 #, python-brace-format msgid "Moved {n} items to {dest}" msgstr "" -#: stock/views.py:889 +#: stock/views.py:1007 #, python-brace-format msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:901 +#: stock/views.py:1019 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:961 +#: stock/views.py:1079 msgid "Create new Stock Location" msgstr "" -#: stock/views.py:982 +#: stock/views.py:1100 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1074 +#: stock/views.py:1192 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1167 +#: stock/views.py:1285 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1240 +#: stock/views.py:1358 msgid "Invalid quantity" msgstr "" -#: stock/views.py:1247 +#: stock/views.py:1361 +msgid "Quantity cannot be less than zero" +msgstr "" + +#: stock/views.py:1365 msgid "Invalid part selection" msgstr "" -#: stock/views.py:1296 +#: stock/views.py:1414 #, python-brace-format msgid "Created {n} new stock items" msgstr "" -#: stock/views.py:1315 stock/views.py:1331 +#: stock/views.py:1433 stock/views.py:1449 msgid "Created new stock item" msgstr "" -#: stock/views.py:1350 +#: stock/views.py:1468 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1363 +#: stock/views.py:1481 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1374 +#: stock/views.py:1492 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1391 +#: stock/views.py:1509 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1400 +#: stock/views.py:1518 msgid "Add Stock Tracking Entry" msgstr "" @@ -3416,39 +3524,83 @@ msgstr "" msgid "Delete attachment" msgstr "" -#: templates/js/barcode.html:28 +#: templates/js/barcode.html:8 msgid "Scan barcode data here using wedge scanner" msgstr "" -#: templates/js/barcode.html:34 +#: templates/js/barcode.html:12 msgid "Barcode" msgstr "" -#: templates/js/barcode.html:42 +#: templates/js/barcode.html:20 msgid "Enter barcode data" msgstr "" -#: templates/js/barcode.html:140 -msgid "Scan barcode data below" -msgstr "" - -#: templates/js/barcode.html:195 templates/js/barcode.html:243 -msgid "Unknown response from server" -msgstr "" - -#: templates/js/barcode.html:198 templates/js/barcode.html:247 +#: templates/js/barcode.html:42 msgid "Invalid server response" msgstr "" -#: templates/js/barcode.html:265 +#: templates/js/barcode.html:143 +msgid "Scan barcode data below" +msgstr "" + +#: templates/js/barcode.html:217 templates/js/barcode.html:263 +msgid "Unknown response from server" +msgstr "" + +#: templates/js/barcode.html:239 +msgid "Link Barcode to Stock Item" +msgstr "" + +#: templates/js/barcode.html:285 msgid "" "This will remove the association between this stock item and the barcode" msgstr "" -#: templates/js/barcode.html:271 +#: templates/js/barcode.html:291 msgid "Unlink" msgstr "" +#: templates/js/barcode.html:350 +msgid "Remove stock item" +msgstr "" + +#: templates/js/barcode.html:397 +msgid "Enter notes" +msgstr "" + +#: templates/js/barcode.html:399 +msgid "Enter optional notes for stock transfer" +msgstr "" + +#: templates/js/barcode.html:404 +msgid "Check Stock Items into Location" +msgstr "" + +#: templates/js/barcode.html:408 +msgid "Check In" +msgstr "" + +#: templates/js/barcode.html:466 +msgid "Server error" +msgstr "" + +#: templates/js/barcode.html:485 +msgid "Stock Item already scanned" +msgstr "" + +#: templates/js/barcode.html:489 +msgid "Stock Item already in this location" +msgstr "" + +#: templates/js/barcode.html:496 +msgid "Added stock item" +msgstr "" + +#: templates/js/barcode.html:503 +msgid "Barcode does not match Stock Item" +msgstr "" + #: templates/js/bom.html:143 msgid "Open subassembly" msgstr "" @@ -3509,7 +3661,7 @@ msgstr "" msgid "No purchase orders found" msgstr "" -#: templates/js/order.html:170 templates/js/stock.html:605 +#: templates/js/order.html:170 templates/js/stock.html:625 msgid "Date" msgstr "" @@ -3521,7 +3673,7 @@ msgstr "" msgid "Shipment Date" msgstr "" -#: templates/js/part.html:106 templates/js/stock.html:403 +#: templates/js/part.html:106 templates/js/stock.html:406 msgid "Select" msgstr "" @@ -3537,7 +3689,7 @@ msgstr "" msgid "No category" msgstr "" -#: templates/js/part.html:214 templates/js/table_filters.html:130 +#: templates/js/part.html:214 templates/js/table_filters.html:167 msgid "Low stock" msgstr "" @@ -3561,11 +3713,11 @@ msgstr "" msgid "No test templates matching query" msgstr "" -#: templates/js/part.html:387 templates/js/stock.html:62 +#: templates/js/part.html:387 templates/js/stock.html:63 msgid "Edit test result" msgstr "" -#: templates/js/part.html:388 templates/js/stock.html:63 +#: templates/js/part.html:388 templates/js/stock.html:64 msgid "Delete test result" msgstr "" @@ -3573,131 +3725,175 @@ msgstr "" msgid "This test is defined for a parent part" msgstr "" -#: templates/js/stock.html:25 +#: templates/js/stock.html:26 msgid "PASS" msgstr "" -#: templates/js/stock.html:27 +#: templates/js/stock.html:28 msgid "FAIL" msgstr "" -#: templates/js/stock.html:32 +#: templates/js/stock.html:33 msgid "NO RESULT" msgstr "" -#: templates/js/stock.html:58 +#: templates/js/stock.html:59 msgid "Add test result" msgstr "" -#: templates/js/stock.html:76 +#: templates/js/stock.html:77 msgid "No test results found" msgstr "" -#: templates/js/stock.html:117 +#: templates/js/stock.html:118 msgid "Test Date" msgstr "" -#: templates/js/stock.html:258 +#: templates/js/stock.html:261 msgid "No stock items matching query" msgstr "" -#: templates/js/stock.html:355 templates/js/stock.html:370 +#: templates/js/stock.html:358 templates/js/stock.html:373 msgid "Undefined location" msgstr "" -#: templates/js/stock.html:467 -msgid "StockItem has been allocated" +#: templates/js/stock.html:464 +msgid "Stock item has been allocated" +msgstr "" + +#: templates/js/stock.html:468 +msgid "Stock item has been assigned to customer" +msgstr "" + +#: templates/js/stock.html:470 +msgid "Stock item was assigned to a build order" msgstr "" #: templates/js/stock.html:472 -msgid "StockItem is lost" +msgid "Stock item was assigned to a sales order" msgstr "" -#: templates/js/stock.html:500 +#: templates/js/stock.html:479 +msgid "Stock item has been rejected" +msgstr "" + +#: templates/js/stock.html:483 +msgid "Stock item is lost" +msgstr "" + +#: templates/js/stock.html:487 templates/js/table_filters.html:52 +msgid "Depleted" +msgstr "" + +#: templates/js/stock.html:516 +msgid "Shipped to customer" +msgstr "" + +#: templates/js/stock.html:519 msgid "No stock location set" msgstr "" -#: templates/js/stock.html:671 +#: templates/js/stock.html:691 msgid "No user information" msgstr "" -#: templates/js/table_filters.html:19 -msgid "Include sublocations" +#: templates/js/table_filters.html:19 templates/js/table_filters.html:67 +msgid "Is Serialized" msgstr "" -#: templates/js/table_filters.html:20 -msgid "Include stock in sublocations" -msgstr "" - -#: templates/js/table_filters.html:24 -msgid "Active parts" -msgstr "" - -#: templates/js/table_filters.html:25 -msgid "Show stock for active parts" -msgstr "" - -#: templates/js/table_filters.html:29 templates/js/table_filters.html:30 -msgid "Stock status" -msgstr "" - -#: templates/js/table_filters.html:34 -msgid "Is allocated" -msgstr "" - -#: templates/js/table_filters.html:35 -msgid "Item has been alloacted" -msgstr "" - -#: templates/js/table_filters.html:38 +#: templates/js/table_filters.html:22 templates/js/table_filters.html:70 msgid "Serial number GTE" msgstr "" -#: templates/js/table_filters.html:39 +#: templates/js/table_filters.html:23 templates/js/table_filters.html:71 msgid "Serial number greater than or equal to" msgstr "" -#: templates/js/table_filters.html:42 +#: templates/js/table_filters.html:26 templates/js/table_filters.html:74 msgid "Serial number LTE" msgstr "" -#: templates/js/table_filters.html:43 +#: templates/js/table_filters.html:27 templates/js/table_filters.html:75 msgid "Serial number less than or equal to" msgstr "" -#: templates/js/table_filters.html:72 +#: templates/js/table_filters.html:37 +msgid "Active parts" +msgstr "" + +#: templates/js/table_filters.html:38 +msgid "Show stock for active parts" +msgstr "" + +#: templates/js/table_filters.html:42 +msgid "Is allocated" +msgstr "" + +#: templates/js/table_filters.html:43 +msgid "Item has been alloacted" +msgstr "" + +#: templates/js/table_filters.html:47 +msgid "Include sublocations" +msgstr "" + +#: templates/js/table_filters.html:48 +msgid "Include stock in sublocations" +msgstr "" + +#: templates/js/table_filters.html:53 +msgid "Show stock items which are depleted" +msgstr "" + +#: templates/js/table_filters.html:58 +msgid "Show items which are in stock" +msgstr "" + +#: templates/js/table_filters.html:62 +msgid "Sent to customer" +msgstr "" + +#: templates/js/table_filters.html:63 +msgid "Show items which have been assigned to a customer" +msgstr "" + +#: templates/js/table_filters.html:79 templates/js/table_filters.html:80 +msgid "Stock status" +msgstr "" + +#: templates/js/table_filters.html:109 msgid "Build status" msgstr "" -#: templates/js/table_filters.html:84 templates/js/table_filters.html:97 +#: templates/js/table_filters.html:121 templates/js/table_filters.html:134 msgid "Order status" msgstr "" -#: templates/js/table_filters.html:89 templates/js/table_filters.html:102 +#: templates/js/table_filters.html:126 templates/js/table_filters.html:139 msgid "Outstanding" msgstr "" -#: templates/js/table_filters.html:112 +#: templates/js/table_filters.html:149 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.html:113 +#: templates/js/table_filters.html:150 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.html:118 +#: templates/js/table_filters.html:155 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.html:126 +#: templates/js/table_filters.html:163 msgid "Stock available" msgstr "" -#: templates/js/table_filters.html:142 +#: templates/js/table_filters.html:179 msgid "Starred" msgstr "" -#: templates/js/table_filters.html:154 +#: templates/js/table_filters.html:191 msgid "Purchasable" msgstr "" diff --git a/InvenTree/locale/es/LC_MESSAGES/django.po b/InvenTree/locale/es/LC_MESSAGES/django.po index c539fbcae5..dda559ee7e 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: 2020-06-12 00:43+0000\n" +"POT-Creation-Date: 2020-08-16 02:11+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -78,7 +78,7 @@ msgstr "" msgid "File comment" msgstr "" -#: InvenTree/models.py:68 templates/js/stock.html:662 +#: InvenTree/models.py:68 templates/js/stock.html:682 msgid "User" msgstr "" @@ -90,24 +90,24 @@ msgstr "" msgid "Description (optional)" msgstr "" -#: InvenTree/settings.py:330 +#: InvenTree/settings.py:335 msgid "English" msgstr "" -#: InvenTree/settings.py:331 +#: InvenTree/settings.py:336 msgid "German" msgstr "" -#: InvenTree/settings.py:332 +#: InvenTree/settings.py:337 msgid "French" msgstr "" -#: InvenTree/settings.py:333 +#: InvenTree/settings.py:338 msgid "Polish" msgstr "" #: InvenTree/status_codes.py:94 InvenTree/status_codes.py:135 -#: InvenTree/status_codes.py:235 +#: InvenTree/status_codes.py:222 msgid "Pending" msgstr "" @@ -115,59 +115,50 @@ msgstr "" msgid "Placed" msgstr "" -#: InvenTree/status_codes.py:96 InvenTree/status_codes.py:238 +#: InvenTree/status_codes.py:96 InvenTree/status_codes.py:225 msgid "Complete" msgstr "" #: InvenTree/status_codes.py:97 InvenTree/status_codes.py:137 -#: InvenTree/status_codes.py:237 +#: InvenTree/status_codes.py:224 msgid "Cancelled" msgstr "" #: InvenTree/status_codes.py:98 InvenTree/status_codes.py:138 -#: InvenTree/status_codes.py:179 +#: InvenTree/status_codes.py:175 msgid "Lost" msgstr "" #: InvenTree/status_codes.py:99 InvenTree/status_codes.py:139 -#: InvenTree/status_codes.py:181 +#: InvenTree/status_codes.py:177 msgid "Returned" msgstr "" -#: InvenTree/status_codes.py:136 InvenTree/status_codes.py:182 -#: order/templates/order/sales_order_base.html:98 +#: InvenTree/status_codes.py:136 order/templates/order/sales_order_base.html:98 msgid "Shipped" msgstr "" -#: InvenTree/status_codes.py:175 +#: InvenTree/status_codes.py:171 msgid "OK" msgstr "" -#: InvenTree/status_codes.py:176 +#: InvenTree/status_codes.py:172 msgid "Attention needed" msgstr "" -#: InvenTree/status_codes.py:177 +#: InvenTree/status_codes.py:173 msgid "Damaged" msgstr "" -#: InvenTree/status_codes.py:178 +#: InvenTree/status_codes.py:174 msgid "Destroyed" msgstr "" -#: InvenTree/status_codes.py:180 +#: InvenTree/status_codes.py:176 msgid "Rejected" msgstr "" -#: InvenTree/status_codes.py:183 -msgid "Used for Build" -msgstr "" - -#: InvenTree/status_codes.py:184 -msgid "Installed in Stock Item" -msgstr "" - -#: InvenTree/status_codes.py:236 build/templates/build/allocate.html:349 +#: InvenTree/status_codes.py:223 build/templates/build/allocate.html:349 #: order/templates/order/sales_order_detail.html:220 #: part/templates/part/tabs.html:23 templates/js/build.html:120 msgid "Allocated" @@ -250,7 +241,7 @@ msgstr "" msgid "Serial numbers" msgstr "" -#: build/forms.py:64 stock/forms.py:93 +#: build/forms.py:64 stock/forms.py:105 msgid "Enter unique serial numbers (or leave blank)" msgstr "" @@ -286,9 +277,10 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:145 #: order/templates/order/receive_parts.html:19 part/models.py:240 #: part/templates/part/part_app_base.html:7 -#: part/templates/part/set_category.html:13 templates/js/bom.html:135 -#: templates/js/build.html:41 templates/js/company.html:109 -#: templates/js/part.html:120 templates/js/stock.html:422 +#: part/templates/part/set_category.html:13 templates/js/barcode.html:336 +#: templates/js/bom.html:135 templates/js/build.html:41 +#: templates/js/company.html:109 templates/js/part.html:120 +#: templates/js/stock.html:425 msgid "Part" msgstr "" @@ -322,7 +314,7 @@ msgstr "" msgid "Number of parts to build" msgstr "" -#: build/models.py:128 part/templates/part/part_base.html:141 +#: build/models.py:128 part/templates/part/part_base.html:139 msgid "Build Status" msgstr "" @@ -330,7 +322,7 @@ msgstr "" msgid "Build status code" msgstr "" -#: build/models.py:136 stock/models.py:374 +#: build/models.py:136 stock/models.py:376 msgid "Batch Code" msgstr "" @@ -341,22 +333,22 @@ msgstr "" #: build/models.py:155 build/templates/build/detail.html:55 #: company/templates/company/supplier_part_base.html:60 #: company/templates/company/supplier_part_detail.html:24 -#: part/templates/part/detail.html:74 part/templates/part/part_base.html:88 -#: stock/models.py:368 stock/templates/stock/item_base.html:230 +#: part/templates/part/detail.html:74 part/templates/part/part_base.html:86 +#: stock/models.py:370 stock/templates/stock/item_base.html:237 msgid "External Link" msgstr "" -#: build/models.py:156 stock/models.py:370 +#: build/models.py:156 stock/models.py:372 msgid "Link to external URL" msgstr "" -#: build/models.py:160 build/templates/build/tabs.html:14 company/models.py:302 +#: build/models.py:160 build/templates/build/tabs.html:14 company/models.py:310 #: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:15 #: order/templates/order/purchase_order_detail.html:200 -#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:73 -#: stock/models.py:436 stock/models.py:1265 stock/templates/stock/tabs.html:26 -#: templates/js/bom.html:229 templates/js/stock.html:113 -#: templates/js/stock.html:506 +#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:64 +#: stock/models.py:438 stock/models.py:1287 stock/templates/stock/tabs.html:26 +#: templates/js/barcode.html:391 templates/js/bom.html:229 +#: templates/js/stock.html:114 templates/js/stock.html:526 msgid "Notes" msgstr "" @@ -386,15 +378,15 @@ msgstr "" msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:512 +#: build/models.py:511 msgid "Build to allocate parts" msgstr "" -#: build/models.py:519 +#: build/models.py:518 msgid "Stock Item to allocate to build" msgstr "" -#: build/models.py:532 +#: build/models.py:531 msgid "Stock quantity to allocate to build" msgstr "" @@ -421,8 +413,8 @@ msgstr "" #: build/templates/build/allocate.html:161 #: order/templates/order/sales_order_detail.html:68 -#: order/templates/order/sales_order_detail.html:150 stock/models.py:362 -#: stock/templates/stock/item_base.html:189 +#: order/templates/order/sales_order_detail.html:150 stock/models.py:364 +#: stock/templates/stock/item_base.html:153 msgid "Serial Number" msgstr "" @@ -439,16 +431,18 @@ msgstr "" #: part/templates/part/allocation.html:49 #: stock/templates/stock/item_base.html:26 #: stock/templates/stock/item_base.html:32 -#: stock/templates/stock/item_base.html:195 -#: stock/templates/stock/stock_adjust.html:18 templates/js/bom.html:172 -#: templates/js/build.html:52 templates/js/stock.html:653 +#: stock/templates/stock/item_base.html:159 +#: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338 +#: templates/js/bom.html:172 templates/js/build.html:52 +#: templates/js/stock.html:673 msgid "Quantity" msgstr "" #: build/templates/build/allocate.html:177 #: build/templates/build/auto_allocate.html:20 -#: stock/templates/stock/item_base.html:171 -#: stock/templates/stock/stock_adjust.html:17 templates/js/stock.html:493 +#: stock/templates/stock/item_base.html:191 +#: stock/templates/stock/stock_adjust.html:17 templates/js/barcode.html:337 +#: templates/js/stock.html:508 msgid "Location" msgstr "" @@ -474,7 +468,7 @@ msgstr "" #: templates/js/bom.html:157 templates/js/company.html:60 #: templates/js/order.html:157 templates/js/order.html:230 #: templates/js/part.html:176 templates/js/part.html:355 -#: templates/js/stock.html:443 templates/js/stock.html:634 +#: templates/js/stock.html:440 templates/js/stock.html:654 msgid "Description" msgstr "" @@ -484,8 +478,8 @@ msgstr "" msgid "Reference" msgstr "" -#: build/templates/build/allocate.html:338 part/models.py:1260 -#: templates/js/part.html:359 templates/js/table_filters.html:63 +#: build/templates/build/allocate.html:338 part/models.py:1270 +#: templates/js/part.html:359 templates/js/table_filters.html:100 msgid "Required" msgstr "" @@ -528,7 +522,7 @@ msgstr "" #: build/templates/build/build_base.html:8 #: build/templates/build/build_base.html:34 #: build/templates/build/complete.html:6 -#: stock/templates/stock/item_base.html:209 templates/js/build.html:33 +#: stock/templates/stock/item_base.html:216 templates/js/build.html:33 #: templates/navbar.html:12 msgid "Build" msgstr "" @@ -548,9 +542,9 @@ msgstr "" #: build/templates/build/build_base.html:80 #: build/templates/build/detail.html:42 #: order/templates/order/receive_parts.html:24 -#: stock/templates/stock/item_base.html:262 templates/js/build.html:57 -#: templates/js/order.html:162 templates/js/order.html:235 -#: templates/js/stock.html:480 +#: stock/templates/stock/item_base.html:269 templates/js/barcode.html:42 +#: templates/js/build.html:57 templates/js/order.html:162 +#: templates/js/order.html:235 templates/js/stock.html:495 msgid "Status" msgstr "" @@ -560,7 +554,7 @@ msgstr "" #: order/templates/order/sales_order_notes.html:10 #: order/templates/order/sales_order_ship.html:25 #: part/templates/part/allocation.html:27 -#: stock/templates/stock/item_base.html:159 templates/js/order.html:209 +#: stock/templates/stock/item_base.html:179 templates/js/order.html:209 msgid "Sales Order" msgstr "" @@ -627,7 +621,7 @@ msgid "Stock can be taken from any available location." msgstr "" #: build/templates/build/detail.html:48 -#: stock/templates/stock/item_base.html:202 templates/js/stock.html:488 +#: stock/templates/stock/item_base.html:209 templates/js/stock.html:503 msgid "Batch" msgstr "" @@ -730,7 +724,7 @@ msgstr "" msgid "Confirm unallocation of build stock" msgstr "" -#: build/views.py:162 stock/views.py:286 +#: build/views.py:162 stock/views.py:404 msgid "Check the confirmation box" msgstr "" @@ -738,7 +732,7 @@ msgstr "" msgid "Complete Build" msgstr "" -#: build/views.py:201 stock/views.py:1118 stock/views.py:1232 +#: build/views.py:201 stock/views.py:1236 stock/views.py:1350 msgid "Next available serial number is" msgstr "" @@ -754,7 +748,7 @@ msgstr "" msgid "Invalid location selected" msgstr "" -#: build/views.py:300 stock/views.py:1268 +#: build/views.py:300 stock/views.py:1386 #, python-brace-format msgid "The following serial numbers already exist: ({sn})" msgstr "" @@ -847,83 +841,113 @@ msgstr "" msgid "Delete Currency" msgstr "" -#: company/models.py:83 +#: company/models.py:86 company/models.py:87 msgid "Company name" msgstr "" -#: company/models.py:85 +#: company/models.py:89 +msgid "Company description" +msgstr "" + +#: company/models.py:89 msgid "Description of the company" msgstr "" -#: company/models.py:87 +#: company/models.py:91 company/templates/company/company_base.html:48 +#: templates/js/company.html:65 +msgid "Website" +msgstr "" + +#: company/models.py:91 msgid "Company website URL" msgstr "" -#: company/models.py:90 -msgid "Company address" -msgstr "" - -#: company/models.py:93 -msgid "Contact phone number" +#: company/models.py:94 company/templates/company/company_base.html:55 +msgid "Address" msgstr "" #: company/models.py:95 -msgid "Contact email address" +msgid "Company address" msgstr "" #: company/models.py:98 +msgid "Phone number" +msgstr "" + +#: company/models.py:99 +msgid "Contact phone number" +msgstr "" + +#: company/models.py:101 company/templates/company/company_base.html:69 +msgid "Email" +msgstr "" + +#: company/models.py:101 +msgid "Contact email address" +msgstr "" + +#: company/models.py:104 company/templates/company/company_base.html:76 +msgid "Contact" +msgstr "" + +#: company/models.py:105 msgid "Point of contact" msgstr "" -#: company/models.py:100 +#: company/models.py:107 msgid "Link to external company information" msgstr "" -#: company/models.py:112 +#: company/models.py:119 msgid "Do you sell items to this company?" msgstr "" -#: company/models.py:114 +#: company/models.py:121 msgid "Do you purchase items from this company?" msgstr "" -#: company/models.py:116 +#: company/models.py:123 msgid "Does this company manufacture parts?" msgstr "" -#: company/models.py:276 +#: company/models.py:279 stock/models.py:324 +#: stock/templates/stock/item_base.html:145 +msgid "Base Part" +msgstr "" + +#: company/models.py:284 msgid "Select part" msgstr "" -#: company/models.py:282 +#: company/models.py:290 msgid "Select supplier" msgstr "" -#: company/models.py:285 +#: company/models.py:293 msgid "Supplier stock keeping unit" msgstr "" -#: company/models.py:292 +#: company/models.py:300 msgid "Select manufacturer" msgstr "" -#: company/models.py:296 +#: company/models.py:304 msgid "Manufacturer part number" msgstr "" -#: company/models.py:298 +#: company/models.py:306 msgid "URL for external supplier part link" msgstr "" -#: company/models.py:300 +#: company/models.py:308 msgid "Supplier part description" msgstr "" -#: company/models.py:304 +#: company/models.py:312 msgid "Minimum charge (e.g. stocking fee)" msgstr "" -#: company/models.py:306 +#: company/models.py:314 msgid "Part packaging" msgstr "" @@ -942,26 +966,10 @@ msgstr "" msgid "Company Details" msgstr "" -#: company/templates/company/company_base.html:48 templates/js/company.html:65 -msgid "Website" -msgstr "" - -#: company/templates/company/company_base.html:55 -msgid "Address" -msgstr "" - #: company/templates/company/company_base.html:62 msgid "Phone" msgstr "" -#: company/templates/company/company_base.html:69 -msgid "Email" -msgstr "" - -#: company/templates/company/company_base.html:76 -msgid "Contact" -msgstr "" - #: company/templates/company/detail.html:16 #: company/templates/company/supplier_part_base.html:76 #: company/templates/company/supplier_part_detail.html:30 @@ -974,14 +982,14 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:21 order/models.py:148 #: order/templates/order/order_base.html:74 #: order/templates/order/order_wizard/select_pos.html:30 -#: stock/templates/stock/item_base.html:237 templates/js/company.html:52 +#: stock/templates/stock/item_base.html:244 templates/js/company.html:52 #: templates/js/company.html:134 templates/js/order.html:144 msgid "Supplier" msgstr "" #: company/templates/company/detail.html:26 order/models.py:314 -#: order/templates/order/sales_order_base.html:73 stock/models.py:357 -#: stock/models.py:358 stock/templates/stock/item_base.html:146 +#: order/templates/order/sales_order_base.html:73 stock/models.py:359 +#: stock/models.py:360 stock/templates/stock/item_base.html:166 #: templates/js/company.html:44 templates/js/order.html:217 msgid "Customer" msgstr "" @@ -992,7 +1000,7 @@ msgstr "" #: company/templates/company/detail_part.html:13 #: order/templates/order/purchase_order_detail.html:67 -#: part/templates/part/stock.html:82 part/templates/part/supplier.html:12 +#: part/templates/part/stock.html:81 part/templates/part/supplier.html:12 msgid "New Supplier Part" msgstr "" @@ -1006,7 +1014,7 @@ msgid "Delete Parts" msgstr "" #: company/templates/company/detail_part.html:43 -#: part/templates/part/stock.html:76 +#: part/templates/part/stock.html:75 msgid "New Part" msgstr "" @@ -1036,9 +1044,9 @@ msgstr "" msgid "Supplier Stock" msgstr "" -#: company/templates/company/detail_stock.html:34 +#: company/templates/company/detail_stock.html:35 #: company/templates/company/supplier_part_stock.html:33 -#: part/templates/part/stock.html:54 templates/stock_table.html:5 +#: part/templates/part/stock.html:53 templates/stock_table.html:5 msgid "Export" msgstr "" @@ -1094,8 +1102,8 @@ msgid "New Sales Order" msgstr "" #: company/templates/company/supplier_part_base.html:6 -#: company/templates/company/supplier_part_base.html:19 stock/models.py:331 -#: stock/templates/stock/item_base.html:242 templates/js/company.html:150 +#: company/templates/company/supplier_part_base.html:19 stock/models.py:333 +#: stock/templates/stock/item_base.html:249 templates/js/company.html:150 msgid "Supplier Part" msgstr "" @@ -1178,12 +1186,12 @@ msgstr "" #: company/templates/company/supplier_part_stock.html:56 #: order/templates/order/purchase_order_detail.html:38 #: order/templates/order/purchase_order_detail.html:118 -#: part/templates/part/stock.html:91 +#: part/templates/part/stock.html:90 msgid "New Location" msgstr "" #: company/templates/company/supplier_part_stock.html:57 -#: part/templates/part/stock.html:92 +#: part/templates/part/stock.html:91 msgid "Create New Location" msgstr "" @@ -1194,7 +1202,7 @@ msgstr "" #: company/templates/company/supplier_part_tabs.html:8 #: company/templates/company/tabs.html:12 part/templates/part/tabs.html:18 #: stock/templates/stock/location.html:12 templates/js/part.html:203 -#: templates/js/stock.html:451 templates/navbar.html:11 +#: templates/js/stock.html:448 templates/navbar.html:11 msgid "Stock" msgstr "" @@ -1274,7 +1282,7 @@ msgstr "" msgid "Edit Supplier Part" msgstr "" -#: company/views.py:265 part/templates/part/stock.html:83 +#: company/views.py:265 part/templates/part/stock.html:82 msgid "Create new Supplier Part" msgstr "" @@ -1294,6 +1302,22 @@ msgstr "" msgid "Delete Price Break" msgstr "" +#: label/models.py:55 +msgid "Label name" +msgstr "" + +#: label/models.py:58 +msgid "Label description" +msgstr "" + +#: label/models.py:63 +msgid "Label template file" +msgstr "" + +#: label/models.py:69 +msgid "Query filters (comma-separated list of key=value pairs" +msgstr "" + #: order/forms.py:24 msgid "Place order" msgstr "" @@ -1344,7 +1368,7 @@ msgid "Supplier order reference code" msgstr "" #: order/models.py:185 order/models.py:259 part/views.py:1167 -#: stock/models.py:243 stock/models.py:665 stock/views.py:1243 +#: stock/models.py:238 stock/models.py:687 msgid "Quantity must be greater than zero" msgstr "" @@ -1378,7 +1402,7 @@ msgstr "" #: order/models.py:466 order/templates/order/order_base.html:9 #: order/templates/order/order_base.html:23 -#: stock/templates/stock/item_base.html:216 templates/js/order.html:136 +#: stock/templates/stock/item_base.html:223 templates/js/order.html:136 msgid "Purchase Order" msgstr "" @@ -1508,7 +1532,7 @@ msgid "Purchase Order Attachments" msgstr "" #: order/templates/order/po_tabs.html:8 order/templates/order/so_tabs.html:16 -#: part/templates/part/tabs.html:70 stock/templates/stock/tabs.html:32 +#: part/templates/part/tabs.html:61 stock/templates/stock/tabs.html:32 msgid "Attachments" msgstr "" @@ -1524,7 +1548,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:39 #: order/templates/order/purchase_order_detail.html:119 -#: stock/templates/stock/location.html:17 +#: stock/templates/stock/location.html:16 msgid "Create new stock location" msgstr "" @@ -1563,7 +1587,7 @@ msgid "Select parts to receive against this order" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:131 templates/js/part.html:219 +#: part/templates/part/part_base.html:129 templates/js/part.html:219 msgid "On Order" msgstr "" @@ -1655,7 +1679,7 @@ msgstr "" msgid "Add Purchase Order Attachment" msgstr "" -#: order/views.py:102 order/views.py:149 part/views.py:85 stock/views.py:166 +#: order/views.py:102 order/views.py:149 part/views.py:85 stock/views.py:167 msgid "Added attachment" msgstr "" @@ -1675,7 +1699,7 @@ msgstr "" msgid "Delete Attachment" msgstr "" -#: order/views.py:222 order/views.py:236 stock/views.py:222 +#: order/views.py:222 order/views.py:236 stock/views.py:223 msgid "Deleted attachment" msgstr "" @@ -1808,11 +1832,11 @@ msgstr "" msgid "Error reading BOM file (incorrect row size)" msgstr "" -#: part/forms.py:55 stock/forms.py:200 +#: part/forms.py:55 stock/forms.py:243 msgid "File Format" msgstr "" -#: part/forms.py:55 stock/forms.py:200 +#: part/forms.py:55 stock/forms.py:243 msgid "Select output file format" msgstr "" @@ -1860,207 +1884,220 @@ msgstr "" msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:427 +#: part/models.py:74 part/templates/part/part_app_base.html:9 +msgid "Part Category" +msgstr "" + +#: part/models.py:75 part/templates/part/category.html:13 +#: part/templates/part/category.html:78 templates/stats.html:12 +msgid "Part Categories" +msgstr "" + +#: part/models.py:428 msgid "Part must be unique for name, IPN and revision" msgstr "" -#: part/models.py:442 part/templates/part/detail.html:19 +#: part/models.py:443 part/templates/part/detail.html:19 msgid "Part name" msgstr "" -#: part/models.py:446 +#: part/models.py:447 msgid "Is this part a template part?" msgstr "" -#: part/models.py:455 +#: part/models.py:456 msgid "Is this part a variant of another part?" msgstr "" -#: part/models.py:457 +#: part/models.py:458 msgid "Part description" msgstr "" -#: part/models.py:459 +#: part/models.py:460 msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:464 +#: part/models.py:465 msgid "Part category" msgstr "" -#: part/models.py:466 +#: part/models.py:467 msgid "Internal Part Number" msgstr "" -#: part/models.py:468 +#: part/models.py:469 msgid "Part revision or version number" msgstr "" -#: part/models.py:470 +#: part/models.py:471 msgid "Link to extenal URL" msgstr "" -#: part/models.py:482 +#: part/models.py:483 msgid "Where is this item normally stored?" msgstr "" -#: part/models.py:526 +#: part/models.py:527 msgid "Default supplier part" msgstr "" -#: part/models.py:529 +#: part/models.py:530 msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:531 +#: part/models.py:532 msgid "Stock keeping units for this part" msgstr "" -#: part/models.py:533 +#: part/models.py:534 msgid "Can this part be built from other parts?" msgstr "" -#: part/models.py:535 +#: part/models.py:536 msgid "Can this part be used to build other parts?" msgstr "" -#: part/models.py:537 +#: part/models.py:538 msgid "Does this part have tracking for unique items?" msgstr "" -#: part/models.py:539 +#: part/models.py:540 msgid "Can this part be purchased from external suppliers?" msgstr "" -#: part/models.py:541 +#: part/models.py:542 msgid "Can this part be sold to customers?" msgstr "" -#: part/models.py:543 +#: part/models.py:544 msgid "Is this part active?" msgstr "" -#: part/models.py:545 +#: part/models.py:546 msgid "Is this a virtual part, such as a software product or license?" msgstr "" -#: part/models.py:547 +#: part/models.py:548 msgid "Part notes - supports Markdown formatting" msgstr "" -#: part/models.py:549 +#: part/models.py:550 msgid "Stored BOM checksum" msgstr "" -#: part/models.py:1212 +#: part/models.py:1222 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:1229 +#: part/models.py:1239 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:1248 templates/js/part.html:350 templates/js/stock.html:89 +#: part/models.py:1258 templates/js/part.html:350 templates/js/stock.html:90 msgid "Test Name" msgstr "" -#: part/models.py:1249 +#: part/models.py:1259 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1254 +#: part/models.py:1264 msgid "Test Description" msgstr "" -#: part/models.py:1255 +#: part/models.py:1265 msgid "Enter description for this test" msgstr "" -#: part/models.py:1261 +#: part/models.py:1271 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:1266 templates/js/part.html:367 +#: part/models.py:1276 templates/js/part.html:367 msgid "Requires Value" msgstr "" -#: part/models.py:1267 +#: part/models.py:1277 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:1272 templates/js/part.html:374 +#: part/models.py:1282 templates/js/part.html:374 msgid "Requires Attachment" msgstr "" -#: part/models.py:1273 +#: part/models.py:1283 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:1306 +#: part/models.py:1316 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:1311 +#: part/models.py:1321 msgid "Parameter Name" msgstr "" -#: part/models.py:1313 +#: part/models.py:1323 msgid "Parameter Units" msgstr "" -#: part/models.py:1339 +#: part/models.py:1349 msgid "Parent Part" msgstr "" -#: part/models.py:1341 +#: part/models.py:1351 msgid "Parameter Template" msgstr "" -#: part/models.py:1343 +#: part/models.py:1353 msgid "Parameter Value" msgstr "" -#: part/models.py:1372 +#: part/models.py:1382 msgid "Select parent part" msgstr "" -#: part/models.py:1380 +#: part/models.py:1390 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:1386 +#: part/models.py:1396 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:1389 +#: part/models.py:1399 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:1392 +#: part/models.py:1402 msgid "BOM item reference" msgstr "" -#: part/models.py:1395 +#: part/models.py:1405 msgid "BOM item notes" msgstr "" -#: part/models.py:1397 +#: part/models.py:1407 msgid "BOM line checksum" msgstr "" -#: part/models.py:1461 stock/models.py:233 +#: part/models.py:1471 stock/models.py:228 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:1470 +#: part/models.py:1480 msgid "Part cannot be added to its own Bill of Materials" msgstr "" -#: part/models.py:1477 +#: part/models.py:1487 #, python-brace-format msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgstr "" +#: part/models.py:1494 +msgid "BOM Item" +msgstr "" + #: part/templates/part/allocation.html:10 msgid "Part Stock Allocations" msgstr "" @@ -2076,14 +2113,14 @@ msgstr "" #: part/templates/part/allocation.html:45 #: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:58 -#: stock/templates/stock/item_base.html:224 +#: stock/templates/stock/item_base.html:231 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106 -#: templates/js/stock.html:623 +#: templates/js/stock.html:643 msgid "Stock Item" msgstr "" #: part/templates/part/allocation.html:20 -#: stock/templates/stock/item_base.html:165 +#: stock/templates/stock/item_base.html:185 msgid "Build Order" msgstr "" @@ -2123,11 +2160,6 @@ msgstr "" msgid "Export Bill of Materials" msgstr "" -#: part/templates/part/category.html:13 part/templates/part/category.html:78 -#: templates/stats.html:12 -msgid "Part Categories" -msgstr "" - #: part/templates/part/category.html:14 msgid "All parts" msgstr "" @@ -2164,7 +2196,7 @@ msgstr "" msgid "Part Details" msgstr "" -#: part/templates/part/detail.html:25 part/templates/part/part_base.html:81 +#: part/templates/part/detail.html:25 part/templates/part/part_base.html:79 msgid "IPN" msgstr "" @@ -2221,8 +2253,8 @@ msgstr "" msgid "Part is not a virtual part" msgstr "" -#: part/templates/part/detail.html:139 stock/forms.py:194 -#: templates/js/table_filters.html:122 +#: part/templates/part/detail.html:139 stock/forms.py:237 +#: templates/js/table_filters.html:159 msgid "Template" msgstr "" @@ -2234,7 +2266,7 @@ msgstr "" msgid "Part is not a template part" msgstr "" -#: part/templates/part/detail.html:148 templates/js/table_filters.html:134 +#: part/templates/part/detail.html:148 templates/js/table_filters.html:171 msgid "Assembly" msgstr "" @@ -2246,7 +2278,7 @@ msgstr "" msgid "Part cannot be assembled from other parts" msgstr "" -#: part/templates/part/detail.html:157 templates/js/table_filters.html:138 +#: part/templates/part/detail.html:157 templates/js/table_filters.html:175 msgid "Component" msgstr "" @@ -2258,7 +2290,7 @@ msgstr "" msgid "Part cannot be used in assemblies" msgstr "" -#: part/templates/part/detail.html:166 templates/js/table_filters.html:150 +#: part/templates/part/detail.html:166 templates/js/table_filters.html:187 msgid "Trackable" msgstr "" @@ -2278,7 +2310,7 @@ msgstr "" msgid "Part can be purchased from external suppliers" msgstr "" -#: part/templates/part/detail.html:184 templates/js/table_filters.html:146 +#: part/templates/part/detail.html:184 templates/js/table_filters.html:183 msgid "Salable" msgstr "" @@ -2290,7 +2322,7 @@ msgstr "" msgid "Part cannot be sold to customers" msgstr "" -#: part/templates/part/detail.html:193 templates/js/table_filters.html:117 +#: part/templates/part/detail.html:193 templates/js/table_filters.html:154 msgid "Active" msgstr "" @@ -2322,8 +2354,8 @@ msgstr "" msgid "New Parameter" msgstr "" -#: part/templates/part/params.html:21 stock/models.py:1252 -#: templates/js/stock.html:109 +#: part/templates/part/params.html:21 stock/models.py:1274 +#: templates/js/stock.html:110 msgid "Value" msgstr "" @@ -2335,10 +2367,6 @@ msgstr "" msgid "Delete" msgstr "" -#: part/templates/part/part_app_base.html:9 -msgid "Part Category" -msgstr "" - #: part/templates/part/part_app_base.html:11 msgid "Part List" msgstr "" @@ -2360,35 +2388,69 @@ msgstr "" msgid "Inactive" msgstr "" -#: part/templates/part/part_base.html:41 +#: part/templates/part/part_base.html:39 msgid "Star this part" msgstr "" +#: part/templates/part/part_base.html:44 +#: stock/templates/stock/item_base.html:78 +#: stock/templates/stock/location.html:22 +msgid "Barcode actions" +msgstr "" + +#: part/templates/part/part_base.html:46 +#: stock/templates/stock/item_base.html:80 +#: stock/templates/stock/location.html:24 +msgid "Show QR Code" +msgstr "" + #: part/templates/part/part_base.html:47 +#: stock/templates/stock/item_base.html:81 +#: stock/templates/stock/location.html:25 +msgid "Print Label" +msgstr "" + +#: part/templates/part/part_base.html:51 msgid "Show pricing information" msgstr "" -#: part/templates/part/part_base.html:104 +#: part/templates/part/part_base.html:64 +msgid "Part actions" +msgstr "" + +#: part/templates/part/part_base.html:66 +msgid "Duplicate part" +msgstr "" + +#: part/templates/part/part_base.html:67 +msgid "Edit part" +msgstr "" + +#: part/templates/part/part_base.html:69 +msgid "Delete part" +msgstr "" + +#: part/templates/part/part_base.html:102 msgid "Available Stock" msgstr "" -#: part/templates/part/part_base.html:110 +#: part/templates/part/part_base.html:108 templates/js/table_filters.html:57 msgid "In Stock" msgstr "" -#: part/templates/part/part_base.html:117 +#: part/templates/part/part_base.html:115 msgid "Allocated to Build Orders" msgstr "" -#: part/templates/part/part_base.html:124 +#: part/templates/part/part_base.html:122 msgid "Allocated to Sales Orders" msgstr "" -#: part/templates/part/part_base.html:146 +#: part/templates/part/part_base.html:144 msgid "Can Build" msgstr "" -#: part/templates/part/part_base.html:152 +#: part/templates/part/part_base.html:150 msgid "Underway" msgstr "" @@ -2428,7 +2490,7 @@ msgstr "" msgid "Part Stock" msgstr "" -#: part/templates/part/stock.html:77 +#: part/templates/part/stock.html:76 msgid "Create New Part" msgstr "" @@ -2473,11 +2535,7 @@ msgstr "" msgid "Used In" msgstr "" -#: part/templates/part/tabs.html:57 stock/templates/stock/tabs.html:6 -msgid "Tracking" -msgstr "" - -#: part/templates/part/tabs.html:64 stock/templates/stock/item_base.html:268 +#: part/templates/part/tabs.html:55 stock/templates/stock/item_base.html:275 msgid "Tests" msgstr "" @@ -2694,219 +2752,227 @@ msgstr "" msgid "Asset file description" msgstr "" -#: stock/forms.py:194 +#: stock/forms.py:185 +msgid "Label" +msgstr "" + +#: stock/forms.py:186 stock/forms.py:237 msgid "Select test report template" msgstr "" -#: stock/forms.py:202 +#: stock/forms.py:245 msgid "Include stock items in sub locations" msgstr "" -#: stock/forms.py:235 +#: stock/forms.py:278 msgid "Destination stock location" msgstr "" -#: stock/forms.py:241 +#: stock/forms.py:284 msgid "Confirm movement of stock items" msgstr "" -#: stock/forms.py:243 +#: stock/forms.py:286 msgid "Set the destination as the default location for selected parts" msgstr "" -#: stock/models.py:208 +#: stock/models.py:209 msgid "StockItem with this serial number already exists" msgstr "" -#: stock/models.py:250 +#: stock/models.py:245 #, python-brace-format msgid "Part type ('{pf}') must be {pe}" msgstr "" -#: stock/models.py:260 stock/models.py:269 +#: stock/models.py:255 stock/models.py:264 msgid "Quantity must be 1 for item with a serial number" msgstr "" -#: stock/models.py:261 +#: stock/models.py:256 msgid "Serial number cannot be set if quantity greater than 1" msgstr "" -#: stock/models.py:282 +#: stock/models.py:277 msgid "Item cannot belong to itself" msgstr "" -#: stock/models.py:314 +#: stock/models.py:316 msgid "Parent Stock Item" msgstr "" -#: stock/models.py:322 stock/templates/stock/item_base.html:138 -msgid "Base Part" -msgstr "" - -#: stock/models.py:323 +#: stock/models.py:325 msgid "Base part" msgstr "" -#: stock/models.py:332 +#: stock/models.py:334 msgid "Select a matching supplier part for this stock item" msgstr "" -#: stock/models.py:337 stock/templates/stock/stock_app_base.html:7 +#: stock/models.py:339 stock/templates/stock/stock_app_base.html:7 msgid "Stock Location" msgstr "" -#: stock/models.py:340 +#: stock/models.py:342 msgid "Where is this stock item located?" msgstr "" -#: stock/models.py:345 +#: stock/models.py:347 msgid "Installed In" msgstr "" -#: stock/models.py:348 +#: stock/models.py:350 msgid "Is this item installed in another item?" msgstr "" -#: stock/models.py:364 +#: stock/models.py:366 msgid "Serial number for this item" msgstr "" -#: stock/models.py:376 +#: stock/models.py:378 msgid "Batch code for this stock item" msgstr "" -#: stock/models.py:380 +#: stock/models.py:382 msgid "Stock Quantity" msgstr "" -#: stock/models.py:389 +#: stock/models.py:391 msgid "Source Build" msgstr "" -#: stock/models.py:391 +#: stock/models.py:393 msgid "Build for this stock item" msgstr "" -#: stock/models.py:398 +#: stock/models.py:400 msgid "Source Purchase Order" msgstr "" -#: stock/models.py:401 +#: stock/models.py:403 msgid "Purchase order for this stock item" msgstr "" -#: stock/models.py:407 +#: stock/models.py:409 msgid "Destination Sales Order" msgstr "" -#: stock/models.py:414 +#: stock/models.py:416 msgid "Destination Build Order" msgstr "" -#: stock/models.py:427 +#: stock/models.py:429 msgid "Delete this Stock Item when stock is depleted" msgstr "" -#: stock/models.py:437 stock/templates/stock/item_notes.html:14 +#: stock/models.py:439 stock/templates/stock/item_notes.html:14 #: stock/templates/stock/item_notes.html:30 msgid "Stock Item Notes" msgstr "" -#: stock/models.py:489 +#: stock/models.py:490 msgid "Assigned to Customer" msgstr "" -#: stock/models.py:491 +#: stock/models.py:492 msgid "Manually assigned to customer" msgstr "" -#: stock/models.py:656 +#: stock/models.py:505 +msgid "Returned from customer" +msgstr "" + +#: stock/models.py:507 +msgid "Returned to location" +msgstr "" + +#: stock/models.py:678 msgid "Part is not set as trackable" msgstr "" -#: stock/models.py:662 +#: stock/models.py:684 msgid "Quantity must be integer" msgstr "" -#: stock/models.py:668 +#: stock/models.py:690 #, python-brace-format msgid "Quantity must not exceed available stock quantity ({n})" msgstr "" -#: stock/models.py:671 stock/models.py:674 +#: stock/models.py:693 stock/models.py:696 msgid "Serial numbers must be a list of integers" msgstr "" -#: stock/models.py:677 +#: stock/models.py:699 msgid "Quantity does not match serial numbers" msgstr "" -#: stock/models.py:687 +#: stock/models.py:709 msgid "Serial numbers already exist: " msgstr "" -#: stock/models.py:712 +#: stock/models.py:734 msgid "Add serial number" msgstr "" -#: stock/models.py:715 +#: stock/models.py:737 #, python-brace-format msgid "Serialized {n} items" msgstr "" -#: stock/models.py:826 +#: stock/models.py:848 msgid "StockItem cannot be moved as it is not in stock" msgstr "" -#: stock/models.py:1153 +#: stock/models.py:1175 msgid "Tracking entry title" msgstr "" -#: stock/models.py:1155 +#: stock/models.py:1177 msgid "Entry notes" msgstr "" -#: stock/models.py:1157 +#: stock/models.py:1179 msgid "Link to external page for further information" msgstr "" -#: stock/models.py:1217 +#: stock/models.py:1239 msgid "Value must be provided for this test" msgstr "" -#: stock/models.py:1223 +#: stock/models.py:1245 msgid "Attachment must be uploaded for this test" msgstr "" -#: stock/models.py:1240 +#: stock/models.py:1262 msgid "Test" msgstr "" -#: stock/models.py:1241 +#: stock/models.py:1263 msgid "Test name" msgstr "" -#: stock/models.py:1246 +#: stock/models.py:1268 msgid "Result" msgstr "" -#: stock/models.py:1247 templates/js/table_filters.html:53 +#: stock/models.py:1269 templates/js/table_filters.html:90 msgid "Test result" msgstr "" -#: stock/models.py:1253 +#: stock/models.py:1275 msgid "Test output value" msgstr "" -#: stock/models.py:1259 +#: stock/models.py:1281 msgid "Attachment" msgstr "" -#: stock/models.py:1260 +#: stock/models.py:1282 msgid "Test result attachment" msgstr "" -#: stock/models.py:1266 +#: stock/models.py:1288 msgid "Test notes" msgstr "" @@ -2945,20 +3011,8 @@ msgid "" "This stock item will be automatically deleted when all stock is depleted." msgstr "" -#: stock/templates/stock/item_base.html:78 -msgid "Barcode actions" -msgstr "" - -#: stock/templates/stock/item_base.html:80 -msgid "Show QR Code" -msgstr "" - -#: stock/templates/stock/item_base.html:81 -msgid "Print Label" -msgstr "" - -#: stock/templates/stock/item_base.html:83 templates/js/barcode.html:263 -#: templates/js/barcode.html:268 +#: stock/templates/stock/item_base.html:83 templates/js/barcode.html:283 +#: templates/js/barcode.html:288 msgid "Unlink Barcode" msgstr "" @@ -2966,11 +3020,12 @@ msgstr "" msgid "Link Barcode" msgstr "" -#: stock/templates/stock/item_base.html:92 +#: stock/templates/stock/item_base.html:91 msgid "Stock adjustment actions" msgstr "" -#: stock/templates/stock/item_base.html:95 templates/stock_table.html:14 +#: stock/templates/stock/item_base.html:95 +#: stock/templates/stock/location.html:33 templates/stock_table.html:14 msgid "Count stock" msgstr "" @@ -2986,67 +3041,76 @@ msgstr "" msgid "Transfer stock" msgstr "" -#: stock/templates/stock/item_base.html:105 -msgid "Stock actions" -msgstr "" - -#: stock/templates/stock/item_base.html:108 +#: stock/templates/stock/item_base.html:101 msgid "Serialize stock" msgstr "" -#: stock/templates/stock/item_base.html:111 +#: stock/templates/stock/item_base.html:105 msgid "Assign to customer" msgstr "" +#: stock/templates/stock/item_base.html:108 +msgid "Return to stock" +msgstr "" + #: stock/templates/stock/item_base.html:114 +#: stock/templates/stock/location.html:30 +msgid "Stock actions" +msgstr "" + +#: stock/templates/stock/item_base.html:118 msgid "Convert to variant" msgstr "" -#: stock/templates/stock/item_base.html:116 +#: stock/templates/stock/item_base.html:120 msgid "Duplicate stock item" msgstr "" -#: stock/templates/stock/item_base.html:117 +#: stock/templates/stock/item_base.html:121 msgid "Edit stock item" msgstr "" -#: stock/templates/stock/item_base.html:119 +#: stock/templates/stock/item_base.html:123 msgid "Delete stock item" msgstr "" -#: stock/templates/stock/item_base.html:124 +#: stock/templates/stock/item_base.html:128 msgid "Generate test report" msgstr "" -#: stock/templates/stock/item_base.html:133 +#: stock/templates/stock/item_base.html:132 +msgid "Print labels" +msgstr "" + +#: stock/templates/stock/item_base.html:140 msgid "Stock Item Details" msgstr "" -#: stock/templates/stock/item_base.html:153 +#: stock/templates/stock/item_base.html:173 msgid "Belongs To" msgstr "" -#: stock/templates/stock/item_base.html:175 +#: stock/templates/stock/item_base.html:195 msgid "No location set" msgstr "" -#: stock/templates/stock/item_base.html:182 +#: stock/templates/stock/item_base.html:202 msgid "Unique Identifier" msgstr "" -#: stock/templates/stock/item_base.html:223 +#: stock/templates/stock/item_base.html:230 msgid "Parent Item" msgstr "" -#: stock/templates/stock/item_base.html:248 +#: stock/templates/stock/item_base.html:255 msgid "Last Updated" msgstr "" -#: stock/templates/stock/item_base.html:253 +#: stock/templates/stock/item_base.html:260 msgid "Last Stocktake" msgstr "" -#: stock/templates/stock/item_base.html:257 +#: stock/templates/stock/item_base.html:264 msgid "No stocktake performed" msgstr "" @@ -3058,6 +3122,10 @@ msgstr "" msgid "This stock item does not have any child items" msgstr "" +#: stock/templates/stock/item_delete.html:9 +msgid "Are you sure you want to delete this stock item?" +msgstr "" + #: stock/templates/stock/item_tests.html:10 stock/templates/stock/tabs.html:13 msgid "Test Data" msgstr "" @@ -3078,50 +3146,62 @@ msgstr "" msgid "All stock items" msgstr "" -#: stock/templates/stock/location.html:22 -msgid "Count stock items" -msgstr "" - -#: stock/templates/stock/location.html:25 -msgid "Edit stock location" -msgstr "" - -#: stock/templates/stock/location.html:28 -msgid "Delete stock location" +#: stock/templates/stock/location.html:26 +msgid "Check-in Items" msgstr "" #: stock/templates/stock/location.html:37 +msgid "Location actions" +msgstr "" + +#: stock/templates/stock/location.html:39 +msgid "Edit location" +msgstr "" + +#: stock/templates/stock/location.html:40 +msgid "Delete location" +msgstr "" + +#: stock/templates/stock/location.html:48 msgid "Location Details" msgstr "" -#: stock/templates/stock/location.html:42 +#: stock/templates/stock/location.html:53 msgid "Location Path" msgstr "" -#: stock/templates/stock/location.html:47 +#: stock/templates/stock/location.html:58 msgid "Location Description" msgstr "" -#: stock/templates/stock/location.html:52 +#: stock/templates/stock/location.html:63 msgid "Sublocations" msgstr "" -#: stock/templates/stock/location.html:57 -#: stock/templates/stock/location.html:72 templates/stats.html:21 +#: stock/templates/stock/location.html:68 +#: stock/templates/stock/location.html:83 templates/stats.html:21 #: templates/stats.html:30 msgid "Stock Items" msgstr "" -#: stock/templates/stock/location.html:62 +#: stock/templates/stock/location.html:73 msgid "Stock Details" msgstr "" -#: stock/templates/stock/location.html:67 +#: stock/templates/stock/location.html:78 #: templates/InvenTree/search_stock_location.html:6 templates/stats.html:25 msgid "Stock Locations" msgstr "" -#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:934 +#: stock/templates/stock/location_delete.html:7 +msgid "Are you sure you want to delete this stock location?" +msgstr "" + +#: stock/templates/stock/stock_adjust.html:35 +msgid "Stock item is serialized and quantity cannot be adjusted" +msgstr "" + +#: stock/templates/stock/stockitem_convert.html:7 stock/views.py:1052 msgid "Convert Stock Item" msgstr "" @@ -3137,6 +3217,10 @@ msgstr "" msgid "This action cannot be easily undone" msgstr "" +#: stock/templates/stock/tabs.html:6 +msgid "Tracking" +msgstr "" + #: stock/templates/stock/tabs.html:21 msgid "Builds" msgstr "" @@ -3145,190 +3229,214 @@ msgstr "" msgid "Children" msgstr "" -#: stock/views.py:113 +#: stock/views.py:114 msgid "Edit Stock Location" msgstr "" -#: stock/views.py:137 +#: stock/views.py:138 msgid "Stock Location QR code" msgstr "" -#: stock/views.py:155 +#: stock/views.py:156 msgid "Add Stock Item Attachment" msgstr "" -#: stock/views.py:200 +#: stock/views.py:201 msgid "Edit Stock Item Attachment" msgstr "" -#: stock/views.py:216 +#: stock/views.py:217 msgid "Delete Stock Item Attachment" msgstr "" -#: stock/views.py:232 +#: stock/views.py:233 msgid "Assign to Customer" msgstr "" #: stock/views.py:270 -msgid "Delete All Test Data" +msgid "Return to Stock" msgstr "" -#: stock/views.py:285 -msgid "Confirm test data deletion" +#: stock/views.py:289 +msgid "Specify a valid location" +msgstr "" + +#: stock/views.py:293 +msgid "Stock item returned from customer" msgstr "" #: stock/views.py:305 +msgid "Select Label Template" +msgstr "" + +#: stock/views.py:326 +msgid "Select valid label" +msgstr "" + +#: stock/views.py:388 +msgid "Delete All Test Data" +msgstr "" + +#: stock/views.py:403 +msgid "Confirm test data deletion" +msgstr "" + +#: stock/views.py:423 msgid "Add Test Result" msgstr "" -#: stock/views.py:342 +#: stock/views.py:460 msgid "Edit Test Result" msgstr "" -#: stock/views.py:359 +#: stock/views.py:477 msgid "Delete Test Result" msgstr "" -#: stock/views.py:370 +#: stock/views.py:488 msgid "Select Test Report Template" msgstr "" -#: stock/views.py:384 +#: stock/views.py:502 msgid "Select valid template" msgstr "" -#: stock/views.py:436 +#: stock/views.py:554 msgid "Stock Export Options" msgstr "" -#: stock/views.py:556 +#: stock/views.py:674 msgid "Stock Item QR Code" msgstr "" -#: stock/views.py:579 +#: stock/views.py:697 msgid "Adjust Stock" msgstr "" -#: stock/views.py:688 +#: stock/views.py:806 msgid "Move Stock Items" msgstr "" -#: stock/views.py:689 +#: stock/views.py:807 msgid "Count Stock Items" msgstr "" -#: stock/views.py:690 +#: stock/views.py:808 msgid "Remove From Stock" msgstr "" -#: stock/views.py:691 +#: stock/views.py:809 msgid "Add Stock Items" msgstr "" -#: stock/views.py:692 +#: stock/views.py:810 msgid "Delete Stock Items" msgstr "" -#: stock/views.py:720 +#: stock/views.py:838 msgid "Must enter integer value" msgstr "" -#: stock/views.py:725 +#: stock/views.py:843 msgid "Quantity must be positive" msgstr "" -#: stock/views.py:732 +#: stock/views.py:850 #, python-brace-format msgid "Quantity must not exceed {x}" msgstr "" -#: stock/views.py:740 +#: stock/views.py:858 msgid "Confirm stock adjustment" msgstr "" -#: stock/views.py:811 +#: stock/views.py:929 #, python-brace-format msgid "Added stock to {n} items" msgstr "" -#: stock/views.py:826 +#: stock/views.py:944 #, python-brace-format msgid "Removed stock from {n} items" msgstr "" -#: stock/views.py:839 +#: stock/views.py:957 #, python-brace-format msgid "Counted stock for {n} items" msgstr "" -#: stock/views.py:867 +#: stock/views.py:985 msgid "No items were moved" msgstr "" -#: stock/views.py:870 +#: stock/views.py:988 #, python-brace-format msgid "Moved {n} items to {dest}" msgstr "" -#: stock/views.py:889 +#: stock/views.py:1007 #, python-brace-format msgid "Deleted {n} stock items" msgstr "" -#: stock/views.py:901 +#: stock/views.py:1019 msgid "Edit Stock Item" msgstr "" -#: stock/views.py:961 +#: stock/views.py:1079 msgid "Create new Stock Location" msgstr "" -#: stock/views.py:982 +#: stock/views.py:1100 msgid "Serialize Stock" msgstr "" -#: stock/views.py:1074 +#: stock/views.py:1192 msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1167 +#: stock/views.py:1285 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1240 +#: stock/views.py:1358 msgid "Invalid quantity" msgstr "" -#: stock/views.py:1247 +#: stock/views.py:1361 +msgid "Quantity cannot be less than zero" +msgstr "" + +#: stock/views.py:1365 msgid "Invalid part selection" msgstr "" -#: stock/views.py:1296 +#: stock/views.py:1414 #, python-brace-format msgid "Created {n} new stock items" msgstr "" -#: stock/views.py:1315 stock/views.py:1331 +#: stock/views.py:1433 stock/views.py:1449 msgid "Created new stock item" msgstr "" -#: stock/views.py:1350 +#: stock/views.py:1468 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1363 +#: stock/views.py:1481 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1374 +#: stock/views.py:1492 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1391 +#: stock/views.py:1509 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1400 +#: stock/views.py:1518 msgid "Add Stock Tracking Entry" msgstr "" @@ -3416,39 +3524,83 @@ msgstr "" msgid "Delete attachment" msgstr "" -#: templates/js/barcode.html:28 +#: templates/js/barcode.html:8 msgid "Scan barcode data here using wedge scanner" msgstr "" -#: templates/js/barcode.html:34 +#: templates/js/barcode.html:12 msgid "Barcode" msgstr "" -#: templates/js/barcode.html:42 +#: templates/js/barcode.html:20 msgid "Enter barcode data" msgstr "" -#: templates/js/barcode.html:140 -msgid "Scan barcode data below" -msgstr "" - -#: templates/js/barcode.html:195 templates/js/barcode.html:243 -msgid "Unknown response from server" -msgstr "" - -#: templates/js/barcode.html:198 templates/js/barcode.html:247 +#: templates/js/barcode.html:42 msgid "Invalid server response" msgstr "" -#: templates/js/barcode.html:265 +#: templates/js/barcode.html:143 +msgid "Scan barcode data below" +msgstr "" + +#: templates/js/barcode.html:217 templates/js/barcode.html:263 +msgid "Unknown response from server" +msgstr "" + +#: templates/js/barcode.html:239 +msgid "Link Barcode to Stock Item" +msgstr "" + +#: templates/js/barcode.html:285 msgid "" "This will remove the association between this stock item and the barcode" msgstr "" -#: templates/js/barcode.html:271 +#: templates/js/barcode.html:291 msgid "Unlink" msgstr "" +#: templates/js/barcode.html:350 +msgid "Remove stock item" +msgstr "" + +#: templates/js/barcode.html:397 +msgid "Enter notes" +msgstr "" + +#: templates/js/barcode.html:399 +msgid "Enter optional notes for stock transfer" +msgstr "" + +#: templates/js/barcode.html:404 +msgid "Check Stock Items into Location" +msgstr "" + +#: templates/js/barcode.html:408 +msgid "Check In" +msgstr "" + +#: templates/js/barcode.html:466 +msgid "Server error" +msgstr "" + +#: templates/js/barcode.html:485 +msgid "Stock Item already scanned" +msgstr "" + +#: templates/js/barcode.html:489 +msgid "Stock Item already in this location" +msgstr "" + +#: templates/js/barcode.html:496 +msgid "Added stock item" +msgstr "" + +#: templates/js/barcode.html:503 +msgid "Barcode does not match Stock Item" +msgstr "" + #: templates/js/bom.html:143 msgid "Open subassembly" msgstr "" @@ -3509,7 +3661,7 @@ msgstr "" msgid "No purchase orders found" msgstr "" -#: templates/js/order.html:170 templates/js/stock.html:605 +#: templates/js/order.html:170 templates/js/stock.html:625 msgid "Date" msgstr "" @@ -3521,7 +3673,7 @@ msgstr "" msgid "Shipment Date" msgstr "" -#: templates/js/part.html:106 templates/js/stock.html:403 +#: templates/js/part.html:106 templates/js/stock.html:406 msgid "Select" msgstr "" @@ -3537,7 +3689,7 @@ msgstr "" msgid "No category" msgstr "" -#: templates/js/part.html:214 templates/js/table_filters.html:130 +#: templates/js/part.html:214 templates/js/table_filters.html:167 msgid "Low stock" msgstr "" @@ -3561,11 +3713,11 @@ msgstr "" msgid "No test templates matching query" msgstr "" -#: templates/js/part.html:387 templates/js/stock.html:62 +#: templates/js/part.html:387 templates/js/stock.html:63 msgid "Edit test result" msgstr "" -#: templates/js/part.html:388 templates/js/stock.html:63 +#: templates/js/part.html:388 templates/js/stock.html:64 msgid "Delete test result" msgstr "" @@ -3573,131 +3725,175 @@ msgstr "" msgid "This test is defined for a parent part" msgstr "" -#: templates/js/stock.html:25 +#: templates/js/stock.html:26 msgid "PASS" msgstr "" -#: templates/js/stock.html:27 +#: templates/js/stock.html:28 msgid "FAIL" msgstr "" -#: templates/js/stock.html:32 +#: templates/js/stock.html:33 msgid "NO RESULT" msgstr "" -#: templates/js/stock.html:58 +#: templates/js/stock.html:59 msgid "Add test result" msgstr "" -#: templates/js/stock.html:76 +#: templates/js/stock.html:77 msgid "No test results found" msgstr "" -#: templates/js/stock.html:117 +#: templates/js/stock.html:118 msgid "Test Date" msgstr "" -#: templates/js/stock.html:258 +#: templates/js/stock.html:261 msgid "No stock items matching query" msgstr "" -#: templates/js/stock.html:355 templates/js/stock.html:370 +#: templates/js/stock.html:358 templates/js/stock.html:373 msgid "Undefined location" msgstr "" -#: templates/js/stock.html:467 -msgid "StockItem has been allocated" +#: templates/js/stock.html:464 +msgid "Stock item has been allocated" +msgstr "" + +#: templates/js/stock.html:468 +msgid "Stock item has been assigned to customer" +msgstr "" + +#: templates/js/stock.html:470 +msgid "Stock item was assigned to a build order" msgstr "" #: templates/js/stock.html:472 -msgid "StockItem is lost" +msgid "Stock item was assigned to a sales order" msgstr "" -#: templates/js/stock.html:500 +#: templates/js/stock.html:479 +msgid "Stock item has been rejected" +msgstr "" + +#: templates/js/stock.html:483 +msgid "Stock item is lost" +msgstr "" + +#: templates/js/stock.html:487 templates/js/table_filters.html:52 +msgid "Depleted" +msgstr "" + +#: templates/js/stock.html:516 +msgid "Shipped to customer" +msgstr "" + +#: templates/js/stock.html:519 msgid "No stock location set" msgstr "" -#: templates/js/stock.html:671 +#: templates/js/stock.html:691 msgid "No user information" msgstr "" -#: templates/js/table_filters.html:19 -msgid "Include sublocations" +#: templates/js/table_filters.html:19 templates/js/table_filters.html:67 +msgid "Is Serialized" msgstr "" -#: templates/js/table_filters.html:20 -msgid "Include stock in sublocations" -msgstr "" - -#: templates/js/table_filters.html:24 -msgid "Active parts" -msgstr "" - -#: templates/js/table_filters.html:25 -msgid "Show stock for active parts" -msgstr "" - -#: templates/js/table_filters.html:29 templates/js/table_filters.html:30 -msgid "Stock status" -msgstr "" - -#: templates/js/table_filters.html:34 -msgid "Is allocated" -msgstr "" - -#: templates/js/table_filters.html:35 -msgid "Item has been alloacted" -msgstr "" - -#: templates/js/table_filters.html:38 +#: templates/js/table_filters.html:22 templates/js/table_filters.html:70 msgid "Serial number GTE" msgstr "" -#: templates/js/table_filters.html:39 +#: templates/js/table_filters.html:23 templates/js/table_filters.html:71 msgid "Serial number greater than or equal to" msgstr "" -#: templates/js/table_filters.html:42 +#: templates/js/table_filters.html:26 templates/js/table_filters.html:74 msgid "Serial number LTE" msgstr "" -#: templates/js/table_filters.html:43 +#: templates/js/table_filters.html:27 templates/js/table_filters.html:75 msgid "Serial number less than or equal to" msgstr "" -#: templates/js/table_filters.html:72 +#: templates/js/table_filters.html:37 +msgid "Active parts" +msgstr "" + +#: templates/js/table_filters.html:38 +msgid "Show stock for active parts" +msgstr "" + +#: templates/js/table_filters.html:42 +msgid "Is allocated" +msgstr "" + +#: templates/js/table_filters.html:43 +msgid "Item has been alloacted" +msgstr "" + +#: templates/js/table_filters.html:47 +msgid "Include sublocations" +msgstr "" + +#: templates/js/table_filters.html:48 +msgid "Include stock in sublocations" +msgstr "" + +#: templates/js/table_filters.html:53 +msgid "Show stock items which are depleted" +msgstr "" + +#: templates/js/table_filters.html:58 +msgid "Show items which are in stock" +msgstr "" + +#: templates/js/table_filters.html:62 +msgid "Sent to customer" +msgstr "" + +#: templates/js/table_filters.html:63 +msgid "Show items which have been assigned to a customer" +msgstr "" + +#: templates/js/table_filters.html:79 templates/js/table_filters.html:80 +msgid "Stock status" +msgstr "" + +#: templates/js/table_filters.html:109 msgid "Build status" msgstr "" -#: templates/js/table_filters.html:84 templates/js/table_filters.html:97 +#: templates/js/table_filters.html:121 templates/js/table_filters.html:134 msgid "Order status" msgstr "" -#: templates/js/table_filters.html:89 templates/js/table_filters.html:102 +#: templates/js/table_filters.html:126 templates/js/table_filters.html:139 msgid "Outstanding" msgstr "" -#: templates/js/table_filters.html:112 +#: templates/js/table_filters.html:149 msgid "Include subcategories" msgstr "" -#: templates/js/table_filters.html:113 +#: templates/js/table_filters.html:150 msgid "Include parts in subcategories" msgstr "" -#: templates/js/table_filters.html:118 +#: templates/js/table_filters.html:155 msgid "Show active parts" msgstr "" -#: templates/js/table_filters.html:126 +#: templates/js/table_filters.html:163 msgid "Stock available" msgstr "" -#: templates/js/table_filters.html:142 +#: templates/js/table_filters.html:179 msgid "Starred" msgstr "" -#: templates/js/table_filters.html:154 +#: templates/js/table_filters.html:191 msgid "Purchasable" msgstr "" diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 472ab1996e..f866a08850 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -190,6 +190,21 @@ class PartThumbs(generics.ListAPIView): return Response(data) +class PartThumbsUpdate(generics.RetrieveUpdateAPIView): + """ API endpoint for updating Part thumbnails""" + + queryset = Part.objects.all() + serializer_class = part_serializers.PartThumbSerializerUpdate + + permission_classes = [ + permissions.IsAuthenticated, + ] + + filter_backends = [ + DjangoFilterBackend + ] + + class PartDetail(generics.RetrieveUpdateDestroyAPIView): """ API endpoint for detail view of a single Part object """ @@ -588,7 +603,20 @@ class BomList(generics.ListCreateAPIView): """ serializer_class = part_serializers.BomItemSerializer - + + def list(self, request, *args, **kwargs): + + queryset = self.filter_queryset(self.get_queryset()) + + serializer = self.get_serializer(queryset, many=True) + + data = serializer.data + + if request.is_ajax(): + return JsonResponse(data, safe=False) + else: + return Response(data) + def get_serializer(self, *args, **kwargs): # Do we wish to include extra detail? @@ -607,8 +635,10 @@ class BomList(generics.ListCreateAPIView): return self.serializer_class(*args, **kwargs) - def get_queryset(self): + def get_queryset(self, *args, **kwargs): + queryset = BomItem.objects.all() + queryset = self.get_serializer_class().setup_eager_loading(queryset) return queryset @@ -716,7 +746,10 @@ part_api_urls = [ url(r'^.*$', PartParameterList.as_view(), name='api-part-param-list'), ])), - url(r'^thumbs/', PartThumbs.as_view(), name='api-part-thumbs'), + url(r'^thumbs/', include([ + url(r'^$', PartThumbs.as_view(), name='api-part-thumbs'), + url(r'^(?P\d+)/?', PartThumbsUpdate.as_view(), name='api-part-thumbs-update'), + ])), url(r'^(?P\d+)/?', PartDetail.as_view(), name='api-part-detail'), diff --git a/InvenTree/part/bom.py b/InvenTree/part/bom.py index 61698d57bf..90c26db86c 100644 --- a/InvenTree/part/bom.py +++ b/InvenTree/part/bom.py @@ -40,7 +40,7 @@ def MakeBomTemplate(fmt): return DownloadFile(data, filename) -def ExportBom(part, fmt='csv', cascade=False): +def ExportBom(part, fmt='csv', cascade=False, max_levels=None): """ Export a BOM (Bill of Materials) for a given part. Args: @@ -59,8 +59,8 @@ def ExportBom(part, fmt='csv', cascade=False): # Add items at a given layer for item in items: - item.level = '-' * level - + item.level = str(int(level)) + # Avoid circular BOM references if item.pk in uids: continue @@ -68,7 +68,8 @@ def ExportBom(part, fmt='csv', cascade=False): bom_items.append(item) if item.sub_part.assembly: - add_items(item.sub_part.bom_items.all().order_by('id'), level + 1) + if max_levels is None or level < max_levels: + add_items(item.sub_part.bom_items.all().order_by('id'), level + 1) if cascade: # Cascading (multi-level) BOM diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py index 986749f7b3..dbbced352b 100644 --- a/InvenTree/part/forms.py +++ b/InvenTree/part/forms.py @@ -56,6 +56,8 @@ class BomExportForm(forms.Form): cascading = forms.BooleanField(label=_("Cascading"), required=False, initial=False, help_text=_("Download cascading / multi-level BOM")) + levels = forms.IntegerField(label=_("Levels"), required=True, initial=0, help_text=_("Select maximum number of BOM levels to export (0 = all levels)")) + def get_choices(self): """ BOM export format choices """ diff --git a/InvenTree/part/migrations/0046_auto_20200804_0107.py b/InvenTree/part/migrations/0046_auto_20200804_0107.py new file mode 100644 index 0000000000..5a0952c1e4 --- /dev/null +++ b/InvenTree/part/migrations/0046_auto_20200804_0107.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.7 on 2020-08-04 01:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0045_auto_20200605_0932'), + ] + + operations = [ + migrations.AlterField( + model_name='partcategory', + name='default_keywords', + field=models.CharField(blank=True, help_text='Default keywords for parts in this category', max_length=250, null=True), + ), + ] diff --git a/InvenTree/part/migrations/0047_auto_20200808_0715.py b/InvenTree/part/migrations/0047_auto_20200808_0715.py new file mode 100644 index 0000000000..4fc3d5a7d9 --- /dev/null +++ b/InvenTree/part/migrations/0047_auto_20200808_0715.py @@ -0,0 +1,17 @@ +# Generated by Django 3.0.7 on 2020-08-08 07:15 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0046_auto_20200804_0107'), + ] + + operations = [ + migrations.AlterModelOptions( + name='part', + options={'ordering': ['name'], 'verbose_name': 'Part', 'verbose_name_plural': 'Parts'}, + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 3fe3deb15c..cbc22c5605 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -65,14 +65,14 @@ class PartCategory(InvenTreeTree): help_text=_('Default location for parts in this category') ) - default_keywords = models.CharField(blank=True, max_length=250, help_text=_('Default keywords for parts in this category')) + default_keywords = models.CharField(null=True, blank=True, max_length=250, help_text=_('Default keywords for parts in this category')) def get_absolute_url(self): return reverse('category-detail', kwargs={'pk': self.id}) class Meta: - verbose_name = "Part Category" - verbose_name_plural = "Part Categories" + verbose_name = _("Part Category") + verbose_name_plural = _("Part Categories") def get_parts(self, cascade=True): """ Return a queryset for all parts under this category. @@ -239,6 +239,7 @@ class Part(MPTTModel): class Meta: verbose_name = _("Part") verbose_name_plural = _("Parts") + ordering = ['name', ] class MPTTMeta: # For legacy reasons the 'variant_of' field is used to indicate the MPTT parent @@ -559,16 +560,17 @@ class Part(MPTTModel): responsible = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True, related_name='parts_responible') - def format_barcode(self): + def format_barcode(self, **kwargs): """ Return a JSON string for formatting a barcode for this Part object """ return helpers.MakeBarcode( "part", + self.id, { - "id": self.id, "name": self.full_name, "url": reverse('api-part-detail', kwargs={'pk': self.id}), - } + }, + **kwargs ) @property @@ -1490,7 +1492,7 @@ class BomItem(models.Model): pass class Meta: - verbose_name = "BOM Item" + verbose_name = _("BOM Item") # Prevent duplication of parent/child rows unique_together = ('part', 'sub_part') diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index f625a02c41..c1ecfb5cce 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -1,6 +1,7 @@ """ JSON serializers for Part app """ +import imghdr from rest_framework import serializers @@ -92,6 +93,27 @@ class PartThumbSerializer(serializers.Serializer): count = serializers.IntegerField(read_only=True) +class PartThumbSerializerUpdate(InvenTreeModelSerializer): + """ Serializer for updating Part thumbnail """ + + def validate_image(self, value): + """ + Check that file is an image. + """ + validate = imghdr.what(value) + if not validate: + raise serializers.ValidationError("File is not an image") + return value + + image = InvenTreeAttachmentSerializerField(required=True) + + class Meta: + model = Part + fields = [ + 'image', + ] + + class PartBriefSerializer(InvenTreeModelSerializer): """ Serializer for Part (brief detail) """ @@ -214,6 +236,9 @@ class PartSerializer(InvenTreeModelSerializer): thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True) starred = serializers.SerializerMethodField() + # PrimaryKeyRelated fields (Note: enforcing field type here results in much faster queries, somehow...) + category = serializers.PrimaryKeyRelatedField(queryset=PartCategory.objects.all()) + # TODO - Include annotation for the following fields: # allocated_stock = serializers.FloatField(source='allocation_count', read_only=True) # bom_items = serializers.IntegerField(source='bom_count', read_only=True) @@ -280,8 +305,13 @@ class BomItemSerializer(InvenTreeModelSerializer): price_range = serializers.CharField(read_only=True) quantity = serializers.FloatField() + + part = serializers.PrimaryKeyRelatedField(queryset=Part.objects.filter(assembly=True)) part_detail = PartBriefSerializer(source='part', many=False, read_only=True) + + sub_part = serializers.PrimaryKeyRelatedField(queryset=Part.objects.filter(component=True)) + sub_part_detail = PartBriefSerializer(source='sub_part', many=False, read_only=True) validated = serializers.BooleanField(read_only=True, source='is_line_valid') @@ -306,6 +336,7 @@ class BomItemSerializer(InvenTreeModelSerializer): queryset = queryset.prefetch_related('part') queryset = queryset.prefetch_related('part__category') queryset = queryset.prefetch_related('part__stock_items') + queryset = queryset.prefetch_related('sub_part') queryset = queryset.prefetch_related('sub_part__category') queryset = queryset.prefetch_related('sub_part__stock_items') diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index eda1db923b..9ae5cc8026 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -1392,10 +1392,22 @@ class BomDownload(AjaxView): cascade = str2bool(request.GET.get('cascade', False)) + levels = request.GET.get('levels', None) + + if levels is not None: + try: + levels = int(levels) + + if levels <= 0: + levels = None + + except ValueError: + levels = None + if not IsValidBOMFormat(export_format): export_format = 'csv' - return ExportBom(part, fmt=export_format, cascade=cascade) + return ExportBom(part, fmt=export_format, cascade=cascade, max_levels=levels) def get_data(self): return { @@ -1419,6 +1431,7 @@ class BomExport(AjaxView): # Extract POSTed form data fmt = request.POST.get('file_format', 'csv').lower() cascade = str2bool(request.POST.get('cascading', False)) + levels = request.POST.get('levels', None) try: part = Part.objects.get(pk=self.kwargs['pk']) @@ -1434,6 +1447,9 @@ class BomExport(AjaxView): url += '?file_format=' + fmt url += '&cascade=' + str(cascade) + if levels: + url += '&levels=' + str(levels) + data = { 'form_valid': part is not None, 'url': url, diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index 018b588c1f..4368f654cf 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -338,11 +338,6 @@ class StockList(generics.ListCreateAPIView): queryset = self.filter_queryset(self.get_queryset()) - page = self.paginate_queryset(queryset) - if page is not None: - serializer = self.get_serializer(page, many=True) - return self.get_paginated_response(serializer.data) - serializer = self.get_serializer(queryset, many=True) data = serializer.data @@ -363,6 +358,7 @@ class StockList(generics.ListCreateAPIView): part_ids.add(part) sp = item['supplier_part'] + if sp: supplier_part_ids.add(sp) @@ -434,6 +430,7 @@ class StockList(generics.ListCreateAPIView): def get_queryset(self, *args, **kwargs): queryset = super().get_queryset(*args, **kwargs) + queryset = StockItemSerializer.prefetch_queryset(queryset) queryset = StockItemSerializer.annotate_queryset(queryset) @@ -477,6 +474,17 @@ class StockList(generics.ListCreateAPIView): if customer: queryset = queryset.filter(customer=customer) + # Filter if items have been sent to a customer (any customer) + sent_to_customer = params.get('sent_to_customer', None) + + if sent_to_customer is not None: + sent_to_customer = str2bool(sent_to_customer) + + if sent_to_customer: + queryset = queryset.exclude(customer=None) + else: + queryset = queryset.filter(customer=None) + # Filter by "serialized" status? serialized = params.get('serialized', None) @@ -507,6 +515,7 @@ class StockList(generics.ListCreateAPIView): if serial_number_lte is not None: queryset = queryset.filter(serial__lte=serial_number_lte) + # Filter by "in_stock" status in_stock = params.get('in_stock', None) if in_stock is not None: @@ -539,10 +548,21 @@ class StockList(generics.ListCreateAPIView): active = str2bool(active) queryset = queryset.filter(part__active=active) + # Filter by 'depleted' status + depleted = params.get('depleted', None) + + if depleted is not None: + depleted = str2bool(depleted) + + if depleted: + queryset = queryset.filter(quantity__lte=0) + else: + queryset = queryset.exclude(quantity__lte=0) + # Filter by internal part number IPN = params.get('IPN', None) - if IPN: + if IPN is not None: queryset = queryset.filter(part__IPN=IPN) # Does the client wish to filter by the Part ID? diff --git a/InvenTree/stock/forms.py b/InvenTree/stock/forms.py index bb403d837d..234da6d53b 100644 --- a/InvenTree/stock/forms.py +++ b/InvenTree/stock/forms.py @@ -46,6 +46,18 @@ class AssignStockItemToCustomerForm(HelperForm): ] +class ReturnStockItemForm(HelperForm): + """ + Form for manually returning a StockItem into stock + """ + + class Meta: + model = StockItem + fields = [ + 'location', + ] + + class EditStockItemTestResultForm(HelperForm): """ Form for creating / editing a StockItemTestResult object. @@ -166,6 +178,37 @@ class SerializeStockForm(HelperForm): ] +class StockItemLabelSelectForm(HelperForm): + """ Form for selecting a label template for a StockItem """ + + label = forms.ChoiceField( + label=_('Label'), + help_text=_('Select test report template') + ) + + class Meta: + model = StockItem + fields = [ + 'label', + ] + + def get_label_choices(self, labels): + + choices = [] + + if len(labels) > 0: + for label in labels: + choices.append((label.pk, label)) + + return choices + + def __init__(self, labels, *args, **kwargs): + + super().__init__(*args, **kwargs) + + self.fields['label'].choices = self.get_label_choices(labels) + + class TestReportFormatForm(HelperForm): """ Form for selection a test report template """ diff --git a/InvenTree/stock/migrations/0048_auto_20200807_2344.py b/InvenTree/stock/migrations/0048_auto_20200807_2344.py new file mode 100644 index 0000000000..b859344bb0 --- /dev/null +++ b/InvenTree/stock/migrations/0048_auto_20200807_2344.py @@ -0,0 +1,19 @@ +# Generated by Django 3.0.7 on 2020-08-07 23:44 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0047_auto_20200605_0932'), + ] + + operations = [ + migrations.AlterField( + model_name='stockitem', + name='status', + field=models.PositiveIntegerField(choices=[(10, 'OK'), (50, 'Attention needed'), (55, 'Damaged'), (60, 'Destroyed'), (70, 'Lost'), (65, 'Rejected'), (85, 'Returned')], default=10, validators=[django.core.validators.MinValueValidator(0)]), + ), + ] diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 736e2218bf..788bf845df 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -45,16 +45,17 @@ class StockLocation(InvenTreeTree): def get_absolute_url(self): return reverse('stock-location-detail', kwargs={'pk': self.id}) - def format_barcode(self): + def format_barcode(self, **kwargs): """ Return a JSON string for formatting a barcode for this StockLocation object """ return helpers.MakeBarcode( 'stocklocation', + self.pk, { - "id": self.id, "name": self.name, "url": reverse('api-location-detail', kwargs={'pk': self.id}), - } + }, + **kwargs ) def get_stock_items(self, cascade=True): @@ -140,6 +141,7 @@ class StockItem(MPTTModel): sales_order=None, build_order=None, belongs_to=None, + customer=None, status__in=StockStatus.AVAILABLE_CODES ) @@ -219,12 +221,6 @@ class StockItem(MPTTModel): super().clean() - if self.status == StockStatus.ASSIGNED_TO_OTHER_ITEM and self.belongs_to is None: - raise ValidationError({ - 'belongs_to': "Belongs_to field must be specified as statis is marked as ASSIGNED_TO_OTHER_ITEM", - 'status': 'Status cannot be marked as ASSIGNED_TO_OTHER_ITEM if the belongs_to field is not set', - }) - try: if self.part.trackable: # Trackable parts must have integer values for quantity field! @@ -288,7 +284,7 @@ class StockItem(MPTTModel): def get_part_name(self): return self.part.full_name - def format_barcode(self): + def format_barcode(self, **kwargs): """ Return a JSON string for formatting a barcode for this StockItem. Can be used to perform lookup of a stockitem using barcode @@ -301,10 +297,11 @@ class StockItem(MPTTModel): return helpers.MakeBarcode( "stockitem", + self.id, { - "id": self.id, "url": reverse('api-stock-detail', kwargs={'pk': self.id}), - } + }, + **kwargs ) uid = models.CharField(blank=True, max_length=128, help_text=("Unique identifier field")) @@ -477,7 +474,6 @@ class StockItem(MPTTModel): # Update StockItem fields with new information item.sales_order = order - item.status = StockStatus.SHIPPED item.customer = customer item.location = None @@ -495,6 +491,23 @@ class StockItem(MPTTModel): # Return the reference to the stock item return item + def returnFromCustomer(self, location, user=None): + """ + Return stock item from customer, back into the specified location. + """ + + self.addTransactionNote( + _("Returned from customer") + " " + self.customer.name, + user, + notes=_("Returned to location") + " " + location.name, + system=True + ) + + self.customer = None + self.location = location + + self.save() + # If stock item is incoming, an (optional) ETA field # expected_arrival = models.DateField(null=True, blank=True) @@ -599,6 +612,10 @@ class StockItem(MPTTModel): if self.build_order is not None: return False + # Not 'in stock' if it has been assigned to a customer + if self.customer is not None: + return False + # Not 'in stock' if the status code makes it unavailable if self.status in StockStatus.UNAVAILABLE_CODES: return False diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index 07fdd7952e..bed3f8f7c1 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -99,15 +99,34 @@ class StockItemSerializer(InvenTreeModelSerializer): return queryset + belongs_to = serializers.PrimaryKeyRelatedField(read_only=True) + + build_order = serializers.PrimaryKeyRelatedField(read_only=True) + + customer = serializers.PrimaryKeyRelatedField(read_only=True) + + location = serializers.PrimaryKeyRelatedField(read_only=True) + + in_stock = serializers.BooleanField(read_only=True) + + sales_order = serializers.PrimaryKeyRelatedField(read_only=True) + status_text = serializers.CharField(source='get_status_display', read_only=True) - part_detail = PartBriefSerializer(source='part', many=False, read_only=True) - location_detail = LocationBriefSerializer(source='location', many=False, read_only=True) + supplier_part = serializers.PrimaryKeyRelatedField(read_only=True) + supplier_part_detail = SupplierPartSerializer(source='supplier_part', many=False, read_only=True) + part = serializers.PrimaryKeyRelatedField(read_only=True) + + part_detail = PartBriefSerializer(source='part', many=False, read_only=True) + + location_detail = LocationBriefSerializer(source='location', many=False, read_only=True) + tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True, required=False) quantity = serializers.FloatField() + allocated = serializers.FloatField(source='allocation_count', required=False) serial = serializers.IntegerField(required=False) @@ -140,9 +159,9 @@ class StockItemSerializer(InvenTreeModelSerializer): fields = [ 'allocated', 'batch', - 'build_order', 'belongs_to', 'customer', + 'build_order', 'in_stock', 'link', 'location', @@ -155,10 +174,10 @@ class StockItemSerializer(InvenTreeModelSerializer): 'required_tests', 'sales_order', 'serial', - 'supplier_part', - 'supplier_part_detail', 'status', 'status_text', + 'supplier_part', + 'supplier_part_detail', 'tracking_items', 'uid', ] diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html index 63804291ec..1b4171297e 100644 --- a/InvenTree/stock/templates/stock/item_base.html +++ b/InvenTree/stock/templates/stock/item_base.html @@ -78,7 +78,7 @@ InvenTree | {% trans "Stock Item" %} - {{ item }} - {% if item.in_stock %} - {% endif %} - - + + {% if item.part.has_test_report_templates %} {% endif %} @@ -157,7 +161,7 @@ InvenTree | {% trans "Stock Item" %} - {{ item }} {% trans "Customer" %} - {{ item.customer.name }} + {{ item.customer.name }} {% endif %} {% if item.belongs_to %} @@ -310,6 +314,15 @@ $("#stock-test-report").click(function() { }); {% endif %} +$("#print-label").click(function() { + launchModalForm( + "{% url 'stock-item-label-select' item.id %}", + { + follow: true, + } + ) +}); + $("#stock-duplicate").click(function() { launchModalForm( "{% url 'stock-item-create' %}", @@ -349,7 +362,6 @@ $("#unlink-barcode").click(function() { {% if item.in_stock %} -{% if item.part.salable %} $("#stock-assign-to-customer").click(function() { launchModalForm("{% url 'stock-item-assign' item.id %}", { @@ -357,7 +369,6 @@ $("#stock-assign-to-customer").click(function() { } ); }); -{% endif %} function itemAdjust(action) { launchModalForm("/stock/adjust/", @@ -398,6 +409,16 @@ $('#stock-add').click(function() { itemAdjust('add'); }); +{% else %} + +$("#stock-return-from-customer").click(function() { + launchModalForm("{% url 'stock-item-return' item.id %}", + { + reload: true, + } + ); +}); + {% endif %} $("#stock-delete").click(function () { diff --git a/InvenTree/stock/templates/stock/item_delete.html b/InvenTree/stock/templates/stock/item_delete.html index 9e908a0d67..09d9397ecc 100644 --- a/InvenTree/stock/templates/stock/item_delete.html +++ b/InvenTree/stock/templates/stock/item_delete.html @@ -1,11 +1,14 @@ {% extends "modal_delete_form.html" %} +{% load i18n %} +{% load inventree_extras %} + {% block pre_form_content %}
-Are you sure you want to delete this stock item? +{% trans "Are you sure you want to delete this stock item?" %}
-This will remove {{ item.quantity }} units of {{ item.part.full_name }} from stock. +This will remove {% decimal item.quantity %} units of {{ item.part.full_name }} from stock.
{% endblock %} \ No newline at end of file diff --git a/InvenTree/stock/templates/stock/stock_adjust.html b/InvenTree/stock/templates/stock/stock_adjust.html index a72407f735..8385fb5039 100644 --- a/InvenTree/stock/templates/stock/stock_adjust.html +++ b/InvenTree/stock/templates/stock/stock_adjust.html @@ -32,6 +32,7 @@ {% if item.error %}
{{ item.error }} diff --git a/InvenTree/stock/urls.py b/InvenTree/stock/urls.py index 65e9c6742b..51067b57de 100644 --- a/InvenTree/stock/urls.py +++ b/InvenTree/stock/urls.py @@ -24,10 +24,12 @@ stock_item_detail_urls = [ url(r'^qr_code/', views.StockItemQRCode.as_view(), name='stock-item-qr'), url(r'^delete_test_data/', views.StockItemDeleteTestData.as_view(), name='stock-item-delete-test-data'), url(r'^assign/', views.StockItemAssignToCustomer.as_view(), name='stock-item-assign'), + url(r'^return/', views.StockItemReturnToStock.as_view(), name='stock-item-return'), 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'), @@ -58,6 +60,7 @@ stock_urls = [ url(r'^item/new/?', views.StockItemCreate.as_view(), name='stock-item-create'), 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 49db90d578..1c9b78a3f0 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -28,6 +28,7 @@ from datetime import datetime 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 from .admin import StockItemResource @@ -260,6 +261,123 @@ class StockItemAssignToCustomer(AjaxUpdateView): return self.renderJsonResponse(request, self.get_form(), data) +class StockItemReturnToStock(AjaxUpdateView): + """ + View for returning a stock item (which is assigned to a customer) to stock. + """ + + model = StockItem + ajax_form_title = _("Return to Stock") + context_object_name = "item" + form_class = StockForms.ReturnStockItemForm + + def post(self, request, *args, **kwargs): + + location = request.POST.get('location', None) + + if location: + try: + location = StockLocation.objects.get(pk=location) + except (ValueError, StockLocation.DoesNotExist): + location = None + + if location: + stock_item = self.get_object() + + stock_item.returnFromCustomer(location, request.user) + else: + raise ValidationError({'location': _("Specify a valid location")}) + + data = { + 'form_valid': True, + 'success': _("Stock item returned from customer") + } + + return self.renderJsonResponse(request, self.get_form(), data) + + +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') + + def get_form(self): + + item = StockItem.objects.get(pk=self.kwargs['pk']) + + labels = [] + + for label in StockItemLabel.objects.all(): + 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 + """ + + 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 @@ -1239,8 +1357,8 @@ class StockItemCreate(AjaxCreateView): valid = False form.errors['quantity'] = [_('Invalid quantity')] - if quantity <= 0: - form.errors['quantity'] = [_('Quantity must be greater than zero')] + if quantity < 0: + form.errors['quantity'] = [_('Quantity cannot be less than zero')] valid = False if part is None: diff --git a/InvenTree/templates/js/stock.html b/InvenTree/templates/js/stock.html index 7a92d0df39..11cf6a94e3 100644 --- a/InvenTree/templates/js/stock.html +++ b/InvenTree/templates/js/stock.html @@ -1,4 +1,5 @@ {% load i18n %} +{% load status_codes %} /* Stock API functions * Requires api.js to be loaded first @@ -425,16 +426,10 @@ function loadStockTable(table, options) { sortable: true, formatter: function(value, row, index, field) { - var url = ''; + var url = `/stock/item/${row.pk}/`; var thumb = row.part_detail.thumbnail; var name = row.part_detail.full_name; - if (row.supplier_part) { - url = `/supplier-part/${row.supplier_part}/`; - } else { - url = `/part/${row.part}/`; - } - html = imageHoverIcon(thumb) + renderLink(name, url); return html; @@ -466,12 +461,30 @@ function loadStockTable(table, options) { var html = renderLink(val, `/stock/item/${row.pk}/`); if (row.allocated) { - html += ``; + html += ``; } + if (row.customer) { + html += ``; + } else if (row.build_order) { + html += ``; + } else if (row.sales_order) { + html += ``; + } + + // Special stock status codes + + // 65 = "REJECTED" + if (row.status == 65) { + html += ``; + } // 70 = "LOST" - if (row.status == 70) { - html += ``; + else if (row.status == 70) { + html += ``; + } + + if (row.quantity <= 0) { + html += `{% trans "Depleted" %}`; } return html; diff --git a/InvenTree/templates/js/table_filters.html b/InvenTree/templates/js/table_filters.html index e2138ef6b3..9050edba6f 100644 --- a/InvenTree/templates/js/table_filters.html +++ b/InvenTree/templates/js/table_filters.html @@ -32,30 +32,35 @@ function getAvailableTableFilters(tableKey) { // Filters for the "Stock" table if (tableKey == 'stock') { return { - in_stock: { + active: { type: 'bool', - title: '{% trans "In Stock" %}', - description: '{% trans "Show items which are in stock" %}', + title: '{% trans "Active parts" %}', + description: '{% trans "Show stock for active parts" %}', + }, + allocated: { + type: 'bool', + title: '{% trans "Is allocated" %}', + description: '{% trans "Item has been alloacted" %}', }, cascade: { type: 'bool', title: '{% trans "Include sublocations" %}', description: '{% trans "Include stock in sublocations" %}', }, - active: { + depleted: { type: 'bool', - title: '{% trans "Active parts" %}', - description: '{% trans "Show stock for active parts" %}', + title: '{% trans "Depleted" %}', + description: '{% trans "Show stock items which are depleted" %}', }, - status: { - options: stockCodes, - title: '{% trans "Stock status" %}', - description: '{% trans "Stock status" %}', - }, - allocated: { + in_stock: { type: 'bool', - title: '{% trans "Is allocated" %}', - description: '{% trans "Item has been alloacted" %}', + title: '{% trans "In Stock" %}', + description: '{% trans "Show items which are in stock" %}', + }, + sent_to_customer: { + type: 'bool', + title: '{% trans "Sent to customer" %}', + description: '{% trans "Show items which have been assigned to a customer" %}', }, serialized: { type: 'bool', @@ -69,6 +74,11 @@ function getAvailableTableFilters(tableKey) { title: "{% trans "Serial number LTE" %}", description: "{% trans "Serial number less than or equal to" %}", }, + status: { + options: stockCodes, + title: '{% trans "Stock status" %}', + description: '{% trans "Stock status" %}', + }, }; } diff --git a/InvenTree/templates/status_codes.html b/InvenTree/templates/status_codes.html index 029252a842..f032f97309 100644 --- a/InvenTree/templates/status_codes.html +++ b/InvenTree/templates/status_codes.html @@ -18,14 +18,18 @@ function {{ label }}StatusDisplay(key) { key = String(key); - var value = {{ label }}Codes[key].value; + var value = null; + var label = null; + + if (key in {{ label }}Codes) { + value = {{ label }}Codes[key].value; + label = {{ label }}Codes[key].label; + } if (value == null || value.length == 0) { value = key; + label = ''; } - // Select the label color - var label = {{ label }}Codes[key].label ?? ''; - return `${value}`; } diff --git a/Makefile b/Makefile index 0072e1ad9c..cc3a3043a6 100644 --- a/Makefile +++ b/Makefile @@ -51,12 +51,12 @@ style: # Run unit tests test: cd InvenTree && python3 manage.py check - cd InvenTree && python3 manage.py test barcode build common company order part report stock InvenTree + cd InvenTree && python3 manage.py test barcode build common company label order part report stock InvenTree # Run code coverage coverage: cd InvenTree && python3 manage.py check - coverage run InvenTree/manage.py test barcode build common company order part report stock InvenTree + coverage run InvenTree/manage.py test barcode build common company label order part report stock InvenTree coverage html # Install packages required to generate code docs diff --git a/README.md b/README.md index a66e3c10ff..1ada93e6b9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Build Status](https://travis-ci.org/inventree/InvenTree.svg?branch=master)](https://travis-ci.org/inventree/InvenTree) [![Documentation Status](https://readthedocs.org/projects/inventree/badge/?version=latest)](https://inventree.readthedocs.io/en/latest/?badge=latest) [![Coverage Status](https://coveralls.io/repos/github/inventree/InvenTree/badge.svg)](https://coveralls.io/github/inventree/InvenTree) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Build Status](https://travis-ci.org/inventree/InvenTree.svg?branch=master)](https://travis-ci.org/inventree/InvenTree) [![Coverage Status](https://coveralls.io/repos/github/inventree/InvenTree/badge.svg)](https://coveralls.io/github/inventree/InvenTree) InvenTree @@ -15,7 +15,7 @@ Refer to the [getting started guide](https://inventree.github.io/docs/start/inst ## Documentation -For InvenTree documentation, refer to the [InvenTre documentation website](https://inventree.github.io). +For InvenTree documentation, refer to the [InvenTree documentation website](https://inventree.github.io). ## Integration diff --git a/requirements.txt b/requirements.txt index 76b9cf12f0..354c7ea316 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ wheel>=0.34.2 # Wheel Django==3.0.7 # Django package -pillow==6.2.2 # Image manipulation +pillow==7.1.0 # Image manipulation +blabel==0.1.3 # Simple PDF label printing djangorestframework==3.10.3 # DRF framework django-dbbackup==3.3.0 # Database backup / restore functionality django-cors-headers==3.2.0 # CORS headers extension for DRF @@ -15,10 +16,11 @@ django-crispy-forms==1.8.1 # Form helpers django-import-export==2.0.0 # Data import / export for admin interface django-cleanup==4.0.0 # Manage deletion of old / unused uploaded files django-qr-code==1.2.0 # Generate QR codes -flake8==3.3.0 # PEP checking +flake8==3.8.3 # PEP checking coverage==4.0.3 # Unit test coverage python-coveralls==2.9.1 # Coveralls linking (for Travis) rapidfuzz==0.7.6 # Fuzzy string matching django-stdimage==5.1.1 # Advanced ImageField management django-tex==1.1.7 # LaTeX PDF export -django-weasyprint==1.0.1 # HTML PDF export \ No newline at end of file +django-weasyprint==1.0.1 # HTML PDF export +django-debug-toolbar==2.2 # Debug / profiling toolbar \ No newline at end of file