Merge pull request #909 from SchrodingersGat/bom-import-export

BOM upload: improve generation of "import" template
This commit is contained in:
Oliver 2020-08-18 14:37:48 +10:00 committed by GitHub
commit 316dfe5e38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 983 additions and 579 deletions

View File

@ -6,7 +6,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-16 02:11+0000\n" "POT-Creation-Date: 2020-08-18 04:01+0000\n"
"PO-Revision-Date: 2020-05-03 11:32+0200\n" "PO-Revision-Date: 2020-05-03 11:32+0200\n"
"Last-Translator: Christian Schlüter <chschlue@gmail.com>\n" "Last-Translator: Christian Schlüter <chschlue@gmail.com>\n"
"Language-Team: C <kde-i18n-doc@kde.org>\n" "Language-Team: C <kde-i18n-doc@kde.org>\n"
@ -45,30 +45,30 @@ msgstr "Neues Teil anlegen"
msgid "Confirm new password" msgid "Confirm new password"
msgstr "" msgstr ""
#: InvenTree/helpers.py:328 order/models.py:187 order/models.py:261 #: InvenTree/helpers.py:336 order/models.py:187 order/models.py:261
msgid "Invalid quantity provided" msgid "Invalid quantity provided"
msgstr "Keine gültige Menge" msgstr "Keine gültige Menge"
#: InvenTree/helpers.py:331 #: InvenTree/helpers.py:339
msgid "Empty serial number string" msgid "Empty serial number string"
msgstr "Keine Seriennummer angegeben" msgstr "Keine Seriennummer angegeben"
#: InvenTree/helpers.py:352 InvenTree/helpers.py:369 #: InvenTree/helpers.py:360 InvenTree/helpers.py:377
#, python-brace-format #, python-brace-format
msgid "Duplicate serial: {n}" msgid "Duplicate serial: {n}"
msgstr "Doppelte Seriennummer: {n}" msgstr "Doppelte Seriennummer: {n}"
#: InvenTree/helpers.py:356 InvenTree/helpers.py:359 InvenTree/helpers.py:362 #: InvenTree/helpers.py:364 InvenTree/helpers.py:367 InvenTree/helpers.py:370
#: InvenTree/helpers.py:373 #: InvenTree/helpers.py:381
#, python-brace-format #, python-brace-format
msgid "Invalid group: {g}" msgid "Invalid group: {g}"
msgstr "Ungültige Gruppe: {g}" msgstr "Ungültige Gruppe: {g}"
#: InvenTree/helpers.py:379 #: InvenTree/helpers.py:387
msgid "No serial numbers found" msgid "No serial numbers found"
msgstr "Keine Seriennummern gefunden" msgstr "Keine Seriennummern gefunden"
#: InvenTree/helpers.py:383 #: InvenTree/helpers.py:391
#, python-brace-format #, python-brace-format
msgid "Number of unique serial number ({s}) must match quantity ({q})" msgid "Number of unique serial number ({s}) must match quantity ({q})"
msgstr "" msgstr ""
@ -341,7 +341,7 @@ msgstr "Bau-Status"
msgid "Build status code" msgid "Build status code"
msgstr "Bau-Statuscode" msgstr "Bau-Statuscode"
#: build/models.py:136 stock/models.py:376 #: build/models.py:136 stock/models.py:371
msgid "Batch Code" msgid "Batch Code"
msgstr "Losnummer" msgstr "Losnummer"
@ -353,11 +353,11 @@ msgstr "Chargennummer für diese Bau-Ausgabe"
#: company/templates/company/supplier_part_base.html:60 #: company/templates/company/supplier_part_base.html:60
#: company/templates/company/supplier_part_detail.html:24 #: company/templates/company/supplier_part_detail.html:24
#: part/templates/part/detail.html:74 part/templates/part/part_base.html:86 #: part/templates/part/detail.html:74 part/templates/part/part_base.html:86
#: stock/models.py:370 stock/templates/stock/item_base.html:237 #: stock/models.py:365 stock/templates/stock/item_base.html:234
msgid "External Link" msgid "External Link"
msgstr "Externer Link" msgstr "Externer Link"
#: build/models.py:156 stock/models.py:372 #: build/models.py:156 stock/models.py:367
msgid "Link to external URL" msgid "Link to external URL"
msgstr "Link zu einer externen URL" msgstr "Link zu einer externen URL"
@ -365,7 +365,7 @@ msgstr "Link zu einer externen URL"
#: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:15 #: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:15
#: order/templates/order/purchase_order_detail.html:200 #: order/templates/order/purchase_order_detail.html:200
#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:64 #: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:64
#: stock/models.py:438 stock/models.py:1287 stock/templates/stock/tabs.html:26 #: stock/models.py:433 stock/models.py:1282 stock/templates/stock/tabs.html:26
#: templates/js/barcode.html:391 templates/js/bom.html:229 #: templates/js/barcode.html:391 templates/js/bom.html:229
#: templates/js/stock.html:114 templates/js/stock.html:526 #: templates/js/stock.html:114 templates/js/stock.html:526
msgid "Notes" msgid "Notes"
@ -433,8 +433,8 @@ msgstr "Neues Lagerobjekt"
#: build/templates/build/allocate.html:161 #: build/templates/build/allocate.html:161
#: order/templates/order/sales_order_detail.html:68 #: order/templates/order/sales_order_detail.html:68
#: order/templates/order/sales_order_detail.html:150 stock/models.py:364 #: order/templates/order/sales_order_detail.html:150 stock/models.py:359
#: stock/templates/stock/item_base.html:153 #: stock/templates/stock/item_base.html:150
msgid "Serial Number" msgid "Serial Number"
msgstr "Seriennummer" msgstr "Seriennummer"
@ -451,7 +451,7 @@ msgstr "Seriennummer"
#: part/templates/part/allocation.html:49 #: part/templates/part/allocation.html:49
#: stock/templates/stock/item_base.html:26 #: stock/templates/stock/item_base.html:26
#: stock/templates/stock/item_base.html:32 #: stock/templates/stock/item_base.html:32
#: stock/templates/stock/item_base.html:159 #: stock/templates/stock/item_base.html:156
#: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338
#: templates/js/bom.html:172 templates/js/build.html:52 #: templates/js/bom.html:172 templates/js/build.html:52
#: templates/js/stock.html:673 #: templates/js/stock.html:673
@ -460,7 +460,7 @@ msgstr "Anzahl"
#: build/templates/build/allocate.html:177 #: build/templates/build/allocate.html:177
#: build/templates/build/auto_allocate.html:20 #: build/templates/build/auto_allocate.html:20
#: stock/templates/stock/item_base.html:191 #: stock/templates/stock/item_base.html:188
#: stock/templates/stock/stock_adjust.html:17 templates/js/barcode.html:337 #: stock/templates/stock/stock_adjust.html:17 templates/js/barcode.html:337
#: templates/js/stock.html:508 #: templates/js/stock.html:508
msgid "Location" msgid "Location"
@ -498,7 +498,7 @@ msgstr "Beschreibung"
msgid "Reference" msgid "Reference"
msgstr "Referenz" msgstr "Referenz"
#: build/templates/build/allocate.html:338 part/models.py:1270 #: build/templates/build/allocate.html:338 part/models.py:1271
#: templates/js/part.html:359 templates/js/table_filters.html:100 #: templates/js/part.html:359 templates/js/table_filters.html:100
msgid "Required" msgid "Required"
msgstr "benötigt" msgstr "benötigt"
@ -543,7 +543,7 @@ msgstr "Keine Lagerobjekt gefunden, die diesem Bau zugewiesen werden können"
#: build/templates/build/build_base.html:8 #: build/templates/build/build_base.html:8
#: build/templates/build/build_base.html:34 #: build/templates/build/build_base.html:34
#: build/templates/build/complete.html:6 #: build/templates/build/complete.html:6
#: stock/templates/stock/item_base.html:216 templates/js/build.html:33 #: stock/templates/stock/item_base.html:213 templates/js/build.html:33
#: templates/navbar.html:12 #: templates/navbar.html:12
msgid "Build" msgid "Build"
msgstr "Bau" msgstr "Bau"
@ -563,7 +563,7 @@ msgstr "Bau-Status"
#: build/templates/build/build_base.html:80 #: build/templates/build/build_base.html:80
#: build/templates/build/detail.html:42 #: build/templates/build/detail.html:42
#: order/templates/order/receive_parts.html:24 #: order/templates/order/receive_parts.html:24
#: stock/templates/stock/item_base.html:269 templates/js/barcode.html:42 #: stock/templates/stock/item_base.html:266 templates/js/barcode.html:42
#: templates/js/build.html:57 templates/js/order.html:162 #: templates/js/build.html:57 templates/js/order.html:162
#: templates/js/order.html:235 templates/js/stock.html:495 #: templates/js/order.html:235 templates/js/stock.html:495
msgid "Status" msgid "Status"
@ -575,7 +575,7 @@ msgstr "Status"
#: order/templates/order/sales_order_notes.html:10 #: order/templates/order/sales_order_notes.html:10
#: order/templates/order/sales_order_ship.html:25 #: order/templates/order/sales_order_ship.html:25
#: part/templates/part/allocation.html:27 #: part/templates/part/allocation.html:27
#: stock/templates/stock/item_base.html:179 templates/js/order.html:209 #: stock/templates/stock/item_base.html:176 templates/js/order.html:209
msgid "Sales Order" msgid "Sales Order"
msgstr "Bestellung" msgstr "Bestellung"
@ -644,7 +644,7 @@ msgid "Stock can be taken from any available location."
msgstr "Bestand kann jedem verfügbaren Lagerort entnommen werden." msgstr "Bestand kann jedem verfügbaren Lagerort entnommen werden."
#: build/templates/build/detail.html:48 #: build/templates/build/detail.html:48
#: stock/templates/stock/item_base.html:209 templates/js/stock.html:503 #: stock/templates/stock/item_base.html:206 templates/js/stock.html:503
msgid "Batch" msgid "Batch"
msgstr "Los" msgstr "Los"
@ -942,8 +942,8 @@ msgstr "Kaufen Sie Teile von dieser Firma?"
msgid "Does this company manufacture parts?" msgid "Does this company manufacture parts?"
msgstr "Produziert diese Firma Teile?" msgstr "Produziert diese Firma Teile?"
#: company/models.py:279 stock/models.py:324 #: company/models.py:279 stock/models.py:319
#: stock/templates/stock/item_base.html:145 #: stock/templates/stock/item_base.html:142
msgid "Base Part" msgid "Base Part"
msgstr "Basisteil" msgstr "Basisteil"
@ -1016,14 +1016,14 @@ msgstr "Hersteller"
#: company/templates/company/supplier_part_detail.html:21 order/models.py:148 #: company/templates/company/supplier_part_detail.html:21 order/models.py:148
#: order/templates/order/order_base.html:74 #: order/templates/order/order_base.html:74
#: order/templates/order/order_wizard/select_pos.html:30 #: order/templates/order/order_wizard/select_pos.html:30
#: stock/templates/stock/item_base.html:244 templates/js/company.html:52 #: stock/templates/stock/item_base.html:241 templates/js/company.html:52
#: templates/js/company.html:134 templates/js/order.html:144 #: templates/js/company.html:134 templates/js/order.html:144
msgid "Supplier" msgid "Supplier"
msgstr "Zulieferer" msgstr "Zulieferer"
#: company/templates/company/detail.html:26 order/models.py:314 #: company/templates/company/detail.html:26 order/models.py:314
#: order/templates/order/sales_order_base.html:73 stock/models.py:359 #: order/templates/order/sales_order_base.html:73 stock/models.py:354
#: stock/models.py:360 stock/templates/stock/item_base.html:166 #: stock/models.py:355 stock/templates/stock/item_base.html:163
#: templates/js/company.html:44 templates/js/order.html:217 #: templates/js/company.html:44 templates/js/order.html:217
msgid "Customer" msgid "Customer"
msgstr "Kunde" msgstr "Kunde"
@ -1137,8 +1137,8 @@ msgid "New Sales Order"
msgstr "Neuer Auftrag" msgstr "Neuer Auftrag"
#: company/templates/company/supplier_part_base.html:6 #: company/templates/company/supplier_part_base.html:6
#: company/templates/company/supplier_part_base.html:19 stock/models.py:333 #: company/templates/company/supplier_part_base.html:19 stock/models.py:328
#: stock/templates/stock/item_base.html:249 templates/js/company.html:150 #: stock/templates/stock/item_base.html:246 templates/js/company.html:150
msgid "Supplier Part" msgid "Supplier Part"
msgstr "Zulieferer-Teil" msgstr "Zulieferer-Teil"
@ -1410,8 +1410,8 @@ msgstr "Bestell-Notizen"
msgid "Supplier order reference code" msgid "Supplier order reference code"
msgstr "Bestellreferenz" msgstr "Bestellreferenz"
#: order/models.py:185 order/models.py:259 part/views.py:1167 #: order/models.py:185 order/models.py:259 part/views.py:1250
#: stock/models.py:238 stock/models.py:687 #: stock/models.py:239 stock/models.py:682
msgid "Quantity must be greater than zero" msgid "Quantity must be greater than zero"
msgstr "Anzahl muss größer Null sein" msgstr "Anzahl muss größer Null sein"
@ -1445,7 +1445,7 @@ msgstr "Position - Notizen"
#: order/models.py:466 order/templates/order/order_base.html:9 #: order/models.py:466 order/templates/order/order_base.html:9
#: order/templates/order/order_base.html:23 #: order/templates/order/order_base.html:23
#: stock/templates/stock/item_base.html:223 templates/js/order.html:136 #: stock/templates/stock/item_base.html:220 templates/js/order.html:136
msgid "Purchase Order" msgid "Purchase Order"
msgstr "Kaufvertrag" msgstr "Kaufvertrag"
@ -1869,16 +1869,16 @@ msgstr "Zuordnung bearbeiten"
msgid "Remove allocation" msgid "Remove allocation"
msgstr "Zuordnung entfernen" msgstr "Zuordnung entfernen"
#: part/bom.py:140 #: part/bom.py:144
#, python-brace-format #, python-brace-format
msgid "Unsupported file format: {f}" msgid "Unsupported file format: {f}"
msgstr "Nicht unterstütztes Dateiformat: {f}" msgstr "Nicht unterstütztes Dateiformat: {f}"
#: part/bom.py:145 #: part/bom.py:149
msgid "Error reading BOM file (invalid data)" msgid "Error reading BOM file (invalid data)"
msgstr "Fehler beim Lesen der Stückliste (ungültige Daten)" msgstr "Fehler beim Lesen der Stückliste (ungültige Daten)"
#: part/bom.py:147 #: part/bom.py:151
msgid "Error reading BOM file (incorrect row size)" msgid "Error reading BOM file (incorrect row size)"
msgstr "Fehler beim Lesen der Stückliste (ungültige Zeilengröße)" msgstr "Fehler beim Lesen der Stückliste (ungültige Zeilengröße)"
@ -1898,33 +1898,41 @@ msgstr "Kaskadierend"
msgid "Download cascading / multi-level BOM" msgid "Download cascading / multi-level BOM"
msgstr "Kaskadierende Stückliste herunterladen" msgstr "Kaskadierende Stückliste herunterladen"
#: part/forms.py:76 #: part/forms.py:59
msgid "Levels"
msgstr ""
#: part/forms.py:59
msgid "Select maximum number of BOM levels to export (0 = all levels)"
msgstr ""
#: part/forms.py:78
msgid "Confirm that the BOM is correct" msgid "Confirm that the BOM is correct"
msgstr "Bestätigen, dass die Stückliste korrekt ist" msgstr "Bestätigen, dass die Stückliste korrekt ist"
#: part/forms.py:88 #: part/forms.py:90
msgid "Select BOM file to upload" msgid "Select BOM file to upload"
msgstr "Stücklisten-Datei zum Upload auswählen" msgstr "Stücklisten-Datei zum Upload auswählen"
#: part/forms.py:112 #: part/forms.py:114
msgid "Select part category" msgid "Select part category"
msgstr "Teilekategorie wählen" msgstr "Teilekategorie wählen"
#: part/forms.py:126 #: part/forms.py:128
msgid "Perform 'deep copy' which will duplicate all BOM data for this part" msgid "Perform 'deep copy' which will duplicate all BOM data for this part"
msgstr "" msgstr ""
"Tiefe Kopie ausführen. Dies wird alle Daten der Stückliste für dieses Teil " "Tiefe Kopie ausführen. Dies wird alle Daten der Stückliste für dieses Teil "
"duplizieren" "duplizieren"
#: part/forms.py:131 #: part/forms.py:133
msgid "Confirm part creation" msgid "Confirm part creation"
msgstr "Erstellen des Teils bestätigen" msgstr "Erstellen des Teils bestätigen"
#: part/forms.py:221 #: part/forms.py:223
msgid "Input quantity for price calculation" msgid "Input quantity for price calculation"
msgstr "Eintragsmenge zur Preisberechnung" msgstr "Eintragsmenge zur Preisberechnung"
#: part/forms.py:224 #: part/forms.py:226
msgid "Select currency for price calculation" msgid "Select currency for price calculation"
msgstr "Währung zur Preisberechnung wählen" msgstr "Währung zur Preisberechnung wählen"
@ -2037,13 +2045,13 @@ msgstr "Bemerkungen - unterstüzt Markdown-Formatierung"
msgid "Stored BOM checksum" msgid "Stored BOM checksum"
msgstr "Prüfsumme der Stückliste gespeichert" msgstr "Prüfsumme der Stückliste gespeichert"
#: part/models.py:1222 #: part/models.py:1223
#, fuzzy #, fuzzy
#| msgid "Stock item cannot be created for a template Part" #| msgid "Stock item cannot be created for a template Part"
msgid "Test templates can only be created for trackable parts" msgid "Test templates can only be created for trackable parts"
msgstr "Lagerobjekt kann nicht für Vorlagen-Teile angelegt werden" msgstr "Lagerobjekt kann nicht für Vorlagen-Teile angelegt werden"
#: part/models.py:1239 #: part/models.py:1240
#, fuzzy #, fuzzy
#| msgid "" #| msgid ""
#| "A stock item with this serial number already exists for template part " #| "A stock item with this serial number already exists for template part "
@ -2053,122 +2061,123 @@ msgstr ""
"Ein Teil mit dieser Seriennummer existiert bereits für die Teilevorlage " "Ein Teil mit dieser Seriennummer existiert bereits für die Teilevorlage "
"{part}" "{part}"
#: part/models.py:1258 templates/js/part.html:350 templates/js/stock.html:90 #: part/models.py:1259 templates/js/part.html:350 templates/js/stock.html:90
#, fuzzy #, fuzzy
#| msgid "Instance Name" #| msgid "Instance Name"
msgid "Test Name" msgid "Test Name"
msgstr "Instanzname" msgstr "Instanzname"
#: part/models.py:1259 #: part/models.py:1260
#, fuzzy #, fuzzy
#| msgid "Serial number for this item" #| msgid "Serial number for this item"
msgid "Enter a name for the test" msgid "Enter a name for the test"
msgstr "Seriennummer für dieses Teil" msgstr "Seriennummer für dieses Teil"
#: part/models.py:1264 #: part/models.py:1265
#, fuzzy #, fuzzy
#| msgid "Description" #| msgid "Description"
msgid "Test Description" msgid "Test Description"
msgstr "Beschreibung" msgstr "Beschreibung"
#: part/models.py:1265 #: part/models.py:1266
#, fuzzy #, fuzzy
#| msgid "Brief description of the build" #| msgid "Brief description of the build"
msgid "Enter description for this test" msgid "Enter description for this test"
msgstr "Kurze Beschreibung des Baus" msgstr "Kurze Beschreibung des Baus"
#: part/models.py:1271 #: part/models.py:1272
msgid "Is this test required to pass?" msgid "Is this test required to pass?"
msgstr "" msgstr ""
#: part/models.py:1276 templates/js/part.html:367 #: part/models.py:1277 templates/js/part.html:367
#, fuzzy #, fuzzy
#| msgid "Required Parts" #| msgid "Required Parts"
msgid "Requires Value" msgid "Requires Value"
msgstr "benötigte Teile" msgstr "benötigte Teile"
#: part/models.py:1277 #: part/models.py:1278
msgid "Does this test require a value when adding a test result?" msgid "Does this test require a value when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1282 templates/js/part.html:374 #: part/models.py:1283 templates/js/part.html:374
#, fuzzy #, fuzzy
#| msgid "Delete Attachment" #| msgid "Delete Attachment"
msgid "Requires Attachment" msgid "Requires Attachment"
msgstr "Anhang löschen" msgstr "Anhang löschen"
#: part/models.py:1283 #: part/models.py:1284
msgid "Does this test require a file attachment when adding a test result?" msgid "Does this test require a file attachment when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1316 #: part/models.py:1317
msgid "Parameter template name must be unique" msgid "Parameter template name must be unique"
msgstr "Vorlagen-Name des Parameters muss eindeutig sein" msgstr "Vorlagen-Name des Parameters muss eindeutig sein"
#: part/models.py:1321 #: part/models.py:1322
msgid "Parameter Name" msgid "Parameter Name"
msgstr "Name des Parameters" msgstr "Name des Parameters"
#: part/models.py:1323 #: part/models.py:1324
msgid "Parameter Units" msgid "Parameter Units"
msgstr "Parameter Einheit" msgstr "Parameter Einheit"
#: part/models.py:1349 #: part/models.py:1350
msgid "Parent Part" msgid "Parent Part"
msgstr "Ausgangsteil" msgstr "Ausgangsteil"
#: part/models.py:1351 #: part/models.py:1352
msgid "Parameter Template" msgid "Parameter Template"
msgstr "Parameter Vorlage" msgstr "Parameter Vorlage"
#: part/models.py:1353 #: part/models.py:1354
msgid "Parameter Value" msgid "Parameter Value"
msgstr "Parameter Wert" msgstr "Parameter Wert"
#: part/models.py:1382 #: part/models.py:1383
msgid "Select parent part" msgid "Select parent part"
msgstr "Ausgangsteil auswählen" msgstr "Ausgangsteil auswählen"
#: part/models.py:1390 #: part/models.py:1391
msgid "Select part to be used in BOM" msgid "Select part to be used in BOM"
msgstr "Teil für die Nutzung in der Stückliste auswählen" msgstr "Teil für die Nutzung in der Stückliste auswählen"
#: part/models.py:1396 #: part/models.py:1397
msgid "BOM quantity for this BOM item" msgid "BOM quantity for this BOM item"
msgstr "Stücklisten-Anzahl für dieses Stücklisten-Teil" msgstr "Stücklisten-Anzahl für dieses Stücklisten-Teil"
#: part/models.py:1399 #: part/models.py:1400
msgid "Estimated build wastage quantity (absolute or percentage)" msgid "Estimated build wastage quantity (absolute or percentage)"
msgstr "Geschätzter Ausschuss (absolut oder prozentual)" msgstr "Geschätzter Ausschuss (absolut oder prozentual)"
#: part/models.py:1402 #: part/models.py:1403
msgid "BOM item reference" msgid "BOM item reference"
msgstr "Referenz des Objekts auf der Stückliste" msgstr "Referenz des Objekts auf der Stückliste"
#: part/models.py:1405 #: part/models.py:1406
msgid "BOM item notes" msgid "BOM item notes"
msgstr "Notizen zum Stücklisten-Objekt" msgstr "Notizen zum Stücklisten-Objekt"
#: part/models.py:1407 #: part/models.py:1408
msgid "BOM line checksum" msgid "BOM line checksum"
msgstr "Prüfsumme der Stückliste" msgstr "Prüfsumme der Stückliste"
#: part/models.py:1471 stock/models.py:228 #: part/models.py:1472 part/views.py:1256 part/views.py:1308
#: stock/models.py:229
#, fuzzy #, fuzzy
#| msgid "Overage must be an integer value or a percentage" #| msgid "Overage must be an integer value or a percentage"
msgid "Quantity must be integer value for trackable parts" msgid "Quantity must be integer value for trackable parts"
msgstr "Überschuss muss eine Ganzzahl oder ein Prozentwert sein" msgstr "Überschuss muss eine Ganzzahl oder ein Prozentwert sein"
#: part/models.py:1480 #: part/models.py:1481
msgid "Part cannot be added to its own Bill of Materials" msgid "Part cannot be added to its own Bill of Materials"
msgstr "Teil kann nicht zu seiner eigenen Stückliste hinzugefügt werden" msgstr "Teil kann nicht zu seiner eigenen Stückliste hinzugefügt werden"
#: part/models.py:1487 #: part/models.py:1488
#, python-brace-format #, python-brace-format
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
msgstr "Teil '{p1}' wird in Stückliste für Teil '{p2}' benutzt (rekursiv)" msgstr "Teil '{p1}' wird in Stückliste für Teil '{p2}' benutzt (rekursiv)"
#: part/models.py:1494 #: part/models.py:1495
#, fuzzy #, fuzzy
#| msgid "New BOM Item" #| msgid "New BOM Item"
msgid "BOM Item" msgid "BOM Item"
@ -2189,14 +2198,14 @@ msgstr "Bestellung"
#: part/templates/part/allocation.html:45 #: part/templates/part/allocation.html:45
#: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:8
#: stock/templates/stock/item_base.html:58 #: stock/templates/stock/item_base.html:58
#: stock/templates/stock/item_base.html:231 #: stock/templates/stock/item_base.html:228
#: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106
#: templates/js/stock.html:643 #: templates/js/stock.html:643
msgid "Stock Item" msgid "Stock Item"
msgstr "Lagerobjekt" msgstr "Lagerobjekt"
#: part/templates/part/allocation.html:20 #: part/templates/part/allocation.html:20
#: stock/templates/stock/item_base.html:185 #: stock/templates/stock/item_base.html:182
msgid "Build Order" msgid "Build Order"
msgstr "Bauauftrag" msgstr "Bauauftrag"
@ -2232,10 +2241,94 @@ msgstr "Stückliste bearbeiten"
msgid "Validate Bill of Materials" msgid "Validate Bill of Materials"
msgstr "Stückliste validieren" msgstr "Stückliste validieren"
#: part/templates/part/bom.html:46 part/views.py:1412 #: part/templates/part/bom.html:46 part/views.py:1523
msgid "Export Bill of Materials" msgid "Export Bill of Materials"
msgstr "Stückliste exportieren" msgstr "Stückliste exportieren"
#: part/templates/part/bom_upload/select_fields.html:8
#: part/templates/part/bom_upload/select_parts.html:8
#: part/templates/part/bom_upload/upload_file.html:10
#, fuzzy
#| msgid "Export Bill of Materials"
msgid "Upload Bill of Materials"
msgstr "Stückliste exportieren"
#: part/templates/part/bom_upload/select_fields.html:10
#, fuzzy
#| msgid "Step 1 of 2 - Select Part Suppliers"
msgid "Step 2 - Select Fields"
msgstr "Schritt 1 von 2 - Zulieferer auswählen"
#: part/templates/part/bom_upload/select_fields.html:15
msgid "Missing selections for the following required columns"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:26
#, fuzzy
#| msgid "Sublocations"
msgid "Submit Selections"
msgstr "Sub-Standorte"
#: part/templates/part/bom_upload/select_fields.html:35
msgid "File Fields"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:52
msgid "Match Fields"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:10
#, fuzzy
#| msgid "Step 1 of 2 - Select Part Suppliers"
msgid "Step 3 - Select Parts"
msgstr "Schritt 1 von 2 - Zulieferer auswählen"
#: part/templates/part/bom_upload/select_parts.html:15
msgid "Errors exist in the submitted data"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:21
#, fuzzy
#| msgid "Edit BOM"
msgid "Submit BOM"
msgstr "Stückliste bearbeiten"
#: part/templates/part/bom_upload/select_parts.html:33
msgid "Row"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:34
#: part/templates/part/bom_upload/select_parts.html:63
#, fuzzy
#| msgid "Select part"
msgid "Select Part"
msgstr "Teil auswählen"
#: part/templates/part/bom_upload/upload_file.html:13
#, fuzzy
#| msgid "Step 1 of 2 - Select Part Suppliers"
msgid "Step 1 - Select BOM File"
msgstr "Schritt 1 von 2 - Zulieferer auswählen"
#: part/templates/part/bom_upload/upload_file.html:16
msgid "Requirements for BOM upload"
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:18
msgid ""
"The BOM file must contain the required named columns as provided in the "
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:18
#, fuzzy
#| msgid "Upload new image"
msgid "BOM Upload Template"
msgstr "Neues Bild hochladen"
#: part/templates/part/bom_upload/upload_file.html:19
msgid "Each part must already exist in the database"
msgstr ""
#: part/templates/part/category.html:14 #: part/templates/part/category.html:14
msgid "All parts" msgid "All parts"
msgstr "Alle Teile" msgstr "Alle Teile"
@ -2440,7 +2533,7 @@ msgstr "Parameter hinzufügen"
msgid "New Parameter" msgid "New Parameter"
msgstr "Neuer Parameter" msgstr "Neuer Parameter"
#: part/templates/part/params.html:21 stock/models.py:1274 #: part/templates/part/params.html:21 stock/models.py:1269
#: templates/js/stock.html:110 #: templates/js/stock.html:110
msgid "Value" msgid "Value"
msgstr "Wert" msgstr "Wert"
@ -2647,7 +2740,7 @@ msgstr "Stückliste"
msgid "Used In" msgid "Used In"
msgstr "Benutzt in" msgstr "Benutzt in"
#: part/templates/part/tabs.html:55 stock/templates/stock/item_base.html:275 #: part/templates/part/tabs.html:55 stock/templates/stock/item_base.html:272
msgid "Tests" msgid "Tests"
msgstr "" msgstr ""
@ -2758,91 +2851,91 @@ msgstr "Teileigenschaften bearbeiten"
msgid "Validate BOM" msgid "Validate BOM"
msgstr "BOM validieren" msgstr "BOM validieren"
#: part/views.py:908 #: part/views.py:909
msgid "No BOM file provided" msgid "No BOM file provided"
msgstr "Keine Stückliste angegeben" msgstr "Keine Stückliste angegeben"
#: part/views.py:1169 #: part/views.py:1259
msgid "Enter a valid quantity" msgid "Enter a valid quantity"
msgstr "Bitte eine gültige Anzahl eingeben" msgstr "Bitte eine gültige Anzahl eingeben"
#: part/views.py:1193 part/views.py:1196 #: part/views.py:1284 part/views.py:1287
msgid "Select valid part" msgid "Select valid part"
msgstr "Bitte ein gültiges Teil auswählen" msgstr "Bitte ein gültiges Teil auswählen"
#: part/views.py:1202 #: part/views.py:1293
msgid "Duplicate part selected" msgid "Duplicate part selected"
msgstr "Teil doppelt ausgewählt" msgstr "Teil doppelt ausgewählt"
#: part/views.py:1230 #: part/views.py:1329
msgid "Select a part" msgid "Select a part"
msgstr "Teil auswählen" msgstr "Teil auswählen"
#: part/views.py:1234 #: part/views.py:1333
msgid "Specify quantity" msgid "Specify quantity"
msgstr "Anzahl angeben" msgstr "Anzahl angeben"
#: part/views.py:1450 #: part/views.py:1565
msgid "Confirm Part Deletion" msgid "Confirm Part Deletion"
msgstr "Löschen des Teils bestätigen" msgstr "Löschen des Teils bestätigen"
#: part/views.py:1457 #: part/views.py:1572
msgid "Part was deleted" msgid "Part was deleted"
msgstr "Teil wurde gelöscht" msgstr "Teil wurde gelöscht"
#: part/views.py:1466 #: part/views.py:1581
msgid "Part Pricing" msgid "Part Pricing"
msgstr "Teilbepreisung" msgstr "Teilbepreisung"
#: part/views.py:1588 #: part/views.py:1703
msgid "Create Part Parameter Template" msgid "Create Part Parameter Template"
msgstr "Teilparametervorlage anlegen" msgstr "Teilparametervorlage anlegen"
#: part/views.py:1596 #: part/views.py:1711
msgid "Edit Part Parameter Template" msgid "Edit Part Parameter Template"
msgstr "Teilparametervorlage bearbeiten" msgstr "Teilparametervorlage bearbeiten"
#: part/views.py:1603 #: part/views.py:1718
msgid "Delete Part Parameter Template" msgid "Delete Part Parameter Template"
msgstr "Teilparametervorlage löschen" msgstr "Teilparametervorlage löschen"
#: part/views.py:1611 #: part/views.py:1726
msgid "Create Part Parameter" msgid "Create Part Parameter"
msgstr "Teilparameter anlegen" msgstr "Teilparameter anlegen"
#: part/views.py:1661 #: part/views.py:1776
msgid "Edit Part Parameter" msgid "Edit Part Parameter"
msgstr "Teilparameter bearbeiten" msgstr "Teilparameter bearbeiten"
#: part/views.py:1675 #: part/views.py:1790
msgid "Delete Part Parameter" msgid "Delete Part Parameter"
msgstr "Teilparameter löschen" msgstr "Teilparameter löschen"
#: part/views.py:1691 #: part/views.py:1806
msgid "Edit Part Category" msgid "Edit Part Category"
msgstr "Teilkategorie bearbeiten" msgstr "Teilkategorie bearbeiten"
#: part/views.py:1726 #: part/views.py:1841
msgid "Delete Part Category" msgid "Delete Part Category"
msgstr "Teilkategorie löschen" msgstr "Teilkategorie löschen"
#: part/views.py:1732 #: part/views.py:1847
msgid "Part category was deleted" msgid "Part category was deleted"
msgstr "Teilekategorie wurde gelöscht" msgstr "Teilekategorie wurde gelöscht"
#: part/views.py:1740 #: part/views.py:1855
msgid "Create new part category" msgid "Create new part category"
msgstr "Teilkategorie anlegen" msgstr "Teilkategorie anlegen"
#: part/views.py:1791 #: part/views.py:1906
msgid "Create BOM item" msgid "Create BOM item"
msgstr "BOM-Position anlegen" msgstr "BOM-Position anlegen"
#: part/views.py:1857 #: part/views.py:1972
msgid "Edit BOM item" msgid "Edit BOM item"
msgstr "BOM-Position beaarbeiten" msgstr "BOM-Position beaarbeiten"
#: part/views.py:1905 #: part/views.py:2020
msgid "Confim BOM item deletion" msgid "Confim BOM item deletion"
msgstr "Löschung von BOM-Position bestätigen" msgstr "Löschung von BOM-Position bestätigen"
@ -2902,226 +2995,226 @@ msgstr "Bewegung der Lagerobjekte bestätigen"
msgid "Set the destination as the default location for selected parts" msgid "Set the destination as the default location for selected parts"
msgstr "Setze das Ziel als Standard-Ziel für ausgewählte Teile" msgstr "Setze das Ziel als Standard-Ziel für ausgewählte Teile"
#: stock/models.py:209 #: stock/models.py:210
#, fuzzy #, fuzzy
#| msgid "A stock item with this serial number already exists" #| msgid "A stock item with this serial number already exists"
msgid "StockItem with this serial number already exists" msgid "StockItem with this serial number already exists"
msgstr "Ein Teil mit dieser Seriennummer existiert bereits" msgstr "Ein Teil mit dieser Seriennummer existiert bereits"
#: stock/models.py:245 #: stock/models.py:246
#, python-brace-format #, python-brace-format
msgid "Part type ('{pf}') must be {pe}" msgid "Part type ('{pf}') must be {pe}"
msgstr "Teile-Typ ('{pf}') muss {pe} sein" msgstr "Teile-Typ ('{pf}') muss {pe} sein"
#: stock/models.py:255 stock/models.py:264 #: stock/models.py:256 stock/models.py:265
msgid "Quantity must be 1 for item with a serial number" msgid "Quantity must be 1 for item with a serial number"
msgstr "Anzahl muss für Objekte mit Seriennummer \"1\" sein" msgstr "Anzahl muss für Objekte mit Seriennummer \"1\" sein"
#: stock/models.py:256 #: stock/models.py:257
msgid "Serial number cannot be set if quantity greater than 1" msgid "Serial number cannot be set if quantity greater than 1"
msgstr "" msgstr ""
"Seriennummer kann nicht gesetzt werden wenn die Anzahl größer als \"1\" ist" "Seriennummer kann nicht gesetzt werden wenn die Anzahl größer als \"1\" ist"
#: stock/models.py:277 #: stock/models.py:278
msgid "Item cannot belong to itself" msgid "Item cannot belong to itself"
msgstr "Teil kann nicht zu sich selbst gehören" msgstr "Teil kann nicht zu sich selbst gehören"
#: stock/models.py:316 #: stock/models.py:311
msgid "Parent Stock Item" msgid "Parent Stock Item"
msgstr "Eltern-Lagerobjekt" msgstr "Eltern-Lagerobjekt"
#: stock/models.py:325 #: stock/models.py:320
msgid "Base part" msgid "Base part"
msgstr "Basis-Teil" msgstr "Basis-Teil"
#: stock/models.py:334 #: stock/models.py:329
msgid "Select a matching supplier part for this stock item" msgid "Select a matching supplier part for this stock item"
msgstr "Passenden Zulieferer für dieses Lagerobjekt auswählen" msgstr "Passenden Zulieferer für dieses Lagerobjekt auswählen"
#: stock/models.py:339 stock/templates/stock/stock_app_base.html:7 #: stock/models.py:334 stock/templates/stock/stock_app_base.html:7
msgid "Stock Location" msgid "Stock Location"
msgstr "Lagerort" msgstr "Lagerort"
#: stock/models.py:342 #: stock/models.py:337
msgid "Where is this stock item located?" msgid "Where is this stock item located?"
msgstr "Wo wird dieses Teil normalerweise gelagert?" msgstr "Wo wird dieses Teil normalerweise gelagert?"
#: stock/models.py:347 #: stock/models.py:342
msgid "Installed In" msgid "Installed In"
msgstr "Installiert in" msgstr "Installiert in"
#: stock/models.py:350 #: stock/models.py:345
msgid "Is this item installed in another item?" msgid "Is this item installed in another item?"
msgstr "Ist dieses Teil in einem anderen verbaut?" msgstr "Ist dieses Teil in einem anderen verbaut?"
#: stock/models.py:366 #: stock/models.py:361
msgid "Serial number for this item" msgid "Serial number for this item"
msgstr "Seriennummer für dieses Teil" msgstr "Seriennummer für dieses Teil"
#: stock/models.py:378 #: stock/models.py:373
msgid "Batch code for this stock item" msgid "Batch code for this stock item"
msgstr "Losnummer für dieses Lagerobjekt" msgstr "Losnummer für dieses Lagerobjekt"
#: stock/models.py:382 #: stock/models.py:377
msgid "Stock Quantity" msgid "Stock Quantity"
msgstr "Bestand" msgstr "Bestand"
#: stock/models.py:391 #: stock/models.py:386
msgid "Source Build" msgid "Source Build"
msgstr "Quellbau" msgstr "Quellbau"
#: stock/models.py:393 #: stock/models.py:388
msgid "Build for this stock item" msgid "Build for this stock item"
msgstr "Bau für dieses Lagerobjekt" msgstr "Bau für dieses Lagerobjekt"
#: stock/models.py:400 #: stock/models.py:395
msgid "Source Purchase Order" msgid "Source Purchase Order"
msgstr "Quellbestellung" msgstr "Quellbestellung"
#: stock/models.py:403 #: stock/models.py:398
msgid "Purchase order for this stock item" msgid "Purchase order for this stock item"
msgstr "Bestellung für dieses Teil" msgstr "Bestellung für dieses Teil"
#: stock/models.py:409 #: stock/models.py:404
msgid "Destination Sales Order" msgid "Destination Sales Order"
msgstr "Zielauftrag" msgstr "Zielauftrag"
#: stock/models.py:416 #: stock/models.py:411
msgid "Destination Build Order" msgid "Destination Build Order"
msgstr "Zielbauauftrag" msgstr "Zielbauauftrag"
#: stock/models.py:429 #: stock/models.py:424
msgid "Delete this Stock Item when stock is depleted" msgid "Delete this Stock Item when stock is depleted"
msgstr "Objekt löschen wenn Lagerbestand aufgebraucht" msgstr "Objekt löschen wenn Lagerbestand aufgebraucht"
#: stock/models.py:439 stock/templates/stock/item_notes.html:14 #: stock/models.py:434 stock/templates/stock/item_notes.html:14
#: stock/templates/stock/item_notes.html:30 #: stock/templates/stock/item_notes.html:30
msgid "Stock Item Notes" msgid "Stock Item Notes"
msgstr "Lagerobjekt-Notizen" msgstr "Lagerobjekt-Notizen"
#: stock/models.py:490 #: stock/models.py:485
#, fuzzy #, fuzzy
#| msgid "Item assigned to customer?" #| msgid "Item assigned to customer?"
msgid "Assigned to Customer" msgid "Assigned to Customer"
msgstr "Ist dieses Objekt einem Kunden zugeteilt?" msgstr "Ist dieses Objekt einem Kunden zugeteilt?"
#: stock/models.py:492 #: stock/models.py:487
#, fuzzy #, fuzzy
#| msgid "Item assigned to customer?" #| msgid "Item assigned to customer?"
msgid "Manually assigned to customer" msgid "Manually assigned to customer"
msgstr "Ist dieses Objekt einem Kunden zugeteilt?" msgstr "Ist dieses Objekt einem Kunden zugeteilt?"
#: stock/models.py:505 #: stock/models.py:500
#, fuzzy #, fuzzy
#| msgid "Item assigned to customer?" #| msgid "Item assigned to customer?"
msgid "Returned from customer" msgid "Returned from customer"
msgstr "Ist dieses Objekt einem Kunden zugeteilt?" msgstr "Ist dieses Objekt einem Kunden zugeteilt?"
#: stock/models.py:507 #: stock/models.py:502
#, fuzzy #, fuzzy
#| msgid "Create new stock location" #| msgid "Create new stock location"
msgid "Returned to location" msgid "Returned to location"
msgstr "Neuen Lagerort anlegen" msgstr "Neuen Lagerort anlegen"
#: stock/models.py:678 #: stock/models.py:673
#, fuzzy #, fuzzy
#| msgid "Part is not a virtual part" #| msgid "Part is not a virtual part"
msgid "Part is not set as trackable" msgid "Part is not set as trackable"
msgstr "Teil ist nicht virtuell" msgstr "Teil ist nicht virtuell"
#: stock/models.py:684 #: stock/models.py:679
msgid "Quantity must be integer" msgid "Quantity must be integer"
msgstr "Anzahl muss eine Ganzzahl sein" msgstr "Anzahl muss eine Ganzzahl sein"
#: stock/models.py:690 #: stock/models.py:685
#, python-brace-format #, python-brace-format
msgid "Quantity must not exceed available stock quantity ({n})" msgid "Quantity must not exceed available stock quantity ({n})"
msgstr "Anzahl darf nicht die verfügbare Anzahl überschreiten ({n})" msgstr "Anzahl darf nicht die verfügbare Anzahl überschreiten ({n})"
#: stock/models.py:693 stock/models.py:696 #: stock/models.py:688 stock/models.py:691
msgid "Serial numbers must be a list of integers" msgid "Serial numbers must be a list of integers"
msgstr "Seriennummern muss eine Liste von Ganzzahlen sein" msgstr "Seriennummern muss eine Liste von Ganzzahlen sein"
#: stock/models.py:699 #: stock/models.py:694
msgid "Quantity does not match serial numbers" msgid "Quantity does not match serial numbers"
msgstr "Anzahl stimmt nicht mit den Seriennummern überein" msgstr "Anzahl stimmt nicht mit den Seriennummern überein"
#: stock/models.py:709 #: stock/models.py:704
msgid "Serial numbers already exist: " msgid "Serial numbers already exist: "
msgstr "Seriennummern existieren bereits:" msgstr "Seriennummern existieren bereits:"
#: stock/models.py:734 #: stock/models.py:729
msgid "Add serial number" msgid "Add serial number"
msgstr "Seriennummer hinzufügen" msgstr "Seriennummer hinzufügen"
#: stock/models.py:737 #: stock/models.py:732
#, python-brace-format #, python-brace-format
msgid "Serialized {n} items" msgid "Serialized {n} items"
msgstr "{n} Teile serialisiert" msgstr "{n} Teile serialisiert"
#: stock/models.py:848 #: stock/models.py:843
msgid "StockItem cannot be moved as it is not in stock" msgid "StockItem cannot be moved as it is not in stock"
msgstr "Lagerobjekt kann nicht bewegt werden, da kein Bestand vorhanden ist" msgstr "Lagerobjekt kann nicht bewegt werden, da kein Bestand vorhanden ist"
#: stock/models.py:1175 #: stock/models.py:1170
msgid "Tracking entry title" msgid "Tracking entry title"
msgstr "Name des Eintrags-Trackings" msgstr "Name des Eintrags-Trackings"
#: stock/models.py:1177 #: stock/models.py:1172
msgid "Entry notes" msgid "Entry notes"
msgstr "Eintrags-Notizen" msgstr "Eintrags-Notizen"
#: stock/models.py:1179 #: stock/models.py:1174
msgid "Link to external page for further information" msgid "Link to external page for further information"
msgstr "Link auf externe Seite für weitere Informationen" msgstr "Link auf externe Seite für weitere Informationen"
#: stock/models.py:1239 #: stock/models.py:1234
#, fuzzy #, fuzzy
#| msgid "Serial number for this item" #| msgid "Serial number for this item"
msgid "Value must be provided for this test" msgid "Value must be provided for this test"
msgstr "Seriennummer für dieses Teil" msgstr "Seriennummer für dieses Teil"
#: stock/models.py:1245 #: stock/models.py:1240
msgid "Attachment must be uploaded for this test" msgid "Attachment must be uploaded for this test"
msgstr "" msgstr ""
#: stock/models.py:1262 #: stock/models.py:1257
msgid "Test" msgid "Test"
msgstr "" msgstr ""
#: stock/models.py:1263 #: stock/models.py:1258
#, fuzzy #, fuzzy
#| msgid "Part name" #| msgid "Part name"
msgid "Test name" msgid "Test name"
msgstr "Name des Teils" msgstr "Name des Teils"
#: stock/models.py:1268 #: stock/models.py:1263
#, fuzzy #, fuzzy
#| msgid "Search Results" #| msgid "Search Results"
msgid "Result" msgid "Result"
msgstr "Suchergebnisse" msgstr "Suchergebnisse"
#: stock/models.py:1269 templates/js/table_filters.html:90 #: stock/models.py:1264 templates/js/table_filters.html:90
msgid "Test result" msgid "Test result"
msgstr "" msgstr ""
#: stock/models.py:1275 #: stock/models.py:1270
msgid "Test output value" msgid "Test output value"
msgstr "" msgstr ""
#: stock/models.py:1281 #: stock/models.py:1276
#, fuzzy #, fuzzy
#| msgid "Attachments" #| msgid "Attachments"
msgid "Attachment" msgid "Attachment"
msgstr "Anhänge" msgstr "Anhänge"
#: stock/models.py:1282 #: stock/models.py:1277
#, fuzzy #, fuzzy
#| msgid "Delete attachment" #| msgid "Delete attachment"
msgid "Test result attachment" msgid "Test result attachment"
msgstr "Anhang löschen" msgstr "Anhang löschen"
#: stock/models.py:1288 #: stock/models.py:1283
#, fuzzy #, fuzzy
#| msgid "Edit notes" #| msgid "Edit notes"
msgid "Test notes" msgid "Test notes"
@ -3257,41 +3350,37 @@ msgstr "Lagerobjekt löschen"
msgid "Generate test report" msgid "Generate test report"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:132 #: stock/templates/stock/item_base.html:137
msgid "Print labels"
msgstr ""
#: stock/templates/stock/item_base.html:140
msgid "Stock Item Details" msgid "Stock Item Details"
msgstr "Lagerbestands-Details" msgstr "Lagerbestands-Details"
#: stock/templates/stock/item_base.html:173 #: stock/templates/stock/item_base.html:170
msgid "Belongs To" msgid "Belongs To"
msgstr "Gehört zu" msgstr "Gehört zu"
#: stock/templates/stock/item_base.html:195 #: stock/templates/stock/item_base.html:192
#, fuzzy #, fuzzy
#| msgid "No stock location set" #| msgid "No stock location set"
msgid "No location set" msgid "No location set"
msgstr "Kein Lagerort gesetzt" msgstr "Kein Lagerort gesetzt"
#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/item_base.html:199
msgid "Unique Identifier" msgid "Unique Identifier"
msgstr "Eindeutiger Bezeichner" msgstr "Eindeutiger Bezeichner"
#: stock/templates/stock/item_base.html:230 #: stock/templates/stock/item_base.html:227
msgid "Parent Item" msgid "Parent Item"
msgstr "Elternposition" msgstr "Elternposition"
#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/item_base.html:252
msgid "Last Updated" msgid "Last Updated"
msgstr "Zuletzt aktualisiert" msgstr "Zuletzt aktualisiert"
#: stock/templates/stock/item_base.html:260 #: stock/templates/stock/item_base.html:257
msgid "Last Stocktake" msgid "Last Stocktake"
msgstr "Letzte Inventur" msgstr "Letzte Inventur"
#: stock/templates/stock/item_base.html:264 #: stock/templates/stock/item_base.html:261
msgid "No stocktake performed" msgid "No stocktake performed"
msgstr "Keine Inventur ausgeführt" msgstr "Keine Inventur ausgeführt"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-16 02:11+0000\n" "POT-Creation-Date: 2020-08-18 04:01+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -42,30 +42,30 @@ msgstr ""
msgid "Confirm new password" msgid "Confirm new password"
msgstr "" msgstr ""
#: InvenTree/helpers.py:328 order/models.py:187 order/models.py:261 #: InvenTree/helpers.py:336 order/models.py:187 order/models.py:261
msgid "Invalid quantity provided" msgid "Invalid quantity provided"
msgstr "" msgstr ""
#: InvenTree/helpers.py:331 #: InvenTree/helpers.py:339
msgid "Empty serial number string" msgid "Empty serial number string"
msgstr "" msgstr ""
#: InvenTree/helpers.py:352 InvenTree/helpers.py:369 #: InvenTree/helpers.py:360 InvenTree/helpers.py:377
#, python-brace-format #, python-brace-format
msgid "Duplicate serial: {n}" msgid "Duplicate serial: {n}"
msgstr "" msgstr ""
#: InvenTree/helpers.py:356 InvenTree/helpers.py:359 InvenTree/helpers.py:362 #: InvenTree/helpers.py:364 InvenTree/helpers.py:367 InvenTree/helpers.py:370
#: InvenTree/helpers.py:373 #: InvenTree/helpers.py:381
#, python-brace-format #, python-brace-format
msgid "Invalid group: {g}" msgid "Invalid group: {g}"
msgstr "" msgstr ""
#: InvenTree/helpers.py:379 #: InvenTree/helpers.py:387
msgid "No serial numbers found" msgid "No serial numbers found"
msgstr "" msgstr ""
#: InvenTree/helpers.py:383 #: InvenTree/helpers.py:391
#, python-brace-format #, python-brace-format
msgid "Number of unique serial number ({s}) must match quantity ({q})" msgid "Number of unique serial number ({s}) must match quantity ({q})"
msgstr "" msgstr ""
@ -322,7 +322,7 @@ msgstr ""
msgid "Build status code" msgid "Build status code"
msgstr "" msgstr ""
#: build/models.py:136 stock/models.py:376 #: build/models.py:136 stock/models.py:371
msgid "Batch Code" msgid "Batch Code"
msgstr "" msgstr ""
@ -334,11 +334,11 @@ msgstr ""
#: company/templates/company/supplier_part_base.html:60 #: company/templates/company/supplier_part_base.html:60
#: company/templates/company/supplier_part_detail.html:24 #: company/templates/company/supplier_part_detail.html:24
#: part/templates/part/detail.html:74 part/templates/part/part_base.html:86 #: part/templates/part/detail.html:74 part/templates/part/part_base.html:86
#: stock/models.py:370 stock/templates/stock/item_base.html:237 #: stock/models.py:365 stock/templates/stock/item_base.html:234
msgid "External Link" msgid "External Link"
msgstr "" msgstr ""
#: build/models.py:156 stock/models.py:372 #: build/models.py:156 stock/models.py:367
msgid "Link to external URL" msgid "Link to external URL"
msgstr "" msgstr ""
@ -346,7 +346,7 @@ msgstr ""
#: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:15 #: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:15
#: order/templates/order/purchase_order_detail.html:200 #: order/templates/order/purchase_order_detail.html:200
#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:64 #: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:64
#: stock/models.py:438 stock/models.py:1287 stock/templates/stock/tabs.html:26 #: stock/models.py:433 stock/models.py:1282 stock/templates/stock/tabs.html:26
#: templates/js/barcode.html:391 templates/js/bom.html:229 #: templates/js/barcode.html:391 templates/js/bom.html:229
#: templates/js/stock.html:114 templates/js/stock.html:526 #: templates/js/stock.html:114 templates/js/stock.html:526
msgid "Notes" msgid "Notes"
@ -413,8 +413,8 @@ msgstr ""
#: build/templates/build/allocate.html:161 #: build/templates/build/allocate.html:161
#: order/templates/order/sales_order_detail.html:68 #: order/templates/order/sales_order_detail.html:68
#: order/templates/order/sales_order_detail.html:150 stock/models.py:364 #: order/templates/order/sales_order_detail.html:150 stock/models.py:359
#: stock/templates/stock/item_base.html:153 #: stock/templates/stock/item_base.html:150
msgid "Serial Number" msgid "Serial Number"
msgstr "" msgstr ""
@ -431,7 +431,7 @@ msgstr ""
#: part/templates/part/allocation.html:49 #: part/templates/part/allocation.html:49
#: stock/templates/stock/item_base.html:26 #: stock/templates/stock/item_base.html:26
#: stock/templates/stock/item_base.html:32 #: stock/templates/stock/item_base.html:32
#: stock/templates/stock/item_base.html:159 #: stock/templates/stock/item_base.html:156
#: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338
#: templates/js/bom.html:172 templates/js/build.html:52 #: templates/js/bom.html:172 templates/js/build.html:52
#: templates/js/stock.html:673 #: templates/js/stock.html:673
@ -440,7 +440,7 @@ msgstr ""
#: build/templates/build/allocate.html:177 #: build/templates/build/allocate.html:177
#: build/templates/build/auto_allocate.html:20 #: build/templates/build/auto_allocate.html:20
#: stock/templates/stock/item_base.html:191 #: stock/templates/stock/item_base.html:188
#: stock/templates/stock/stock_adjust.html:17 templates/js/barcode.html:337 #: stock/templates/stock/stock_adjust.html:17 templates/js/barcode.html:337
#: templates/js/stock.html:508 #: templates/js/stock.html:508
msgid "Location" msgid "Location"
@ -478,7 +478,7 @@ msgstr ""
msgid "Reference" msgid "Reference"
msgstr "" msgstr ""
#: build/templates/build/allocate.html:338 part/models.py:1270 #: build/templates/build/allocate.html:338 part/models.py:1271
#: templates/js/part.html:359 templates/js/table_filters.html:100 #: templates/js/part.html:359 templates/js/table_filters.html:100
msgid "Required" msgid "Required"
msgstr "" msgstr ""
@ -522,7 +522,7 @@ msgstr ""
#: build/templates/build/build_base.html:8 #: build/templates/build/build_base.html:8
#: build/templates/build/build_base.html:34 #: build/templates/build/build_base.html:34
#: build/templates/build/complete.html:6 #: build/templates/build/complete.html:6
#: stock/templates/stock/item_base.html:216 templates/js/build.html:33 #: stock/templates/stock/item_base.html:213 templates/js/build.html:33
#: templates/navbar.html:12 #: templates/navbar.html:12
msgid "Build" msgid "Build"
msgstr "" msgstr ""
@ -542,7 +542,7 @@ msgstr ""
#: build/templates/build/build_base.html:80 #: build/templates/build/build_base.html:80
#: build/templates/build/detail.html:42 #: build/templates/build/detail.html:42
#: order/templates/order/receive_parts.html:24 #: order/templates/order/receive_parts.html:24
#: stock/templates/stock/item_base.html:269 templates/js/barcode.html:42 #: stock/templates/stock/item_base.html:266 templates/js/barcode.html:42
#: templates/js/build.html:57 templates/js/order.html:162 #: templates/js/build.html:57 templates/js/order.html:162
#: templates/js/order.html:235 templates/js/stock.html:495 #: templates/js/order.html:235 templates/js/stock.html:495
msgid "Status" msgid "Status"
@ -554,7 +554,7 @@ msgstr ""
#: order/templates/order/sales_order_notes.html:10 #: order/templates/order/sales_order_notes.html:10
#: order/templates/order/sales_order_ship.html:25 #: order/templates/order/sales_order_ship.html:25
#: part/templates/part/allocation.html:27 #: part/templates/part/allocation.html:27
#: stock/templates/stock/item_base.html:179 templates/js/order.html:209 #: stock/templates/stock/item_base.html:176 templates/js/order.html:209
msgid "Sales Order" msgid "Sales Order"
msgstr "" msgstr ""
@ -621,7 +621,7 @@ msgid "Stock can be taken from any available location."
msgstr "" msgstr ""
#: build/templates/build/detail.html:48 #: build/templates/build/detail.html:48
#: stock/templates/stock/item_base.html:209 templates/js/stock.html:503 #: stock/templates/stock/item_base.html:206 templates/js/stock.html:503
msgid "Batch" msgid "Batch"
msgstr "" msgstr ""
@ -910,8 +910,8 @@ msgstr ""
msgid "Does this company manufacture parts?" msgid "Does this company manufacture parts?"
msgstr "" msgstr ""
#: company/models.py:279 stock/models.py:324 #: company/models.py:279 stock/models.py:319
#: stock/templates/stock/item_base.html:145 #: stock/templates/stock/item_base.html:142
msgid "Base Part" msgid "Base Part"
msgstr "" msgstr ""
@ -982,14 +982,14 @@ msgstr ""
#: company/templates/company/supplier_part_detail.html:21 order/models.py:148 #: company/templates/company/supplier_part_detail.html:21 order/models.py:148
#: order/templates/order/order_base.html:74 #: order/templates/order/order_base.html:74
#: order/templates/order/order_wizard/select_pos.html:30 #: order/templates/order/order_wizard/select_pos.html:30
#: stock/templates/stock/item_base.html:244 templates/js/company.html:52 #: stock/templates/stock/item_base.html:241 templates/js/company.html:52
#: templates/js/company.html:134 templates/js/order.html:144 #: templates/js/company.html:134 templates/js/order.html:144
msgid "Supplier" msgid "Supplier"
msgstr "" msgstr ""
#: company/templates/company/detail.html:26 order/models.py:314 #: company/templates/company/detail.html:26 order/models.py:314
#: order/templates/order/sales_order_base.html:73 stock/models.py:359 #: order/templates/order/sales_order_base.html:73 stock/models.py:354
#: stock/models.py:360 stock/templates/stock/item_base.html:166 #: stock/models.py:355 stock/templates/stock/item_base.html:163
#: templates/js/company.html:44 templates/js/order.html:217 #: templates/js/company.html:44 templates/js/order.html:217
msgid "Customer" msgid "Customer"
msgstr "" msgstr ""
@ -1102,8 +1102,8 @@ msgid "New Sales Order"
msgstr "" msgstr ""
#: company/templates/company/supplier_part_base.html:6 #: company/templates/company/supplier_part_base.html:6
#: company/templates/company/supplier_part_base.html:19 stock/models.py:333 #: company/templates/company/supplier_part_base.html:19 stock/models.py:328
#: stock/templates/stock/item_base.html:249 templates/js/company.html:150 #: stock/templates/stock/item_base.html:246 templates/js/company.html:150
msgid "Supplier Part" msgid "Supplier Part"
msgstr "" msgstr ""
@ -1367,8 +1367,8 @@ msgstr ""
msgid "Supplier order reference code" msgid "Supplier order reference code"
msgstr "" msgstr ""
#: order/models.py:185 order/models.py:259 part/views.py:1167 #: order/models.py:185 order/models.py:259 part/views.py:1250
#: stock/models.py:238 stock/models.py:687 #: stock/models.py:239 stock/models.py:682
msgid "Quantity must be greater than zero" msgid "Quantity must be greater than zero"
msgstr "" msgstr ""
@ -1402,7 +1402,7 @@ msgstr ""
#: order/models.py:466 order/templates/order/order_base.html:9 #: order/models.py:466 order/templates/order/order_base.html:9
#: order/templates/order/order_base.html:23 #: order/templates/order/order_base.html:23
#: stock/templates/stock/item_base.html:223 templates/js/order.html:136 #: stock/templates/stock/item_base.html:220 templates/js/order.html:136
msgid "Purchase Order" msgid "Purchase Order"
msgstr "" msgstr ""
@ -1819,16 +1819,16 @@ msgstr ""
msgid "Remove allocation" msgid "Remove allocation"
msgstr "" msgstr ""
#: part/bom.py:140 #: part/bom.py:144
#, python-brace-format #, python-brace-format
msgid "Unsupported file format: {f}" msgid "Unsupported file format: {f}"
msgstr "" msgstr ""
#: part/bom.py:145 #: part/bom.py:149
msgid "Error reading BOM file (invalid data)" msgid "Error reading BOM file (invalid data)"
msgstr "" msgstr ""
#: part/bom.py:147 #: part/bom.py:151
msgid "Error reading BOM file (incorrect row size)" msgid "Error reading BOM file (incorrect row size)"
msgstr "" msgstr ""
@ -1848,31 +1848,39 @@ msgstr ""
msgid "Download cascading / multi-level BOM" msgid "Download cascading / multi-level BOM"
msgstr "" msgstr ""
#: part/forms.py:76 #: part/forms.py:59
msgid "Levels"
msgstr ""
#: part/forms.py:59
msgid "Select maximum number of BOM levels to export (0 = all levels)"
msgstr ""
#: part/forms.py:78
msgid "Confirm that the BOM is correct" msgid "Confirm that the BOM is correct"
msgstr "" msgstr ""
#: part/forms.py:88 #: part/forms.py:90
msgid "Select BOM file to upload" msgid "Select BOM file to upload"
msgstr "" msgstr ""
#: part/forms.py:112 #: part/forms.py:114
msgid "Select part category" msgid "Select part category"
msgstr "" msgstr ""
#: part/forms.py:126 #: part/forms.py:128
msgid "Perform 'deep copy' which will duplicate all BOM data for this part" msgid "Perform 'deep copy' which will duplicate all BOM data for this part"
msgstr "" msgstr ""
#: part/forms.py:131 #: part/forms.py:133
msgid "Confirm part creation" msgid "Confirm part creation"
msgstr "" msgstr ""
#: part/forms.py:221 #: part/forms.py:223
msgid "Input quantity for price calculation" msgid "Input quantity for price calculation"
msgstr "" msgstr ""
#: part/forms.py:224 #: part/forms.py:226
msgid "Select currency for price calculation" msgid "Select currency for price calculation"
msgstr "" msgstr ""
@ -1985,116 +1993,117 @@ msgstr ""
msgid "Stored BOM checksum" msgid "Stored BOM checksum"
msgstr "" msgstr ""
#: part/models.py:1222 #: part/models.py:1223
msgid "Test templates can only be created for trackable parts" msgid "Test templates can only be created for trackable parts"
msgstr "" msgstr ""
#: part/models.py:1239 #: part/models.py:1240
msgid "Test with this name already exists for this part" msgid "Test with this name already exists for this part"
msgstr "" msgstr ""
#: part/models.py:1258 templates/js/part.html:350 templates/js/stock.html:90 #: part/models.py:1259 templates/js/part.html:350 templates/js/stock.html:90
msgid "Test Name" msgid "Test Name"
msgstr "" msgstr ""
#: part/models.py:1259 #: part/models.py:1260
msgid "Enter a name for the test" msgid "Enter a name for the test"
msgstr "" msgstr ""
#: part/models.py:1264 #: part/models.py:1265
msgid "Test Description" msgid "Test Description"
msgstr "" msgstr ""
#: part/models.py:1265 #: part/models.py:1266
msgid "Enter description for this test" msgid "Enter description for this test"
msgstr "" msgstr ""
#: part/models.py:1271 #: part/models.py:1272
msgid "Is this test required to pass?" msgid "Is this test required to pass?"
msgstr "" msgstr ""
#: part/models.py:1276 templates/js/part.html:367 #: part/models.py:1277 templates/js/part.html:367
msgid "Requires Value" msgid "Requires Value"
msgstr "" msgstr ""
#: part/models.py:1277 #: part/models.py:1278
msgid "Does this test require a value when adding a test result?" msgid "Does this test require a value when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1282 templates/js/part.html:374 #: part/models.py:1283 templates/js/part.html:374
msgid "Requires Attachment" msgid "Requires Attachment"
msgstr "" msgstr ""
#: part/models.py:1283 #: part/models.py:1284
msgid "Does this test require a file attachment when adding a test result?" msgid "Does this test require a file attachment when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1316 #: part/models.py:1317
msgid "Parameter template name must be unique" msgid "Parameter template name must be unique"
msgstr "" msgstr ""
#: part/models.py:1321 #: part/models.py:1322
msgid "Parameter Name" msgid "Parameter Name"
msgstr "" msgstr ""
#: part/models.py:1323 #: part/models.py:1324
msgid "Parameter Units" msgid "Parameter Units"
msgstr "" msgstr ""
#: part/models.py:1349 #: part/models.py:1350
msgid "Parent Part" msgid "Parent Part"
msgstr "" msgstr ""
#: part/models.py:1351 #: part/models.py:1352
msgid "Parameter Template" msgid "Parameter Template"
msgstr "" msgstr ""
#: part/models.py:1353 #: part/models.py:1354
msgid "Parameter Value" msgid "Parameter Value"
msgstr "" msgstr ""
#: part/models.py:1382 #: part/models.py:1383
msgid "Select parent part" msgid "Select parent part"
msgstr "" msgstr ""
#: part/models.py:1390 #: part/models.py:1391
msgid "Select part to be used in BOM" msgid "Select part to be used in BOM"
msgstr "" msgstr ""
#: part/models.py:1396 #: part/models.py:1397
msgid "BOM quantity for this BOM item" msgid "BOM quantity for this BOM item"
msgstr "" msgstr ""
#: part/models.py:1399 #: part/models.py:1400
msgid "Estimated build wastage quantity (absolute or percentage)" msgid "Estimated build wastage quantity (absolute or percentage)"
msgstr "" msgstr ""
#: part/models.py:1402 #: part/models.py:1403
msgid "BOM item reference" msgid "BOM item reference"
msgstr "" msgstr ""
#: part/models.py:1405 #: part/models.py:1406
msgid "BOM item notes" msgid "BOM item notes"
msgstr "" msgstr ""
#: part/models.py:1407 #: part/models.py:1408
msgid "BOM line checksum" msgid "BOM line checksum"
msgstr "" msgstr ""
#: part/models.py:1471 stock/models.py:228 #: part/models.py:1472 part/views.py:1256 part/views.py:1308
#: stock/models.py:229
msgid "Quantity must be integer value for trackable parts" msgid "Quantity must be integer value for trackable parts"
msgstr "" msgstr ""
#: part/models.py:1480 #: part/models.py:1481
msgid "Part cannot be added to its own Bill of Materials" msgid "Part cannot be added to its own Bill of Materials"
msgstr "" msgstr ""
#: part/models.py:1487 #: part/models.py:1488
#, python-brace-format #, python-brace-format
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
msgstr "" msgstr ""
#: part/models.py:1494 #: part/models.py:1495
msgid "BOM Item" msgid "BOM Item"
msgstr "" msgstr ""
@ -2113,14 +2122,14 @@ msgstr ""
#: part/templates/part/allocation.html:45 #: part/templates/part/allocation.html:45
#: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:8
#: stock/templates/stock/item_base.html:58 #: stock/templates/stock/item_base.html:58
#: stock/templates/stock/item_base.html:231 #: stock/templates/stock/item_base.html:228
#: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106
#: templates/js/stock.html:643 #: templates/js/stock.html:643
msgid "Stock Item" msgid "Stock Item"
msgstr "" msgstr ""
#: part/templates/part/allocation.html:20 #: part/templates/part/allocation.html:20
#: stock/templates/stock/item_base.html:185 #: stock/templates/stock/item_base.html:182
msgid "Build Order" msgid "Build Order"
msgstr "" msgstr ""
@ -2156,10 +2165,78 @@ msgstr ""
msgid "Validate Bill of Materials" msgid "Validate Bill of Materials"
msgstr "" msgstr ""
#: part/templates/part/bom.html:46 part/views.py:1412 #: part/templates/part/bom.html:46 part/views.py:1523
msgid "Export Bill of Materials" msgid "Export Bill of Materials"
msgstr "" msgstr ""
#: part/templates/part/bom_upload/select_fields.html:8
#: part/templates/part/bom_upload/select_parts.html:8
#: part/templates/part/bom_upload/upload_file.html:10
msgid "Upload Bill of Materials"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:10
msgid "Step 2 - Select Fields"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:15
msgid "Missing selections for the following required columns"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:26
msgid "Submit Selections"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:35
msgid "File Fields"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:52
msgid "Match Fields"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:10
msgid "Step 3 - Select Parts"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:15
msgid "Errors exist in the submitted data"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:21
msgid "Submit BOM"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:33
msgid "Row"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:34
#: part/templates/part/bom_upload/select_parts.html:63
msgid "Select Part"
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:13
msgid "Step 1 - Select BOM File"
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:16
msgid "Requirements for BOM upload"
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:18
msgid ""
"The BOM file must contain the required named columns as provided in the "
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:18
msgid "BOM Upload Template"
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:19
msgid "Each part must already exist in the database"
msgstr ""
#: part/templates/part/category.html:14 #: part/templates/part/category.html:14
msgid "All parts" msgid "All parts"
msgstr "" msgstr ""
@ -2354,7 +2431,7 @@ msgstr ""
msgid "New Parameter" msgid "New Parameter"
msgstr "" msgstr ""
#: part/templates/part/params.html:21 stock/models.py:1274 #: part/templates/part/params.html:21 stock/models.py:1269
#: templates/js/stock.html:110 #: templates/js/stock.html:110
msgid "Value" msgid "Value"
msgstr "" msgstr ""
@ -2535,7 +2612,7 @@ msgstr ""
msgid "Used In" msgid "Used In"
msgstr "" msgstr ""
#: part/templates/part/tabs.html:55 stock/templates/stock/item_base.html:275 #: part/templates/part/tabs.html:55 stock/templates/stock/item_base.html:272
msgid "Tests" msgid "Tests"
msgstr "" msgstr ""
@ -2640,91 +2717,91 @@ msgstr ""
msgid "Validate BOM" msgid "Validate BOM"
msgstr "" msgstr ""
#: part/views.py:908 #: part/views.py:909
msgid "No BOM file provided" msgid "No BOM file provided"
msgstr "" msgstr ""
#: part/views.py:1169 #: part/views.py:1259
msgid "Enter a valid quantity" msgid "Enter a valid quantity"
msgstr "" msgstr ""
#: part/views.py:1193 part/views.py:1196 #: part/views.py:1284 part/views.py:1287
msgid "Select valid part" msgid "Select valid part"
msgstr "" msgstr ""
#: part/views.py:1202 #: part/views.py:1293
msgid "Duplicate part selected" msgid "Duplicate part selected"
msgstr "" msgstr ""
#: part/views.py:1230 #: part/views.py:1329
msgid "Select a part" msgid "Select a part"
msgstr "" msgstr ""
#: part/views.py:1234 #: part/views.py:1333
msgid "Specify quantity" msgid "Specify quantity"
msgstr "" msgstr ""
#: part/views.py:1450 #: part/views.py:1565
msgid "Confirm Part Deletion" msgid "Confirm Part Deletion"
msgstr "" msgstr ""
#: part/views.py:1457 #: part/views.py:1572
msgid "Part was deleted" msgid "Part was deleted"
msgstr "" msgstr ""
#: part/views.py:1466 #: part/views.py:1581
msgid "Part Pricing" msgid "Part Pricing"
msgstr "" msgstr ""
#: part/views.py:1588 #: part/views.py:1703
msgid "Create Part Parameter Template" msgid "Create Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1596 #: part/views.py:1711
msgid "Edit Part Parameter Template" msgid "Edit Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1603 #: part/views.py:1718
msgid "Delete Part Parameter Template" msgid "Delete Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1611 #: part/views.py:1726
msgid "Create Part Parameter" msgid "Create Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1661 #: part/views.py:1776
msgid "Edit Part Parameter" msgid "Edit Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1675 #: part/views.py:1790
msgid "Delete Part Parameter" msgid "Delete Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1691 #: part/views.py:1806
msgid "Edit Part Category" msgid "Edit Part Category"
msgstr "" msgstr ""
#: part/views.py:1726 #: part/views.py:1841
msgid "Delete Part Category" msgid "Delete Part Category"
msgstr "" msgstr ""
#: part/views.py:1732 #: part/views.py:1847
msgid "Part category was deleted" msgid "Part category was deleted"
msgstr "" msgstr ""
#: part/views.py:1740 #: part/views.py:1855
msgid "Create new part category" msgid "Create new part category"
msgstr "" msgstr ""
#: part/views.py:1791 #: part/views.py:1906
msgid "Create BOM item" msgid "Create BOM item"
msgstr "" msgstr ""
#: part/views.py:1857 #: part/views.py:1972
msgid "Edit BOM item" msgid "Edit BOM item"
msgstr "" msgstr ""
#: part/views.py:1905 #: part/views.py:2020
msgid "Confim BOM item deletion" msgid "Confim BOM item deletion"
msgstr "" msgstr ""
@ -2776,203 +2853,203 @@ msgstr ""
msgid "Set the destination as the default location for selected parts" msgid "Set the destination as the default location for selected parts"
msgstr "" msgstr ""
#: stock/models.py:209 #: stock/models.py:210
msgid "StockItem with this serial number already exists" msgid "StockItem with this serial number already exists"
msgstr "" msgstr ""
#: stock/models.py:245 #: stock/models.py:246
#, python-brace-format #, python-brace-format
msgid "Part type ('{pf}') must be {pe}" msgid "Part type ('{pf}') must be {pe}"
msgstr "" msgstr ""
#: stock/models.py:255 stock/models.py:264 #: stock/models.py:256 stock/models.py:265
msgid "Quantity must be 1 for item with a serial number" msgid "Quantity must be 1 for item with a serial number"
msgstr "" msgstr ""
#: stock/models.py:256 #: stock/models.py:257
msgid "Serial number cannot be set if quantity greater than 1" msgid "Serial number cannot be set if quantity greater than 1"
msgstr "" msgstr ""
#: stock/models.py:277 #: stock/models.py:278
msgid "Item cannot belong to itself" msgid "Item cannot belong to itself"
msgstr "" msgstr ""
#: stock/models.py:316 #: stock/models.py:311
msgid "Parent Stock Item" msgid "Parent Stock Item"
msgstr "" msgstr ""
#: stock/models.py:325 #: stock/models.py:320
msgid "Base part" msgid "Base part"
msgstr "" msgstr ""
#: stock/models.py:334 #: stock/models.py:329
msgid "Select a matching supplier part for this stock item" msgid "Select a matching supplier part for this stock item"
msgstr "" msgstr ""
#: stock/models.py:339 stock/templates/stock/stock_app_base.html:7 #: stock/models.py:334 stock/templates/stock/stock_app_base.html:7
msgid "Stock Location" msgid "Stock Location"
msgstr "" msgstr ""
#: stock/models.py:342 #: stock/models.py:337
msgid "Where is this stock item located?" msgid "Where is this stock item located?"
msgstr "" msgstr ""
#: stock/models.py:347 #: stock/models.py:342
msgid "Installed In" msgid "Installed In"
msgstr "" msgstr ""
#: stock/models.py:350 #: stock/models.py:345
msgid "Is this item installed in another item?" msgid "Is this item installed in another item?"
msgstr "" msgstr ""
#: stock/models.py:366 #: stock/models.py:361
msgid "Serial number for this item" msgid "Serial number for this item"
msgstr "" msgstr ""
#: stock/models.py:378 #: stock/models.py:373
msgid "Batch code for this stock item" msgid "Batch code for this stock item"
msgstr "" msgstr ""
#: stock/models.py:382 #: stock/models.py:377
msgid "Stock Quantity" msgid "Stock Quantity"
msgstr "" msgstr ""
#: stock/models.py:391 #: stock/models.py:386
msgid "Source Build" msgid "Source Build"
msgstr "" msgstr ""
#: stock/models.py:393 #: stock/models.py:388
msgid "Build for this stock item" msgid "Build for this stock item"
msgstr "" msgstr ""
#: stock/models.py:400 #: stock/models.py:395
msgid "Source Purchase Order" msgid "Source Purchase Order"
msgstr "" msgstr ""
#: stock/models.py:403 #: stock/models.py:398
msgid "Purchase order for this stock item" msgid "Purchase order for this stock item"
msgstr "" msgstr ""
#: stock/models.py:409 #: stock/models.py:404
msgid "Destination Sales Order" msgid "Destination Sales Order"
msgstr "" msgstr ""
#: stock/models.py:416 #: stock/models.py:411
msgid "Destination Build Order" msgid "Destination Build Order"
msgstr "" msgstr ""
#: stock/models.py:429 #: stock/models.py:424
msgid "Delete this Stock Item when stock is depleted" msgid "Delete this Stock Item when stock is depleted"
msgstr "" msgstr ""
#: stock/models.py:439 stock/templates/stock/item_notes.html:14 #: stock/models.py:434 stock/templates/stock/item_notes.html:14
#: stock/templates/stock/item_notes.html:30 #: stock/templates/stock/item_notes.html:30
msgid "Stock Item Notes" msgid "Stock Item Notes"
msgstr "" msgstr ""
#: stock/models.py:490 #: stock/models.py:485
msgid "Assigned to Customer" msgid "Assigned to Customer"
msgstr "" msgstr ""
#: stock/models.py:492 #: stock/models.py:487
msgid "Manually assigned to customer" msgid "Manually assigned to customer"
msgstr "" msgstr ""
#: stock/models.py:505 #: stock/models.py:500
msgid "Returned from customer" msgid "Returned from customer"
msgstr "" msgstr ""
#: stock/models.py:507 #: stock/models.py:502
msgid "Returned to location" msgid "Returned to location"
msgstr "" msgstr ""
#: stock/models.py:678 #: stock/models.py:673
msgid "Part is not set as trackable" msgid "Part is not set as trackable"
msgstr "" msgstr ""
#: stock/models.py:684 #: stock/models.py:679
msgid "Quantity must be integer" msgid "Quantity must be integer"
msgstr "" msgstr ""
#: stock/models.py:690 #: stock/models.py:685
#, python-brace-format #, python-brace-format
msgid "Quantity must not exceed available stock quantity ({n})" msgid "Quantity must not exceed available stock quantity ({n})"
msgstr "" msgstr ""
#: stock/models.py:693 stock/models.py:696 #: stock/models.py:688 stock/models.py:691
msgid "Serial numbers must be a list of integers" msgid "Serial numbers must be a list of integers"
msgstr "" msgstr ""
#: stock/models.py:699 #: stock/models.py:694
msgid "Quantity does not match serial numbers" msgid "Quantity does not match serial numbers"
msgstr "" msgstr ""
#: stock/models.py:709 #: stock/models.py:704
msgid "Serial numbers already exist: " msgid "Serial numbers already exist: "
msgstr "" msgstr ""
#: stock/models.py:734 #: stock/models.py:729
msgid "Add serial number" msgid "Add serial number"
msgstr "" msgstr ""
#: stock/models.py:737 #: stock/models.py:732
#, python-brace-format #, python-brace-format
msgid "Serialized {n} items" msgid "Serialized {n} items"
msgstr "" msgstr ""
#: stock/models.py:848 #: stock/models.py:843
msgid "StockItem cannot be moved as it is not in stock" msgid "StockItem cannot be moved as it is not in stock"
msgstr "" msgstr ""
#: stock/models.py:1175 #: stock/models.py:1170
msgid "Tracking entry title" msgid "Tracking entry title"
msgstr "" msgstr ""
#: stock/models.py:1177 #: stock/models.py:1172
msgid "Entry notes" msgid "Entry notes"
msgstr "" msgstr ""
#: stock/models.py:1179 #: stock/models.py:1174
msgid "Link to external page for further information" msgid "Link to external page for further information"
msgstr "" msgstr ""
#: stock/models.py:1239 #: stock/models.py:1234
msgid "Value must be provided for this test" msgid "Value must be provided for this test"
msgstr "" msgstr ""
#: stock/models.py:1245 #: stock/models.py:1240
msgid "Attachment must be uploaded for this test" msgid "Attachment must be uploaded for this test"
msgstr "" msgstr ""
#: stock/models.py:1262 #: stock/models.py:1257
msgid "Test" msgid "Test"
msgstr "" msgstr ""
#: stock/models.py:1263 #: stock/models.py:1258
msgid "Test name" msgid "Test name"
msgstr "" msgstr ""
#: stock/models.py:1268 #: stock/models.py:1263
msgid "Result" msgid "Result"
msgstr "" msgstr ""
#: stock/models.py:1269 templates/js/table_filters.html:90 #: stock/models.py:1264 templates/js/table_filters.html:90
msgid "Test result" msgid "Test result"
msgstr "" msgstr ""
#: stock/models.py:1275 #: stock/models.py:1270
msgid "Test output value" msgid "Test output value"
msgstr "" msgstr ""
#: stock/models.py:1281 #: stock/models.py:1276
msgid "Attachment" msgid "Attachment"
msgstr "" msgstr ""
#: stock/models.py:1282 #: stock/models.py:1277
msgid "Test result attachment" msgid "Test result attachment"
msgstr "" msgstr ""
#: stock/models.py:1288 #: stock/models.py:1283
msgid "Test notes" msgid "Test notes"
msgstr "" msgstr ""
@ -3078,39 +3155,35 @@ msgstr ""
msgid "Generate test report" msgid "Generate test report"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:132 #: stock/templates/stock/item_base.html:137
msgid "Print labels"
msgstr ""
#: stock/templates/stock/item_base.html:140
msgid "Stock Item Details" msgid "Stock Item Details"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:173 #: stock/templates/stock/item_base.html:170
msgid "Belongs To" msgid "Belongs To"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:195 #: stock/templates/stock/item_base.html:192
msgid "No location set" msgid "No location set"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/item_base.html:199
msgid "Unique Identifier" msgid "Unique Identifier"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:230 #: stock/templates/stock/item_base.html:227
msgid "Parent Item" msgid "Parent Item"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/item_base.html:252
msgid "Last Updated" msgid "Last Updated"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:260 #: stock/templates/stock/item_base.html:257
msgid "Last Stocktake" msgid "Last Stocktake"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:264 #: stock/templates/stock/item_base.html:261
msgid "No stocktake performed" msgid "No stocktake performed"
msgstr "" msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-08-16 02:11+0000\n" "POT-Creation-Date: 2020-08-18 04:01+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -42,30 +42,30 @@ msgstr ""
msgid "Confirm new password" msgid "Confirm new password"
msgstr "" msgstr ""
#: InvenTree/helpers.py:328 order/models.py:187 order/models.py:261 #: InvenTree/helpers.py:336 order/models.py:187 order/models.py:261
msgid "Invalid quantity provided" msgid "Invalid quantity provided"
msgstr "" msgstr ""
#: InvenTree/helpers.py:331 #: InvenTree/helpers.py:339
msgid "Empty serial number string" msgid "Empty serial number string"
msgstr "" msgstr ""
#: InvenTree/helpers.py:352 InvenTree/helpers.py:369 #: InvenTree/helpers.py:360 InvenTree/helpers.py:377
#, python-brace-format #, python-brace-format
msgid "Duplicate serial: {n}" msgid "Duplicate serial: {n}"
msgstr "" msgstr ""
#: InvenTree/helpers.py:356 InvenTree/helpers.py:359 InvenTree/helpers.py:362 #: InvenTree/helpers.py:364 InvenTree/helpers.py:367 InvenTree/helpers.py:370
#: InvenTree/helpers.py:373 #: InvenTree/helpers.py:381
#, python-brace-format #, python-brace-format
msgid "Invalid group: {g}" msgid "Invalid group: {g}"
msgstr "" msgstr ""
#: InvenTree/helpers.py:379 #: InvenTree/helpers.py:387
msgid "No serial numbers found" msgid "No serial numbers found"
msgstr "" msgstr ""
#: InvenTree/helpers.py:383 #: InvenTree/helpers.py:391
#, python-brace-format #, python-brace-format
msgid "Number of unique serial number ({s}) must match quantity ({q})" msgid "Number of unique serial number ({s}) must match quantity ({q})"
msgstr "" msgstr ""
@ -322,7 +322,7 @@ msgstr ""
msgid "Build status code" msgid "Build status code"
msgstr "" msgstr ""
#: build/models.py:136 stock/models.py:376 #: build/models.py:136 stock/models.py:371
msgid "Batch Code" msgid "Batch Code"
msgstr "" msgstr ""
@ -334,11 +334,11 @@ msgstr ""
#: company/templates/company/supplier_part_base.html:60 #: company/templates/company/supplier_part_base.html:60
#: company/templates/company/supplier_part_detail.html:24 #: company/templates/company/supplier_part_detail.html:24
#: part/templates/part/detail.html:74 part/templates/part/part_base.html:86 #: part/templates/part/detail.html:74 part/templates/part/part_base.html:86
#: stock/models.py:370 stock/templates/stock/item_base.html:237 #: stock/models.py:365 stock/templates/stock/item_base.html:234
msgid "External Link" msgid "External Link"
msgstr "" msgstr ""
#: build/models.py:156 stock/models.py:372 #: build/models.py:156 stock/models.py:367
msgid "Link to external URL" msgid "Link to external URL"
msgstr "" msgstr ""
@ -346,7 +346,7 @@ msgstr ""
#: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:15 #: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:15
#: order/templates/order/purchase_order_detail.html:200 #: order/templates/order/purchase_order_detail.html:200
#: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:64 #: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html:64
#: stock/models.py:438 stock/models.py:1287 stock/templates/stock/tabs.html:26 #: stock/models.py:433 stock/models.py:1282 stock/templates/stock/tabs.html:26
#: templates/js/barcode.html:391 templates/js/bom.html:229 #: templates/js/barcode.html:391 templates/js/bom.html:229
#: templates/js/stock.html:114 templates/js/stock.html:526 #: templates/js/stock.html:114 templates/js/stock.html:526
msgid "Notes" msgid "Notes"
@ -413,8 +413,8 @@ msgstr ""
#: build/templates/build/allocate.html:161 #: build/templates/build/allocate.html:161
#: order/templates/order/sales_order_detail.html:68 #: order/templates/order/sales_order_detail.html:68
#: order/templates/order/sales_order_detail.html:150 stock/models.py:364 #: order/templates/order/sales_order_detail.html:150 stock/models.py:359
#: stock/templates/stock/item_base.html:153 #: stock/templates/stock/item_base.html:150
msgid "Serial Number" msgid "Serial Number"
msgstr "" msgstr ""
@ -431,7 +431,7 @@ msgstr ""
#: part/templates/part/allocation.html:49 #: part/templates/part/allocation.html:49
#: stock/templates/stock/item_base.html:26 #: stock/templates/stock/item_base.html:26
#: stock/templates/stock/item_base.html:32 #: stock/templates/stock/item_base.html:32
#: stock/templates/stock/item_base.html:159 #: stock/templates/stock/item_base.html:156
#: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338 #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338
#: templates/js/bom.html:172 templates/js/build.html:52 #: templates/js/bom.html:172 templates/js/build.html:52
#: templates/js/stock.html:673 #: templates/js/stock.html:673
@ -440,7 +440,7 @@ msgstr ""
#: build/templates/build/allocate.html:177 #: build/templates/build/allocate.html:177
#: build/templates/build/auto_allocate.html:20 #: build/templates/build/auto_allocate.html:20
#: stock/templates/stock/item_base.html:191 #: stock/templates/stock/item_base.html:188
#: stock/templates/stock/stock_adjust.html:17 templates/js/barcode.html:337 #: stock/templates/stock/stock_adjust.html:17 templates/js/barcode.html:337
#: templates/js/stock.html:508 #: templates/js/stock.html:508
msgid "Location" msgid "Location"
@ -478,7 +478,7 @@ msgstr ""
msgid "Reference" msgid "Reference"
msgstr "" msgstr ""
#: build/templates/build/allocate.html:338 part/models.py:1270 #: build/templates/build/allocate.html:338 part/models.py:1271
#: templates/js/part.html:359 templates/js/table_filters.html:100 #: templates/js/part.html:359 templates/js/table_filters.html:100
msgid "Required" msgid "Required"
msgstr "" msgstr ""
@ -522,7 +522,7 @@ msgstr ""
#: build/templates/build/build_base.html:8 #: build/templates/build/build_base.html:8
#: build/templates/build/build_base.html:34 #: build/templates/build/build_base.html:34
#: build/templates/build/complete.html:6 #: build/templates/build/complete.html:6
#: stock/templates/stock/item_base.html:216 templates/js/build.html:33 #: stock/templates/stock/item_base.html:213 templates/js/build.html:33
#: templates/navbar.html:12 #: templates/navbar.html:12
msgid "Build" msgid "Build"
msgstr "" msgstr ""
@ -542,7 +542,7 @@ msgstr ""
#: build/templates/build/build_base.html:80 #: build/templates/build/build_base.html:80
#: build/templates/build/detail.html:42 #: build/templates/build/detail.html:42
#: order/templates/order/receive_parts.html:24 #: order/templates/order/receive_parts.html:24
#: stock/templates/stock/item_base.html:269 templates/js/barcode.html:42 #: stock/templates/stock/item_base.html:266 templates/js/barcode.html:42
#: templates/js/build.html:57 templates/js/order.html:162 #: templates/js/build.html:57 templates/js/order.html:162
#: templates/js/order.html:235 templates/js/stock.html:495 #: templates/js/order.html:235 templates/js/stock.html:495
msgid "Status" msgid "Status"
@ -554,7 +554,7 @@ msgstr ""
#: order/templates/order/sales_order_notes.html:10 #: order/templates/order/sales_order_notes.html:10
#: order/templates/order/sales_order_ship.html:25 #: order/templates/order/sales_order_ship.html:25
#: part/templates/part/allocation.html:27 #: part/templates/part/allocation.html:27
#: stock/templates/stock/item_base.html:179 templates/js/order.html:209 #: stock/templates/stock/item_base.html:176 templates/js/order.html:209
msgid "Sales Order" msgid "Sales Order"
msgstr "" msgstr ""
@ -621,7 +621,7 @@ msgid "Stock can be taken from any available location."
msgstr "" msgstr ""
#: build/templates/build/detail.html:48 #: build/templates/build/detail.html:48
#: stock/templates/stock/item_base.html:209 templates/js/stock.html:503 #: stock/templates/stock/item_base.html:206 templates/js/stock.html:503
msgid "Batch" msgid "Batch"
msgstr "" msgstr ""
@ -910,8 +910,8 @@ msgstr ""
msgid "Does this company manufacture parts?" msgid "Does this company manufacture parts?"
msgstr "" msgstr ""
#: company/models.py:279 stock/models.py:324 #: company/models.py:279 stock/models.py:319
#: stock/templates/stock/item_base.html:145 #: stock/templates/stock/item_base.html:142
msgid "Base Part" msgid "Base Part"
msgstr "" msgstr ""
@ -982,14 +982,14 @@ msgstr ""
#: company/templates/company/supplier_part_detail.html:21 order/models.py:148 #: company/templates/company/supplier_part_detail.html:21 order/models.py:148
#: order/templates/order/order_base.html:74 #: order/templates/order/order_base.html:74
#: order/templates/order/order_wizard/select_pos.html:30 #: order/templates/order/order_wizard/select_pos.html:30
#: stock/templates/stock/item_base.html:244 templates/js/company.html:52 #: stock/templates/stock/item_base.html:241 templates/js/company.html:52
#: templates/js/company.html:134 templates/js/order.html:144 #: templates/js/company.html:134 templates/js/order.html:144
msgid "Supplier" msgid "Supplier"
msgstr "" msgstr ""
#: company/templates/company/detail.html:26 order/models.py:314 #: company/templates/company/detail.html:26 order/models.py:314
#: order/templates/order/sales_order_base.html:73 stock/models.py:359 #: order/templates/order/sales_order_base.html:73 stock/models.py:354
#: stock/models.py:360 stock/templates/stock/item_base.html:166 #: stock/models.py:355 stock/templates/stock/item_base.html:163
#: templates/js/company.html:44 templates/js/order.html:217 #: templates/js/company.html:44 templates/js/order.html:217
msgid "Customer" msgid "Customer"
msgstr "" msgstr ""
@ -1102,8 +1102,8 @@ msgid "New Sales Order"
msgstr "" msgstr ""
#: company/templates/company/supplier_part_base.html:6 #: company/templates/company/supplier_part_base.html:6
#: company/templates/company/supplier_part_base.html:19 stock/models.py:333 #: company/templates/company/supplier_part_base.html:19 stock/models.py:328
#: stock/templates/stock/item_base.html:249 templates/js/company.html:150 #: stock/templates/stock/item_base.html:246 templates/js/company.html:150
msgid "Supplier Part" msgid "Supplier Part"
msgstr "" msgstr ""
@ -1367,8 +1367,8 @@ msgstr ""
msgid "Supplier order reference code" msgid "Supplier order reference code"
msgstr "" msgstr ""
#: order/models.py:185 order/models.py:259 part/views.py:1167 #: order/models.py:185 order/models.py:259 part/views.py:1250
#: stock/models.py:238 stock/models.py:687 #: stock/models.py:239 stock/models.py:682
msgid "Quantity must be greater than zero" msgid "Quantity must be greater than zero"
msgstr "" msgstr ""
@ -1402,7 +1402,7 @@ msgstr ""
#: order/models.py:466 order/templates/order/order_base.html:9 #: order/models.py:466 order/templates/order/order_base.html:9
#: order/templates/order/order_base.html:23 #: order/templates/order/order_base.html:23
#: stock/templates/stock/item_base.html:223 templates/js/order.html:136 #: stock/templates/stock/item_base.html:220 templates/js/order.html:136
msgid "Purchase Order" msgid "Purchase Order"
msgstr "" msgstr ""
@ -1819,16 +1819,16 @@ msgstr ""
msgid "Remove allocation" msgid "Remove allocation"
msgstr "" msgstr ""
#: part/bom.py:140 #: part/bom.py:144
#, python-brace-format #, python-brace-format
msgid "Unsupported file format: {f}" msgid "Unsupported file format: {f}"
msgstr "" msgstr ""
#: part/bom.py:145 #: part/bom.py:149
msgid "Error reading BOM file (invalid data)" msgid "Error reading BOM file (invalid data)"
msgstr "" msgstr ""
#: part/bom.py:147 #: part/bom.py:151
msgid "Error reading BOM file (incorrect row size)" msgid "Error reading BOM file (incorrect row size)"
msgstr "" msgstr ""
@ -1848,31 +1848,39 @@ msgstr ""
msgid "Download cascading / multi-level BOM" msgid "Download cascading / multi-level BOM"
msgstr "" msgstr ""
#: part/forms.py:76 #: part/forms.py:59
msgid "Levels"
msgstr ""
#: part/forms.py:59
msgid "Select maximum number of BOM levels to export (0 = all levels)"
msgstr ""
#: part/forms.py:78
msgid "Confirm that the BOM is correct" msgid "Confirm that the BOM is correct"
msgstr "" msgstr ""
#: part/forms.py:88 #: part/forms.py:90
msgid "Select BOM file to upload" msgid "Select BOM file to upload"
msgstr "" msgstr ""
#: part/forms.py:112 #: part/forms.py:114
msgid "Select part category" msgid "Select part category"
msgstr "" msgstr ""
#: part/forms.py:126 #: part/forms.py:128
msgid "Perform 'deep copy' which will duplicate all BOM data for this part" msgid "Perform 'deep copy' which will duplicate all BOM data for this part"
msgstr "" msgstr ""
#: part/forms.py:131 #: part/forms.py:133
msgid "Confirm part creation" msgid "Confirm part creation"
msgstr "" msgstr ""
#: part/forms.py:221 #: part/forms.py:223
msgid "Input quantity for price calculation" msgid "Input quantity for price calculation"
msgstr "" msgstr ""
#: part/forms.py:224 #: part/forms.py:226
msgid "Select currency for price calculation" msgid "Select currency for price calculation"
msgstr "" msgstr ""
@ -1985,116 +1993,117 @@ msgstr ""
msgid "Stored BOM checksum" msgid "Stored BOM checksum"
msgstr "" msgstr ""
#: part/models.py:1222 #: part/models.py:1223
msgid "Test templates can only be created for trackable parts" msgid "Test templates can only be created for trackable parts"
msgstr "" msgstr ""
#: part/models.py:1239 #: part/models.py:1240
msgid "Test with this name already exists for this part" msgid "Test with this name already exists for this part"
msgstr "" msgstr ""
#: part/models.py:1258 templates/js/part.html:350 templates/js/stock.html:90 #: part/models.py:1259 templates/js/part.html:350 templates/js/stock.html:90
msgid "Test Name" msgid "Test Name"
msgstr "" msgstr ""
#: part/models.py:1259 #: part/models.py:1260
msgid "Enter a name for the test" msgid "Enter a name for the test"
msgstr "" msgstr ""
#: part/models.py:1264 #: part/models.py:1265
msgid "Test Description" msgid "Test Description"
msgstr "" msgstr ""
#: part/models.py:1265 #: part/models.py:1266
msgid "Enter description for this test" msgid "Enter description for this test"
msgstr "" msgstr ""
#: part/models.py:1271 #: part/models.py:1272
msgid "Is this test required to pass?" msgid "Is this test required to pass?"
msgstr "" msgstr ""
#: part/models.py:1276 templates/js/part.html:367 #: part/models.py:1277 templates/js/part.html:367
msgid "Requires Value" msgid "Requires Value"
msgstr "" msgstr ""
#: part/models.py:1277 #: part/models.py:1278
msgid "Does this test require a value when adding a test result?" msgid "Does this test require a value when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1282 templates/js/part.html:374 #: part/models.py:1283 templates/js/part.html:374
msgid "Requires Attachment" msgid "Requires Attachment"
msgstr "" msgstr ""
#: part/models.py:1283 #: part/models.py:1284
msgid "Does this test require a file attachment when adding a test result?" msgid "Does this test require a file attachment when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1316 #: part/models.py:1317
msgid "Parameter template name must be unique" msgid "Parameter template name must be unique"
msgstr "" msgstr ""
#: part/models.py:1321 #: part/models.py:1322
msgid "Parameter Name" msgid "Parameter Name"
msgstr "" msgstr ""
#: part/models.py:1323 #: part/models.py:1324
msgid "Parameter Units" msgid "Parameter Units"
msgstr "" msgstr ""
#: part/models.py:1349 #: part/models.py:1350
msgid "Parent Part" msgid "Parent Part"
msgstr "" msgstr ""
#: part/models.py:1351 #: part/models.py:1352
msgid "Parameter Template" msgid "Parameter Template"
msgstr "" msgstr ""
#: part/models.py:1353 #: part/models.py:1354
msgid "Parameter Value" msgid "Parameter Value"
msgstr "" msgstr ""
#: part/models.py:1382 #: part/models.py:1383
msgid "Select parent part" msgid "Select parent part"
msgstr "" msgstr ""
#: part/models.py:1390 #: part/models.py:1391
msgid "Select part to be used in BOM" msgid "Select part to be used in BOM"
msgstr "" msgstr ""
#: part/models.py:1396 #: part/models.py:1397
msgid "BOM quantity for this BOM item" msgid "BOM quantity for this BOM item"
msgstr "" msgstr ""
#: part/models.py:1399 #: part/models.py:1400
msgid "Estimated build wastage quantity (absolute or percentage)" msgid "Estimated build wastage quantity (absolute or percentage)"
msgstr "" msgstr ""
#: part/models.py:1402 #: part/models.py:1403
msgid "BOM item reference" msgid "BOM item reference"
msgstr "" msgstr ""
#: part/models.py:1405 #: part/models.py:1406
msgid "BOM item notes" msgid "BOM item notes"
msgstr "" msgstr ""
#: part/models.py:1407 #: part/models.py:1408
msgid "BOM line checksum" msgid "BOM line checksum"
msgstr "" msgstr ""
#: part/models.py:1471 stock/models.py:228 #: part/models.py:1472 part/views.py:1256 part/views.py:1308
#: stock/models.py:229
msgid "Quantity must be integer value for trackable parts" msgid "Quantity must be integer value for trackable parts"
msgstr "" msgstr ""
#: part/models.py:1480 #: part/models.py:1481
msgid "Part cannot be added to its own Bill of Materials" msgid "Part cannot be added to its own Bill of Materials"
msgstr "" msgstr ""
#: part/models.py:1487 #: part/models.py:1488
#, python-brace-format #, python-brace-format
msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)" msgid "Part '{p1}' is used in BOM for '{p2}' (recursive)"
msgstr "" msgstr ""
#: part/models.py:1494 #: part/models.py:1495
msgid "BOM Item" msgid "BOM Item"
msgstr "" msgstr ""
@ -2113,14 +2122,14 @@ msgstr ""
#: part/templates/part/allocation.html:45 #: part/templates/part/allocation.html:45
#: stock/templates/stock/item_base.html:8 #: stock/templates/stock/item_base.html:8
#: stock/templates/stock/item_base.html:58 #: stock/templates/stock/item_base.html:58
#: stock/templates/stock/item_base.html:231 #: stock/templates/stock/item_base.html:228
#: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106 #: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106
#: templates/js/stock.html:643 #: templates/js/stock.html:643
msgid "Stock Item" msgid "Stock Item"
msgstr "" msgstr ""
#: part/templates/part/allocation.html:20 #: part/templates/part/allocation.html:20
#: stock/templates/stock/item_base.html:185 #: stock/templates/stock/item_base.html:182
msgid "Build Order" msgid "Build Order"
msgstr "" msgstr ""
@ -2156,10 +2165,78 @@ msgstr ""
msgid "Validate Bill of Materials" msgid "Validate Bill of Materials"
msgstr "" msgstr ""
#: part/templates/part/bom.html:46 part/views.py:1412 #: part/templates/part/bom.html:46 part/views.py:1523
msgid "Export Bill of Materials" msgid "Export Bill of Materials"
msgstr "" msgstr ""
#: part/templates/part/bom_upload/select_fields.html:8
#: part/templates/part/bom_upload/select_parts.html:8
#: part/templates/part/bom_upload/upload_file.html:10
msgid "Upload Bill of Materials"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:10
msgid "Step 2 - Select Fields"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:15
msgid "Missing selections for the following required columns"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:26
msgid "Submit Selections"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:35
msgid "File Fields"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:52
msgid "Match Fields"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:10
msgid "Step 3 - Select Parts"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:15
msgid "Errors exist in the submitted data"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:21
msgid "Submit BOM"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:33
msgid "Row"
msgstr ""
#: part/templates/part/bom_upload/select_parts.html:34
#: part/templates/part/bom_upload/select_parts.html:63
msgid "Select Part"
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:13
msgid "Step 1 - Select BOM File"
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:16
msgid "Requirements for BOM upload"
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:18
msgid ""
"The BOM file must contain the required named columns as provided in the "
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:18
msgid "BOM Upload Template"
msgstr ""
#: part/templates/part/bom_upload/upload_file.html:19
msgid "Each part must already exist in the database"
msgstr ""
#: part/templates/part/category.html:14 #: part/templates/part/category.html:14
msgid "All parts" msgid "All parts"
msgstr "" msgstr ""
@ -2354,7 +2431,7 @@ msgstr ""
msgid "New Parameter" msgid "New Parameter"
msgstr "" msgstr ""
#: part/templates/part/params.html:21 stock/models.py:1274 #: part/templates/part/params.html:21 stock/models.py:1269
#: templates/js/stock.html:110 #: templates/js/stock.html:110
msgid "Value" msgid "Value"
msgstr "" msgstr ""
@ -2535,7 +2612,7 @@ msgstr ""
msgid "Used In" msgid "Used In"
msgstr "" msgstr ""
#: part/templates/part/tabs.html:55 stock/templates/stock/item_base.html:275 #: part/templates/part/tabs.html:55 stock/templates/stock/item_base.html:272
msgid "Tests" msgid "Tests"
msgstr "" msgstr ""
@ -2640,91 +2717,91 @@ msgstr ""
msgid "Validate BOM" msgid "Validate BOM"
msgstr "" msgstr ""
#: part/views.py:908 #: part/views.py:909
msgid "No BOM file provided" msgid "No BOM file provided"
msgstr "" msgstr ""
#: part/views.py:1169 #: part/views.py:1259
msgid "Enter a valid quantity" msgid "Enter a valid quantity"
msgstr "" msgstr ""
#: part/views.py:1193 part/views.py:1196 #: part/views.py:1284 part/views.py:1287
msgid "Select valid part" msgid "Select valid part"
msgstr "" msgstr ""
#: part/views.py:1202 #: part/views.py:1293
msgid "Duplicate part selected" msgid "Duplicate part selected"
msgstr "" msgstr ""
#: part/views.py:1230 #: part/views.py:1329
msgid "Select a part" msgid "Select a part"
msgstr "" msgstr ""
#: part/views.py:1234 #: part/views.py:1333
msgid "Specify quantity" msgid "Specify quantity"
msgstr "" msgstr ""
#: part/views.py:1450 #: part/views.py:1565
msgid "Confirm Part Deletion" msgid "Confirm Part Deletion"
msgstr "" msgstr ""
#: part/views.py:1457 #: part/views.py:1572
msgid "Part was deleted" msgid "Part was deleted"
msgstr "" msgstr ""
#: part/views.py:1466 #: part/views.py:1581
msgid "Part Pricing" msgid "Part Pricing"
msgstr "" msgstr ""
#: part/views.py:1588 #: part/views.py:1703
msgid "Create Part Parameter Template" msgid "Create Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1596 #: part/views.py:1711
msgid "Edit Part Parameter Template" msgid "Edit Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1603 #: part/views.py:1718
msgid "Delete Part Parameter Template" msgid "Delete Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1611 #: part/views.py:1726
msgid "Create Part Parameter" msgid "Create Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1661 #: part/views.py:1776
msgid "Edit Part Parameter" msgid "Edit Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1675 #: part/views.py:1790
msgid "Delete Part Parameter" msgid "Delete Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1691 #: part/views.py:1806
msgid "Edit Part Category" msgid "Edit Part Category"
msgstr "" msgstr ""
#: part/views.py:1726 #: part/views.py:1841
msgid "Delete Part Category" msgid "Delete Part Category"
msgstr "" msgstr ""
#: part/views.py:1732 #: part/views.py:1847
msgid "Part category was deleted" msgid "Part category was deleted"
msgstr "" msgstr ""
#: part/views.py:1740 #: part/views.py:1855
msgid "Create new part category" msgid "Create new part category"
msgstr "" msgstr ""
#: part/views.py:1791 #: part/views.py:1906
msgid "Create BOM item" msgid "Create BOM item"
msgstr "" msgstr ""
#: part/views.py:1857 #: part/views.py:1972
msgid "Edit BOM item" msgid "Edit BOM item"
msgstr "" msgstr ""
#: part/views.py:1905 #: part/views.py:2020
msgid "Confim BOM item deletion" msgid "Confim BOM item deletion"
msgstr "" msgstr ""
@ -2776,203 +2853,203 @@ msgstr ""
msgid "Set the destination as the default location for selected parts" msgid "Set the destination as the default location for selected parts"
msgstr "" msgstr ""
#: stock/models.py:209 #: stock/models.py:210
msgid "StockItem with this serial number already exists" msgid "StockItem with this serial number already exists"
msgstr "" msgstr ""
#: stock/models.py:245 #: stock/models.py:246
#, python-brace-format #, python-brace-format
msgid "Part type ('{pf}') must be {pe}" msgid "Part type ('{pf}') must be {pe}"
msgstr "" msgstr ""
#: stock/models.py:255 stock/models.py:264 #: stock/models.py:256 stock/models.py:265
msgid "Quantity must be 1 for item with a serial number" msgid "Quantity must be 1 for item with a serial number"
msgstr "" msgstr ""
#: stock/models.py:256 #: stock/models.py:257
msgid "Serial number cannot be set if quantity greater than 1" msgid "Serial number cannot be set if quantity greater than 1"
msgstr "" msgstr ""
#: stock/models.py:277 #: stock/models.py:278
msgid "Item cannot belong to itself" msgid "Item cannot belong to itself"
msgstr "" msgstr ""
#: stock/models.py:316 #: stock/models.py:311
msgid "Parent Stock Item" msgid "Parent Stock Item"
msgstr "" msgstr ""
#: stock/models.py:325 #: stock/models.py:320
msgid "Base part" msgid "Base part"
msgstr "" msgstr ""
#: stock/models.py:334 #: stock/models.py:329
msgid "Select a matching supplier part for this stock item" msgid "Select a matching supplier part for this stock item"
msgstr "" msgstr ""
#: stock/models.py:339 stock/templates/stock/stock_app_base.html:7 #: stock/models.py:334 stock/templates/stock/stock_app_base.html:7
msgid "Stock Location" msgid "Stock Location"
msgstr "" msgstr ""
#: stock/models.py:342 #: stock/models.py:337
msgid "Where is this stock item located?" msgid "Where is this stock item located?"
msgstr "" msgstr ""
#: stock/models.py:347 #: stock/models.py:342
msgid "Installed In" msgid "Installed In"
msgstr "" msgstr ""
#: stock/models.py:350 #: stock/models.py:345
msgid "Is this item installed in another item?" msgid "Is this item installed in another item?"
msgstr "" msgstr ""
#: stock/models.py:366 #: stock/models.py:361
msgid "Serial number for this item" msgid "Serial number for this item"
msgstr "" msgstr ""
#: stock/models.py:378 #: stock/models.py:373
msgid "Batch code for this stock item" msgid "Batch code for this stock item"
msgstr "" msgstr ""
#: stock/models.py:382 #: stock/models.py:377
msgid "Stock Quantity" msgid "Stock Quantity"
msgstr "" msgstr ""
#: stock/models.py:391 #: stock/models.py:386
msgid "Source Build" msgid "Source Build"
msgstr "" msgstr ""
#: stock/models.py:393 #: stock/models.py:388
msgid "Build for this stock item" msgid "Build for this stock item"
msgstr "" msgstr ""
#: stock/models.py:400 #: stock/models.py:395
msgid "Source Purchase Order" msgid "Source Purchase Order"
msgstr "" msgstr ""
#: stock/models.py:403 #: stock/models.py:398
msgid "Purchase order for this stock item" msgid "Purchase order for this stock item"
msgstr "" msgstr ""
#: stock/models.py:409 #: stock/models.py:404
msgid "Destination Sales Order" msgid "Destination Sales Order"
msgstr "" msgstr ""
#: stock/models.py:416 #: stock/models.py:411
msgid "Destination Build Order" msgid "Destination Build Order"
msgstr "" msgstr ""
#: stock/models.py:429 #: stock/models.py:424
msgid "Delete this Stock Item when stock is depleted" msgid "Delete this Stock Item when stock is depleted"
msgstr "" msgstr ""
#: stock/models.py:439 stock/templates/stock/item_notes.html:14 #: stock/models.py:434 stock/templates/stock/item_notes.html:14
#: stock/templates/stock/item_notes.html:30 #: stock/templates/stock/item_notes.html:30
msgid "Stock Item Notes" msgid "Stock Item Notes"
msgstr "" msgstr ""
#: stock/models.py:490 #: stock/models.py:485
msgid "Assigned to Customer" msgid "Assigned to Customer"
msgstr "" msgstr ""
#: stock/models.py:492 #: stock/models.py:487
msgid "Manually assigned to customer" msgid "Manually assigned to customer"
msgstr "" msgstr ""
#: stock/models.py:505 #: stock/models.py:500
msgid "Returned from customer" msgid "Returned from customer"
msgstr "" msgstr ""
#: stock/models.py:507 #: stock/models.py:502
msgid "Returned to location" msgid "Returned to location"
msgstr "" msgstr ""
#: stock/models.py:678 #: stock/models.py:673
msgid "Part is not set as trackable" msgid "Part is not set as trackable"
msgstr "" msgstr ""
#: stock/models.py:684 #: stock/models.py:679
msgid "Quantity must be integer" msgid "Quantity must be integer"
msgstr "" msgstr ""
#: stock/models.py:690 #: stock/models.py:685
#, python-brace-format #, python-brace-format
msgid "Quantity must not exceed available stock quantity ({n})" msgid "Quantity must not exceed available stock quantity ({n})"
msgstr "" msgstr ""
#: stock/models.py:693 stock/models.py:696 #: stock/models.py:688 stock/models.py:691
msgid "Serial numbers must be a list of integers" msgid "Serial numbers must be a list of integers"
msgstr "" msgstr ""
#: stock/models.py:699 #: stock/models.py:694
msgid "Quantity does not match serial numbers" msgid "Quantity does not match serial numbers"
msgstr "" msgstr ""
#: stock/models.py:709 #: stock/models.py:704
msgid "Serial numbers already exist: " msgid "Serial numbers already exist: "
msgstr "" msgstr ""
#: stock/models.py:734 #: stock/models.py:729
msgid "Add serial number" msgid "Add serial number"
msgstr "" msgstr ""
#: stock/models.py:737 #: stock/models.py:732
#, python-brace-format #, python-brace-format
msgid "Serialized {n} items" msgid "Serialized {n} items"
msgstr "" msgstr ""
#: stock/models.py:848 #: stock/models.py:843
msgid "StockItem cannot be moved as it is not in stock" msgid "StockItem cannot be moved as it is not in stock"
msgstr "" msgstr ""
#: stock/models.py:1175 #: stock/models.py:1170
msgid "Tracking entry title" msgid "Tracking entry title"
msgstr "" msgstr ""
#: stock/models.py:1177 #: stock/models.py:1172
msgid "Entry notes" msgid "Entry notes"
msgstr "" msgstr ""
#: stock/models.py:1179 #: stock/models.py:1174
msgid "Link to external page for further information" msgid "Link to external page for further information"
msgstr "" msgstr ""
#: stock/models.py:1239 #: stock/models.py:1234
msgid "Value must be provided for this test" msgid "Value must be provided for this test"
msgstr "" msgstr ""
#: stock/models.py:1245 #: stock/models.py:1240
msgid "Attachment must be uploaded for this test" msgid "Attachment must be uploaded for this test"
msgstr "" msgstr ""
#: stock/models.py:1262 #: stock/models.py:1257
msgid "Test" msgid "Test"
msgstr "" msgstr ""
#: stock/models.py:1263 #: stock/models.py:1258
msgid "Test name" msgid "Test name"
msgstr "" msgstr ""
#: stock/models.py:1268 #: stock/models.py:1263
msgid "Result" msgid "Result"
msgstr "" msgstr ""
#: stock/models.py:1269 templates/js/table_filters.html:90 #: stock/models.py:1264 templates/js/table_filters.html:90
msgid "Test result" msgid "Test result"
msgstr "" msgstr ""
#: stock/models.py:1275 #: stock/models.py:1270
msgid "Test output value" msgid "Test output value"
msgstr "" msgstr ""
#: stock/models.py:1281 #: stock/models.py:1276
msgid "Attachment" msgid "Attachment"
msgstr "" msgstr ""
#: stock/models.py:1282 #: stock/models.py:1277
msgid "Test result attachment" msgid "Test result attachment"
msgstr "" msgstr ""
#: stock/models.py:1288 #: stock/models.py:1283
msgid "Test notes" msgid "Test notes"
msgstr "" msgstr ""
@ -3078,39 +3155,35 @@ msgstr ""
msgid "Generate test report" msgid "Generate test report"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:132 #: stock/templates/stock/item_base.html:137
msgid "Print labels"
msgstr ""
#: stock/templates/stock/item_base.html:140
msgid "Stock Item Details" msgid "Stock Item Details"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:173 #: stock/templates/stock/item_base.html:170
msgid "Belongs To" msgid "Belongs To"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:195 #: stock/templates/stock/item_base.html:192
msgid "No location set" msgid "No location set"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:202 #: stock/templates/stock/item_base.html:199
msgid "Unique Identifier" msgid "Unique Identifier"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:230 #: stock/templates/stock/item_base.html:227
msgid "Parent Item" msgid "Parent Item"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:255 #: stock/templates/stock/item_base.html:252
msgid "Last Updated" msgid "Last Updated"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:260 #: stock/templates/stock/item_base.html:257
msgid "Last Stocktake" msgid "Last Stocktake"
msgstr "" msgstr ""
#: stock/templates/stock/item_base.html:264 #: stock/templates/stock/item_base.html:261
msgid "No stocktake performed" msgid "No stocktake performed"
msgstr "" msgstr ""

