2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-30 20:46:47 +00:00

Merge pull request #1092 from SchrodingersGat/copy-bom

Copy bom
This commit is contained in:
Oliver 2020-10-30 11:40:06 +11:00 committed by GitHub
commit 1311e5fe58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 722 additions and 423 deletions

View File

@ -213,6 +213,39 @@ class AjaxMixin(InvenTreeRoleMixin):
""" """
return {} return {}
def pre_save(self, obj, form, **kwargs):
"""
Hook for doing something *before* an object is saved.
obj: The object to be saved
form: The cleaned form
"""
# Do nothing by default
pass
def post_save(self, obj, form, **kwargs):
"""
Hook for doing something *after* an object is saved.
"""
# Do nothing by default
pass
def validate(self, obj, form, **kwargs):
"""
Hook for performing custom form validation steps.
If a form error is detected, add it to the form,
with 'form.add_error()'
Ref: https://docs.djangoproject.com/en/dev/topics/forms/
"""
# Do nothing by default
pass
def renderJsonResponse(self, request, form=None, data={}, context=None): def renderJsonResponse(self, request, form=None, data={}, context=None):
""" Render a JSON response based on specific class context. """ Render a JSON response based on specific class context.
@ -320,18 +353,6 @@ class AjaxCreateView(AjaxMixin, CreateView):
- Handles form validation via AJAX POST requests - Handles form validation via AJAX POST requests
""" """
def pre_save(self, **kwargs):
"""
Hook for doing something before the form is validated
"""
pass
def post_save(self, **kwargs):
"""
Hook for doing something with the created object after it is saved
"""
pass
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
""" Creates form with initial data, and renders JSON response """ """ Creates form with initial data, and renders JSON response """
@ -351,16 +372,29 @@ class AjaxCreateView(AjaxMixin, CreateView):
self.request = request self.request = request
self.form = self.get_form() self.form = self.get_form()
# Perform initial form validation
self.form.is_valid()
# Perform custom validation (no object can be provided yet)
self.validate(None, self.form)
valid = self.form.is_valid()
# Extra JSON data sent alongside form # Extra JSON data sent alongside form
data = { data = {
'form_valid': self.form.is_valid(), 'form_valid': valid
} }
if self.form.is_valid(): if valid:
self.pre_save() # Perform (optional) pre-save step
self.pre_save(None, self.form)
# Save the object to the database
self.object = self.form.save() self.object = self.form.save()
self.post_save()
# Perform (optional) post-save step
self.post_save(self.object, self.form)
# Return the PK of the newly-created object # Return the PK of the newly-created object
data['pk'] = self.object.pk data['pk'] = self.object.pk
@ -400,22 +434,40 @@ class AjaxUpdateView(AjaxMixin, UpdateView):
- Otherwise, return sucess status - Otherwise, return sucess status
""" """
self.request = request
# Make sure we have an object to point to # Make sure we have an object to point to
self.object = self.get_object() self.object = self.get_object()
form = self.get_form() form = self.get_form()
# Perform initial form validation
form.is_valid()
# Perform custom validation
self.validate(self.object, form)
valid = form.is_valid()
data = { data = {
'form_valid': form.is_valid() 'form_valid': valid
} }
if form.is_valid(): if valid:
# Perform (optional) pre-save step
self.pre_save(self.object, form)
# Save the updated objec to the database
obj = form.save() obj = form.save()
# Include context data about the updated object # Perform (optional) post-save step
data['pk'] = obj.id self.post_save(obj, form)
self.post_save(obj) # Include context data about the updated object
data['pk'] = obj.pk
self.post_save(obj, form)
try: try:
data['url'] = obj.get_absolute_url() data['url'] = obj.get_absolute_url()
@ -424,13 +476,6 @@ class AjaxUpdateView(AjaxMixin, UpdateView):
return self.renderJsonResponse(request, form, data) return self.renderJsonResponse(request, form, data)
def post_save(self, obj, *args, **kwargs):
"""
Hook called after the form data is saved.
(Optional)
"""
pass
class AjaxDeleteView(AjaxMixin, UpdateView): class AjaxDeleteView(AjaxMixin, UpdateView):

View File

