From 440a5fafead8f9b08ca4266f1f3b39775256e7e5 Mon Sep 17 00:00:00 2001 From: eeintech Date: Fri, 4 Sep 2020 14:02:12 -0500 Subject: [PATCH 01/11] Implemented part parameters copy from template/original part --- InvenTree/part/forms.py | 18 +++++++++++++----- InvenTree/part/models.py | 19 +++++++++++++++++++ InvenTree/part/views.py | 21 ++++++++++++++------- 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py index a578e19011..277b687076 100644 --- a/InvenTree/part/forms.py +++ b/InvenTree/part/forms.py @@ -129,10 +129,17 @@ class EditPartForm(HelperForm): 'IPN': 'fa-hashtag', } - deep_copy = forms.BooleanField(required=False, - initial=True, - help_text=_("Perform 'deep copy' which will duplicate all BOM data for this part"), - widget=forms.HiddenInput()) + bom_copy = forms.BooleanField(required=False, + initial=True, + help_text=_("Duplicate all BOM data for this part"), + label=_('Copy BOM'), + widget=forms.HiddenInput()) + + parameters_copy = forms.BooleanField(required=False, + initial=True, + help_text=_("Duplicate all parameters data for this part"), + label=_('Copy Parameters'), + widget=forms.HiddenInput()) confirm_creation = forms.BooleanField(required=False, initial=False, @@ -142,7 +149,8 @@ class EditPartForm(HelperForm): class Meta: model = Part fields = [ - 'deep_copy', + 'bom_copy', + 'parameters_copy', 'confirm_creation', 'category', 'name', diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 18f10a902d..f1b0890cba 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -1041,6 +1041,7 @@ class Part(MPTTModel): Keyword Args: image: If True, copies Part image (default = True) bom: If True, copies BOM data (default = False) + parameters: If True, copies Parameters data (default = True) """ # Copy the part image @@ -1058,6 +1059,17 @@ class Part(MPTTModel): item.pk = None item.save() + # Copy the parameters data + if kwargs.get('parameters', True): + # Get template part parameters + parameters = other.get_parameters() + # Copy template part parameters to new variant part + for parameter in parameters: + PartParameter.create(part=self, + template=parameter.template, + data=parameter.data, + save=True) + # Copy the fields that aren't available in the duplicate form self.salable = other.salable self.assembly = other.assembly @@ -1402,6 +1414,13 @@ class PartParameter(models.Model): data = models.CharField(max_length=500, help_text=_('Parameter Value')) + @classmethod + def create(cls, part, template, data, save=False): + part_parameter = cls(part=part, template=template, data=data) + if save: + part_parameter.save() + return part_parameter + class BomItem(models.Model): """ A BomItem links a part to its component items. diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index f2d0089e60..64edb15d20 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -330,7 +330,7 @@ class MakePartVariant(AjaxCreateView): data['url'] = part.get_absolute_url() # Copy relevent information from the template part - part.deepCopy(part_template, bom=True) + part.deepCopy(part_template, bom=True, parameters=True) return self.renderJsonResponse(request, form, data, context=context) @@ -377,15 +377,19 @@ class PartDuplicate(AjaxCreateView): def get_form(self): form = super(AjaxCreateView, self).get_form() - # Force display of the 'deep_copy' widget - form.fields['deep_copy'].widget = CheckboxInput() + # Force display of the 'bom_copy' widget + form.fields['bom_copy'].widget = CheckboxInput() + + # Force display of the 'parameters_copy' widget + form.fields['parameters_copy'].widget = CheckboxInput() return form def post(self, request, *args, **kwargs): """ Capture the POST request for part duplication - - If the deep_copy object is set, copy all the BOM items too! + - If the bom_copy object is set, copy all the BOM items too! + - If the parameters_copy object is set, copy all the parameters too! """ form = self.get_form() @@ -428,12 +432,13 @@ class PartDuplicate(AjaxCreateView): data['pk'] = part.pk data['text'] = str(part) - deep_copy = str2bool(request.POST.get('deep_copy', False)) + bom_copy = str2bool(request.POST.get('bom_copy', False)) + parameters_copy = str2bool(request.POST.get('parameters_copy', False)) original = self.get_part_to_copy() if original: - part.deepCopy(original, bom=deep_copy) + part.deepCopy(original, bom=bom_copy, parameters=parameters_copy) try: data['url'] = part.get_absolute_url() @@ -456,7 +461,9 @@ class PartDuplicate(AjaxCreateView): else: initials = super(AjaxCreateView, self).get_initial() - initials['deep_copy'] = str2bool(InvenTreeSetting.get_setting('part_deep_copy', True)) + initials['bom_copy'] = str2bool(InvenTreeSetting.get_setting('part_deep_copy', True)) + # Create new entry in InvenTree/common/kvp.yaml? + initials['parameters_copy'] = str2bool(InvenTreeSetting.get_setting('part_deep_copy', True)) return initials From c4989e59b257bc996a6dcc85aa9934392d37eb53 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 5 Sep 2020 20:10:18 +1000 Subject: [PATCH 02/11] Allow selection of bom_copy and parameter_copy when making a new variant --- InvenTree/part/forms.py | 2 +- InvenTree/part/views.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py index 277b687076..ffcb46114a 100644 --- a/InvenTree/part/forms.py +++ b/InvenTree/part/forms.py @@ -137,7 +137,7 @@ class EditPartForm(HelperForm): parameters_copy = forms.BooleanField(required=False, initial=True, - help_text=_("Duplicate all parameters data for this part"), + help_text=_("Duplicate all parameter data for this part"), label=_('Copy Parameters'), widget=forms.HiddenInput()) diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index 64edb15d20..a33946de3d 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -303,6 +303,12 @@ class MakePartVariant(AjaxCreateView): # Hide some variant-related fields # form.fields['variant_of'].widget = HiddenInput() + # Force display of the 'bom_copy' widget + form.fields['bom_copy'].widget = CheckboxInput() + + # Force display of the 'parameters_copy' widget + form.fields['parameters_copy'].widget = CheckboxInput() + return form def post(self, request, *args, **kwargs): @@ -329,8 +335,11 @@ class MakePartVariant(AjaxCreateView): data['text'] = str(part) data['url'] = part.get_absolute_url() + bom_copy = str2bool(request.POST.get('bom_copy', False)) + parameters_copy = str2bool(request.POST.get('parameters_copy', False)) + # Copy relevent information from the template part - part.deepCopy(part_template, bom=True, parameters=True) + part.deepCopy(part_template, bom=bom_copy, parameters=parameters_copy) return self.renderJsonResponse(request, form, data, context=context) From f737ad2d389dd30cb9f2912a7110eef6b140cd87 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 5 Sep 2020 20:31:18 +1000 Subject: [PATCH 03/11] Bugfix: CreateStockItem form - hide the field rather than popping it --- InvenTree/stock/views.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index 2833a47af9..aadac17c7a 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -1243,12 +1243,12 @@ class StockItemCreate(AjaxCreateView): # Hide the 'part' field (as a valid part is selected) # form.fields['part'].widget = HiddenInput() - # trackable parts get special consideration + # Trackable parts get special consideration: if part.trackable: form.fields['delete_on_deplete'].widget = HiddenInput() form.fields['delete_on_deplete'].initial = False else: - form.fields.pop('serial_numbers') + form.fields['serial_numbers'].widget = HiddenInput() # If the part is NOT purchaseable, hide the supplier_part field if not part.purchaseable: @@ -1306,11 +1306,9 @@ class StockItemCreate(AjaxCreateView): supplier_part = None if part is not None: - # Check that the supplied part is 'valid' - if not part.is_template and part.active and not part.virtual: - initials['part'] = part - initials['location'] = part.get_default_location() - initials['supplier_part'] = part.default_supplier + initials['part'] = part + initials['location'] = part.get_default_location() + initials['supplier_part'] = part.default_supplier # SupplierPart field has been specified # It must match the Part, if that has been supplied From 42967905bc17bb3538bb51bd87a6bfe17ba231b0 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 5 Sep 2020 22:35:19 +1000 Subject: [PATCH 04/11] New approach for multiple annotations - Use the django-sql-utils addon - https://github.com/martsberger/django-sql-utils - The "distinct=True" flag was not doing what I thought it was doing... --- InvenTree/part/api.py | 1 + InvenTree/part/serializers.py | 56 ++++++++++++++++++++++---------- InvenTree/templates/js/part.html | 3 ++ requirements.txt | 1 + 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index 80e45523c9..abc4181895 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -377,6 +377,7 @@ class PartList(generics.ListCreateAPIView): def get_queryset(self, *args, **kwargs): queryset = super().get_queryset(*args, **kwargs) + queryset = part_serializers.PartSerializer.prefetch_queryset(queryset) queryset = part_serializers.PartSerializer.annotate_queryset(queryset) diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index c1ecfb5cce..09b5b21d91 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -15,7 +15,9 @@ from .models import PartTestTemplate from decimal import Decimal -from django.db.models import Q, Sum +from sql_util.utils import SubquerySum + +from django.db.models import Q from django.db.models.functions import Coalesce from InvenTree.status_codes import StockStatus, PurchaseOrderStatus, BuildStatus @@ -190,28 +192,48 @@ class PartSerializer(InvenTreeModelSerializer): """ # Filter to limit stock items to "available" - stock_filter = Q(stock_items__status__in=StockStatus.AVAILABLE_CODES) + stock_filter = Q( + status__in=StockStatus.AVAILABLE_CODES, + sales_order=None, + build_order=None, + belongs_to=None, + customer=None, + ) - # Filter to limit orders to "open" - order_filter = Q(supplier_parts__purchase_order_line_items__order__status__in=PurchaseOrderStatus.OPEN) + # Annotate with the total 'in stock' quantity + queryset = queryset.annotate( + in_stock=Coalesce( + SubquerySum('stock_items__quantity', filter=stock_filter), + Decimal(0) + ), + ) # Filter to limit builds to "active" - build_filter = Q(builds__status__in=BuildStatus.ACTIVE_CODES) + build_filter = Q( + status__in=BuildStatus.ACTIVE_CODES + ) - # Annotate the number total stock count + # Annotate with the total 'building' quantity queryset = queryset.annotate( - in_stock=Coalesce(Sum('stock_items__quantity', filter=stock_filter, distinct=True), Decimal(0)), - ordering=Coalesce(Sum( - 'supplier_parts__purchase_order_line_items__quantity', - filter=order_filter, - distinct=True - ), Decimal(0)) - Coalesce(Sum( - 'supplier_parts__purchase_order_line_items__received', - filter=order_filter, - distinct=True - ), Decimal(0)), building=Coalesce( - Sum('builds__quantity', filter=build_filter, distinct=True), Decimal(0) + SubquerySum('builds__quantity', filter=build_filter), + Decimal(0), + ) + ) + + # Filter to limit orders to "open" + order_filter = Q( + order__status__in=PurchaseOrderStatus.OPEN + ) + + # Annotate with the total 'on order' quantity + queryset = queryset.annotate( + ordering=Coalesce( + SubquerySum('supplier_parts__purchase_order_line_items__quantity', filter=order_filter), + Decimal(0), + ) - Coalesce( + SubquerySum('supplier_parts__purchase_order_line_items__received', filter=order_filter), + Decimal(0), ) ) diff --git a/InvenTree/templates/js/part.html b/InvenTree/templates/js/part.html index 2fdcfd57f7..03c98e09a4 100644 --- a/InvenTree/templates/js/part.html +++ b/InvenTree/templates/js/part.html @@ -122,6 +122,9 @@ function loadPartVariantTable(table, partId, options) { { field: 'in_stock', title: '{% trans "Stock" %}', + formatter: function(value, row) { + return renderLink(value, `/part/${row.pk}/stock/`); + } } ]; diff --git a/requirements.txt b/requirements.txt index 38b5a37b6d..8faa7f58a5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,6 +7,7 @@ django-dbbackup==3.3.0 # Database backup / restore functionality django-cors-headers==3.2.0 # CORS headers extension for DRF django_filter==2.2.0 # Extended filtering options django-mptt==0.11.0 # Modified Preorder Tree Traversal +django-sql-utils==0.5.0 # Advanced query annotation / aggregation django-markdownx==3.0.1 # Markdown form fields django-markdownify==0.8.0 # Markdown rendering coreapi==2.3.0 # API documentation From db214dfd731d98a0da2f77900f971d008ecd8ad8 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 5 Sep 2020 22:50:17 +1000 Subject: [PATCH 05/11] Update queryset annotation for StockItem - Query time reduced from 4.1 to 3.5s (for sample data) --- InvenTree/stock/serializers.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index f50b8572c9..4a9b5a886b 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -9,9 +9,12 @@ from .models import StockItemTracking from .models import StockItemAttachment from .models import StockItemTestResult -from django.db.models import Sum, Count from django.db.models.functions import Coalesce +from sql_util.utils import SubquerySum, SubqueryCount + +from decimal import Decimal + from company.serializers import SupplierPartSerializer from part.serializers import PartBriefSerializer from InvenTree.serializers import UserSerializerBrief, InvenTreeModelSerializer @@ -90,11 +93,18 @@ class StockItemSerializer(InvenTreeModelSerializer): performing database queries as efficiently as possible. """ + # Annotate the queryset with the total allocated to sales orders queryset = queryset.annotate( allocated=Coalesce( - Sum('sales_order_allocations__quantity', distinct=True), 0) + Coalesce( - Sum('allocations__quantity', distinct=True), 0), - tracking_items=Count('tracking_info'), + SubquerySum('sales_order_allocations__quantity'), Decimal(0) + ) + Coalesce( + SubquerySum('allocations__quantity'), Decimal(0) + ) + ) + + # Annotate the queryset with the number of tracking items + queryset = queryset.annotate( + tracking_items=SubqueryCount('tracking_info') ) return queryset From 598e15af4632a6077f3838f64c6ad3b50d0da1b7 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 5 Sep 2020 23:03:38 +1000 Subject: [PATCH 06/11] Fix annotations for Company serializers --- InvenTree/company/serializers.py | 14 ++- .../company/templates/company/index.html | 1 + InvenTree/company/views.py | 4 + InvenTree/templates/js/company.html | 116 +++++++++++------- 4 files changed, 84 insertions(+), 51 deletions(-) diff --git a/InvenTree/company/serializers.py b/InvenTree/company/serializers.py index 16e7911ceb..a80b3b55a9 100644 --- a/InvenTree/company/serializers.py +++ b/InvenTree/company/serializers.py @@ -4,7 +4,7 @@ JSON serializers for Company app from rest_framework import serializers -from django.db.models import Count +from sql_util.utils import SubqueryCount from .models import Company from .models import SupplierPart, SupplierPriceBreak @@ -38,11 +38,17 @@ class CompanySerializer(InvenTreeModelSerializer): @staticmethod def annotate_queryset(queryset): - return queryset.annotate( - parts_supplied=Count('supplied_parts'), - parts_manufactured=Count('manufactured_parts') + # Add count of parts manufactured + queryset = queryset.annotate( + parts_manufactured=SubqueryCount('manufactured_parts') ) + queryset = queryset.annotate( + parts_supplied=SubqueryCount('supplied_parts') + ) + + return queryset + url = serializers.CharField(source='get_absolute_url', read_only=True) image = serializers.CharField(source='get_thumbnail_url', read_only=True) diff --git a/InvenTree/company/templates/company/index.html b/InvenTree/company/templates/company/index.html index f337019409..253085568e 100644 --- a/InvenTree/company/templates/company/index.html +++ b/InvenTree/company/templates/company/index.html @@ -33,6 +33,7 @@ InvenTree | {% trans "Supplier List" %} loadCompanyTable("#company-table", "{% url 'api-company-list' %}", { + pagetype: '{{ pagetype }}', params: { {% for key,value in filters.items %}{{ key }}: "{{ value }}",{% endfor %} } diff --git a/InvenTree/company/views.py b/InvenTree/company/views.py index 3f8cde21d3..457cf74ec2 100644 --- a/InvenTree/company/views.py +++ b/InvenTree/company/views.py @@ -51,18 +51,21 @@ class CompanyIndex(ListView): 'button_text': _('New Supplier'), 'filters': {'is_supplier': 'true'}, 'create_url': reverse('supplier-create'), + 'pagetype': 'suppliers', }, reverse('manufacturer-index'): { 'title': _('Manufacturers'), 'button_text': _('New Manufacturer'), 'filters': {'is_manufacturer': 'true'}, 'create_url': reverse('manufacturer-create'), + 'pagetype': 'manufacturers', }, reverse('customer-index'): { 'title': _('Customers'), 'button_text': _('New Customer'), 'filters': {'is_customer': 'true'}, 'create_url': reverse('customer-create'), + 'pagetype': 'customers', } } @@ -71,6 +74,7 @@ class CompanyIndex(ListView): 'button_text': _('New Company'), 'filters': {}, 'create_url': reverse('company-create'), + 'pagetype': 'companies' } context = None diff --git a/InvenTree/templates/js/company.html b/InvenTree/templates/js/company.html index ef80070d99..f904c0f506 100644 --- a/InvenTree/templates/js/company.html +++ b/InvenTree/templates/js/company.html @@ -21,6 +21,73 @@ function loadCompanyTable(table, url, options={}) { setupFilterList("company", $(table)); + var columns = [ + { + field: 'pk', + title: 'ID', + visible: false, + switchable: false, + }, + { + field: 'name', + title: '{% trans "Company" %}', + sortable: true, + switchable: false, + formatter: function(value, row, index, field) { + var html = imageHoverIcon(row.image) + renderLink(value, row.url); + + if (row.is_customer) { + html += ``; + } + + if (row.is_manufacturer) { + html += ``; + } + + if (row.is_supplier) { + html += ``; + } + + return html; + } + }, + { + field: 'description', + title: '{% trans "Description" %}', + sortable: true, + }, + { + field: 'website', + title: '{% trans "Website" %}', + formatter: function(value, row, index, field) { + if (value) { + return renderLink(value, value); + } + return ''; + } + }, + ]; + + if (options.pagetype == 'suppliers') { + columns.push({ + sortable: true, + field: 'parts_supplied', + title: '{% trans "Parts Supplied" %}', + formatter: function(value, row) { + return renderLink(value, `/company/${row.pk}/parts/`); + } + }); + } else if (options.pagetype == 'manufacturers') { + columns.push({ + sortable: true, + field: 'parts_manufactured', + title: '{% trans "Parts Manufactured" %}', + formatter: function(value, row) { + return renderLink(value, `/company/${row.pk}/parts/`); + } + }); + } + $(table).inventreeTable({ url: url, method: 'get', @@ -28,53 +95,8 @@ function loadCompanyTable(table, url, options={}) { groupBy: false, formatNoMatches: function() { return "{% trans "No company information found" %}"; }, showColumns: true, - name: 'company', - columns: [ - { - field: 'pk', - title: 'ID', - visible: false, - switchable: false, - }, - { - field: 'name', - title: '{% trans "Company" %}', - sortable: true, - switchable: false, - formatter: function(value, row, index, field) { - var html = imageHoverIcon(row.image) + renderLink(value, row.url); - - if (row.is_customer) { - html += ``; - } - - if (row.is_manufacturer) { - html += ``; - } - - if (row.is_supplier) { - html += ``; - } - - return html; - } - }, - { - field: 'description', - title: '{% trans "Description" %}', - sortable: true, - }, - { - field: 'website', - title: '{% trans "Website" %}', - formatter: function(value, row, index, field) { - if (value) { - return renderLink(value, value); - } - return ''; - } - }, - ], + name: options.pagetype || 'company', + columns: columns, }); } From 5f2e4c3790fff2aa408bbb59e702d99a5a0082e7 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 5 Sep 2020 23:08:59 +1000 Subject: [PATCH 07/11] Update serializers for Order model --- InvenTree/order/serializers.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index 2f87727ced..e9838f3347 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -7,7 +7,7 @@ from __future__ import unicode_literals from rest_framework import serializers -from django.db.models import Count +from sql_util.utils import SubqueryCount from InvenTree.serializers import InvenTreeModelSerializer from InvenTree.serializers import InvenTreeAttachmentSerializerField @@ -39,10 +39,12 @@ class POSerializer(InvenTreeModelSerializer): Add extra information to the queryset """ - return queryset.annotate( - line_items=Count('lines'), + queryset = queryset.annotate( + line_items=SubqueryCount('lines') ) + return queryset + supplier_detail = CompanyBriefSerializer(source='supplier', many=False, read_only=True) line_items = serializers.IntegerField(read_only=True) @@ -147,10 +149,12 @@ class SalesOrderSerializer(InvenTreeModelSerializer): Add extra information to the queryset """ - return queryset.annotate( - line_items=Count('lines'), + queryset = queryset.annotate( + line_items=SubqueryCount('lines') ) + return queryset + customer_detail = CompanyBriefSerializer(source='customer', many=False, read_only=True) line_items = serializers.IntegerField(read_only=True) From f7ad38dad5ffc28689eca78961322b830a6a12c4 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 5 Sep 2020 23:28:54 +1000 Subject: [PATCH 08/11] Add unit tests for new aggregation annotation approach --- InvenTree/company/fixtures/company.yaml | 9 ++- InvenTree/part/serializers.py | 9 ++- InvenTree/part/test_api.py | 81 +++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 2 deletions(-) diff --git a/InvenTree/company/fixtures/company.yaml b/InvenTree/company/fixtures/company.yaml index e83d886812..69edee693a 100644 --- a/InvenTree/company/fixtures/company.yaml +++ b/InvenTree/company/fixtures/company.yaml @@ -14,4 +14,11 @@ pk: 3 fields: name: Zerg Corp - description: We eat the competition \ No newline at end of file + description: We eat the competition +- model: company.company + pk: 4 + fields: + name: A customer + description: A company that we sell things to! + is_customer: True + \ No newline at end of file diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index 09b5b21d91..bab58f8dbe 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -15,7 +15,7 @@ from .models import PartTestTemplate from decimal import Decimal -from sql_util.utils import SubquerySum +from sql_util.utils import SubquerySum, SubqueryCount from django.db.models import Q from django.db.models.functions import Coalesce @@ -208,6 +208,11 @@ class PartSerializer(InvenTreeModelSerializer): ), ) + # Annotate with the total number of stock items + queryset = queryset.annotate( + stock_item_count=SubqueryCount('stock_items') + ) + # Filter to limit builds to "active" build_filter = Q( status__in=BuildStatus.ACTIVE_CODES @@ -253,6 +258,7 @@ class PartSerializer(InvenTreeModelSerializer): in_stock = serializers.FloatField(read_only=True) ordering = serializers.FloatField(read_only=True) building = serializers.FloatField(read_only=True) + stock_item_count = serializers.IntegerField(read_only=True) image = serializers.CharField(source='get_image_url', read_only=True) thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True) @@ -295,6 +301,7 @@ class PartSerializer(InvenTreeModelSerializer): 'revision', 'salable', 'starred', + 'stock_item_count', 'thumbnail', 'trackable', 'units', diff --git a/InvenTree/part/test_api.py b/InvenTree/part/test_api.py index 9fcf98d712..3b116fa445 100644 --- a/InvenTree/part/test_api.py +++ b/InvenTree/part/test_api.py @@ -1,8 +1,15 @@ from rest_framework.test import APITestCase from rest_framework import status + from django.urls import reverse from django.contrib.auth import get_user_model +from part.models import Part +from stock.models import StockItem +from company.models import Company + +from InvenTree.status_codes import StockStatus + class PartAPITest(APITestCase): """ @@ -213,3 +220,77 @@ class PartAPITest(APITestCase): ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + +class PartAPIAggregationTest(APITestCase): + """ + Tests to ensure that the various aggregation annotations are working correctly... + """ + + fixtures = [ + 'category', + 'company', + 'part', + 'location', + 'bom', + 'test_templates', + ] + + def setUp(self): + # Create a user for auth + User = get_user_model() + User.objects.create_user('testuser', 'test@testing.com', 'password') + + self.client.login(username='testuser', password='password') + + # Add a new part + self.part = Part.objects.create( + name='Banana', + ) + + # Create some stock items associated with the part + + # First create 600 units which are OK + StockItem.objects.create(part=self.part, quantity=100) + StockItem.objects.create(part=self.part, quantity=200) + StockItem.objects.create(part=self.part, quantity=300) + + # Now create another 400 units which are LOST + StockItem.objects.create(part=self.part, quantity=400, status=StockStatus.LOST) + + def get_part_data(self): + url = reverse('api-part-list') + + response = self.client.get(url, format='json') + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + for part in response.data: + if part['pk'] == self.part.pk: + return part + + # We should never get here! + self.assertTrue(False) + + def test_stock_quantity(self): + """ + Simple test for the stock quantity + """ + + data = self.get_part_data() + + self.assertEqual(data['in_stock'], 600) + self.assertEqual(data['stock_item_count'], 4) + + # Add some more stock items!! + for i in range(100): + StockItem.objects.create(part=self.part, quantity=5) + + # Add another stock item which is assigned to a customer (and shouldn't count) + customer = Company.objects.get(pk=4) + StockItem.objects.create(part=self.part, quantity=9999, customer=customer) + + data = self.get_part_data() + + self.assertEqual(data['in_stock'], 1100) + self.assertEqual(data['stock_item_count'], 105) From 2cf40c0e0b147ab8d06baa470f6e393d72c3127b Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 5 Sep 2020 23:32:36 +1000 Subject: [PATCH 09/11] Translation updates --- InvenTree/locale/de/LC_MESSAGES/django.mo | Bin 50156 -> 49966 bytes InvenTree/locale/de/LC_MESSAGES/django.po | 370 ++++++++++++-------- InvenTree/locale/en/LC_MESSAGES/django.po | 342 ++++++++++-------- InvenTree/locale/es/LC_MESSAGES/django.po | 342 ++++++++++-------- InvenTree/part/templates/part/category.html | 42 +-- 5 files changed, 665 insertions(+), 431 deletions(-) diff --git a/InvenTree/locale/de/LC_MESSAGES/django.mo b/InvenTree/locale/de/LC_MESSAGES/django.mo index e05de8f1f54ac04ca54ef085ecc7f643773864bd..272b16c0d6cc083b978bb5b3b2f3ea2a62d9763b 100644 GIT binary patch delta 15637 zcmY+~2Xq$2`}XmLgpdRXA)$nxPy+!1gf6|;(3Bz|gbq=VDn)tdAiWpqAcS5-n$oL+ z3IRa@rHD!qeu{vii2lFVGdJ(y-E$_NnR{kuW@lzM!Q=f&0b3^q_^w3+&iA-3ruDo$ zcs#r3oeJ>0H%lt&d6TPpUS@nBgK#ls#FZF^TQC#uN3}bRdGQM7!lxFGtmb)9lnY`W ztcqDY&*!x#6GyP@aw9xCC|MW=xMKP!sqP)8Q3V`x~eU+(S+5Z_I%q)%^o` zF{pTgSsOzb-)l)mH+H~Un2b4bi+Ku5Q@)8>l!zLhN8eseRD6`V4dW@_u=?{UfQP$K5T-l+DI(3g$OYzw5ImUIVd#(OXtkD_k8W%0DNUB{VF@%*U!s-q@e7xh4` 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 delta 15814 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 diff --git a/InvenTree/locale/de/LC_MESSAGES/django.po b/InvenTree/locale/de/LC_MESSAGES/django.po index 16356efbab..c4036bfc49 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-09-02 13:57+0000\n" +"POT-Creation-Date: 2020-09-05 13:32+0000\n" "PO-Revision-Date: 2020-05-03 11:32+0200\n" "Last-Translator: Christian Schlüter \n" "Language-Team: C \n" @@ -302,7 +302,7 @@ msgstr "Eltern-Bau, dem dieser Bau zugewiesen ist" #: part/templates/part/part_app_base.html:7 #: part/templates/part/set_category.html:13 templates/js/barcode.html:336 #: templates/js/bom.html:135 templates/js/build.html:43 -#: templates/js/company.html:115 templates/js/part.html:212 +#: templates/js/company.html:137 templates/js/part.html:215 #: templates/js/stock.html:429 msgid "Part" msgstr "Teil" @@ -418,6 +418,7 @@ msgstr "Lagerobjekt-Anzahl dem Bau zuweisen" #: build/templates/build/allocate.html:17 #: company/templates/company/detail_part.html:18 order/views.py:779 +#: part/templates/part/category.html:106 msgid "Order Parts" msgstr "Teile bestellen" @@ -491,10 +492,10 @@ msgstr "Keine BOM-Einträge gefunden" #: company/templates/company/supplier_part_detail.html:27 #: order/templates/order/purchase_order_detail.html:159 #: part/templates/part/detail.html:51 part/templates/part/set_category.html:14 -#: templates/js/bom.html:158 templates/js/company.html:64 +#: templates/js/bom.html:158 templates/js/company.html:56 #: templates/js/order.html:159 templates/js/order.html:234 -#: templates/js/part.html:120 templates/js/part.html:268 -#: templates/js/part.html:449 templates/js/stock.html:444 +#: templates/js/part.html:120 templates/js/part.html:271 +#: templates/js/part.html:452 templates/js/stock.html:444 #: templates/js/stock.html:658 msgid "Description" msgstr "Beschreibung" @@ -505,8 +506,8 @@ msgstr "Beschreibung" msgid "Reference" msgstr "Referenz" -#: build/templates/build/allocate.html:338 part/models.py:1320 -#: templates/js/part.html:453 templates/js/table_filters.html:100 +#: build/templates/build/allocate.html:338 part/models.py:1332 +#: templates/js/part.html:456 templates/js/table_filters.html:100 msgid "Required" msgstr "benötigt" @@ -881,7 +882,7 @@ msgid "Description of the company" msgstr "Firmenbeschreibung" #: company/models.py:91 company/templates/company/company_base.html:48 -#: templates/js/company.html:69 +#: templates/js/company.html:61 msgid "Website" msgstr "Website" @@ -988,7 +989,7 @@ msgid "Assigned Stock" msgstr "Zugewiesen" #: company/templates/company/company_base.html:7 -#: company/templates/company/company_base.html:22 templates/js/company.html:41 +#: company/templates/company/company_base.html:22 templates/js/company.html:33 msgid "Company" msgstr "Firma" @@ -1004,7 +1005,7 @@ msgstr "Telefon" #: company/templates/company/detail.html:16 #: company/templates/company/supplier_part_base.html:76 #: company/templates/company/supplier_part_detail.html:30 part/bom.py:172 -#: templates/js/company.html:52 templates/js/company.html:164 +#: templates/js/company.html:44 templates/js/company.html:186 msgid "Manufacturer" msgstr "Hersteller" @@ -1013,15 +1014,15 @@ msgstr "Hersteller" #: company/templates/company/supplier_part_detail.html:21 #: order/templates/order/order_base.html:74 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:170 -#: stock/templates/stock/item_base.html:239 templates/js/company.html:56 -#: templates/js/company.html:140 templates/js/order.html:146 +#: stock/templates/stock/item_base.html:239 templates/js/company.html:48 +#: templates/js/company.html:162 templates/js/order.html:146 msgid "Supplier" msgstr "Zulieferer" #: company/templates/company/detail.html:26 #: order/templates/order/sales_order_base.html:73 stock/models.py:354 #: stock/models.py:355 stock/templates/stock/item_base.html:161 -#: templates/js/company.html:48 templates/js/order.html:221 +#: templates/js/company.html:40 templates/js/order.html:221 msgid "Customer" msgstr "Kunde" @@ -1036,7 +1037,8 @@ msgid "New Supplier Part" msgstr "Neues Zulieferer-Teil" #: company/templates/company/detail_part.html:15 -#: part/templates/part/supplier.html:14 templates/stock_table.html:10 +#: part/templates/part/category.html:103 part/templates/part/supplier.html:14 +#: templates/stock_table.html:10 msgid "Options" msgstr "Optionen" @@ -1057,16 +1059,16 @@ msgstr "Neues Teil hinzufügen" msgid "New Supplier" msgstr "Neuer Zulieferer" -#: company/templates/company/detail_part.html:50 company/views.py:182 +#: company/templates/company/detail_part.html:50 company/views.py:186 msgid "Create new Supplier" msgstr "Neuen Zulieferer anlegen" -#: company/templates/company/detail_part.html:55 company/views.py:57 +#: company/templates/company/detail_part.html:55 company/views.py:58 #: part/templates/part/supplier.html:50 msgid "New Manufacturer" msgstr "Neuer Hersteller" -#: company/templates/company/detail_part.html:56 company/views.py:185 +#: company/templates/company/detail_part.html:56 company/views.py:189 msgid "Create new Manufacturer" msgstr "Neuen Hersteller anlegen" @@ -1076,6 +1078,7 @@ msgstr "Zuliefererbestand" #: company/templates/company/detail_stock.html:35 #: company/templates/company/supplier_part_stock.html:33 +#: part/templates/part/category.html:100 part/templates/part/category.html:107 #: part/templates/part/stock.html:51 templates/stock_table.html:5 msgid "Export" msgstr "Exportieren" @@ -1134,7 +1137,7 @@ msgstr "Neuer Auftrag" #: company/templates/company/supplier_part_base.html:6 #: company/templates/company/supplier_part_base.html:19 stock/models.py:328 -#: stock/templates/stock/item_base.html:244 templates/js/company.html:156 +#: stock/templates/stock/item_base.html:244 templates/js/company.html:178 msgid "Supplier Part" msgstr "Zulieferer-Teil" @@ -1168,7 +1171,7 @@ msgstr "SKU" #: company/templates/company/supplier_part_base.html:80 #: company/templates/company/supplier_part_detail.html:31 part/bom.py:173 -#: templates/js/company.html:180 +#: templates/js/company.html:202 msgid "MPN" msgstr "MPN" @@ -1221,7 +1224,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:124 -#: templates/js/part.html:295 templates/js/stock.html:452 +#: templates/js/part.html:298 templates/js/stock.html:452 #: templates/navbar.html:19 msgid "Stock" msgstr "Lagerbestand" @@ -1242,83 +1245,83 @@ msgstr "Teile" msgid "Suppliers" msgstr "Zulieferer" -#: company/views.py:56 templates/navbar.html:25 +#: company/views.py:57 templates/navbar.html:25 msgid "Manufacturers" msgstr "Hersteller" -#: company/views.py:62 templates/navbar.html:32 +#: company/views.py:64 templates/navbar.html:32 msgid "Customers" msgstr "Kunden" -#: company/views.py:63 +#: company/views.py:65 msgid "New Customer" msgstr "Neuer Kunde" -#: company/views.py:70 +#: company/views.py:73 msgid "Companies" msgstr "Firmen" -#: company/views.py:71 +#: company/views.py:74 msgid "New Company" msgstr "Neue Firma" -#: company/views.py:147 +#: company/views.py:151 msgid "Update Company Image" msgstr "Firmenbild aktualisieren" -#: company/views.py:152 +#: company/views.py:156 msgid "Updated company image" msgstr "Aktualisiertes Firmenbild" -#: company/views.py:162 +#: company/views.py:166 msgid "Edit Company" msgstr "Firma bearbeiten" -#: company/views.py:166 +#: company/views.py:170 msgid "Edited company information" msgstr "Firmeninformation bearbeitet" -#: company/views.py:188 +#: company/views.py:192 msgid "Create new Customer" msgstr "Neuen Kunden anlegen" -#: company/views.py:190 +#: company/views.py:194 msgid "Create new Company" msgstr "Neue Firma anlegen" -#: company/views.py:217 +#: company/views.py:221 msgid "Created new company" msgstr "Neue Firma angelegt" -#: company/views.py:227 +#: company/views.py:231 msgid "Delete Company" msgstr "Firma löschen" -#: company/views.py:232 +#: company/views.py:236 msgid "Company was deleted" msgstr "Firma gelöscht" -#: company/views.py:256 +#: company/views.py:260 msgid "Edit Supplier Part" msgstr "Zuliefererteil bearbeiten" -#: company/views.py:265 templates/js/stock.html:785 +#: company/views.py:269 templates/js/stock.html:785 msgid "Create new Supplier Part" msgstr "Neues Zuliefererteil anlegen" -#: company/views.py:325 +#: company/views.py:329 msgid "Delete Supplier Part" msgstr "Zuliefererteil entfernen" -#: company/views.py:395 +#: company/views.py:399 msgid "Add Price Break" msgstr "Preisstaffel hinzufügen" -#: company/views.py:437 +#: company/views.py:441 msgid "Edit Price Break" msgstr "Preisstaffel bearbeiten" -#: company/views.py:452 +#: company/views.py:456 msgid "Delete Price Break" msgstr "Preisstaffel löschen" @@ -1423,7 +1426,7 @@ msgstr "" msgid "Date order was completed" msgstr "Bestellung als vollständig markieren" -#: order/models.py:185 order/models.py:259 part/views.py:1250 +#: order/models.py:185 order/models.py:259 part/views.py:1266 #: stock/models.py:239 stock/models.py:682 msgid "Quantity must be greater than zero" msgstr "Anzahl muss größer Null sein" @@ -1609,6 +1612,7 @@ msgstr "Bestellpositionen" #: order/templates/order/purchase_order_detail.html:38 #: order/templates/order/purchase_order_detail.html:118 +#: part/templates/part/category.html:151 part/templates/part/category.html:192 #: templates/js/stock.html:790 msgid "New Location" msgstr "Neuer Standort" @@ -1654,7 +1658,7 @@ msgid "Select parts to receive against this order" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.html:311 +#: part/templates/part/part_base.html:129 templates/js/part.html:314 msgid "On Order" msgstr "bestellt" @@ -1983,20 +1987,36 @@ msgid "Select part category" msgstr "Teilekategorie wählen" #: part/forms.py:134 -msgid "Perform 'deep copy' which will duplicate all BOM data for this part" +#, fuzzy +#| msgid "Perform 'deep copy' which will duplicate all BOM data for this part" +msgid "Duplicate all BOM data for this part" msgstr "" "Tiefe Kopie ausführen. Dies wird alle Daten der Stückliste für dieses Teil " "duplizieren" -#: part/forms.py:139 +#: part/forms.py:135 +msgid "Copy BOM" +msgstr "" + +#: part/forms.py:140 +msgid "Duplicate all parameter data for this part" +msgstr "" + +#: part/forms.py:141 +#, fuzzy +#| msgid "Parameters" +msgid "Copy Parameters" +msgstr "Parameter" + +#: part/forms.py:146 msgid "Confirm part creation" msgstr "Erstellen des Teils bestätigen" -#: part/forms.py:237 +#: part/forms.py:245 msgid "Input quantity for price calculation" msgstr "Eintragsmenge zur Preisberechnung" -#: part/forms.py:240 +#: part/forms.py:248 msgid "Select currency for price calculation" msgstr "Währung zur Preisberechnung wählen" @@ -2130,13 +2150,13 @@ msgstr "Bemerkungen - unterstüzt Markdown-Formatierung" msgid "Stored BOM checksum" msgstr "Prüfsumme der Stückliste gespeichert" -#: part/models.py:1272 +#: part/models.py:1284 #, 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:1289 +#: part/models.py:1301 #, fuzzy #| msgid "" #| "A stock item with this serial number already exists for template part " @@ -2146,114 +2166,114 @@ msgstr "" "Ein Teil mit dieser Seriennummer existiert bereits für die Teilevorlage " "{part}" -#: part/models.py:1308 templates/js/part.html:444 templates/js/stock.html:92 +#: part/models.py:1320 templates/js/part.html:447 templates/js/stock.html:92 #, fuzzy #| msgid "Instance Name" msgid "Test Name" msgstr "Instanzname" -#: part/models.py:1309 +#: part/models.py:1321 #, fuzzy #| msgid "Serial number for this item" msgid "Enter a name for the test" msgstr "Seriennummer für dieses Teil" -#: part/models.py:1314 +#: part/models.py:1326 #, fuzzy #| msgid "Description" msgid "Test Description" msgstr "Beschreibung" -#: part/models.py:1315 +#: part/models.py:1327 #, fuzzy #| msgid "Brief description of the build" msgid "Enter description for this test" msgstr "Kurze Beschreibung des Baus" -#: part/models.py:1321 +#: part/models.py:1333 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:1326 templates/js/part.html:461 +#: part/models.py:1338 templates/js/part.html:464 #, fuzzy #| msgid "Required Parts" msgid "Requires Value" msgstr "benötigte Teile" -#: part/models.py:1327 +#: part/models.py:1339 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:1332 templates/js/part.html:468 +#: part/models.py:1344 templates/js/part.html:471 #, fuzzy #| msgid "Delete Attachment" msgid "Requires Attachment" msgstr "Anhang löschen" -#: part/models.py:1333 +#: part/models.py:1345 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:1366 +#: part/models.py:1378 msgid "Parameter template name must be unique" msgstr "Vorlagen-Name des Parameters muss eindeutig sein" -#: part/models.py:1371 +#: part/models.py:1383 msgid "Parameter Name" msgstr "Name des Parameters" -#: part/models.py:1373 +#: part/models.py:1385 msgid "Parameter Units" msgstr "Parameter Einheit" -#: part/models.py:1399 +#: part/models.py:1411 msgid "Parent Part" msgstr "Ausgangsteil" -#: part/models.py:1401 +#: part/models.py:1413 msgid "Parameter Template" msgstr "Parameter Vorlage" -#: part/models.py:1403 +#: part/models.py:1415 msgid "Parameter Value" msgstr "Parameter Wert" -#: part/models.py:1432 +#: part/models.py:1451 msgid "Select parent part" msgstr "Ausgangsteil auswählen" -#: part/models.py:1440 +#: part/models.py:1459 msgid "Select part to be used in BOM" msgstr "Teil für die Nutzung in der Stückliste auswählen" -#: part/models.py:1446 +#: part/models.py:1465 msgid "BOM quantity for this BOM item" msgstr "Stücklisten-Anzahl für dieses Stücklisten-Teil" -#: part/models.py:1449 +#: part/models.py:1468 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "Geschätzter Ausschuss (absolut oder prozentual)" -#: part/models.py:1452 +#: part/models.py:1471 msgid "BOM item reference" msgstr "Referenz des Objekts auf der Stückliste" -#: part/models.py:1455 +#: part/models.py:1474 msgid "BOM item notes" msgstr "Notizen zum Stücklisten-Objekt" -#: part/models.py:1457 +#: part/models.py:1476 msgid "BOM line checksum" msgstr "Prüfsumme der Stückliste" -#: part/models.py:1521 part/views.py:1256 part/views.py:1308 +#: part/models.py:1540 part/views.py:1272 part/views.py:1324 #: stock/models.py:229 #, 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:1530 +#: part/models.py:1549 #, fuzzy #| msgid "New BOM Item" msgid "BOM Item" @@ -2317,7 +2337,7 @@ msgstr "Stückliste bearbeiten" msgid "Validate Bill of Materials" msgstr "Stückliste validieren" -#: part/templates/part/bom.html:46 part/views.py:1543 +#: part/templates/part/bom.html:46 part/views.py:1559 msgid "Export Bill of Materials" msgstr "Stückliste exportieren" @@ -2409,6 +2429,22 @@ msgstr "" msgid "All parts" msgstr "Alle Teile" +#: part/templates/part/category.html:18 part/views.py:1897 +msgid "Create new part category" +msgstr "Teilkategorie anlegen" + +#: part/templates/part/category.html:22 +#, fuzzy +#| msgid "Edit Part Category" +msgid "Edit part category" +msgstr "Teilkategorie bearbeiten" + +#: part/templates/part/category.html:25 +#, fuzzy +#| msgid "Select part category" +msgid "Delete part category" +msgstr "Teilekategorie wählen" + #: part/templates/part/category.html:34 part/templates/part/category.html:73 msgid "Category Details" msgstr "Kategorie-Details" @@ -2433,6 +2469,62 @@ msgstr "Unter-Kategorien" msgid "Parts (Including subcategories)" msgstr "Teile (inklusive Unter-Kategorien)" +#: part/templates/part/category.html:100 +msgid "Export Part Data" +msgstr "" + +#: part/templates/part/category.html:105 +#, fuzzy +#| msgid "Part category" +msgid "Set category" +msgstr "Teile-Kategorie" + +#: part/templates/part/category.html:105 +#, fuzzy +#| msgid "Set Part Category" +msgid "Set Category" +msgstr "Teilkategorie auswählen" + +#: part/templates/part/category.html:106 +#, fuzzy +#| msgid "Order part" +msgid "Order parts" +msgstr "Teil bestellen" + +#: part/templates/part/category.html:107 +#, fuzzy +#| msgid "Export" +msgid "Export Data" +msgstr "Exportieren" + +#: part/templates/part/category.html:152 +#, fuzzy +#| msgid "Create New Location" +msgid "Create new location" +msgstr "Neuen Standort anlegen" + +#: part/templates/part/category.html:157 part/templates/part/category.html:186 +#, fuzzy +#| msgid "Category" +msgid "New Category" +msgstr "Kategorie" + +#: part/templates/part/category.html:158 +#, fuzzy +#| msgid "Create new part category" +msgid "Create new category" +msgstr "Teilkategorie anlegen" + +#: part/templates/part/category.html:187 +#, fuzzy +#| msgid "Create new part category" +msgid "Create new Part Category" +msgstr "Teilkategorie anlegen" + +#: part/templates/part/category.html:193 stock/views.py:1080 +msgid "Create new Stock Location" +msgstr "Neuen Lager-Standort erstellen" + #: part/templates/part/detail.html:9 msgid "Part Details" msgstr "Teile-Details" @@ -2463,7 +2555,7 @@ msgid "Variant Of" msgstr "Variante von" #: part/templates/part/detail.html:70 part/templates/part/set_category.html:15 -#: templates/js/part.html:282 +#: templates/js/part.html:285 msgid "Category" msgstr "Kategorie" @@ -2643,8 +2735,8 @@ msgstr "Dieses Teil ist eine Vorlage." msgid "This part is a variant of" msgstr "Dieses Teil ist eine Variante von" -#: part/templates/part/part_base.html:33 templates/js/company.html:131 -#: templates/js/part.html:259 +#: part/templates/part/part_base.html:33 templates/js/company.html:153 +#: templates/js/part.html:262 msgid "Inactive" msgstr "Inaktiv" @@ -2763,7 +2855,7 @@ msgid "Part Stock" msgstr "Teilbestand" #: part/templates/part/stock_count.html:7 templates/js/bom.html:204 -#: templates/js/part.html:319 +#: templates/js/part.html:322 msgid "No Stock" msgstr "Kein Bestand" @@ -2896,141 +2988,137 @@ msgstr "Kategorie für {n} Teile setzen" msgid "Create Variant" msgstr "Variante anlegen" -#: part/views.py:358 +#: part/views.py:367 msgid "Duplicate Part" msgstr "Teil duplizieren" -#: part/views.py:363 +#: part/views.py:372 msgid "Copied part" msgstr "Teil kopiert" -#: part/views.py:474 +#: part/views.py:490 msgid "Create new part" msgstr "Neues Teil anlegen" -#: part/views.py:479 +#: part/views.py:495 msgid "Created new part" msgstr "Neues Teil angelegt" -#: part/views.py:653 +#: part/views.py:669 msgid "Part QR Code" msgstr "Teil-QR-Code" -#: part/views.py:670 +#: part/views.py:686 msgid "Upload Part Image" msgstr "Teilbild hochladen" -#: part/views.py:675 part/views.py:710 +#: part/views.py:691 part/views.py:726 msgid "Updated part image" msgstr "Teilbild aktualisiert" -#: part/views.py:684 +#: part/views.py:700 msgid "Select Part Image" msgstr "Teilbild auswählen" -#: part/views.py:713 +#: part/views.py:729 msgid "Part image not found" msgstr "Teilbild nicht gefunden" -#: part/views.py:724 +#: part/views.py:740 msgid "Edit Part Properties" msgstr "Teileigenschaften bearbeiten" -#: part/views.py:746 +#: part/views.py:762 msgid "Validate BOM" msgstr "BOM validieren" -#: part/views.py:909 +#: part/views.py:925 msgid "No BOM file provided" msgstr "Keine Stückliste angegeben" -#: part/views.py:1259 +#: part/views.py:1275 msgid "Enter a valid quantity" msgstr "Bitte eine gültige Anzahl eingeben" -#: part/views.py:1284 part/views.py:1287 +#: part/views.py:1300 part/views.py:1303 msgid "Select valid part" msgstr "Bitte ein gültiges Teil auswählen" -#: part/views.py:1293 +#: part/views.py:1309 msgid "Duplicate part selected" msgstr "Teil doppelt ausgewählt" -#: part/views.py:1331 +#: part/views.py:1347 msgid "Select a part" msgstr "Teil auswählen" -#: part/views.py:1337 +#: part/views.py:1353 #, fuzzy #| msgid "Select part to be used in BOM" msgid "Selected part creates a circular BOM" msgstr "Teil für die Nutzung in der Stückliste auswählen" -#: part/views.py:1341 +#: part/views.py:1357 msgid "Specify quantity" msgstr "Anzahl angeben" -#: part/views.py:1591 +#: part/views.py:1607 msgid "Confirm Part Deletion" msgstr "Löschen des Teils bestätigen" -#: part/views.py:1598 +#: part/views.py:1614 msgid "Part was deleted" msgstr "Teil wurde gelöscht" -#: part/views.py:1607 +#: part/views.py:1623 msgid "Part Pricing" msgstr "Teilbepreisung" -#: part/views.py:1729 +#: part/views.py:1745 msgid "Create Part Parameter Template" msgstr "Teilparametervorlage anlegen" -#: part/views.py:1737 +#: part/views.py:1753 msgid "Edit Part Parameter Template" msgstr "Teilparametervorlage bearbeiten" -#: part/views.py:1744 +#: part/views.py:1760 msgid "Delete Part Parameter Template" msgstr "Teilparametervorlage löschen" -#: part/views.py:1752 +#: part/views.py:1768 msgid "Create Part Parameter" msgstr "Teilparameter anlegen" -#: part/views.py:1802 +#: part/views.py:1818 msgid "Edit Part Parameter" msgstr "Teilparameter bearbeiten" -#: part/views.py:1816 +#: part/views.py:1832 msgid "Delete Part Parameter" msgstr "Teilparameter löschen" -#: part/views.py:1832 +#: part/views.py:1848 msgid "Edit Part Category" msgstr "Teilkategorie bearbeiten" -#: part/views.py:1867 +#: part/views.py:1883 msgid "Delete Part Category" msgstr "Teilkategorie löschen" -#: part/views.py:1873 +#: part/views.py:1889 msgid "Part category was deleted" msgstr "Teilekategorie wurde gelöscht" -#: part/views.py:1881 -msgid "Create new part category" -msgstr "Teilkategorie anlegen" - -#: part/views.py:1932 +#: part/views.py:1948 msgid "Create BOM item" msgstr "BOM-Position anlegen" -#: part/views.py:1998 +#: part/views.py:2014 msgid "Edit BOM item" msgstr "BOM-Position beaarbeiten" -#: part/views.py:2046 +#: part/views.py:2062 msgid "Confim BOM item deletion" msgstr "Löschung von BOM-Position bestätigen" @@ -3796,10 +3884,6 @@ msgstr "{n} Teile im Lager gelöscht" msgid "Edit Stock Item" msgstr "Lagerobjekt bearbeiten" -#: stock/views.py:1080 -msgid "Create new Stock Location" -msgstr "Neuen Lager-Standort erstellen" - #: stock/views.py:1101 msgid "Serialize Stock" msgstr "Lagerbestand erfassen" @@ -4082,23 +4166,35 @@ msgstr "Keine Baue passen zur Anfrage" msgid "No parts allocated for" msgstr "Keine Teile zugeordnet zu" -#: templates/js/company.html:29 +#: templates/js/company.html:75 +#, fuzzy +#| msgid "Suppliers" +msgid "Parts Supplied" +msgstr "Zulieferer" + +#: templates/js/company.html:84 +#, fuzzy +#| msgid "Manufacturer" +msgid "Parts Manufactured" +msgstr "Hersteller" + +#: templates/js/company.html:96 msgid "No company information found" msgstr "Keine Firmeninformation gefunden" -#: templates/js/company.html:106 +#: templates/js/company.html:128 msgid "No supplier parts found" msgstr "Keine Zuliefererteile gefunden" -#: templates/js/company.html:123 templates/js/part.html:237 +#: templates/js/company.html:145 templates/js/part.html:240 msgid "Template part" msgstr "Vorlagenteil" -#: templates/js/company.html:127 templates/js/part.html:241 +#: templates/js/company.html:149 templates/js/part.html:244 msgid "Assembled part" msgstr "Baugruppe" -#: templates/js/company.html:184 +#: templates/js/company.html:206 msgid "Link" msgstr "Link" @@ -4118,67 +4214,67 @@ msgstr "Keine Aufträge gefunden" msgid "Shipment Date" msgstr "Versanddatum" -#: templates/js/part.html:134 +#: templates/js/part.html:137 #, fuzzy #| msgid "No parts found" msgid "No variants found" msgstr "Keine Teile gefunden" -#: templates/js/part.html:198 templates/js/stock.html:409 +#: templates/js/part.html:201 templates/js/stock.html:409 msgid "Select" msgstr "Auswählen" -#: templates/js/part.html:245 +#: templates/js/part.html:248 msgid "Starred part" msgstr "Favoritenteil" -#: templates/js/part.html:249 +#: templates/js/part.html:252 msgid "Salable part" msgstr "Verkäufliches Teil" -#: templates/js/part.html:288 +#: templates/js/part.html:291 msgid "No category" msgstr "Keine Kategorie" -#: templates/js/part.html:306 templates/js/table_filters.html:167 +#: templates/js/part.html:309 templates/js/table_filters.html:167 msgid "Low stock" msgstr "Bestand niedrig" -#: templates/js/part.html:315 +#: templates/js/part.html:318 msgid "Building" msgstr "Im Bau" -#: templates/js/part.html:334 +#: templates/js/part.html:337 msgid "No parts found" msgstr "Keine Teile gefunden" -#: templates/js/part.html:394 +#: templates/js/part.html:397 msgid "YES" msgstr "" -#: templates/js/part.html:396 +#: templates/js/part.html:399 msgid "NO" msgstr "" -#: templates/js/part.html:430 +#: templates/js/part.html:433 #, fuzzy #| msgid "No stock items matching query" msgid "No test templates matching query" msgstr "Keine zur Anfrage passenden Lagerobjekte" -#: templates/js/part.html:481 templates/js/stock.html:63 +#: templates/js/part.html:484 templates/js/stock.html:63 #, fuzzy #| msgid "Edit Sales Order" msgid "Edit test result" msgstr "Auftrag bearbeiten" -#: templates/js/part.html:482 templates/js/stock.html:64 +#: templates/js/part.html:485 templates/js/stock.html:64 #, fuzzy #| msgid "Delete attachment" msgid "Delete test result" msgstr "Anhang löschen" -#: templates/js/part.html:488 +#: templates/js/part.html:491 msgid "This test is defined for a parent part" msgstr "" diff --git a/InvenTree/locale/en/LC_MESSAGES/django.po b/InvenTree/locale/en/LC_MESSAGES/django.po index 435cbd5be4..a2f0a67186 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-09-02 13:57+0000\n" +"POT-Creation-Date: 2020-09-05 13:32+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -284,7 +284,7 @@ msgstr "" #: part/templates/part/part_app_base.html:7 #: part/templates/part/set_category.html:13 templates/js/barcode.html:336 #: templates/js/bom.html:135 templates/js/build.html:43 -#: templates/js/company.html:115 templates/js/part.html:212 +#: templates/js/company.html:137 templates/js/part.html:215 #: templates/js/stock.html:429 msgid "Part" msgstr "" @@ -397,6 +397,7 @@ msgstr "" #: build/templates/build/allocate.html:17 #: company/templates/company/detail_part.html:18 order/views.py:779 +#: part/templates/part/category.html:106 msgid "Order Parts" msgstr "" @@ -470,10 +471,10 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:27 #: order/templates/order/purchase_order_detail.html:159 #: part/templates/part/detail.html:51 part/templates/part/set_category.html:14 -#: templates/js/bom.html:158 templates/js/company.html:64 +#: templates/js/bom.html:158 templates/js/company.html:56 #: templates/js/order.html:159 templates/js/order.html:234 -#: templates/js/part.html:120 templates/js/part.html:268 -#: templates/js/part.html:449 templates/js/stock.html:444 +#: templates/js/part.html:120 templates/js/part.html:271 +#: templates/js/part.html:452 templates/js/stock.html:444 #: templates/js/stock.html:658 msgid "Description" msgstr "" @@ -484,8 +485,8 @@ msgstr "" msgid "Reference" msgstr "" -#: build/templates/build/allocate.html:338 part/models.py:1320 -#: templates/js/part.html:453 templates/js/table_filters.html:100 +#: build/templates/build/allocate.html:338 part/models.py:1332 +#: templates/js/part.html:456 templates/js/table_filters.html:100 msgid "Required" msgstr "" @@ -852,7 +853,7 @@ msgid "Description of the company" msgstr "" #: company/models.py:91 company/templates/company/company_base.html:48 -#: templates/js/company.html:69 +#: templates/js/company.html:61 msgid "Website" msgstr "" @@ -955,7 +956,7 @@ msgid "Assigned Stock" msgstr "" #: company/templates/company/company_base.html:7 -#: company/templates/company/company_base.html:22 templates/js/company.html:41 +#: company/templates/company/company_base.html:22 templates/js/company.html:33 msgid "Company" msgstr "" @@ -971,7 +972,7 @@ msgstr "" #: company/templates/company/detail.html:16 #: company/templates/company/supplier_part_base.html:76 #: company/templates/company/supplier_part_detail.html:30 part/bom.py:172 -#: templates/js/company.html:52 templates/js/company.html:164 +#: templates/js/company.html:44 templates/js/company.html:186 msgid "Manufacturer" msgstr "" @@ -980,15 +981,15 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:21 #: order/templates/order/order_base.html:74 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:170 -#: stock/templates/stock/item_base.html:239 templates/js/company.html:56 -#: templates/js/company.html:140 templates/js/order.html:146 +#: stock/templates/stock/item_base.html:239 templates/js/company.html:48 +#: templates/js/company.html:162 templates/js/order.html:146 msgid "Supplier" msgstr "" #: company/templates/company/detail.html:26 #: order/templates/order/sales_order_base.html:73 stock/models.py:354 #: stock/models.py:355 stock/templates/stock/item_base.html:161 -#: templates/js/company.html:48 templates/js/order.html:221 +#: templates/js/company.html:40 templates/js/order.html:221 msgid "Customer" msgstr "" @@ -1003,7 +1004,8 @@ msgid "New Supplier Part" msgstr "" #: company/templates/company/detail_part.html:15 -#: part/templates/part/supplier.html:14 templates/stock_table.html:10 +#: part/templates/part/category.html:103 part/templates/part/supplier.html:14 +#: templates/stock_table.html:10 msgid "Options" msgstr "" @@ -1024,16 +1026,16 @@ msgstr "" msgid "New Supplier" msgstr "" -#: company/templates/company/detail_part.html:50 company/views.py:182 +#: company/templates/company/detail_part.html:50 company/views.py:186 msgid "Create new Supplier" msgstr "" -#: company/templates/company/detail_part.html:55 company/views.py:57 +#: company/templates/company/detail_part.html:55 company/views.py:58 #: part/templates/part/supplier.html:50 msgid "New Manufacturer" msgstr "" -#: company/templates/company/detail_part.html:56 company/views.py:185 +#: company/templates/company/detail_part.html:56 company/views.py:189 msgid "Create new Manufacturer" msgstr "" @@ -1043,6 +1045,7 @@ msgstr "" #: company/templates/company/detail_stock.html:35 #: company/templates/company/supplier_part_stock.html:33 +#: part/templates/part/category.html:100 part/templates/part/category.html:107 #: part/templates/part/stock.html:51 templates/stock_table.html:5 msgid "Export" msgstr "" @@ -1100,7 +1103,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:6 #: company/templates/company/supplier_part_base.html:19 stock/models.py:328 -#: stock/templates/stock/item_base.html:244 templates/js/company.html:156 +#: stock/templates/stock/item_base.html:244 templates/js/company.html:178 msgid "Supplier Part" msgstr "" @@ -1134,7 +1137,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:80 #: company/templates/company/supplier_part_detail.html:31 part/bom.py:173 -#: templates/js/company.html:180 +#: templates/js/company.html:202 msgid "MPN" msgstr "" @@ -1187,7 +1190,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:124 -#: templates/js/part.html:295 templates/js/stock.html:452 +#: templates/js/part.html:298 templates/js/stock.html:452 #: templates/navbar.html:19 msgid "Stock" msgstr "" @@ -1208,83 +1211,83 @@ msgstr "" msgid "Suppliers" msgstr "" -#: company/views.py:56 templates/navbar.html:25 +#: company/views.py:57 templates/navbar.html:25 msgid "Manufacturers" msgstr "" -#: company/views.py:62 templates/navbar.html:32 +#: company/views.py:64 templates/navbar.html:32 msgid "Customers" msgstr "" -#: company/views.py:63 +#: company/views.py:65 msgid "New Customer" msgstr "" -#: company/views.py:70 +#: company/views.py:73 msgid "Companies" msgstr "" -#: company/views.py:71 +#: company/views.py:74 msgid "New Company" msgstr "" -#: company/views.py:147 +#: company/views.py:151 msgid "Update Company Image" msgstr "" -#: company/views.py:152 +#: company/views.py:156 msgid "Updated company image" msgstr "" -#: company/views.py:162 +#: company/views.py:166 msgid "Edit Company" msgstr "" -#: company/views.py:166 +#: company/views.py:170 msgid "Edited company information" msgstr "" -#: company/views.py:188 +#: company/views.py:192 msgid "Create new Customer" msgstr "" -#: company/views.py:190 +#: company/views.py:194 msgid "Create new Company" msgstr "" -#: company/views.py:217 +#: company/views.py:221 msgid "Created new company" msgstr "" -#: company/views.py:227 +#: company/views.py:231 msgid "Delete Company" msgstr "" -#: company/views.py:232 +#: company/views.py:236 msgid "Company was deleted" msgstr "" -#: company/views.py:256 +#: company/views.py:260 msgid "Edit Supplier Part" msgstr "" -#: company/views.py:265 templates/js/stock.html:785 +#: company/views.py:269 templates/js/stock.html:785 msgid "Create new Supplier Part" msgstr "" -#: company/views.py:325 +#: company/views.py:329 msgid "Delete Supplier Part" msgstr "" -#: company/views.py:395 +#: company/views.py:399 msgid "Add Price Break" msgstr "" -#: company/views.py:437 +#: company/views.py:441 msgid "Edit Price Break" msgstr "" -#: company/views.py:452 +#: company/views.py:456 msgid "Delete Price Break" msgstr "" @@ -1377,7 +1380,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:185 order/models.py:259 part/views.py:1250 +#: order/models.py:185 order/models.py:259 part/views.py:1266 #: stock/models.py:239 stock/models.py:682 msgid "Quantity must be greater than zero" msgstr "" @@ -1562,6 +1565,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:38 #: order/templates/order/purchase_order_detail.html:118 +#: part/templates/part/category.html:151 part/templates/part/category.html:192 #: templates/js/stock.html:790 msgid "New Location" msgstr "" @@ -1607,7 +1611,7 @@ msgid "Select parts to receive against this order" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.html:311 +#: part/templates/part/part_base.html:129 templates/js/part.html:314 msgid "On Order" msgstr "" @@ -1922,18 +1926,30 @@ msgid "Select part category" msgstr "" #: part/forms.py:134 -msgid "Perform 'deep copy' which will duplicate all BOM data for this part" +msgid "Duplicate all BOM data for this part" msgstr "" -#: part/forms.py:139 +#: part/forms.py:135 +msgid "Copy BOM" +msgstr "" + +#: part/forms.py:140 +msgid "Duplicate all parameter data for this part" +msgstr "" + +#: part/forms.py:141 +msgid "Copy Parameters" +msgstr "" + +#: part/forms.py:146 msgid "Confirm part creation" msgstr "" -#: part/forms.py:237 +#: part/forms.py:245 msgid "Input quantity for price calculation" msgstr "" -#: part/forms.py:240 +#: part/forms.py:248 msgid "Select currency for price calculation" msgstr "" @@ -2063,108 +2079,108 @@ msgstr "" msgid "Stored BOM checksum" msgstr "" -#: part/models.py:1272 +#: part/models.py:1284 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:1289 +#: part/models.py:1301 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:1308 templates/js/part.html:444 templates/js/stock.html:92 +#: part/models.py:1320 templates/js/part.html:447 templates/js/stock.html:92 msgid "Test Name" msgstr "" -#: part/models.py:1309 +#: part/models.py:1321 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1314 +#: part/models.py:1326 msgid "Test Description" msgstr "" -#: part/models.py:1315 +#: part/models.py:1327 msgid "Enter description for this test" msgstr "" -#: part/models.py:1321 +#: part/models.py:1333 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:1326 templates/js/part.html:461 +#: part/models.py:1338 templates/js/part.html:464 msgid "Requires Value" msgstr "" -#: part/models.py:1327 +#: part/models.py:1339 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:1332 templates/js/part.html:468 +#: part/models.py:1344 templates/js/part.html:471 msgid "Requires Attachment" msgstr "" -#: part/models.py:1333 +#: part/models.py:1345 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:1366 +#: part/models.py:1378 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:1371 +#: part/models.py:1383 msgid "Parameter Name" msgstr "" -#: part/models.py:1373 +#: part/models.py:1385 msgid "Parameter Units" msgstr "" -#: part/models.py:1399 +#: part/models.py:1411 msgid "Parent Part" msgstr "" -#: part/models.py:1401 +#: part/models.py:1413 msgid "Parameter Template" msgstr "" -#: part/models.py:1403 +#: part/models.py:1415 msgid "Parameter Value" msgstr "" -#: part/models.py:1432 +#: part/models.py:1451 msgid "Select parent part" msgstr "" -#: part/models.py:1440 +#: part/models.py:1459 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:1446 +#: part/models.py:1465 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:1449 +#: part/models.py:1468 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:1452 +#: part/models.py:1471 msgid "BOM item reference" msgstr "" -#: part/models.py:1455 +#: part/models.py:1474 msgid "BOM item notes" msgstr "" -#: part/models.py:1457 +#: part/models.py:1476 msgid "BOM line checksum" msgstr "" -#: part/models.py:1521 part/views.py:1256 part/views.py:1308 +#: part/models.py:1540 part/views.py:1272 part/views.py:1324 #: stock/models.py:229 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:1530 +#: part/models.py:1549 msgid "BOM Item" msgstr "" @@ -2226,7 +2242,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:46 part/views.py:1543 +#: part/templates/part/bom.html:46 part/views.py:1559 msgid "Export Bill of Materials" msgstr "" @@ -2302,6 +2318,18 @@ msgstr "" msgid "All parts" msgstr "" +#: part/templates/part/category.html:18 part/views.py:1897 +msgid "Create new part category" +msgstr "" + +#: part/templates/part/category.html:22 +msgid "Edit part category" +msgstr "" + +#: part/templates/part/category.html:25 +msgid "Delete part category" +msgstr "" + #: part/templates/part/category.html:34 part/templates/part/category.html:73 msgid "Category Details" msgstr "" @@ -2326,6 +2354,46 @@ msgstr "" msgid "Parts (Including subcategories)" msgstr "" +#: part/templates/part/category.html:100 +msgid "Export Part Data" +msgstr "" + +#: part/templates/part/category.html:105 +msgid "Set category" +msgstr "" + +#: part/templates/part/category.html:105 +msgid "Set Category" +msgstr "" + +#: part/templates/part/category.html:106 +msgid "Order parts" +msgstr "" + +#: part/templates/part/category.html:107 +msgid "Export Data" +msgstr "" + +#: part/templates/part/category.html:152 +msgid "Create new location" +msgstr "" + +#: part/templates/part/category.html:157 part/templates/part/category.html:186 +msgid "New Category" +msgstr "" + +#: part/templates/part/category.html:158 +msgid "Create new category" +msgstr "" + +#: part/templates/part/category.html:187 +msgid "Create new Part Category" +msgstr "" + +#: part/templates/part/category.html:193 stock/views.py:1080 +msgid "Create new Stock Location" +msgstr "" + #: part/templates/part/detail.html:9 msgid "Part Details" msgstr "" @@ -2352,7 +2420,7 @@ msgid "Variant Of" msgstr "" #: part/templates/part/detail.html:70 part/templates/part/set_category.html:15 -#: templates/js/part.html:282 +#: templates/js/part.html:285 msgid "Category" msgstr "" @@ -2522,8 +2590,8 @@ msgstr "" msgid "This part is a variant of" msgstr "" -#: part/templates/part/part_base.html:33 templates/js/company.html:131 -#: templates/js/part.html:259 +#: part/templates/part/part_base.html:33 templates/js/company.html:153 +#: templates/js/part.html:262 msgid "Inactive" msgstr "" @@ -2626,7 +2694,7 @@ msgid "Part Stock" msgstr "" #: part/templates/part/stock_count.html:7 templates/js/bom.html:204 -#: templates/js/part.html:319 +#: templates/js/part.html:322 msgid "No Stock" msgstr "" @@ -2739,139 +2807,135 @@ msgstr "" msgid "Create Variant" msgstr "" -#: part/views.py:358 +#: part/views.py:367 msgid "Duplicate Part" msgstr "" -#: part/views.py:363 +#: part/views.py:372 msgid "Copied part" msgstr "" -#: part/views.py:474 +#: part/views.py:490 msgid "Create new part" msgstr "" -#: part/views.py:479 +#: part/views.py:495 msgid "Created new part" msgstr "" -#: part/views.py:653 +#: part/views.py:669 msgid "Part QR Code" msgstr "" -#: part/views.py:670 +#: part/views.py:686 msgid "Upload Part Image" msgstr "" -#: part/views.py:675 part/views.py:710 +#: part/views.py:691 part/views.py:726 msgid "Updated part image" msgstr "" -#: part/views.py:684 +#: part/views.py:700 msgid "Select Part Image" msgstr "" -#: part/views.py:713 +#: part/views.py:729 msgid "Part image not found" msgstr "" -#: part/views.py:724 +#: part/views.py:740 msgid "Edit Part Properties" msgstr "" -#: part/views.py:746 +#: part/views.py:762 msgid "Validate BOM" msgstr "" -#: part/views.py:909 +#: part/views.py:925 msgid "No BOM file provided" msgstr "" -#: part/views.py:1259 +#: part/views.py:1275 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1284 part/views.py:1287 +#: part/views.py:1300 part/views.py:1303 msgid "Select valid part" msgstr "" -#: part/views.py:1293 +#: part/views.py:1309 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1331 +#: part/views.py:1347 msgid "Select a part" msgstr "" -#: part/views.py:1337 +#: part/views.py:1353 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1341 +#: part/views.py:1357 msgid "Specify quantity" msgstr "" -#: part/views.py:1591 +#: part/views.py:1607 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1598 +#: part/views.py:1614 msgid "Part was deleted" msgstr "" -#: part/views.py:1607 +#: part/views.py:1623 msgid "Part Pricing" msgstr "" -#: part/views.py:1729 +#: part/views.py:1745 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:1737 +#: part/views.py:1753 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:1744 +#: part/views.py:1760 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:1752 +#: part/views.py:1768 msgid "Create Part Parameter" msgstr "" -#: part/views.py:1802 +#: part/views.py:1818 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:1816 +#: part/views.py:1832 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:1832 +#: part/views.py:1848 msgid "Edit Part Category" msgstr "" -#: part/views.py:1867 +#: part/views.py:1883 msgid "Delete Part Category" msgstr "" -#: part/views.py:1873 +#: part/views.py:1889 msgid "Part category was deleted" msgstr "" -#: part/views.py:1881 -msgid "Create new part category" -msgstr "" - -#: part/views.py:1932 +#: part/views.py:1948 msgid "Create BOM item" msgstr "" -#: part/views.py:1998 +#: part/views.py:2014 msgid "Edit BOM item" msgstr "" -#: part/views.py:2046 +#: part/views.py:2062 msgid "Confim BOM item deletion" msgstr "" @@ -3526,10 +3590,6 @@ msgstr "" msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1080 -msgid "Create new Stock Location" -msgstr "" - #: stock/views.py:1101 msgid "Serialize Stock" msgstr "" @@ -3780,23 +3840,31 @@ msgstr "" msgid "No parts allocated for" msgstr "" -#: templates/js/company.html:29 +#: templates/js/company.html:75 +msgid "Parts Supplied" +msgstr "" + +#: templates/js/company.html:84 +msgid "Parts Manufactured" +msgstr "" + +#: templates/js/company.html:96 msgid "No company information found" msgstr "" -#: templates/js/company.html:106 +#: templates/js/company.html:128 msgid "No supplier parts found" msgstr "" -#: templates/js/company.html:123 templates/js/part.html:237 +#: templates/js/company.html:145 templates/js/part.html:240 msgid "Template part" msgstr "" -#: templates/js/company.html:127 templates/js/part.html:241 +#: templates/js/company.html:149 templates/js/part.html:244 msgid "Assembled part" msgstr "" -#: templates/js/company.html:184 +#: templates/js/company.html:206 msgid "Link" msgstr "" @@ -3816,59 +3884,59 @@ msgstr "" msgid "Shipment Date" msgstr "" -#: templates/js/part.html:134 +#: templates/js/part.html:137 msgid "No variants found" msgstr "" -#: templates/js/part.html:198 templates/js/stock.html:409 +#: templates/js/part.html:201 templates/js/stock.html:409 msgid "Select" msgstr "" -#: templates/js/part.html:245 +#: templates/js/part.html:248 msgid "Starred part" msgstr "" -#: templates/js/part.html:249 +#: templates/js/part.html:252 msgid "Salable part" msgstr "" -#: templates/js/part.html:288 +#: templates/js/part.html:291 msgid "No category" msgstr "" -#: templates/js/part.html:306 templates/js/table_filters.html:167 +#: templates/js/part.html:309 templates/js/table_filters.html:167 msgid "Low stock" msgstr "" -#: templates/js/part.html:315 +#: templates/js/part.html:318 msgid "Building" msgstr "" -#: templates/js/part.html:334 +#: templates/js/part.html:337 msgid "No parts found" msgstr "" -#: templates/js/part.html:394 +#: templates/js/part.html:397 msgid "YES" msgstr "" -#: templates/js/part.html:396 +#: templates/js/part.html:399 msgid "NO" msgstr "" -#: templates/js/part.html:430 +#: templates/js/part.html:433 msgid "No test templates matching query" msgstr "" -#: templates/js/part.html:481 templates/js/stock.html:63 +#: templates/js/part.html:484 templates/js/stock.html:63 msgid "Edit test result" msgstr "" -#: templates/js/part.html:482 templates/js/stock.html:64 +#: templates/js/part.html:485 templates/js/stock.html:64 msgid "Delete test result" msgstr "" -#: templates/js/part.html:488 +#: templates/js/part.html:491 msgid "This test is defined for a parent part" msgstr "" diff --git a/InvenTree/locale/es/LC_MESSAGES/django.po b/InvenTree/locale/es/LC_MESSAGES/django.po index 435cbd5be4..a2f0a67186 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-09-02 13:57+0000\n" +"POT-Creation-Date: 2020-09-05 13:32+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -284,7 +284,7 @@ msgstr "" #: part/templates/part/part_app_base.html:7 #: part/templates/part/set_category.html:13 templates/js/barcode.html:336 #: templates/js/bom.html:135 templates/js/build.html:43 -#: templates/js/company.html:115 templates/js/part.html:212 +#: templates/js/company.html:137 templates/js/part.html:215 #: templates/js/stock.html:429 msgid "Part" msgstr "" @@ -397,6 +397,7 @@ msgstr "" #: build/templates/build/allocate.html:17 #: company/templates/company/detail_part.html:18 order/views.py:779 +#: part/templates/part/category.html:106 msgid "Order Parts" msgstr "" @@ -470,10 +471,10 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:27 #: order/templates/order/purchase_order_detail.html:159 #: part/templates/part/detail.html:51 part/templates/part/set_category.html:14 -#: templates/js/bom.html:158 templates/js/company.html:64 +#: templates/js/bom.html:158 templates/js/company.html:56 #: templates/js/order.html:159 templates/js/order.html:234 -#: templates/js/part.html:120 templates/js/part.html:268 -#: templates/js/part.html:449 templates/js/stock.html:444 +#: templates/js/part.html:120 templates/js/part.html:271 +#: templates/js/part.html:452 templates/js/stock.html:444 #: templates/js/stock.html:658 msgid "Description" msgstr "" @@ -484,8 +485,8 @@ msgstr "" msgid "Reference" msgstr "" -#: build/templates/build/allocate.html:338 part/models.py:1320 -#: templates/js/part.html:453 templates/js/table_filters.html:100 +#: build/templates/build/allocate.html:338 part/models.py:1332 +#: templates/js/part.html:456 templates/js/table_filters.html:100 msgid "Required" msgstr "" @@ -852,7 +853,7 @@ msgid "Description of the company" msgstr "" #: company/models.py:91 company/templates/company/company_base.html:48 -#: templates/js/company.html:69 +#: templates/js/company.html:61 msgid "Website" msgstr "" @@ -955,7 +956,7 @@ msgid "Assigned Stock" msgstr "" #: company/templates/company/company_base.html:7 -#: company/templates/company/company_base.html:22 templates/js/company.html:41 +#: company/templates/company/company_base.html:22 templates/js/company.html:33 msgid "Company" msgstr "" @@ -971,7 +972,7 @@ msgstr "" #: company/templates/company/detail.html:16 #: company/templates/company/supplier_part_base.html:76 #: company/templates/company/supplier_part_detail.html:30 part/bom.py:172 -#: templates/js/company.html:52 templates/js/company.html:164 +#: templates/js/company.html:44 templates/js/company.html:186 msgid "Manufacturer" msgstr "" @@ -980,15 +981,15 @@ msgstr "" #: company/templates/company/supplier_part_detail.html:21 #: order/templates/order/order_base.html:74 #: order/templates/order/order_wizard/select_pos.html:30 part/bom.py:170 -#: stock/templates/stock/item_base.html:239 templates/js/company.html:56 -#: templates/js/company.html:140 templates/js/order.html:146 +#: stock/templates/stock/item_base.html:239 templates/js/company.html:48 +#: templates/js/company.html:162 templates/js/order.html:146 msgid "Supplier" msgstr "" #: company/templates/company/detail.html:26 #: order/templates/order/sales_order_base.html:73 stock/models.py:354 #: stock/models.py:355 stock/templates/stock/item_base.html:161 -#: templates/js/company.html:48 templates/js/order.html:221 +#: templates/js/company.html:40 templates/js/order.html:221 msgid "Customer" msgstr "" @@ -1003,7 +1004,8 @@ msgid "New Supplier Part" msgstr "" #: company/templates/company/detail_part.html:15 -#: part/templates/part/supplier.html:14 templates/stock_table.html:10 +#: part/templates/part/category.html:103 part/templates/part/supplier.html:14 +#: templates/stock_table.html:10 msgid "Options" msgstr "" @@ -1024,16 +1026,16 @@ msgstr "" msgid "New Supplier" msgstr "" -#: company/templates/company/detail_part.html:50 company/views.py:182 +#: company/templates/company/detail_part.html:50 company/views.py:186 msgid "Create new Supplier" msgstr "" -#: company/templates/company/detail_part.html:55 company/views.py:57 +#: company/templates/company/detail_part.html:55 company/views.py:58 #: part/templates/part/supplier.html:50 msgid "New Manufacturer" msgstr "" -#: company/templates/company/detail_part.html:56 company/views.py:185 +#: company/templates/company/detail_part.html:56 company/views.py:189 msgid "Create new Manufacturer" msgstr "" @@ -1043,6 +1045,7 @@ msgstr "" #: company/templates/company/detail_stock.html:35 #: company/templates/company/supplier_part_stock.html:33 +#: part/templates/part/category.html:100 part/templates/part/category.html:107 #: part/templates/part/stock.html:51 templates/stock_table.html:5 msgid "Export" msgstr "" @@ -1100,7 +1103,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:6 #: company/templates/company/supplier_part_base.html:19 stock/models.py:328 -#: stock/templates/stock/item_base.html:244 templates/js/company.html:156 +#: stock/templates/stock/item_base.html:244 templates/js/company.html:178 msgid "Supplier Part" msgstr "" @@ -1134,7 +1137,7 @@ msgstr "" #: company/templates/company/supplier_part_base.html:80 #: company/templates/company/supplier_part_detail.html:31 part/bom.py:173 -#: templates/js/company.html:180 +#: templates/js/company.html:202 msgid "MPN" msgstr "" @@ -1187,7 +1190,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:124 -#: templates/js/part.html:295 templates/js/stock.html:452 +#: templates/js/part.html:298 templates/js/stock.html:452 #: templates/navbar.html:19 msgid "Stock" msgstr "" @@ -1208,83 +1211,83 @@ msgstr "" msgid "Suppliers" msgstr "" -#: company/views.py:56 templates/navbar.html:25 +#: company/views.py:57 templates/navbar.html:25 msgid "Manufacturers" msgstr "" -#: company/views.py:62 templates/navbar.html:32 +#: company/views.py:64 templates/navbar.html:32 msgid "Customers" msgstr "" -#: company/views.py:63 +#: company/views.py:65 msgid "New Customer" msgstr "" -#: company/views.py:70 +#: company/views.py:73 msgid "Companies" msgstr "" -#: company/views.py:71 +#: company/views.py:74 msgid "New Company" msgstr "" -#: company/views.py:147 +#: company/views.py:151 msgid "Update Company Image" msgstr "" -#: company/views.py:152 +#: company/views.py:156 msgid "Updated company image" msgstr "" -#: company/views.py:162 +#: company/views.py:166 msgid "Edit Company" msgstr "" -#: company/views.py:166 +#: company/views.py:170 msgid "Edited company information" msgstr "" -#: company/views.py:188 +#: company/views.py:192 msgid "Create new Customer" msgstr "" -#: company/views.py:190 +#: company/views.py:194 msgid "Create new Company" msgstr "" -#: company/views.py:217 +#: company/views.py:221 msgid "Created new company" msgstr "" -#: company/views.py:227 +#: company/views.py:231 msgid "Delete Company" msgstr "" -#: company/views.py:232 +#: company/views.py:236 msgid "Company was deleted" msgstr "" -#: company/views.py:256 +#: company/views.py:260 msgid "Edit Supplier Part" msgstr "" -#: company/views.py:265 templates/js/stock.html:785 +#: company/views.py:269 templates/js/stock.html:785 msgid "Create new Supplier Part" msgstr "" -#: company/views.py:325 +#: company/views.py:329 msgid "Delete Supplier Part" msgstr "" -#: company/views.py:395 +#: company/views.py:399 msgid "Add Price Break" msgstr "" -#: company/views.py:437 +#: company/views.py:441 msgid "Edit Price Break" msgstr "" -#: company/views.py:452 +#: company/views.py:456 msgid "Delete Price Break" msgstr "" @@ -1377,7 +1380,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:185 order/models.py:259 part/views.py:1250 +#: order/models.py:185 order/models.py:259 part/views.py:1266 #: stock/models.py:239 stock/models.py:682 msgid "Quantity must be greater than zero" msgstr "" @@ -1562,6 +1565,7 @@ msgstr "" #: order/templates/order/purchase_order_detail.html:38 #: order/templates/order/purchase_order_detail.html:118 +#: part/templates/part/category.html:151 part/templates/part/category.html:192 #: templates/js/stock.html:790 msgid "New Location" msgstr "" @@ -1607,7 +1611,7 @@ msgid "Select parts to receive against this order" msgstr "" #: order/templates/order/receive_parts.html:21 -#: part/templates/part/part_base.html:129 templates/js/part.html:311 +#: part/templates/part/part_base.html:129 templates/js/part.html:314 msgid "On Order" msgstr "" @@ -1922,18 +1926,30 @@ msgid "Select part category" msgstr "" #: part/forms.py:134 -msgid "Perform 'deep copy' which will duplicate all BOM data for this part" +msgid "Duplicate all BOM data for this part" msgstr "" -#: part/forms.py:139 +#: part/forms.py:135 +msgid "Copy BOM" +msgstr "" + +#: part/forms.py:140 +msgid "Duplicate all parameter data for this part" +msgstr "" + +#: part/forms.py:141 +msgid "Copy Parameters" +msgstr "" + +#: part/forms.py:146 msgid "Confirm part creation" msgstr "" -#: part/forms.py:237 +#: part/forms.py:245 msgid "Input quantity for price calculation" msgstr "" -#: part/forms.py:240 +#: part/forms.py:248 msgid "Select currency for price calculation" msgstr "" @@ -2063,108 +2079,108 @@ msgstr "" msgid "Stored BOM checksum" msgstr "" -#: part/models.py:1272 +#: part/models.py:1284 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:1289 +#: part/models.py:1301 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:1308 templates/js/part.html:444 templates/js/stock.html:92 +#: part/models.py:1320 templates/js/part.html:447 templates/js/stock.html:92 msgid "Test Name" msgstr "" -#: part/models.py:1309 +#: part/models.py:1321 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1314 +#: part/models.py:1326 msgid "Test Description" msgstr "" -#: part/models.py:1315 +#: part/models.py:1327 msgid "Enter description for this test" msgstr "" -#: part/models.py:1321 +#: part/models.py:1333 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:1326 templates/js/part.html:461 +#: part/models.py:1338 templates/js/part.html:464 msgid "Requires Value" msgstr "" -#: part/models.py:1327 +#: part/models.py:1339 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:1332 templates/js/part.html:468 +#: part/models.py:1344 templates/js/part.html:471 msgid "Requires Attachment" msgstr "" -#: part/models.py:1333 +#: part/models.py:1345 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:1366 +#: part/models.py:1378 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:1371 +#: part/models.py:1383 msgid "Parameter Name" msgstr "" -#: part/models.py:1373 +#: part/models.py:1385 msgid "Parameter Units" msgstr "" -#: part/models.py:1399 +#: part/models.py:1411 msgid "Parent Part" msgstr "" -#: part/models.py:1401 +#: part/models.py:1413 msgid "Parameter Template" msgstr "" -#: part/models.py:1403 +#: part/models.py:1415 msgid "Parameter Value" msgstr "" -#: part/models.py:1432 +#: part/models.py:1451 msgid "Select parent part" msgstr "" -#: part/models.py:1440 +#: part/models.py:1459 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:1446 +#: part/models.py:1465 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:1449 +#: part/models.py:1468 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:1452 +#: part/models.py:1471 msgid "BOM item reference" msgstr "" -#: part/models.py:1455 +#: part/models.py:1474 msgid "BOM item notes" msgstr "" -#: part/models.py:1457 +#: part/models.py:1476 msgid "BOM line checksum" msgstr "" -#: part/models.py:1521 part/views.py:1256 part/views.py:1308 +#: part/models.py:1540 part/views.py:1272 part/views.py:1324 #: stock/models.py:229 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:1530 +#: part/models.py:1549 msgid "BOM Item" msgstr "" @@ -2226,7 +2242,7 @@ msgstr "" msgid "Validate Bill of Materials" msgstr "" -#: part/templates/part/bom.html:46 part/views.py:1543 +#: part/templates/part/bom.html:46 part/views.py:1559 msgid "Export Bill of Materials" msgstr "" @@ -2302,6 +2318,18 @@ msgstr "" msgid "All parts" msgstr "" +#: part/templates/part/category.html:18 part/views.py:1897 +msgid "Create new part category" +msgstr "" + +#: part/templates/part/category.html:22 +msgid "Edit part category" +msgstr "" + +#: part/templates/part/category.html:25 +msgid "Delete part category" +msgstr "" + #: part/templates/part/category.html:34 part/templates/part/category.html:73 msgid "Category Details" msgstr "" @@ -2326,6 +2354,46 @@ msgstr "" msgid "Parts (Including subcategories)" msgstr "" +#: part/templates/part/category.html:100 +msgid "Export Part Data" +msgstr "" + +#: part/templates/part/category.html:105 +msgid "Set category" +msgstr "" + +#: part/templates/part/category.html:105 +msgid "Set Category" +msgstr "" + +#: part/templates/part/category.html:106 +msgid "Order parts" +msgstr "" + +#: part/templates/part/category.html:107 +msgid "Export Data" +msgstr "" + +#: part/templates/part/category.html:152 +msgid "Create new location" +msgstr "" + +#: part/templates/part/category.html:157 part/templates/part/category.html:186 +msgid "New Category" +msgstr "" + +#: part/templates/part/category.html:158 +msgid "Create new category" +msgstr "" + +#: part/templates/part/category.html:187 +msgid "Create new Part Category" +msgstr "" + +#: part/templates/part/category.html:193 stock/views.py:1080 +msgid "Create new Stock Location" +msgstr "" + #: part/templates/part/detail.html:9 msgid "Part Details" msgstr "" @@ -2352,7 +2420,7 @@ msgid "Variant Of" msgstr "" #: part/templates/part/detail.html:70 part/templates/part/set_category.html:15 -#: templates/js/part.html:282 +#: templates/js/part.html:285 msgid "Category" msgstr "" @@ -2522,8 +2590,8 @@ msgstr "" msgid "This part is a variant of" msgstr "" -#: part/templates/part/part_base.html:33 templates/js/company.html:131 -#: templates/js/part.html:259 +#: part/templates/part/part_base.html:33 templates/js/company.html:153 +#: templates/js/part.html:262 msgid "Inactive" msgstr "" @@ -2626,7 +2694,7 @@ msgid "Part Stock" msgstr "" #: part/templates/part/stock_count.html:7 templates/js/bom.html:204 -#: templates/js/part.html:319 +#: templates/js/part.html:322 msgid "No Stock" msgstr "" @@ -2739,139 +2807,135 @@ msgstr "" msgid "Create Variant" msgstr "" -#: part/views.py:358 +#: part/views.py:367 msgid "Duplicate Part" msgstr "" -#: part/views.py:363 +#: part/views.py:372 msgid "Copied part" msgstr "" -#: part/views.py:474 +#: part/views.py:490 msgid "Create new part" msgstr "" -#: part/views.py:479 +#: part/views.py:495 msgid "Created new part" msgstr "" -#: part/views.py:653 +#: part/views.py:669 msgid "Part QR Code" msgstr "" -#: part/views.py:670 +#: part/views.py:686 msgid "Upload Part Image" msgstr "" -#: part/views.py:675 part/views.py:710 +#: part/views.py:691 part/views.py:726 msgid "Updated part image" msgstr "" -#: part/views.py:684 +#: part/views.py:700 msgid "Select Part Image" msgstr "" -#: part/views.py:713 +#: part/views.py:729 msgid "Part image not found" msgstr "" -#: part/views.py:724 +#: part/views.py:740 msgid "Edit Part Properties" msgstr "" -#: part/views.py:746 +#: part/views.py:762 msgid "Validate BOM" msgstr "" -#: part/views.py:909 +#: part/views.py:925 msgid "No BOM file provided" msgstr "" -#: part/views.py:1259 +#: part/views.py:1275 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1284 part/views.py:1287 +#: part/views.py:1300 part/views.py:1303 msgid "Select valid part" msgstr "" -#: part/views.py:1293 +#: part/views.py:1309 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1331 +#: part/views.py:1347 msgid "Select a part" msgstr "" -#: part/views.py:1337 +#: part/views.py:1353 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1341 +#: part/views.py:1357 msgid "Specify quantity" msgstr "" -#: part/views.py:1591 +#: part/views.py:1607 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1598 +#: part/views.py:1614 msgid "Part was deleted" msgstr "" -#: part/views.py:1607 +#: part/views.py:1623 msgid "Part Pricing" msgstr "" -#: part/views.py:1729 +#: part/views.py:1745 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:1737 +#: part/views.py:1753 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:1744 +#: part/views.py:1760 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:1752 +#: part/views.py:1768 msgid "Create Part Parameter" msgstr "" -#: part/views.py:1802 +#: part/views.py:1818 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:1816 +#: part/views.py:1832 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:1832 +#: part/views.py:1848 msgid "Edit Part Category" msgstr "" -#: part/views.py:1867 +#: part/views.py:1883 msgid "Delete Part Category" msgstr "" -#: part/views.py:1873 +#: part/views.py:1889 msgid "Part category was deleted" msgstr "" -#: part/views.py:1881 -msgid "Create new part category" -msgstr "" - -#: part/views.py:1932 +#: part/views.py:1948 msgid "Create BOM item" msgstr "" -#: part/views.py:1998 +#: part/views.py:2014 msgid "Edit BOM item" msgstr "" -#: part/views.py:2046 +#: part/views.py:2062 msgid "Confim BOM item deletion" msgstr "" @@ -3526,10 +3590,6 @@ msgstr "" msgid "Edit Stock Item" msgstr "" -#: stock/views.py:1080 -msgid "Create new Stock Location" -msgstr "" - #: stock/views.py:1101 msgid "Serialize Stock" msgstr "" @@ -3780,23 +3840,31 @@ msgstr "" msgid "No parts allocated for" msgstr "" -#: templates/js/company.html:29 +#: templates/js/company.html:75 +msgid "Parts Supplied" +msgstr "" + +#: templates/js/company.html:84 +msgid "Parts Manufactured" +msgstr "" + +#: templates/js/company.html:96 msgid "No company information found" msgstr "" -#: templates/js/company.html:106 +#: templates/js/company.html:128 msgid "No supplier parts found" msgstr "" -#: templates/js/company.html:123 templates/js/part.html:237 +#: templates/js/company.html:145 templates/js/part.html:240 msgid "Template part" msgstr "" -#: templates/js/company.html:127 templates/js/part.html:241 +#: templates/js/company.html:149 templates/js/part.html:244 msgid "Assembled part" msgstr "" -#: templates/js/company.html:184 +#: templates/js/company.html:206 msgid "Link" msgstr "" @@ -3816,59 +3884,59 @@ msgstr "" msgid "Shipment Date" msgstr "" -#: templates/js/part.html:134 +#: templates/js/part.html:137 msgid "No variants found" msgstr "" -#: templates/js/part.html:198 templates/js/stock.html:409 +#: templates/js/part.html:201 templates/js/stock.html:409 msgid "Select" msgstr "" -#: templates/js/part.html:245 +#: templates/js/part.html:248 msgid "Starred part" msgstr "" -#: templates/js/part.html:249 +#: templates/js/part.html:252 msgid "Salable part" msgstr "" -#: templates/js/part.html:288 +#: templates/js/part.html:291 msgid "No category" msgstr "" -#: templates/js/part.html:306 templates/js/table_filters.html:167 +#: templates/js/part.html:309 templates/js/table_filters.html:167 msgid "Low stock" msgstr "" -#: templates/js/part.html:315 +#: templates/js/part.html:318 msgid "Building" msgstr "" -#: templates/js/part.html:334 +#: templates/js/part.html:337 msgid "No parts found" msgstr "" -#: templates/js/part.html:394 +#: templates/js/part.html:397 msgid "YES" msgstr "" -#: templates/js/part.html:396 +#: templates/js/part.html:399 msgid "NO" msgstr "" -#: templates/js/part.html:430 +#: templates/js/part.html:433 msgid "No test templates matching query" msgstr "" -#: templates/js/part.html:481 templates/js/stock.html:63 +#: templates/js/part.html:484 templates/js/stock.html:63 msgid "Edit test result" msgstr "" -#: templates/js/part.html:482 templates/js/stock.html:64 +#: templates/js/part.html:485 templates/js/stock.html:64 msgid "Delete test result" msgstr "" -#: templates/js/part.html:488 +#: templates/js/part.html:491 msgid "This test is defined for a parent part" msgstr "" diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index 672edfb587..6091a9654a 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -15,14 +15,14 @@ {% endif %}

- {% if category %} - - {% endif %} @@ -97,14 +97,14 @@
- +
@@ -148,14 +148,14 @@ secondary: [ { field: 'default_location', - label: 'New Location', - title: 'Create new location', + label: '{% trans "New Location" %}', + title: '{% trans "Create new location" %}', url: "{% url 'stock-location-create' %}", }, { field: 'parent', - label: 'New Category', - title: 'Create new category', + label: '{% trans "New Category" %}', + title: '{% trans "Create new category" %}', url: "{% url 'category-create' %}", }, ] @@ -183,14 +183,14 @@ secondary: [ { field: 'category', - label: 'New Category', - title: 'Create new Part Category', + label: '{% trans "New Category" %}', + title: '{% trans "Create new Part Category" %}', url: "{% url 'category-create' %}", }, { field: 'default_location', - label: 'New Location', - title: 'Create new Stock Location', + label: '{% trans "New Location" %}', + title: '{% trans "Create new Stock Location" %}', url: "{% url 'stock-location-create' %}", } ] @@ -216,10 +216,12 @@ {% endif %} $('#cat-delete').click(function() { - launchModalForm("{% url 'category-delete' category.id %}", - { - redirect: redirect - }); + launchModalForm( + "{% url 'category-delete' category.id %}", + { + redirect: redirect + } + ); }); {% endif %} From 46a8107be5c4f5243d9431438a24cb1b75888442 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sat, 5 Sep 2020 23:35:48 +1000 Subject: [PATCH 10/11] Refactor stock filter --- InvenTree/part/serializers.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/InvenTree/part/serializers.py b/InvenTree/part/serializers.py index bab58f8dbe..8adb26680e 100644 --- a/InvenTree/part/serializers.py +++ b/InvenTree/part/serializers.py @@ -13,6 +13,8 @@ from .models import PartParameter, PartParameterTemplate from .models import PartAttachment from .models import PartTestTemplate +from stock.models import StockItem + from decimal import Decimal from sql_util.utils import SubquerySum, SubqueryCount @@ -20,7 +22,7 @@ from sql_util.utils import SubquerySum, SubqueryCount from django.db.models import Q from django.db.models.functions import Coalesce -from InvenTree.status_codes import StockStatus, PurchaseOrderStatus, BuildStatus +from InvenTree.status_codes import PurchaseOrderStatus, BuildStatus from InvenTree.serializers import InvenTreeModelSerializer from InvenTree.serializers import InvenTreeAttachmentSerializerField @@ -191,19 +193,10 @@ class PartSerializer(InvenTreeModelSerializer): to reduce database trips. """ - # Filter to limit stock items to "available" - stock_filter = Q( - status__in=StockStatus.AVAILABLE_CODES, - sales_order=None, - build_order=None, - belongs_to=None, - customer=None, - ) - # Annotate with the total 'in stock' quantity queryset = queryset.annotate( in_stock=Coalesce( - SubquerySum('stock_items__quantity', filter=stock_filter), + SubquerySum('stock_items__quantity', filter=StockItem.IN_STOCK_FILTER), Decimal(0) ), ) From 87f25eacc57e16dcf4dfbc8b7fb509c6ee4f285c Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Sun, 6 Sep 2020 00:01:14 +1000 Subject: [PATCH 11/11] Add link from stock item to base part --- InvenTree/stock/templates/stock/item_base.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/stock/templates/stock/item_base.html b/InvenTree/stock/templates/stock/item_base.html index f2b80596fd..fa146910d4 100644 --- a/InvenTree/stock/templates/stock/item_base.html +++ b/InvenTree/stock/templates/stock/item_base.html @@ -61,9 +61,9 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}

{% if item.serialized %} -{{ item.part.full_name}} # {{ item.serial }} +{{ item.part.full_name}} # {{ item.serial }} {% else %} -{% decimal item.quantity %} × {{ item.part.full_name }} +{{ item.part.full_name }} × {% decimal item.quantity %} {% endif %}