mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 13:15:43 +00:00 
			
		
		
		
	Merge pull request #909 from SchrodingersGat/bom-import-export
BOM upload: improve generation of "import" template
This commit is contained in:
		| @@ -6,7 +6,7 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: \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" | ||||
| "Last-Translator: Christian Schlüter <chschlue@gmail.com>\n" | ||||
| "Language-Team: C <kde-i18n-doc@kde.org>\n" | ||||
| @@ -45,30 +45,30 @@ msgstr "Neues Teil anlegen" | ||||
| msgid "Confirm new password" | ||||
| 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" | ||||
| msgstr "Keine gültige Menge" | ||||
|  | ||||
| #: InvenTree/helpers.py:331 | ||||
| #: InvenTree/helpers.py:339 | ||||
| msgid "Empty serial number string" | ||||
| msgstr "Keine Seriennummer angegeben" | ||||
|  | ||||
| #: InvenTree/helpers.py:352 InvenTree/helpers.py:369 | ||||
| #: InvenTree/helpers.py:360 InvenTree/helpers.py:377 | ||||
| #, python-brace-format | ||||
| msgid "Duplicate serial: {n}" | ||||
| msgstr "Doppelte Seriennummer: {n}" | ||||
|  | ||||
| #: InvenTree/helpers.py:356 InvenTree/helpers.py:359 InvenTree/helpers.py:362 | ||||
| #: InvenTree/helpers.py:373 | ||||
| #: InvenTree/helpers.py:364 InvenTree/helpers.py:367 InvenTree/helpers.py:370 | ||||
| #: InvenTree/helpers.py:381 | ||||
| #, python-brace-format | ||||
| msgid "Invalid group: {g}" | ||||
| msgstr "Ungültige Gruppe: {g}" | ||||
|  | ||||
| #: InvenTree/helpers.py:379 | ||||
| #: InvenTree/helpers.py:387 | ||||
| msgid "No serial numbers found" | ||||
| msgstr "Keine Seriennummern gefunden" | ||||
|  | ||||
| #: InvenTree/helpers.py:383 | ||||
| #: InvenTree/helpers.py:391 | ||||
| #, python-brace-format | ||||
| msgid "Number of unique serial number ({s}) must match quantity ({q})" | ||||
| msgstr "" | ||||
| @@ -341,7 +341,7 @@ msgstr "Bau-Status" | ||||
| msgid "Build status code" | ||||
| msgstr "Bau-Statuscode" | ||||
|  | ||||
| #: build/models.py:136 stock/models.py:376 | ||||
| #: build/models.py:136 stock/models.py:371 | ||||
| msgid "Batch Code" | ||||
| 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_detail.html:24 | ||||
| #: 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" | ||||
| msgstr "Externer Link" | ||||
|  | ||||
| #: build/models.py:156 stock/models.py:372 | ||||
| #: build/models.py:156 stock/models.py:367 | ||||
| msgid "Link to external 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 | ||||
| #: order/templates/order/purchase_order_detail.html:200 | ||||
| #: 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/stock.html:114 templates/js/stock.html:526 | ||||
| msgid "Notes" | ||||
| @@ -433,8 +433,8 @@ msgstr "Neues Lagerobjekt" | ||||
|  | ||||
| #: build/templates/build/allocate.html:161 | ||||
| #: order/templates/order/sales_order_detail.html:68 | ||||
| #: order/templates/order/sales_order_detail.html:150 stock/models.py:364 | ||||
| #: stock/templates/stock/item_base.html:153 | ||||
| #: order/templates/order/sales_order_detail.html:150 stock/models.py:359 | ||||
| #: stock/templates/stock/item_base.html:150 | ||||
| msgid "Serial Number" | ||||
| msgstr "Seriennummer" | ||||
|  | ||||
| @@ -451,7 +451,7 @@ msgstr "Seriennummer" | ||||
| #: part/templates/part/allocation.html:49 | ||||
| #: stock/templates/stock/item_base.html:26 | ||||
| #: stock/templates/stock/item_base.html:32 | ||||
| #: stock/templates/stock/item_base.html:159 | ||||
| #: stock/templates/stock/item_base.html:156 | ||||
| #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338 | ||||
| #: templates/js/bom.html:172 templates/js/build.html:52 | ||||
| #: templates/js/stock.html:673 | ||||
| @@ -460,7 +460,7 @@ msgstr "Anzahl" | ||||
|  | ||||
| #: build/templates/build/allocate.html:177 | ||||
| #: 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 | ||||
| #: templates/js/stock.html:508 | ||||
| msgid "Location" | ||||
| @@ -498,7 +498,7 @@ msgstr "Beschreibung" | ||||
| msgid "Reference" | ||||
| 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 | ||||
| msgid "Required" | ||||
| 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:34 | ||||
| #: 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 | ||||
| msgid "Build" | ||||
| msgstr "Bau" | ||||
| @@ -563,7 +563,7 @@ msgstr "Bau-Status" | ||||
| #: build/templates/build/build_base.html:80 | ||||
| #: build/templates/build/detail.html:42 | ||||
| #: order/templates/order/receive_parts.html:24 | ||||
| #: stock/templates/stock/item_base.html: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/order.html:235 templates/js/stock.html:495 | ||||
| msgid "Status" | ||||
| @@ -575,7 +575,7 @@ msgstr "Status" | ||||
| #: order/templates/order/sales_order_notes.html:10 | ||||
| #: order/templates/order/sales_order_ship.html:25 | ||||
| #: part/templates/part/allocation.html:27 | ||||
| #: stock/templates/stock/item_base.html:179 templates/js/order.html:209 | ||||
| #: stock/templates/stock/item_base.html:176 templates/js/order.html:209 | ||||
| msgid "Sales Order" | ||||
| msgstr "Bestellung" | ||||
|  | ||||
| @@ -644,7 +644,7 @@ msgid "Stock can be taken from any available location." | ||||
| msgstr "Bestand kann jedem verfügbaren Lagerort entnommen werden." | ||||
|  | ||||
| #: build/templates/build/detail.html:48 | ||||
| #: stock/templates/stock/item_base.html:209 templates/js/stock.html:503 | ||||
| #: stock/templates/stock/item_base.html:206 templates/js/stock.html:503 | ||||
| msgid "Batch" | ||||
| msgstr "Los" | ||||
|  | ||||
| @@ -942,8 +942,8 @@ msgstr "Kaufen Sie Teile von dieser Firma?" | ||||
| msgid "Does this company manufacture parts?" | ||||
| msgstr "Produziert diese Firma Teile?" | ||||
|  | ||||
| #: company/models.py:279 stock/models.py:324 | ||||
| #: stock/templates/stock/item_base.html:145 | ||||
| #: company/models.py:279 stock/models.py:319 | ||||
| #: stock/templates/stock/item_base.html:142 | ||||
| msgid "Base Part" | ||||
| msgstr "Basisteil" | ||||
|  | ||||
| @@ -1016,14 +1016,14 @@ msgstr "Hersteller" | ||||
| #: company/templates/company/supplier_part_detail.html:21 order/models.py:148 | ||||
| #: order/templates/order/order_base.html:74 | ||||
| #: order/templates/order/order_wizard/select_pos.html:30 | ||||
| #: stock/templates/stock/item_base.html: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 | ||||
| msgid "Supplier" | ||||
| msgstr "Zulieferer" | ||||
|  | ||||
| #: company/templates/company/detail.html:26 order/models.py:314 | ||||
| #: order/templates/order/sales_order_base.html:73 stock/models.py:359 | ||||
| #: stock/models.py:360 stock/templates/stock/item_base.html:166 | ||||
| #: order/templates/order/sales_order_base.html:73 stock/models.py:354 | ||||
| #: stock/models.py:355 stock/templates/stock/item_base.html:163 | ||||
| #: templates/js/company.html:44 templates/js/order.html:217 | ||||
| msgid "Customer" | ||||
| msgstr "Kunde" | ||||
| @@ -1137,8 +1137,8 @@ msgid "New Sales Order" | ||||
| msgstr "Neuer Auftrag" | ||||
|  | ||||
| #: company/templates/company/supplier_part_base.html:6 | ||||
| #: company/templates/company/supplier_part_base.html:19 stock/models.py:333 | ||||
| #: stock/templates/stock/item_base.html:249 templates/js/company.html:150 | ||||
| #: company/templates/company/supplier_part_base.html:19 stock/models.py:328 | ||||
| #: stock/templates/stock/item_base.html:246 templates/js/company.html:150 | ||||
| msgid "Supplier Part" | ||||
| msgstr "Zulieferer-Teil" | ||||
|  | ||||
| @@ -1410,8 +1410,8 @@ msgstr "Bestell-Notizen" | ||||
| msgid "Supplier order reference code" | ||||
| msgstr "Bestellreferenz" | ||||
|  | ||||
| #: order/models.py:185 order/models.py:259 part/views.py:1167 | ||||
| #: stock/models.py:238 stock/models.py:687 | ||||
| #: order/models.py:185 order/models.py:259 part/views.py:1250 | ||||
| #: stock/models.py:239 stock/models.py:682 | ||||
| msgid "Quantity must be greater than zero" | ||||
| 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/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" | ||||
| msgstr "Kaufvertrag" | ||||
|  | ||||
| @@ -1869,16 +1869,16 @@ msgstr "Zuordnung bearbeiten" | ||||
| msgid "Remove allocation" | ||||
| msgstr "Zuordnung entfernen" | ||||
|  | ||||
| #: part/bom.py:140 | ||||
| #: part/bom.py:144 | ||||
| #, python-brace-format | ||||
| msgid "Unsupported file format: {f}" | ||||
| msgstr "Nicht unterstütztes Dateiformat: {f}" | ||||
|  | ||||
| #: part/bom.py:145 | ||||
| #: part/bom.py:149 | ||||
| msgid "Error reading BOM file (invalid data)" | ||||
| 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)" | ||||
| msgstr "Fehler beim Lesen der Stückliste (ungültige Zeilengröße)" | ||||
|  | ||||
| @@ -1898,33 +1898,41 @@ msgstr "Kaskadierend" | ||||
| msgid "Download cascading / multi-level BOM" | ||||
| 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" | ||||
| msgstr "Bestätigen, dass die Stückliste korrekt ist" | ||||
|  | ||||
| #: part/forms.py:88 | ||||
| #: part/forms.py:90 | ||||
| msgid "Select BOM file to upload" | ||||
| msgstr "Stücklisten-Datei zum Upload auswählen" | ||||
|  | ||||
| #: part/forms.py:112 | ||||
| #: part/forms.py:114 | ||||
| msgid "Select part category" | ||||
| 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" | ||||
| msgstr "" | ||||
| "Tiefe Kopie ausführen. Dies wird alle Daten der Stückliste für dieses Teil " | ||||
| "duplizieren" | ||||
|  | ||||
| #: part/forms.py:131 | ||||
| #: part/forms.py:133 | ||||
| msgid "Confirm part creation" | ||||
| msgstr "Erstellen des Teils bestätigen" | ||||
|  | ||||
| #: part/forms.py:221 | ||||
| #: part/forms.py:223 | ||||
| msgid "Input quantity for price calculation" | ||||
| msgstr "Eintragsmenge zur Preisberechnung" | ||||
|  | ||||
| #: part/forms.py:224 | ||||
| #: part/forms.py:226 | ||||
| msgid "Select currency for price calculation" | ||||
| msgstr "Währung zur Preisberechnung wählen" | ||||
|  | ||||
| @@ -2037,13 +2045,13 @@ msgstr "Bemerkungen - unterstüzt Markdown-Formatierung" | ||||
| msgid "Stored BOM checksum" | ||||
| msgstr "Prüfsumme der Stückliste gespeichert" | ||||
|  | ||||
| #: part/models.py:1222 | ||||
| #: part/models.py:1223 | ||||
| #, fuzzy | ||||
| #| msgid "Stock item cannot be created for a template Part" | ||||
| msgid "Test templates can only be created for trackable parts" | ||||
| msgstr "Lagerobjekt kann nicht für Vorlagen-Teile angelegt werden" | ||||
|  | ||||
| #: part/models.py:1239 | ||||
| #: part/models.py:1240 | ||||
| #, fuzzy | ||||
| #| msgid "" | ||||
| #| "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 " | ||||
| "{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 | ||||
| #| msgid "Instance Name" | ||||
| msgid "Test Name" | ||||
| msgstr "Instanzname" | ||||
|  | ||||
| #: part/models.py:1259 | ||||
| #: part/models.py:1260 | ||||
| #, fuzzy | ||||
| #| msgid "Serial number for this item" | ||||
| msgid "Enter a name for the test" | ||||
| msgstr "Seriennummer für dieses Teil" | ||||
|  | ||||
| #: part/models.py:1264 | ||||
| #: part/models.py:1265 | ||||
| #, fuzzy | ||||
| #| msgid "Description" | ||||
| msgid "Test Description" | ||||
| msgstr "Beschreibung" | ||||
|  | ||||
| #: part/models.py:1265 | ||||
| #: part/models.py:1266 | ||||
| #, fuzzy | ||||
| #| msgid "Brief description of the build" | ||||
| msgid "Enter description for this test" | ||||
| msgstr "Kurze Beschreibung des Baus" | ||||
|  | ||||
| #: part/models.py:1271 | ||||
| #: part/models.py:1272 | ||||
| msgid "Is this test required to pass?" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1276 templates/js/part.html:367 | ||||
| #: part/models.py:1277 templates/js/part.html:367 | ||||
| #, fuzzy | ||||
| #| msgid "Required Parts" | ||||
| msgid "Requires Value" | ||||
| msgstr "benötigte Teile" | ||||
|  | ||||
| #: part/models.py:1277 | ||||
| #: part/models.py:1278 | ||||
| msgid "Does this test require a value when adding a test result?" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1282 templates/js/part.html:374 | ||||
| #: part/models.py:1283 templates/js/part.html:374 | ||||
| #, fuzzy | ||||
| #| msgid "Delete Attachment" | ||||
| msgid "Requires Attachment" | ||||
| 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?" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1316 | ||||
| #: part/models.py:1317 | ||||
| msgid "Parameter template name must be unique" | ||||
| msgstr "Vorlagen-Name des Parameters muss eindeutig sein" | ||||
|  | ||||
| #: part/models.py:1321 | ||||
| #: part/models.py:1322 | ||||
| msgid "Parameter Name" | ||||
| msgstr "Name des Parameters" | ||||
|  | ||||
| #: part/models.py:1323 | ||||
| #: part/models.py:1324 | ||||
| msgid "Parameter Units" | ||||
| msgstr "Parameter Einheit" | ||||
|  | ||||
| #: part/models.py:1349 | ||||
| #: part/models.py:1350 | ||||
| msgid "Parent Part" | ||||
| msgstr "Ausgangsteil" | ||||
|  | ||||
| #: part/models.py:1351 | ||||
| #: part/models.py:1352 | ||||
| msgid "Parameter Template" | ||||
| msgstr "Parameter Vorlage" | ||||
|  | ||||
| #: part/models.py:1353 | ||||
| #: part/models.py:1354 | ||||
| msgid "Parameter Value" | ||||
| msgstr "Parameter Wert" | ||||
|  | ||||
| #: part/models.py:1382 | ||||
| #: part/models.py:1383 | ||||
| msgid "Select parent part" | ||||
| msgstr "Ausgangsteil auswählen" | ||||
|  | ||||
| #: part/models.py:1390 | ||||
| #: part/models.py:1391 | ||||
| msgid "Select part to be used in BOM" | ||||
| 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" | ||||
| 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)" | ||||
| msgstr "Geschätzter Ausschuss (absolut oder prozentual)" | ||||
|  | ||||
| #: part/models.py:1402 | ||||
| #: part/models.py:1403 | ||||
| msgid "BOM item reference" | ||||
| msgstr "Referenz des Objekts auf der Stückliste" | ||||
|  | ||||
| #: part/models.py:1405 | ||||
| #: part/models.py:1406 | ||||
| msgid "BOM item notes" | ||||
| msgstr "Notizen zum Stücklisten-Objekt" | ||||
|  | ||||
| #: part/models.py:1407 | ||||
| #: part/models.py:1408 | ||||
| msgid "BOM line checksum" | ||||
| 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 | ||||
| #| msgid "Overage must be an integer value or a percentage" | ||||
| msgid "Quantity must be integer value for trackable parts" | ||||
| msgstr "Überschuss muss eine Ganzzahl oder ein Prozentwert sein" | ||||
|  | ||||
| #: part/models.py:1480 | ||||
| #: part/models.py:1481 | ||||
| msgid "Part cannot be added to its own Bill of Materials" | ||||
| msgstr "Teil kann nicht zu seiner eigenen Stückliste hinzugefügt werden" | ||||
|  | ||||
| #: part/models.py:1487 | ||||
| #: part/models.py:1488 | ||||
| #, python-brace-format | ||||
| msgid "Part '{p1}' is  used in BOM for '{p2}' (recursive)" | ||||
| msgstr "Teil '{p1}' wird in Stückliste für Teil '{p2}' benutzt (rekursiv)" | ||||
|  | ||||
| #: part/models.py:1494 | ||||
| #: part/models.py:1495 | ||||
| #, fuzzy | ||||
| #| msgid "New BOM Item" | ||||
| msgid "BOM Item" | ||||
| @@ -2189,14 +2198,14 @@ msgstr "Bestellung" | ||||
| #: part/templates/part/allocation.html:45 | ||||
| #: stock/templates/stock/item_base.html:8 | ||||
| #: stock/templates/stock/item_base.html:58 | ||||
| #: stock/templates/stock/item_base.html:231 | ||||
| #: stock/templates/stock/item_base.html:228 | ||||
| #: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106 | ||||
| #: templates/js/stock.html:643 | ||||
| msgid "Stock Item" | ||||
| msgstr "Lagerobjekt" | ||||
|  | ||||
| #: part/templates/part/allocation.html:20 | ||||
| #: stock/templates/stock/item_base.html:185 | ||||
| #: stock/templates/stock/item_base.html:182 | ||||
| msgid "Build Order" | ||||
| msgstr "Bauauftrag" | ||||
|  | ||||
| @@ -2232,10 +2241,94 @@ msgstr "Stückliste bearbeiten" | ||||
| msgid "Validate Bill of Materials" | ||||
| 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" | ||||
| 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 | ||||
| msgid "All parts" | ||||
| msgstr "Alle Teile" | ||||
| @@ -2440,7 +2533,7 @@ msgstr "Parameter hinzufügen" | ||||
| msgid "New 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 | ||||
| msgid "Value" | ||||
| msgstr "Wert" | ||||
| @@ -2647,7 +2740,7 @@ msgstr "Stückliste" | ||||
| msgid "Used 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" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -2758,91 +2851,91 @@ msgstr "Teileigenschaften bearbeiten" | ||||
| msgid "Validate BOM" | ||||
| msgstr "BOM validieren" | ||||
|  | ||||
| #: part/views.py:908 | ||||
| #: part/views.py:909 | ||||
| msgid "No BOM file provided" | ||||
| msgstr "Keine Stückliste angegeben" | ||||
|  | ||||
| #: part/views.py:1169 | ||||
| #: part/views.py:1259 | ||||
| msgid "Enter a valid quantity" | ||||
| 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" | ||||
| msgstr "Bitte ein gültiges Teil auswählen" | ||||
|  | ||||
| #: part/views.py:1202 | ||||
| #: part/views.py:1293 | ||||
| msgid "Duplicate part selected" | ||||
| msgstr "Teil doppelt ausgewählt" | ||||
|  | ||||
| #: part/views.py:1230 | ||||
| #: part/views.py:1329 | ||||
| msgid "Select a part" | ||||
| msgstr "Teil auswählen" | ||||
|  | ||||
| #: part/views.py:1234 | ||||
| #: part/views.py:1333 | ||||
| msgid "Specify quantity" | ||||
| msgstr "Anzahl angeben" | ||||
|  | ||||
| #: part/views.py:1450 | ||||
| #: part/views.py:1565 | ||||
| msgid "Confirm Part Deletion" | ||||
| msgstr "Löschen des Teils bestätigen" | ||||
|  | ||||
| #: part/views.py:1457 | ||||
| #: part/views.py:1572 | ||||
| msgid "Part was deleted" | ||||
| msgstr "Teil wurde gelöscht" | ||||
|  | ||||
| #: part/views.py:1466 | ||||
| #: part/views.py:1581 | ||||
| msgid "Part Pricing" | ||||
| msgstr "Teilbepreisung" | ||||
|  | ||||
| #: part/views.py:1588 | ||||
| #: part/views.py:1703 | ||||
| msgid "Create Part Parameter Template" | ||||
| msgstr "Teilparametervorlage anlegen" | ||||
|  | ||||
| #: part/views.py:1596 | ||||
| #: part/views.py:1711 | ||||
| msgid "Edit Part Parameter Template" | ||||
| msgstr "Teilparametervorlage bearbeiten" | ||||
|  | ||||
| #: part/views.py:1603 | ||||
| #: part/views.py:1718 | ||||
| msgid "Delete Part Parameter Template" | ||||
| msgstr "Teilparametervorlage löschen" | ||||
|  | ||||
| #: part/views.py:1611 | ||||
| #: part/views.py:1726 | ||||
| msgid "Create Part Parameter" | ||||
| msgstr "Teilparameter anlegen" | ||||
|  | ||||
| #: part/views.py:1661 | ||||
| #: part/views.py:1776 | ||||
| msgid "Edit Part Parameter" | ||||
| msgstr "Teilparameter bearbeiten" | ||||
|  | ||||
| #: part/views.py:1675 | ||||
| #: part/views.py:1790 | ||||
| msgid "Delete Part Parameter" | ||||
| msgstr "Teilparameter löschen" | ||||
|  | ||||
| #: part/views.py:1691 | ||||
| #: part/views.py:1806 | ||||
| msgid "Edit Part Category" | ||||
| msgstr "Teilkategorie bearbeiten" | ||||
|  | ||||
| #: part/views.py:1726 | ||||
| #: part/views.py:1841 | ||||
| msgid "Delete Part Category" | ||||
| msgstr "Teilkategorie löschen" | ||||
|  | ||||
| #: part/views.py:1732 | ||||
| #: part/views.py:1847 | ||||
| msgid "Part category was deleted" | ||||
| msgstr "Teilekategorie wurde gelöscht" | ||||
|  | ||||
| #: part/views.py:1740 | ||||
| #: part/views.py:1855 | ||||
| msgid "Create new part category" | ||||
| msgstr "Teilkategorie anlegen" | ||||
|  | ||||
| #: part/views.py:1791 | ||||
| #: part/views.py:1906 | ||||
| msgid "Create BOM item" | ||||
| msgstr "BOM-Position anlegen" | ||||
|  | ||||
| #: part/views.py:1857 | ||||
| #: part/views.py:1972 | ||||
| msgid "Edit BOM item" | ||||
| msgstr "BOM-Position beaarbeiten" | ||||
|  | ||||
| #: part/views.py:1905 | ||||
| #: part/views.py:2020 | ||||
| msgid "Confim BOM item deletion" | ||||
| 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" | ||||
| msgstr "Setze das Ziel als Standard-Ziel für ausgewählte Teile" | ||||
|  | ||||
| #: stock/models.py:209 | ||||
| #: stock/models.py:210 | ||||
| #, fuzzy | ||||
| #| msgid "A stock item with this serial number already exists" | ||||
| msgid "StockItem with this serial number already exists" | ||||
| msgstr "Ein Teil mit dieser Seriennummer existiert bereits" | ||||
|  | ||||
| #: stock/models.py:245 | ||||
| #: stock/models.py:246 | ||||
| #, python-brace-format | ||||
| msgid "Part type ('{pf}') must be {pe}" | ||||
| 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" | ||||
| 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" | ||||
| msgstr "" | ||||
| "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" | ||||
| msgstr "Teil kann nicht zu sich selbst gehören" | ||||
|  | ||||
| #: stock/models.py:316 | ||||
| #: stock/models.py:311 | ||||
| msgid "Parent Stock Item" | ||||
| msgstr "Eltern-Lagerobjekt" | ||||
|  | ||||
| #: stock/models.py:325 | ||||
| #: stock/models.py:320 | ||||
| msgid "Base part" | ||||
| msgstr "Basis-Teil" | ||||
|  | ||||
| #: stock/models.py:334 | ||||
| #: stock/models.py:329 | ||||
| msgid "Select a matching supplier part for this stock item" | ||||
| 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" | ||||
| msgstr "Lagerort" | ||||
|  | ||||
| #: stock/models.py:342 | ||||
| #: stock/models.py:337 | ||||
| msgid "Where is this stock item located?" | ||||
| msgstr "Wo wird dieses Teil normalerweise gelagert?" | ||||
|  | ||||
| #: stock/models.py:347 | ||||
| #: stock/models.py:342 | ||||
| msgid "Installed In" | ||||
| msgstr "Installiert in" | ||||
|  | ||||
| #: stock/models.py:350 | ||||
| #: stock/models.py:345 | ||||
| msgid "Is this item installed in another item?" | ||||
| msgstr "Ist dieses Teil in einem anderen verbaut?" | ||||
|  | ||||
| #: stock/models.py:366 | ||||
| #: stock/models.py:361 | ||||
| msgid "Serial number for this item" | ||||
| msgstr "Seriennummer für dieses Teil" | ||||
|  | ||||
| #: stock/models.py:378 | ||||
| #: stock/models.py:373 | ||||
| msgid "Batch code for this stock item" | ||||
| msgstr "Losnummer für dieses Lagerobjekt" | ||||
|  | ||||
| #: stock/models.py:382 | ||||
| #: stock/models.py:377 | ||||
| msgid "Stock Quantity" | ||||
| msgstr "Bestand" | ||||
|  | ||||
| #: stock/models.py:391 | ||||
| #: stock/models.py:386 | ||||
| msgid "Source Build" | ||||
| msgstr "Quellbau" | ||||
|  | ||||
| #: stock/models.py:393 | ||||
| #: stock/models.py:388 | ||||
| msgid "Build for this stock item" | ||||
| msgstr "Bau für dieses Lagerobjekt" | ||||
|  | ||||
| #: stock/models.py:400 | ||||
| #: stock/models.py:395 | ||||
| msgid "Source Purchase Order" | ||||
| msgstr "Quellbestellung" | ||||
|  | ||||
| #: stock/models.py:403 | ||||
| #: stock/models.py:398 | ||||
| msgid "Purchase order for this stock item" | ||||
| msgstr "Bestellung für dieses Teil" | ||||
|  | ||||
| #: stock/models.py:409 | ||||
| #: stock/models.py:404 | ||||
| msgid "Destination Sales Order" | ||||
| msgstr "Zielauftrag" | ||||
|  | ||||
| #: stock/models.py:416 | ||||
| #: stock/models.py:411 | ||||
| msgid "Destination Build Order" | ||||
| msgstr "Zielbauauftrag" | ||||
|  | ||||
| #: stock/models.py:429 | ||||
| #: stock/models.py:424 | ||||
| msgid "Delete this Stock Item when stock is depleted" | ||||
| 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 | ||||
| msgid "Stock Item Notes" | ||||
| msgstr "Lagerobjekt-Notizen" | ||||
|  | ||||
| #: stock/models.py:490 | ||||
| #: stock/models.py:485 | ||||
| #, fuzzy | ||||
| #| msgid "Item assigned to customer?" | ||||
| msgid "Assigned to Customer" | ||||
| msgstr "Ist dieses Objekt einem Kunden zugeteilt?" | ||||
|  | ||||
| #: stock/models.py:492 | ||||
| #: stock/models.py:487 | ||||
| #, fuzzy | ||||
| #| msgid "Item assigned to customer?" | ||||
| msgid "Manually assigned to customer" | ||||
| msgstr "Ist dieses Objekt einem Kunden zugeteilt?" | ||||
|  | ||||
| #: stock/models.py:505 | ||||
| #: stock/models.py:500 | ||||
| #, fuzzy | ||||
| #| msgid "Item assigned to customer?" | ||||
| msgid "Returned from customer" | ||||
| msgstr "Ist dieses Objekt einem Kunden zugeteilt?" | ||||
|  | ||||
| #: stock/models.py:507 | ||||
| #: stock/models.py:502 | ||||
| #, fuzzy | ||||
| #| msgid "Create new stock location" | ||||
| msgid "Returned to location" | ||||
| msgstr "Neuen Lagerort anlegen" | ||||
|  | ||||
| #: stock/models.py:678 | ||||
| #: stock/models.py:673 | ||||
| #, fuzzy | ||||
| #| msgid "Part is not a virtual part" | ||||
| msgid "Part is not set as trackable" | ||||
| msgstr "Teil ist nicht virtuell" | ||||
|  | ||||
| #: stock/models.py:684 | ||||
| #: stock/models.py:679 | ||||
| msgid "Quantity must be integer" | ||||
| msgstr "Anzahl muss eine Ganzzahl sein" | ||||
|  | ||||
| #: stock/models.py:690 | ||||
| #: stock/models.py:685 | ||||
| #, python-brace-format | ||||
| msgid "Quantity must not exceed available stock quantity ({n})" | ||||
| msgstr "Anzahl darf nicht die verfügbare Anzahl überschreiten ({n})" | ||||
|  | ||||
| #: stock/models.py:693 stock/models.py:696 | ||||
| #: stock/models.py:688 stock/models.py:691 | ||||
| msgid "Serial numbers must be a list of integers" | ||||
| msgstr "Seriennummern muss eine Liste von Ganzzahlen sein" | ||||
|  | ||||
| #: stock/models.py:699 | ||||
| #: stock/models.py:694 | ||||
| msgid "Quantity does not match serial numbers" | ||||
| msgstr "Anzahl stimmt nicht mit den Seriennummern überein" | ||||
|  | ||||
| #: stock/models.py:709 | ||||
| #: stock/models.py:704 | ||||
| msgid "Serial numbers already exist: " | ||||
| msgstr "Seriennummern existieren bereits:" | ||||
|  | ||||
| #: stock/models.py:734 | ||||
| #: stock/models.py:729 | ||||
| msgid "Add serial number" | ||||
| msgstr "Seriennummer hinzufügen" | ||||
|  | ||||
| #: stock/models.py:737 | ||||
| #: stock/models.py:732 | ||||
| #, python-brace-format | ||||
| msgid "Serialized {n} items" | ||||
| msgstr "{n} Teile serialisiert" | ||||
|  | ||||
| #: stock/models.py:848 | ||||
| #: stock/models.py:843 | ||||
| msgid "StockItem cannot be moved as it is not in stock" | ||||
| msgstr "Lagerobjekt kann nicht bewegt werden, da kein Bestand vorhanden ist" | ||||
|  | ||||
| #: stock/models.py:1175 | ||||
| #: stock/models.py:1170 | ||||
| msgid "Tracking entry title" | ||||
| msgstr "Name des Eintrags-Trackings" | ||||
|  | ||||
| #: stock/models.py:1177 | ||||
| #: stock/models.py:1172 | ||||
| msgid "Entry notes" | ||||
| msgstr "Eintrags-Notizen" | ||||
|  | ||||
| #: stock/models.py:1179 | ||||
| #: stock/models.py:1174 | ||||
| msgid "Link to external page for further information" | ||||
| msgstr "Link auf externe Seite für weitere Informationen" | ||||
|  | ||||
| #: stock/models.py:1239 | ||||
| #: stock/models.py:1234 | ||||
| #, fuzzy | ||||
| #| msgid "Serial number for this item" | ||||
| msgid "Value must be provided for this test" | ||||
| msgstr "Seriennummer für dieses Teil" | ||||
|  | ||||
| #: stock/models.py:1245 | ||||
| #: stock/models.py:1240 | ||||
| msgid "Attachment must be uploaded for this test" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1262 | ||||
| #: stock/models.py:1257 | ||||
| msgid "Test" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1263 | ||||
| #: stock/models.py:1258 | ||||
| #, fuzzy | ||||
| #| msgid "Part name" | ||||
| msgid "Test name" | ||||
| msgstr "Name des Teils" | ||||
|  | ||||
| #: stock/models.py:1268 | ||||
| #: stock/models.py:1263 | ||||
| #, fuzzy | ||||
| #| msgid "Search Results" | ||||
| msgid "Result" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1275 | ||||
| #: stock/models.py:1270 | ||||
| msgid "Test output value" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1281 | ||||
| #: stock/models.py:1276 | ||||
| #, fuzzy | ||||
| #| msgid "Attachments" | ||||
| msgid "Attachment" | ||||
| msgstr "Anhänge" | ||||
|  | ||||
| #: stock/models.py:1282 | ||||
| #: stock/models.py:1277 | ||||
| #, fuzzy | ||||
| #| msgid "Delete attachment" | ||||
| msgid "Test result attachment" | ||||
| msgstr "Anhang löschen" | ||||
|  | ||||
| #: stock/models.py:1288 | ||||
| #: stock/models.py:1283 | ||||
| #, fuzzy | ||||
| #| msgid "Edit notes" | ||||
| msgid "Test notes" | ||||
| @@ -3257,41 +3350,37 @@ msgstr "Lagerobjekt löschen" | ||||
| msgid "Generate test report" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:132 | ||||
| msgid "Print labels" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:140 | ||||
| #: stock/templates/stock/item_base.html:137 | ||||
| msgid "Stock Item Details" | ||||
| msgstr "Lagerbestands-Details" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:173 | ||||
| #: stock/templates/stock/item_base.html:170 | ||||
| msgid "Belongs To" | ||||
| msgstr "Gehört zu" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:195 | ||||
| #: stock/templates/stock/item_base.html:192 | ||||
| #, fuzzy | ||||
| #| msgid "No stock location set" | ||||
| msgid "No location set" | ||||
| msgstr "Kein Lagerort gesetzt" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:202 | ||||
| #: stock/templates/stock/item_base.html:199 | ||||
| msgid "Unique Identifier" | ||||
| msgstr "Eindeutiger Bezeichner" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:230 | ||||
| #: stock/templates/stock/item_base.html:227 | ||||
| msgid "Parent Item" | ||||
| msgstr "Elternposition" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:255 | ||||
| #: stock/templates/stock/item_base.html:252 | ||||
| msgid "Last Updated" | ||||
| msgstr "Zuletzt aktualisiert" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:260 | ||||
| #: stock/templates/stock/item_base.html:257 | ||||
| msgid "Last Stocktake" | ||||
| msgstr "Letzte Inventur" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:264 | ||||
| #: stock/templates/stock/item_base.html:261 | ||||
| msgid "No stocktake performed" | ||||
| msgstr "Keine Inventur ausgeführt" | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PACKAGE VERSION\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" | ||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | ||||
| @@ -42,30 +42,30 @@ msgstr "" | ||||
| msgid "Confirm new password" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: InvenTree/helpers.py:331 | ||||
| #: InvenTree/helpers.py:339 | ||||
| msgid "Empty serial number string" | ||||
| msgstr "" | ||||
|  | ||||
| #: InvenTree/helpers.py:352 InvenTree/helpers.py:369 | ||||
| #: InvenTree/helpers.py:360 InvenTree/helpers.py:377 | ||||
| #, python-brace-format | ||||
| msgid "Duplicate serial: {n}" | ||||
| msgstr "" | ||||
|  | ||||
| #: InvenTree/helpers.py:356 InvenTree/helpers.py:359 InvenTree/helpers.py:362 | ||||
| #: InvenTree/helpers.py:373 | ||||
| #: InvenTree/helpers.py:364 InvenTree/helpers.py:367 InvenTree/helpers.py:370 | ||||
| #: InvenTree/helpers.py:381 | ||||
| #, python-brace-format | ||||
| msgid "Invalid group: {g}" | ||||
| msgstr "" | ||||
|  | ||||
| #: InvenTree/helpers.py:379 | ||||
| #: InvenTree/helpers.py:387 | ||||
| msgid "No serial numbers found" | ||||
| msgstr "" | ||||
|  | ||||
| #: InvenTree/helpers.py:383 | ||||
| #: InvenTree/helpers.py:391 | ||||
| #, python-brace-format | ||||
| msgid "Number of unique serial number ({s}) must match quantity ({q})" | ||||
| msgstr "" | ||||
| @@ -322,7 +322,7 @@ msgstr "" | ||||
| msgid "Build status code" | ||||
| msgstr "" | ||||
|  | ||||
| #: build/models.py:136 stock/models.py:376 | ||||
| #: build/models.py:136 stock/models.py:371 | ||||
| msgid "Batch Code" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -334,11 +334,11 @@ msgstr "" | ||||
| #: company/templates/company/supplier_part_base.html:60 | ||||
| #: company/templates/company/supplier_part_detail.html:24 | ||||
| #: part/templates/part/detail.html:74 part/templates/part/part_base.html: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" | ||||
| msgstr "" | ||||
|  | ||||
| #: build/models.py:156 stock/models.py:372 | ||||
| #: build/models.py:156 stock/models.py:367 | ||||
| msgid "Link to external URL" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -346,7 +346,7 @@ msgstr "" | ||||
| #: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:15 | ||||
| #: order/templates/order/purchase_order_detail.html:200 | ||||
| #: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html: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/stock.html:114 templates/js/stock.html:526 | ||||
| msgid "Notes" | ||||
| @@ -413,8 +413,8 @@ msgstr "" | ||||
|  | ||||
| #: build/templates/build/allocate.html:161 | ||||
| #: order/templates/order/sales_order_detail.html:68 | ||||
| #: order/templates/order/sales_order_detail.html:150 stock/models.py:364 | ||||
| #: stock/templates/stock/item_base.html:153 | ||||
| #: order/templates/order/sales_order_detail.html:150 stock/models.py:359 | ||||
| #: stock/templates/stock/item_base.html:150 | ||||
| msgid "Serial Number" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -431,7 +431,7 @@ msgstr "" | ||||
| #: part/templates/part/allocation.html:49 | ||||
| #: stock/templates/stock/item_base.html:26 | ||||
| #: stock/templates/stock/item_base.html:32 | ||||
| #: stock/templates/stock/item_base.html:159 | ||||
| #: stock/templates/stock/item_base.html:156 | ||||
| #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338 | ||||
| #: templates/js/bom.html:172 templates/js/build.html:52 | ||||
| #: templates/js/stock.html:673 | ||||
| @@ -440,7 +440,7 @@ msgstr "" | ||||
|  | ||||
| #: build/templates/build/allocate.html:177 | ||||
| #: 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 | ||||
| #: templates/js/stock.html:508 | ||||
| msgid "Location" | ||||
| @@ -478,7 +478,7 @@ msgstr "" | ||||
| msgid "Reference" | ||||
| 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 | ||||
| msgid "Required" | ||||
| msgstr "" | ||||
| @@ -522,7 +522,7 @@ msgstr "" | ||||
| #: build/templates/build/build_base.html:8 | ||||
| #: build/templates/build/build_base.html:34 | ||||
| #: build/templates/build/complete.html:6 | ||||
| #: stock/templates/stock/item_base.html:216 templates/js/build.html:33 | ||||
| #: stock/templates/stock/item_base.html:213 templates/js/build.html:33 | ||||
| #: templates/navbar.html:12 | ||||
| msgid "Build" | ||||
| msgstr "" | ||||
| @@ -542,7 +542,7 @@ msgstr "" | ||||
| #: build/templates/build/build_base.html:80 | ||||
| #: build/templates/build/detail.html:42 | ||||
| #: order/templates/order/receive_parts.html:24 | ||||
| #: stock/templates/stock/item_base.html: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/order.html:235 templates/js/stock.html:495 | ||||
| msgid "Status" | ||||
| @@ -554,7 +554,7 @@ msgstr "" | ||||
| #: order/templates/order/sales_order_notes.html:10 | ||||
| #: order/templates/order/sales_order_ship.html:25 | ||||
| #: part/templates/part/allocation.html:27 | ||||
| #: stock/templates/stock/item_base.html:179 templates/js/order.html:209 | ||||
| #: stock/templates/stock/item_base.html:176 templates/js/order.html:209 | ||||
| msgid "Sales Order" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -621,7 +621,7 @@ msgid "Stock can be taken from any available location." | ||||
| msgstr "" | ||||
|  | ||||
| #: build/templates/build/detail.html:48 | ||||
| #: stock/templates/stock/item_base.html:209 templates/js/stock.html:503 | ||||
| #: stock/templates/stock/item_base.html:206 templates/js/stock.html:503 | ||||
| msgid "Batch" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -910,8 +910,8 @@ msgstr "" | ||||
| msgid "Does this company manufacture parts?" | ||||
| msgstr "" | ||||
|  | ||||
| #: company/models.py:279 stock/models.py:324 | ||||
| #: stock/templates/stock/item_base.html:145 | ||||
| #: company/models.py:279 stock/models.py:319 | ||||
| #: stock/templates/stock/item_base.html:142 | ||||
| msgid "Base Part" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -982,14 +982,14 @@ msgstr "" | ||||
| #: company/templates/company/supplier_part_detail.html:21 order/models.py:148 | ||||
| #: order/templates/order/order_base.html:74 | ||||
| #: order/templates/order/order_wizard/select_pos.html:30 | ||||
| #: stock/templates/stock/item_base.html: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 | ||||
| msgid "Supplier" | ||||
| msgstr "" | ||||
|  | ||||
| #: company/templates/company/detail.html:26 order/models.py:314 | ||||
| #: order/templates/order/sales_order_base.html:73 stock/models.py:359 | ||||
| #: stock/models.py:360 stock/templates/stock/item_base.html:166 | ||||
| #: order/templates/order/sales_order_base.html:73 stock/models.py:354 | ||||
| #: stock/models.py:355 stock/templates/stock/item_base.html:163 | ||||
| #: templates/js/company.html:44 templates/js/order.html:217 | ||||
| msgid "Customer" | ||||
| msgstr "" | ||||
| @@ -1102,8 +1102,8 @@ msgid "New Sales Order" | ||||
| msgstr "" | ||||
|  | ||||
| #: company/templates/company/supplier_part_base.html:6 | ||||
| #: company/templates/company/supplier_part_base.html:19 stock/models.py:333 | ||||
| #: stock/templates/stock/item_base.html:249 templates/js/company.html:150 | ||||
| #: company/templates/company/supplier_part_base.html:19 stock/models.py:328 | ||||
| #: stock/templates/stock/item_base.html:246 templates/js/company.html:150 | ||||
| msgid "Supplier Part" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -1367,8 +1367,8 @@ msgstr "" | ||||
| msgid "Supplier order reference code" | ||||
| msgstr "" | ||||
|  | ||||
| #: order/models.py:185 order/models.py:259 part/views.py:1167 | ||||
| #: stock/models.py:238 stock/models.py:687 | ||||
| #: order/models.py:185 order/models.py:259 part/views.py:1250 | ||||
| #: stock/models.py:239 stock/models.py:682 | ||||
| msgid "Quantity must be greater than zero" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -1402,7 +1402,7 @@ msgstr "" | ||||
|  | ||||
| #: order/models.py:466 order/templates/order/order_base.html:9 | ||||
| #: order/templates/order/order_base.html:23 | ||||
| #: stock/templates/stock/item_base.html:223 templates/js/order.html:136 | ||||
| #: stock/templates/stock/item_base.html:220 templates/js/order.html:136 | ||||
| msgid "Purchase Order" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -1819,16 +1819,16 @@ msgstr "" | ||||
| msgid "Remove allocation" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/bom.py:140 | ||||
| #: part/bom.py:144 | ||||
| #, python-brace-format | ||||
| msgid "Unsupported file format: {f}" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/bom.py:145 | ||||
| #: part/bom.py:149 | ||||
| msgid "Error reading BOM file (invalid data)" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/bom.py:147 | ||||
| #: part/bom.py:151 | ||||
| msgid "Error reading BOM file (incorrect row size)" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -1848,31 +1848,39 @@ msgstr "" | ||||
| msgid "Download cascading / multi-level BOM" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:88 | ||||
| #: part/forms.py:90 | ||||
| msgid "Select BOM file to upload" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:112 | ||||
| #: part/forms.py:114 | ||||
| msgid "Select part category" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:126 | ||||
| #: part/forms.py:128 | ||||
| msgid "Perform 'deep copy' which will duplicate all BOM data for this part" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:131 | ||||
| #: part/forms.py:133 | ||||
| msgid "Confirm part creation" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:221 | ||||
| #: part/forms.py:223 | ||||
| msgid "Input quantity for price calculation" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:224 | ||||
| #: part/forms.py:226 | ||||
| msgid "Select currency for price calculation" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -1985,116 +1993,117 @@ msgstr "" | ||||
| msgid "Stored BOM checksum" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1222 | ||||
| #: part/models.py:1223 | ||||
| msgid "Test templates can only be created for trackable parts" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1239 | ||||
| #: part/models.py:1240 | ||||
| msgid "Test with this name already exists for this part" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1259 | ||||
| #: part/models.py:1260 | ||||
| msgid "Enter a name for the test" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1264 | ||||
| #: part/models.py:1265 | ||||
| msgid "Test Description" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1265 | ||||
| #: part/models.py:1266 | ||||
| msgid "Enter description for this test" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1271 | ||||
| #: part/models.py:1272 | ||||
| msgid "Is this test required to pass?" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1276 templates/js/part.html:367 | ||||
| #: part/models.py:1277 templates/js/part.html:367 | ||||
| msgid "Requires Value" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1277 | ||||
| #: part/models.py:1278 | ||||
| msgid "Does this test require a value when adding a test result?" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1282 templates/js/part.html:374 | ||||
| #: part/models.py:1283 templates/js/part.html:374 | ||||
| msgid "Requires Attachment" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1283 | ||||
| #: part/models.py:1284 | ||||
| msgid "Does this test require a file attachment when adding a test result?" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1316 | ||||
| #: part/models.py:1317 | ||||
| msgid "Parameter template name must be unique" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1321 | ||||
| #: part/models.py:1322 | ||||
| msgid "Parameter Name" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1323 | ||||
| #: part/models.py:1324 | ||||
| msgid "Parameter Units" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1349 | ||||
| #: part/models.py:1350 | ||||
| msgid "Parent Part" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1351 | ||||
| #: part/models.py:1352 | ||||
| msgid "Parameter Template" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1353 | ||||
| #: part/models.py:1354 | ||||
| msgid "Parameter Value" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1382 | ||||
| #: part/models.py:1383 | ||||
| msgid "Select parent part" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1390 | ||||
| #: part/models.py:1391 | ||||
| msgid "Select part to be used in BOM" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1396 | ||||
| #: part/models.py:1397 | ||||
| msgid "BOM quantity for this BOM item" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1399 | ||||
| #: part/models.py:1400 | ||||
| msgid "Estimated build wastage quantity (absolute or percentage)" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1402 | ||||
| #: part/models.py:1403 | ||||
| msgid "BOM item reference" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1405 | ||||
| #: part/models.py:1406 | ||||
| msgid "BOM item notes" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1407 | ||||
| #: part/models.py:1408 | ||||
| msgid "BOM line checksum" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1480 | ||||
| #: part/models.py:1481 | ||||
| msgid "Part cannot be added to its own Bill of Materials" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1487 | ||||
| #: part/models.py:1488 | ||||
| #, python-brace-format | ||||
| msgid "Part '{p1}' is  used in BOM for '{p2}' (recursive)" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1494 | ||||
| #: part/models.py:1495 | ||||
| msgid "BOM Item" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -2113,14 +2122,14 @@ msgstr "" | ||||
| #: part/templates/part/allocation.html:45 | ||||
| #: stock/templates/stock/item_base.html:8 | ||||
| #: stock/templates/stock/item_base.html:58 | ||||
| #: stock/templates/stock/item_base.html:231 | ||||
| #: stock/templates/stock/item_base.html:228 | ||||
| #: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106 | ||||
| #: templates/js/stock.html:643 | ||||
| msgid "Stock Item" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/templates/part/allocation.html:20 | ||||
| #: stock/templates/stock/item_base.html:185 | ||||
| #: stock/templates/stock/item_base.html:182 | ||||
| msgid "Build Order" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -2156,10 +2165,78 @@ msgstr "" | ||||
| msgid "Validate Bill of Materials" | ||||
| 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" | ||||
| 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 | ||||
| msgid "All parts" | ||||
| msgstr "" | ||||
| @@ -2354,7 +2431,7 @@ msgstr "" | ||||
| msgid "New Parameter" | ||||
| 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 | ||||
| msgid "Value" | ||||
| msgstr "" | ||||
| @@ -2535,7 +2612,7 @@ msgstr "" | ||||
| msgid "Used In" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -2640,91 +2717,91 @@ msgstr "" | ||||
| msgid "Validate BOM" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:908 | ||||
| #: part/views.py:909 | ||||
| msgid "No BOM file provided" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1169 | ||||
| #: part/views.py:1259 | ||||
| msgid "Enter a valid quantity" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1193 part/views.py:1196 | ||||
| #: part/views.py:1284 part/views.py:1287 | ||||
| msgid "Select valid part" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1202 | ||||
| #: part/views.py:1293 | ||||
| msgid "Duplicate part selected" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1230 | ||||
| #: part/views.py:1329 | ||||
| msgid "Select a part" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1234 | ||||
| #: part/views.py:1333 | ||||
| msgid "Specify quantity" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1450 | ||||
| #: part/views.py:1565 | ||||
| msgid "Confirm Part Deletion" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1457 | ||||
| #: part/views.py:1572 | ||||
| msgid "Part was deleted" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1466 | ||||
| #: part/views.py:1581 | ||||
| msgid "Part Pricing" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1588 | ||||
| #: part/views.py:1703 | ||||
| msgid "Create Part Parameter Template" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1596 | ||||
| #: part/views.py:1711 | ||||
| msgid "Edit Part Parameter Template" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1603 | ||||
| #: part/views.py:1718 | ||||
| msgid "Delete Part Parameter Template" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1611 | ||||
| #: part/views.py:1726 | ||||
| msgid "Create Part Parameter" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1661 | ||||
| #: part/views.py:1776 | ||||
| msgid "Edit Part Parameter" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1675 | ||||
| #: part/views.py:1790 | ||||
| msgid "Delete Part Parameter" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1691 | ||||
| #: part/views.py:1806 | ||||
| msgid "Edit Part Category" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1726 | ||||
| #: part/views.py:1841 | ||||
| msgid "Delete Part Category" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1732 | ||||
| #: part/views.py:1847 | ||||
| msgid "Part category was deleted" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1740 | ||||
| #: part/views.py:1855 | ||||
| msgid "Create new part category" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1791 | ||||
| #: part/views.py:1906 | ||||
| msgid "Create BOM item" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1857 | ||||
| #: part/views.py:1972 | ||||
| msgid "Edit BOM item" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1905 | ||||
| #: part/views.py:2020 | ||||
| msgid "Confim BOM item deletion" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -2776,203 +2853,203 @@ msgstr "" | ||||
| msgid "Set the destination as the default location for selected parts" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:209 | ||||
| #: stock/models.py:210 | ||||
| msgid "StockItem with this serial number already exists" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:245 | ||||
| #: stock/models.py:246 | ||||
| #, python-brace-format | ||||
| msgid "Part type ('{pf}') must be {pe}" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:256 | ||||
| #: stock/models.py:257 | ||||
| msgid "Serial number cannot be set if quantity greater than 1" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:277 | ||||
| #: stock/models.py:278 | ||||
| msgid "Item cannot belong to itself" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:316 | ||||
| #: stock/models.py:311 | ||||
| msgid "Parent Stock Item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:325 | ||||
| #: stock/models.py:320 | ||||
| msgid "Base part" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:334 | ||||
| #: stock/models.py:329 | ||||
| msgid "Select a matching supplier part for this stock item" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:342 | ||||
| #: stock/models.py:337 | ||||
| msgid "Where is this stock item located?" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:347 | ||||
| #: stock/models.py:342 | ||||
| msgid "Installed In" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:350 | ||||
| #: stock/models.py:345 | ||||
| msgid "Is this item installed in another item?" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:366 | ||||
| #: stock/models.py:361 | ||||
| msgid "Serial number for this item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:378 | ||||
| #: stock/models.py:373 | ||||
| msgid "Batch code for this stock item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:382 | ||||
| #: stock/models.py:377 | ||||
| msgid "Stock Quantity" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:391 | ||||
| #: stock/models.py:386 | ||||
| msgid "Source Build" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:393 | ||||
| #: stock/models.py:388 | ||||
| msgid "Build for this stock item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:400 | ||||
| #: stock/models.py:395 | ||||
| msgid "Source Purchase Order" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:403 | ||||
| #: stock/models.py:398 | ||||
| msgid "Purchase order for this stock item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:409 | ||||
| #: stock/models.py:404 | ||||
| msgid "Destination Sales Order" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:416 | ||||
| #: stock/models.py:411 | ||||
| msgid "Destination Build Order" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:429 | ||||
| #: stock/models.py:424 | ||||
| msgid "Delete this Stock Item when stock is depleted" | ||||
| 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 | ||||
| msgid "Stock Item Notes" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:490 | ||||
| #: stock/models.py:485 | ||||
| msgid "Assigned to Customer" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:492 | ||||
| #: stock/models.py:487 | ||||
| msgid "Manually assigned to customer" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:505 | ||||
| #: stock/models.py:500 | ||||
| msgid "Returned from customer" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:507 | ||||
| #: stock/models.py:502 | ||||
| msgid "Returned to location" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:678 | ||||
| #: stock/models.py:673 | ||||
| msgid "Part is not set as trackable" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:684 | ||||
| #: stock/models.py:679 | ||||
| msgid "Quantity must be integer" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:690 | ||||
| #: stock/models.py:685 | ||||
| #, python-brace-format | ||||
| msgid "Quantity must not exceed available stock quantity ({n})" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:699 | ||||
| #: stock/models.py:694 | ||||
| msgid "Quantity does not match serial numbers" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:709 | ||||
| #: stock/models.py:704 | ||||
| msgid "Serial numbers already exist: " | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:734 | ||||
| #: stock/models.py:729 | ||||
| msgid "Add serial number" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:737 | ||||
| #: stock/models.py:732 | ||||
| #, python-brace-format | ||||
| msgid "Serialized {n} items" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:848 | ||||
| #: stock/models.py:843 | ||||
| msgid "StockItem cannot be moved as it is not in stock" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1175 | ||||
| #: stock/models.py:1170 | ||||
| msgid "Tracking entry title" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1177 | ||||
| #: stock/models.py:1172 | ||||
| msgid "Entry notes" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1179 | ||||
| #: stock/models.py:1174 | ||||
| msgid "Link to external page for further information" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1239 | ||||
| #: stock/models.py:1234 | ||||
| msgid "Value must be provided for this test" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1245 | ||||
| #: stock/models.py:1240 | ||||
| msgid "Attachment must be uploaded for this test" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1262 | ||||
| #: stock/models.py:1257 | ||||
| msgid "Test" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1263 | ||||
| #: stock/models.py:1258 | ||||
| msgid "Test name" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1268 | ||||
| #: stock/models.py:1263 | ||||
| msgid "Result" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1269 templates/js/table_filters.html:90 | ||||
| #: stock/models.py:1264 templates/js/table_filters.html:90 | ||||
| msgid "Test result" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1275 | ||||
| #: stock/models.py:1270 | ||||
| msgid "Test output value" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1281 | ||||
| #: stock/models.py:1276 | ||||
| msgid "Attachment" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1282 | ||||
| #: stock/models.py:1277 | ||||
| msgid "Test result attachment" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1288 | ||||
| #: stock/models.py:1283 | ||||
| msgid "Test notes" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -3078,39 +3155,35 @@ msgstr "" | ||||
| msgid "Generate test report" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:132 | ||||
| msgid "Print labels" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:140 | ||||
| #: stock/templates/stock/item_base.html:137 | ||||
| msgid "Stock Item Details" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:173 | ||||
| #: stock/templates/stock/item_base.html:170 | ||||
| msgid "Belongs To" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:195 | ||||
| #: stock/templates/stock/item_base.html:192 | ||||
| msgid "No location set" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:202 | ||||
| #: stock/templates/stock/item_base.html:199 | ||||
| msgid "Unique Identifier" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:230 | ||||
| #: stock/templates/stock/item_base.html:227 | ||||
| msgid "Parent Item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:255 | ||||
| #: stock/templates/stock/item_base.html:252 | ||||
| msgid "Last Updated" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:260 | ||||
| #: stock/templates/stock/item_base.html:257 | ||||
| msgid "Last Stocktake" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:264 | ||||
| #: stock/templates/stock/item_base.html:261 | ||||
| msgid "No stocktake performed" | ||||
| msgstr "" | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: PACKAGE VERSION\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" | ||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | ||||
| @@ -42,30 +42,30 @@ msgstr "" | ||||
| msgid "Confirm new password" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: InvenTree/helpers.py:331 | ||||
| #: InvenTree/helpers.py:339 | ||||
| msgid "Empty serial number string" | ||||
| msgstr "" | ||||
|  | ||||
| #: InvenTree/helpers.py:352 InvenTree/helpers.py:369 | ||||
| #: InvenTree/helpers.py:360 InvenTree/helpers.py:377 | ||||
| #, python-brace-format | ||||
| msgid "Duplicate serial: {n}" | ||||
| msgstr "" | ||||
|  | ||||
| #: InvenTree/helpers.py:356 InvenTree/helpers.py:359 InvenTree/helpers.py:362 | ||||
| #: InvenTree/helpers.py:373 | ||||
| #: InvenTree/helpers.py:364 InvenTree/helpers.py:367 InvenTree/helpers.py:370 | ||||
| #: InvenTree/helpers.py:381 | ||||
| #, python-brace-format | ||||
| msgid "Invalid group: {g}" | ||||
| msgstr "" | ||||
|  | ||||
| #: InvenTree/helpers.py:379 | ||||
| #: InvenTree/helpers.py:387 | ||||
| msgid "No serial numbers found" | ||||
| msgstr "" | ||||
|  | ||||
| #: InvenTree/helpers.py:383 | ||||
| #: InvenTree/helpers.py:391 | ||||
| #, python-brace-format | ||||
| msgid "Number of unique serial number ({s}) must match quantity ({q})" | ||||
| msgstr "" | ||||
| @@ -322,7 +322,7 @@ msgstr "" | ||||
| msgid "Build status code" | ||||
| msgstr "" | ||||
|  | ||||
| #: build/models.py:136 stock/models.py:376 | ||||
| #: build/models.py:136 stock/models.py:371 | ||||
| msgid "Batch Code" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -334,11 +334,11 @@ msgstr "" | ||||
| #: company/templates/company/supplier_part_base.html:60 | ||||
| #: company/templates/company/supplier_part_detail.html:24 | ||||
| #: part/templates/part/detail.html:74 part/templates/part/part_base.html: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" | ||||
| msgstr "" | ||||
|  | ||||
| #: build/models.py:156 stock/models.py:372 | ||||
| #: build/models.py:156 stock/models.py:367 | ||||
| msgid "Link to external URL" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -346,7 +346,7 @@ msgstr "" | ||||
| #: company/templates/company/tabs.html:33 order/templates/order/po_tabs.html:15 | ||||
| #: order/templates/order/purchase_order_detail.html:200 | ||||
| #: order/templates/order/so_tabs.html:23 part/templates/part/tabs.html: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/stock.html:114 templates/js/stock.html:526 | ||||
| msgid "Notes" | ||||
| @@ -413,8 +413,8 @@ msgstr "" | ||||
|  | ||||
| #: build/templates/build/allocate.html:161 | ||||
| #: order/templates/order/sales_order_detail.html:68 | ||||
| #: order/templates/order/sales_order_detail.html:150 stock/models.py:364 | ||||
| #: stock/templates/stock/item_base.html:153 | ||||
| #: order/templates/order/sales_order_detail.html:150 stock/models.py:359 | ||||
| #: stock/templates/stock/item_base.html:150 | ||||
| msgid "Serial Number" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -431,7 +431,7 @@ msgstr "" | ||||
| #: part/templates/part/allocation.html:49 | ||||
| #: stock/templates/stock/item_base.html:26 | ||||
| #: stock/templates/stock/item_base.html:32 | ||||
| #: stock/templates/stock/item_base.html:159 | ||||
| #: stock/templates/stock/item_base.html:156 | ||||
| #: stock/templates/stock/stock_adjust.html:18 templates/js/barcode.html:338 | ||||
| #: templates/js/bom.html:172 templates/js/build.html:52 | ||||
| #: templates/js/stock.html:673 | ||||
| @@ -440,7 +440,7 @@ msgstr "" | ||||
|  | ||||
| #: build/templates/build/allocate.html:177 | ||||
| #: 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 | ||||
| #: templates/js/stock.html:508 | ||||
| msgid "Location" | ||||
| @@ -478,7 +478,7 @@ msgstr "" | ||||
| msgid "Reference" | ||||
| 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 | ||||
| msgid "Required" | ||||
| msgstr "" | ||||
| @@ -522,7 +522,7 @@ msgstr "" | ||||
| #: build/templates/build/build_base.html:8 | ||||
| #: build/templates/build/build_base.html:34 | ||||
| #: build/templates/build/complete.html:6 | ||||
| #: stock/templates/stock/item_base.html:216 templates/js/build.html:33 | ||||
| #: stock/templates/stock/item_base.html:213 templates/js/build.html:33 | ||||
| #: templates/navbar.html:12 | ||||
| msgid "Build" | ||||
| msgstr "" | ||||
| @@ -542,7 +542,7 @@ msgstr "" | ||||
| #: build/templates/build/build_base.html:80 | ||||
| #: build/templates/build/detail.html:42 | ||||
| #: order/templates/order/receive_parts.html:24 | ||||
| #: stock/templates/stock/item_base.html: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/order.html:235 templates/js/stock.html:495 | ||||
| msgid "Status" | ||||
| @@ -554,7 +554,7 @@ msgstr "" | ||||
| #: order/templates/order/sales_order_notes.html:10 | ||||
| #: order/templates/order/sales_order_ship.html:25 | ||||
| #: part/templates/part/allocation.html:27 | ||||
| #: stock/templates/stock/item_base.html:179 templates/js/order.html:209 | ||||
| #: stock/templates/stock/item_base.html:176 templates/js/order.html:209 | ||||
| msgid "Sales Order" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -621,7 +621,7 @@ msgid "Stock can be taken from any available location." | ||||
| msgstr "" | ||||
|  | ||||
| #: build/templates/build/detail.html:48 | ||||
| #: stock/templates/stock/item_base.html:209 templates/js/stock.html:503 | ||||
| #: stock/templates/stock/item_base.html:206 templates/js/stock.html:503 | ||||
| msgid "Batch" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -910,8 +910,8 @@ msgstr "" | ||||
| msgid "Does this company manufacture parts?" | ||||
| msgstr "" | ||||
|  | ||||
| #: company/models.py:279 stock/models.py:324 | ||||
| #: stock/templates/stock/item_base.html:145 | ||||
| #: company/models.py:279 stock/models.py:319 | ||||
| #: stock/templates/stock/item_base.html:142 | ||||
| msgid "Base Part" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -982,14 +982,14 @@ msgstr "" | ||||
| #: company/templates/company/supplier_part_detail.html:21 order/models.py:148 | ||||
| #: order/templates/order/order_base.html:74 | ||||
| #: order/templates/order/order_wizard/select_pos.html:30 | ||||
| #: stock/templates/stock/item_base.html: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 | ||||
| msgid "Supplier" | ||||
| msgstr "" | ||||
|  | ||||
| #: company/templates/company/detail.html:26 order/models.py:314 | ||||
| #: order/templates/order/sales_order_base.html:73 stock/models.py:359 | ||||
| #: stock/models.py:360 stock/templates/stock/item_base.html:166 | ||||
| #: order/templates/order/sales_order_base.html:73 stock/models.py:354 | ||||
| #: stock/models.py:355 stock/templates/stock/item_base.html:163 | ||||
| #: templates/js/company.html:44 templates/js/order.html:217 | ||||
| msgid "Customer" | ||||
| msgstr "" | ||||
| @@ -1102,8 +1102,8 @@ msgid "New Sales Order" | ||||
| msgstr "" | ||||
|  | ||||
| #: company/templates/company/supplier_part_base.html:6 | ||||
| #: company/templates/company/supplier_part_base.html:19 stock/models.py:333 | ||||
| #: stock/templates/stock/item_base.html:249 templates/js/company.html:150 | ||||
| #: company/templates/company/supplier_part_base.html:19 stock/models.py:328 | ||||
| #: stock/templates/stock/item_base.html:246 templates/js/company.html:150 | ||||
| msgid "Supplier Part" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -1367,8 +1367,8 @@ msgstr "" | ||||
| msgid "Supplier order reference code" | ||||
| msgstr "" | ||||
|  | ||||
| #: order/models.py:185 order/models.py:259 part/views.py:1167 | ||||
| #: stock/models.py:238 stock/models.py:687 | ||||
| #: order/models.py:185 order/models.py:259 part/views.py:1250 | ||||
| #: stock/models.py:239 stock/models.py:682 | ||||
| msgid "Quantity must be greater than zero" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -1402,7 +1402,7 @@ msgstr "" | ||||
|  | ||||
| #: order/models.py:466 order/templates/order/order_base.html:9 | ||||
| #: order/templates/order/order_base.html:23 | ||||
| #: stock/templates/stock/item_base.html:223 templates/js/order.html:136 | ||||
| #: stock/templates/stock/item_base.html:220 templates/js/order.html:136 | ||||
| msgid "Purchase Order" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -1819,16 +1819,16 @@ msgstr "" | ||||
| msgid "Remove allocation" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/bom.py:140 | ||||
| #: part/bom.py:144 | ||||
| #, python-brace-format | ||||
| msgid "Unsupported file format: {f}" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/bom.py:145 | ||||
| #: part/bom.py:149 | ||||
| msgid "Error reading BOM file (invalid data)" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/bom.py:147 | ||||
| #: part/bom.py:151 | ||||
| msgid "Error reading BOM file (incorrect row size)" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -1848,31 +1848,39 @@ msgstr "" | ||||
| msgid "Download cascading / multi-level BOM" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:88 | ||||
| #: part/forms.py:90 | ||||
| msgid "Select BOM file to upload" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:112 | ||||
| #: part/forms.py:114 | ||||
| msgid "Select part category" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:126 | ||||
| #: part/forms.py:128 | ||||
| msgid "Perform 'deep copy' which will duplicate all BOM data for this part" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:131 | ||||
| #: part/forms.py:133 | ||||
| msgid "Confirm part creation" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:221 | ||||
| #: part/forms.py:223 | ||||
| msgid "Input quantity for price calculation" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/forms.py:224 | ||||
| #: part/forms.py:226 | ||||
| msgid "Select currency for price calculation" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -1985,116 +1993,117 @@ msgstr "" | ||||
| msgid "Stored BOM checksum" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1222 | ||||
| #: part/models.py:1223 | ||||
| msgid "Test templates can only be created for trackable parts" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1239 | ||||
| #: part/models.py:1240 | ||||
| msgid "Test with this name already exists for this part" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1259 | ||||
| #: part/models.py:1260 | ||||
| msgid "Enter a name for the test" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1264 | ||||
| #: part/models.py:1265 | ||||
| msgid "Test Description" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1265 | ||||
| #: part/models.py:1266 | ||||
| msgid "Enter description for this test" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1271 | ||||
| #: part/models.py:1272 | ||||
| msgid "Is this test required to pass?" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1276 templates/js/part.html:367 | ||||
| #: part/models.py:1277 templates/js/part.html:367 | ||||
| msgid "Requires Value" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1277 | ||||
| #: part/models.py:1278 | ||||
| msgid "Does this test require a value when adding a test result?" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1282 templates/js/part.html:374 | ||||
| #: part/models.py:1283 templates/js/part.html:374 | ||||
| msgid "Requires Attachment" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1283 | ||||
| #: part/models.py:1284 | ||||
| msgid "Does this test require a file attachment when adding a test result?" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1316 | ||||
| #: part/models.py:1317 | ||||
| msgid "Parameter template name must be unique" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1321 | ||||
| #: part/models.py:1322 | ||||
| msgid "Parameter Name" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1323 | ||||
| #: part/models.py:1324 | ||||
| msgid "Parameter Units" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1349 | ||||
| #: part/models.py:1350 | ||||
| msgid "Parent Part" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1351 | ||||
| #: part/models.py:1352 | ||||
| msgid "Parameter Template" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1353 | ||||
| #: part/models.py:1354 | ||||
| msgid "Parameter Value" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1382 | ||||
| #: part/models.py:1383 | ||||
| msgid "Select parent part" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1390 | ||||
| #: part/models.py:1391 | ||||
| msgid "Select part to be used in BOM" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1396 | ||||
| #: part/models.py:1397 | ||||
| msgid "BOM quantity for this BOM item" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1399 | ||||
| #: part/models.py:1400 | ||||
| msgid "Estimated build wastage quantity (absolute or percentage)" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1402 | ||||
| #: part/models.py:1403 | ||||
| msgid "BOM item reference" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1405 | ||||
| #: part/models.py:1406 | ||||
| msgid "BOM item notes" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1407 | ||||
| #: part/models.py:1408 | ||||
| msgid "BOM line checksum" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1480 | ||||
| #: part/models.py:1481 | ||||
| msgid "Part cannot be added to its own Bill of Materials" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1487 | ||||
| #: part/models.py:1488 | ||||
| #, python-brace-format | ||||
| msgid "Part '{p1}' is  used in BOM for '{p2}' (recursive)" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/models.py:1494 | ||||
| #: part/models.py:1495 | ||||
| msgid "BOM Item" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -2113,14 +2122,14 @@ msgstr "" | ||||
| #: part/templates/part/allocation.html:45 | ||||
| #: stock/templates/stock/item_base.html:8 | ||||
| #: stock/templates/stock/item_base.html:58 | ||||
| #: stock/templates/stock/item_base.html:231 | ||||
| #: stock/templates/stock/item_base.html:228 | ||||
| #: stock/templates/stock/stock_adjust.html:16 templates/js/build.html:106 | ||||
| #: templates/js/stock.html:643 | ||||
| msgid "Stock Item" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/templates/part/allocation.html:20 | ||||
| #: stock/templates/stock/item_base.html:185 | ||||
| #: stock/templates/stock/item_base.html:182 | ||||
| msgid "Build Order" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -2156,10 +2165,78 @@ msgstr "" | ||||
| msgid "Validate Bill of Materials" | ||||
| 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" | ||||
| 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 | ||||
| msgid "All parts" | ||||
| msgstr "" | ||||
| @@ -2354,7 +2431,7 @@ msgstr "" | ||||
| msgid "New Parameter" | ||||
| 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 | ||||
| msgid "Value" | ||||
| msgstr "" | ||||
| @@ -2535,7 +2612,7 @@ msgstr "" | ||||
| msgid "Used In" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -2640,91 +2717,91 @@ msgstr "" | ||||
| msgid "Validate BOM" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:908 | ||||
| #: part/views.py:909 | ||||
| msgid "No BOM file provided" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1169 | ||||
| #: part/views.py:1259 | ||||
| msgid "Enter a valid quantity" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1193 part/views.py:1196 | ||||
| #: part/views.py:1284 part/views.py:1287 | ||||
| msgid "Select valid part" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1202 | ||||
| #: part/views.py:1293 | ||||
| msgid "Duplicate part selected" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1230 | ||||
| #: part/views.py:1329 | ||||
| msgid "Select a part" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1234 | ||||
| #: part/views.py:1333 | ||||
| msgid "Specify quantity" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1450 | ||||
| #: part/views.py:1565 | ||||
| msgid "Confirm Part Deletion" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1457 | ||||
| #: part/views.py:1572 | ||||
| msgid "Part was deleted" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1466 | ||||
| #: part/views.py:1581 | ||||
| msgid "Part Pricing" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1588 | ||||
| #: part/views.py:1703 | ||||
| msgid "Create Part Parameter Template" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1596 | ||||
| #: part/views.py:1711 | ||||
| msgid "Edit Part Parameter Template" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1603 | ||||
| #: part/views.py:1718 | ||||
| msgid "Delete Part Parameter Template" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1611 | ||||
| #: part/views.py:1726 | ||||
| msgid "Create Part Parameter" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1661 | ||||
| #: part/views.py:1776 | ||||
| msgid "Edit Part Parameter" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1675 | ||||
| #: part/views.py:1790 | ||||
| msgid "Delete Part Parameter" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1691 | ||||
| #: part/views.py:1806 | ||||
| msgid "Edit Part Category" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1726 | ||||
| #: part/views.py:1841 | ||||
| msgid "Delete Part Category" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1732 | ||||
| #: part/views.py:1847 | ||||
| msgid "Part category was deleted" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1740 | ||||
| #: part/views.py:1855 | ||||
| msgid "Create new part category" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1791 | ||||
| #: part/views.py:1906 | ||||
| msgid "Create BOM item" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1857 | ||||
| #: part/views.py:1972 | ||||
| msgid "Edit BOM item" | ||||
| msgstr "" | ||||
|  | ||||
| #: part/views.py:1905 | ||||
| #: part/views.py:2020 | ||||
| msgid "Confim BOM item deletion" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -2776,203 +2853,203 @@ msgstr "" | ||||
| msgid "Set the destination as the default location for selected parts" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:209 | ||||
| #: stock/models.py:210 | ||||
| msgid "StockItem with this serial number already exists" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:245 | ||||
| #: stock/models.py:246 | ||||
| #, python-brace-format | ||||
| msgid "Part type ('{pf}') must be {pe}" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:256 | ||||
| #: stock/models.py:257 | ||||
| msgid "Serial number cannot be set if quantity greater than 1" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:277 | ||||
| #: stock/models.py:278 | ||||
| msgid "Item cannot belong to itself" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:316 | ||||
| #: stock/models.py:311 | ||||
| msgid "Parent Stock Item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:325 | ||||
| #: stock/models.py:320 | ||||
| msgid "Base part" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:334 | ||||
| #: stock/models.py:329 | ||||
| msgid "Select a matching supplier part for this stock item" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:342 | ||||
| #: stock/models.py:337 | ||||
| msgid "Where is this stock item located?" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:347 | ||||
| #: stock/models.py:342 | ||||
| msgid "Installed In" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:350 | ||||
| #: stock/models.py:345 | ||||
| msgid "Is this item installed in another item?" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:366 | ||||
| #: stock/models.py:361 | ||||
| msgid "Serial number for this item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:378 | ||||
| #: stock/models.py:373 | ||||
| msgid "Batch code for this stock item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:382 | ||||
| #: stock/models.py:377 | ||||
| msgid "Stock Quantity" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:391 | ||||
| #: stock/models.py:386 | ||||
| msgid "Source Build" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:393 | ||||
| #: stock/models.py:388 | ||||
| msgid "Build for this stock item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:400 | ||||
| #: stock/models.py:395 | ||||
| msgid "Source Purchase Order" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:403 | ||||
| #: stock/models.py:398 | ||||
| msgid "Purchase order for this stock item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:409 | ||||
| #: stock/models.py:404 | ||||
| msgid "Destination Sales Order" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:416 | ||||
| #: stock/models.py:411 | ||||
| msgid "Destination Build Order" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:429 | ||||
| #: stock/models.py:424 | ||||
| msgid "Delete this Stock Item when stock is depleted" | ||||
| 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 | ||||
| msgid "Stock Item Notes" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:490 | ||||
| #: stock/models.py:485 | ||||
| msgid "Assigned to Customer" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:492 | ||||
| #: stock/models.py:487 | ||||
| msgid "Manually assigned to customer" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:505 | ||||
| #: stock/models.py:500 | ||||
| msgid "Returned from customer" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:507 | ||||
| #: stock/models.py:502 | ||||
| msgid "Returned to location" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:678 | ||||
| #: stock/models.py:673 | ||||
| msgid "Part is not set as trackable" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:684 | ||||
| #: stock/models.py:679 | ||||
| msgid "Quantity must be integer" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:690 | ||||
| #: stock/models.py:685 | ||||
| #, python-brace-format | ||||
| msgid "Quantity must not exceed available stock quantity ({n})" | ||||
| 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" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:699 | ||||
| #: stock/models.py:694 | ||||
| msgid "Quantity does not match serial numbers" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:709 | ||||
| #: stock/models.py:704 | ||||
| msgid "Serial numbers already exist: " | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:734 | ||||
| #: stock/models.py:729 | ||||
| msgid "Add serial number" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:737 | ||||
| #: stock/models.py:732 | ||||
| #, python-brace-format | ||||
| msgid "Serialized {n} items" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:848 | ||||
| #: stock/models.py:843 | ||||
| msgid "StockItem cannot be moved as it is not in stock" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1175 | ||||
| #: stock/models.py:1170 | ||||
| msgid "Tracking entry title" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1177 | ||||
| #: stock/models.py:1172 | ||||
| msgid "Entry notes" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1179 | ||||
| #: stock/models.py:1174 | ||||
| msgid "Link to external page for further information" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1239 | ||||
| #: stock/models.py:1234 | ||||
| msgid "Value must be provided for this test" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1245 | ||||
| #: stock/models.py:1240 | ||||
| msgid "Attachment must be uploaded for this test" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1262 | ||||
| #: stock/models.py:1257 | ||||
| msgid "Test" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1263 | ||||
| #: stock/models.py:1258 | ||||
| msgid "Test name" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1268 | ||||
| #: stock/models.py:1263 | ||||
| msgid "Result" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1269 templates/js/table_filters.html:90 | ||||
| #: stock/models.py:1264 templates/js/table_filters.html:90 | ||||
| msgid "Test result" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1275 | ||||
| #: stock/models.py:1270 | ||||
| msgid "Test output value" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1281 | ||||
| #: stock/models.py:1276 | ||||
| msgid "Attachment" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1282 | ||||
| #: stock/models.py:1277 | ||||
| msgid "Test result attachment" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/models.py:1288 | ||||
| #: stock/models.py:1283 | ||||
| msgid "Test notes" | ||||
| msgstr "" | ||||
|  | ||||
| @@ -3078,39 +3155,35 @@ msgstr "" | ||||
| msgid "Generate test report" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:132 | ||||
| msgid "Print labels" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:140 | ||||
| #: stock/templates/stock/item_base.html:137 | ||||
| msgid "Stock Item Details" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:173 | ||||
| #: stock/templates/stock/item_base.html:170 | ||||
| msgid "Belongs To" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:195 | ||||
| #: stock/templates/stock/item_base.html:192 | ||||
| msgid "No location set" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:202 | ||||
| #: stock/templates/stock/item_base.html:199 | ||||
| msgid "Unique Identifier" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:230 | ||||
| #: stock/templates/stock/item_base.html:227 | ||||
| msgid "Parent Item" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:255 | ||||
| #: stock/templates/stock/item_base.html:252 | ||||
| msgid "Last Updated" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:260 | ||||
| #: stock/templates/stock/item_base.html:257 | ||||
| msgid "Last Stocktake" | ||||
| msgstr "" | ||||
|  | ||||
| #: stock/templates/stock/item_base.html:264 | ||||
| #: stock/templates/stock/item_base.html:261 | ||||
| msgid "No stocktake performed" | ||||
| msgstr "" | ||||
|  | ||||
|   | ||||
| @@ -139,16 +139,71 @@ class BomItemResource(ModelResource): | ||||
|  | ||||
|     bom_id = Field(attribute='pk') | ||||
|  | ||||
|     # ID of the parent 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) | ||||
|  | ||||
|     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: | ||||
|         model = BomItem | ||||
|         skip_unchanged = True | ||||
|   | ||||
| @@ -30,8 +30,14 @@ def MakeBomTemplate(fmt): | ||||
|     if not IsValidBOMFormat(fmt): | ||||
|         fmt = 'csv' | ||||
|  | ||||
|     # Create an "empty" queryset, essentially. | ||||
|     # This will then export just the row headers! | ||||
|     query = BomItem.objects.filter(pk=None) | ||||
|     dataset = BomItemResource().export(queryset=query) | ||||
|  | ||||
|     dataset = BomItemResource().export( | ||||
|         queryset=query, | ||||
|         importing=True | ||||
|     ) | ||||
|  | ||||
|     data = dataset.export(fmt) | ||||
|  | ||||
| @@ -96,26 +102,23 @@ class BomUploadManager: | ||||
|  | ||||
|     # Fields which are absolutely necessary for valid upload | ||||
|     REQUIRED_HEADERS = [ | ||||
|         'Part', | ||||
|         'Part_Name', | ||||
|         'Quantity' | ||||
|     ] | ||||
|      | ||||
|     # Fields which would be helpful but are not required | ||||
|     OPTIONAL_HEADERS = [ | ||||
|         'Part_IPN', | ||||
|         'Part_ID', | ||||
|         'Reference', | ||||
|         'Notes', | ||||
|         'Note', | ||||
|         'Overage', | ||||
|         'Description', | ||||
|         'Category', | ||||
|         'Supplier', | ||||
|         'Manufacturer', | ||||
|         'MPN', | ||||
|         'IPN', | ||||
|     ] | ||||
|  | ||||
|     EDITABLE_HEADERS = [ | ||||
|         'Reference', | ||||
|         'Notes' | ||||
|         'Note', | ||||
|         'Overage' | ||||
|     ] | ||||
|  | ||||
|     HEADERS = REQUIRED_HEADERS + OPTIONAL_HEADERS | ||||
| @@ -165,6 +168,11 @@ class BomUploadManager: | ||||
|             if h.lower() == header.lower(): | ||||
|                 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 | ||||
|         matches = [] | ||||
|  | ||||
|   | ||||
| @@ -271,6 +271,42 @@ class Part(MPTTModel): | ||||
|     def __str__(self): | ||||
|         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): | ||||
|         """ | ||||
|         Check if a serial number exists for this Part. | ||||
| @@ -1474,22 +1510,8 @@ class BomItem(models.Model): | ||||
|         except Part.DoesNotExist: | ||||
|             pass | ||||
|  | ||||
|         # A part cannot refer to itself in its BOM | ||||
|         try: | ||||
|             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 | ||||
|         # Check for circular BOM references | ||||
|         self.sub_part.checkAddToBOM(self.part) | ||||
|  | ||||
|     class Meta: | ||||
|         verbose_name = _("BOM Item") | ||||
|   | ||||
| @@ -1,17 +1,18 @@ | ||||
| {% extends "part/part_base.html" %} | ||||
| {% load static %} | ||||
| {% load i18n %} | ||||
| {% load inventree_extras %} | ||||
|  | ||||
| {% block details %} | ||||
| {% 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> | ||||
|  | ||||
| {% if missing_columns and missing_columns|length > 0 %} | ||||
| <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> | ||||
|     <ul> | ||||
|         {% for col in missing_columns %} | ||||
| @@ -22,7 +23,7 @@ | ||||
| {% endif %} | ||||
|  | ||||
| <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 %} | ||||
|  | ||||
|     <input type='hidden' name='form_step' value='select_fields'/> | ||||
| @@ -31,7 +32,7 @@ | ||||
|         <thead> | ||||
|             <tr> | ||||
|                 <th></th> | ||||
|                 <th>Row</th> | ||||
|                 <th>{% trans "File Fields" %}</th> | ||||
|                 {% for col in bom_columns %} | ||||
|                 <th> | ||||
|                     <div> | ||||
| @@ -48,7 +49,7 @@ | ||||
|         <tbody> | ||||
|             <tr> | ||||
|                 <td></td> | ||||
|                 <td></td> | ||||
|                 <td>{% trans "Match Fields" %}</td> | ||||
|                 {% for col in bom_columns %} | ||||
|                 <td> | ||||
|                     <select class='select' id='id_col_{{ forloop.counter0 }}' name='col_guess_{{ forloop.counter0 }}'> | ||||
|   | ||||
| @@ -1,23 +1,24 @@ | ||||
| {% extends "part/part_base.html" %} | ||||
| {% load static %} | ||||
| {% load i18n %} | ||||
| {% load inventree_extras %} | ||||
|  | ||||
| {% block details %} | ||||
| {% 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> | ||||
|  | ||||
| {% if form_errors %} | ||||
| <div class='alert alert-danger alert-block' role='alert'> | ||||
|     Errors exist in the submitted data. | ||||
|     {% trans "Errors exist in the submitted data" %} | ||||
| </div> | ||||
| {% endif %} | ||||
|  | ||||
| <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 %} | ||||
|     {% load crispy_forms_tags %} | ||||
| @@ -29,7 +30,8 @@ | ||||
|             <tr> | ||||
|                 <th></th> | ||||
|                 <th></th> | ||||
|                 <th>Row</th> | ||||
|                 <th>{% trans "Row" %}</th> | ||||
|                 <th>{% trans "Select Part" %}</th> | ||||
|                 {% for col in bom_columns %} | ||||
|                 <th> | ||||
|                     <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> | ||||
|                     </button> | ||||
|                 </td> | ||||
|                 <td> | ||||
|                 </td> | ||||
|                 <td></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 %} | ||||
|                 <td> | ||||
|                     {% 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> | ||||
|                     {% if row.errors.part %} | ||||
|                     <p class='help-inline'>{{ row.errors.part }}</p> | ||||
|                     {% endif %} | ||||
|                     {% 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 %} | ||||
|                     <p class='help-inline'>{{ row.errors.quantity }}</p> | ||||
|                     {% endif %} | ||||
|                     {% elif item.column.guess == '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 }}'/> | ||||
|                     {% elif item.column.guess == 'Overage' %} | ||||
|                     <input name='overage_{{ row.index }}' value='{{ row.overage }}'/> | ||||
|   | ||||
| @@ -1,18 +1,23 @@ | ||||
| {% extends "part/part_base.html" %} | ||||
| {% load static %} | ||||
| {% load i18n %} | ||||
| {% load inventree_extras %} | ||||
|  | ||||
| {% block details %} | ||||
|  | ||||
| {% include "part/tabs.html" with tab='bom' %} | ||||
|  | ||||
| <h4>Upload Bill of Materials</h4> | ||||
| <h4>{% trans "Upload Bill of Materials" %}</h4> | ||||
| <hr> | ||||
|  | ||||
| <p>Step 1 - Select BOM File</p> | ||||
| <p>{% trans "Step 1 - Select BOM File" %}</p> | ||||
|  | ||||
| <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> | ||||
|  | ||||
| <form method="post" action='' class='js-modal-form' enctype="multipart/form-data"> | ||||
|   | ||||
| @@ -19,7 +19,7 @@ from django.conf import settings | ||||
| import os | ||||
|  | ||||
| from rapidfuzz import fuzz | ||||
| from decimal import Decimal | ||||
| from decimal import Decimal, InvalidOperation | ||||
|  | ||||
| from .models import PartCategory, Part, PartAttachment | ||||
| 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. | ||||
|         """ | ||||
|  | ||||
|         # 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') | ||||
|         p_idx = self.getColumnIndex('Part') | ||||
|         i_idx = self.getColumnIndex('IPN') | ||||
|         d_idx = self.getColumnIndex('Description') | ||||
|         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: | ||||
|             """ | ||||
|  | ||||
|             quantity = 0 | ||||
|             part = None | ||||
|             Iterate through each row in the uploaded data, | ||||
|             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: | ||||
|                 q_val = row['data'][q_idx] | ||||
|  | ||||
|                 try: | ||||
|                     quantity = int(q_val) | ||||
|                 except ValueError: | ||||
|                     pass | ||||
|                 if q_val: | ||||
|                     try: | ||||
|                         # Attempt to extract a valid quantity from the field | ||||
|                         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: | ||||
|                 part_name = row['data'][p_idx] | ||||
|  | ||||
|                 row['part_name'] = part_name | ||||
|  | ||||
|                 # Fuzzy match the values and see what happens | ||||
|                 matches = [] | ||||
|  | ||||
|                 for part in self.allowed_parts: | ||||
|                     ratio = fuzz.partial_ratio(part.name + part.description, part_name) | ||||
|                     matches.append({'part': part, 'match': ratio}) | ||||
|  | ||||
|                 # Sort matches by the 'strength' of the match ratio | ||||
|                 if len(matches) > 0: | ||||
|                     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: | ||||
|                 row['part_ipn'] = row['data'][i_idx] | ||||
|  | ||||
|             if d_idx >= 0: | ||||
|                 row['description'] = row['data'][d_idx] | ||||
|             # Check if there is a column corresponding to "Overage" field | ||||
|             if o_idx >= 0: | ||||
|                 row['overage'] = row['data'][o_idx] | ||||
|  | ||||
|             # Check if there is a column corresponding to "Reference" field | ||||
|             if r_idx >= 0: | ||||
|                 row['reference'] = row['data'][r_idx] | ||||
|  | ||||
|             # Check if there is a column corresponding to "Note" field | ||||
|             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 | ||||
|             try: | ||||
|                 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] | ||||
|             # Unless found, the 'part_match' is blank | ||||
|             row['part_match'] = None | ||||
|  | ||||
|                     # Check for single match | ||||
|                     if len(part_matches) == 1: | ||||
|                         row['part_match'] = part_matches[0] | ||||
|  | ||||
|                     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] | ||||
|             if exact_match_part: | ||||
|                 # If there is an exact match based on PK, use that | ||||
|                 row['part_match'] = exact_match_part | ||||
|             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): | ||||
|         """ Read data from the BOM file """ | ||||
| @@ -1190,13 +1242,20 @@ class BomUpload(FormView): | ||||
|                     if row is None: | ||||
|                         continue | ||||
|  | ||||
|                     q = 1 | ||||
|                     q = Decimal(1) | ||||
|  | ||||
|                     try: | ||||
|                         q = int(value) | ||||
|                         if q <= 0: | ||||
|                         q = Decimal(value) | ||||
|                         if q < 0: | ||||
|                             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['quantity'] = q | ||||
| @@ -1206,6 +1265,7 @@ class BomUpload(FormView): | ||||
|  | ||||
|             # Extract part from each row | ||||
|             if key.startswith('part_'): | ||||
|  | ||||
|                 try: | ||||
|                     row_id = int(key.replace('part_', '')) | ||||
|  | ||||
| @@ -1239,6 +1299,14 @@ class BomUpload(FormView): | ||||
|  | ||||
|                 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 | ||||
|             for field in ['reference', 'notes']: | ||||
|                 if key.startswith(field + '_'): | ||||
| @@ -1257,8 +1325,16 @@ class BomUpload(FormView): | ||||
|  | ||||
|         for row in self.bom_rows: | ||||
|             # 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') | ||||
|             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? | ||||
|             if row.get('quantity', None) is None: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user