View File

@ -139,16 +139,71 @@ class BomItemResource(ModelResource):
bom_id = Field(attribute='pk') bom_id = Field(attribute='pk')
# ID of the parent part
parent_part_id = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part)) parent_part_id = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
parent_part_name = Field(attribute='part__full_name', readonly=True) # IPN of the parent part
parent_part_ipn = Field(attribute='part__IPN', readonly=True)
sub_part_id = Field(attribute='sub_part', widget=widgets.ForeignKeyWidget(Part)) # Name of the parent part
parent_part_name = Field(attribute='part__name', readonly=True)
sub_part_name = Field(attribute='sub_part__full_name', readonly=True) # ID of the sub-part
part_id = Field(attribute='sub_part', widget=widgets.ForeignKeyWidget(Part))
# IPN of the sub-part
part_ipn = Field(attribute='sub_part__IPN', readonly=True)
# Name of the sub-part
part_name = Field(attribute='sub_part__name', readonly=True)
# Description of the sub-part
part_description = Field(attribute='sub_part__description', readonly=True)
# Is the sub-part itself an assembly?
sub_assembly = Field(attribute='sub_part__assembly', readonly=True) sub_assembly = Field(attribute='sub_part__assembly', readonly=True)
def before_export(self, queryset, *args, **kwargs):
self.is_importing = kwargs.get('importing', False)
def get_fields(self, **kwargs):
"""
If we are exporting for the purposes of generating
a 'bom-import' template, there are some fields which
we are not interested in.
"""
fields = super().get_fields(**kwargs)
# If we are not generating an "import" template,
# just return the complete list of fields
if not self.is_importing:
return fields
# Otherwise, remove some fields we are not interested in
idx = 0
to_remove = [
'level',
'bom_id',
'parent_part_id',
'parent_part_ipn',
'parent_part_name',
'part_description',
'sub_assembly'
]
while idx < len(fields):
if fields[idx].column_name.lower() in to_remove:
del fields[idx]
else:
idx += 1
return fields
class Meta: class Meta:
model = BomItem model = BomItem
skip_unchanged = True skip_unchanged = True

