mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Collate parts by supplier and present a purchase-order form
This commit is contained in:
parent
2fffd874a3
commit
7049ab1d8c
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
{% block form %}
|
{% block form %}
|
||||||
|
|
||||||
|
<h4>
|
||||||
|
Step 1 of 2 - Select Parts
|
||||||
|
</h4>
|
||||||
|
|
||||||
{% if parts|length > 0 %}
|
{% if parts|length > 0 %}
|
||||||
<div class='alert alert-info alert-block' role='alert'>
|
<div class='alert alert-info alert-block' role='alert'>
|
||||||
Select suppliers for {{ parts|length }} parts.
|
Select suppliers for {{ parts|length }} parts.
|
||||||
@ -18,7 +22,7 @@
|
|||||||
|
|
||||||
<input type='hidden' name='form_step' value='select_parts'/>
|
<input type='hidden' name='form_step' value='select_parts'/>
|
||||||
|
|
||||||
<table class='table table-condensed table-striped' id='part-table'>
|
<table class='table table-condensed table-striped' id='order-wizard-part-table'>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Part</th>
|
<th>Part</th>
|
||||||
<th>Supplier</th>
|
<th>Supplier</th>
|
||||||
@ -61,5 +65,5 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
49
InvenTree/order/templates/order/order_wizard/select_pos.html
Normal file
49
InvenTree/order/templates/order/order_wizard/select_pos.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{% extends "modal_form.html" %}
|
||||||
|
|
||||||
|
{% block form %}
|
||||||
|
|
||||||
|
<h4>
|
||||||
|
Step 2 of 2 - Select Purchase Orders
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div class='alert alert-info alert-block' role='alert'>
|
||||||
|
Select existing purchase orders, or create new orders.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method='post' action='' class='js-modal-form' enctype='multipart/form-data'>
|
||||||
|
{% csrf_token %}
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
|
<input type='hidden' name='form_step' value='select_purchase_orders'/>
|
||||||
|
|
||||||
|
<table class='table table-condensed table-striped' id='order-wizard-po-table'>
|
||||||
|
<tr>
|
||||||
|
<th>Supplier</th>
|
||||||
|
<th>Items</th>
|
||||||
|
<th>Purchase Order</th>
|
||||||
|
</tr>
|
||||||
|
{% for supplier in suppliers %}
|
||||||
|
<tr id='suppier_row_{{ supplier.id }}'>
|
||||||
|
<td>
|
||||||
|
{% include 'hover_image.html' with image=supplier.image hover=False %}
|
||||||
|
{{ supplier.name }}
|
||||||
|
</td>
|
||||||
|
<td>{{ supplier.order_items|length }}</td>
|
||||||
|
<td>
|
||||||
|
<div class='control-group'>
|
||||||
|
<div class='controls'>
|
||||||
|
<select
|
||||||
|
class='select'
|
||||||
|
id='id_purchase_order_{{ supplier.id }}'
|
||||||
|
name='purchase_order_{{ supplier.id }}'>
|
||||||
|
<option value=''>---------</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
@ -155,15 +155,41 @@ class OrderParts(AjaxView):
|
|||||||
|
|
||||||
# List of Parts we wish to order
|
# List of Parts we wish to order
|
||||||
parts = []
|
parts = []
|
||||||
|
suppliers = []
|
||||||
|
|
||||||
def get_context_data(self):
|
def get_context_data(self):
|
||||||
|
|
||||||
ctx = {}
|
ctx = {}
|
||||||
|
|
||||||
ctx['parts'] = sorted(self.parts, key=lambda part: int(part.order_quantity), reverse=True)
|
ctx['parts'] = sorted(self.parts, key=lambda part: int(part.order_quantity), reverse=True)
|
||||||
|
ctx['suppliers'] = self.suppliers
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
def get_suppliers(self):
|
||||||
|
""" Calculates a list of suppliers which the user will need to create POs for.
|
||||||
|
This is calculated AFTER the user finishes selecting the parts to order.
|
||||||
|
Crucially, get_parts() must be called before get_suppliers()
|
||||||
|
"""
|
||||||
|
|
||||||
|
suppliers = {}
|
||||||
|
|
||||||
|
for part in self.parts:
|
||||||
|
supplier_part_id = part.order_supplier
|
||||||
|
|
||||||
|
try:
|
||||||
|
supplier = SupplierPart.objects.get(pk=supplier_part_id).supplier
|
||||||
|
except SupplierPart.DoesNotExist:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not supplier.name in suppliers:
|
||||||
|
supplier.order_items = []
|
||||||
|
suppliers[supplier.name] = supplier
|
||||||
|
|
||||||
|
suppliers[supplier.name].order_items.append(part)
|
||||||
|
|
||||||
|
self.suppliers = [suppliers[key] for key in suppliers.keys()]
|
||||||
|
|
||||||
def get_parts(self):
|
def get_parts(self):
|
||||||
""" Determine which parts the user wishes to order.
|
""" Determine which parts the user wishes to order.
|
||||||
This is performed on the initial GET request.
|
This is performed on the initial GET request.
|
||||||
@ -279,6 +305,9 @@ class OrderParts(AjaxView):
|
|||||||
|
|
||||||
self.parts = []
|
self.parts = []
|
||||||
|
|
||||||
|
# Any errors for the part selection form?
|
||||||
|
errors = False
|
||||||
|
|
||||||
for item in self.request.POST:
|
for item in self.request.POST:
|
||||||
|
|
||||||
if item.startswith('supplier-'):
|
if item.startswith('supplier-'):
|
||||||
@ -316,12 +345,18 @@ class OrderParts(AjaxView):
|
|||||||
|
|
||||||
self.parts.append(part)
|
self.parts.append(part)
|
||||||
|
|
||||||
print(part.name, part.order_supplier, part.order_quantity)
|
if supplier_part is None:
|
||||||
|
errors = True
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
'form_valid': False,
|
'form_valid': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# No errors? Proceed to PO selection form
|
||||||
|
if errors == False:
|
||||||
|
self.ajax_template_name = 'order/order_wizard/select_pos.html'
|
||||||
|
self.get_suppliers()
|
||||||
|
|
||||||
return self.renderJsonResponse(self.request, data=data)
|
return self.renderJsonResponse(self.request, data=data)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user