mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-16 20:15:44 +00:00
Added match parts step, need to process fields data
This commit is contained in:
@ -309,9 +309,9 @@ class UploadFile(forms.Form):
|
||||
|
||||
class MatchField(forms.Form):
|
||||
""" Step 2 """
|
||||
last_name = forms.CharField(max_length=100)
|
||||
pass
|
||||
|
||||
|
||||
class MatchPart(forms.Form):
|
||||
""" Step 3 """
|
||||
age = forms.IntegerField()
|
||||
pass
|
||||
|
@ -0,0 +1,89 @@
|
||||
{% extends "order/order_wizard/po_upload.html" %}
|
||||
{% load inventree_extras %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
|
||||
{% block form %}
|
||||
|
||||
{% if missing_columns and missing_columns|length > 0 %}
|
||||
<div class='alert alert-danger alert-block' role='alert'>
|
||||
{% trans "Missing selections for the following required columns" %}:
|
||||
<br>
|
||||
<ul>
|
||||
{% for col in missing_columns %}
|
||||
<li>{{ col }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% load crispy_forms_tags %}
|
||||
{{ wizard.management_form }}
|
||||
|
||||
{% if wizard.steps.prev %}
|
||||
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button>
|
||||
{% endif %}
|
||||
<button type="submit" class="save btn btn-default">{% trans "Submit Selections" %}</button>
|
||||
|
||||
<table class='table table-striped' style='margin-top: 12px'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{% trans "File Fields" %}</th>
|
||||
{% for col in columns %}
|
||||
<th>
|
||||
<div>
|
||||
<input type='hidden' name='col_name_{{ forloop.counter0 }}' value='{{ col.name }}'/>
|
||||
{{ col.name }}
|
||||
<button class='btn btn-default btn-remove' onClick='removeColFromBomWizard()' id='del_col_{{ forloop.counter0 }}' style='display: inline; float: right;' title='{% trans "Remove column" %}'>
|
||||
<span col_id='{{ forloop.counter0 }}' class='fas fa-trash-alt icon-red'></span>
|
||||
</button>
|
||||
</div>
|
||||
</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>{% trans "Match Fields" %}</td>
|
||||
{% for col in columns %}
|
||||
<td>
|
||||
<select class='select' id='id_col_{{ forloop.counter0 }}' name='col_guess_{{ forloop.counter0 }}'>
|
||||
<option value=''>---------</option>
|
||||
{% for req in headers %}
|
||||
<option value='{{ req }}'{% if req == col.guess %}selected='selected'{% endif %}>{{ req }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% if col.duplicate %}
|
||||
<p class='help-inline'>{% trans "Duplicate column selection" %}</p>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% for row in rows %}
|
||||
{% with forloop.counter as row_index %}
|
||||
<tr>
|
||||
<td>
|
||||
<button class='btn btn-default btn-remove' onClick='removeRowFromBomWizard()' id='del_row_{{ row_index }}' style='display: inline; float: right;' title='{% trans "Remove row" %}'>
|
||||
<span row_id='{{ row_index }}' class='fas fa-trash-alt icon-red'></span>
|
||||
</button>
|
||||
</td>
|
||||
<td>{{ row_index }}</td>
|
||||
{% for item in row.data %}
|
||||
<td>
|
||||
<input type='hidden' name='row_{{ row_index }}_col_{{ forloop.counter0 }}' value='{{ item }}'/>
|
||||
{{ item }}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
112
InvenTree/order/templates/order/order_wizard/match_parts.html
Normal file
112
InvenTree/order/templates/order/order_wizard/match_parts.html
Normal file
@ -0,0 +1,112 @@
|
||||
{% extends "order/order_wizard/po_upload.html" %}
|
||||
{% load inventree_extras %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
|
||||
{% block form %}
|
||||
|
||||
{% if form_errors %}
|
||||
<div class='alert alert-danger alert-block' role='alert'>
|
||||
{% trans "Errors exist in the submitted data" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% load crispy_forms_tags %}
|
||||
{{ wizard.management_form }}
|
||||
|
||||
{% if wizard.steps.prev %}
|
||||
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button>
|
||||
{% endif %}
|
||||
<button type="submit" class="save btn btn-default">{% trans "Submit Selections" %}</button>
|
||||
{% csrf_token %}
|
||||
|
||||
<table class='table table-striped'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th>{% trans "Row" %}</th>
|
||||
<th>{% trans "Select Part" %}</th>
|
||||
{% for col in bom_columns %}
|
||||
<th>
|
||||
<input type='hidden' name='col_name_{{ forloop.counter0 }}' value='{{ col.name }}'/>
|
||||
<input type='hidden' name='col_guess_{{ forloop.counter0 }}' value='{{ col.guess }}'/>
|
||||
{% if col.guess %}
|
||||
{{ col.guess }}
|
||||
{% else %}
|
||||
{{ col.name }}
|
||||
{% endif %}
|
||||
</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in bom_rows %}
|
||||
<tr {% if row.errors %} style='background: #ffeaea;'{% endif %} part-name='{{ row.part_name }}' part-description='{{ row.description }}' part-select='#select_part_{{ row.index }}'>
|
||||
<td>
|
||||
<button class='btn btn-default btn-remove' onClick='removeRowFromBomWizard()' id='del_row_{{ forloop.counter }}' style='display: inline; float: right;' title='{% trans "Remove row" %}'>
|
||||
<span row_id='{{ forloop.counter }}' class='fas fa-trash-alt icon-red'></span>
|
||||
</button>
|
||||
</td>
|
||||
<td></td>
|
||||
<td>{% add row.index 1 %}</td>
|
||||
<td>
|
||||
<button class='btn btn-default btn-create' onClick='newPartFromBomWizard()' id='new_part_row_{{ row.index }}' title='{% trans "Create new part" %}' type='button'>
|
||||
<span row_id='{{ row.index }}' class='fas fa-plus icon-green'/>
|
||||
</button>
|
||||
<select class='select bomselect' id='select_part_{{ row.index }}' name='part_{{ row.index }}'>
|
||||
<option value=''>--- {% trans "Select Part" %} ---</option>
|
||||
{% for part in row.part_options %}
|
||||
<option value='{{ part.id }}' {% if part.id == row.part.id %} selected='selected' {% elif part.id == row.part_match.id %} selected='selected' {% endif %}>
|
||||
{{ part }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% if row.errors.part %}
|
||||
<p class='help-inline'>{{ row.errors.part }}</p>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% for item in row.data %}
|
||||
<td>
|
||||
{% if item.column.guess == 'Part' %}
|
||||
<i>{{ item.cell }}</i>
|
||||
{% if row.errors.part %}
|
||||
<p class='help-inline'>{{ row.errors.part }}</p>
|
||||
{% endif %}
|
||||
{% elif item.column.guess == 'Quantity' %}
|
||||
<input name='quantity_{{ row.index }}' class='numberinput' type='number' min='1' step='any' value='{% decimal row.quantity %}'/>
|
||||
{% if row.errors.quantity %}
|
||||
<p class='help-inline'>{{ row.errors.quantity }}</p>
|
||||
{% endif %}
|
||||
{% elif item.column.guess == 'Reference' %}
|
||||
<input name='reference_{{ row.index }}' value='{{ row.reference }}'/>
|
||||
{% elif item.column.guess == 'Note' %}
|
||||
<input name='notes_{{ row.index }}' value='{{ row.notes }}'/>
|
||||
{% elif item.column.guess == 'Overage' %}
|
||||
<input name='overage_{{ row.index }}' value='{{ row.overage }}'/>
|
||||
{% else %}
|
||||
{{ item.cell }}
|
||||
{% endif %}
|
||||
<input type='hidden' name='row_{{ row.index }}_col_{{ forloop.counter0 }}' value='{{ item.cell }}'/>
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
|
||||
$('.bomselect').select2({
|
||||
dropdownAutoWidth: true,
|
||||
matcher: partialMatcher,
|
||||
});
|
||||
|
||||
{% endblock %}
|
@ -1,5 +1,4 @@
|
||||
{% extends "order/order_base.html" %}
|
||||
|
||||
{% load inventree_extras %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
@ -17,7 +16,11 @@
|
||||
|
||||
<p>{% trans "Step" %} {{ wizard.steps.step1 }} {% trans "of" %} {{ wizard.steps.count }}
|
||||
{% if description %}- {{ description }}{% endif %}</p>
|
||||
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
|
||||
|
||||
{% block form %}
|
||||
|
||||
<form action="" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
{% load crispy_forms_tags %}
|
||||
{{ wizard.management_form }}
|
||||
@ -29,15 +32,16 @@
|
||||
{% else %}
|
||||
{% crispy wizard.form %}
|
||||
{% endif %}
|
||||
</table>
|
||||
{% if wizard.steps.prev %}
|
||||
|
||||
{% if wizard.steps.prev %}
|
||||
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}" class="save btn btn-default">{% trans "Previous Step" %}</button>
|
||||
{% endif %}
|
||||
<button type="submit" class="save btn btn-default">{% trans "Submit" %}</button>
|
||||
<button type="submit" class="save btn btn-default">{% trans "Upload File" %}</button>
|
||||
</form>
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
||||
{% endblock form %}
|
||||
{% endblock details %}
|
||||
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
@ -567,21 +567,30 @@ class SalesOrderShip(AjaxUpdateView):
|
||||
|
||||
|
||||
class PurchaseOrderUpload(MultiStepFormView):
|
||||
''' PurchaseOrder: Upload file and match to parts, using multi-Step form '''
|
||||
''' PurchaseOrder: Upload file, match to fields and parts (using multi-Step form) '''
|
||||
|
||||
form_list = [
|
||||
order_forms.UploadFile,
|
||||
order_forms.MatchField,
|
||||
order_forms.MatchPart,
|
||||
]
|
||||
form_steps_template = [
|
||||
'order/order_wizard/po_upload.html',
|
||||
'order/order_wizard/match_fields.html',
|
||||
'order/order_wizard/match_parts.html',
|
||||
]
|
||||
form_steps_description = [
|
||||
_("Upload File"),
|
||||
_("Select Fields"),
|
||||
_("Select Parts"),
|
||||
_("Match Fields"),
|
||||
_("Match Parts"),
|
||||
]
|
||||
template_name = "order/po_upload.html"
|
||||
media_folder = 'order_uploads/'
|
||||
|
||||
# Used for data table
|
||||
headers = None
|
||||
rows = None
|
||||
columns = None
|
||||
|
||||
def get_context_data(self, form, **kwargs):
|
||||
context = super().get_context_data(form=form, **kwargs)
|
||||
|
||||
@ -589,25 +598,52 @@ class PurchaseOrderUpload(MultiStepFormView):
|
||||
|
||||
context.update({'order': order})
|
||||
|
||||
if self.headers:
|
||||
context.update({'headers': self.headers})
|
||||
# print(f'{self.headers}')
|
||||
if self.columns:
|
||||
context.update({'columns': self.columns})
|
||||
# print(f'{self.columns}')
|
||||
if self.rows:
|
||||
context.update({'rows': self.rows})
|
||||
# print(f'{self.rows}')
|
||||
|
||||
return context
|
||||
|
||||
def get_form_step_data(self, form):
|
||||
# print(f'{self.steps.current=}\n{form.data=}')
|
||||
return form.data
|
||||
def process_step(self, form):
|
||||
print(f'{self.steps.current=} | {form.data}')
|
||||
return self.get_form_step_data(form)
|
||||
|
||||
# def get_all_cleaned_data(self):
|
||||
# cleaned_data = super().get_all_cleaned_data()
|
||||
# print(f'{self.steps.current=} | {cleaned_data}')
|
||||
# return cleaned_data
|
||||
|
||||
# def get_form_step_data(self, form):
|
||||
# print(f'{self.steps.current=} | {form.data}')
|
||||
# return form.data
|
||||
|
||||
def get_form_step_files(self, form):
|
||||
# Check if user completed file upload
|
||||
if self.steps.current == '0':
|
||||
# Extract columns and rows from FileManager
|
||||
self.extractDataFromFile(form.file_manager)
|
||||
# Retrieve FileManager instance from form
|
||||
self.file_manager = form.file_manager
|
||||
# Setup FileManager for order upload
|
||||
setup_valid = self.file_manager.setup()
|
||||
if setup_valid:
|
||||
# Set headers
|
||||
self.headers = self.file_manager.HEADERS
|
||||
# Set columns and rows
|
||||
self.columns = self.file_manager.columns()
|
||||
self.rows = self.file_manager.rows()
|
||||
|
||||
return form.files
|
||||
|
||||
def extractDataFromFile(self, file_manager):
|
||||
""" Read data from the file """
|
||||
|
||||
self.columns = file_manager.columns()
|
||||
self.rows = file_manager.rows()
|
||||
def post(self, request, *args, **kwargs):
|
||||
""" Perform the various 'POST' requests required.
|
||||
"""
|
||||
print('Posting!')
|
||||
return super().post(*args, **kwargs)
|
||||
|
||||
def done(self, form_list, **kwargs):
|
||||
return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']}))
|
||||
|
Reference in New Issue
Block a user