View File

@ -30,8 +30,14 @@ def MakeBomTemplate(fmt):
if not IsValidBOMFormat(fmt): if not IsValidBOMFormat(fmt):
fmt = 'csv' fmt = 'csv'
# Create an "empty" queryset, essentially.
# This will then export just the row headers!
query = BomItem.objects.filter(pk=None) query = BomItem.objects.filter(pk=None)
dataset = BomItemResource().export(queryset=query)
dataset = BomItemResource().export(
queryset=query,
importing=True
)
data = dataset.export(fmt) data = dataset.export(fmt)
@ -96,26 +102,23 @@ class BomUploadManager:
# Fields which are absolutely necessary for valid upload # Fields which are absolutely necessary for valid upload
REQUIRED_HEADERS = [ REQUIRED_HEADERS = [
'Part', 'Part_Name',
'Quantity' 'Quantity'
] ]
# Fields which would be helpful but are not required # Fields which would be helpful but are not required
OPTIONAL_HEADERS = [ OPTIONAL_HEADERS = [
'Part_IPN',
'Part_ID',
'Reference', 'Reference',
'Notes', 'Note',
'Overage', 'Overage',
'Description',
'Category',
'Supplier',
'Manufacturer',
'MPN',
'IPN',
] ]
EDITABLE_HEADERS = [ EDITABLE_HEADERS = [
'Reference', 'Reference',
'Notes' 'Note',
'Overage'
] ]
HEADERS = REQUIRED_HEADERS + OPTIONAL_HEADERS HEADERS = REQUIRED_HEADERS + OPTIONAL_HEADERS
@ -165,6 +168,11 @@ class BomUploadManager:
if h.lower() == header.lower(): if h.lower() == header.lower():
return h return h
# Try for a case-insensitive match with space replacement
for h in self.HEADERS:
if h.lower() == header.lower().replace(' ', '_'):
return h
# Finally, look for a close match using fuzzy matching # Finally, look for a close match using fuzzy matching
matches = [] matches = []

