mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-30 04:26:44 +00:00
First pass at 'order parts' fom
- Select parts in modal form window
This commit is contained in:
parent
8e82488f70
commit
bc05146e72
@ -170,7 +170,7 @@ class AjaxView(AjaxMixin, View):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
return JsonResponse('', safe=False)
|
return self.renderJsonResponse(request)
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
|
|
||||||
|
44
InvenTree/order/templates/order/order_select_parts.html
Normal file
44
InvenTree/order/templates/order/order_select_parts.html
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{% extends "modal_form.html" %}
|
||||||
|
|
||||||
|
{% block form %}
|
||||||
|
|
||||||
|
<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_parts'/>
|
||||||
|
|
||||||
|
<table class='table table-condensed table-striped' id='part-table'>
|
||||||
|
<tr>
|
||||||
|
<th>Part</th>
|
||||||
|
<th>Supplier</th>
|
||||||
|
<th>Quantity</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
{% for part in parts %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{% include "hover_image.html" with image=part.image hover=False %}
|
||||||
|
{{ part.full_name }} <small><i>{{ part.description }}</i></small>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select name="part_select_{{ item.part.id }}">
|
||||||
|
<option value=''>---------</option>
|
||||||
|
{% for supplier in part.supplier_parts.all %}
|
||||||
|
<option value="{{ supplier.id }}"{% if part.get_default_supplier and part.get_default_supplier.id == supplier.id %} selected="selected"{% endif %}>{{ supplier }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input class='numberinput' min='0' value='{{ part.quantity_to_order }}' name='part_quantity_{{ part.id }}'/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class='btn btn-default btn-remove' id='del_item_{{ part.id }}' title='Remove part' type='button'>
|
||||||
|
<span row='part_row_{{ item.part.id }}' onclick='removeOrderRow()' class='glyphicon glyphicon-small glyphicon-remove'></span>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -26,6 +26,8 @@ purchase_order_urls = [
|
|||||||
|
|
||||||
url(r'^new/', views.PurchaseOrderCreate.as_view(), name='purchase-order-create'),
|
url(r'^new/', views.PurchaseOrderCreate.as_view(), name='purchase-order-create'),
|
||||||
|
|
||||||
|
url(r'^order-parts/', views.OrderParts.as_view(), name='order-parts'),
|
||||||
|
|
||||||
# Display detail view for a single purchase order
|
# Display detail view for a single purchase order
|
||||||
url(r'^(?P<pk>\d+)/', include(purchase_order_detail_urls)),
|
url(r'^(?P<pk>\d+)/', include(purchase_order_detail_urls)),
|
||||||
|
|
||||||
|
@ -7,14 +7,17 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.views.generic import DetailView, ListView
|
from django.views.generic import DetailView, ListView
|
||||||
|
from django.views.generic.edit import FormMixin
|
||||||
from django.forms import HiddenInput
|
from django.forms import HiddenInput
|
||||||
|
|
||||||
from .models import PurchaseOrder, PurchaseOrderLineItem
|
from .models import PurchaseOrder, PurchaseOrderLineItem
|
||||||
from company.models import Company, SupplierPart
|
from company.models import Company, SupplierPart
|
||||||
|
from stock.models import StockItem
|
||||||
|
from part.models import Part
|
||||||
|
|
||||||
from . import forms as order_forms
|
from . import forms as order_forms
|
||||||
|
|
||||||
from InvenTree.views import AjaxCreateView, AjaxUpdateView
|
from InvenTree.views import AjaxView, AjaxCreateView, AjaxUpdateView
|
||||||
from InvenTree.helpers import str2bool
|
from InvenTree.helpers import str2bool
|
||||||
|
|
||||||
from InvenTree.status_codes import OrderStatus
|
from InvenTree.status_codes import OrderStatus
|
||||||
@ -135,6 +138,96 @@ class PurchaseOrderIssue(AjaxUpdateView):
|
|||||||
return self.renderJsonResponse(request, form, data)
|
return self.renderJsonResponse(request, form, data)
|
||||||
|
|
||||||
|
|
||||||
|
class OrderParts(AjaxView):
|
||||||
|
""" View for adding various SupplierPart items to a Purchase Order.
|
||||||
|
|
||||||
|
SupplierParts can be selected from a variety of 'sources':
|
||||||
|
|
||||||
|
- ?supplier_parts[]= -> Direct list of SupplierPart objects
|
||||||
|
- ?parts[]= -> List of base Part objects (user must then select supplier parts)
|
||||||
|
- ?stock[]= -> List of StockItem objects (user must select supplier parts)
|
||||||
|
- ?build= -> A Build object (user must select parts, then supplier parts)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
ajax_form_title = "Order Parts"
|
||||||
|
ajax_template_name = 'order/order_select_parts.html'
|
||||||
|
|
||||||
|
# List of Parts we wish to order
|
||||||
|
parts = []
|
||||||
|
|
||||||
|
def get_context_data(self):
|
||||||
|
|
||||||
|
ctx = {}
|
||||||
|
|
||||||
|
print("Getting context data")
|
||||||
|
|
||||||
|
ctx['parts'] = self.get_parts()
|
||||||
|
|
||||||
|
return ctx
|
||||||
|
|
||||||
|
def get_parts(self):
|
||||||
|
""" Determine which parts the user wishes to order.
|
||||||
|
This is performed on the initial GET request.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.parts = []
|
||||||
|
|
||||||
|
part_ids = set()
|
||||||
|
|
||||||
|
# User has passed a list of stock items
|
||||||
|
if 'stock[]' in self.request.GET:
|
||||||
|
|
||||||
|
stock_id_list = self.request.GET.getlist('stock[]')
|
||||||
|
|
||||||
|
print("Looking up parts from stock items:")
|
||||||
|
print(stock_id_list)
|
||||||
|
|
||||||
|
""" Get a list of all the parts associated with the stock items.
|
||||||
|
- Base part must be purchaseable.
|
||||||
|
- Return a set of corresponding Part IDs
|
||||||
|
"""
|
||||||
|
stock_items = StockItem.objects.filter(
|
||||||
|
part__purchaseable=True,
|
||||||
|
id__in=stock_id_list)
|
||||||
|
|
||||||
|
for item in stock_items:
|
||||||
|
part_ids.add(item.part.id)
|
||||||
|
|
||||||
|
print("Parts:", part_ids)
|
||||||
|
|
||||||
|
|
||||||
|
# Create the list of parts
|
||||||
|
for id in part_ids:
|
||||||
|
try:
|
||||||
|
part = Part.objects.get(id=id)
|
||||||
|
except Part.DoesNotExist:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.parts.append(part)
|
||||||
|
|
||||||
|
return self.parts
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
|
||||||
|
self.request = request
|
||||||
|
|
||||||
|
print("GET HERE")
|
||||||
|
|
||||||
|
print(request.GET)
|
||||||
|
|
||||||
|
self.get_parts()
|
||||||
|
|
||||||
|
return self.renderJsonResponse(request)
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
|
||||||
|
self.request = request
|
||||||
|
print("POST here")
|
||||||
|
|
||||||
|
return self.renderJsonResponse(request)
|
||||||
|
|
||||||
|
|
||||||
class POLineItemCreate(AjaxCreateView):
|
class POLineItemCreate(AjaxCreateView):
|
||||||
""" AJAX view for creating a new PurchaseOrderLineItem object
|
""" AJAX view for creating a new PurchaseOrderLineItem object
|
||||||
"""
|
"""
|
||||||
|
@ -339,7 +339,7 @@ class Part(models.Model):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if self.default_supplier:
|
if self.default_supplier:
|
||||||
return self.default_suppliers
|
return self.default_supplier
|
||||||
|
|
||||||
if self.supplier_count == 1:
|
if self.supplier_count == 1:
|
||||||
return self.supplier_parts.first()
|
return self.supplier_parts.first()
|
||||||
@ -410,6 +410,13 @@ class Part(models.Model):
|
|||||||
|
|
||||||
return max(total, 0)
|
return max(total, 0)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def quantity_to_order(self):
|
||||||
|
""" Return the quantity needing to be ordered for this part. """
|
||||||
|
|
||||||
|
required = -1 * self.net_stock
|
||||||
|
return max(required, 0)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def net_stock(self):
|
def net_stock(self):
|
||||||
""" Return the 'net' stock. It takes into account:
|
""" Return the 'net' stock. It takes into account:
|
||||||
|
@ -237,6 +237,22 @@ function loadStockTable(table, options) {
|
|||||||
$("#multi-item-move").click(function() {
|
$("#multi-item-move").click(function() {
|
||||||
stockAdjustment('move');
|
stockAdjustment('move');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#multi-item-order").click(function() {
|
||||||
|
var selections = $("#stock-table").bootstrapTable("getSelections");
|
||||||
|
|
||||||
|
var stock = [];
|
||||||
|
|
||||||
|
selections.forEach(function(item) {
|
||||||
|
stock.push(item.pk);
|
||||||
|
});
|
||||||
|
|
||||||
|
launchModalForm("/order/purchase-order/order-parts/", {
|
||||||
|
data: {
|
||||||
|
stock: stock,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
{% block pre_form_content %}
|
{% block pre_form_content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block form %}
|
||||||
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data">
|
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% load crispy_forms_tags %}
|
{% load crispy_forms_tags %}
|
||||||
@ -32,5 +34,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block post_form_content %}
|
{% block post_form_content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -9,7 +9,8 @@
|
|||||||
<li><a href="#" id='multi-item-add' title='Add to selected stock items'>Add stock</a></li>
|
<li><a href="#" id='multi-item-add' title='Add to selected stock items'>Add stock</a></li>
|
||||||
<li><a href="#" id='multi-item-remove' title='Remove from selected stock items'>Remove stock</a></li>
|
<li><a href="#" id='multi-item-remove' title='Remove from selected stock items'>Remove stock</a></li>
|
||||||
<li><a href="#" id='multi-item-stocktake' title='Stocktake selected stock items'>Count stock</a></li>
|
<li><a href="#" id='multi-item-stocktake' title='Stocktake selected stock items'>Count stock</a></li>
|
||||||
<li><a href='#' id='multi-item-move' title='Move selected stock items'>Move stock</a></li>
|
<li><a href='#' id='multi-item-move' title='Move selected stock items'>Move stock</a></li>
|
||||||
|
<li><a href='#' id='multi-item-order' title='Order selected items'>Order stock</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user