@ -6,7 +6,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-10-29 02:25+0000\n" "POT-Creation-Date: 2020-10-29 23:05+0000\n"
"PO-Revision-Date: 2020-05-03 11:32+0200\n" "PO-Revision-Date: 2020-05-03 11:32+0200\n"
"Last-Translator: Christian Schlüter <chschlue@gmail.com>\n" "Last-Translator: Christian Schlüter <chschlue@gmail.com>\n"
"Language-Team: C <kde-i18n-doc@kde.org>\n" "Language-Team: C <kde-i18n-doc@kde.org>\n"
@ -214,7 +214,7 @@ msgstr "Überschuss darf 100% nicht überschreiten"
msgid "Overage must be an integer value or a percentage" msgid "Overage must be an integer value or a percentage"
msgstr "Überschuss muss eine Ganzzahl oder ein Prozentwert sein" msgstr "Überschuss muss eine Ganzzahl oder ein Prozentwert sein"
#: InvenTree/views.py:707 #: InvenTree/views.py:752
msgid "Database Statistics" msgid "Database Statistics"
msgstr "Datenbankstatistiken" msgstr "Datenbankstatistiken"
@ -547,7 +547,7 @@ msgstr "Zuweisung löschen"
msgid "No BOM items found" msgid "No BOM items found"
msgstr "Keine BOM-Einträge gefunden" msgstr "Keine BOM-Einträge gefunden"
#: build/templates/build/allocate.html:347 part/models.py:1401 #: build/templates/build/allocate.html:347 part/models.py:1425
#: templates/js/part.js:569 templates/js/table_filters.js:167 #: templates/js/part.js:569 templates/js/table_filters.js:167
msgid "Required" msgid "Required"
msgstr "benötigt" msgstr "benötigt"
@ -1279,7 +1279,7 @@ msgstr "Zuliefererbestand"
#: company/templates/company/detail_stock.html:35 #: company/templates/company/detail_stock.html:35
#: company/templates/company/supplier_part_stock.html:33 #: company/templates/company/supplier_part_stock.html:33
#: part/templates/part/bom.html:62 part/templates/part/category.html:112 #: part/templates/part/bom.html:67 part/templates/part/category.html:112
#: part/templates/part/category.html:126 part/templates/part/stock.html:51 #: part/templates/part/category.html:126 part/templates/part/stock.html:51
#: templates/stock_table.html:7 #: templates/stock_table.html:7
msgid "Export" msgid "Export"
@ -1398,7 +1398,7 @@ msgid "Pricing Information"
msgstr "Preisinformationen ansehen" msgstr "Preisinformationen ansehen"
#: company/templates/company/supplier_part_pricing.html:17 company/views.py:410 #: company/templates/company/supplier_part_pricing.html:17 company/views.py:410
#: part/templates/part/sale_prices.html:13 part/views.py:2229 #: part/templates/part/sale_prices.html:13 part/views.py:2278
msgid "Add Price Break" msgid "Add Price Break"
msgstr "Preisstaffel hinzufügen" msgstr "Preisstaffel hinzufügen"
@ -1531,17 +1531,17 @@ msgstr "Neues Zuliefererteil anlegen"
msgid "Delete Supplier Part" msgid "Delete Supplier Part"
msgstr "Zuliefererteil entfernen" msgstr "Zuliefererteil entfernen"
#: company/views.py:416 part/views.py:2235 #: company/views.py:416 part/views.py:2284
#, fuzzy #, fuzzy
#| msgid "Add Price Break" #| msgid "Add Price Break"
msgid "Added new price break" msgid "Added new price break"
msgstr "Preisstaffel hinzufügen" msgstr "Preisstaffel hinzufügen"
#: company/views.py:453 part/views.py:2280 #: company/views.py:453 part/views.py:2329
msgid "Edit Price Break" msgid "Edit Price Break"
msgstr "Preisstaffel bearbeiten" msgstr "Preisstaffel bearbeiten"
#: company/views.py:469 part/views.py:2296 #: company/views.py:469 part/views.py:2345
msgid "Delete Price Break" msgid "Delete Price Break"
msgstr "Preisstaffel löschen" msgstr "Preisstaffel löschen"
@ -1646,7 +1646,7 @@ msgstr ""
msgid "Date order was completed" msgid "Date order was completed"
msgstr "Bestellung als vollständig markieren" msgstr "Bestellung als vollständig markieren"
#: order/models.py:185 order/models.py:259 part/views.py:1346 #: order/models.py:185 order/models.py:259 part/views.py:1395
#: stock/models.py:241 stock/models.py:805 #: stock/models.py:241 stock/models.py:805
msgid "Quantity must be greater than zero" msgid "Quantity must be greater than zero"
msgstr "Anzahl muss größer Null sein" msgstr "Anzahl muss größer Null sein"
@ -1934,6 +1934,7 @@ msgstr "Kundenreferenz"
#: order/templates/order/sales_order_cancel.html:8 #: order/templates/order/sales_order_cancel.html:8
#: order/templates/order/sales_order_ship.html:9 #: order/templates/order/sales_order_ship.html:9
#: part/templates/part/bom_duplicate.html:12
#: stock/templates/stock/stockitem_convert.html:13 #: stock/templates/stock/stockitem_convert.html:13
msgid "Warning" msgid "Warning"
msgstr "Warnung" msgstr "Warnung"
@ -2162,75 +2163,97 @@ msgstr "Fehler beim Lesen der Stückliste (ungültige Daten)"
msgid "Error reading BOM file (incorrect row size)" msgid "Error reading BOM file (incorrect row size)"
msgstr "Fehler beim Lesen der Stückliste (ungültige Zeilengröße)" msgstr "Fehler beim Lesen der Stückliste (ungültige Zeilengröße)"
#: part/forms.py:57 stock/forms.py:254 #: part/forms.py:62 stock/forms.py:254
msgid "File Format" msgid "File Format"
msgstr "Dateiformat" msgstr "Dateiformat"
#: part/forms.py:57 stock/forms.py:254 #: part/forms.py:62 stock/forms.py:254
msgid "Select output file format" msgid "Select output file format"
msgstr "Ausgabe-Dateiformat auswählen" msgstr "Ausgabe-Dateiformat auswählen"
#: part/forms.py:59 #: part/forms.py:64
msgid "Cascading" msgid "Cascading"
msgstr "Kaskadierend" msgstr "Kaskadierend"
#: part/forms.py:59 #: part/forms.py:64
msgid "Download cascading / multi-level BOM" msgid "Download cascading / multi-level BOM"
msgstr "Kaskadierende Stückliste herunterladen" msgstr "Kaskadierende Stückliste herunterladen"
#: part/forms.py:61 #: part/forms.py:66
msgid "Levels" msgid "Levels"
msgstr "" msgstr ""
#: part/forms.py:61 #: part/forms.py:66
msgid "Select maximum number of BOM levels to export (0 = all levels)" msgid "Select maximum number of BOM levels to export (0 = all levels)"
msgstr "" msgstr ""
#: part/forms.py:63 #: part/forms.py:68
#, fuzzy #, fuzzy
#| msgid "New Parameter" #| msgid "New Parameter"
msgid "Include Parameter Data" msgid "Include Parameter Data"
msgstr "Neuer Parameter" msgstr "Neuer Parameter"
#: part/forms.py:63 #: part/forms.py:68
msgid "Include part parameters data in exported BOM" msgid "Include part parameters data in exported BOM"
msgstr "" msgstr ""
#: part/forms.py:65 #: part/forms.py:70
#, fuzzy #, fuzzy
#| msgid "Include stock in sublocations" #| msgid "Include stock in sublocations"
msgid "Include Stock Data" msgid "Include Stock Data"
msgstr "Bestand in Unterlagerorten einschließen" msgstr "Bestand in Unterlagerorten einschließen"
#: part/forms.py:65 #: part/forms.py:70
#, fuzzy #, fuzzy
#| msgid "Include parts in subcategories" #| msgid "Include parts in subcategories"
msgid "Include part stock data in exported BOM" msgid "Include part stock data in exported BOM"
msgstr "Teile in Unterkategorien einschließen" msgstr "Teile in Unterkategorien einschließen"
#: part/forms.py:67 #: part/forms.py:72
#, fuzzy #, fuzzy
#| msgid "New Supplier Part" #| msgid "New Supplier Part"
msgid "Include Supplier Data" msgid "Include Supplier Data"
msgstr "Neues Zulieferer-Teil" msgstr "Neues Zulieferer-Teil"
#: part/forms.py:67 #: part/forms.py:72
msgid "Include part supplier data in exported BOM" msgid "Include part supplier data in exported BOM"
msgstr "" msgstr ""
#: part/forms.py:86 #: part/forms.py:93 part/models.py:1504
msgid "Parent Part"
msgstr "Ausgangsteil"
#: part/forms.py:94 part/templates/part/bom_duplicate.html:7
#, fuzzy
#| msgid "Select parent part"
msgid "Select parent part to copy BOM from"
msgstr "Ausgangsteil auswählen"
#: part/forms.py:100
#, fuzzy
#| msgid "Select from existing images"
msgid "Clear existing BOM items"
msgstr "Aus vorhandenen Bildern auswählen"
#: part/forms.py:105
#, fuzzy
#| msgid "Confim BOM item deletion"
msgid "Confirm BOM duplication"
msgstr "Löschung von BOM-Position bestätigen"
#: part/forms.py:123
msgid "Confirm that the BOM is correct" msgid "Confirm that the BOM is correct"
msgstr "Bestätigen, dass die Stückliste korrekt ist" msgstr "Bestätigen, dass die Stückliste korrekt ist"
#: part/forms.py:98 #: part/forms.py:135
msgid "Select BOM file to upload" msgid "Select BOM file to upload"
msgstr "Stücklisten-Datei zum Upload auswählen" msgstr "Stücklisten-Datei zum Upload auswählen"
#: part/forms.py:122 #: part/forms.py:159
msgid "Select part category" msgid "Select part category"
msgstr "Teilekategorie wählen" msgstr "Teilekategorie wählen"
#: part/forms.py:136 #: part/forms.py:173
#, fuzzy #, fuzzy
#| msgid "Perform 'deep copy' which will duplicate all BOM data for this part" #| msgid "Perform 'deep copy' which will duplicate all BOM data for this part"
msgid "Duplicate all BOM data for this part" msgid "Duplicate all BOM data for this part"
@ -2238,29 +2261,29 @@ msgstr ""
"Tiefe Kopie ausführen. Dies wird alle Daten der Stückliste für dieses Teil " "Tiefe Kopie ausführen. Dies wird alle Daten der Stückliste für dieses Teil "
"duplizieren" "duplizieren"
#: part/forms.py:137 #: part/forms.py:174
msgid "Copy BOM" msgid "Copy BOM"
msgstr "" msgstr ""
#: part/forms.py:142 #: part/forms.py:179
msgid "Duplicate all parameter data for this part" msgid "Duplicate all parameter data for this part"
msgstr "" msgstr ""
#: part/forms.py:143 #: part/forms.py:180
#, fuzzy #, fuzzy
#| msgid "Parameters" #| msgid "Parameters"
msgid "Copy Parameters" msgid "Copy Parameters"
msgstr "Parameter" msgstr "Parameter"
#: part/forms.py:148 #: part/forms.py:185
msgid "Confirm part creation" msgid "Confirm part creation"
msgstr "Erstellen des Teils bestätigen" msgstr "Erstellen des Teils bestätigen"
#: part/forms.py:248 #: part/forms.py:279
msgid "Input quantity for price calculation" msgid "Input quantity for price calculation"
msgstr "Eintragsmenge zur Preisberechnung" msgstr "Eintragsmenge zur Preisberechnung"
#: part/forms.py:251 #: part/forms.py:282
msgid "Select currency for price calculation" msgid "Select currency for price calculation"
msgstr "Währung zur Preisberechnung wählen" msgstr "Währung zur Preisberechnung wählen"
@ -2390,13 +2413,13 @@ msgstr "Bemerkungen - unterstüzt Markdown-Formatierung"
msgid "Stored BOM checksum" msgid "Stored BOM checksum"
msgstr "Prüfsumme der Stückliste gespeichert" msgstr "Prüfsumme der Stückliste gespeichert"
#: part/models.py:1353 #: part/models.py:1377
#, fuzzy #, fuzzy
#| msgid "Stock item cannot be created for a template Part" #| msgid "Stock item cannot be created for a template Part"
msgid "Test templates can only be created for trackable parts" msgid "Test templates can only be created for trackable parts"
msgstr "Lagerobjekt kann nicht für Vorlagen-Teile angelegt werden" msgstr "Lagerobjekt kann nicht für Vorlagen-Teile angelegt werden"
#: part/models.py:1370 #: part/models.py:1394
#, fuzzy #, fuzzy
#| msgid "" #| msgid ""
#| "A stock item with this serial number already exists for template part " #| "A stock item with this serial number already exists for template part "
@ -2406,120 +2429,116 @@ msgstr ""
"Ein Teil mit dieser Seriennummer existiert bereits für die Teilevorlage " "Ein Teil mit dieser Seriennummer existiert bereits für die Teilevorlage "
"{part}" "{part}"
#: part/models.py:1389 templates/js/part.js:560 templates/js/stock.js:92 #: part/models.py:1413 templates/js/part.js:560 templates/js/stock.js:92
#, fuzzy #, fuzzy
#| msgid "Instance Name" #| msgid "Instance Name"
msgid "Test Name" msgid "Test Name"
msgstr "Instanzname" msgstr "Instanzname"
#: part/models.py:1390 #: part/models.py:1414
#, fuzzy #, fuzzy
#| msgid "Serial number for this item" #| msgid "Serial number for this item"
msgid "Enter a name for the test" msgid "Enter a name for the test"
msgstr "Seriennummer für dieses Teil" msgstr "Seriennummer für dieses Teil"
#: part/models.py:1395 #: part/models.py:1419
#, fuzzy #, fuzzy
#| msgid "Description" #| msgid "Description"
msgid "Test Description" msgid "Test Description"
msgstr "Beschreibung" msgstr "Beschreibung"
#: part/models.py:1396 #: part/models.py:1420
#, fuzzy #, fuzzy
#| msgid "Brief description of the build" #| msgid "Brief description of the build"
msgid "Enter description for this test" msgid "Enter description for this test"
msgstr "Kurze Beschreibung des Baus" msgstr "Kurze Beschreibung des Baus"
#: part/models.py:1402 #: part/models.py:1426
msgid "Is this test required to pass?" msgid "Is this test required to pass?"
msgstr "" msgstr ""
#: part/models.py:1407 templates/js/part.js:577 #: part/models.py:1431 templates/js/part.js:577
#, fuzzy #, fuzzy
#| msgid "Required Parts" #| msgid "Required Parts"
msgid "Requires Value" msgid "Requires Value"
msgstr "benötigte Teile" msgstr "benötigte Teile"
#: part/models.py:1408 #: part/models.py:1432
msgid "Does this test require a value when adding a test result?" msgid "Does this test require a value when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1413 templates/js/part.js:584 #: part/models.py:1437 templates/js/part.js:584
#, fuzzy #, fuzzy
#| msgid "Delete Attachment" #| msgid "Delete Attachment"
msgid "Requires Attachment" msgid "Requires Attachment"
msgstr "Anhang löschen" msgstr "Anhang löschen"
#: part/models.py:1414 #: part/models.py:1438
msgid "Does this test require a file attachment when adding a test result?" msgid "Does this test require a file attachment when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1447 #: part/models.py:1471
msgid "Parameter template name must be unique" msgid "Parameter template name must be unique"
msgstr "Vorlagen-Name des Parameters muss eindeutig sein" msgstr "Vorlagen-Name des Parameters muss eindeutig sein"
#: part/models.py:1452 #: part/models.py:1476
msgid "Parameter Name" msgid "Parameter Name"
msgstr "Name des Parameters" msgstr "Name des Parameters"
#: part/models.py:1454 #: part/models.py:1478
msgid "Parameter Units" msgid "Parameter Units"
msgstr "Parameter Einheit" msgstr "Parameter Einheit"
#: part/models.py:1480 #: part/models.py:1506
msgid "Parent Part"
msgstr "Ausgangsteil"
#: part/models.py:1482
msgid "Parameter Template" msgid "Parameter Template"
msgstr "Parameter Vorlage" msgstr "Parameter Vorlage"
#: part/models.py:1484 #: part/models.py:1508
msgid "Parameter Value" msgid "Parameter Value"
msgstr "Parameter Wert" msgstr "Parameter Wert"
#: part/models.py:1521 #: part/models.py:1545
msgid "Select parent part" msgid "Select parent part"
msgstr "Ausgangsteil auswählen" msgstr "Ausgangsteil auswählen"
#: part/models.py:1529 #: part/models.py:1553
msgid "Select part to be used in BOM" msgid "Select part to be used in BOM"
msgstr "Teil für die Nutzung in der Stückliste auswählen" msgstr "Teil für die Nutzung in der Stückliste auswählen"
#: part/models.py:1535 #: part/models.py:1559
msgid "BOM quantity for this BOM item" msgid "BOM quantity for this BOM item"
msgstr "Stücklisten-Anzahl für dieses Stücklisten-Teil" msgstr "Stücklisten-Anzahl für dieses Stücklisten-Teil"
#: part/models.py:1537 #: part/models.py:1561
#, fuzzy #, fuzzy
#| msgid "Confim BOM item deletion" #| msgid "Confim BOM item deletion"
msgid "This BOM item is optional" msgid "This BOM item is optional"
msgstr "Löschung von BOM-Position bestätigen" msgstr "Löschung von BOM-Position bestätigen"
#: part/models.py:1540 #: part/models.py:1564
msgid "Estimated build wastage quantity (absolute or percentage)" msgid "Estimated build wastage quantity (absolute or percentage)"
msgstr "Geschätzter Ausschuss (absolut oder prozentual)" msgstr "Geschätzter Ausschuss (absolut oder prozentual)"
#: part/models.py:1543 #: part/models.py:1567
msgid "BOM item reference" msgid "BOM item reference"
msgstr "Referenz des Objekts auf der Stückliste" msgstr "Referenz des Objekts auf der Stückliste"
#: part/models.py:1546 #: part/models.py:1570
msgid "BOM item notes" msgid "BOM item notes"
msgstr "Notizen zum Stücklisten-Objekt" msgstr "Notizen zum Stücklisten-Objekt"
#: part/models.py:1548 #: part/models.py:1572
msgid "BOM line checksum" msgid "BOM line checksum"
msgstr "Prüfsumme der Stückliste" msgstr "Prüfsumme der Stückliste"
#: part/models.py:1612 part/views.py:1352 part/views.py:1404 #: part/models.py:1636 part/views.py:1401 part/views.py:1453
#: stock/models.py:231 #: stock/models.py:231
#, fuzzy #, fuzzy
#| msgid "Overage must be an integer value or a percentage" #| msgid "Overage must be an integer value or a percentage"
msgid "Quantity must be integer value for trackable parts" msgid "Quantity must be integer value for trackable parts"
msgstr "Überschuss muss eine Ganzzahl oder ein Prozentwert sein" msgstr "Überschuss muss eine Ganzzahl oder ein Prozentwert sein"
#: part/models.py:1621 #: part/models.py:1645
#, fuzzy #, fuzzy
#| msgid "New BOM Item" #| msgid "New BOM Item"
msgid "BOM Item" msgid "BOM Item"
@ -2563,64 +2582,80 @@ msgid "Import BOM data"
msgstr "Stückliste importieren" msgstr "Stückliste importieren"
#: part/templates/part/bom.html:42 #: part/templates/part/bom.html:42
msgid "Upload" msgid "Import from File"
msgstr "" msgstr ""
#: part/templates/part/bom.html:44 #: part/templates/part/bom.html:45
msgid "Copy BOM from parent part"
msgstr ""
#: part/templates/part/bom.html:46
#, fuzzy
#| msgid "Parameters"
msgid "Copy from Parent"
msgstr "Parameter"
#: part/templates/part/bom.html:49
msgid "New BOM Item" msgid "New BOM Item"
msgstr "Neue Stücklistenposition" msgstr "Neue Stücklistenposition"
#: part/templates/part/bom.html:45 #: part/templates/part/bom.html:50
#, fuzzy #, fuzzy
#| msgid "Add Line Item" #| msgid "Add Line Item"
msgid "Add Item" msgid "Add Item"
msgstr "Position hinzufügen" msgstr "Position hinzufügen"
#: part/templates/part/bom.html:47 #: part/templates/part/bom.html:52
msgid "Finish Editing" msgid "Finish Editing"
msgstr "Bearbeitung beenden" msgstr "Bearbeitung beenden"
#: part/templates/part/bom.html:48 #: part/templates/part/bom.html:53
#, fuzzy #, fuzzy
#| msgid "Finish Editing" #| msgid "Finish Editing"
msgid "Finished" msgid "Finished"
msgstr "Bearbeitung beenden" msgstr "Bearbeitung beenden"
#: part/templates/part/bom.html:52 #: part/templates/part/bom.html:57
msgid "Edit BOM" msgid "Edit BOM"
msgstr "Stückliste bearbeiten" msgstr "Stückliste bearbeiten"
#: part/templates/part/bom.html:53 part/templates/part/params.html:38 #: part/templates/part/bom.html:58 part/templates/part/params.html:38
#: templates/InvenTree/settings/user.html:19 #: templates/InvenTree/settings/user.html:19
msgid "Edit" msgid "Edit"
msgstr "Bearbeiten" msgstr "Bearbeiten"
#: part/templates/part/bom.html:56 #: part/templates/part/bom.html:61
msgid "Validate Bill of Materials" msgid "Validate Bill of Materials"
msgstr "Stückliste validieren" msgstr "Stückliste validieren"
#: part/templates/part/bom.html:57 #: part/templates/part/bom.html:62
#, fuzzy #, fuzzy
#| msgid "Validate BOM" #| msgid "Validate BOM"
msgid "Validate" msgid "Validate"
msgstr "BOM validieren" msgstr "BOM validieren"
#: part/templates/part/bom.html:61 part/views.py:1643 #: part/templates/part/bom.html:66 part/views.py:1692
msgid "Export Bill of Materials" msgid "Export Bill of Materials"
msgstr "Stückliste exportieren" msgstr "Stückliste exportieren"
#: part/templates/part/bom.html:122 #: part/templates/part/bom.html:127
#, fuzzy #, fuzzy
#| msgid "Remove selected BOM items" #| msgid "Remove selected BOM items"
msgid "Delete selected BOM items?" msgid "Delete selected BOM items?"
msgstr "Ausgewählte Stücklistenpositionen entfernen" msgstr "Ausgewählte Stücklistenpositionen entfernen"
#: part/templates/part/bom.html:123 #: part/templates/part/bom.html:128
#, fuzzy #, fuzzy
#| msgid "Remove selected BOM items" #| msgid "Remove selected BOM items"
msgid "All selected BOM items will be deleted" msgid "All selected BOM items will be deleted"
msgstr "Ausgewählte Stücklistenpositionen entfernen" msgstr "Ausgewählte Stücklistenpositionen entfernen"
#: part/templates/part/bom_duplicate.html:13
#, fuzzy
#| msgid "Export Bill of Materials"
msgid "This part already has a Bill of Materials"
msgstr "Stückliste exportieren"
#: part/templates/part/bom_upload/select_fields.html:8 #: part/templates/part/bom_upload/select_fields.html:8
#: part/templates/part/bom_upload/select_parts.html:8 #: part/templates/part/bom_upload/select_parts.html:8
#: part/templates/part/bom_upload/upload_file.html:10 #: part/templates/part/bom_upload/upload_file.html:10
@ -2721,7 +2756,7 @@ msgstr "Neuen Bau beginnen"
msgid "All parts" msgid "All parts"
msgstr "Alle Teile" msgstr "Alle Teile"
#: part/templates/part/category.html:24 part/views.py:2046 #: part/templates/part/category.html:24 part/views.py:2095
msgid "Create new part category" msgid "Create new part category"
msgstr "Teilkategorie anlegen" msgstr "Teilkategorie anlegen"
@ -2895,104 +2930,104 @@ msgstr "Erstellt von"
msgid "Responsible User" msgid "Responsible User"
msgstr "Verantwortlicher Benutzer" msgstr "Verantwortlicher Benutzer"
#: part/templates/part/detail.html:136 templates/js/table_filters.js:27 #: part/templates/part/detail.html:138 templates/js/table_filters.js:27
msgid "Virtual" msgid "Virtual"
msgstr "Virtuell" msgstr "Virtuell"
#: part/templates/part/detail.html:139 #: part/templates/part/detail.html:141
msgid "Part is virtual (not a physical part)" msgid "Part is virtual (not a physical part)"
msgstr "Teil ist virtuell (kein physisches Teil)" msgstr "Teil ist virtuell (kein physisches Teil)"
#: part/templates/part/detail.html:141 #: part/templates/part/detail.html:143
msgid "Part is not a virtual part" msgid "Part is not a virtual part"
msgstr "Teil ist nicht virtuell" msgstr "Teil ist nicht virtuell"
#: part/templates/part/detail.html:145 stock/forms.py:248 #: part/templates/part/detail.html:148 stock/forms.py:248
#: templates/js/table_filters.js:23 templates/js/table_filters.js:243 #: templates/js/table_filters.js:23 templates/js/table_filters.js:243
msgid "Template" msgid "Template"
msgstr "Vorlage" msgstr "Vorlage"
#: part/templates/part/detail.html:148 #: part/templates/part/detail.html:151
#, fuzzy #, fuzzy
#| msgid "Part cannot be a template part if it is a variant of another part" #| msgid "Part cannot be a template part if it is a variant of another part"
msgid "Part is a template part (variants can be made from this part)" msgid "Part is a template part (variants can be made from this part)"
msgstr "Teil kann keine Vorlage sein wenn es Variante eines anderen Teils ist" msgstr "Teil kann keine Vorlage sein wenn es Variante eines anderen Teils ist"
#: part/templates/part/detail.html:150 #: part/templates/part/detail.html:153
#, fuzzy #, fuzzy
#| msgid "Part is not a virtual part" #| msgid "Part is not a virtual part"
msgid "Part is not a template part" msgid "Part is not a template part"
msgstr "Teil ist nicht virtuell" msgstr "Teil ist nicht virtuell"
#: part/templates/part/detail.html:154 templates/js/table_filters.js:255 #: part/templates/part/detail.html:158 templates/js/table_filters.js:255
msgid "Assembly" msgid "Assembly"
msgstr "Baugruppe" msgstr "Baugruppe"
#: part/templates/part/detail.html:157 #: part/templates/part/detail.html:161
msgid "Part can be assembled from other parts" msgid "Part can be assembled from other parts"
msgstr "Teil kann aus anderen Teilen angefertigt werden" msgstr "Teil kann aus anderen Teilen angefertigt werden"
#: part/templates/part/detail.html:159 #: part/templates/part/detail.html:163
msgid "Part cannot be assembled from other parts" msgid "Part cannot be assembled from other parts"
msgstr "Teil kann nicht aus anderen Teilen angefertigt werden" msgstr "Teil kann nicht aus anderen Teilen angefertigt werden"
#: part/templates/part/detail.html:163 templates/js/table_filters.js:259 #: part/templates/part/detail.html:168 templates/js/table_filters.js:259
msgid "Component" msgid "Component"
msgstr "Komponente" msgstr "Komponente"
#: part/templates/part/detail.html:166 #: part/templates/part/detail.html:171
msgid "Part can be used in assemblies" msgid "Part can be used in assemblies"
msgstr "Teil kann in Baugruppen benutzt werden" msgstr "Teil kann in Baugruppen benutzt werden"
#: part/templates/part/detail.html:168 #: part/templates/part/detail.html:173
msgid "Part cannot be used in assemblies" msgid "Part cannot be used in assemblies"
msgstr "Teil kann nicht in Baugruppen benutzt werden" msgstr "Teil kann nicht in Baugruppen benutzt werden"
#: part/templates/part/detail.html:172 templates/js/table_filters.js:31 #: part/templates/part/detail.html:178 templates/js/table_filters.js:31
#: templates/js/table_filters.js:271 #: templates/js/table_filters.js:271
msgid "Trackable" msgid "Trackable"
msgstr "nachverfolgbar" msgstr "nachverfolgbar"
#: part/templates/part/detail.html:175 #: part/templates/part/detail.html:181
msgid "Part stock is tracked by serial number" msgid "Part stock is tracked by serial number"
msgstr "Teilebestand in der Seriennummer hinterlegt" msgstr "Teilebestand in der Seriennummer hinterlegt"
#: part/templates/part/detail.html:177 #: part/templates/part/detail.html:183
msgid "Part stock is not tracked by serial number" msgid "Part stock is not tracked by serial number"
msgstr "Teilebestand ist nicht in der Seriennummer hinterlegt" msgstr "Teilebestand ist nicht in der Seriennummer hinterlegt"
#: part/templates/part/detail.html:181 #: part/templates/part/detail.html:188
msgid "Purchaseable" msgid "Purchaseable"
msgstr "Kaufbar" msgstr "Kaufbar"
#: part/templates/part/detail.html:184 part/templates/part/detail.html:186 #: part/templates/part/detail.html:191 part/templates/part/detail.html:193
msgid "Part can be purchased from external suppliers" msgid "Part can be purchased from external suppliers"
msgstr "Teil kann von externen Zulieferern gekauft werden" msgstr "Teil kann von externen Zulieferern gekauft werden"
#: part/templates/part/detail.html:190 templates/js/table_filters.js:267 #: part/templates/part/detail.html:198 templates/js/table_filters.js:267
msgid "Salable" msgid "Salable"
msgstr "Verkäuflich" msgstr "Verkäuflich"
#: part/templates/part/detail.html:193 #: part/templates/part/detail.html:201
msgid "Part can be sold to customers" msgid "Part can be sold to customers"
msgstr "Teil kann an Kunden verkauft werden" msgstr "Teil kann an Kunden verkauft werden"
#: part/templates/part/detail.html:195 #: part/templates/part/detail.html:203
msgid "Part cannot be sold to customers" msgid "Part cannot be sold to customers"
msgstr "Teil kann nicht an Kunden verkauft werden" msgstr "Teil kann nicht an Kunden verkauft werden"
#: part/templates/part/detail.html:199 templates/js/table_filters.js:19 #: part/templates/part/detail.html:214 templates/js/table_filters.js:19
#: templates/js/table_filters.js:55 templates/js/table_filters.js:238 #: templates/js/table_filters.js:55 templates/js/table_filters.js:238
msgid "Active" msgid "Active"
msgstr "Aktiv" msgstr "Aktiv"
#: part/templates/part/detail.html:202 #: part/templates/part/detail.html:217
#, fuzzy #, fuzzy
#| msgid "This part is not active" #| msgid "This part is not active"
msgid "Part is active" msgid "Part is active"
msgstr "Dieses Teil ist nicht aktiv" msgstr "Dieses Teil ist nicht aktiv"
#: part/templates/part/detail.html:204 #: part/templates/part/detail.html:219
#, fuzzy #, fuzzy
#| msgid "This part is not active" #| msgid "This part is not active"
msgid "Part is not active" msgid "Part is not active"
@ -3344,99 +3379,111 @@ msgstr "Teilbild nicht gefunden"
msgid "Edit Part Properties" msgid "Edit Part Properties"
msgstr "Teileigenschaften bearbeiten" msgstr "Teileigenschaften bearbeiten"
#: part/views.py:838 #: part/views.py:841
#, fuzzy
#| msgid "Duplicate Part"
msgid "Duplicate BOM"
msgstr "Teil duplizieren"
#: part/views.py:871
#, fuzzy
#| msgid "Confirm unallocation of build stock"
msgid "Confirm duplication of BOM from parent"
msgstr "Zuweisungsaufhebung bestätigen"
#: part/views.py:887
msgid "Validate BOM" msgid "Validate BOM"
msgstr "BOM validieren" msgstr "BOM validieren"
#: part/views.py:1005 #: part/views.py:1054
msgid "No BOM file provided" msgid "No BOM file provided"
msgstr "Keine Stückliste angegeben" msgstr "Keine Stückliste angegeben"
#: part/views.py:1355 #: part/views.py:1404
msgid "Enter a valid quantity" msgid "Enter a valid quantity"
msgstr "Bitte eine gültige Anzahl eingeben" msgstr "Bitte eine gültige Anzahl eingeben"
#: part/views.py:1380 part/views.py:1383 #: part/views.py:1429 part/views.py:1432
msgid "Select valid part" msgid "Select valid part"
msgstr "Bitte ein gültiges Teil auswählen" msgstr "Bitte ein gültiges Teil auswählen"
#: part/views.py:1389 #: part/views.py:1438
msgid "Duplicate part selected" msgid "Duplicate part selected"
msgstr "Teil doppelt ausgewählt" msgstr "Teil doppelt ausgewählt"
#: part/views.py:1427 #: part/views.py:1476
msgid "Select a part" msgid "Select a part"
msgstr "Teil auswählen" msgstr "Teil auswählen"
#: part/views.py:1433 #: part/views.py:1482
#, fuzzy #, fuzzy
#| msgid "Select part to be used in BOM" #| msgid "Select part to be used in BOM"
msgid "Selected part creates a circular BOM" msgid "Selected part creates a circular BOM"
msgstr "Teil für die Nutzung in der Stückliste auswählen" msgstr "Teil für die Nutzung in der Stückliste auswählen"
#: part/views.py:1437 #: part/views.py:1486
msgid "Specify quantity" msgid "Specify quantity"
msgstr "Anzahl angeben" msgstr "Anzahl angeben"
#: part/views.py:1693 #: part/views.py:1742
msgid "Confirm Part Deletion" msgid "Confirm Part Deletion"
msgstr "Löschen des Teils bestätigen" msgstr "Löschen des Teils bestätigen"
#: part/views.py:1702 #: part/views.py:1751
msgid "Part was deleted" msgid "Part was deleted"
msgstr "Teil wurde gelöscht" msgstr "Teil wurde gelöscht"
#: part/views.py:1711 #: part/views.py:1760
msgid "Part Pricing" msgid "Part Pricing"
msgstr "Teilbepreisung" msgstr "Teilbepreisung"
#: part/views.py:1837 #: part/views.py:1886
msgid "Create Part Parameter Template" msgid "Create Part Parameter Template"
msgstr "Teilparametervorlage anlegen" msgstr "Teilparametervorlage anlegen"
#: part/views.py:1847 #: part/views.py:1896
msgid "Edit Part Parameter Template" msgid "Edit Part Parameter Template"
msgstr "Teilparametervorlage bearbeiten" msgstr "Teilparametervorlage bearbeiten"
#: part/views.py:1856 #: part/views.py:1905
msgid "Delete Part Parameter Template" msgid "Delete Part Parameter Template"
msgstr "Teilparametervorlage löschen" msgstr "Teilparametervorlage löschen"
#: part/views.py:1866 #: part/views.py:1915
msgid "Create Part Parameter" msgid "Create Part Parameter"
msgstr "Teilparameter anlegen" msgstr "Teilparameter anlegen"
#: part/views.py:1918 #: part/views.py:1967
msgid "Edit Part Parameter" msgid "Edit Part Parameter"
msgstr "Teilparameter bearbeiten" msgstr "Teilparameter bearbeiten"
#: part/views.py:1934 #: part/views.py:1983
msgid "Delete Part Parameter" msgid "Delete Part Parameter"
msgstr "Teilparameter löschen" msgstr "Teilparameter löschen"
#: part/views.py:1993 #: part/views.py:2042
msgid "Edit Part Category" msgid "Edit Part Category"
msgstr "Teilkategorie bearbeiten" msgstr "Teilkategorie bearbeiten"
#: part/views.py:2030 #: part/views.py:2079
msgid "Delete Part Category" msgid "Delete Part Category"
msgstr "Teilkategorie löschen" msgstr "Teilkategorie löschen"
#: part/views.py:2038 #: part/views.py:2087
msgid "Part category was deleted" msgid "Part category was deleted"
msgstr "Teilekategorie wurde gelöscht" msgstr "Teilekategorie wurde gelöscht"
#: part/views.py:2101 #: part/views.py:2150
#, fuzzy #, fuzzy
#| msgid "Create BOM item" #| msgid "Create BOM item"
msgid "Create BOM Item" msgid "Create BOM Item"
msgstr "BOM-Position anlegen" msgstr "BOM-Position anlegen"
#: part/views.py:2169 #: part/views.py:2218
msgid "Edit BOM item" msgid "Edit BOM item"
msgstr "BOM-Position beaarbeiten" msgstr "BOM-Position beaarbeiten"
#: part/views.py:2219 #: part/views.py:2268
msgid "Confim BOM item deletion" msgid "Confim BOM item deletion"
msgstr "Löschung von BOM-Position bestätigen" msgstr "Löschung von BOM-Position bestätigen"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-10-29 02:25+0000\n" "POT-Creation-Date: 2020-10-29 23:05+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -204,7 +204,7 @@ msgstr ""
msgid "Overage must be an integer value or a percentage" msgid "Overage must be an integer value or a percentage"
msgstr "" msgstr ""
#: InvenTree/views.py:707 #: InvenTree/views.py:752
msgid "Database Statistics" msgid "Database Statistics"
msgstr "" msgstr ""
@ -520,7 +520,7 @@ msgstr ""
msgid "No BOM items found" msgid "No BOM items found"
msgstr "" msgstr ""
#: build/templates/build/allocate.html:347 part/models.py:1401 #: build/templates/build/allocate.html:347 part/models.py:1425
#: templates/js/part.js:569 templates/js/table_filters.js:167 #: templates/js/part.js:569 templates/js/table_filters.js:167
msgid "Required" msgid "Required"
msgstr "" msgstr ""
@ -1192,7 +1192,7 @@ msgstr ""
#: company/templates/company/detail_stock.html:35 #: company/templates/company/detail_stock.html:35
#: company/templates/company/supplier_part_stock.html:33 #: company/templates/company/supplier_part_stock.html:33
#: part/templates/part/bom.html:62 part/templates/part/category.html:112 #: part/templates/part/bom.html:67 part/templates/part/category.html:112
#: part/templates/part/category.html:126 part/templates/part/stock.html:51 #: part/templates/part/category.html:126 part/templates/part/stock.html:51
#: templates/stock_table.html:7 #: templates/stock_table.html:7
msgid "Export" msgid "Export"
@ -1310,7 +1310,7 @@ msgid "Pricing Information"
msgstr "" msgstr ""
#: company/templates/company/supplier_part_pricing.html:17 company/views.py:410 #: company/templates/company/supplier_part_pricing.html:17 company/views.py:410
#: part/templates/part/sale_prices.html:13 part/views.py:2229 #: part/templates/part/sale_prices.html:13 part/views.py:2278
msgid "Add Price Break" msgid "Add Price Break"
msgstr "" msgstr ""
@ -1437,15 +1437,15 @@ msgstr ""
msgid "Delete Supplier Part" msgid "Delete Supplier Part"
msgstr "" msgstr ""
#: company/views.py:416 part/views.py:2235 #: company/views.py:416 part/views.py:2284
msgid "Added new price break" msgid "Added new price break"
msgstr "" msgstr ""
#: company/views.py:453 part/views.py:2280 #: company/views.py:453 part/views.py:2329
msgid "Edit Price Break" msgid "Edit Price Break"
msgstr "" msgstr ""
#: company/views.py:469 part/views.py:2296 #: company/views.py:469 part/views.py:2345
msgid "Delete Price Break" msgid "Delete Price Break"
msgstr "" msgstr ""
@ -1538,7 +1538,7 @@ msgstr ""
msgid "Date order was completed" msgid "Date order was completed"
msgstr "" msgstr ""
#: order/models.py:185 order/models.py:259 part/views.py:1346 #: order/models.py:185 order/models.py:259 part/views.py:1395
#: stock/models.py:241 stock/models.py:805 #: stock/models.py:241 stock/models.py:805
msgid "Quantity must be greater than zero" msgid "Quantity must be greater than zero"
msgstr "" msgstr ""
@ -1815,6 +1815,7 @@ msgstr ""
#: order/templates/order/sales_order_cancel.html:8 #: order/templates/order/sales_order_cancel.html:8
#: order/templates/order/sales_order_ship.html:9 #: order/templates/order/sales_order_ship.html:9
#: part/templates/part/bom_duplicate.html:12
#: stock/templates/stock/stockitem_convert.html:13 #: stock/templates/stock/stockitem_convert.html:13
msgid "Warning" msgid "Warning"
msgstr "" msgstr ""
@ -2039,91 +2040,107 @@ msgstr ""
msgid "Error reading BOM file (incorrect row size)" msgid "Error reading BOM file (incorrect row size)"
msgstr "" msgstr ""
#: part/forms.py:57 stock/forms.py:254 #: part/forms.py:62 stock/forms.py:254
msgid "File Format" msgid "File Format"
msgstr "" msgstr ""
#: part/forms.py:57 stock/forms.py:254 #: part/forms.py:62 stock/forms.py:254
msgid "Select output file format" msgid "Select output file format"
msgstr "" msgstr ""
#: part/forms.py:59 #: part/forms.py:64
msgid "Cascading" msgid "Cascading"
msgstr "" msgstr ""
#: part/forms.py:59 #: part/forms.py:64
msgid "Download cascading / multi-level BOM" msgid "Download cascading / multi-level BOM"
msgstr "" msgstr ""
#: part/forms.py:61 #: part/forms.py:66
msgid "Levels" msgid "Levels"
msgstr "" msgstr ""
#: part/forms.py:61 #: part/forms.py:66
msgid "Select maximum number of BOM levels to export (0 = all levels)" msgid "Select maximum number of BOM levels to export (0 = all levels)"
msgstr "" msgstr ""
#: part/forms.py:63 #: part/forms.py:68
msgid "Include Parameter Data" msgid "Include Parameter Data"
msgstr "" msgstr ""
#: part/forms.py:63 #: part/forms.py:68
msgid "Include part parameters data in exported BOM" msgid "Include part parameters data in exported BOM"
msgstr "" msgstr ""
#: part/forms.py:65 #: part/forms.py:70
msgid "Include Stock Data" msgid "Include Stock Data"
msgstr "" msgstr ""
#: part/forms.py:65 #: part/forms.py:70
msgid "Include part stock data in exported BOM" msgid "Include part stock data in exported BOM"
msgstr "" msgstr ""
#: part/forms.py:67 #: part/forms.py:72
msgid "Include Supplier Data" msgid "Include Supplier Data"
msgstr "" msgstr ""
#: part/forms.py:67 #: part/forms.py:72
msgid "Include part supplier data in exported BOM" msgid "Include part supplier data in exported BOM"
msgstr "" msgstr ""
#: part/forms.py:86 #: part/forms.py:93 part/models.py:1504
msgid "Parent Part"
msgstr ""
#: part/forms.py:94 part/templates/part/bom_duplicate.html:7
msgid "Select parent part to copy BOM from"
msgstr ""
#: part/forms.py:100
msgid "Clear existing BOM items"
msgstr ""
#: part/forms.py:105
msgid "Confirm BOM duplication"
msgstr ""
#: part/forms.py:123
msgid "Confirm that the BOM is correct" msgid "Confirm that the BOM is correct"
msgstr "" msgstr ""
#: part/forms.py:98 #: part/forms.py:135
msgid "Select BOM file to upload" msgid "Select BOM file to upload"
msgstr "" msgstr ""
#: part/forms.py:122 #: part/forms.py:159
msgid "Select part category" msgid "Select part category"
msgstr "" msgstr ""
#: part/forms.py:136 #: part/forms.py:173
msgid "Duplicate all BOM data for this part" msgid "Duplicate all BOM data for this part"
msgstr "" msgstr ""
#: part/forms.py:137 #: part/forms.py:174
msgid "Copy BOM" msgid "Copy BOM"
msgstr "" msgstr ""
#: part/forms.py:142 #: part/forms.py:179
msgid "Duplicate all parameter data for this part" msgid "Duplicate all parameter data for this part"
msgstr "" msgstr ""
#: part/forms.py:143 #: part/forms.py:180
msgid "Copy Parameters" msgid "Copy Parameters"
msgstr "" msgstr ""
#: part/forms.py:148 #: part/forms.py:185
msgid "Confirm part creation" msgid "Confirm part creation"
msgstr "" msgstr ""
#: part/forms.py:248 #: part/forms.py:279
msgid "Input quantity for price calculation" msgid "Input quantity for price calculation"
msgstr "" msgstr ""
#: part/forms.py:251 #: part/forms.py:282
msgid "Select currency for price calculation" msgid "Select currency for price calculation"
msgstr "" msgstr ""
@ -2249,112 +2266,108 @@ msgstr ""
msgid "Stored BOM checksum" msgid "Stored BOM checksum"
msgstr "" msgstr ""
#: part/models.py:1353 #: part/models.py:1377
msgid "Test templates can only be created for trackable parts" msgid "Test templates can only be created for trackable parts"
msgstr "" msgstr ""
#: part/models.py:1370 #: part/models.py:1394
msgid "Test with this name already exists for this part" msgid "Test with this name already exists for this part"
msgstr "" msgstr ""
#: part/models.py:1389 templates/js/part.js:560 templates/js/stock.js:92 #: part/models.py:1413 templates/js/part.js:560 templates/js/stock.js:92
msgid "Test Name" msgid "Test Name"
msgstr "" msgstr ""
#: part/models.py:1390 #: part/models.py:1414
msgid "Enter a name for the test" msgid "Enter a name for the test"
msgstr "" msgstr ""
#: part/models.py:1395 #: part/models.py:1419
msgid "Test Description" msgid "Test Description"
msgstr "" msgstr ""
#: part/models.py:1396 #: part/models.py:1420
msgid "Enter description for this test" msgid "Enter description for this test"
msgstr "" msgstr ""
#: part/models.py:1402 #: part/models.py:1426
msgid "Is this test required to pass?" msgid "Is this test required to pass?"
msgstr "" msgstr ""
#: part/models.py:1407 templates/js/part.js:577 #: part/models.py:1431 templates/js/part.js:577
msgid "Requires Value" msgid "Requires Value"
msgstr "" msgstr ""
#: part/models.py:1408 #: part/models.py:1432
msgid "Does this test require a value when adding a test result?" msgid "Does this test require a value when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1413 templates/js/part.js:584 #: part/models.py:1437 templates/js/part.js:584
msgid "Requires Attachment" msgid "Requires Attachment"
msgstr "" msgstr ""
#: part/models.py:1414 #: part/models.py:1438
msgid "Does this test require a file attachment when adding a test result?" msgid "Does this test require a file attachment when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1447 #: part/models.py:1471
msgid "Parameter template name must be unique" msgid "Parameter template name must be unique"
msgstr "" msgstr ""
#: part/models.py:1452 #: part/models.py:1476
msgid "Parameter Name" msgid "Parameter Name"
msgstr "" msgstr ""
#: part/models.py:1454 #: part/models.py:1478
msgid "Parameter Units" msgid "Parameter Units"
msgstr "" msgstr ""
#: part/models.py:1480 #: part/models.py:1506
msgid "Parent Part"
msgstr ""
#: part/models.py:1482
msgid "Parameter Template" msgid "Parameter Template"
msgstr "" msgstr ""
#: part/models.py:1484 #: part/models.py:1508
msgid "Parameter Value" msgid "Parameter Value"
msgstr "" msgstr ""
#: part/models.py:1521 #: part/models.py:1545
msgid "Select parent part" msgid "Select parent part"
msgstr "" msgstr ""
#: part/models.py:1529 #: part/models.py:1553
msgid "Select part to be used in BOM" msgid "Select part to be used in BOM"
msgstr "" msgstr ""
#: part/models.py:1535 #: part/models.py:1559
msgid "BOM quantity for this BOM item" msgid "BOM quantity for this BOM item"
msgstr "" msgstr ""
#: part/models.py:1537 #: part/models.py:1561
msgid "This BOM item is optional" msgid "This BOM item is optional"
msgstr "" msgstr ""
#: part/models.py:1540 #: part/models.py:1564
msgid "Estimated build wastage quantity (absolute or percentage)" msgid "Estimated build wastage quantity (absolute or percentage)"
msgstr "" msgstr ""
#: part/models.py:1543 #: part/models.py:1567
msgid "BOM item reference" msgid "BOM item reference"
msgstr "" msgstr ""
#: part/models.py:1546 #: part/models.py:1570
msgid "BOM item notes" msgid "BOM item notes"
msgstr "" msgstr ""
#: part/models.py:1548 #: part/models.py:1572
msgid "BOM line checksum" msgid "BOM line checksum"
msgstr "" msgstr ""
#: part/models.py:1612 part/views.py:1352 part/views.py:1404 #: part/models.py:1636 part/views.py:1401 part/views.py:1453
#: stock/models.py:231 #: stock/models.py:231
msgid "Quantity must be integer value for trackable parts" msgid "Quantity must be integer value for trackable parts"
msgstr "" msgstr ""
#: part/models.py:1621 #: part/models.py:1645
msgid "BOM Item" msgid "BOM Item"
msgstr "" msgstr ""
@ -2396,54 +2409,66 @@ msgid "Import BOM data"
msgstr "" msgstr ""
#: part/templates/part/bom.html:42 #: part/templates/part/bom.html:42
msgid "Upload" msgid "Import from File"
msgstr ""
#: part/templates/part/bom.html:44
msgid "New BOM Item"
msgstr "" msgstr ""
#: part/templates/part/bom.html:45 #: part/templates/part/bom.html:45
msgid "Copy BOM from parent part"
msgstr ""
#: part/templates/part/bom.html:46
msgid "Copy from Parent"
msgstr ""
#: part/templates/part/bom.html:49
msgid "New BOM Item"
msgstr ""
#: part/templates/part/bom.html:50
msgid "Add Item" msgid "Add Item"
msgstr "" msgstr ""
#: part/templates/part/bom.html:47 #: part/templates/part/bom.html:52
msgid "Finish Editing" msgid "Finish Editing"
msgstr "" msgstr ""
#: part/templates/part/bom.html:48 #: part/templates/part/bom.html:53
msgid "Finished" msgid "Finished"
msgstr "" msgstr ""
#: part/templates/part/bom.html:52 #: part/templates/part/bom.html:57
msgid "Edit BOM" msgid "Edit BOM"
msgstr "" msgstr ""
#: part/templates/part/bom.html:53 part/templates/part/params.html:38 #: part/templates/part/bom.html:58 part/templates/part/params.html:38
#: templates/InvenTree/settings/user.html:19 #: templates/InvenTree/settings/user.html:19
msgid "Edit" msgid "Edit"
msgstr "" msgstr ""
#: part/templates/part/bom.html:56 #: part/templates/part/bom.html:61
msgid "Validate Bill of Materials" msgid "Validate Bill of Materials"
msgstr "" msgstr ""
#: part/templates/part/bom.html:57 #: part/templates/part/bom.html:62
msgid "Validate" msgid "Validate"
msgstr "" msgstr ""
#: part/templates/part/bom.html:61 part/views.py:1643 #: part/templates/part/bom.html:66 part/views.py:1692
msgid "Export Bill of Materials" msgid "Export Bill of Materials"
msgstr "" msgstr ""
#: part/templates/part/bom.html:122 #: part/templates/part/bom.html:127
msgid "Delete selected BOM items?" msgid "Delete selected BOM items?"
msgstr "" msgstr ""
#: part/templates/part/bom.html:123 #: part/templates/part/bom.html:128
msgid "All selected BOM items will be deleted" msgid "All selected BOM items will be deleted"
msgstr "" msgstr ""
#: part/templates/part/bom_duplicate.html:13
msgid "This part already has a Bill of Materials"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:8 #: part/templates/part/bom_upload/select_fields.html:8
#: part/templates/part/bom_upload/select_parts.html:8 #: part/templates/part/bom_upload/select_parts.html:8
#: part/templates/part/bom_upload/upload_file.html:10 #: part/templates/part/bom_upload/upload_file.html:10
@ -2524,7 +2549,7 @@ msgstr ""
msgid "All parts" msgid "All parts"
msgstr "" msgstr ""
#: part/templates/part/category.html:24 part/views.py:2046 #: part/templates/part/category.html:24 part/views.py:2095
msgid "Create new part category" msgid "Create new part category"
msgstr "" msgstr ""
@ -2670,98 +2695,98 @@ msgstr ""
msgid "Responsible User" msgid "Responsible User"
msgstr "" msgstr ""
#: part/templates/part/detail.html:136 templates/js/table_filters.js:27 #: part/templates/part/detail.html:138 templates/js/table_filters.js:27
msgid "Virtual" msgid "Virtual"
msgstr "" msgstr ""
#: part/templates/part/detail.html:139 #: part/templates/part/detail.html:141
msgid "Part is virtual (not a physical part)" msgid "Part is virtual (not a physical part)"
msgstr "" msgstr ""
#: part/templates/part/detail.html:141 #: part/templates/part/detail.html:143
msgid "Part is not a virtual part" msgid "Part is not a virtual part"
msgstr "" msgstr ""
#: part/templates/part/detail.html:145 stock/forms.py:248 #: part/templates/part/detail.html:148 stock/forms.py:248
#: templates/js/table_filters.js:23 templates/js/table_filters.js:243 #: templates/js/table_filters.js:23 templates/js/table_filters.js:243
msgid "Template" msgid "Template"
msgstr "" msgstr ""
#: part/templates/part/detail.html:148 #: part/templates/part/detail.html:151
msgid "Part is a template part (variants can be made from this part)" msgid "Part is a template part (variants can be made from this part)"
msgstr "" msgstr ""
#: part/templates/part/detail.html:150 #: part/templates/part/detail.html:153
msgid "Part is not a template part" msgid "Part is not a template part"
msgstr "" msgstr ""
#: part/templates/part/detail.html:154 templates/js/table_filters.js:255 #: part/templates/part/detail.html:158 templates/js/table_filters.js:255
msgid "Assembly" msgid "Assembly"
msgstr "" msgstr ""
#: part/templates/part/detail.html:157 #: part/templates/part/detail.html:161
msgid "Part can be assembled from other parts" msgid "Part can be assembled from other parts"
msgstr "" msgstr ""
#: part/templates/part/detail.html:159 #: part/templates/part/detail.html:163
msgid "Part cannot be assembled from other parts" msgid "Part cannot be assembled from other parts"
msgstr "" msgstr ""
#: part/templates/part/detail.html:163 templates/js/table_filters.js:259 #: part/templates/part/detail.html:168 templates/js/table_filters.js:259
msgid "Component" msgid "Component"
msgstr "" msgstr ""
#: part/templates/part/detail.html:166 #: part/templates/part/detail.html:171
msgid "Part can be used in assemblies" msgid "Part can be used in assemblies"
msgstr "" msgstr ""
#: part/templates/part/detail.html:168 #: part/templates/part/detail.html:173
msgid "Part cannot be used in assemblies" msgid "Part cannot be used in assemblies"
msgstr "" msgstr ""
#: part/templates/part/detail.html:172 templates/js/table_filters.js:31 #: part/templates/part/detail.html:178 templates/js/table_filters.js:31
#: templates/js/table_filters.js:271 #: templates/js/table_filters.js:271
msgid "Trackable" msgid "Trackable"
msgstr "" msgstr ""
#: part/templates/part/detail.html:175 #: part/templates/part/detail.html:181
msgid "Part stock is tracked by serial number" msgid "Part stock is tracked by serial number"
msgstr "" msgstr ""
#: part/templates/part/detail.html:177 #: part/templates/part/detail.html:183
msgid "Part stock is not tracked by serial number" msgid "Part stock is not tracked by serial number"
msgstr "" msgstr ""
#: part/templates/part/detail.html:181 #: part/templates/part/detail.html:188
msgid "Purchaseable" msgid "Purchaseable"
msgstr "" msgstr ""
#: part/templates/part/detail.html:184 part/templates/part/detail.html:186 #: part/templates/part/detail.html:191 part/templates/part/detail.html:193
msgid "Part can be purchased from external suppliers" msgid "Part can be purchased from external suppliers"
msgstr "" msgstr ""
#: part/templates/part/detail.html:190 templates/js/table_filters.js:267 #: part/templates/part/detail.html:198 templates/js/table_filters.js:267
msgid "Salable" msgid "Salable"
msgstr "" msgstr ""
#: part/templates/part/detail.html:193 #: part/templates/part/detail.html:201
msgid "Part can be sold to customers" msgid "Part can be sold to customers"
msgstr "" msgstr ""
#: part/templates/part/detail.html:195 #: part/templates/part/detail.html:203
msgid "Part cannot be sold to customers" msgid "Part cannot be sold to customers"
msgstr "" msgstr ""
#: part/templates/part/detail.html:199 templates/js/table_filters.js:19 #: part/templates/part/detail.html:214 templates/js/table_filters.js:19
#: templates/js/table_filters.js:55 templates/js/table_filters.js:238 #: templates/js/table_filters.js:55 templates/js/table_filters.js:238
msgid "Active" msgid "Active"
msgstr "" msgstr ""
#: part/templates/part/detail.html:202 #: part/templates/part/detail.html:217
msgid "Part is active" msgid "Part is active"
msgstr "" msgstr ""
#: part/templates/part/detail.html:204 #: part/templates/part/detail.html:219
msgid "Part is not active" msgid "Part is not active"
msgstr "" msgstr ""
@ -3069,95 +3094,103 @@ msgstr ""
msgid "Edit Part Properties" msgid "Edit Part Properties"
msgstr "" msgstr ""
#: part/views.py:838 #: part/views.py:841
msgid "Duplicate BOM"
msgstr ""
#: part/views.py:871
msgid "Confirm duplication of BOM from parent"
msgstr ""
#: part/views.py:887
msgid "Validate BOM" msgid "Validate BOM"
msgstr "" msgstr ""
#: part/views.py:1005 #: part/views.py:1054
msgid "No BOM file provided" msgid "No BOM file provided"
msgstr "" msgstr ""
#: part/views.py:1355 #: part/views.py:1404
msgid "Enter a valid quantity" msgid "Enter a valid quantity"
msgstr "" msgstr ""
#: part/views.py:1380 part/views.py:1383 #: part/views.py:1429 part/views.py:1432
msgid "Select valid part" msgid "Select valid part"
msgstr "" msgstr ""
#: part/views.py:1389 #: part/views.py:1438
msgid "Duplicate part selected" msgid "Duplicate part selected"
msgstr "" msgstr ""
#: part/views.py:1427 #: part/views.py:1476
msgid "Select a part" msgid "Select a part"
msgstr "" msgstr ""
#: part/views.py:1433 #: part/views.py:1482
msgid "Selected part creates a circular BOM" msgid "Selected part creates a circular BOM"
msgstr "" msgstr ""
#: part/views.py:1437 #: part/views.py:1486
msgid "Specify quantity" msgid "Specify quantity"
msgstr "" msgstr ""
#: part/views.py:1693 #: part/views.py:1742
msgid "Confirm Part Deletion" msgid "Confirm Part Deletion"
msgstr "" msgstr ""
#: part/views.py:1702 #: part/views.py:1751
msgid "Part was deleted" msgid "Part was deleted"
msgstr "" msgstr ""
#: part/views.py:1711 #: part/views.py:1760
msgid "Part Pricing" msgid "Part Pricing"
msgstr "" msgstr ""
#: part/views.py:1837 #: part/views.py:1886
msgid "Create Part Parameter Template" msgid "Create Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1847 #: part/views.py:1896
msgid "Edit Part Parameter Template" msgid "Edit Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1856 #: part/views.py:1905
msgid "Delete Part Parameter Template" msgid "Delete Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1866 #: part/views.py:1915
msgid "Create Part Parameter" msgid "Create Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1918 #: part/views.py:1967
msgid "Edit Part Parameter" msgid "Edit Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1934 #: part/views.py:1983
msgid "Delete Part Parameter" msgid "Delete Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1993 #: part/views.py:2042
msgid "Edit Part Category" msgid "Edit Part Category"
msgstr "" msgstr ""
#: part/views.py:2030 #: part/views.py:2079
msgid "Delete Part Category" msgid "Delete Part Category"
msgstr "" msgstr ""
#: part/views.py:2038 #: part/views.py:2087
msgid "Part category was deleted" msgid "Part category was deleted"
msgstr "" msgstr ""
#: part/views.py:2101 #: part/views.py:2150
msgid "Create BOM Item" msgid "Create BOM Item"
msgstr "" msgstr ""
#: part/views.py:2169 #: part/views.py:2218
msgid "Edit BOM item" msgid "Edit BOM item"
msgstr "" msgstr ""
#: part/views.py:2219 #: part/views.py:2268
msgid "Confim BOM item deletion" msgid "Confim BOM item deletion"
msgstr "" msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-10-29 02:25+0000\n" "POT-Creation-Date: 2020-10-29 23:05+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -204,7 +204,7 @@ msgstr ""
msgid "Overage must be an integer value or a percentage" msgid "Overage must be an integer value or a percentage"
msgstr "" msgstr ""
#: InvenTree/views.py:707 #: InvenTree/views.py:752
msgid "Database Statistics" msgid "Database Statistics"
msgstr "" msgstr ""
@ -520,7 +520,7 @@ msgstr ""
msgid "No BOM items found" msgid "No BOM items found"
msgstr "" msgstr ""
#: build/templates/build/allocate.html:347 part/models.py:1401 #: build/templates/build/allocate.html:347 part/models.py:1425
#: templates/js/part.js:569 templates/js/table_filters.js:167 #: templates/js/part.js:569 templates/js/table_filters.js:167
msgid "Required" msgid "Required"
msgstr "" msgstr ""
@ -1192,7 +1192,7 @@ msgstr ""
#: company/templates/company/detail_stock.html:35 #: company/templates/company/detail_stock.html:35
#: company/templates/company/supplier_part_stock.html:33 #: company/templates/company/supplier_part_stock.html:33
#: part/templates/part/bom.html:62 part/templates/part/category.html:112 #: part/templates/part/bom.html:67 part/templates/part/category.html:112
#: part/templates/part/category.html:126 part/templates/part/stock.html:51 #: part/templates/part/category.html:126 part/templates/part/stock.html:51
#: templates/stock_table.html:7 #: templates/stock_table.html:7
msgid "Export" msgid "Export"
@ -1310,7 +1310,7 @@ msgid "Pricing Information"
msgstr "" msgstr ""
#: company/templates/company/supplier_part_pricing.html:17 company/views.py:410 #: company/templates/company/supplier_part_pricing.html:17 company/views.py:410
#: part/templates/part/sale_prices.html:13 part/views.py:2229 #: part/templates/part/sale_prices.html:13 part/views.py:2278
msgid "Add Price Break" msgid "Add Price Break"
msgstr "" msgstr ""
@ -1437,15 +1437,15 @@ msgstr ""
msgid "Delete Supplier Part" msgid "Delete Supplier Part"
msgstr "" msgstr ""
#: company/views.py:416 part/views.py:2235 #: company/views.py:416 part/views.py:2284
msgid "Added new price break" msgid "Added new price break"
msgstr "" msgstr ""
#: company/views.py:453 part/views.py:2280 #: company/views.py:453 part/views.py:2329
msgid "Edit Price Break" msgid "Edit Price Break"
msgstr "" msgstr ""
#: company/views.py:469 part/views.py:2296 #: company/views.py:469 part/views.py:2345
msgid "Delete Price Break" msgid "Delete Price Break"
msgstr "" msgstr ""
@ -1538,7 +1538,7 @@ msgstr ""
msgid "Date order was completed" msgid "Date order was completed"
msgstr "" msgstr ""
#: order/models.py:185 order/models.py:259 part/views.py:1346 #: order/models.py:185 order/models.py:259 part/views.py:1395
#: stock/models.py:241 stock/models.py:805 #: stock/models.py:241 stock/models.py:805
msgid "Quantity must be greater than zero" msgid "Quantity must be greater than zero"
msgstr "" msgstr ""
@ -1815,6 +1815,7 @@ msgstr ""
#: order/templates/order/sales_order_cancel.html:8 #: order/templates/order/sales_order_cancel.html:8
#: order/templates/order/sales_order_ship.html:9 #: order/templates/order/sales_order_ship.html:9
#: part/templates/part/bom_duplicate.html:12
#: stock/templates/stock/stockitem_convert.html:13 #: stock/templates/stock/stockitem_convert.html:13
msgid "Warning" msgid "Warning"
msgstr "" msgstr ""
@ -2039,91 +2040,107 @@ msgstr ""
msgid "Error reading BOM file (incorrect row size)" msgid "Error reading BOM file (incorrect row size)"
msgstr "" msgstr ""
#: part/forms.py:57 stock/forms.py:254 #: part/forms.py:62 stock/forms.py:254
msgid "File Format" msgid "File Format"
msgstr "" msgstr ""
#: part/forms.py:57 stock/forms.py:254 #: part/forms.py:62 stock/forms.py:254
msgid "Select output file format" msgid "Select output file format"
msgstr "" msgstr ""
#: part/forms.py:59 #: part/forms.py:64
msgid "Cascading" msgid "Cascading"
msgstr "" msgstr ""
#: part/forms.py:59 #: part/forms.py:64
msgid "Download cascading / multi-level BOM" msgid "Download cascading / multi-level BOM"
msgstr "" msgstr ""
#: part/forms.py:61 #: part/forms.py:66
msgid "Levels" msgid "Levels"
msgstr "" msgstr ""
#: part/forms.py:61 #: part/forms.py:66
msgid "Select maximum number of BOM levels to export (0 = all levels)" msgid "Select maximum number of BOM levels to export (0 = all levels)"
msgstr "" msgstr ""
#: part/forms.py:63 #: part/forms.py:68
msgid "Include Parameter Data" msgid "Include Parameter Data"
msgstr "" msgstr ""
#: part/forms.py:63 #: part/forms.py:68
msgid "Include part parameters data in exported BOM" msgid "Include part parameters data in exported BOM"
msgstr "" msgstr ""
#: part/forms.py:65 #: part/forms.py:70
msgid "Include Stock Data" msgid "Include Stock Data"
msgstr "" msgstr ""
#: part/forms.py:65 #: part/forms.py:70
msgid "Include part stock data in exported BOM" msgid "Include part stock data in exported BOM"
msgstr "" msgstr ""
#: part/forms.py:67 #: part/forms.py:72
msgid "Include Supplier Data" msgid "Include Supplier Data"
msgstr "" msgstr ""
#: part/forms.py:67 #: part/forms.py:72
msgid "Include part supplier data in exported BOM" msgid "Include part supplier data in exported BOM"
msgstr "" msgstr ""
#: part/forms.py:86 #: part/forms.py:93 part/models.py:1504
msgid "Parent Part"
msgstr ""
#: part/forms.py:94 part/templates/part/bom_duplicate.html:7
msgid "Select parent part to copy BOM from"
msgstr ""
#: part/forms.py:100
msgid "Clear existing BOM items"
msgstr ""
#: part/forms.py:105
msgid "Confirm BOM duplication"
msgstr ""
#: part/forms.py:123
msgid "Confirm that the BOM is correct" msgid "Confirm that the BOM is correct"
msgstr "" msgstr ""
#: part/forms.py:98 #: part/forms.py:135
msgid "Select BOM file to upload" msgid "Select BOM file to upload"
msgstr "" msgstr ""
#: part/forms.py:122 #: part/forms.py:159
msgid "Select part category" msgid "Select part category"
msgstr "" msgstr ""
#: part/forms.py:136 #: part/forms.py:173
msgid "Duplicate all BOM data for this part" msgid "Duplicate all BOM data for this part"
msgstr "" msgstr ""
#: part/forms.py:137 #: part/forms.py:174
msgid "Copy BOM" msgid "Copy BOM"
msgstr "" msgstr ""
#: part/forms.py:142 #: part/forms.py:179
msgid "Duplicate all parameter data for this part" msgid "Duplicate all parameter data for this part"
msgstr "" msgstr ""
#: part/forms.py:143 #: part/forms.py:180
msgid "Copy Parameters" msgid "Copy Parameters"
msgstr "" msgstr ""
#: part/forms.py:148 #: part/forms.py:185
msgid "Confirm part creation" msgid "Confirm part creation"
msgstr "" msgstr ""
#: part/forms.py:248 #: part/forms.py:279
msgid "Input quantity for price calculation" msgid "Input quantity for price calculation"
msgstr "" msgstr ""
#: part/forms.py:251 #: part/forms.py:282
msgid "Select currency for price calculation" msgid "Select currency for price calculation"
msgstr "" msgstr ""
@ -2249,112 +2266,108 @@ msgstr ""
msgid "Stored BOM checksum" msgid "Stored BOM checksum"
msgstr "" msgstr ""
#: part/models.py:1353 #: part/models.py:1377
msgid "Test templates can only be created for trackable parts" msgid "Test templates can only be created for trackable parts"
msgstr "" msgstr ""
#: part/models.py:1370 #: part/models.py:1394
msgid "Test with this name already exists for this part" msgid "Test with this name already exists for this part"
msgstr "" msgstr ""
#: part/models.py:1389 templates/js/part.js:560 templates/js/stock.js:92 #: part/models.py:1413 templates/js/part.js:560 templates/js/stock.js:92
msgid "Test Name" msgid "Test Name"
msgstr "" msgstr ""
#: part/models.py:1390 #: part/models.py:1414
msgid "Enter a name for the test" msgid "Enter a name for the test"
msgstr "" msgstr ""
#: part/models.py:1395 #: part/models.py:1419
msgid "Test Description" msgid "Test Description"
msgstr "" msgstr ""
#: part/models.py:1396 #: part/models.py:1420
msgid "Enter description for this test" msgid "Enter description for this test"
msgstr "" msgstr ""
#: part/models.py:1402 #: part/models.py:1426
msgid "Is this test required to pass?" msgid "Is this test required to pass?"
msgstr "" msgstr ""
#: part/models.py:1407 templates/js/part.js:577 #: part/models.py:1431 templates/js/part.js:577
msgid "Requires Value" msgid "Requires Value"
msgstr "" msgstr ""
#: part/models.py:1408 #: part/models.py:1432
msgid "Does this test require a value when adding a test result?" msgid "Does this test require a value when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1413 templates/js/part.js:584 #: part/models.py:1437 templates/js/part.js:584
msgid "Requires Attachment" msgid "Requires Attachment"
msgstr "" msgstr ""
#: part/models.py:1414 #: part/models.py:1438
msgid "Does this test require a file attachment when adding a test result?" msgid "Does this test require a file attachment when adding a test result?"
msgstr "" msgstr ""
#: part/models.py:1447 #: part/models.py:1471
msgid "Parameter template name must be unique" msgid "Parameter template name must be unique"
msgstr "" msgstr ""
#: part/models.py:1452 #: part/models.py:1476
msgid "Parameter Name" msgid "Parameter Name"
msgstr "" msgstr ""
#: part/models.py:1454 #: part/models.py:1478
msgid "Parameter Units" msgid "Parameter Units"
msgstr "" msgstr ""
#: part/models.py:1480 #: part/models.py:1506
msgid "Parent Part"
msgstr ""
#: part/models.py:1482
msgid "Parameter Template" msgid "Parameter Template"
msgstr "" msgstr ""
#: part/models.py:1484 #: part/models.py:1508
msgid "Parameter Value" msgid "Parameter Value"
msgstr "" msgstr ""
#: part/models.py:1521 #: part/models.py:1545
msgid "Select parent part" msgid "Select parent part"
msgstr "" msgstr ""
#: part/models.py:1529 #: part/models.py:1553
msgid "Select part to be used in BOM" msgid "Select part to be used in BOM"
msgstr "" msgstr ""
#: part/models.py:1535 #: part/models.py:1559
msgid "BOM quantity for this BOM item" msgid "BOM quantity for this BOM item"
msgstr "" msgstr ""
#: part/models.py:1537 #: part/models.py:1561
msgid "This BOM item is optional" msgid "This BOM item is optional"
msgstr "" msgstr ""
#: part/models.py:1540 #: part/models.py:1564
msgid "Estimated build wastage quantity (absolute or percentage)" msgid "Estimated build wastage quantity (absolute or percentage)"
msgstr "" msgstr ""
#: part/models.py:1543 #: part/models.py:1567
msgid "BOM item reference" msgid "BOM item reference"
msgstr "" msgstr ""
#: part/models.py:1546 #: part/models.py:1570
msgid "BOM item notes" msgid "BOM item notes"
msgstr "" msgstr ""
#: part/models.py:1548 #: part/models.py:1572
msgid "BOM line checksum" msgid "BOM line checksum"
msgstr "" msgstr ""
#: part/models.py:1612 part/views.py:1352 part/views.py:1404 #: part/models.py:1636 part/views.py:1401 part/views.py:1453
#: stock/models.py:231 #: stock/models.py:231
msgid "Quantity must be integer value for trackable parts" msgid "Quantity must be integer value for trackable parts"
msgstr "" msgstr ""
#: part/models.py:1621 #: part/models.py:1645
msgid "BOM Item" msgid "BOM Item"
msgstr "" msgstr ""
@ -2396,54 +2409,66 @@ msgid "Import BOM data"
msgstr "" msgstr ""
#: part/templates/part/bom.html:42 #: part/templates/part/bom.html:42
msgid "Upload" msgid "Import from File"
msgstr ""
#: part/templates/part/bom.html:44
msgid "New BOM Item"
msgstr "" msgstr ""
#: part/templates/part/bom.html:45 #: part/templates/part/bom.html:45
msgid "Copy BOM from parent part"
msgstr ""
#: part/templates/part/bom.html:46
msgid "Copy from Parent"
msgstr ""
#: part/templates/part/bom.html:49
msgid "New BOM Item"
msgstr ""
#: part/templates/part/bom.html:50
msgid "Add Item" msgid "Add Item"
msgstr "" msgstr ""
#: part/templates/part/bom.html:47 #: part/templates/part/bom.html:52
msgid "Finish Editing" msgid "Finish Editing"
msgstr "" msgstr ""
#: part/templates/part/bom.html:48 #: part/templates/part/bom.html:53
msgid "Finished" msgid "Finished"
msgstr "" msgstr ""
#: part/templates/part/bom.html:52 #: part/templates/part/bom.html:57
msgid "Edit BOM" msgid "Edit BOM"
msgstr "" msgstr ""
#: part/templates/part/bom.html:53 part/templates/part/params.html:38 #: part/templates/part/bom.html:58 part/templates/part/params.html:38
#: templates/InvenTree/settings/user.html:19 #: templates/InvenTree/settings/user.html:19
msgid "Edit" msgid "Edit"
msgstr "" msgstr ""
#: part/templates/part/bom.html:56 #: part/templates/part/bom.html:61
msgid "Validate Bill of Materials" msgid "Validate Bill of Materials"
msgstr "" msgstr ""
#: part/templates/part/bom.html:57 #: part/templates/part/bom.html:62
msgid "Validate" msgid "Validate"
msgstr "" msgstr ""
#: part/templates/part/bom.html:61 part/views.py:1643 #: part/templates/part/bom.html:66 part/views.py:1692
msgid "Export Bill of Materials" msgid "Export Bill of Materials"
msgstr "" msgstr ""
#: part/templates/part/bom.html:122 #: part/templates/part/bom.html:127
msgid "Delete selected BOM items?" msgid "Delete selected BOM items?"
msgstr "" msgstr ""
#: part/templates/part/bom.html:123 #: part/templates/part/bom.html:128
msgid "All selected BOM items will be deleted" msgid "All selected BOM items will be deleted"
msgstr "" msgstr ""
#: part/templates/part/bom_duplicate.html:13
msgid "This part already has a Bill of Materials"
msgstr ""
#: part/templates/part/bom_upload/select_fields.html:8 #: part/templates/part/bom_upload/select_fields.html:8
#: part/templates/part/bom_upload/select_parts.html:8 #: part/templates/part/bom_upload/select_parts.html:8
#: part/templates/part/bom_upload/upload_file.html:10 #: part/templates/part/bom_upload/upload_file.html:10
@ -2524,7 +2549,7 @@ msgstr ""
msgid "All parts" msgid "All parts"
msgstr "" msgstr ""
#: part/templates/part/category.html:24 part/views.py:2046 #: part/templates/part/category.html:24 part/views.py:2095
msgid "Create new part category" msgid "Create new part category"
msgstr "" msgstr ""
@ -2670,98 +2695,98 @@ msgstr ""
msgid "Responsible User" msgid "Responsible User"
msgstr "" msgstr ""
#: part/templates/part/detail.html:136 templates/js/table_filters.js:27 #: part/templates/part/detail.html:138 templates/js/table_filters.js:27
msgid "Virtual" msgid "Virtual"
msgstr "" msgstr ""
#: part/templates/part/detail.html:139 #: part/templates/part/detail.html:141
msgid "Part is virtual (not a physical part)" msgid "Part is virtual (not a physical part)"
msgstr "" msgstr ""
#: part/templates/part/detail.html:141 #: part/templates/part/detail.html:143
msgid "Part is not a virtual part" msgid "Part is not a virtual part"
msgstr "" msgstr ""
#: part/templates/part/detail.html:145 stock/forms.py:248 #: part/templates/part/detail.html:148 stock/forms.py:248
#: templates/js/table_filters.js:23 templates/js/table_filters.js:243 #: templates/js/table_filters.js:23 templates/js/table_filters.js:243
msgid "Template" msgid "Template"
msgstr "" msgstr ""
#: part/templates/part/detail.html:148 #: part/templates/part/detail.html:151
msgid "Part is a template part (variants can be made from this part)" msgid "Part is a template part (variants can be made from this part)"
msgstr "" msgstr ""
#: part/templates/part/detail.html:150 #: part/templates/part/detail.html:153
msgid "Part is not a template part" msgid "Part is not a template part"
msgstr "" msgstr ""
#: part/templates/part/detail.html:154 templates/js/table_filters.js:255 #: part/templates/part/detail.html:158 templates/js/table_filters.js:255
msgid "Assembly" msgid "Assembly"
msgstr "" msgstr ""
#: part/templates/part/detail.html:157 #: part/templates/part/detail.html:161
msgid "Part can be assembled from other parts" msgid "Part can be assembled from other parts"
msgstr "" msgstr ""
#: part/templates/part/detail.html:159 #: part/templates/part/detail.html:163
msgid "Part cannot be assembled from other parts" msgid "Part cannot be assembled from other parts"
msgstr "" msgstr ""
#: part/templates/part/detail.html:163 templates/js/table_filters.js:259 #: part/templates/part/detail.html:168 templates/js/table_filters.js:259
msgid "Component" msgid "Component"
msgstr "" msgstr ""
#: part/templates/part/detail.html:166 #: part/templates/part/detail.html:171
msgid "Part can be used in assemblies" msgid "Part can be used in assemblies"
msgstr "" msgstr ""
#: part/templates/part/detail.html:168 #: part/templates/part/detail.html:173
msgid "Part cannot be used in assemblies" msgid "Part cannot be used in assemblies"
msgstr "" msgstr ""
#: part/templates/part/detail.html:172 templates/js/table_filters.js:31 #: part/templates/part/detail.html:178 templates/js/table_filters.js:31
#: templates/js/table_filters.js:271 #: templates/js/table_filters.js:271
msgid "Trackable" msgid "Trackable"
msgstr "" msgstr ""
#: part/templates/part/detail.html:175 #: part/templates/part/detail.html:181
msgid "Part stock is tracked by serial number" msgid "Part stock is tracked by serial number"
msgstr "" msgstr ""
#: part/templates/part/detail.html:177 #: part/templates/part/detail.html:183
msgid "Part stock is not tracked by serial number" msgid "Part stock is not tracked by serial number"
msgstr "" msgstr ""
#: part/templates/part/detail.html:181 #: part/templates/part/detail.html:188
msgid "Purchaseable" msgid "Purchaseable"
msgstr "" msgstr ""
#: part/templates/part/detail.html:184 part/templates/part/detail.html:186 #: part/templates/part/detail.html:191 part/templates/part/detail.html:193
msgid "Part can be purchased from external suppliers" msgid "Part can be purchased from external suppliers"
msgstr "" msgstr ""
#: part/templates/part/detail.html:190 templates/js/table_filters.js:267 #: part/templates/part/detail.html:198 templates/js/table_filters.js:267
msgid "Salable" msgid "Salable"
msgstr "" msgstr ""
#: part/templates/part/detail.html:193 #: part/templates/part/detail.html:201
msgid "Part can be sold to customers" msgid "Part can be sold to customers"
msgstr "" msgstr ""
#: part/templates/part/detail.html:195 #: part/templates/part/detail.html:203
msgid "Part cannot be sold to customers" msgid "Part cannot be sold to customers"
msgstr "" msgstr ""
#: part/templates/part/detail.html:199 templates/js/table_filters.js:19 #: part/templates/part/detail.html:214 templates/js/table_filters.js:19
#: templates/js/table_filters.js:55 templates/js/table_filters.js:238 #: templates/js/table_filters.js:55 templates/js/table_filters.js:238
msgid "Active" msgid "Active"
msgstr "" msgstr ""
#: part/templates/part/detail.html:202 #: part/templates/part/detail.html:217
msgid "Part is active" msgid "Part is active"
msgstr "" msgstr ""
#: part/templates/part/detail.html:204 #: part/templates/part/detail.html:219
msgid "Part is not active" msgid "Part is not active"
msgstr "" msgstr ""
@ -3069,95 +3094,103 @@ msgstr ""
msgid "Edit Part Properties" msgid "Edit Part Properties"
msgstr "" msgstr ""
#: part/views.py:838 #: part/views.py:841
msgid "Duplicate BOM"
msgstr ""
#: part/views.py:871
msgid "Confirm duplication of BOM from parent"
msgstr ""
#: part/views.py:887
msgid "Validate BOM" msgid "Validate BOM"
msgstr "" msgstr ""
#: part/views.py:1005 #: part/views.py:1054
msgid "No BOM file provided" msgid "No BOM file provided"
msgstr "" msgstr ""
#: part/views.py:1355 #: part/views.py:1404
msgid "Enter a valid quantity" msgid "Enter a valid quantity"
msgstr "" msgstr ""
#: part/views.py:1380 part/views.py:1383 #: part/views.py:1429 part/views.py:1432
msgid "Select valid part" msgid "Select valid part"
msgstr "" msgstr ""
#: part/views.py:1389 #: part/views.py:1438
msgid "Duplicate part selected" msgid "Duplicate part selected"
msgstr "" msgstr ""
#: part/views.py:1427 #: part/views.py:1476
msgid "Select a part" msgid "Select a part"
msgstr "" msgstr ""
#: part/views.py:1433 #: part/views.py:1482
msgid "Selected part creates a circular BOM" msgid "Selected part creates a circular BOM"
msgstr "" msgstr ""
#: part/views.py:1437 #: part/views.py:1486
msgid "Specify quantity" msgid "Specify quantity"
msgstr "" msgstr ""
#: part/views.py:1693 #: part/views.py:1742
msgid "Confirm Part Deletion" msgid "Confirm Part Deletion"
msgstr "" msgstr ""
#: part/views.py:1702 #: part/views.py:1751
msgid "Part was deleted" msgid "Part was deleted"
msgstr "" msgstr ""
#: part/views.py:1711 #: part/views.py:1760
msgid "Part Pricing" msgid "Part Pricing"
msgstr "" msgstr ""
#: part/views.py:1837 #: part/views.py:1886
msgid "Create Part Parameter Template" msgid "Create Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1847 #: part/views.py:1896
msgid "Edit Part Parameter Template" msgid "Edit Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1856 #: part/views.py:1905
msgid "Delete Part Parameter Template" msgid "Delete Part Parameter Template"
msgstr "" msgstr ""
#: part/views.py:1866 #: part/views.py:1915
msgid "Create Part Parameter" msgid "Create Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1918 #: part/views.py:1967
msgid "Edit Part Parameter" msgid "Edit Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1934 #: part/views.py:1983
msgid "Delete Part Parameter" msgid "Delete Part Parameter"
msgstr "" msgstr ""
#: part/views.py:1993 #: part/views.py:2042
msgid "Edit Part Category" msgid "Edit Part Category"
msgstr "" msgstr ""
#: part/views.py:2030 #: part/views.py:2079
msgid "Delete Part Category" msgid "Delete Part Category"
msgstr "" msgstr ""
#: part/views.py:2038 #: part/views.py:2087
msgid "Part category was deleted" msgid "Part category was deleted"
msgstr "" msgstr ""
#: part/views.py:2101 #: part/views.py:2150
msgid "Create BOM Item" msgid "Create BOM Item"
msgstr "" msgstr ""
#: part/views.py:2169 #: part/views.py:2218
msgid "Edit BOM item" msgid "Edit BOM item"
msgstr "" msgstr ""
#: part/views.py:2219 #: part/views.py:2268
msgid "Confim BOM item deletion" msgid "Confim BOM item deletion"
msgstr "" msgstr ""

