2019-06-04 13:59:15 +00:00
|
|
|
"""
|
|
|
|
Django views for interacting with Order app
|
|
|
|
"""
|
2019-06-04 12:19:04 +00:00
|
|
|
|
2019-06-04 13:59:15 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from __future__ import unicode_literals
|
|
|
|
|
2019-06-06 11:55:02 +00:00
|
|
|
from django.utils.translation import ugettext as _
|
2019-06-04 13:59:15 +00:00
|
|
|
from django.views.generic import DetailView, ListView
|
2019-06-05 11:19:41 +00:00
|
|
|
from django.forms import HiddenInput
|
2019-06-04 13:59:15 +00:00
|
|
|
|
2019-06-13 11:17:06 +00:00
|
|
|
import logging
|
|
|
|
|
2019-06-05 10:59:30 +00:00
|
|
|
from .models import PurchaseOrder, PurchaseOrderLineItem
|
2019-06-11 14:21:18 +00:00
|
|
|
from build.models import Build
|
2019-06-10 12:56:34 +00:00
|
|
|
from company.models import Company, SupplierPart
|
2019-06-11 13:37:32 +00:00
|
|
|
from stock.models import StockItem
|
|
|
|
from part.models import Part
|
2019-06-05 12:24:18 +00:00
|
|
|
|
|
|
|
from . import forms as order_forms
|
2019-06-05 10:59:30 +00:00
|
|
|
|
2019-06-11 13:37:32 +00:00
|
|
|
from InvenTree.views import AjaxView, AjaxCreateView, AjaxUpdateView
|
2019-06-10 12:14:23 +00:00
|
|
|
from InvenTree.helpers import str2bool
|
2019-06-04 13:59:15 +00:00
|
|
|
|
|
|
|
from InvenTree.status_codes import OrderStatus
|
|
|
|
|
2019-06-13 11:17:06 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2019-06-04 13:59:15 +00:00
|
|
|
|
|
|
|
class PurchaseOrderIndex(ListView):
|
2019-06-04 14:17:25 +00:00
|
|
|
""" List view for all purchase orders """
|
2019-06-04 13:59:15 +00:00
|
|
|
|
|
|
|
model = PurchaseOrder
|
|
|
|
template_name = 'order/purchase_orders.html'
|
|
|
|
context_object_name = 'orders'
|
|
|
|
|
2019-06-06 11:39:04 +00:00
|
|
|
def get_queryset(self):
|
|
|
|
""" Retrieve the list of purchase orders,
|
|
|
|
ensure that the most recent ones are returned first. """
|
|
|
|
|
|
|
|
queryset = PurchaseOrder.objects.all().order_by('-creation_date')
|
|
|
|
|
|
|
|
return queryset
|
|
|
|
|
2019-06-05 10:59:30 +00:00
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
ctx = super().get_context_data(**kwargs)
|
2019-06-04 13:59:15 +00:00
|
|
|
|
|
|
|
ctx['OrderStatus'] = OrderStatus
|
|
|
|
|
|
|
|
return ctx
|
2019-06-04 14:17:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
class PurchaseOrderDetail(DetailView):
|
|
|
|
""" Detail view for a PurchaseOrder object """
|
|
|
|
|
|
|
|
context_object_name = 'order'
|
|
|
|
queryset = PurchaseOrder.objects.all().prefetch_related('lines')
|
|
|
|
template_name = 'order/purchase_order_detail.html'
|
2019-06-05 10:59:30 +00:00
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
ctx = super().get_context_data(**kwargs)
|
|
|
|
|
|
|
|
ctx['OrderStatus'] = OrderStatus
|
|
|
|
|
|
|
|
return ctx
|
|
|
|
|
|
|
|
|
2019-06-06 11:39:04 +00:00
|
|
|
class PurchaseOrderCreate(AjaxCreateView):
|
|
|
|
""" View for creating a new PurchaseOrder object using a modal form """
|
|
|
|
|
|
|
|
model = PurchaseOrder
|
|
|
|
ajax_form_title = "Create Purchase Order"
|
|
|
|
form_class = order_forms.EditPurchaseOrderForm
|
|
|
|
|
|
|
|
def get_initial(self):
|
|
|
|
initials = super().get_initial().copy()
|
|
|
|
|
|
|
|
initials['status'] = OrderStatus.PENDING
|
|
|
|
|
2019-06-10 12:56:34 +00:00
|
|
|
supplier_id = self.request.GET.get('supplier', None)
|
|
|
|
|
|
|
|
if supplier_id:
|
|
|
|
try:
|
|
|
|
supplier = Company.objects.get(id=supplier_id)
|
|
|
|
initials['supplier'] = supplier
|
|
|
|
except Company.DoesNotExist:
|
|
|
|
pass
|
|
|
|
|
2019-06-10 13:08:08 +00:00
|
|
|
return initials
|
2019-06-06 11:39:04 +00:00
|
|
|
|
|
|
|
|
2019-06-05 12:24:18 +00:00
|
|
|
class PurchaseOrderEdit(AjaxUpdateView):
|
|
|
|
""" View for editing a PurchaseOrder using a modal form """
|
|
|
|
|
|
|
|
model = PurchaseOrder
|
|
|
|
ajax_form_title = 'Edit Purchase Order'
|
|
|
|
form_class = order_forms.EditPurchaseOrderForm
|
|
|
|
|
|
|
|
def get_form(self):
|
|
|
|
|
|
|
|
form = super(AjaxUpdateView, self).get_form()
|
|
|
|
|
|
|
|
order = self.get_object()
|
|
|
|
|
2019-06-06 11:39:04 +00:00
|
|
|
# Prevent user from editing supplier if there are already lines in the order
|
2019-06-10 12:17:19 +00:00
|
|
|
if order.lines.count() > 0 or not order.status == OrderStatus.PENDING:
|
2019-06-05 12:24:18 +00:00
|
|
|
form.fields['supplier'].widget = HiddenInput()
|
|
|
|
|
|
|
|
return form
|
|
|
|
|
|
|
|
|
|
|
|
class PurchaseOrderIssue(AjaxUpdateView):
|
|
|
|
""" View for changing a purchase order from 'PENDING' to 'ISSUED' """
|
|
|
|
|
|
|
|
model = PurchaseOrder
|
|
|
|
ajax_form_title = 'Issue Order'
|
|
|
|
ajax_template_name = "order/order_issue.html"
|
|
|
|
form_class = order_forms.IssuePurchaseOrderForm
|
|
|
|
|
2019-06-10 12:14:23 +00:00
|
|
|
def post(self, request, *args, **kwargs):
|
|
|
|
""" Mark the purchase order as 'PLACED' """
|
|
|
|
|
|
|
|
order = self.get_object()
|
|
|
|
form = self.get_form()
|
|
|
|
|
|
|
|
confirm = str2bool(request.POST.get('confirm', False))
|
|
|
|
|
|
|
|
valid = False
|
|
|
|
|
|
|
|
if not confirm:
|
|
|
|
form.errors['confirm'] = [_('Confirm order placement')]
|
|
|
|
else:
|
|
|
|
valid = True
|
|
|
|
|
|
|
|
data = {
|
|
|
|
'form_valid': valid,
|
|
|
|
}
|
|
|
|
|
|
|
|
if valid:
|
2019-06-10 12:17:19 +00:00
|
|
|
order.place_order()
|
2019-06-10 12:14:23 +00:00
|
|
|
|
|
|
|
return self.renderJsonResponse(request, form, data)
|
|
|
|
|
2019-06-05 12:24:18 +00:00
|
|
|
|
2019-06-11 13:37:32 +00:00
|
|
|
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"
|
2019-06-13 09:10:31 +00:00
|
|
|
ajax_template_name = 'order/order_wizard/select_parts.html'
|
2019-06-11 13:37:32 +00:00
|
|
|
|
|
|
|
# List of Parts we wish to order
|
|
|
|
parts = []
|
2019-06-13 09:30:18 +00:00
|
|
|
suppliers = []
|
2019-06-11 13:37:32 +00:00
|
|
|
|
|
|
|
def get_context_data(self):
|
|
|
|
|
|
|
|
ctx = {}
|
|
|
|
|
2019-06-13 09:12:34 +00:00
|
|
|
ctx['parts'] = sorted(self.parts, key=lambda part: int(part.order_quantity), reverse=True)
|
2019-06-13 09:30:18 +00:00
|
|
|
ctx['suppliers'] = self.suppliers
|
2019-06-11 13:37:32 +00:00
|
|
|
|
|
|
|
return ctx
|
|
|
|
|
2019-06-13 09:30:18 +00:00
|
|
|
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 = {}
|
|
|
|
|
2019-06-13 10:17:36 +00:00
|
|
|
for supplier in self.suppliers:
|
|
|
|
supplier.order_items = []
|
|
|
|
suppliers[supplier.name] = supplier
|
|
|
|
|
2019-06-13 09:30:18 +00:00
|
|
|
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 = []
|
2019-06-13 10:17:36 +00:00
|
|
|
supplier.selected_purchase_order = None
|
2019-06-13 09:30:18 +00:00
|
|
|
suppliers[supplier.name] = supplier
|
|
|
|
|
|
|
|
suppliers[supplier.name].order_items.append(part)
|
|
|
|
|
|
|
|
self.suppliers = [suppliers[key] for key in suppliers.keys()]
|
|
|
|
|
2019-06-11 13:37:32 +00:00
|
|
|
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[]')
|
|
|
|
|
|
|
|
""" Get a list of all the parts associated with the stock items.
|
|
|
|
- Base part must be purchaseable.
|
2019-06-11 14:39:33 +00:00
|
|
|
- Return a set of corresponding Part IDs
|
2019-06-11 13:37:32 +00:00
|
|
|
"""
|
|
|
|
stock_items = StockItem.objects.filter(
|
|
|
|
part__purchaseable=True,
|
|
|
|
id__in=stock_id_list)
|
|
|
|
|
|
|
|
for item in stock_items:
|
|
|
|
part_ids.add(item.part.id)
|
|
|
|
|
2019-06-11 14:04:20 +00:00
|
|
|
# User has passed a single Part ID
|
|
|
|
elif 'part' in self.request.GET:
|
|
|
|
try:
|
|
|
|
part_id = self.request.GET.get('part')
|
|
|
|
part = Part.objects.get(id=part_id)
|
|
|
|
|
|
|
|
part_ids.add(part.id)
|
|
|
|
|
|
|
|
except Part.DoesNotExist:
|
|
|
|
pass
|
|
|
|
|
2019-06-11 13:55:20 +00:00
|
|
|
# User has passed a list of part ID values
|
2019-06-11 14:04:20 +00:00
|
|
|
elif 'parts[]' in self.request.GET:
|
2019-06-11 13:55:20 +00:00
|
|
|
part_id_list = self.request.GET.getlist('parts[]')
|
|
|
|
|
|
|
|
parts = Part.objects.filter(
|
|
|
|
purchaseable=True,
|
|
|
|
id__in=part_id_list)
|
|
|
|
|
|
|
|
for part in parts:
|
|
|
|
part_ids.add(part.id)
|
|
|
|
|
2019-06-11 14:21:18 +00:00
|
|
|
# User has provided a Build ID
|
|
|
|
elif 'build' in self.request.GET:
|
|
|
|
build_id = self.request.GET.get('build')
|
|
|
|
try:
|
|
|
|
build = Build.objects.get(id=build_id)
|
|
|
|
|
|
|
|
parts = build.part.required_parts()
|
|
|
|
|
|
|
|
for part in parts:
|
|
|
|
part_ids.add(part.id)
|
|
|
|
except Build.DoesNotExist:
|
|
|
|
pass
|
|
|
|
|
2019-06-11 13:37:32 +00:00
|
|
|
# Create the list of parts
|
|
|
|
for id in part_ids:
|
|
|
|
try:
|
|
|
|
part = Part.objects.get(id=id)
|
2019-06-13 09:10:31 +00:00
|
|
|
# Pre-fill the 'order quantity' value
|
|
|
|
part.order_quantity = part.quantity_to_order
|
|
|
|
|
|
|
|
default_supplier = part.get_default_supplier()
|
|
|
|
|
|
|
|
if default_supplier:
|
|
|
|
part.order_supplier = default_supplier.id
|
|
|
|
else:
|
|
|
|
part.order_supplier = None
|
2019-06-11 13:37:32 +00:00
|
|
|
except Part.DoesNotExist:
|
|
|
|
continue
|
|
|
|
|
|
|
|
self.parts.append(part)
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
|
|
|
|
self.request = request
|
|
|
|
|
|
|
|
self.get_parts()
|
|
|
|
|
|
|
|
return self.renderJsonResponse(request)
|
|
|
|
|
|
|
|
def post(self, request, *args, **kwargs):
|
2019-06-13 09:10:31 +00:00
|
|
|
""" Handle the POST action for part selection.
|
|
|
|
|
|
|
|
- Validates each part / quantity / supplier / etc
|
|
|
|
|
|
|
|
Part selection form contains the following fields for each part:
|
|
|
|
|
|
|
|
- supplier-<pk> : The ID of the selected supplier
|
|
|
|
- quantity-<pk> : The quantity to add to the order
|
|
|
|
"""
|
|
|
|
|
2019-06-13 10:17:36 +00:00
|
|
|
self.request = request
|
|
|
|
|
2019-06-13 09:10:31 +00:00
|
|
|
self.parts = []
|
2019-06-13 10:17:36 +00:00
|
|
|
self.suppliers = []
|
2019-06-13 09:10:31 +00:00
|
|
|
|
2019-06-13 09:30:18 +00:00
|
|
|
# Any errors for the part selection form?
|
2019-06-13 10:17:36 +00:00
|
|
|
part_errors = False
|
|
|
|
supplier_errors = False
|
2019-06-13 09:30:18 +00:00
|
|
|
|
2019-06-13 10:17:36 +00:00
|
|
|
# Extract part information from the form
|
2019-06-13 09:10:31 +00:00
|
|
|
for item in self.request.POST:
|
|
|
|
|
2019-06-13 10:17:36 +00:00
|
|
|
if item.startswith('part-supplier-'):
|
2019-06-13 09:10:31 +00:00
|
|
|
|
2019-06-13 10:17:36 +00:00
|
|
|
pk = item.replace('part-supplier-', '')
|
2019-06-13 09:10:31 +00:00
|
|
|
|
|
|
|
# Check that the part actually exists
|
|
|
|
try:
|
|
|
|
part = Part.objects.get(id=pk)
|
|
|
|
except (Part.DoesNotExist, ValueError):
|
|
|
|
continue
|
|
|
|
|
|
|
|
supplier_part_id = self.request.POST[item]
|
|
|
|
|
2019-06-13 10:17:36 +00:00
|
|
|
quantity = self.request.POST.get('part-quantity-' + str(pk), 0)
|
2019-06-13 09:10:31 +00:00
|
|
|
|
|
|
|
# Ensure a valid supplier has been passed
|
|
|
|
try:
|
|
|
|
supplier_part = SupplierPart.objects.get(id=supplier_part_id)
|
|
|
|
except (SupplierPart.DoesNotExist, ValueError):
|
|
|
|
supplier_part = None
|
|
|
|
|
|
|
|
# Ensure a valid quantity is passed
|
|
|
|
try:
|
2019-06-13 10:17:36 +00:00
|
|
|
quantity = int(quantity)
|
|
|
|
|
|
|
|
# Eliminate lines where the quantity is zero
|
|
|
|
if quantity == 0:
|
2019-06-13 09:10:31 +00:00
|
|
|
continue
|
|
|
|
except ValueError:
|
|
|
|
quantity = part.quantity_to_order
|
|
|
|
|
|
|
|
part.order_supplier = supplier_part.id if supplier_part else None
|
|
|
|
part.order_quantity = quantity
|
|
|
|
|
|
|
|
self.parts.append(part)
|
|
|
|
|
2019-06-13 09:30:18 +00:00
|
|
|
if supplier_part is None:
|
2019-06-13 10:17:36 +00:00
|
|
|
part_errors = True
|
|
|
|
|
|
|
|
elif quantity < 0:
|
|
|
|
part_errors = True
|
|
|
|
|
|
|
|
elif item.startswith('purchase-order-'):
|
|
|
|
# Which purchase order is selected for a given supplier?
|
|
|
|
pk = item.replace('purchase-order-', '')
|
|
|
|
|
|
|
|
# Check that the Supplier actually exists
|
|
|
|
try:
|
|
|
|
supplier = Company.objects.get(id=pk)
|
|
|
|
except Company.DoesNotExist:
|
|
|
|
# Skip this item
|
|
|
|
continue
|
|
|
|
|
|
|
|
purchase_order_id = self.request.POST[item]
|
|
|
|
|
|
|
|
# Ensure that a valid purchase order has been passed
|
|
|
|
try:
|
|
|
|
purchase_order = PurchaseOrder.objects.get(pk=purchase_order_id)
|
|
|
|
except (PurchaseOrder.DoesNotExist, ValueError):
|
|
|
|
purchase_order = None
|
|
|
|
|
|
|
|
supplier.selected_purchase_order = purchase_order.id if purchase_order else None
|
|
|
|
|
|
|
|
self.suppliers.append(supplier)
|
|
|
|
|
|
|
|
if supplier.selected_purchase_order is None:
|
|
|
|
supplier_errors = True
|
|
|
|
|
|
|
|
form_step = request.POST.get('form_step')
|
|
|
|
|
|
|
|
# Map parts to suppliers
|
|
|
|
self.get_suppliers()
|
|
|
|
|
2019-06-13 11:17:06 +00:00
|
|
|
valid = False
|
|
|
|
|
2019-06-13 10:17:36 +00:00
|
|
|
if form_step == 'select_parts':
|
|
|
|
# No errors? Proceed to PO selection form
|
|
|
|
if part_errors == False:
|
|
|
|
self.ajax_template_name = 'order/order_wizard/select_pos.html'
|
|
|
|
|
|
|
|
else:
|
|
|
|
self.ajax_template_name = 'order/order_wizard/select_parts.html'
|
|
|
|
|
|
|
|
elif form_step == 'select_purchase_orders':
|
|
|
|
|
|
|
|
self.ajax_template_name = 'order/order_wizard/select_pos.html'
|
2019-06-13 09:10:31 +00:00
|
|
|
|
2019-06-13 11:17:06 +00:00
|
|
|
valid = part_errors is False and supplier_errors is False
|
|
|
|
|
|
|
|
# Form wizard is complete! Add items to purchase orders
|
|
|
|
if valid:
|
|
|
|
self.order_items()
|
|
|
|
|
2019-06-13 09:10:31 +00:00
|
|
|
data = {
|
2019-06-13 11:17:06 +00:00
|
|
|
'form_valid': valid,
|
|
|
|
'success': 'Ordered {n} parts'.format(n=len(self.parts))
|
2019-06-13 09:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return self.renderJsonResponse(self.request, data=data)
|
|
|
|
|
2019-06-13 11:17:06 +00:00
|
|
|
def order_items(self):
|
|
|
|
""" Add the selected items to the purchase orders. """
|
|
|
|
|
|
|
|
for supplier in self.suppliers:
|
|
|
|
|
|
|
|
# Check that the purchase order does actually exist
|
|
|
|
try:
|
|
|
|
order = PurchaseOrder.objects.get(pk=supplier.selected_purchase_order)
|
|
|
|
except PurchaseOrder.DoesNotExist:
|
|
|
|
logger.critical('Could not add items to purchase order {po} - Order does not exist'.format(po=supplier.selected_purchase_order))
|
|
|
|
continue
|
|
|
|
|
|
|
|
for item in supplier.order_items:
|
|
|
|
|
|
|
|
# Ensure that the quantity is valid
|
|
|
|
try:
|
|
|
|
quantity = int(item.order_quantity)
|
|
|
|
if quantity <= 0:
|
|
|
|
continue
|
|
|
|
except ValueError:
|
|
|
|
logger.warning("Did not add part to purchase order - incorrect quantity")
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Check that the supplier part does actually exist
|
|
|
|
try:
|
|
|
|
supplier_part = SupplierPart.objects.get(pk=item.order_supplier)
|
|
|
|
except SupplierPart.DoesNotExist:
|
|
|
|
logger.critical("Could not add part '{part}' to purchase order - selected supplier part '{sp}' does not exist.".format(
|
|
|
|
part=item,
|
|
|
|
sp=item.order_supplier))
|
|
|
|
continue
|
|
|
|
|
|
|
|
order.add_line_item(supplier_part, quantity)
|
|
|
|
|
2019-06-11 13:37:32 +00:00
|
|
|
|
2019-06-05 10:59:30 +00:00
|
|
|
class POLineItemCreate(AjaxCreateView):
|
|
|
|
""" AJAX view for creating a new PurchaseOrderLineItem object
|
|
|
|
"""
|
|
|
|
|
|
|
|
model = PurchaseOrderLineItem
|
|
|
|
context_object_name = 'line'
|
2019-06-05 12:24:18 +00:00
|
|
|
form_class = order_forms.EditPurchaseOrderLineItemForm
|
2019-06-05 11:19:41 +00:00
|
|
|
ajax_form_title = 'Add Line Item'
|
2019-06-05 10:59:30 +00:00
|
|
|
|
2019-06-06 11:55:02 +00:00
|
|
|
def post(self, request, *arg, **kwargs):
|
|
|
|
|
|
|
|
self.request = request
|
|
|
|
|
|
|
|
form = self.get_form()
|
|
|
|
|
|
|
|
valid = form.is_valid()
|
|
|
|
|
|
|
|
part_id = form['part'].value()
|
|
|
|
|
|
|
|
try:
|
|
|
|
SupplierPart.objects.get(id=part_id)
|
|
|
|
except (SupplierPart.DoesNotExist, ValueError):
|
|
|
|
valid = False
|
|
|
|
form.errors['part'] = [_('This field is required')]
|
|
|
|
|
|
|
|
data = {
|
|
|
|
'form_valid': valid,
|
|
|
|
}
|
|
|
|
|
|
|
|
if valid:
|
|
|
|
self.object = form.save()
|
|
|
|
|
|
|
|
data['pk'] = self.object.pk
|
|
|
|
data['text'] = str(self.object)
|
|
|
|
else:
|
|
|
|
self.object = None
|
|
|
|
|
|
|
|
return self.renderJsonResponse(request, form, data,)
|
|
|
|
|
2019-06-05 10:59:30 +00:00
|
|
|
def get_form(self):
|
|
|
|
""" Limit choice options based on the selected order, etc
|
|
|
|
"""
|
|
|
|
|
|
|
|
form = super().get_form()
|
|
|
|
|
|
|
|
order_id = form['order'].value()
|
|
|
|
|
|
|
|
try:
|
|
|
|
order = PurchaseOrder.objects.get(id=order_id)
|
|
|
|
|
|
|
|
query = form.fields['part'].queryset
|
|
|
|
|
|
|
|
# Only allow parts from the selected supplier
|
|
|
|
query = query.filter(supplier=order.supplier.id)
|
|
|
|
|
2019-06-05 11:19:41 +00:00
|
|
|
exclude = []
|
|
|
|
|
|
|
|
for line in order.lines.all():
|
|
|
|
if line.part and line.part.id not in exclude:
|
|
|
|
exclude.append(line.part.id)
|
|
|
|
|
2019-06-05 11:13:08 +00:00
|
|
|
# Remove parts that are already in the order
|
2019-06-05 11:19:41 +00:00
|
|
|
query = query.exclude(id__in=exclude)
|
2019-06-05 10:59:30 +00:00
|
|
|
|
|
|
|
form.fields['part'].queryset = query
|
2019-06-05 11:19:41 +00:00
|
|
|
form.fields['order'].widget = HiddenInput()
|
2019-06-05 10:59:30 +00:00
|
|
|
except PurchaseOrder.DoesNotExist:
|
|
|
|
pass
|
|
|
|
|
|
|
|
return form
|
|
|
|
|
|
|
|
def get_initial(self):
|
|
|
|
""" Extract initial data for the line item.
|
|
|
|
|
|
|
|
- The 'order' will be passed as a query parameter
|
|
|
|
- Use this to set the 'order' field and limit the options for 'part'
|
|
|
|
"""
|
|
|
|
|
|
|
|
initials = super().get_initial().copy()
|
|
|
|
|
|
|
|
order_id = self.request.GET.get('order', None)
|
|
|
|
|
|
|
|
if order_id:
|
|
|
|
try:
|
|
|
|
order = PurchaseOrder.objects.get(id=order_id)
|
|
|
|
initials['order'] = order
|
|
|
|
|
|
|
|
except PurchaseOrder.DoesNotExist:
|
|
|
|
pass
|
|
|
|
|
|
|
|
return initials
|
|
|
|
|
|
|
|
|
|
|
|
class POLineItemEdit(AjaxUpdateView):
|
|
|
|
|
|
|
|
model = PurchaseOrderLineItem
|
2019-06-05 12:24:18 +00:00
|
|
|
form_class = order_forms.EditPurchaseOrderLineItemForm
|
2019-06-05 10:59:30 +00:00
|
|
|
ajax_template_name = 'modal_form.html'
|
|
|
|
ajax_form_action = 'Edit Line Item'
|