diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py index 80df8914d3..f9f8378526 100644 --- a/InvenTree/InvenTree/forms.py +++ b/InvenTree/InvenTree/forms.py @@ -28,6 +28,11 @@ class HelperForm(forms.ModelForm): self.helper.form_tag = False + # Check for errors from model validation + # If none, disable crispy form errors + if not self.errors: + self.helper.form_show_errors = False + """ Create a default 'layout' for this form. Ref: https://django-crispy-forms.readthedocs.io/en/latest/layouts.html diff --git a/InvenTree/build/templates/build/tabs.html b/InvenTree/build/templates/build/tabs.html index 2c45cd2361..8bdb2a3013 100644 --- a/InvenTree/build/templates/build/tabs.html +++ b/InvenTree/build/templates/build/tabs.html @@ -4,16 +4,29 @@ {% trans "Details" %} + {% if build.active %} - {% trans "Allocate Parts" %} + + {% trans "Incomplete" %} + {{ build.incomplete_outputs.count }} + + {% endif %} - {% trans "Build Outputs" %}{% if build.output_count > 0%}{{ build.output_count }}{% endif %} + + {% trans "Build Outputs" %} + {{ build.output_count }} + - {% trans "Notes" %}{% if build.notes %} {% endif %} + + {% trans "Notes" %} + {% if build.notes %} {% endif %} +
  • - {% trans "Attachments" %} + + {% trans "Attachments" %} +
  • \ No newline at end of file diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 0d3afbe226..8254d161d6 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -64,6 +64,13 @@ class InvenTreeSetting(models.Model): 'description': _('Regular expression pattern for matching Part IPN') }, + 'PART_ALLOW_DUPLICATE_IPN': { + 'name': _('Allow Duplicate IPN'), + 'description': _('Allow multiple parts to share the same IPN'), + 'default': True, + 'validator': bool, + }, + 'PART_COPY_BOM': { 'name': _('Copy Part BOM Data'), 'description': _('Copy BOM data by default when duplicating a part'), @@ -85,6 +92,34 @@ class InvenTreeSetting(models.Model): 'validator': bool }, + 'PART_COMPONENT': { + 'name': _('Component'), + 'description': _('Parts can be used as sub-components by default'), + 'default': True, + 'validator': bool, + }, + + 'PART_PURCHASEABLE': { + 'name': _('Purchaseable'), + 'description': _('Parts are purchaseable by default'), + 'default': False, + 'validator': bool, + }, + + 'PART_SALABLE': { + 'name': _('Salable'), + 'description': _('Parts are salable by default'), + 'default': False, + 'validator': bool, + }, + + 'PART_TRACKABLE': { + 'name': _('Trackable'), + 'description': _('Parts are trackable by default'), + 'default': False, + 'validator': bool, + }, + 'BUILDORDER_REFERENCE_PREFIX': { 'name': _('Build Order Reference Prefix'), 'description': _('Prefix value for build order reference'), @@ -242,9 +277,16 @@ class InvenTreeSetting(models.Model): setting = InvenTreeSetting.get_setting_object(key) if setting: - return setting.value + value = setting.value + + # If the particular setting is defined as a boolean, cast the value to a boolean + if setting.is_bool(): + value = InvenTree.helpers.str2bool(value) + else: - return backup_value + value = backup_value + + return value @classmethod def set_setting(cls, key, value, user, create=True): @@ -270,6 +312,10 @@ class InvenTreeSetting(models.Model): setting = InvenTreeSetting(key=key) else: return + + # Enforce standard boolean representation + if setting.is_bool(): + value = InvenTree.helpers.str2bool(value) setting.value = str(value) setting.save() @@ -282,6 +328,10 @@ class InvenTreeSetting(models.Model): def name(self): return InvenTreeSetting.get_setting_name(self.key) + @property + def default_value(self): + return InvenTreeSetting.get_default_value(self.key) + @property def description(self): return InvenTreeSetting.get_setting_description(self.key) diff --git a/InvenTree/common/tests.py b/InvenTree/common/tests.py index e0b6812f40..323049f164 100644 --- a/InvenTree/common/tests.py +++ b/InvenTree/common/tests.py @@ -69,4 +69,14 @@ class SettingsTest(TestCase): InvenTreeSetting.set_setting(key, value, self.user) - self.assertEqual(str(value), InvenTreeSetting.get_setting(key)) + self.assertEqual(value, InvenTreeSetting.get_setting(key)) + + # Any fields marked as 'boolean' must have a default value specified + setting = InvenTreeSetting.get_setting_object(key) + + if setting.is_bool(): + if setting.default_value in ['', None]: + raise ValueError(f'Default value for boolean setting {key} not provided') + + if setting.default_value not in [True, False]: + raise ValueError(f'Non-boolean default value specified for {key}') diff --git a/InvenTree/locale/de/LC_MESSAGES/django.po b/InvenTree/locale/de/LC_MESSAGES/django.po index 8a486733dc..00c43092f0 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-11-03 10:02+0000\n" +"POT-Creation-Date: 2020-11-09 12:47+0000\n" "PO-Revision-Date: 2020-05-03 11:32+0200\n" "Last-Translator: Christian Schlüter \n" "Language-Team: C \n" @@ -25,27 +25,27 @@ msgstr "Keine Aktion angegeben" msgid "No matching action found" msgstr "Keine passende Aktion gefunden" -#: InvenTree/forms.py:102 build/forms.py:82 build/forms.py:170 +#: InvenTree/forms.py:130 build/forms.py:82 build/forms.py:170 msgid "Confirm" msgstr "Bestätigen" -#: InvenTree/forms.py:118 +#: InvenTree/forms.py:146 #, fuzzy #| msgid "Confim BOM item deletion" msgid "Confirm item deletion" msgstr "Löschung von BOM-Position bestätigen" -#: InvenTree/forms.py:150 +#: InvenTree/forms.py:178 #, fuzzy #| msgid "Create new part" msgid "Enter new password" msgstr "Neues Teil anlegen" -#: InvenTree/forms.py:157 +#: InvenTree/forms.py:185 msgid "Confirm new password" msgstr "" -#: InvenTree/forms.py:192 +#: InvenTree/forms.py:220 msgid "Apply Theme" msgstr "" @@ -446,8 +446,8 @@ msgstr "Bestellung, die diesem Bau zugwiesen ist" #: build/templates/build/detail.html:24 order/models.py:519 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:148 -#: order/templates/order/receive_parts.html:19 part/models.py:293 -#: part/templates/part/part_app_base.html:7 +#: order/templates/order/receive_parts.html:19 part/models.py:294 +#: part/templates/part/part_app_base.html:7 part/templates/part/related.html:26 #: part/templates/part/set_category.html:13 templates/InvenTree/search.html:133 #: templates/js/barcode.js:336 templates/js/bom.js:147 templates/js/bom.js:484 #: templates/js/build.js:647 templates/js/company.js:138 @@ -536,14 +536,14 @@ msgstr "Chargennummer für diese Bau-Ausgabe" msgid "External Link" msgstr "Externer Link" -#: build/models.py:177 part/models.py:596 stock/models.py:385 +#: build/models.py:177 part/models.py:597 stock/models.py:385 msgid "Link to external URL" msgstr "Link zu einer externen URL" -#: build/models.py:181 build/templates/build/tabs.html:14 company/models.py:314 +#: build/models.py:181 build/templates/build/tabs.html:23 company/models.py:314 #: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:18 #: order/templates/order/purchase_order_detail.html:203 -#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:70 +#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:73 #: stock/forms.py:306 stock/forms.py:338 stock/forms.py:366 stock/models.py:455 #: stock/models.py:1428 stock/templates/stock/tabs.html:26 #: templates/js/barcode.js:391 templates/js/bom.js:250 @@ -555,76 +555,76 @@ msgstr "Notizen" msgid "Extra build notes" msgstr "Notizen für den Bau" -#: build/models.py:543 +#: build/models.py:551 #, fuzzy #| msgid "No action specified" msgid "No build output specified" msgstr "Keine Aktion angegeben" -#: build/models.py:546 +#: build/models.py:554 msgid "Build output is already completed" msgstr "" -#: build/models.py:549 +#: build/models.py:557 #, fuzzy #| msgid "Quantity does not match serial numbers" msgid "Build output does not match Build Order" msgstr "Anzahl stimmt nicht mit den Seriennummern überein" -#: build/models.py:620 +#: build/models.py:632 #, fuzzy #| msgid "Complete Build" msgid "Completed build output" msgstr "Bau fertigstellen" -#: build/models.py:858 +#: build/models.py:870 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:880 +#: build/models.py:892 #, fuzzy #| msgid "Allocate Stock to Build" msgid "Build item must specify a build output" msgstr "Lagerbestand dem Bau zuweisen" -#: build/models.py:885 +#: build/models.py:897 #, python-brace-format msgid "Selected stock item not found in BOM for part '{p}'" msgstr "Ausgewähltes Lagerobjekt nicht in BOM für Teil '{p}' gefunden" -#: build/models.py:889 +#: build/models.py:901 #, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" "zugewiesene Anzahl ({n}) darf nicht die verfügbare ({q}) Anzahl überschreiten" -#: build/models.py:896 order/models.py:603 +#: build/models.py:908 order/models.py:603 msgid "StockItem is over-allocated" msgstr "Zu viele Lagerobjekte zugewiesen" -#: build/models.py:900 order/models.py:606 +#: build/models.py:912 order/models.py:606 msgid "Allocation quantity must be greater than zero" msgstr "Anzahl muss größer null sein" -#: build/models.py:904 +#: build/models.py:916 msgid "Quantity must be 1 for serialized stock" msgstr "Anzahl muss 1 für Objekte mit Seriennummer sein" -#: build/models.py:944 +#: build/models.py:956 msgid "Build to allocate parts" msgstr "Bau starten um Teile zuzuweisen" -#: build/models.py:951 +#: build/models.py:963 #, fuzzy #| msgid "Remove stock" msgid "Source stock item" msgstr "Bestand entfernen" -#: build/models.py:964 +#: build/models.py:976 msgid "Stock quantity to allocate to build" msgstr "Lagerobjekt-Anzahl dem Bau zuweisen" -#: build/models.py:972 +#: build/models.py:984 #, fuzzy #| msgid "Destination stock location" msgid "Destination stock item" @@ -642,59 +642,59 @@ msgstr "Bau fertigstellen" msgid "Build order has been completed" msgstr "Bau-Zuweisung ist vollständig" -#: build/templates/build/allocate.html:24 +#: build/templates/build/allocate.html:25 #, fuzzy #| msgid "Created new build" msgid "Create new build output" msgstr "Neuen Bau angelegt" -#: build/templates/build/allocate.html:25 +#: build/templates/build/allocate.html:26 #, fuzzy #| msgid "Create New Part" msgid "Create New Output" msgstr "Neues Teil anlegen" -#: build/templates/build/allocate.html:28 +#: build/templates/build/allocate.html:29 #, fuzzy #| msgid "Order part" msgid "Order required parts" msgstr "Teil bestellen" -#: build/templates/build/allocate.html:29 -#: company/templates/company/detail_part.html:28 order/views.py:801 +#: build/templates/build/allocate.html:30 +#: company/templates/company/detail_part.html:28 order/views.py:803 #: part/templates/part/category.html:125 msgid "Order Parts" msgstr "Teile bestellen" -#: build/templates/build/allocate.html:32 templates/js/build.js:574 +#: build/templates/build/allocate.html:33 templates/js/build.js:574 #, fuzzy #| msgid "Unallocate Stock" msgid "Unallocate stock" msgstr "Zuweisung aufheben" -#: build/templates/build/allocate.html:33 build/views.py:341 build/views.py:778 +#: build/templates/build/allocate.html:34 build/views.py:341 build/views.py:778 msgid "Unallocate Stock" msgstr "Zuweisung aufheben" -#: build/templates/build/allocate.html:46 +#: build/templates/build/allocate.html:48 #, fuzzy #| msgid "Created new build" msgid "Create a new build output" msgstr "Neuen Bau angelegt" -#: build/templates/build/allocate.html:47 +#: build/templates/build/allocate.html:49 #, fuzzy #| msgid "Complete Build" msgid "No incomplete build outputs remain." msgstr "Bau fertigstellen" -#: build/templates/build/allocate.html:48 +#: build/templates/build/allocate.html:50 msgid "Create a new build output using the button above" msgstr "" -#: build/templates/build/attachments.html:11 build/templates/build/tabs.html:17 +#: build/templates/build/attachments.html:11 build/templates/build/tabs.html:29 #: order/templates/order/po_tabs.html:11 order/templates/order/so_tabs.html:16 -#: part/templates/part/tabs.html:67 stock/templates/stock/tabs.html:32 +#: part/templates/part/tabs.html:70 stock/templates/stock/tabs.html:32 msgid "Attachments" msgstr "Anhänge" @@ -801,7 +801,7 @@ msgstr "" msgid "Sales Order" msgstr "Bestellung" -#: build/templates/build/build_output.html:9 build/templates/build/tabs.html:11 +#: build/templates/build/build_output.html:9 build/templates/build/tabs.html:17 msgid "Build Outputs" msgstr "Bau-Ausgabe" @@ -993,11 +993,11 @@ msgstr "Bermerkungen bearbeiten" msgid "Details" msgstr "Details" -#: build/templates/build/tabs.html:8 +#: build/templates/build/tabs.html:10 #, fuzzy -#| msgid "Allocated Parts" -msgid "Allocate Parts" -msgstr "Zugeordnete Teile" +#| msgid "Complete" +msgid "Incomplete" +msgstr "Fertig" #: build/templates/build/unallocate.html:10 msgid "Are you sure you wish to unallocate all stock for this build?" @@ -1036,7 +1036,7 @@ msgstr "Lagerbestand dem Bau zuweisen" msgid "Create Build Output" msgstr "Bau-Ausgabe" -#: build/views.py:207 stock/models.py:832 stock/views.py:1645 +#: build/views.py:207 stock/models.py:832 stock/views.py:1647 #, fuzzy #| msgid "Serial numbers already exist: " msgid "Serial numbers already exist" @@ -1175,7 +1175,7 @@ msgstr "Bauobjekt aktualisiert" msgid "Add Build Order Attachment" msgstr "Auftragsanhang hinzufügen" -#: build/views.py:1059 order/views.py:111 order/views.py:164 part/views.py:96 +#: build/views.py:1059 order/views.py:111 order/views.py:164 part/views.py:164 #: stock/views.py:176 msgid "Added attachment" msgstr "Anhang hinzugefügt" @@ -1256,91 +1256,128 @@ msgstr "Parameter" msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:89 +#: common/models.py:89 part/models.py:668 part/templates/part/detail.html:168 +#: templates/js/table_filters.js:264 +msgid "Component" +msgstr "Komponente" + +#: common/models.py:90 +#, fuzzy +#| msgid "Part can be used in assemblies" +msgid "Parts can be used as sub-components by default" +msgstr "Teil kann in Baugruppen benutzt werden" + +#: common/models.py:96 part/models.py:679 part/templates/part/detail.html:188 +msgid "Purchaseable" +msgstr "Kaufbar" + +#: common/models.py:97 +msgid "Parts are purchaseable by default" +msgstr "" + +#: common/models.py:103 part/models.py:684 part/templates/part/detail.html:198 +#: templates/js/table_filters.js:272 +msgid "Salable" +msgstr "Verkäuflich" + +#: common/models.py:104 +msgid "Parts are salable by default" +msgstr "" + +#: common/models.py:110 part/models.py:674 part/templates/part/detail.html:178 +#: templates/js/table_filters.js:31 templates/js/table_filters.js:276 +msgid "Trackable" +msgstr "nachverfolgbar" + +#: common/models.py:111 +msgid "Parts are trackable by default" +msgstr "" + +#: common/models.py:117 #, fuzzy #| msgid "Order Reference" msgid "Build Order Reference Prefix" msgstr "Bestellreferenz" -#: common/models.py:90 +#: common/models.py:118 #, fuzzy #| msgid "Order reference" msgid "Prefix value for build order reference" msgstr "Bestell-Referenz" -#: common/models.py:95 +#: common/models.py:123 #, fuzzy #| msgid "Order Reference" msgid "Build Order Reference Regex" msgstr "Bestellreferenz" -#: common/models.py:96 +#: common/models.py:124 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:100 +#: common/models.py:128 #, fuzzy #| msgid "Sales Order Reference" msgid "Sales Order Reference Prefix" msgstr "Bestellungsreferenz" -#: common/models.py:101 +#: common/models.py:129 #, fuzzy #| msgid "Order reference" msgid "Prefix value for sales order reference" msgstr "Bestell-Referenz" -#: common/models.py:105 +#: common/models.py:133 #, fuzzy #| msgid "Order reference" msgid "Purchase Order Reference Prefix" msgstr "Bestell-Referenz" -#: common/models.py:106 +#: common/models.py:134 #, fuzzy #| msgid "Order reference" msgid "Prefix value for purchase order reference" msgstr "Bestell-Referenz" -#: common/models.py:277 +#: common/models.py:312 msgid "Settings key (must be unique - case insensitive" msgstr "" "Einstellungs-Schlüssel (muss einzigartig sein, Groß-/ Kleinschreibung wird " "nicht beachtet)" -#: common/models.py:279 +#: common/models.py:314 msgid "Settings value" msgstr "Einstellungs-Wert" -#: common/models.py:331 +#: common/models.py:366 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:345 +#: common/models.py:380 msgid "Key string must be unique" msgstr "Schlüsseltext muss eindeutig sein" -#: common/models.py:384 +#: common/models.py:419 msgid "Currency Symbol e.g. $" msgstr "Währungs-Symbol (z.B. €)" -#: common/models.py:386 +#: common/models.py:421 msgid "Currency Suffix e.g. AUD" msgstr "Währungs-Suffix (z.B. EUR)" -#: common/models.py:388 +#: common/models.py:423 msgid "Currency Description" msgstr "Währungs-Beschreibung" -#: common/models.py:390 +#: common/models.py:425 msgid "Currency Value" msgstr "Währungs-Wert" -#: common/models.py:392 +#: common/models.py:427 msgid "Use this currency as the base currency" msgstr "Benutze diese Währung als Basis-Währung" -#: common/models.py:475 +#: common/models.py:510 #, fuzzy #| msgid "Default Location" msgid "Default" @@ -1715,7 +1752,7 @@ msgid "Pricing Information" msgstr "Preisinformationen ansehen" #: company/templates/company/supplier_part_pricing.html:17 company/views.py:410 -#: part/templates/part/sale_prices.html:13 part/views.py:2292 +#: part/templates/part/sale_prices.html:13 part/views.py:2360 msgid "Add Price Break" msgstr "Preisstaffel hinzufügen" @@ -1767,7 +1804,7 @@ msgid "Orders" msgstr "Bestellungen" #: company/templates/company/tabs.html:9 -#: order/templates/order/receive_parts.html:14 part/models.py:294 +#: order/templates/order/receive_parts.html:14 part/models.py:295 #: part/templates/part/cat_link.html:7 part/templates/part/category.html:94 #: part/templates/part/category_tabs.html:6 #: templates/InvenTree/settings/tabs.html:22 templates/navbar.html:19 @@ -1848,17 +1885,17 @@ msgstr "Neues Zuliefererteil anlegen" msgid "Delete Supplier Part" msgstr "Zuliefererteil entfernen" -#: company/views.py:416 part/views.py:2298 +#: company/views.py:416 part/views.py:2366 #, fuzzy #| msgid "Add Price Break" msgid "Added new price break" msgstr "Preisstaffel hinzufügen" -#: company/views.py:453 part/views.py:2343 +#: company/views.py:453 part/views.py:2411 msgid "Edit Price Break" msgstr "Preisstaffel bearbeiten" -#: company/views.py:469 part/views.py:2359 +#: company/views.py:469 part/views.py:2427 msgid "Delete Price Break" msgstr "Preisstaffel löschen" @@ -1963,7 +2000,7 @@ msgstr "" msgid "Date order was completed" msgstr "Bestellung als vollständig markieren" -#: order/models.py:185 order/models.py:267 part/views.py:1409 +#: order/models.py:185 order/models.py:267 part/views.py:1477 #: stock/models.py:243 stock/models.py:816 msgid "Quantity must be greater than zero" msgstr "Anzahl muss größer Null sein" @@ -2161,8 +2198,8 @@ msgid "Line Items" msgstr "Position hinzufügen" #: order/templates/order/purchase_order_detail.html:17 -#: order/templates/order/sales_order_detail.html:19 order/views.py:1115 -#: order/views.py:1199 +#: order/templates/order/sales_order_detail.html:19 order/views.py:1117 +#: order/views.py:1201 msgid "Add Line Item" msgstr "Position hinzufügen" @@ -2351,131 +2388,135 @@ msgstr "Auftragsanhang hinzufügen" msgid "Create Purchase Order" msgstr "Bestellung anlegen" -#: order/views.py:345 +#: order/views.py:346 msgid "Create Sales Order" msgstr "Auftrag anlegen" -#: order/views.py:380 +#: order/views.py:382 msgid "Edit Purchase Order" msgstr "Bestellung bearbeiten" -#: order/views.py:401 +#: order/views.py:403 msgid "Edit Sales Order" msgstr "Auftrag bearbeiten" -#: order/views.py:418 +#: order/views.py:420 msgid "Cancel Order" msgstr "Bestellung stornieren" -#: order/views.py:428 order/views.py:455 +#: order/views.py:430 order/views.py:457 msgid "Confirm order cancellation" msgstr "Bestellstornierung bestätigen" -#: order/views.py:431 order/views.py:458 -msgid "Order cannot be cancelled" +#: order/views.py:433 +msgid "Order cannot be cancelled as either pending or placed" msgstr "" -#: order/views.py:445 +#: order/views.py:447 msgid "Cancel sales order" msgstr "Auftrag stornieren" -#: order/views.py:472 +#: order/views.py:460 +msgid "Order cannot be cancelled" +msgstr "" + +#: order/views.py:474 msgid "Issue Order" msgstr "Bestellung aufgeben" -#: order/views.py:482 +#: order/views.py:484 msgid "Confirm order placement" msgstr "Bestellungstätigung bestätigen" -#: order/views.py:492 +#: order/views.py:494 #, fuzzy #| msgid "Purchase Order Details" msgid "Purchase order issued" msgstr "Bestelldetails" -#: order/views.py:503 +#: order/views.py:505 msgid "Complete Order" msgstr "Auftrag fertigstellen" -#: order/views.py:520 +#: order/views.py:522 #, fuzzy #| msgid "Confirm build completion" msgid "Confirm order completion" msgstr "Bau-Fertigstellung bestätigen" -#: order/views.py:531 +#: order/views.py:533 #, fuzzy #| msgid "Mark order as complete" msgid "Purchase order completed" msgstr "Bestellung als vollständig markieren" -#: order/views.py:541 +#: order/views.py:543 msgid "Ship Order" msgstr "Versenden" -#: order/views.py:558 +#: order/views.py:560 msgid "Confirm order shipment" msgstr "Versand bestätigen" -#: order/views.py:564 +#: order/views.py:566 msgid "Could not ship order" msgstr "Versand fehlgeschlagen" -#: order/views.py:616 +#: order/views.py:618 msgid "Receive Parts" msgstr "Teile empfangen" -#: order/views.py:684 +#: order/views.py:686 msgid "Items received" msgstr "Anzahl empfangener Positionen" -#: order/views.py:698 +#: order/views.py:700 msgid "No destination set" msgstr "Kein Ziel gesetzt" -#: order/views.py:743 +#: order/views.py:745 msgid "Error converting quantity to number" msgstr "Fehler beim Konvertieren zu Zahl" -#: order/views.py:749 +#: order/views.py:751 msgid "Receive quantity less than zero" msgstr "Anzahl kleiner null empfangen" -#: order/views.py:755 +#: order/views.py:757 msgid "No lines specified" msgstr "Keine Zeilen angegeben" -#: order/views.py:1125 +#: order/views.py:1127 #, fuzzy #| msgid "Supplier part description" msgid "Supplier part must be specified" msgstr "Zuliefererbeschreibung des Teils" -#: order/views.py:1131 +#: order/views.py:1133 msgid "Supplier must match for Part and Order" msgstr "Zulieferer muss zum Teil und zur Bestellung passen" -#: order/views.py:1251 order/views.py:1270 +#: order/views.py:1253 order/views.py:1272 msgid "Edit Line Item" msgstr "Position bearbeiten" -#: order/views.py:1287 order/views.py:1300 +#: order/views.py:1289 order/views.py:1302 msgid "Delete Line Item" msgstr "Position löschen" -#: order/views.py:1293 order/views.py:1306 +#: order/views.py:1295 order/views.py:1308 msgid "Deleted line item" msgstr "Position gelöscht" -#: order/views.py:1315 +#: order/views.py:1317 msgid "Allocate Stock to Order" msgstr "Lagerbestand dem Auftrag zuweisen" -#: order/views.py:1385 +#: order/views.py:1387 msgid "Edit Allocation Quantity" msgstr "Zuordnung bearbeiten" -#: order/views.py:1401 +#: order/views.py:1403 msgid "Remove allocation" msgstr "Zuordnung entfernen" @@ -2557,7 +2598,7 @@ msgstr "Neues Zulieferer-Teil" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:93 part/models.py:1582 +#: part/forms.py:93 part/models.py:1632 msgid "Parent Part" msgstr "Ausgangsteil" @@ -2587,11 +2628,17 @@ msgstr "Bestätigen, dass die Stückliste korrekt ist" msgid "Select BOM file to upload" msgstr "Stücklisten-Datei zum Upload auswählen" -#: part/forms.py:159 +#: part/forms.py:154 +#, fuzzy +#| msgid "Delete Parts" +msgid "Related Part" +msgstr "Teile löschen" + +#: part/forms.py:173 msgid "Select part category" msgstr "Teilekategorie wählen" -#: part/forms.py:173 +#: part/forms.py:189 #, fuzzy #| msgid "Perform 'deep copy' which will duplicate all BOM data for this part" msgid "Duplicate all BOM data for this part" @@ -2599,165 +2646,181 @@ msgstr "" "Tiefe Kopie ausführen. Dies wird alle Daten der Stückliste für dieses Teil " "duplizieren" -#: part/forms.py:174 +#: part/forms.py:190 msgid "Copy BOM" msgstr "" -#: part/forms.py:179 +#: part/forms.py:195 msgid "Duplicate all parameter data for this part" msgstr "" -#: part/forms.py:180 +#: part/forms.py:196 #, fuzzy #| msgid "Parameters" msgid "Copy Parameters" msgstr "Parameter" -#: part/forms.py:185 +#: part/forms.py:201 msgid "Confirm part creation" msgstr "Erstellen des Teils bestätigen" -#: part/forms.py:279 +#: part/forms.py:298 msgid "Input quantity for price calculation" msgstr "Eintragsmenge zur Preisberechnung" -#: part/forms.py:282 +#: part/forms.py:301 msgid "Select currency for price calculation" msgstr "Währung zur Preisberechnung wählen" -#: part/models.py:66 +#: part/models.py:67 msgid "Default location for parts in this category" msgstr "Standard-Standort für Teile dieser Kategorie" -#: part/models.py:69 +#: part/models.py:70 msgid "Default keywords for parts in this category" msgstr "Standard-Stichworte für Teile dieser Kategorie" -#: part/models.py:75 part/templates/part/part_app_base.html:9 +#: part/models.py:76 part/templates/part/part_app_base.html:9 msgid "Part Category" msgstr "Teilkategorie" -#: part/models.py:76 part/templates/part/category.html:18 +#: part/models.py:77 part/templates/part/category.html:18 #: part/templates/part/category.html:89 templates/stats.html:12 msgid "Part Categories" msgstr "Teile-Kategorien" -#: part/models.py:345 part/models.py:355 +#: part/models.py:346 part/models.py:356 #, python-brace-format msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgstr "Teil '{p1}' wird in Stückliste für Teil '{p2}' benutzt (rekursiv)" -#: part/models.py:452 +#: part/models.py:453 #, fuzzy #| msgid "No serial numbers found" msgid "Next available serial numbers are" msgstr "Keine Seriennummern gefunden" -#: part/models.py:456 +#: part/models.py:457 msgid "Next available serial number is" msgstr "" -#: part/models.py:461 +#: part/models.py:462 #, fuzzy #| msgid "Empty serial number string" msgid "Most recent serial number is" msgstr "Keine Seriennummer angegeben" -#: part/models.py:539 +#: part/models.py:540 msgid "Part must be unique for name, IPN and revision" msgstr "Namen, Teile- und Revisionsnummern müssen eindeutig sein" -#: part/models.py:568 part/templates/part/detail.html:19 +#: part/models.py:569 part/templates/part/detail.html:19 msgid "Part name" msgstr "Name des Teils" -#: part/models.py:572 +#: part/models.py:573 msgid "Is this part a template part?" msgstr "Ist dieses Teil eine Vorlage?" -#: part/models.py:581 +#: part/models.py:582 msgid "Is this part a variant of another part?" msgstr "Ist dieses Teil eine Variante eines anderen Teils?" -#: part/models.py:583 +#: part/models.py:584 msgid "Part description" msgstr "Beschreibung des Teils" -#: part/models.py:585 +#: part/models.py:586 msgid "Part keywords to improve visibility in search results" msgstr "Schlüsselworte um die Sichtbarkeit in Suchergebnissen zu verbessern" -#: part/models.py:590 +#: part/models.py:591 msgid "Part category" msgstr "Teile-Kategorie" -#: part/models.py:592 +#: part/models.py:593 msgid "Internal Part Number" msgstr "Interne Teilenummer" -#: part/models.py:594 +#: part/models.py:595 msgid "Part revision or version number" msgstr "Revisions- oder Versionsnummer" -#: part/models.py:608 +#: part/models.py:609 msgid "Where is this item normally stored?" msgstr "Wo wird dieses Teil normalerweise gelagert?" -#: part/models.py:652 +#: part/models.py:653 msgid "Default supplier part" msgstr "Standard-Zulieferer?" -#: part/models.py:655 +#: part/models.py:656 msgid "Minimum allowed stock level" msgstr "Minimal zulässiger Lagerbestand" -#: part/models.py:657 +#: part/models.py:658 msgid "Stock keeping units for this part" msgstr "Stock Keeping Units (SKU) für dieses Teil" -#: part/models.py:659 +#: part/models.py:662 part/templates/part/detail.html:158 +#: templates/js/table_filters.js:260 +msgid "Assembly" +msgstr "Baugruppe" + +#: part/models.py:663 msgid "Can this part be built from other parts?" msgstr "Kann dieses Teil aus anderen Teilen angefertigt werden?" -#: part/models.py:661 +#: part/models.py:669 msgid "Can this part be used to build other parts?" msgstr "Kann dieses Teil zum Bau von anderen genutzt werden?" -#: part/models.py:663 +#: part/models.py:675 msgid "Does this part have tracking for unique items?" msgstr "Hat dieses Teil Tracking für einzelne Objekte?" -#: part/models.py:665 +#: part/models.py:680 msgid "Can this part be purchased from external suppliers?" msgstr "Kann dieses Teil von externen Zulieferern gekauft werden?" -#: part/models.py:667 +#: part/models.py:685 msgid "Can this part be sold to customers?" msgstr "Kann dieses Teil an Kunden verkauft werden?" -#: part/models.py:669 +#: part/models.py:689 part/templates/part/detail.html:215 +#: templates/js/table_filters.js:19 templates/js/table_filters.js:55 +#: templates/js/table_filters.js:186 templates/js/table_filters.js:243 +msgid "Active" +msgstr "Aktiv" + +#: part/models.py:690 msgid "Is this part active?" msgstr "Ist dieses Teil aktiv?" -#: part/models.py:671 +#: part/models.py:694 part/templates/part/detail.html:138 +#: templates/js/table_filters.js:27 +msgid "Virtual" +msgstr "Virtuell" + +#: part/models.py:695 msgid "Is this a virtual part, such as a software product or license?" msgstr "Ist dieses Teil virtuell, wie zum Beispiel eine Software oder Lizenz?" -#: part/models.py:673 +#: part/models.py:697 msgid "Part notes - supports Markdown formatting" msgstr "Bemerkungen - unterstüzt Markdown-Formatierung" -#: part/models.py:675 +#: part/models.py:699 msgid "Stored BOM checksum" msgstr "Prüfsumme der Stückliste gespeichert" -#: part/models.py:1455 +#: part/models.py:1505 #, 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:1472 +#: part/models.py:1522 #, fuzzy #| msgid "" #| "A stock item with this serial number already exists for template part " @@ -2767,126 +2830,138 @@ msgstr "" "Ein Teil mit dieser Seriennummer existiert bereits für die Teilevorlage " "{part}" -#: part/models.py:1491 templates/js/part.js:567 templates/js/stock.js:92 +#: part/models.py:1541 templates/js/part.js:567 templates/js/stock.js:92 #, fuzzy #| msgid "Instance Name" msgid "Test Name" msgstr "Instanzname" -#: part/models.py:1492 +#: part/models.py:1542 #, fuzzy #| msgid "Serial number for this item" msgid "Enter a name for the test" msgstr "Seriennummer für dieses Teil" -#: part/models.py:1497 +#: part/models.py:1547 #, fuzzy #| msgid "Description" msgid "Test Description" msgstr "Beschreibung" -#: part/models.py:1498 +#: part/models.py:1548 #, fuzzy #| msgid "Brief description of the build" msgid "Enter description for this test" msgstr "Kurze Beschreibung des Baus" -#: part/models.py:1503 templates/js/part.js:576 +#: part/models.py:1553 templates/js/part.js:576 #: templates/js/table_filters.js:172 msgid "Required" msgstr "benötigt" -#: part/models.py:1504 +#: part/models.py:1554 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:1509 templates/js/part.js:584 +#: part/models.py:1559 templates/js/part.js:584 #, fuzzy #| msgid "Required Parts" msgid "Requires Value" msgstr "benötigte Teile" -#: part/models.py:1510 +#: part/models.py:1560 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:1515 templates/js/part.js:591 +#: part/models.py:1565 templates/js/part.js:591 #, fuzzy #| msgid "Delete Attachment" msgid "Requires Attachment" msgstr "Anhang löschen" -#: part/models.py:1516 +#: part/models.py:1566 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:1549 +#: part/models.py:1599 msgid "Parameter template name must be unique" msgstr "Vorlagen-Name des Parameters muss eindeutig sein" -#: part/models.py:1554 +#: part/models.py:1604 msgid "Parameter Name" msgstr "Name des Parameters" -#: part/models.py:1556 +#: part/models.py:1606 msgid "Parameter Units" msgstr "Parameter Einheit" -#: part/models.py:1584 +#: part/models.py:1634 msgid "Parameter Template" msgstr "Parameter Vorlage" -#: part/models.py:1586 +#: part/models.py:1636 msgid "Parameter Value" msgstr "Parameter Wert" -#: part/models.py:1623 +#: part/models.py:1673 msgid "Select parent part" msgstr "Ausgangsteil auswählen" -#: part/models.py:1631 +#: part/models.py:1681 msgid "Select part to be used in BOM" msgstr "Teil für die Nutzung in der Stückliste auswählen" -#: part/models.py:1637 +#: part/models.py:1687 msgid "BOM quantity for this BOM item" msgstr "Stücklisten-Anzahl für dieses Stücklisten-Teil" -#: part/models.py:1639 +#: part/models.py:1689 #, fuzzy #| msgid "Confim BOM item deletion" msgid "This BOM item is optional" msgstr "Löschung von BOM-Position bestätigen" -#: part/models.py:1642 +#: part/models.py:1692 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "Geschätzter Ausschuss (absolut oder prozentual)" -#: part/models.py:1645 +#: part/models.py:1695 msgid "BOM item reference" msgstr "Referenz des Objekts auf der Stückliste" -#: part/models.py:1648 +#: part/models.py:1698 msgid "BOM item notes" msgstr "Notizen zum Stücklisten-Objekt" -#: part/models.py:1650 +#: part/models.py:1700 msgid "BOM line checksum" msgstr "Prüfsumme der Stückliste" -#: part/models.py:1717 part/views.py:1415 part/views.py:1467 +#: part/models.py:1767 part/views.py:1483 part/views.py:1535 #: stock/models.py:233 #, 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:1733 +#: part/models.py:1783 #, fuzzy #| msgid "New BOM Item" msgid "BOM Item" msgstr "Neue Stücklistenposition" +#: part/models.py:1898 +#, fuzzy +#| msgid "Select a part" +msgid "Select Related Part" +msgstr "Teil auswählen" + +#: part/models.py:1930 +msgid "" +"Error creating relationship: check that the part is not related to itself " +"and that the relationship is unique" +msgstr "" + #: part/templates/part/allocation.html:10 msgid "Part Stock Allocations" msgstr "Teilbestandszuordnungen" @@ -2977,7 +3052,7 @@ msgstr "Stückliste validieren" msgid "Validate" msgstr "BOM validieren" -#: part/templates/part/bom.html:62 part/views.py:1706 +#: part/templates/part/bom.html:62 part/views.py:1774 msgid "Export Bill of Materials" msgstr "Stückliste exportieren" @@ -3099,7 +3174,7 @@ msgstr "Neuen Bau beginnen" msgid "All parts" msgstr "Alle Teile" -#: part/templates/part/category.html:24 part/views.py:2109 +#: part/templates/part/category.html:24 part/views.py:2177 msgid "Create new part category" msgstr "Teilkategorie anlegen" @@ -3273,10 +3348,6 @@ msgstr "Erstellt von" msgid "Responsible User" msgstr "Verantwortlicher Benutzer" -#: part/templates/part/detail.html:138 templates/js/table_filters.js:27 -msgid "Virtual" -msgstr "Virtuell" - #: part/templates/part/detail.html:141 msgid "Part is virtual (not a physical part)" msgstr "Teil ist virtuell (kein physisches Teil)" @@ -3302,10 +3373,6 @@ msgstr "Teil kann keine Vorlage sein wenn es Variante eines anderen Teils ist" msgid "Part is not a template part" msgstr "Teil ist nicht virtuell" -#: part/templates/part/detail.html:158 templates/js/table_filters.js:260 -msgid "Assembly" -msgstr "Baugruppe" - #: part/templates/part/detail.html:161 msgid "Part can be assembled from other parts" msgstr "Teil kann aus anderen Teilen angefertigt werden" @@ -3314,10 +3381,6 @@ msgstr "Teil kann aus anderen Teilen angefertigt werden" msgid "Part cannot be assembled from other parts" msgstr "Teil kann nicht aus anderen Teilen angefertigt werden" -#: part/templates/part/detail.html:168 templates/js/table_filters.js:264 -msgid "Component" -msgstr "Komponente" - #: part/templates/part/detail.html:171 msgid "Part can be used in assemblies" msgstr "Teil kann in Baugruppen benutzt werden" @@ -3326,11 +3389,6 @@ msgstr "Teil kann in Baugruppen benutzt werden" msgid "Part cannot be used in assemblies" msgstr "Teil kann nicht in Baugruppen benutzt werden" -#: part/templates/part/detail.html:178 templates/js/table_filters.js:31 -#: templates/js/table_filters.js:276 -msgid "Trackable" -msgstr "nachverfolgbar" - #: part/templates/part/detail.html:181 msgid "Part stock is tracked by serial number" msgstr "Teilebestand in der Seriennummer hinterlegt" @@ -3339,18 +3397,10 @@ msgstr "Teilebestand in der Seriennummer hinterlegt" msgid "Part stock is not tracked by serial number" msgstr "Teilebestand ist nicht in der Seriennummer hinterlegt" -#: part/templates/part/detail.html:188 -msgid "Purchaseable" -msgstr "Kaufbar" - #: part/templates/part/detail.html:191 part/templates/part/detail.html:193 msgid "Part can be purchased from external suppliers" msgstr "Teil kann von externen Zulieferern gekauft werden" -#: part/templates/part/detail.html:198 templates/js/table_filters.js:272 -msgid "Salable" -msgstr "Verkäuflich" - #: part/templates/part/detail.html:201 msgid "Part can be sold to customers" msgstr "Teil kann an Kunden verkauft werden" @@ -3359,19 +3409,13 @@ msgstr "Teil kann an Kunden verkauft werden" msgid "Part cannot be sold to customers" msgstr "Teil kann nicht an Kunden verkauft werden" -#: part/templates/part/detail.html:214 templates/js/table_filters.js:19 -#: templates/js/table_filters.js:55 templates/js/table_filters.js:186 -#: templates/js/table_filters.js:243 -msgid "Active" -msgstr "Aktiv" - -#: part/templates/part/detail.html:217 +#: part/templates/part/detail.html:218 #, fuzzy #| msgid "This part is not active" msgid "Part is active" msgstr "Dieses Teil ist nicht aktiv" -#: part/templates/part/detail.html:219 +#: part/templates/part/detail.html:220 #, fuzzy #| msgid "This part is not active" msgid "Part is not active" @@ -3389,7 +3433,7 @@ msgstr "Teilparameter" msgid "Add new parameter" msgstr "Parameter hinzufügen" -#: part/templates/part/params.html:15 templates/InvenTree/settings/part.html:28 +#: part/templates/part/params.html:15 templates/InvenTree/settings/part.html:35 msgid "New Parameter" msgstr "Neuer Parameter" @@ -3398,8 +3442,8 @@ msgstr "Neuer Parameter" msgid "Value" msgstr "Wert" -#: part/templates/part/params.html:41 part/templates/part/supplier.html:19 -#: users/models.py:146 +#: part/templates/part/params.html:41 part/templates/part/related.html:41 +#: part/templates/part/supplier.html:19 users/models.py:147 msgid "Delete" msgstr "Löschen" @@ -3526,6 +3570,18 @@ msgstr "Aus vorhandenen Bildern auswählen" msgid "Upload new image" msgstr "Neues Bild hochladen" +#: part/templates/part/related.html:9 +#, fuzzy +#| msgid "Delete Parts" +msgid "Related Parts" +msgstr "Teile löschen" + +#: part/templates/part/related.html:15 +#, fuzzy +#| msgid "Edit Template" +msgid "Add Related" +msgstr "Vorlage bearbeiten" + #: part/templates/part/sale_prices.html:9 part/templates/part/tabs.html:53 #, fuzzy #| msgid "Price" @@ -3605,6 +3661,12 @@ msgstr "Benutzt in" msgid "Tests" msgstr "" +#: part/templates/part/tabs.html:67 +#, fuzzy +#| msgid "Created" +msgid "Related" +msgstr "Erstellt" + #: part/templates/part/track.html:8 msgid "Part Tracking" msgstr "Teilverfolgung" @@ -3632,217 +3694,229 @@ msgid "New Variant" msgstr "Varianten" #: part/views.py:80 +#, fuzzy +#| msgid "Allocated Parts" +msgid "Add Related Part" +msgstr "Zugeordnete Teile" + +#: part/views.py:136 +#, fuzzy +#| msgid "Delete Supplier Part" +msgid "Delete Related Part" +msgstr "Zuliefererteil entfernen" + +#: part/views.py:148 msgid "Add part attachment" msgstr "Teilanhang hinzufügen" -#: part/views.py:135 templates/attachment_table.html:34 +#: part/views.py:203 templates/attachment_table.html:34 msgid "Edit attachment" msgstr "Anhang bearbeiten" -#: part/views.py:141 +#: part/views.py:209 msgid "Part attachment updated" msgstr "Teilanhang aktualisiert" -#: part/views.py:156 +#: part/views.py:224 msgid "Delete Part Attachment" msgstr "Teilanhang löschen" -#: part/views.py:164 +#: part/views.py:232 msgid "Deleted part attachment" msgstr "Teilanhang gelöscht" -#: part/views.py:173 +#: part/views.py:241 #, fuzzy #| msgid "Create Part Parameter Template" msgid "Create Test Template" msgstr "Teilparametervorlage anlegen" -#: part/views.py:202 +#: part/views.py:270 #, fuzzy #| msgid "Edit Template" msgid "Edit Test Template" msgstr "Vorlage bearbeiten" -#: part/views.py:218 +#: part/views.py:286 #, fuzzy #| msgid "Delete Template" msgid "Delete Test Template" msgstr "Vorlage löschen" -#: part/views.py:227 +#: part/views.py:295 msgid "Set Part Category" msgstr "Teilkategorie auswählen" -#: part/views.py:277 +#: part/views.py:345 #, python-brace-format msgid "Set category for {n} parts" msgstr "Kategorie für {n} Teile setzen" -#: part/views.py:312 +#: part/views.py:380 msgid "Create Variant" msgstr "Variante anlegen" -#: part/views.py:394 +#: part/views.py:462 msgid "Duplicate Part" msgstr "Teil duplizieren" -#: part/views.py:401 +#: part/views.py:469 msgid "Copied part" msgstr "Teil kopiert" -#: part/views.py:455 part/views.py:585 +#: part/views.py:523 part/views.py:653 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:520 templates/js/stock.js:840 +#: part/views.py:588 templates/js/stock.js:840 msgid "Create New Part" msgstr "Neues Teil anlegen" -#: part/views.py:527 +#: part/views.py:595 msgid "Created new part" msgstr "Neues Teil angelegt" -#: part/views.py:743 +#: part/views.py:811 msgid "Part QR Code" msgstr "Teil-QR-Code" -#: part/views.py:762 +#: part/views.py:830 msgid "Upload Part Image" msgstr "Teilbild hochladen" -#: part/views.py:770 part/views.py:807 +#: part/views.py:838 part/views.py:875 msgid "Updated part image" msgstr "Teilbild aktualisiert" -#: part/views.py:779 +#: part/views.py:847 msgid "Select Part Image" msgstr "Teilbild auswählen" -#: part/views.py:810 +#: part/views.py:878 msgid "Part image not found" msgstr "Teilbild nicht gefunden" -#: part/views.py:821 +#: part/views.py:889 msgid "Edit Part Properties" msgstr "Teileigenschaften bearbeiten" -#: part/views.py:848 +#: part/views.py:916 #, fuzzy #| msgid "Duplicate Part" msgid "Duplicate BOM" msgstr "Teil duplizieren" -#: part/views.py:879 +#: part/views.py:947 #, fuzzy #| msgid "Confirm unallocation of build stock" msgid "Confirm duplication of BOM from parent" msgstr "Zuweisungsaufhebung bestätigen" -#: part/views.py:900 +#: part/views.py:968 msgid "Validate BOM" msgstr "BOM validieren" -#: part/views.py:923 +#: part/views.py:991 #, fuzzy #| msgid "Confirm that the BOM is correct" msgid "Confirm that the BOM is valid" msgstr "Bestätigen, dass die Stückliste korrekt ist" -#: part/views.py:934 +#: part/views.py:1002 #, fuzzy #| msgid "Validate Bill of Materials" msgid "Validated Bill of Materials" msgstr "Stückliste validieren" -#: part/views.py:1068 +#: part/views.py:1136 msgid "No BOM file provided" msgstr "Keine Stückliste angegeben" -#: part/views.py:1418 +#: part/views.py:1486 msgid "Enter a valid quantity" msgstr "Bitte eine gültige Anzahl eingeben" -#: part/views.py:1443 part/views.py:1446 +#: part/views.py:1511 part/views.py:1514 msgid "Select valid part" msgstr "Bitte ein gültiges Teil auswählen" -#: part/views.py:1452 +#: part/views.py:1520 msgid "Duplicate part selected" msgstr "Teil doppelt ausgewählt" -#: part/views.py:1490 +#: part/views.py:1558 msgid "Select a part" msgstr "Teil auswählen" -#: part/views.py:1496 +#: part/views.py:1564 #, 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:1500 +#: part/views.py:1568 msgid "Specify quantity" msgstr "Anzahl angeben" -#: part/views.py:1756 +#: part/views.py:1824 msgid "Confirm Part Deletion" msgstr "Löschen des Teils bestätigen" -#: part/views.py:1765 +#: part/views.py:1833 msgid "Part was deleted" msgstr "Teil wurde gelöscht" -#: part/views.py:1774 +#: part/views.py:1842 msgid "Part Pricing" msgstr "Teilbepreisung" -#: part/views.py:1900 +#: part/views.py:1968 msgid "Create Part Parameter Template" msgstr "Teilparametervorlage anlegen" -#: part/views.py:1910 +#: part/views.py:1978 msgid "Edit Part Parameter Template" msgstr "Teilparametervorlage bearbeiten" -#: part/views.py:1919 +#: part/views.py:1987 msgid "Delete Part Parameter Template" msgstr "Teilparametervorlage löschen" -#: part/views.py:1929 +#: part/views.py:1997 msgid "Create Part Parameter" msgstr "Teilparameter anlegen" -#: part/views.py:1981 +#: part/views.py:2049 msgid "Edit Part Parameter" msgstr "Teilparameter bearbeiten" -#: part/views.py:1997 +#: part/views.py:2065 msgid "Delete Part Parameter" msgstr "Teilparameter löschen" -#: part/views.py:2056 +#: part/views.py:2124 msgid "Edit Part Category" msgstr "Teilkategorie bearbeiten" -#: part/views.py:2093 +#: part/views.py:2161 msgid "Delete Part Category" msgstr "Teilkategorie löschen" -#: part/views.py:2101 +#: part/views.py:2169 msgid "Part category was deleted" msgstr "Teilekategorie wurde gelöscht" -#: part/views.py:2164 +#: part/views.py:2232 #, fuzzy #| msgid "Create BOM item" msgid "Create BOM Item" msgstr "BOM-Position anlegen" -#: part/views.py:2232 +#: part/views.py:2300 msgid "Edit BOM item" msgstr "BOM-Position beaarbeiten" -#: part/views.py:2282 +#: part/views.py:2350 msgid "Confim BOM item deletion" msgstr "Löschung von BOM-Position bestätigen" @@ -4806,52 +4880,52 @@ msgstr "Lagerbestand erfassen" msgid "Create new Stock Item" msgstr "Neues Lagerobjekt hinzufügen" -#: stock/views.py:1553 +#: stock/views.py:1555 #, fuzzy #| msgid "Count stock items" msgid "Duplicate Stock Item" msgstr "Lagerobjekte zählen" -#: stock/views.py:1619 +#: stock/views.py:1621 msgid "Invalid quantity" msgstr "Ungültige Menge" -#: stock/views.py:1622 +#: stock/views.py:1624 #, fuzzy #| msgid "Quantity must be greater than zero" msgid "Quantity cannot be less than zero" msgstr "Anzahl muss größer Null sein" -#: stock/views.py:1626 +#: stock/views.py:1628 msgid "Invalid part selection" msgstr "Ungültige Teileauswahl" -#: stock/views.py:1674 +#: stock/views.py:1676 #, python-brace-format msgid "Created {n} new stock items" msgstr "{n} neue Lagerobjekte erstellt" -#: stock/views.py:1693 stock/views.py:1709 +#: stock/views.py:1695 stock/views.py:1711 msgid "Created new stock item" msgstr "Neues Lagerobjekt erstellt" -#: stock/views.py:1728 +#: stock/views.py:1730 msgid "Delete Stock Location" msgstr "Standort löschen" -#: stock/views.py:1742 +#: stock/views.py:1744 msgid "Delete Stock Item" msgstr "Lagerobjekt löschen" -#: stock/views.py:1754 +#: stock/views.py:1756 msgid "Delete Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag löschen" -#: stock/views.py:1773 +#: stock/views.py:1775 msgid "Edit Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag bearbeiten" -#: stock/views.py:1783 +#: stock/views.py:1785 msgid "Add Stock Tracking Entry" msgstr "Lagerbestands-Tracking-Eintrag hinzufügen" @@ -4975,21 +5049,27 @@ msgstr "InvenTree-Version" msgid "Part Settings" msgstr "Einstellungen" -#: templates/InvenTree/settings/part.html:24 +#: templates/InvenTree/settings/part.html:14 +#, fuzzy +#| msgid "Source Location" +msgid "Part Options" +msgstr "Quell-Standort" + +#: templates/InvenTree/settings/part.html:31 #, fuzzy #| msgid "Edit Part Parameter Template" msgid "Part Parameter Templates" msgstr "Teilparametervorlage bearbeiten" -#: templates/InvenTree/settings/part.html:45 +#: templates/InvenTree/settings/part.html:52 msgid "No part parameter templates found" msgstr "Keine Teilparametervorlagen gefunden" -#: templates/InvenTree/settings/part.html:65 +#: templates/InvenTree/settings/part.html:72 msgid "Edit Template" msgstr "Vorlage bearbeiten" -#: templates/InvenTree/settings/part.html:66 +#: templates/InvenTree/settings/part.html:73 msgid "Delete Template" msgstr "Vorlage löschen" @@ -5920,69 +6000,73 @@ msgstr "Position löschen" msgid "Delete Stock" msgstr "Bestand löschen" -#: users/admin.py:61 +#: users/admin.py:62 #, fuzzy #| msgid "User" msgid "Users" msgstr "Benutzer" -#: users/admin.py:62 +#: users/admin.py:63 msgid "Select which users are assigned to this group" msgstr "" #: users/admin.py:120 +msgid "The following users are members of multiple groups:" +msgstr "" + +#: users/admin.py:143 #, fuzzy #| msgid "External Link" msgid "Personal info" msgstr "Externer Link" -#: users/admin.py:121 +#: users/admin.py:144 #, fuzzy #| msgid "Revision" msgid "Permissions" msgstr "Revision" -#: users/admin.py:124 +#: users/admin.py:147 #, fuzzy #| msgid "Import BOM data" msgid "Important dates" msgstr "Stückliste importieren" -#: users/models.py:129 +#: users/models.py:130 msgid "Permission set" msgstr "" -#: users/models.py:137 +#: users/models.py:138 msgid "Group" msgstr "" -#: users/models.py:140 +#: users/models.py:141 msgid "View" msgstr "" -#: users/models.py:140 +#: users/models.py:141 msgid "Permission to view items" msgstr "" -#: users/models.py:142 +#: users/models.py:143 #, fuzzy #| msgid "Address" msgid "Add" msgstr "Adresse" -#: users/models.py:142 +#: users/models.py:143 msgid "Permission to add items" msgstr "" -#: users/models.py:144 +#: users/models.py:145 msgid "Change" msgstr "" -#: users/models.py:144 +#: users/models.py:145 msgid "Permissions to edit items" msgstr "" -#: users/models.py:146 +#: users/models.py:147 #, fuzzy #| msgid "Remove selected BOM items" msgid "Permission to delete items" diff --git a/InvenTree/locale/en/LC_MESSAGES/django.po b/InvenTree/locale/en/LC_MESSAGES/django.po index aacb4b74ec..c4c14849c2 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-11-03 10:02+0000\n" +"POT-Creation-Date: 2020-11-09 12:47+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -26,23 +26,23 @@ msgstr "" msgid "No matching action found" msgstr "" -#: InvenTree/forms.py:102 build/forms.py:82 build/forms.py:170 +#: InvenTree/forms.py:130 build/forms.py:82 build/forms.py:170 msgid "Confirm" msgstr "" -#: InvenTree/forms.py:118 +#: InvenTree/forms.py:146 msgid "Confirm item deletion" msgstr "" -#: InvenTree/forms.py:150 +#: InvenTree/forms.py:178 msgid "Enter new password" msgstr "" -#: InvenTree/forms.py:157 +#: InvenTree/forms.py:185 msgid "Confirm new password" msgstr "" -#: InvenTree/forms.py:192 +#: InvenTree/forms.py:220 msgid "Apply Theme" msgstr "" @@ -396,8 +396,8 @@ msgstr "" #: build/templates/build/detail.html:24 order/models.py:519 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:148 -#: order/templates/order/receive_parts.html:19 part/models.py:293 -#: part/templates/part/part_app_base.html:7 +#: order/templates/order/receive_parts.html:19 part/models.py:294 +#: part/templates/part/part_app_base.html:7 part/templates/part/related.html:26 #: part/templates/part/set_category.html:13 templates/InvenTree/search.html:133 #: templates/js/barcode.js:336 templates/js/bom.js:147 templates/js/bom.js:484 #: templates/js/build.js:647 templates/js/company.js:138 @@ -476,14 +476,14 @@ msgstr "" msgid "External Link" msgstr "" -#: build/models.py:177 part/models.py:596 stock/models.py:385 +#: build/models.py:177 part/models.py:597 stock/models.py:385 msgid "Link to external URL" msgstr "" -#: build/models.py:181 build/templates/build/tabs.html:14 company/models.py:314 +#: build/models.py:181 build/templates/build/tabs.html:23 company/models.py:314 #: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:18 #: order/templates/order/purchase_order_detail.html:203 -#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:70 +#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:73 #: stock/forms.py:306 stock/forms.py:338 stock/forms.py:366 stock/models.py:455 #: stock/models.py:1428 stock/templates/stock/tabs.html:26 #: templates/js/barcode.js:391 templates/js/bom.js:250 @@ -495,65 +495,65 @@ msgstr "" msgid "Extra build notes" msgstr "" -#: build/models.py:543 +#: build/models.py:551 msgid "No build output specified" msgstr "" -#: build/models.py:546 +#: build/models.py:554 msgid "Build output is already completed" msgstr "" -#: build/models.py:549 +#: build/models.py:557 msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:620 +#: build/models.py:632 msgid "Completed build output" msgstr "" -#: build/models.py:858 +#: build/models.py:870 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:880 +#: build/models.py:892 msgid "Build item must specify a build output" msgstr "" -#: build/models.py:885 +#: build/models.py:897 #, python-brace-format msgid "Selected stock item not found in BOM for part '{p}'" msgstr "" -#: build/models.py:889 +#: build/models.py:901 #, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:896 order/models.py:603 +#: build/models.py:908 order/models.py:603 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:900 order/models.py:606 +#: build/models.py:912 order/models.py:606 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:904 +#: build/models.py:916 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:944 +#: build/models.py:956 msgid "Build to allocate parts" msgstr "" -#: build/models.py:951 +#: build/models.py:963 msgid "Source stock item" msgstr "" -#: build/models.py:964 +#: build/models.py:976 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:972 +#: build/models.py:984 msgid "Destination stock item" msgstr "" @@ -565,47 +565,47 @@ msgstr "" msgid "Build order has been completed" msgstr "" -#: build/templates/build/allocate.html:24 +#: build/templates/build/allocate.html:25 msgid "Create new build output" msgstr "" -#: build/templates/build/allocate.html:25 +#: build/templates/build/allocate.html:26 msgid "Create New Output" msgstr "" -#: build/templates/build/allocate.html:28 +#: build/templates/build/allocate.html:29 msgid "Order required parts" msgstr "" -#: build/templates/build/allocate.html:29 -#: company/templates/company/detail_part.html:28 order/views.py:801 +#: build/templates/build/allocate.html:30 +#: company/templates/company/detail_part.html:28 order/views.py:803 #: part/templates/part/category.html:125 msgid "Order Parts" msgstr "" -#: build/templates/build/allocate.html:32 templates/js/build.js:574 +#: build/templates/build/allocate.html:33 templates/js/build.js:574 msgid "Unallocate stock" msgstr "" -#: build/templates/build/allocate.html:33 build/views.py:341 build/views.py:778 +#: build/templates/build/allocate.html:34 build/views.py:341 build/views.py:778 msgid "Unallocate Stock" msgstr "" -#: build/templates/build/allocate.html:46 +#: build/templates/build/allocate.html:48 msgid "Create a new build output" msgstr "" -#: build/templates/build/allocate.html:47 +#: build/templates/build/allocate.html:49 msgid "No incomplete build outputs remain." msgstr "" -#: build/templates/build/allocate.html:48 +#: build/templates/build/allocate.html:50 msgid "Create a new build output using the button above" msgstr "" -#: build/templates/build/attachments.html:11 build/templates/build/tabs.html:17 +#: build/templates/build/attachments.html:11 build/templates/build/tabs.html:29 #: order/templates/order/po_tabs.html:11 order/templates/order/so_tabs.html:16 -#: part/templates/part/tabs.html:67 stock/templates/stock/tabs.html:32 +#: part/templates/part/tabs.html:70 stock/templates/stock/tabs.html:32 msgid "Attachments" msgstr "" @@ -698,7 +698,7 @@ msgstr "" msgid "Sales Order" msgstr "" -#: build/templates/build/build_output.html:9 build/templates/build/tabs.html:11 +#: build/templates/build/build_output.html:9 build/templates/build/tabs.html:17 msgid "Build Outputs" msgstr "" @@ -855,8 +855,8 @@ msgstr "" msgid "Details" msgstr "" -#: build/templates/build/tabs.html:8 -msgid "Allocate Parts" +#: build/templates/build/tabs.html:10 +msgid "Incomplete" msgstr "" #: build/templates/build/unallocate.html:10 @@ -887,7 +887,7 @@ msgstr "" msgid "Create Build Output" msgstr "" -#: build/views.py:207 stock/models.py:832 stock/views.py:1645 +#: build/views.py:207 stock/models.py:832 stock/views.py:1647 msgid "Serial numbers already exist" msgstr "" @@ -992,7 +992,7 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1059 order/views.py:111 order/views.py:164 part/views.py:96 +#: build/views.py:1059 order/views.py:111 order/views.py:164 part/views.py:164 #: stock/views.py:176 msgid "Added attachment" msgstr "" @@ -1061,75 +1061,110 @@ msgstr "" msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:89 -msgid "Build Order Reference Prefix" +#: common/models.py:89 part/models.py:668 part/templates/part/detail.html:168 +#: templates/js/table_filters.js:264 +msgid "Component" msgstr "" #: common/models.py:90 +msgid "Parts can be used as sub-components by default" +msgstr "" + +#: common/models.py:96 part/models.py:679 part/templates/part/detail.html:188 +msgid "Purchaseable" +msgstr "" + +#: common/models.py:97 +msgid "Parts are purchaseable by default" +msgstr "" + +#: common/models.py:103 part/models.py:684 part/templates/part/detail.html:198 +#: templates/js/table_filters.js:272 +msgid "Salable" +msgstr "" + +#: common/models.py:104 +msgid "Parts are salable by default" +msgstr "" + +#: common/models.py:110 part/models.py:674 part/templates/part/detail.html:178 +#: templates/js/table_filters.js:31 templates/js/table_filters.js:276 +msgid "Trackable" +msgstr "" + +#: common/models.py:111 +msgid "Parts are trackable by default" +msgstr "" + +#: common/models.py:117 +msgid "Build Order Reference Prefix" +msgstr "" + +#: common/models.py:118 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:95 +#: common/models.py:123 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:96 +#: common/models.py:124 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:100 +#: common/models.py:128 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:101 +#: common/models.py:129 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:105 +#: common/models.py:133 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:106 +#: common/models.py:134 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:277 +#: common/models.py:312 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:279 +#: common/models.py:314 msgid "Settings value" msgstr "" -#: common/models.py:331 +#: common/models.py:366 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:345 +#: common/models.py:380 msgid "Key string must be unique" msgstr "" -#: common/models.py:384 +#: common/models.py:419 msgid "Currency Symbol e.g. $" msgstr "" -#: common/models.py:386 +#: common/models.py:421 msgid "Currency Suffix e.g. AUD" msgstr "" -#: common/models.py:388 +#: common/models.py:423 msgid "Currency Description" msgstr "" -#: common/models.py:390 +#: common/models.py:425 msgid "Currency Value" msgstr "" -#: common/models.py:392 +#: common/models.py:427 msgid "Use this currency as the base currency" msgstr "" -#: common/models.py:475 +#: common/models.py:510 msgid "Default" msgstr "" @@ -1487,7 +1522,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:17 company/views.py:410 -#: part/templates/part/sale_prices.html:13 part/views.py:2292 +#: part/templates/part/sale_prices.html:13 part/views.py:2360 msgid "Add Price Break" msgstr "" @@ -1533,7 +1568,7 @@ msgid "Orders" msgstr "" #: company/templates/company/tabs.html:9 -#: order/templates/order/receive_parts.html:14 part/models.py:294 +#: order/templates/order/receive_parts.html:14 part/models.py:295 #: part/templates/part/cat_link.html:7 part/templates/part/category.html:94 #: part/templates/part/category_tabs.html:6 #: templates/InvenTree/settings/tabs.html:22 templates/navbar.html:19 @@ -1614,15 +1649,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:416 part/views.py:2298 +#: company/views.py:416 part/views.py:2366 msgid "Added new price break" msgstr "" -#: company/views.py:453 part/views.py:2343 +#: company/views.py:453 part/views.py:2411 msgid "Edit Price Break" msgstr "" -#: company/views.py:469 part/views.py:2359 +#: company/views.py:469 part/views.py:2427 msgid "Delete Price Break" msgstr "" @@ -1715,7 +1750,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:185 order/models.py:267 part/views.py:1409 +#: order/models.py:185 order/models.py:267 part/views.py:1477 #: stock/models.py:243 stock/models.py:816 msgid "Quantity must be greater than zero" msgstr "" @@ -1904,8 +1939,8 @@ msgid "Line Items" msgstr "" #: order/templates/order/purchase_order_detail.html:17 -#: order/templates/order/sales_order_detail.html:19 order/views.py:1115 -#: order/views.py:1199 +#: order/templates/order/sales_order_detail.html:19 order/views.py:1117 +#: order/views.py:1201 msgid "Add Line Item" msgstr "" @@ -2088,123 +2123,127 @@ msgstr "" msgid "Create Purchase Order" msgstr "" -#: order/views.py:345 +#: order/views.py:346 msgid "Create Sales Order" msgstr "" -#: order/views.py:380 +#: order/views.py:382 msgid "Edit Purchase Order" msgstr "" -#: order/views.py:401 +#: order/views.py:403 msgid "Edit Sales Order" msgstr "" -#: order/views.py:418 +#: order/views.py:420 msgid "Cancel Order" msgstr "" -#: order/views.py:428 order/views.py:455 +#: order/views.py:430 order/views.py:457 msgid "Confirm order cancellation" msgstr "" -#: order/views.py:431 order/views.py:458 -msgid "Order cannot be cancelled" +#: order/views.py:433 +msgid "Order cannot be cancelled as either pending or placed" msgstr "" -#: order/views.py:445 +#: order/views.py:447 msgid "Cancel sales order" msgstr "" -#: order/views.py:472 +#: order/views.py:460 +msgid "Order cannot be cancelled" +msgstr "" + +#: order/views.py:474 msgid "Issue Order" msgstr "" -#: order/views.py:482 +#: order/views.py:484 msgid "Confirm order placement" msgstr "" -#: order/views.py:492 +#: order/views.py:494 msgid "Purchase order issued" msgstr "" -#: order/views.py:503 +#: order/views.py:505 msgid "Complete Order" msgstr "" -#: order/views.py:520 +#: order/views.py:522 msgid "Confirm order completion" msgstr "" -#: order/views.py:531 +#: order/views.py:533 msgid "Purchase order completed" msgstr "" -#: order/views.py:541 +#: order/views.py:543 msgid "Ship Order" msgstr "" -#: order/views.py:558 +#: order/views.py:560 msgid "Confirm order shipment" msgstr "" -#: order/views.py:564 +#: order/views.py:566 msgid "Could not ship order" msgstr "" -#: order/views.py:616 +#: order/views.py:618 msgid "Receive Parts" msgstr "" -#: order/views.py:684 +#: order/views.py:686 msgid "Items received" msgstr "" -#: order/views.py:698 +#: order/views.py:700 msgid "No destination set" msgstr "" -#: order/views.py:743 +#: order/views.py:745 msgid "Error converting quantity to number" msgstr "" -#: order/views.py:749 +#: order/views.py:751 msgid "Receive quantity less than zero" msgstr "" -#: order/views.py:755 +#: order/views.py:757 msgid "No lines specified" msgstr "" -#: order/views.py:1125 +#: order/views.py:1127 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1131 +#: order/views.py:1133 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1251 order/views.py:1270 +#: order/views.py:1253 order/views.py:1272 msgid "Edit Line Item" msgstr "" -#: order/views.py:1287 order/views.py:1300 +#: order/views.py:1289 order/views.py:1302 msgid "Delete Line Item" msgstr "" -#: order/views.py:1293 order/views.py:1306 +#: order/views.py:1295 order/views.py:1308 msgid "Deleted line item" msgstr "" -#: order/views.py:1315 +#: order/views.py:1317 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1385 +#: order/views.py:1387 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1401 +#: order/views.py:1403 msgid "Remove allocation" msgstr "" @@ -2278,7 +2317,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:93 part/models.py:1582 +#: part/forms.py:93 part/models.py:1632 msgid "Parent Part" msgstr "" @@ -2302,270 +2341,300 @@ msgstr "" msgid "Select BOM file to upload" msgstr "" -#: part/forms.py:159 -msgid "Select part category" +#: part/forms.py:154 +msgid "Related Part" msgstr "" #: part/forms.py:173 +msgid "Select part category" +msgstr "" + +#: part/forms.py:189 msgid "Duplicate all BOM data for this part" msgstr "" -#: part/forms.py:174 +#: part/forms.py:190 msgid "Copy BOM" msgstr "" -#: part/forms.py:179 +#: part/forms.py:195 msgid "Duplicate all parameter data for this part" msgstr "" -#: part/forms.py:180 +#: part/forms.py:196 msgid "Copy Parameters" msgstr "" -#: part/forms.py:185 +#: part/forms.py:201 msgid "Confirm part creation" msgstr "" -#: part/forms.py:279 +#: part/forms.py:298 msgid "Input quantity for price calculation" msgstr "" -#: part/forms.py:282 +#: part/forms.py:301 msgid "Select currency for price calculation" msgstr "" -#: part/models.py:66 +#: part/models.py:67 msgid "Default location for parts in this category" msgstr "" -#: part/models.py:69 +#: part/models.py:70 msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:75 part/templates/part/part_app_base.html:9 +#: part/models.py:76 part/templates/part/part_app_base.html:9 msgid "Part Category" msgstr "" -#: part/models.py:76 part/templates/part/category.html:18 +#: part/models.py:77 part/templates/part/category.html:18 #: part/templates/part/category.html:89 templates/stats.html:12 msgid "Part Categories" msgstr "" -#: part/models.py:345 part/models.py:355 +#: part/models.py:346 part/models.py:356 #, python-brace-format msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgstr "" -#: part/models.py:452 +#: part/models.py:453 msgid "Next available serial numbers are" msgstr "" -#: part/models.py:456 +#: part/models.py:457 msgid "Next available serial number is" msgstr "" -#: part/models.py:461 +#: part/models.py:462 msgid "Most recent serial number is" msgstr "" -#: part/models.py:539 +#: part/models.py:540 msgid "Part must be unique for name, IPN and revision" msgstr "" -#: part/models.py:568 part/templates/part/detail.html:19 +#: part/models.py:569 part/templates/part/detail.html:19 msgid "Part name" msgstr "" -#: part/models.py:572 +#: part/models.py:573 msgid "Is this part a template part?" msgstr "" -#: part/models.py:581 +#: part/models.py:582 msgid "Is this part a variant of another part?" msgstr "" -#: part/models.py:583 +#: part/models.py:584 msgid "Part description" msgstr "" -#: part/models.py:585 +#: part/models.py:586 msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:590 +#: part/models.py:591 msgid "Part category" msgstr "" -#: part/models.py:592 +#: part/models.py:593 msgid "Internal Part Number" msgstr "" -#: part/models.py:594 +#: part/models.py:595 msgid "Part revision or version number" msgstr "" -#: part/models.py:608 +#: part/models.py:609 msgid "Where is this item normally stored?" msgstr "" -#: part/models.py:652 +#: part/models.py:653 msgid "Default supplier part" msgstr "" -#: part/models.py:655 +#: part/models.py:656 msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:657 +#: part/models.py:658 msgid "Stock keeping units for this part" msgstr "" -#: part/models.py:659 -msgid "Can this part be built from other parts?" -msgstr "" - -#: part/models.py:661 -msgid "Can this part be used to build other parts?" +#: part/models.py:662 part/templates/part/detail.html:158 +#: templates/js/table_filters.js:260 +msgid "Assembly" msgstr "" #: part/models.py:663 -msgid "Does this part have tracking for unique items?" -msgstr "" - -#: part/models.py:665 -msgid "Can this part be purchased from external suppliers?" -msgstr "" - -#: part/models.py:667 -msgid "Can this part be sold to customers?" +msgid "Can this part be built from other parts?" msgstr "" #: part/models.py:669 -msgid "Is this part active?" -msgstr "" - -#: part/models.py:671 -msgid "Is this a virtual part, such as a software product or license?" -msgstr "" - -#: part/models.py:673 -msgid "Part notes - supports Markdown formatting" +msgid "Can this part be used to build other parts?" msgstr "" #: part/models.py:675 +msgid "Does this part have tracking for unique items?" +msgstr "" + +#: part/models.py:680 +msgid "Can this part be purchased from external suppliers?" +msgstr "" + +#: part/models.py:685 +msgid "Can this part be sold to customers?" +msgstr "" + +#: part/models.py:689 part/templates/part/detail.html:215 +#: templates/js/table_filters.js:19 templates/js/table_filters.js:55 +#: templates/js/table_filters.js:186 templates/js/table_filters.js:243 +msgid "Active" +msgstr "" + +#: part/models.py:690 +msgid "Is this part active?" +msgstr "" + +#: part/models.py:694 part/templates/part/detail.html:138 +#: templates/js/table_filters.js:27 +msgid "Virtual" +msgstr "" + +#: part/models.py:695 +msgid "Is this a virtual part, such as a software product or license?" +msgstr "" + +#: part/models.py:697 +msgid "Part notes - supports Markdown formatting" +msgstr "" + +#: part/models.py:699 msgid "Stored BOM checksum" msgstr "" -#: part/models.py:1455 +#: part/models.py:1505 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:1472 +#: part/models.py:1522 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:1491 templates/js/part.js:567 templates/js/stock.js:92 +#: part/models.py:1541 templates/js/part.js:567 templates/js/stock.js:92 msgid "Test Name" msgstr "" -#: part/models.py:1492 +#: part/models.py:1542 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1497 +#: part/models.py:1547 msgid "Test Description" msgstr "" -#: part/models.py:1498 +#: part/models.py:1548 msgid "Enter description for this test" msgstr "" -#: part/models.py:1503 templates/js/part.js:576 +#: part/models.py:1553 templates/js/part.js:576 #: templates/js/table_filters.js:172 msgid "Required" msgstr "" -#: part/models.py:1504 +#: part/models.py:1554 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:1509 templates/js/part.js:584 +#: part/models.py:1559 templates/js/part.js:584 msgid "Requires Value" msgstr "" -#: part/models.py:1510 +#: part/models.py:1560 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:1515 templates/js/part.js:591 +#: part/models.py:1565 templates/js/part.js:591 msgid "Requires Attachment" msgstr "" -#: part/models.py:1516 +#: part/models.py:1566 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:1549 +#: part/models.py:1599 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:1554 +#: part/models.py:1604 msgid "Parameter Name" msgstr "" -#: part/models.py:1556 +#: part/models.py:1606 msgid "Parameter Units" msgstr "" -#: part/models.py:1584 +#: part/models.py:1634 msgid "Parameter Template" msgstr "" -#: part/models.py:1586 +#: part/models.py:1636 msgid "Parameter Value" msgstr "" -#: part/models.py:1623 +#: part/models.py:1673 msgid "Select parent part" msgstr "" -#: part/models.py:1631 +#: part/models.py:1681 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:1637 +#: part/models.py:1687 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:1639 +#: part/models.py:1689 msgid "This BOM item is optional" msgstr "" -#: part/models.py:1642 +#: part/models.py:1692 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:1645 +#: part/models.py:1695 msgid "BOM item reference" msgstr "" -#: part/models.py:1648 +#: part/models.py:1698 msgid "BOM item notes" msgstr "" -#: part/models.py:1650 +#: part/models.py:1700 msgid "BOM line checksum" msgstr "" -#: part/models.py:1717 part/views.py:1415 part/views.py:1467 +#: part/models.py:1767 part/views.py:1483 part/views.py:1535 #: stock/models.py:233 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:1733 +#: part/models.py:1783 msgid "BOM Item" msgstr "" +#: part/models.py:1898 +msgid "Select Related Part" +msgstr "" + +#: part/models.py:1930 +msgid "" +"Error creating relationship: check that the part is not related to itself " +"and that the relationship is unique" +msgstr "" + #: part/templates/part/allocation.html:10 msgid "Part Stock Allocations" msgstr "" @@ -2648,7 +2717,7 @@ msgstr "" msgid "Validate" msgstr "" -#: part/templates/part/bom.html:62 part/views.py:1706 +#: part/templates/part/bom.html:62 part/views.py:1774 msgid "Export Bill of Materials" msgstr "" @@ -2744,7 +2813,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:24 part/views.py:2109 +#: part/templates/part/category.html:24 part/views.py:2177 msgid "Create new part category" msgstr "" @@ -2890,10 +2959,6 @@ msgstr "" msgid "Responsible User" msgstr "" -#: part/templates/part/detail.html:138 templates/js/table_filters.js:27 -msgid "Virtual" -msgstr "" - #: part/templates/part/detail.html:141 msgid "Part is virtual (not a physical part)" msgstr "" @@ -2915,10 +2980,6 @@ msgstr "" msgid "Part is not a template part" msgstr "" -#: part/templates/part/detail.html:158 templates/js/table_filters.js:260 -msgid "Assembly" -msgstr "" - #: part/templates/part/detail.html:161 msgid "Part can be assembled from other parts" msgstr "" @@ -2927,10 +2988,6 @@ msgstr "" msgid "Part cannot be assembled from other parts" msgstr "" -#: part/templates/part/detail.html:168 templates/js/table_filters.js:264 -msgid "Component" -msgstr "" - #: part/templates/part/detail.html:171 msgid "Part can be used in assemblies" msgstr "" @@ -2939,11 +2996,6 @@ msgstr "" msgid "Part cannot be used in assemblies" msgstr "" -#: part/templates/part/detail.html:178 templates/js/table_filters.js:31 -#: templates/js/table_filters.js:276 -msgid "Trackable" -msgstr "" - #: part/templates/part/detail.html:181 msgid "Part stock is tracked by serial number" msgstr "" @@ -2952,18 +3004,10 @@ msgstr "" msgid "Part stock is not tracked by serial number" msgstr "" -#: part/templates/part/detail.html:188 -msgid "Purchaseable" -msgstr "" - #: part/templates/part/detail.html:191 part/templates/part/detail.html:193 msgid "Part can be purchased from external suppliers" msgstr "" -#: part/templates/part/detail.html:198 templates/js/table_filters.js:272 -msgid "Salable" -msgstr "" - #: part/templates/part/detail.html:201 msgid "Part can be sold to customers" msgstr "" @@ -2972,17 +3016,11 @@ msgstr "" msgid "Part cannot be sold to customers" msgstr "" -#: part/templates/part/detail.html:214 templates/js/table_filters.js:19 -#: templates/js/table_filters.js:55 templates/js/table_filters.js:186 -#: templates/js/table_filters.js:243 -msgid "Active" -msgstr "" - -#: part/templates/part/detail.html:217 +#: part/templates/part/detail.html:218 msgid "Part is active" msgstr "" -#: part/templates/part/detail.html:219 +#: part/templates/part/detail.html:220 msgid "Part is not active" msgstr "" @@ -2998,7 +3036,7 @@ msgstr "" msgid "Add new parameter" msgstr "" -#: part/templates/part/params.html:15 templates/InvenTree/settings/part.html:28 +#: part/templates/part/params.html:15 templates/InvenTree/settings/part.html:35 msgid "New Parameter" msgstr "" @@ -3007,8 +3045,8 @@ msgstr "" msgid "Value" msgstr "" -#: part/templates/part/params.html:41 part/templates/part/supplier.html:19 -#: users/models.py:146 +#: part/templates/part/params.html:41 part/templates/part/related.html:41 +#: part/templates/part/supplier.html:19 users/models.py:147 msgid "Delete" msgstr "" @@ -3115,6 +3153,14 @@ msgstr "" msgid "Upload new image" msgstr "" +#: part/templates/part/related.html:9 +msgid "Related Parts" +msgstr "" + +#: part/templates/part/related.html:15 +msgid "Add Related" +msgstr "" + #: part/templates/part/sale_prices.html:9 part/templates/part/tabs.html:53 msgid "Sale Price" msgstr "" @@ -3184,6 +3230,10 @@ msgstr "" msgid "Tests" msgstr "" +#: part/templates/part/tabs.html:67 +msgid "Related" +msgstr "" + #: part/templates/part/track.html:8 msgid "Part Tracking" msgstr "" @@ -3205,199 +3255,207 @@ msgid "New Variant" msgstr "" #: part/views.py:80 +msgid "Add Related Part" +msgstr "" + +#: part/views.py:136 +msgid "Delete Related Part" +msgstr "" + +#: part/views.py:148 msgid "Add part attachment" msgstr "" -#: part/views.py:135 templates/attachment_table.html:34 +#: part/views.py:203 templates/attachment_table.html:34 msgid "Edit attachment" msgstr "" -#: part/views.py:141 +#: part/views.py:209 msgid "Part attachment updated" msgstr "" -#: part/views.py:156 +#: part/views.py:224 msgid "Delete Part Attachment" msgstr "" -#: part/views.py:164 +#: part/views.py:232 msgid "Deleted part attachment" msgstr "" -#: part/views.py:173 +#: part/views.py:241 msgid "Create Test Template" msgstr "" -#: part/views.py:202 +#: part/views.py:270 msgid "Edit Test Template" msgstr "" -#: part/views.py:218 +#: part/views.py:286 msgid "Delete Test Template" msgstr "" -#: part/views.py:227 +#: part/views.py:295 msgid "Set Part Category" msgstr "" -#: part/views.py:277 +#: part/views.py:345 #, python-brace-format msgid "Set category for {n} parts" msgstr "" -#: part/views.py:312 +#: part/views.py:380 msgid "Create Variant" msgstr "" -#: part/views.py:394 +#: part/views.py:462 msgid "Duplicate Part" msgstr "" -#: part/views.py:401 +#: part/views.py:469 msgid "Copied part" msgstr "" -#: part/views.py:455 part/views.py:585 +#: part/views.py:523 part/views.py:653 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:520 templates/js/stock.js:840 +#: part/views.py:588 templates/js/stock.js:840 msgid "Create New Part" msgstr "" -#: part/views.py:527 +#: part/views.py:595 msgid "Created new part" msgstr "" -#: part/views.py:743 +#: part/views.py:811 msgid "Part QR Code" msgstr "" -#: part/views.py:762 +#: part/views.py:830 msgid "Upload Part Image" msgstr "" -#: part/views.py:770 part/views.py:807 +#: part/views.py:838 part/views.py:875 msgid "Updated part image" msgstr "" -#: part/views.py:779 +#: part/views.py:847 msgid "Select Part Image" msgstr "" -#: part/views.py:810 +#: part/views.py:878 msgid "Part image not found" msgstr "" -#: part/views.py:821 +#: part/views.py:889 msgid "Edit Part Properties" msgstr "" -#: part/views.py:848 +#: part/views.py:916 msgid "Duplicate BOM" msgstr "" -#: part/views.py:879 +#: part/views.py:947 msgid "Confirm duplication of BOM from parent" msgstr "" -#: part/views.py:900 +#: part/views.py:968 msgid "Validate BOM" msgstr "" -#: part/views.py:923 +#: part/views.py:991 msgid "Confirm that the BOM is valid" msgstr "" -#: part/views.py:934 +#: part/views.py:1002 msgid "Validated Bill of Materials" msgstr "" -#: part/views.py:1068 +#: part/views.py:1136 msgid "No BOM file provided" msgstr "" -#: part/views.py:1418 +#: part/views.py:1486 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1443 part/views.py:1446 +#: part/views.py:1511 part/views.py:1514 msgid "Select valid part" msgstr "" -#: part/views.py:1452 +#: part/views.py:1520 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1490 +#: part/views.py:1558 msgid "Select a part" msgstr "" -#: part/views.py:1496 +#: part/views.py:1564 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1500 +#: part/views.py:1568 msgid "Specify quantity" msgstr "" -#: part/views.py:1756 +#: part/views.py:1824 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1765 +#: part/views.py:1833 msgid "Part was deleted" msgstr "" -#: part/views.py:1774 +#: part/views.py:1842 msgid "Part Pricing" msgstr "" -#: part/views.py:1900 +#: part/views.py:1968 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:1910 +#: part/views.py:1978 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:1919 +#: part/views.py:1987 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:1929 +#: part/views.py:1997 msgid "Create Part Parameter" msgstr "" -#: part/views.py:1981 +#: part/views.py:2049 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:1997 +#: part/views.py:2065 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2056 +#: part/views.py:2124 msgid "Edit Part Category" msgstr "" -#: part/views.py:2093 +#: part/views.py:2161 msgid "Delete Part Category" msgstr "" -#: part/views.py:2101 +#: part/views.py:2169 msgid "Part category was deleted" msgstr "" -#: part/views.py:2164 +#: part/views.py:2232 msgid "Create BOM Item" msgstr "" -#: part/views.py:2232 +#: part/views.py:2300 msgid "Edit BOM item" msgstr "" -#: part/views.py:2282 +#: part/views.py:2350 msgid "Confim BOM item deletion" msgstr "" @@ -4198,48 +4256,48 @@ msgstr "" msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1553 +#: stock/views.py:1555 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1619 +#: stock/views.py:1621 msgid "Invalid quantity" msgstr "" -#: stock/views.py:1622 +#: stock/views.py:1624 msgid "Quantity cannot be less than zero" msgstr "" -#: stock/views.py:1626 +#: stock/views.py:1628 msgid "Invalid part selection" msgstr "" -#: stock/views.py:1674 +#: stock/views.py:1676 #, python-brace-format msgid "Created {n} new stock items" msgstr "" -#: stock/views.py:1693 stock/views.py:1709 +#: stock/views.py:1695 stock/views.py:1711 msgid "Created new stock item" msgstr "" -#: stock/views.py:1728 +#: stock/views.py:1730 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1742 +#: stock/views.py:1744 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1754 +#: stock/views.py:1756 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1773 +#: stock/views.py:1775 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1783 +#: stock/views.py:1785 msgid "Add Stock Tracking Entry" msgstr "" @@ -4331,19 +4389,23 @@ msgstr "" msgid "Part Settings" msgstr "" -#: templates/InvenTree/settings/part.html:24 +#: templates/InvenTree/settings/part.html:14 +msgid "Part Options" +msgstr "" + +#: templates/InvenTree/settings/part.html:31 msgid "Part Parameter Templates" msgstr "" -#: templates/InvenTree/settings/part.html:45 +#: templates/InvenTree/settings/part.html:52 msgid "No part parameter templates found" msgstr "" -#: templates/InvenTree/settings/part.html:65 +#: templates/InvenTree/settings/part.html:72 msgid "Edit Template" msgstr "" -#: templates/InvenTree/settings/part.html:66 +#: templates/InvenTree/settings/part.html:73 msgid "Delete Template" msgstr "" @@ -5102,58 +5164,62 @@ msgstr "" msgid "Delete Stock" msgstr "" -#: users/admin.py:61 +#: users/admin.py:62 msgid "Users" msgstr "" -#: users/admin.py:62 +#: users/admin.py:63 msgid "Select which users are assigned to this group" msgstr "" #: users/admin.py:120 +msgid "The following users are members of multiple groups:" +msgstr "" + +#: users/admin.py:143 msgid "Personal info" msgstr "" -#: users/admin.py:121 +#: users/admin.py:144 msgid "Permissions" msgstr "" -#: users/admin.py:124 +#: users/admin.py:147 msgid "Important dates" msgstr "" -#: users/models.py:129 +#: users/models.py:130 msgid "Permission set" msgstr "" -#: users/models.py:137 +#: users/models.py:138 msgid "Group" msgstr "" -#: users/models.py:140 +#: users/models.py:141 msgid "View" msgstr "" -#: users/models.py:140 +#: users/models.py:141 msgid "Permission to view items" msgstr "" -#: users/models.py:142 +#: users/models.py:143 msgid "Add" msgstr "" -#: users/models.py:142 +#: users/models.py:143 msgid "Permission to add items" msgstr "" -#: users/models.py:144 +#: users/models.py:145 msgid "Change" msgstr "" -#: users/models.py:144 +#: users/models.py:145 msgid "Permissions to edit items" msgstr "" -#: users/models.py:146 +#: users/models.py:147 msgid "Permission to delete items" msgstr "" diff --git a/InvenTree/locale/es/LC_MESSAGES/django.po b/InvenTree/locale/es/LC_MESSAGES/django.po index aacb4b74ec..c4c14849c2 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-11-03 10:02+0000\n" +"POT-Creation-Date: 2020-11-09 12:47+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -26,23 +26,23 @@ msgstr "" msgid "No matching action found" msgstr "" -#: InvenTree/forms.py:102 build/forms.py:82 build/forms.py:170 +#: InvenTree/forms.py:130 build/forms.py:82 build/forms.py:170 msgid "Confirm" msgstr "" -#: InvenTree/forms.py:118 +#: InvenTree/forms.py:146 msgid "Confirm item deletion" msgstr "" -#: InvenTree/forms.py:150 +#: InvenTree/forms.py:178 msgid "Enter new password" msgstr "" -#: InvenTree/forms.py:157 +#: InvenTree/forms.py:185 msgid "Confirm new password" msgstr "" -#: InvenTree/forms.py:192 +#: InvenTree/forms.py:220 msgid "Apply Theme" msgstr "" @@ -396,8 +396,8 @@ msgstr "" #: build/templates/build/detail.html:24 order/models.py:519 #: order/templates/order/order_wizard/select_parts.html:30 #: order/templates/order/purchase_order_detail.html:148 -#: order/templates/order/receive_parts.html:19 part/models.py:293 -#: part/templates/part/part_app_base.html:7 +#: order/templates/order/receive_parts.html:19 part/models.py:294 +#: part/templates/part/part_app_base.html:7 part/templates/part/related.html:26 #: part/templates/part/set_category.html:13 templates/InvenTree/search.html:133 #: templates/js/barcode.js:336 templates/js/bom.js:147 templates/js/bom.js:484 #: templates/js/build.js:647 templates/js/company.js:138 @@ -476,14 +476,14 @@ msgstr "" msgid "External Link" msgstr "" -#: build/models.py:177 part/models.py:596 stock/models.py:385 +#: build/models.py:177 part/models.py:597 stock/models.py:385 msgid "Link to external URL" msgstr "" -#: build/models.py:181 build/templates/build/tabs.html:14 company/models.py:314 +#: build/models.py:181 build/templates/build/tabs.html:23 company/models.py:314 #: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:18 #: order/templates/order/purchase_order_detail.html:203 -#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:70 +#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:73 #: stock/forms.py:306 stock/forms.py:338 stock/forms.py:366 stock/models.py:455 #: stock/models.py:1428 stock/templates/stock/tabs.html:26 #: templates/js/barcode.js:391 templates/js/bom.js:250 @@ -495,65 +495,65 @@ msgstr "" msgid "Extra build notes" msgstr "" -#: build/models.py:543 +#: build/models.py:551 msgid "No build output specified" msgstr "" -#: build/models.py:546 +#: build/models.py:554 msgid "Build output is already completed" msgstr "" -#: build/models.py:549 +#: build/models.py:557 msgid "Build output does not match Build Order" msgstr "" -#: build/models.py:620 +#: build/models.py:632 msgid "Completed build output" msgstr "" -#: build/models.py:858 +#: build/models.py:870 msgid "BuildItem must be unique for build, stock_item and install_into" msgstr "" -#: build/models.py:880 +#: build/models.py:892 msgid "Build item must specify a build output" msgstr "" -#: build/models.py:885 +#: build/models.py:897 #, python-brace-format msgid "Selected stock item not found in BOM for part '{p}'" msgstr "" -#: build/models.py:889 +#: build/models.py:901 #, python-brace-format msgid "Allocated quantity ({n}) must not exceed available quantity ({q})" msgstr "" -#: build/models.py:896 order/models.py:603 +#: build/models.py:908 order/models.py:603 msgid "StockItem is over-allocated" msgstr "" -#: build/models.py:900 order/models.py:606 +#: build/models.py:912 order/models.py:606 msgid "Allocation quantity must be greater than zero" msgstr "" -#: build/models.py:904 +#: build/models.py:916 msgid "Quantity must be 1 for serialized stock" msgstr "" -#: build/models.py:944 +#: build/models.py:956 msgid "Build to allocate parts" msgstr "" -#: build/models.py:951 +#: build/models.py:963 msgid "Source stock item" msgstr "" -#: build/models.py:964 +#: build/models.py:976 msgid "Stock quantity to allocate to build" msgstr "" -#: build/models.py:972 +#: build/models.py:984 msgid "Destination stock item" msgstr "" @@ -565,47 +565,47 @@ msgstr "" msgid "Build order has been completed" msgstr "" -#: build/templates/build/allocate.html:24 +#: build/templates/build/allocate.html:25 msgid "Create new build output" msgstr "" -#: build/templates/build/allocate.html:25 +#: build/templates/build/allocate.html:26 msgid "Create New Output" msgstr "" -#: build/templates/build/allocate.html:28 +#: build/templates/build/allocate.html:29 msgid "Order required parts" msgstr "" -#: build/templates/build/allocate.html:29 -#: company/templates/company/detail_part.html:28 order/views.py:801 +#: build/templates/build/allocate.html:30 +#: company/templates/company/detail_part.html:28 order/views.py:803 #: part/templates/part/category.html:125 msgid "Order Parts" msgstr "" -#: build/templates/build/allocate.html:32 templates/js/build.js:574 +#: build/templates/build/allocate.html:33 templates/js/build.js:574 msgid "Unallocate stock" msgstr "" -#: build/templates/build/allocate.html:33 build/views.py:341 build/views.py:778 +#: build/templates/build/allocate.html:34 build/views.py:341 build/views.py:778 msgid "Unallocate Stock" msgstr "" -#: build/templates/build/allocate.html:46 +#: build/templates/build/allocate.html:48 msgid "Create a new build output" msgstr "" -#: build/templates/build/allocate.html:47 +#: build/templates/build/allocate.html:49 msgid "No incomplete build outputs remain." msgstr "" -#: build/templates/build/allocate.html:48 +#: build/templates/build/allocate.html:50 msgid "Create a new build output using the button above" msgstr "" -#: build/templates/build/attachments.html:11 build/templates/build/tabs.html:17 +#: build/templates/build/attachments.html:11 build/templates/build/tabs.html:29 #: order/templates/order/po_tabs.html:11 order/templates/order/so_tabs.html:16 -#: part/templates/part/tabs.html:67 stock/templates/stock/tabs.html:32 +#: part/templates/part/tabs.html:70 stock/templates/stock/tabs.html:32 msgid "Attachments" msgstr "" @@ -698,7 +698,7 @@ msgstr "" msgid "Sales Order" msgstr "" -#: build/templates/build/build_output.html:9 build/templates/build/tabs.html:11 +#: build/templates/build/build_output.html:9 build/templates/build/tabs.html:17 msgid "Build Outputs" msgstr "" @@ -855,8 +855,8 @@ msgstr "" msgid "Details" msgstr "" -#: build/templates/build/tabs.html:8 -msgid "Allocate Parts" +#: build/templates/build/tabs.html:10 +msgid "Incomplete" msgstr "" #: build/templates/build/unallocate.html:10 @@ -887,7 +887,7 @@ msgstr "" msgid "Create Build Output" msgstr "" -#: build/views.py:207 stock/models.py:832 stock/views.py:1645 +#: build/views.py:207 stock/models.py:832 stock/views.py:1647 msgid "Serial numbers already exist" msgstr "" @@ -992,7 +992,7 @@ msgstr "" msgid "Add Build Order Attachment" msgstr "" -#: build/views.py:1059 order/views.py:111 order/views.py:164 part/views.py:96 +#: build/views.py:1059 order/views.py:111 order/views.py:164 part/views.py:164 #: stock/views.py:176 msgid "Added attachment" msgstr "" @@ -1061,75 +1061,110 @@ msgstr "" msgid "Copy test data by default when duplicating a part" msgstr "" -#: common/models.py:89 -msgid "Build Order Reference Prefix" +#: common/models.py:89 part/models.py:668 part/templates/part/detail.html:168 +#: templates/js/table_filters.js:264 +msgid "Component" msgstr "" #: common/models.py:90 +msgid "Parts can be used as sub-components by default" +msgstr "" + +#: common/models.py:96 part/models.py:679 part/templates/part/detail.html:188 +msgid "Purchaseable" +msgstr "" + +#: common/models.py:97 +msgid "Parts are purchaseable by default" +msgstr "" + +#: common/models.py:103 part/models.py:684 part/templates/part/detail.html:198 +#: templates/js/table_filters.js:272 +msgid "Salable" +msgstr "" + +#: common/models.py:104 +msgid "Parts are salable by default" +msgstr "" + +#: common/models.py:110 part/models.py:674 part/templates/part/detail.html:178 +#: templates/js/table_filters.js:31 templates/js/table_filters.js:276 +msgid "Trackable" +msgstr "" + +#: common/models.py:111 +msgid "Parts are trackable by default" +msgstr "" + +#: common/models.py:117 +msgid "Build Order Reference Prefix" +msgstr "" + +#: common/models.py:118 msgid "Prefix value for build order reference" msgstr "" -#: common/models.py:95 +#: common/models.py:123 msgid "Build Order Reference Regex" msgstr "" -#: common/models.py:96 +#: common/models.py:124 msgid "Regular expression pattern for matching build order reference" msgstr "" -#: common/models.py:100 +#: common/models.py:128 msgid "Sales Order Reference Prefix" msgstr "" -#: common/models.py:101 +#: common/models.py:129 msgid "Prefix value for sales order reference" msgstr "" -#: common/models.py:105 +#: common/models.py:133 msgid "Purchase Order Reference Prefix" msgstr "" -#: common/models.py:106 +#: common/models.py:134 msgid "Prefix value for purchase order reference" msgstr "" -#: common/models.py:277 +#: common/models.py:312 msgid "Settings key (must be unique - case insensitive" msgstr "" -#: common/models.py:279 +#: common/models.py:314 msgid "Settings value" msgstr "" -#: common/models.py:331 +#: common/models.py:366 msgid "Value must be a boolean value" msgstr "" -#: common/models.py:345 +#: common/models.py:380 msgid "Key string must be unique" msgstr "" -#: common/models.py:384 +#: common/models.py:419 msgid "Currency Symbol e.g. $" msgstr "" -#: common/models.py:386 +#: common/models.py:421 msgid "Currency Suffix e.g. AUD" msgstr "" -#: common/models.py:388 +#: common/models.py:423 msgid "Currency Description" msgstr "" -#: common/models.py:390 +#: common/models.py:425 msgid "Currency Value" msgstr "" -#: common/models.py:392 +#: common/models.py:427 msgid "Use this currency as the base currency" msgstr "" -#: common/models.py:475 +#: common/models.py:510 msgid "Default" msgstr "" @@ -1487,7 +1522,7 @@ msgid "Pricing Information" msgstr "" #: company/templates/company/supplier_part_pricing.html:17 company/views.py:410 -#: part/templates/part/sale_prices.html:13 part/views.py:2292 +#: part/templates/part/sale_prices.html:13 part/views.py:2360 msgid "Add Price Break" msgstr "" @@ -1533,7 +1568,7 @@ msgid "Orders" msgstr "" #: company/templates/company/tabs.html:9 -#: order/templates/order/receive_parts.html:14 part/models.py:294 +#: order/templates/order/receive_parts.html:14 part/models.py:295 #: part/templates/part/cat_link.html:7 part/templates/part/category.html:94 #: part/templates/part/category_tabs.html:6 #: templates/InvenTree/settings/tabs.html:22 templates/navbar.html:19 @@ -1614,15 +1649,15 @@ msgstr "" msgid "Delete Supplier Part" msgstr "" -#: company/views.py:416 part/views.py:2298 +#: company/views.py:416 part/views.py:2366 msgid "Added new price break" msgstr "" -#: company/views.py:453 part/views.py:2343 +#: company/views.py:453 part/views.py:2411 msgid "Edit Price Break" msgstr "" -#: company/views.py:469 part/views.py:2359 +#: company/views.py:469 part/views.py:2427 msgid "Delete Price Break" msgstr "" @@ -1715,7 +1750,7 @@ msgstr "" msgid "Date order was completed" msgstr "" -#: order/models.py:185 order/models.py:267 part/views.py:1409 +#: order/models.py:185 order/models.py:267 part/views.py:1477 #: stock/models.py:243 stock/models.py:816 msgid "Quantity must be greater than zero" msgstr "" @@ -1904,8 +1939,8 @@ msgid "Line Items" msgstr "" #: order/templates/order/purchase_order_detail.html:17 -#: order/templates/order/sales_order_detail.html:19 order/views.py:1115 -#: order/views.py:1199 +#: order/templates/order/sales_order_detail.html:19 order/views.py:1117 +#: order/views.py:1201 msgid "Add Line Item" msgstr "" @@ -2088,123 +2123,127 @@ msgstr "" msgid "Create Purchase Order" msgstr "" -#: order/views.py:345 +#: order/views.py:346 msgid "Create Sales Order" msgstr "" -#: order/views.py:380 +#: order/views.py:382 msgid "Edit Purchase Order" msgstr "" -#: order/views.py:401 +#: order/views.py:403 msgid "Edit Sales Order" msgstr "" -#: order/views.py:418 +#: order/views.py:420 msgid "Cancel Order" msgstr "" -#: order/views.py:428 order/views.py:455 +#: order/views.py:430 order/views.py:457 msgid "Confirm order cancellation" msgstr "" -#: order/views.py:431 order/views.py:458 -msgid "Order cannot be cancelled" +#: order/views.py:433 +msgid "Order cannot be cancelled as either pending or placed" msgstr "" -#: order/views.py:445 +#: order/views.py:447 msgid "Cancel sales order" msgstr "" -#: order/views.py:472 +#: order/views.py:460 +msgid "Order cannot be cancelled" +msgstr "" + +#: order/views.py:474 msgid "Issue Order" msgstr "" -#: order/views.py:482 +#: order/views.py:484 msgid "Confirm order placement" msgstr "" -#: order/views.py:492 +#: order/views.py:494 msgid "Purchase order issued" msgstr "" -#: order/views.py:503 +#: order/views.py:505 msgid "Complete Order" msgstr "" -#: order/views.py:520 +#: order/views.py:522 msgid "Confirm order completion" msgstr "" -#: order/views.py:531 +#: order/views.py:533 msgid "Purchase order completed" msgstr "" -#: order/views.py:541 +#: order/views.py:543 msgid "Ship Order" msgstr "" -#: order/views.py:558 +#: order/views.py:560 msgid "Confirm order shipment" msgstr "" -#: order/views.py:564 +#: order/views.py:566 msgid "Could not ship order" msgstr "" -#: order/views.py:616 +#: order/views.py:618 msgid "Receive Parts" msgstr "" -#: order/views.py:684 +#: order/views.py:686 msgid "Items received" msgstr "" -#: order/views.py:698 +#: order/views.py:700 msgid "No destination set" msgstr "" -#: order/views.py:743 +#: order/views.py:745 msgid "Error converting quantity to number" msgstr "" -#: order/views.py:749 +#: order/views.py:751 msgid "Receive quantity less than zero" msgstr "" -#: order/views.py:755 +#: order/views.py:757 msgid "No lines specified" msgstr "" -#: order/views.py:1125 +#: order/views.py:1127 msgid "Supplier part must be specified" msgstr "" -#: order/views.py:1131 +#: order/views.py:1133 msgid "Supplier must match for Part and Order" msgstr "" -#: order/views.py:1251 order/views.py:1270 +#: order/views.py:1253 order/views.py:1272 msgid "Edit Line Item" msgstr "" -#: order/views.py:1287 order/views.py:1300 +#: order/views.py:1289 order/views.py:1302 msgid "Delete Line Item" msgstr "" -#: order/views.py:1293 order/views.py:1306 +#: order/views.py:1295 order/views.py:1308 msgid "Deleted line item" msgstr "" -#: order/views.py:1315 +#: order/views.py:1317 msgid "Allocate Stock to Order" msgstr "" -#: order/views.py:1385 +#: order/views.py:1387 msgid "Edit Allocation Quantity" msgstr "" -#: order/views.py:1401 +#: order/views.py:1403 msgid "Remove allocation" msgstr "" @@ -2278,7 +2317,7 @@ msgstr "" msgid "Include part supplier data in exported BOM" msgstr "" -#: part/forms.py:93 part/models.py:1582 +#: part/forms.py:93 part/models.py:1632 msgid "Parent Part" msgstr "" @@ -2302,270 +2341,300 @@ msgstr "" msgid "Select BOM file to upload" msgstr "" -#: part/forms.py:159 -msgid "Select part category" +#: part/forms.py:154 +msgid "Related Part" msgstr "" #: part/forms.py:173 +msgid "Select part category" +msgstr "" + +#: part/forms.py:189 msgid "Duplicate all BOM data for this part" msgstr "" -#: part/forms.py:174 +#: part/forms.py:190 msgid "Copy BOM" msgstr "" -#: part/forms.py:179 +#: part/forms.py:195 msgid "Duplicate all parameter data for this part" msgstr "" -#: part/forms.py:180 +#: part/forms.py:196 msgid "Copy Parameters" msgstr "" -#: part/forms.py:185 +#: part/forms.py:201 msgid "Confirm part creation" msgstr "" -#: part/forms.py:279 +#: part/forms.py:298 msgid "Input quantity for price calculation" msgstr "" -#: part/forms.py:282 +#: part/forms.py:301 msgid "Select currency for price calculation" msgstr "" -#: part/models.py:66 +#: part/models.py:67 msgid "Default location for parts in this category" msgstr "" -#: part/models.py:69 +#: part/models.py:70 msgid "Default keywords for parts in this category" msgstr "" -#: part/models.py:75 part/templates/part/part_app_base.html:9 +#: part/models.py:76 part/templates/part/part_app_base.html:9 msgid "Part Category" msgstr "" -#: part/models.py:76 part/templates/part/category.html:18 +#: part/models.py:77 part/templates/part/category.html:18 #: part/templates/part/category.html:89 templates/stats.html:12 msgid "Part Categories" msgstr "" -#: part/models.py:345 part/models.py:355 +#: part/models.py:346 part/models.py:356 #, python-brace-format msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgstr "" -#: part/models.py:452 +#: part/models.py:453 msgid "Next available serial numbers are" msgstr "" -#: part/models.py:456 +#: part/models.py:457 msgid "Next available serial number is" msgstr "" -#: part/models.py:461 +#: part/models.py:462 msgid "Most recent serial number is" msgstr "" -#: part/models.py:539 +#: part/models.py:540 msgid "Part must be unique for name, IPN and revision" msgstr "" -#: part/models.py:568 part/templates/part/detail.html:19 +#: part/models.py:569 part/templates/part/detail.html:19 msgid "Part name" msgstr "" -#: part/models.py:572 +#: part/models.py:573 msgid "Is this part a template part?" msgstr "" -#: part/models.py:581 +#: part/models.py:582 msgid "Is this part a variant of another part?" msgstr "" -#: part/models.py:583 +#: part/models.py:584 msgid "Part description" msgstr "" -#: part/models.py:585 +#: part/models.py:586 msgid "Part keywords to improve visibility in search results" msgstr "" -#: part/models.py:590 +#: part/models.py:591 msgid "Part category" msgstr "" -#: part/models.py:592 +#: part/models.py:593 msgid "Internal Part Number" msgstr "" -#: part/models.py:594 +#: part/models.py:595 msgid "Part revision or version number" msgstr "" -#: part/models.py:608 +#: part/models.py:609 msgid "Where is this item normally stored?" msgstr "" -#: part/models.py:652 +#: part/models.py:653 msgid "Default supplier part" msgstr "" -#: part/models.py:655 +#: part/models.py:656 msgid "Minimum allowed stock level" msgstr "" -#: part/models.py:657 +#: part/models.py:658 msgid "Stock keeping units for this part" msgstr "" -#: part/models.py:659 -msgid "Can this part be built from other parts?" -msgstr "" - -#: part/models.py:661 -msgid "Can this part be used to build other parts?" +#: part/models.py:662 part/templates/part/detail.html:158 +#: templates/js/table_filters.js:260 +msgid "Assembly" msgstr "" #: part/models.py:663 -msgid "Does this part have tracking for unique items?" -msgstr "" - -#: part/models.py:665 -msgid "Can this part be purchased from external suppliers?" -msgstr "" - -#: part/models.py:667 -msgid "Can this part be sold to customers?" +msgid "Can this part be built from other parts?" msgstr "" #: part/models.py:669 -msgid "Is this part active?" -msgstr "" - -#: part/models.py:671 -msgid "Is this a virtual part, such as a software product or license?" -msgstr "" - -#: part/models.py:673 -msgid "Part notes - supports Markdown formatting" +msgid "Can this part be used to build other parts?" msgstr "" #: part/models.py:675 +msgid "Does this part have tracking for unique items?" +msgstr "" + +#: part/models.py:680 +msgid "Can this part be purchased from external suppliers?" +msgstr "" + +#: part/models.py:685 +msgid "Can this part be sold to customers?" +msgstr "" + +#: part/models.py:689 part/templates/part/detail.html:215 +#: templates/js/table_filters.js:19 templates/js/table_filters.js:55 +#: templates/js/table_filters.js:186 templates/js/table_filters.js:243 +msgid "Active" +msgstr "" + +#: part/models.py:690 +msgid "Is this part active?" +msgstr "" + +#: part/models.py:694 part/templates/part/detail.html:138 +#: templates/js/table_filters.js:27 +msgid "Virtual" +msgstr "" + +#: part/models.py:695 +msgid "Is this a virtual part, such as a software product or license?" +msgstr "" + +#: part/models.py:697 +msgid "Part notes - supports Markdown formatting" +msgstr "" + +#: part/models.py:699 msgid "Stored BOM checksum" msgstr "" -#: part/models.py:1455 +#: part/models.py:1505 msgid "Test templates can only be created for trackable parts" msgstr "" -#: part/models.py:1472 +#: part/models.py:1522 msgid "Test with this name already exists for this part" msgstr "" -#: part/models.py:1491 templates/js/part.js:567 templates/js/stock.js:92 +#: part/models.py:1541 templates/js/part.js:567 templates/js/stock.js:92 msgid "Test Name" msgstr "" -#: part/models.py:1492 +#: part/models.py:1542 msgid "Enter a name for the test" msgstr "" -#: part/models.py:1497 +#: part/models.py:1547 msgid "Test Description" msgstr "" -#: part/models.py:1498 +#: part/models.py:1548 msgid "Enter description for this test" msgstr "" -#: part/models.py:1503 templates/js/part.js:576 +#: part/models.py:1553 templates/js/part.js:576 #: templates/js/table_filters.js:172 msgid "Required" msgstr "" -#: part/models.py:1504 +#: part/models.py:1554 msgid "Is this test required to pass?" msgstr "" -#: part/models.py:1509 templates/js/part.js:584 +#: part/models.py:1559 templates/js/part.js:584 msgid "Requires Value" msgstr "" -#: part/models.py:1510 +#: part/models.py:1560 msgid "Does this test require a value when adding a test result?" msgstr "" -#: part/models.py:1515 templates/js/part.js:591 +#: part/models.py:1565 templates/js/part.js:591 msgid "Requires Attachment" msgstr "" -#: part/models.py:1516 +#: part/models.py:1566 msgid "Does this test require a file attachment when adding a test result?" msgstr "" -#: part/models.py:1549 +#: part/models.py:1599 msgid "Parameter template name must be unique" msgstr "" -#: part/models.py:1554 +#: part/models.py:1604 msgid "Parameter Name" msgstr "" -#: part/models.py:1556 +#: part/models.py:1606 msgid "Parameter Units" msgstr "" -#: part/models.py:1584 +#: part/models.py:1634 msgid "Parameter Template" msgstr "" -#: part/models.py:1586 +#: part/models.py:1636 msgid "Parameter Value" msgstr "" -#: part/models.py:1623 +#: part/models.py:1673 msgid "Select parent part" msgstr "" -#: part/models.py:1631 +#: part/models.py:1681 msgid "Select part to be used in BOM" msgstr "" -#: part/models.py:1637 +#: part/models.py:1687 msgid "BOM quantity for this BOM item" msgstr "" -#: part/models.py:1639 +#: part/models.py:1689 msgid "This BOM item is optional" msgstr "" -#: part/models.py:1642 +#: part/models.py:1692 msgid "Estimated build wastage quantity (absolute or percentage)" msgstr "" -#: part/models.py:1645 +#: part/models.py:1695 msgid "BOM item reference" msgstr "" -#: part/models.py:1648 +#: part/models.py:1698 msgid "BOM item notes" msgstr "" -#: part/models.py:1650 +#: part/models.py:1700 msgid "BOM line checksum" msgstr "" -#: part/models.py:1717 part/views.py:1415 part/views.py:1467 +#: part/models.py:1767 part/views.py:1483 part/views.py:1535 #: stock/models.py:233 msgid "Quantity must be integer value for trackable parts" msgstr "" -#: part/models.py:1733 +#: part/models.py:1783 msgid "BOM Item" msgstr "" +#: part/models.py:1898 +msgid "Select Related Part" +msgstr "" + +#: part/models.py:1930 +msgid "" +"Error creating relationship: check that the part is not related to itself " +"and that the relationship is unique" +msgstr "" + #: part/templates/part/allocation.html:10 msgid "Part Stock Allocations" msgstr "" @@ -2648,7 +2717,7 @@ msgstr "" msgid "Validate" msgstr "" -#: part/templates/part/bom.html:62 part/views.py:1706 +#: part/templates/part/bom.html:62 part/views.py:1774 msgid "Export Bill of Materials" msgstr "" @@ -2744,7 +2813,7 @@ msgstr "" msgid "All parts" msgstr "" -#: part/templates/part/category.html:24 part/views.py:2109 +#: part/templates/part/category.html:24 part/views.py:2177 msgid "Create new part category" msgstr "" @@ -2890,10 +2959,6 @@ msgstr "" msgid "Responsible User" msgstr "" -#: part/templates/part/detail.html:138 templates/js/table_filters.js:27 -msgid "Virtual" -msgstr "" - #: part/templates/part/detail.html:141 msgid "Part is virtual (not a physical part)" msgstr "" @@ -2915,10 +2980,6 @@ msgstr "" msgid "Part is not a template part" msgstr "" -#: part/templates/part/detail.html:158 templates/js/table_filters.js:260 -msgid "Assembly" -msgstr "" - #: part/templates/part/detail.html:161 msgid "Part can be assembled from other parts" msgstr "" @@ -2927,10 +2988,6 @@ msgstr "" msgid "Part cannot be assembled from other parts" msgstr "" -#: part/templates/part/detail.html:168 templates/js/table_filters.js:264 -msgid "Component" -msgstr "" - #: part/templates/part/detail.html:171 msgid "Part can be used in assemblies" msgstr "" @@ -2939,11 +2996,6 @@ msgstr "" msgid "Part cannot be used in assemblies" msgstr "" -#: part/templates/part/detail.html:178 templates/js/table_filters.js:31 -#: templates/js/table_filters.js:276 -msgid "Trackable" -msgstr "" - #: part/templates/part/detail.html:181 msgid "Part stock is tracked by serial number" msgstr "" @@ -2952,18 +3004,10 @@ msgstr "" msgid "Part stock is not tracked by serial number" msgstr "" -#: part/templates/part/detail.html:188 -msgid "Purchaseable" -msgstr "" - #: part/templates/part/detail.html:191 part/templates/part/detail.html:193 msgid "Part can be purchased from external suppliers" msgstr "" -#: part/templates/part/detail.html:198 templates/js/table_filters.js:272 -msgid "Salable" -msgstr "" - #: part/templates/part/detail.html:201 msgid "Part can be sold to customers" msgstr "" @@ -2972,17 +3016,11 @@ msgstr "" msgid "Part cannot be sold to customers" msgstr "" -#: part/templates/part/detail.html:214 templates/js/table_filters.js:19 -#: templates/js/table_filters.js:55 templates/js/table_filters.js:186 -#: templates/js/table_filters.js:243 -msgid "Active" -msgstr "" - -#: part/templates/part/detail.html:217 +#: part/templates/part/detail.html:218 msgid "Part is active" msgstr "" -#: part/templates/part/detail.html:219 +#: part/templates/part/detail.html:220 msgid "Part is not active" msgstr "" @@ -2998,7 +3036,7 @@ msgstr "" msgid "Add new parameter" msgstr "" -#: part/templates/part/params.html:15 templates/InvenTree/settings/part.html:28 +#: part/templates/part/params.html:15 templates/InvenTree/settings/part.html:35 msgid "New Parameter" msgstr "" @@ -3007,8 +3045,8 @@ msgstr "" msgid "Value" msgstr "" -#: part/templates/part/params.html:41 part/templates/part/supplier.html:19 -#: users/models.py:146 +#: part/templates/part/params.html:41 part/templates/part/related.html:41 +#: part/templates/part/supplier.html:19 users/models.py:147 msgid "Delete" msgstr "" @@ -3115,6 +3153,14 @@ msgstr "" msgid "Upload new image" msgstr "" +#: part/templates/part/related.html:9 +msgid "Related Parts" +msgstr "" + +#: part/templates/part/related.html:15 +msgid "Add Related" +msgstr "" + #: part/templates/part/sale_prices.html:9 part/templates/part/tabs.html:53 msgid "Sale Price" msgstr "" @@ -3184,6 +3230,10 @@ msgstr "" msgid "Tests" msgstr "" +#: part/templates/part/tabs.html:67 +msgid "Related" +msgstr "" + #: part/templates/part/track.html:8 msgid "Part Tracking" msgstr "" @@ -3205,199 +3255,207 @@ msgid "New Variant" msgstr "" #: part/views.py:80 +msgid "Add Related Part" +msgstr "" + +#: part/views.py:136 +msgid "Delete Related Part" +msgstr "" + +#: part/views.py:148 msgid "Add part attachment" msgstr "" -#: part/views.py:135 templates/attachment_table.html:34 +#: part/views.py:203 templates/attachment_table.html:34 msgid "Edit attachment" msgstr "" -#: part/views.py:141 +#: part/views.py:209 msgid "Part attachment updated" msgstr "" -#: part/views.py:156 +#: part/views.py:224 msgid "Delete Part Attachment" msgstr "" -#: part/views.py:164 +#: part/views.py:232 msgid "Deleted part attachment" msgstr "" -#: part/views.py:173 +#: part/views.py:241 msgid "Create Test Template" msgstr "" -#: part/views.py:202 +#: part/views.py:270 msgid "Edit Test Template" msgstr "" -#: part/views.py:218 +#: part/views.py:286 msgid "Delete Test Template" msgstr "" -#: part/views.py:227 +#: part/views.py:295 msgid "Set Part Category" msgstr "" -#: part/views.py:277 +#: part/views.py:345 #, python-brace-format msgid "Set category for {n} parts" msgstr "" -#: part/views.py:312 +#: part/views.py:380 msgid "Create Variant" msgstr "" -#: part/views.py:394 +#: part/views.py:462 msgid "Duplicate Part" msgstr "" -#: part/views.py:401 +#: part/views.py:469 msgid "Copied part" msgstr "" -#: part/views.py:455 part/views.py:585 +#: part/views.py:523 part/views.py:653 msgid "Possible matches exist - confirm creation of new part" msgstr "" -#: part/views.py:520 templates/js/stock.js:840 +#: part/views.py:588 templates/js/stock.js:840 msgid "Create New Part" msgstr "" -#: part/views.py:527 +#: part/views.py:595 msgid "Created new part" msgstr "" -#: part/views.py:743 +#: part/views.py:811 msgid "Part QR Code" msgstr "" -#: part/views.py:762 +#: part/views.py:830 msgid "Upload Part Image" msgstr "" -#: part/views.py:770 part/views.py:807 +#: part/views.py:838 part/views.py:875 msgid "Updated part image" msgstr "" -#: part/views.py:779 +#: part/views.py:847 msgid "Select Part Image" msgstr "" -#: part/views.py:810 +#: part/views.py:878 msgid "Part image not found" msgstr "" -#: part/views.py:821 +#: part/views.py:889 msgid "Edit Part Properties" msgstr "" -#: part/views.py:848 +#: part/views.py:916 msgid "Duplicate BOM" msgstr "" -#: part/views.py:879 +#: part/views.py:947 msgid "Confirm duplication of BOM from parent" msgstr "" -#: part/views.py:900 +#: part/views.py:968 msgid "Validate BOM" msgstr "" -#: part/views.py:923 +#: part/views.py:991 msgid "Confirm that the BOM is valid" msgstr "" -#: part/views.py:934 +#: part/views.py:1002 msgid "Validated Bill of Materials" msgstr "" -#: part/views.py:1068 +#: part/views.py:1136 msgid "No BOM file provided" msgstr "" -#: part/views.py:1418 +#: part/views.py:1486 msgid "Enter a valid quantity" msgstr "" -#: part/views.py:1443 part/views.py:1446 +#: part/views.py:1511 part/views.py:1514 msgid "Select valid part" msgstr "" -#: part/views.py:1452 +#: part/views.py:1520 msgid "Duplicate part selected" msgstr "" -#: part/views.py:1490 +#: part/views.py:1558 msgid "Select a part" msgstr "" -#: part/views.py:1496 +#: part/views.py:1564 msgid "Selected part creates a circular BOM" msgstr "" -#: part/views.py:1500 +#: part/views.py:1568 msgid "Specify quantity" msgstr "" -#: part/views.py:1756 +#: part/views.py:1824 msgid "Confirm Part Deletion" msgstr "" -#: part/views.py:1765 +#: part/views.py:1833 msgid "Part was deleted" msgstr "" -#: part/views.py:1774 +#: part/views.py:1842 msgid "Part Pricing" msgstr "" -#: part/views.py:1900 +#: part/views.py:1968 msgid "Create Part Parameter Template" msgstr "" -#: part/views.py:1910 +#: part/views.py:1978 msgid "Edit Part Parameter Template" msgstr "" -#: part/views.py:1919 +#: part/views.py:1987 msgid "Delete Part Parameter Template" msgstr "" -#: part/views.py:1929 +#: part/views.py:1997 msgid "Create Part Parameter" msgstr "" -#: part/views.py:1981 +#: part/views.py:2049 msgid "Edit Part Parameter" msgstr "" -#: part/views.py:1997 +#: part/views.py:2065 msgid "Delete Part Parameter" msgstr "" -#: part/views.py:2056 +#: part/views.py:2124 msgid "Edit Part Category" msgstr "" -#: part/views.py:2093 +#: part/views.py:2161 msgid "Delete Part Category" msgstr "" -#: part/views.py:2101 +#: part/views.py:2169 msgid "Part category was deleted" msgstr "" -#: part/views.py:2164 +#: part/views.py:2232 msgid "Create BOM Item" msgstr "" -#: part/views.py:2232 +#: part/views.py:2300 msgid "Edit BOM item" msgstr "" -#: part/views.py:2282 +#: part/views.py:2350 msgid "Confim BOM item deletion" msgstr "" @@ -4198,48 +4256,48 @@ msgstr "" msgid "Create new Stock Item" msgstr "" -#: stock/views.py:1553 +#: stock/views.py:1555 msgid "Duplicate Stock Item" msgstr "" -#: stock/views.py:1619 +#: stock/views.py:1621 msgid "Invalid quantity" msgstr "" -#: stock/views.py:1622 +#: stock/views.py:1624 msgid "Quantity cannot be less than zero" msgstr "" -#: stock/views.py:1626 +#: stock/views.py:1628 msgid "Invalid part selection" msgstr "" -#: stock/views.py:1674 +#: stock/views.py:1676 #, python-brace-format msgid "Created {n} new stock items" msgstr "" -#: stock/views.py:1693 stock/views.py:1709 +#: stock/views.py:1695 stock/views.py:1711 msgid "Created new stock item" msgstr "" -#: stock/views.py:1728 +#: stock/views.py:1730 msgid "Delete Stock Location" msgstr "" -#: stock/views.py:1742 +#: stock/views.py:1744 msgid "Delete Stock Item" msgstr "" -#: stock/views.py:1754 +#: stock/views.py:1756 msgid "Delete Stock Tracking Entry" msgstr "" -#: stock/views.py:1773 +#: stock/views.py:1775 msgid "Edit Stock Tracking Entry" msgstr "" -#: stock/views.py:1783 +#: stock/views.py:1785 msgid "Add Stock Tracking Entry" msgstr "" @@ -4331,19 +4389,23 @@ msgstr "" msgid "Part Settings" msgstr "" -#: templates/InvenTree/settings/part.html:24 +#: templates/InvenTree/settings/part.html:14 +msgid "Part Options" +msgstr "" + +#: templates/InvenTree/settings/part.html:31 msgid "Part Parameter Templates" msgstr "" -#: templates/InvenTree/settings/part.html:45 +#: templates/InvenTree/settings/part.html:52 msgid "No part parameter templates found" msgstr "" -#: templates/InvenTree/settings/part.html:65 +#: templates/InvenTree/settings/part.html:72 msgid "Edit Template" msgstr "" -#: templates/InvenTree/settings/part.html:66 +#: templates/InvenTree/settings/part.html:73 msgid "Delete Template" msgstr "" @@ -5102,58 +5164,62 @@ msgstr "" msgid "Delete Stock" msgstr "" -#: users/admin.py:61 +#: users/admin.py:62 msgid "Users" msgstr "" -#: users/admin.py:62 +#: users/admin.py:63 msgid "Select which users are assigned to this group" msgstr "" #: users/admin.py:120 +msgid "The following users are members of multiple groups:" +msgstr "" + +#: users/admin.py:143 msgid "Personal info" msgstr "" -#: users/admin.py:121 +#: users/admin.py:144 msgid "Permissions" msgstr "" -#: users/admin.py:124 +#: users/admin.py:147 msgid "Important dates" msgstr "" -#: users/models.py:129 +#: users/models.py:130 msgid "Permission set" msgstr "" -#: users/models.py:137 +#: users/models.py:138 msgid "Group" msgstr "" -#: users/models.py:140 +#: users/models.py:141 msgid "View" msgstr "" -#: users/models.py:140 +#: users/models.py:141 msgid "Permission to view items" msgstr "" -#: users/models.py:142 +#: users/models.py:143 msgid "Add" msgstr "" -#: users/models.py:142 +#: users/models.py:143 msgid "Permission to add items" msgstr "" -#: users/models.py:144 +#: users/models.py:145 msgid "Change" msgstr "" -#: users/models.py:144 +#: users/models.py:145 msgid "Permissions to edit items" msgstr "" -#: users/models.py:146 +#: users/models.py:147 msgid "Permission to delete items" msgstr "" diff --git a/InvenTree/order/views.py b/InvenTree/order/views.py index a65cc300fa..d5658909bb 100644 --- a/InvenTree/order/views.py +++ b/InvenTree/order/views.py @@ -335,7 +335,8 @@ class PurchaseOrderCreate(AjaxCreateView): order = form.save(commit=False) order.created_by = self.request.user - order.save() + + return super().save(form) class SalesOrderCreate(AjaxCreateView): @@ -370,7 +371,8 @@ class SalesOrderCreate(AjaxCreateView): order = form.save(commit=False) order.created_by = self.request.user - order.save() + + return super().save(form) class PurchaseOrderEdit(AjaxUpdateView): @@ -428,7 +430,7 @@ class PurchaseOrderCancel(AjaxUpdateView): form.add_error('confirm', _('Confirm order cancellation')) if not order.can_cancel(): - form.add_error(None, _('Order cannot be cancelled')) + form.add_error(None, _('Order cannot be cancelled as either pending or placed')) def save(self, order, form, **kwargs): """ diff --git a/InvenTree/part/forms.py b/InvenTree/part/forms.py index 0b24e5a462..d72df4ed9f 100644 --- a/InvenTree/part/forms.py +++ b/InvenTree/part/forms.py @@ -174,7 +174,9 @@ class SetPartCategoryForm(forms.Form): class EditPartForm(HelperForm): - """ Form for editing a Part object """ + """ + Form for editing a Part object. + """ field_prefix = { 'keywords': 'fa-key', @@ -202,14 +204,14 @@ class EditPartForm(HelperForm): class Meta: model = Part fields = [ - 'bom_copy', - 'parameters_copy', - 'confirm_creation', 'category', 'name', 'IPN', 'description', 'revision', + 'bom_copy', + 'parameters_copy', + 'confirm_creation', 'keywords', 'variant_of', 'link', @@ -217,6 +219,9 @@ class EditPartForm(HelperForm): 'default_supplier', 'units', 'minimum_stock', + 'trackable', + 'purchaseable', + 'salable', ] diff --git a/InvenTree/part/migrations/0054_auto_20201109_1246.py b/InvenTree/part/migrations/0054_auto_20201109_1246.py new file mode 100644 index 0000000000..705ef51466 --- /dev/null +++ b/InvenTree/part/migrations/0054_auto_20201109_1246.py @@ -0,0 +1,44 @@ +# Generated by Django 3.0.7 on 2020-11-09 12:46 + +from django.db import migrations, models +import part.settings + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0053_merge_20201103_1028'), + ] + + operations = [ + migrations.AlterField( + model_name='part', + name='active', + field=models.BooleanField(default=True, help_text='Is this part active?', verbose_name='Active'), + ), + migrations.AlterField( + model_name='part', + name='component', + field=models.BooleanField(default=part.settings.part_component_default, help_text='Can this part be used to build other parts?', verbose_name='Component'), + ), + migrations.AlterField( + model_name='part', + name='purchaseable', + field=models.BooleanField(default=part.settings.part_purchaseable_default, help_text='Can this part be purchased from external suppliers?', verbose_name='Purchaseable'), + ), + migrations.AlterField( + model_name='part', + name='salable', + field=models.BooleanField(default=part.settings.part_salable_default, help_text='Can this part be sold to customers?', verbose_name='Salable'), + ), + migrations.AlterField( + model_name='part', + name='trackable', + field=models.BooleanField(default=part.settings.part_trackable_default, help_text='Does this part have tracking for unique items?', verbose_name='Trackable'), + ), + migrations.AlterField( + model_name='part', + name='virtual', + field=models.BooleanField(default=False, help_text='Is this a virtual part, such as a software product or license?', verbose_name='Virtual'), + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 0c8aeb5665..d6c536db59 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -47,6 +47,7 @@ from company.models import SupplierPart from stock import models as StockModels import common.models +import part.settings as part_settings class PartCategory(InvenTreeTree): @@ -528,6 +529,18 @@ class Part(MPTTModel): """ super().validate_unique(exclude) + # User can decide whether duplicate IPN (Internal Part Number) values are allowed + allow_duplicate_ipn = common.models.InvenTreeSetting.get_setting('PART_ALLOW_DUPLICATE_IPN') + + if not allow_duplicate_ipn: + parts = Part.objects.filter(IPN__iexact=self.IPN) + parts = parts.exclude(pk=self.pk) + + if parts.exists(): + raise ValidationError({ + 'IPN': _('Duplicate IPN not allowed in part settings'), + }) + # Part name uniqueness should be case insensitive try: parts = Part.objects.exclude(id=self.id).filter( @@ -656,19 +669,42 @@ class Part(MPTTModel): units = models.CharField(max_length=20, default="", blank=True, null=True, help_text=_('Stock keeping units for this part')) - assembly = models.BooleanField(default=False, verbose_name='Assembly', help_text=_('Can this part be built from other parts?')) + assembly = models.BooleanField( + default=False, + verbose_name=_('Assembly'), + help_text=_('Can this part be built from other parts?') + ) - component = models.BooleanField(default=True, verbose_name='Component', help_text=_('Can this part be used to build other parts?')) + component = models.BooleanField( + default=part_settings.part_component_default, + verbose_name=_('Component'), + help_text=_('Can this part be used to build other parts?') + ) - trackable = models.BooleanField(default=False, help_text=_('Does this part have tracking for unique items?')) + trackable = models.BooleanField( + default=part_settings.part_trackable_default, + verbose_name=_('Trackable'), + help_text=_('Does this part have tracking for unique items?')) - purchaseable = models.BooleanField(default=True, help_text=_('Can this part be purchased from external suppliers?')) + purchaseable = models.BooleanField( + default=part_settings.part_purchaseable_default, + verbose_name=_('Purchaseable'), + help_text=_('Can this part be purchased from external suppliers?')) - salable = models.BooleanField(default=False, help_text=_("Can this part be sold to customers?")) + salable = models.BooleanField( + default=part_settings.part_salable_default, + verbose_name=_('Salable'), + help_text=_("Can this part be sold to customers?")) - active = models.BooleanField(default=True, help_text=_('Is this part active?')) + active = models.BooleanField( + default=True, + verbose_name=_('Active'), + help_text=_('Is this part active?')) - virtual = models.BooleanField(default=False, help_text=_('Is this a virtual part, such as a software product or license?')) + virtual = models.BooleanField( + default=False, + verbose_name=_('Virtual'), + help_text=_('Is this a virtual part, such as a software product or license?')) notes = MarkdownxField(blank=True, null=True, help_text=_('Part notes - supports Markdown formatting')) diff --git a/InvenTree/part/settings.py b/InvenTree/part/settings.py new file mode 100644 index 0000000000..8d87cdffe3 --- /dev/null +++ b/InvenTree/part/settings.py @@ -0,0 +1,40 @@ +""" +User-configurable settings for the Part app +""" + +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from common.models import InvenTreeSetting + + +def part_component_default(): + """ + Returns the default value for the 'component' field of a Part object + """ + + return InvenTreeSetting.get_setting('PART_COMPONENT') + + +def part_purchaseable_default(): + """ + Returns the default value for the 'purchasable' field for a Part object + """ + + return InvenTreeSetting.get_setting('PART_PURCHASEABLE') + + +def part_salable_default(): + """ + Returns the default value for the 'salable' field for a Part object + """ + + return InvenTreeSetting.get_setting('PART_SALABLE') + + +def part_trackable_default(): + """ + Returns the defualt value fro the 'trackable' field for a Part object + """ + + return InvenTreeSetting.get_setting('PART_TRACKABLE') diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index a3c11e5669..9711c9fbc8 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -203,6 +203,7 @@ {% trans "Part cannot be sold to customers" %} {% endif %} + {% if part.active %} diff --git a/InvenTree/part/test_part.py b/InvenTree/part/test_part.py index 1301df3c91..677b159762 100644 --- a/InvenTree/part/test_part.py +++ b/InvenTree/part/test_part.py @@ -4,6 +4,8 @@ from __future__ import unicode_literals +from django.contrib.auth import get_user_model + from django.test import TestCase from django.core.exceptions import ValidationError @@ -13,6 +15,10 @@ from .models import Part, PartTestTemplate from .models import rename_part_image, match_part_names from .templatetags import inventree_extras +import part.settings + +from common.models import InvenTreeSetting + class TemplateTagTest(TestCase): """ Tests for the custom template tag code """ @@ -164,3 +170,107 @@ class TestTemplateTest(TestCase): PartTestTemplate.objects.create(part=variant, test_name='A Sample Test') self.assertEqual(variant.getTestTemplates().count(), n + 1) + + +class PartSettingsTest(TestCase): + """ + Tests to ensure that the user-configurable default values work as expected. + + Some fields for the Part model can have default values specified by the user. + """ + + def setUp(self): + # Create a user for auth + User = get_user_model() + + self.user = User.objects.create_user( + username='testuser', + email='test@testing.com', + password='password', + is_staff=True + ) + + def make_part(self): + """ + Helper function to create a simple part + """ + + part = Part.objects.create( + name='Test Part', + description='I am but a humble test part', + IPN='IPN-123', + ) + + return part + + def test_defaults(self): + """ + Test that the default values for the part settings are correct + """ + + self.assertTrue(part.settings.part_component_default()) + self.assertFalse(part.settings.part_purchaseable_default()) + self.assertFalse(part.settings.part_salable_default()) + self.assertFalse(part.settings.part_trackable_default()) + + def test_initial(self): + """ + Test the 'initial' default values (no default values have been set) + """ + + part = self.make_part() + + self.assertTrue(part.component) + self.assertFalse(part.purchaseable) + self.assertFalse(part.salable) + self.assertFalse(part.trackable) + + def test_custom(self): + """ + Update some of the part values and re-test + """ + + for val in [True, False]: + InvenTreeSetting.set_setting('PART_COMPONENT', val, self.user) + InvenTreeSetting.set_setting('PART_PURCHASEABLE', val, self.user) + InvenTreeSetting.set_setting('PART_SALABLE', val, self.user) + InvenTreeSetting.set_setting('PART_TRACKABLE', val, self.user) + + self.assertEqual(val, InvenTreeSetting.get_setting('PART_COMPONENT')) + self.assertEqual(val, InvenTreeSetting.get_setting('PART_PURCHASEABLE')) + self.assertEqual(val, InvenTreeSetting.get_setting('PART_SALABLE')) + self.assertEqual(val, InvenTreeSetting.get_setting('PART_TRACKABLE')) + + part = self.make_part() + + self.assertEqual(part.component, val) + self.assertEqual(part.purchaseable, val) + self.assertEqual(part.salable, val) + self.assertEqual(part.trackable, val) + + Part.objects.filter(pk=part.pk).delete() + + def test_duplicate_ipn(self): + """ + Test the setting which controls duplicate IPN values + """ + + # Create a part + Part.objects.create(name='Hello', description='A thing', IPN='IPN123') + + # Attempt to create a duplicate item (should fail) + with self.assertRaises(ValidationError): + Part.objects.create(name='Hello', description='A thing', IPN='IPN123') + + # Attempt to create item with duplicate IPN (should be allowed by default) + Part.objects.create(name='Hello', description='A thing', IPN='IPN123', revision='B') + + # And attempt again with the same values (should fail) + with self.assertRaises(ValidationError): + Part.objects.create(name='Hello', description='A thing', IPN='IPN123', revision='B') + + # Now update the settings so duplicate IPN values are *not* allowed + InvenTreeSetting.set_setting('PART_ALLOW_DUPLICATE_IPN', False, self.user) + + with self.assertRaises(ValidationError): + Part.objects.create(name='Hello', description='A thing', IPN='IPN123', revision='C') diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 2ec42dd2f3..4899ddee8d 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -1247,12 +1247,21 @@ class StockItem(MPTTModel): @property def required_test_count(self): + """ + Return the number of 'required tests' for this StockItem + """ return self.part.getRequiredTests().count() def hasRequiredTests(self): + """ + Return True if there are any 'required tests' associated with this StockItem + """ return self.part.getRequiredTests().count() > 0 def passedAllRequiredTests(self): + """ + Returns True if this StockItem has passed all required tests + """ status = self.requiredTestStatus() diff --git a/InvenTree/templates/InvenTree/settings/part.html b/InvenTree/templates/InvenTree/settings/part.html index 19578ba858..a19ce83922 100644 --- a/InvenTree/templates/InvenTree/settings/part.html +++ b/InvenTree/templates/InvenTree/settings/part.html @@ -11,10 +11,19 @@ {% block settings %} +

    {% trans "Part Options" %}

    + {% include "InvenTree/settings/setting.html" with key="PART_IPN_REGEX" %} + {% include "InvenTree/settings/setting.html" with key="PART_ALLOW_DUPLICATE_IPN" %} + + {% include "InvenTree/settings/setting.html" with key="PART_COMPONENT" %} + {% include "InvenTree/settings/setting.html" with key="PART_PURCHASEABLE" %} + {% include "InvenTree/settings/setting.html" with key="PART_SALABLE" %} + {% include "InvenTree/settings/setting.html" with key="PART_TRACKABLE" %} + {% include "InvenTree/settings/setting.html" with key="PART_COPY_BOM" %} {% include "InvenTree/settings/setting.html" with key="PART_COPY_PARAMETERS" %} {% include "InvenTree/settings/setting.html" with key="PART_COPY_TESTS" %} diff --git a/InvenTree/users/models.py b/InvenTree/users/models.py index 9dd117f1bd..98efb14764 100644 --- a/InvenTree/users/models.py +++ b/InvenTree/users/models.py @@ -316,7 +316,8 @@ def update_group_roles(group, debug=False): permission = get_permission_object(perm) - group.permissions.add(permission) + if permission: + group.permissions.add(permission) if debug: print(f"Adding permission {perm} to group {group.name}") @@ -330,7 +331,8 @@ def update_group_roles(group, debug=False): permission = get_permission_object(perm) - group.permissions.remove(permission) + if permission: + group.permissions.remove(permission) if debug: print(f"Removing permission {perm} from group {group.name}")