View File

@ -100,9 +100,9 @@ class PurchaseOrderAttachmentCreate(AjaxCreateView):
ajax_template_name = "modal_form.html" ajax_template_name = "modal_form.html"
role_required = 'purchase_order.add' role_required = 'purchase_order.add'
def post_save(self, **kwargs): def post_save(self, attachment, form, **kwargs):
self.object.user = self.request.user attachment.user = self.request.user
self.object.save() attachment.save()
def get_data(self): def get_data(self):
return { return {
@ -148,7 +148,7 @@ class SalesOrderAttachmentCreate(AjaxCreateView):
ajax_form_title = _('Add Sales Order Attachment') ajax_form_title = _('Add Sales Order Attachment')
role_required = 'sales_order.add' role_required = 'sales_order.add'
def post_save(self, **kwargs): def post_save(self, attachment, form, **kwargs):
self.object.user = self.request.user self.object.user = self.request.user
self.object.save() self.object.save()
@ -319,11 +319,11 @@ class PurchaseOrderCreate(AjaxCreateView):
return initials return initials
def post_save(self, **kwargs): def post_save(self, order, form, **kwargs):
# Record the user who created this purchase order # Record the user who created this purchase order
self.object.created_by = self.request.user order.created_by = self.request.user
self.object.save() order.save()
class SalesOrderCreate(AjaxCreateView): class SalesOrderCreate(AjaxCreateView):
@ -351,10 +351,10 @@ class SalesOrderCreate(AjaxCreateView):
return initials return initials
def post_save(self, **kwargs): def post_save(self, order, form, **kwargs):
# Record the user who created this sales order # Record the user who created this sales order
self.object.created_by = self.request.user order.created_by = self.request.user
self.object.save() order.save()
class PurchaseOrderEdit(AjaxUpdateView): class PurchaseOrderEdit(AjaxUpdateView):

View File

@ -19,10 +19,15 @@ from .models import PartParameterTemplate, PartParameter
from .models import PartTestTemplate from .models import PartTestTemplate
from .models import PartSellPriceBreak from .models import PartSellPriceBreak
from common.models import Currency from common.models import Currency
class PartModelChoiceField(forms.ModelChoiceField):
""" Extending string representation of Part instance with available stock """
def label_from_instance(self, part):
return f'{part} - {part.available_stock}'
class PartImageForm(HelperForm): class PartImageForm(HelperForm):
""" Form for uploading a Part image """ """ Form for uploading a Part image """
@ -77,6 +82,38 @@ class BomExportForm(forms.Form):
self.fields['file_format'].choices = self.get_choices() self.fields['file_format'].choices = self.get_choices()
class BomDuplicateForm(HelperForm):
"""
Simple confirmation form for BOM duplication.
Select which parent to select from.
"""
parent = PartModelChoiceField(
label=_('Parent Part'),
help_text=_('Select parent part to copy BOM from'),
queryset=Part.objects.filter(is_template=True),
)
clear = forms.BooleanField(
required=False, initial=True,
help_text=_('Clear existing BOM items')
)
confirm = forms.BooleanField(
required=False, initial=False,
help_text=_('Confirm BOM duplication')
)
class Meta:
model = Part
fields = [
'parent',
'clear',
'confirm',
]
class BomValidateForm(HelperForm): class BomValidateForm(HelperForm):
""" Simple confirmation form for BOM validation. """ Simple confirmation form for BOM validation.
User is presented with a single checkbox input, User is presented with a single checkbox input,
@ -210,12 +247,6 @@ class EditCategoryForm(HelperForm):
] ]
class PartModelChoiceField(forms.ModelChoiceField):
""" Extending string representation of Part instance with available stock """
def label_from_instance(self, part):
return f'{part} - {part.available_stock}'
class EditBomItemForm(HelperForm): class EditBomItemForm(HelperForm):
""" Form for editing a BomItem object """ """ Form for editing a BomItem object """

View File

@ -1087,6 +1087,35 @@ class Part(MPTTModel):
max(buy_price_range[1], bom_price_range[1]) max(buy_price_range[1], bom_price_range[1])
) )
@transaction.atomic
def copy_bom_from(self, other, clear=True, **kwargs):
"""
Copy the BOM from another part.
args:
other - The part to copy the BOM from
clear - Remove existing BOM items first (default=True)
"""
if clear:
# Remove existing BOM items
self.bom_items.all().delete()
for bom_item in other.bom_items.all():
# If this part already has a BomItem pointing to the same sub-part,
# delete that BomItem from this part first!
try:
existing = BomItem.objects.get(part=self, sub_part=bom_item.sub_part)
existing.delete()
except (BomItem.DoesNotExist):
pass
bom_item.part = self
bom_item.pk = None
bom_item.save()
def deepCopy(self, other, **kwargs): def deepCopy(self, other, **kwargs):
""" Duplicates non-field data from another part. """ Duplicates non-field data from another part.
Does not alter the normal fields of this part, Does not alter the normal fields of this part,
@ -1106,12 +1135,7 @@ class Part(MPTTModel):
# Copy the BOM data # Copy the BOM data
if kwargs.get('bom', False): if kwargs.get('bom', False):
for item in other.bom_items.all(): self.copy_bom_from(other)
# Point the item to THIS part.
# Set the pk to None so a new entry is created.
item.part = self
item.pk = None
item.save()
# Copy the parameters data # Copy the parameters data
if kwargs.get('parameters', True): if kwargs.get('parameters', True):