View File

@ -271,6 +271,42 @@ class Part(MPTTModel):
def __str__(self): def __str__(self):
return "{n} - {d}".format(n=self.full_name, d=self.description) return "{n} - {d}".format(n=self.full_name, d=self.description)
def checkAddToBOM(self, parent):
"""
Check if this Part can be added to the BOM of another part.
This will fail if:
a) The parent part is the same as this one
b) The parent part is used in the BOM for *this* part
c) The parent part is used in the BOM for any child parts under this one
Failing this check raises a ValidationError!
"""
if parent is None:
return
if self.pk == parent.pk:
raise ValidationError({'sub_part': _("Part '{p1}' is used in BOM for '{p2}' (recursive)".format(
p1=str(self),
p2=str(parent)
))})
# Ensure that the parent part does not appear under any child BOM item!
for item in self.bom_items.all():
# Check for simple match
if item.sub_part == parent:
raise ValidationError({'sub_part': _("Part '{p1}' is used in BOM for '{p2}' (recursive)".format(
p1=str(parent),
p2=str(self)
))})
# And recursively check too
item.sub_part.checkAddToBOM(parent)
def checkIfSerialNumberExists(self, sn): def checkIfSerialNumberExists(self, sn):
""" """
Check if a serial number exists for this Part. Check if a serial number exists for this Part.
@ -1474,22 +1510,8 @@ class BomItem(models.Model):
except Part.DoesNotExist: except Part.DoesNotExist:
pass pass
# A part cannot refer to itself in its BOM # Check for circular BOM references
try: self.sub_part.checkAddToBOM(self.part)
if self.sub_part is not None and self.part is not None:
if self.part == self.sub_part:
raise ValidationError({'sub_part': _('Part cannot be added to its own Bill of Materials')})
# TODO - Make sure that there is no recusion
# Test for simple recursion
for item in self.sub_part.bom_items.all():
if self.part == item.sub_part:
raise ValidationError({'sub_part': _("Part '{p1}' is used in BOM for '{p2}' (recursive)".format(p1=str(self.part), p2=str(self.sub_part)))})
except Part.DoesNotExist:
# A blank Part will be caught elsewhere
pass
class Meta: class Meta:
verbose_name = _("BOM Item") verbose_name = _("BOM Item")

