mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Pass file data through to the next form page
This commit is contained in:
parent
a9396f4c74
commit
4648db6ce5
@ -59,15 +59,8 @@ class BomUploadManager:
|
|||||||
'Notes'
|
'Notes'
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, bom_file, starting_row=2):
|
def __init__(self, bom_file):
|
||||||
""" Initialize the BomUpload class with a user-uploaded file object """
|
""" Initialize the BomUpload class with a user-uploaded file object """
|
||||||
try:
|
|
||||||
start = int(starting_row) - 1
|
|
||||||
if start < 0:
|
|
||||||
start = 0
|
|
||||||
self.starting_row = start
|
|
||||||
except ValueError:
|
|
||||||
self.starting_row = 1
|
|
||||||
|
|
||||||
self.process(bom_file)
|
self.process(bom_file)
|
||||||
|
|
||||||
@ -154,6 +147,20 @@ class BomUploadManager:
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_headers(self):
|
||||||
|
""" Return a list of headers for the thingy """
|
||||||
|
headers = []
|
||||||
|
|
||||||
|
return headers
|
||||||
|
|
||||||
|
|
||||||
|
def col_count(self):
|
||||||
|
if self.data is None:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
return len(self.data.headers)
|
||||||
|
|
||||||
def row_count(self):
|
def row_count(self):
|
||||||
""" Return the number of rows in the file.
|
""" Return the number of rows in the file.
|
||||||
Ignored the top rows as indicated by 'starting row'
|
Ignored the top rows as indicated by 'starting row'
|
||||||
@ -162,16 +169,30 @@ class BomUploadManager:
|
|||||||
if self.data is None:
|
if self.data is None:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# Limit the number of BOM lines to be sensible
|
return len(self.data)
|
||||||
count = min(len(self.data) - self.starting_row, 1000)
|
|
||||||
|
|
||||||
return count
|
def rows(self):
|
||||||
|
""" Return a list of all rows """
|
||||||
|
rows = []
|
||||||
|
|
||||||
def get_row(self, index):
|
for i in range(self.row_count()):
|
||||||
|
row = self.get_row_data(i)
|
||||||
|
|
||||||
|
if row:
|
||||||
|
rows.append(row)
|
||||||
|
|
||||||
|
return rows
|
||||||
|
|
||||||
|
def get_row_data(self, index):
|
||||||
|
""" Retrieve row data at a particular index """
|
||||||
|
if self.data is None or index >= len(self.data):
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.data[index]
|
||||||
|
|
||||||
|
def get_row_dict(self, index):
|
||||||
""" Retrieve a dict object representing the data row at a particular offset """
|
""" Retrieve a dict object representing the data row at a particular offset """
|
||||||
|
|
||||||
index += self.starting_row
|
|
||||||
|
|
||||||
if self.data is None or index >= len(self.data):
|
if self.data is None or index >= len(self.data):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -39,25 +39,29 @@ class BomValidateForm(HelperForm):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class BomImportForm(HelperForm):
|
class BomUploadSelectFile(HelperForm):
|
||||||
""" Form for importing a BOM. Provides a file input box for upload """
|
""" Form for importing a BOM. Provides a file input box for upload """
|
||||||
|
|
||||||
bom_file = forms.FileField(label='BOM file', required=True, help_text="Select BOM file to upload")
|
bom_file = forms.FileField(label='BOM file', required=True, help_text="Select BOM file to upload")
|
||||||
|
|
||||||
starting_row = forms.IntegerField(
|
|
||||||
required=True,
|
|
||||||
initial=2,
|
|
||||||
help_text='First row containing valid BOM data',
|
|
||||||
validators=[
|
|
||||||
MinValueValidator(1)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Part
|
model = Part
|
||||||
fields = [
|
fields = [
|
||||||
'bom_file',
|
'bom_file',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class BomUploadSelectFields(HelperForm):
|
||||||
|
""" Form for selecting BOM fields """
|
||||||
|
|
||||||
|
starting_row = forms.IntegerField(required=True, initial=2, help_text='Index of starting row', validators=[MinValueValidator(1)])
|
||||||
|
row_count = forms.IntegerField(required=True, help_text='Number of rows to process', validators=[MinValueValidator(0)])
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Part
|
||||||
|
fields = [
|
||||||
'starting_row',
|
'starting_row',
|
||||||
|
'row_count',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
38
InvenTree/part/templates/part/bom_upload/select_fields.html
Normal file
38
InvenTree/part/templates/part/bom_upload/select_fields.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{% extends "modal_form.html" %}
|
||||||
|
{% load inventree_extras %}
|
||||||
|
|
||||||
|
{% block form %}
|
||||||
|
|
||||||
|
<h4>Step 2 of 3 - Select BOM Fields</h4>
|
||||||
|
|
||||||
|
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
|
{% crispy form %}
|
||||||
|
|
||||||
|
<input type='hidden' name='form_step' value='select_fields'/>
|
||||||
|
|
||||||
|
<table class='table table-striped'>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for row in bom.rows %}
|
||||||
|
<tr>
|
||||||
|
{% for item in row %}
|
||||||
|
<td>
|
||||||
|
{{ item }}
|
||||||
|
</td>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<b>BOM Rows: {{ bom.row_count }}</b>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
{% block pre_form_content %}
|
{% block pre_form_content %}
|
||||||
|
|
||||||
|
<h4>Step 1 of 3 - Select BOM File</h4>
|
||||||
|
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
|
||||||
<p>Select a BOM file to upload for <b>{{ part.name }} - <i>{{ part.description }}</i></b>.</p>
|
<p>Select a BOM file to upload for:<br>
|
||||||
|
<b>{{ part.name }} - <i>{{ part.description }}</i></b>
|
||||||
|
</p>
|
||||||
|
|
||||||
<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>
|
<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>
|
||||||
|
|
||||||
@ -14,4 +18,8 @@
|
|||||||
<li>Maximum of 1000 lines per BOM</li>
|
<li>Maximum of 1000 lines per BOM</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block form_data %}
|
||||||
|
<input type='hidden' name='form_step' value='select_file'/>
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -8,6 +8,11 @@ from InvenTree import version
|
|||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag()
|
||||||
|
def inrange(n, *args, **kwargs):
|
||||||
|
""" Return range(n) for iterating through a numeric quantity """
|
||||||
|
return range(n)
|
||||||
|
|
||||||
@register.simple_tag()
|
@register.simple_tag()
|
||||||
def multiply(x, y, *args, **kwargs):
|
def multiply(x, y, *args, **kwargs):
|
||||||
""" Multiply two numbers together """
|
""" Multiply two numbers together """
|
||||||
|
@ -650,8 +650,17 @@ class BomUpload(AjaxView, FormMixin):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
ajax_form_title = 'Upload Bill of Materials'
|
ajax_form_title = 'Upload Bill of Materials'
|
||||||
ajax_template_name = 'part/bom_upload.html'
|
ajax_template_name = 'part/bom_upload/select_file.html'
|
||||||
form_class = part_forms.BomImportForm
|
|
||||||
|
def get_form_class(self):
|
||||||
|
|
||||||
|
form_step = self.request.POST.get('form_step', None)
|
||||||
|
|
||||||
|
if form_step == 'select_fields':
|
||||||
|
return part_forms.BomUploadSelectFields
|
||||||
|
else:
|
||||||
|
# Default form is the starting point
|
||||||
|
return part_forms.BomUploadSelectFile
|
||||||
|
|
||||||
def get_context_data(self):
|
def get_context_data(self):
|
||||||
ctx = {
|
ctx = {
|
||||||
@ -674,24 +683,54 @@ class BomUpload(AjaxView, FormMixin):
|
|||||||
|
|
||||||
return self.renderJsonResponse(request, self.form)
|
return self.renderJsonResponse(request, self.form)
|
||||||
|
|
||||||
def handleBomFileUpload(self, bom_file):
|
def handleBomFileUpload(self):
|
||||||
|
|
||||||
|
bom_file = self.request.FILES.get('bom_file', None)
|
||||||
|
|
||||||
|
manager = None
|
||||||
|
bom_file_valid = False
|
||||||
|
|
||||||
|
if bom_file is None:
|
||||||
|
self.form.errors['bom_file'] = [_('No BOM file provided')]
|
||||||
|
else:
|
||||||
|
# Create a BomUploadManager object - will perform initial data validation
|
||||||
|
# (and raise a ValidationError if there is something wrong with the file)
|
||||||
|
try:
|
||||||
|
manager = BomUploadManager(bom_file)
|
||||||
|
bom_file_valid = True
|
||||||
|
except ValidationError as e:
|
||||||
|
errors = e.error_dict
|
||||||
|
|
||||||
|
for k,v in errors.items():
|
||||||
|
self.form.errors[k] = v
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
# TODO - Validate the form if there isn't actually an error!
|
|
||||||
'form_valid': False
|
'form_valid': False
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create a BomUploadManager object - will perform initial data validation
|
ctx = {}
|
||||||
# (and raise a ValidationError if there is something wrong with the file)
|
|
||||||
try:
|
|
||||||
manager = BomUploadManager(bom_file, self.form['starting_row'].value())
|
|
||||||
except ValidationError as e:
|
|
||||||
errors = e.error_dict
|
|
||||||
|
|
||||||
for k,v in errors.items():
|
if bom_file_valid:
|
||||||
self.form.errors[k] = v
|
# BOM file is valid? Proceed to the next step!
|
||||||
|
form = part_forms.BomUploadSelectFields
|
||||||
|
self.ajax_template_name = 'part/bom_upload/select_fields.html'
|
||||||
|
ctx['bom'] = manager
|
||||||
|
else:
|
||||||
|
form = self.form
|
||||||
|
|
||||||
return self.renderJsonResponse(self.request, self.form, data=data)
|
return self.renderJsonResponse(self.request, form, data=data, context=ctx)
|
||||||
|
|
||||||
|
def handleFieldSelection(self):
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'form_valid': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ajax_template_name = 'part/bom_upload/select_fields.html'
|
||||||
|
|
||||||
|
ctx = {}
|
||||||
|
|
||||||
|
return self.renderJsonResponse(self.request, form=self.get_form(), data=data, context=ctx)
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
""" Perform the various 'POST' requests required.
|
""" Perform the various 'POST' requests required.
|
||||||
@ -703,10 +742,14 @@ class BomUpload(AjaxView, FormMixin):
|
|||||||
self.form = self.get_form()
|
self.form = self.get_form()
|
||||||
|
|
||||||
# Did the user POST a file named bom_file?
|
# Did the user POST a file named bom_file?
|
||||||
bom_file = request.FILES.get('bom_file', None)
|
|
||||||
|
|
||||||
if bom_file:
|
form_step = request.POST.get('form_step', None)
|
||||||
return self.handleBomFileUpload(bom_file)
|
|
||||||
|
if form_step == 'select_file':
|
||||||
|
return self.handleBomFileUpload()
|
||||||
|
elif form_step == 'select_fields':
|
||||||
|
return self.handleFieldSelection()
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'form_valid': False,
|
'form_valid': False,
|
||||||
|
Loading…
Reference in New Issue
Block a user