View File

@ -39,8 +39,13 @@
<span class='fas fa-trash-alt'></span> <span class='fas fa-trash-alt'></span>
</button> </button>
<button class='btn btn-primary' type='button' title='{% trans "Import BOM data" %}' id='bom-upload'> <button class='btn btn-primary' type='button' title='{% trans "Import BOM data" %}' id='bom-upload'>
<span class='fas fa-file-upload'></span> {% trans "Upload" %} <span class='fas fa-file-upload'></span> {% trans "Import from File" %}
</button> </button>
{% if part.variant_of %}
<button class='btn btn-default' type='button' title='{% trans "Copy BOM from parent part" %}' id='bom-duplicate'>
<span class='fas fa-clone'></span> {% trans "Copy from Parent" %}
</button>
{% endif %}
<button class='btn btn-default' type='button' title='{% trans "New BOM Item" %}' id='bom-item-new'> <button class='btn btn-default' type='button' title='{% trans "New BOM Item" %}' id='bom-item-new'>
<span class='fas fa-plus-circle'></span> {% trans "Add Item" %} <span class='fas fa-plus-circle'></span> {% trans "Add Item" %}
</button> </button>
@ -157,6 +162,17 @@
location.href = "{% url 'upload-bom' part.id %}"; location.href = "{% url 'upload-bom' part.id %}";
}); });
$('#bom-duplicate').click(function() {
launchModalForm(
"{% url 'duplicate-bom' part.id %}",
{
success: function() {
$('#bom-table').bootstrapTable('refresh');
}
}
);
});
$("#bom-item-new").click(function () { $("#bom-item-new").click(function () {
launchModalForm( launchModalForm(
"{% url 'bom-item-create' %}?parent={{ part.id }}", "{% url 'bom-item-create' %}?parent={{ part.id }}",

View File

@ -0,0 +1,17 @@
{% extends "modal_form.html" %}
{% load i18n %}
{% block pre_form_content %}
<p>
{% trans "Select parent part to copy BOM from" %}
</p>
{% if part.has_bom %}
<div class='alert alert-block alert-danger'>
<b>{% trans "Warning" %}</b><br>
{% trans "This part already has a Bill of Materials" %}<br>
</div>
{% endif %}
{% endblock %}

View File

@ -46,6 +46,7 @@ part_detail_urls = [
url(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'), url(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'),
url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'), url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'),
url(r'^bom-duplicate/?', views.BomDuplicate.as_view(), name='duplicate-bom'),
url(r'^params/', views.PartDetail.as_view(template_name='part/params.html'), name='part-params'), url(r'^params/', views.PartDetail.as_view(template_name='part/params.html'), name='part-params'),
url(r'^variants/?', views.PartDetail.as_view(template_name='part/variants.html'), name='part-variants'), url(r'^variants/?', views.PartDetail.as_view(template_name='part/variants.html'), name='part-variants'),

View File

@ -831,8 +831,60 @@ class PartEdit(AjaxUpdateView):
return form return form
class BomDuplicate(AjaxUpdateView):
"""
View for duplicating BOM from a parent item.
"""
model = Part
context_object_name = 'part'
ajax_form_title = _('Duplicate BOM')
ajax_template_name = 'part/bom_duplicate.html'
form_class = part_forms.BomDuplicateForm
role_required = 'part.change'
def get_form(self):
form = super().get_form()
# Limit choices to parents of the current part
parents = self.get_object().get_ancestors()
form.fields['parent'].queryset = parents
return form
def get_initial(self):
initials = super().get_initial()
parents = self.get_object().get_ancestors()
if parents.count() == 1:
initials['parent'] = parents[0]
return initials
def validate(self, part, form):
confirm = str2bool(form.cleaned_data.get('confirm', False))
if not confirm:
form.add_error('confirm', _('Confirm duplication of BOM from parent'))
def post_save(self, part, form):
parent = form.cleaned_data.get('parent', None)
clear = str2bool(form.cleaned_data.get('clear', True))
if parent:
part.copy_bom_from(parent, clear=clear)
class BomValidate(AjaxUpdateView): class BomValidate(AjaxUpdateView):
""" Modal form view for validating a part BOM """ """
Modal form view for validating a part BOM
"""
model = Part model = Part
ajax_form_title = _("Validate BOM") ajax_form_title = _("Validate BOM")

View File

@ -164,11 +164,11 @@ class StockItemAttachmentCreate(AjaxCreateView):
ajax_template_name = "modal_form.html" ajax_template_name = "modal_form.html"
role_required = 'stock.add' role_required = 'stock.add'
def post_save(self, **kwargs): def post_save(self, attachment, form, **kwargs):
""" Record the user that uploaded the attachment """ """ Record the user that uploaded the attachment """
self.object.user = self.request.user attachment.user = self.request.user
self.object.save() attachment.save()
def get_data(self): def get_data(self):
return { return {
@ -440,11 +440,11 @@ class StockItemTestResultCreate(AjaxCreateView):
ajax_form_title = _("Add Test Result") ajax_form_title = _("Add Test Result")
role_required = 'stock.add' role_required = 'stock.add'
def post_save(self, **kwargs): def post_save(self, result, form, **kwargs):
""" Record the user that uploaded the test result """ """ Record the user that uploaded the test result """
self.object.user = self.request.user result.user = self.request.user
self.object.save() result.save()
def get_initial(self): def get_initial(self):