View File

@ -1,17 +1,18 @@
{% extends "part/part_base.html" %} {% extends "part/part_base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% load inventree_extras %} {% load inventree_extras %}
{% block details %} {% block details %}
{% include "part/tabs.html" with tab='bom' %} {% include "part/tabs.html" with tab='bom' %}
<h4>Upload Bill of Materials</h4> <h4>{% trans "Upload Bill of Materials" %}</h4>
<p>Step 2 - Select Fields</p> <p>{% trans "Step 2 - Select Fields" %}</p>
<hr> <hr>
{% if missing_columns and missing_columns|length > 0 %} {% if missing_columns and missing_columns|length > 0 %}
<div class='alert alert-danger alert-block' role='alert'> <div class='alert alert-danger alert-block' role='alert'>
Missing selections for the following required columns: {% trans "Missing selections for the following required columns" %}:
<br> <br>
<ul> <ul>
{% for col in missing_columns %} {% for col in missing_columns %}
@ -22,7 +23,7 @@
{% endif %} {% endif %}
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data"> <form method="post" action='' class='js-modal-form' enctype="multipart/form-data">
<button type="submit" class="save btn btn-default">Submit Selections</button> <button type="submit" class="save btn btn-default">{% trans "Submit Selections" %}</button>
{% csrf_token %} {% csrf_token %}
<input type='hidden' name='form_step' value='select_fields'/> <input type='hidden' name='form_step' value='select_fields'/>
@ -31,7 +32,7 @@
<thead> <thead>
<tr> <tr>
<th></th> <th></th>
<th>Row</th> <th>{% trans "File Fields" %}</th>
{% for col in bom_columns %} {% for col in bom_columns %}
<th> <th>
<div> <div>
@ -48,7 +49,7 @@
<tbody> <tbody>
<tr> <tr>
<td></td> <td></td>
<td></td> <td>{% trans "Match Fields" %}</td>
{% for col in bom_columns %} {% for col in bom_columns %}
<td> <td>
<select class='select' id='id_col_{{ forloop.counter0 }}' name='col_guess_{{ forloop.counter0 }}'> <select class='select' id='id_col_{{ forloop.counter0 }}' name='col_guess_{{ forloop.counter0 }}'>

View File

@ -1,23 +1,24 @@
{% extends "part/part_base.html" %} {% extends "part/part_base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% load inventree_extras %} {% load inventree_extras %}
{% block details %} {% block details %}
{% include "part/tabs.html" with tab="bom" %} {% include "part/tabs.html" with tab="bom" %}
<h4>Upload Bill of Materials</h4> <h4>{% trans "Upload Bill of Materials" %}</h4>
<p>Step 3 - Select Parts</p> <p>{% trans "Step 3 - Select Parts" %}</p>
<hr> <hr>
{% if form_errors %} {% if form_errors %}
<div class='alert alert-danger alert-block' role='alert'> <div class='alert alert-danger alert-block' role='alert'>
Errors exist in the submitted data. {% trans "Errors exist in the submitted data" %}
</div> </div>
{% endif %} {% endif %}
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data"> <form method="post" action='' class='js-modal-form' enctype="multipart/form-data">
<button type="submit" class="save btn btn-default">Submit BOM</button> <button type="submit" class="save btn btn-default">{% trans "Submit BOM" %}</button>
{% csrf_token %} {% csrf_token %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
@ -29,7 +30,8 @@
<tr> <tr>
<th></th> <th></th>
<th></th> <th></th>
<th>Row</th> <th>{% trans "Row" %}</th>
<th>{% trans "Select Part" %}</th>
{% for col in bom_columns %} {% for col in bom_columns %}
<th> <th>
<input type='hidden' name='col_name_{{ forloop.counter0 }}' value='{{ col.name }}'/> <input type='hidden' name='col_name_{{ forloop.counter0 }}' value='{{ col.name }}'/>
@ -51,39 +53,39 @@
<span row_id='{{ forloop.counter }}' class='fas fa-trash-alt icon-red'></span> <span row_id='{{ forloop.counter }}' class='fas fa-trash-alt icon-red'></span>
</button> </button>
</td> </td>
<td> <td></td>
</td>
<td>{% add row.index 1 %}</td> <td>{% add row.index 1 %}</td>
<td>
<button class='btn btn-default btn-create' onClick='newPartFromBomWizard()' id='new_part_row_{{ row.index }}' title='Create new part' type='button'>
<span row_id='{{ row.index }}' class='fas fa-plus icon-green'/>
</button>
<select class='select bomselect' id='select_part_{{ row.index }}' name='part_{{ row.index }}'>
<option value=''>--- {% trans "Select Part" %} ---</option>
{% for part in row.part_options %}
<option value='{{ part.id }}' {% if part.id == row.part.id %} selected='selected' {% elif part.id == row.part_match.id %} selected='selected' {% endif %}>
{{ part.full_name }} - {{ part.description }}
</option>
{% endfor %}
</select>
{% if row.errors.part %}
<p class='help-inline'>{{ row.errors.part }}</p>
{% endif %}
</td>
{% for item in row.data %} {% for item in row.data %}
<td> <td>
{% if item.column.guess == 'Part' %} {% if item.column.guess == 'Part' %}
<button class='btn btn-default btn-create' onClick='newPartFromBomWizard()' id='new_part_row_{{ row.index }}' title='Create new part' type='button'>
<span row_id='{{ row.index }}' class='fas fa-trash-alt icon-red'/>
</button>
<select class='select bomselect' id='select_part_{{ row.index }}' name='part_{{ row.index }}'>
{% if row.part_match %}
{% with row.part_match as part %}
<option value='{{ part.id }}'{% if part.id == row.part.id %} selected='selected'{% endif %}>{{ part.full_name }} - {{ part.description }}</option>
{% endwith %}
{% endif %}
<option value=''>---------</option>
{% for part in row.part_options %}
<option value='{{ part.id }}'{% if part.id == row.part.id %} selected='selected'{% endif %}>{{ part.full_name }} - {{ part.description }}</option>
{% endfor %}
</select>
<i>{{ item.cell }}</i> <i>{{ item.cell }}</i>
{% if row.errors.part %} {% if row.errors.part %}
<p class='help-inline'>{{ row.errors.part }}</p> <p class='help-inline'>{{ row.errors.part }}</p>
{% endif %} {% endif %}
{% elif item.column.guess == 'Quantity' %} {% elif item.column.guess == 'Quantity' %}
<input name='quantity_{{ row.index }}' class='numberinput' type='number' min='1' value='{{ row.quantity }}'/> <input name='quantity_{{ row.index }}' class='numberinput' type='number' min='1' step='any' value='{% decimal row.quantity %}'/>
{% if row.errors.quantity %} {% if row.errors.quantity %}
<p class='help-inline'>{{ row.errors.quantity }}</p> <p class='help-inline'>{{ row.errors.quantity }}</p>
{% endif %} {% endif %}
{% elif item.column.guess == 'Reference' %} {% elif item.column.guess == 'Reference' %}
<input name='reference_{{ row.index }}' value='{{ row.reference }}'/> <input name='reference_{{ row.index }}' value='{{ row.reference }}'/>
{% elif item.column.guess == 'Notes' %} {% elif item.column.guess == 'Note' %}
<input name='notes_{{ row.index }}' value='{{ row.notes }}'/> <input name='notes_{{ row.index }}' value='{{ row.notes }}'/>
{% elif item.column.guess == 'Overage' %} {% elif item.column.guess == 'Overage' %}
<input name='overage_{{ row.index }}' value='{{ row.overage }}'/> <input name='overage_{{ row.index }}' value='{{ row.overage }}'/>

View File

@ -1,18 +1,23 @@
{% extends "part/part_base.html" %} {% extends "part/part_base.html" %}
{% load static %} {% load static %}
{% load i18n %}
{% load inventree_extras %} {% load inventree_extras %}
{% block details %} {% block details %}
{% include "part/tabs.html" with tab='bom' %} {% include "part/tabs.html" with tab='bom' %}
<h4>Upload Bill of Materials</h4> <h4>{% trans "Upload Bill of Materials" %}</h4>
<hr> <hr>
<p>Step 1 - Select BOM File</p> <p>{% trans "Step 1 - Select BOM File" %}</p>
<div class='alert alert-info alert-block'> <div class='alert alert-info alert-block'>
<p>The BOM file must contain the required named columns as provided in the <a href="/part/bom_template/">BOM Upload Template</a></a></p> <b>{% trans "Requirements for BOM upload" %}:</b>
<ul>
<li>{% trans "The BOM file must contain the required named columns as provided in the " %} <b><a href="/part/bom_template/">{% trans "BOM Upload Template" %}</a></b></li>
<li>{% trans "Each part must already exist in the database" %}</li>
</ul>
</div> </div>
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data"> <form method="post" action='' class='js-modal-form' enctype="multipart/form-data">

View File

@ -19,7 +19,7 @@ from django.conf import settings
import os import os
from rapidfuzz import fuzz from rapidfuzz import fuzz
from decimal import Decimal from decimal import Decimal, InvalidOperation
from .models import PartCategory, Part, PartAttachment from .models import PartCategory, Part, PartAttachment
from .models import PartParameterTemplate, PartParameter from .models import PartParameterTemplate, PartParameter
@ -948,81 +948,133 @@ class BomUpload(FormView):
The pre-fill data are then passed through to the part selection form. The pre-fill data are then passed through to the part selection form.
""" """
# Fields prefixed with "Part_" can be used to do "smart matching" against Part objects in the database
k_idx = self.getColumnIndex('Part_ID')
p_idx = self.getColumnIndex('Part_Name')
i_idx = self.getColumnIndex('Part_IPN')
q_idx = self.getColumnIndex('Quantity') q_idx = self.getColumnIndex('Quantity')
p_idx = self.getColumnIndex('Part')
i_idx = self.getColumnIndex('IPN')
d_idx = self.getColumnIndex('Description')
r_idx = self.getColumnIndex('Reference') r_idx = self.getColumnIndex('Reference')
n_idx = self.getColumnIndex('Notes') o_idx = self.getColumnIndex('Overage')
n_idx = self.getColumnIndex('Note')
for row in self.bom_rows: for row in self.bom_rows:
"""
quantity = 0 Iterate through each row in the uploaded data,
part = None and see if we can match the row to a "Part" object in the database.
There are three potential ways to match, based on the uploaded data:
a) Use the PK (primary key) field for the part, uploaded in the "Part_ID" field
b) Use the IPN (internal part number) field for the part, uploaded in the "Part_IPN" field
c) Use the name of the part, uploaded in the "Part_Name" field
Notes:
- If using the Part_ID field, we can do an exact match against the PK field
- If using the Part_IPN field, we can do an exact match against the IPN field
- If using the Part_Name field, we can use fuzzy string matching to match "close" values
We also extract other information from the row, for the other non-matched fields:
- Quantity
- Reference
- Overage
- Note
"""
# Initially use a quantity of zero
quantity = Decimal(0)
# Initially we do not have a part to reference
exact_match_part = None
# A list of potential Part matches
part_options = self.allowed_parts
# Check if there is a column corresponding to "quantity"
if q_idx >= 0: if q_idx >= 0:
q_val = row['data'][q_idx] q_val = row['data'][q_idx]
try: if q_val:
quantity = int(q_val) try:
except ValueError: # Attempt to extract a valid quantity from the field
pass quantity = Decimal(q_val)
except (ValueError, InvalidOperation):
pass
# Store the 'quantity' value
row['quantity'] = quantity
# Check if there is a column corresponding to "PK"
if k_idx >= 0:
pk = row['data'][k_idx]
if pk:
try:
# Attempt Part lookup based on PK value
exact_match_part = Part.objects.get(pk=pk)
except (ValueError, Part.DoesNotExist):
exact_match_part = None
# Check if there is a column corresponding to "Part Name"
if p_idx >= 0: if p_idx >= 0:
part_name = row['data'][p_idx] part_name = row['data'][p_idx]
row['part_name'] = part_name row['part_name'] = part_name
# Fuzzy match the values and see what happens
matches = [] matches = []
for part in self.allowed_parts: for part in self.allowed_parts:
ratio = fuzz.partial_ratio(part.name + part.description, part_name) ratio = fuzz.partial_ratio(part.name + part.description, part_name)
matches.append({'part': part, 'match': ratio}) matches.append({'part': part, 'match': ratio})
# Sort matches by the 'strength' of the match ratio
if len(matches) > 0: if len(matches) > 0:
matches = sorted(matches, key=lambda item: item['match'], reverse=True) matches = sorted(matches, key=lambda item: item['match'], reverse=True)
part_options = [m['part'] for m in matches]
# Check if there is a column corresponding to "Part IPN"
if i_idx >= 0: if i_idx >= 0:
row['part_ipn'] = row['data'][i_idx] row['part_ipn'] = row['data'][i_idx]
if d_idx >= 0: # Check if there is a column corresponding to "Overage" field
row['description'] = row['data'][d_idx] if o_idx >= 0:
row['overage'] = row['data'][o_idx]
# Check if there is a column corresponding to "Reference" field
if r_idx >= 0: if r_idx >= 0:
row['reference'] = row['data'][r_idx] row['reference'] = row['data'][r_idx]
# Check if there is a column corresponding to "Note" field
if n_idx >= 0: if n_idx >= 0:
row['notes'] = row['data'][n_idx] row['note'] = row['data'][n_idx]
row['quantity'] = quantity # Supply list of part options for each row, sorted by how closely they match the part name
row['part_options'] = part_options
# Part selection using IPN # Unless found, the 'part_match' is blank
try: row['part_match'] = None
if row['part_ipn']:
part_matches = [part for part in self.allowed_parts if row['part_ipn'] == part.IPN]
part_options = [part for part in self.allowed_parts if part not in part_matches]
# Check for single match if exact_match_part:
if len(part_matches) == 1: # If there is an exact match based on PK, use that
row['part_match'] = part_matches[0] row['part_match'] = exact_match_part
row['part_options'] = part_options
continue
except KeyError:
pass
# Part selection using Part Name
match_limit = 100
part_matches = [m['part'] for m in matches if m['match'] >= match_limit]
# Check for single match
if len(part_matches) == 1:
row['part_match'] = part_matches[0]
row['part_options'] = [m['part'] for m in matches if m['match'] < match_limit]
else: else:
row['part_options'] = [m['part'] for m in matches] # Otherwise, check to see if there is a matching IPN
try:
if row['part_ipn']:
part_matches = [part for part in self.allowed_parts if row['part_ipn'].lower() == part.IPN.lower()]
# Check for single match
if len(part_matches) == 1:
row['part_match'] = part_matches[0]
continue
except KeyError:
pass
print(row, row['part_match'], len(row['part_options']))
def extractDataFromFile(self, bom): def extractDataFromFile(self, bom):
""" Read data from the BOM file """ """ Read data from the BOM file """
@ -1190,13 +1242,20 @@ class BomUpload(FormView):
if row is None: if row is None:
continue continue
q = 1 q = Decimal(1)
try: try:
q = int(value) q = Decimal(value)
if q <= 0: if q < 0:
row['errors']['quantity'] = _('Quantity must be greater than zero') row['errors']['quantity'] = _('Quantity must be greater than zero')
except ValueError:
if 'part' in row.keys():
if row['part'].trackable:
# Trackable parts must use integer quantities
if not q == int(q):
row['errors']['quantity'] = _('Quantity must be integer value for trackable parts')
except (ValueError, InvalidOperation):
row['errors']['quantity'] = _('Enter a valid quantity') row['errors']['quantity'] = _('Enter a valid quantity')
row['quantity'] = q row['quantity'] = q
@ -1206,6 +1265,7 @@ class BomUpload(FormView):
# Extract part from each row # Extract part from each row
if key.startswith('part_'): if key.startswith('part_'):
try: try:
row_id = int(key.replace('part_', '')) row_id = int(key.replace('part_', ''))
@ -1239,6 +1299,14 @@ class BomUpload(FormView):
row['part'] = part row['part'] = part
if part.trackable:
# For trackable parts, ensure the quantity is an integer value!
if 'quantity' in row.keys():
q = row['quantity']
if not q == int(q):
row['errors']['quantity'] = _('Quantity must be integer value for trackable parts')
# Extract other fields which do not require further validation # Extract other fields which do not require further validation
for field in ['reference', 'notes']: for field in ['reference', 'notes']:
if key.startswith(field + '_'): if key.startswith(field + '_'):
@ -1257,8 +1325,16 @@ class BomUpload(FormView):
for row in self.bom_rows: for row in self.bom_rows:
# Has a part been selected for the given row? # Has a part been selected for the given row?
if row.get('part', None) is None: part = row.get('part', None)
if part is None:
row['errors']['part'] = _('Select a part') row['errors']['part'] = _('Select a part')
else:
# Will the selected part result in a recursive BOM?
try:
part.checkAddToBOM(self.part)
except ValidationError:
row['errors']['part'] = _('Selected part creates a circular BOM')
# Has a quantity been specified? # Has a quantity been specified?
if row.get('quantity', None) is None: if row.get('quantity', None) is None: