2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-05-04 06:18:48 +00:00

Automatically add line items to an order

This commit is contained in:
Oliver Walters 2019-06-13 21:17:06 +10:00
parent f52aa0af21
commit 52b7051060
2 changed files with 93 additions and 5 deletions

View File

@ -6,6 +6,7 @@ Order model definitions
from django.db import models from django.db import models
from django.core.validators import MinValueValidator from django.core.validators import MinValueValidator
from django.core.exceptions import ValidationError
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.urls import reverse from django.urls import reverse
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -101,6 +102,50 @@ class PurchaseOrder(Order):
def get_absolute_url(self): def get_absolute_url(self):
return reverse('purchase-order-detail', kwargs={'pk': self.id}) return reverse('purchase-order-detail', kwargs={'pk': self.id})
def add_line_item(self, supplier_part, quantity, group=True, reference=''):
""" Add a new line item to this purchase order.
This function will check that:
* The supplier part matches the supplier specified for this purchase order
* The quantity is greater than zero
Args:
supplier_part - The supplier_part to add
quantity - The number of items to add
group - If True, this new quantity will be added to an existing line item for the same supplier_part (if it exists)
"""
try:
quantity = int(quantity)
if quantity <= 0:
raise ValidationError({
'quantity': _("Quantity must be greater than zero")})
except ValueError:
raise ValidationError({'quantity': _("Invalid quantity provided")})
if not supplier_part.supplier == self.supplier:
raise ValidationError({'supplier': _("Part supplier must match PO supplier")})
if group:
# Check if there is already a matching line item
matches = PurchaseOrderLineItem.objects.filter(part=supplier_part)
if matches.count() > 0:
line = matches.first()
line.quantity += quantity
line.save()
return
line = PurchaseOrderLineItem(
order=self,
part=supplier_part,
quantity=quantity,
reference=reference)
line.save()
class OrderLineItem(models.Model): class OrderLineItem(models.Model):
""" Abstract model for an order line item """ Abstract model for an order line item

View File

@ -9,6 +9,8 @@ from django.utils.translation import ugettext as _
from django.views.generic import DetailView, ListView from django.views.generic import DetailView, ListView
from django.forms import HiddenInput from django.forms import HiddenInput
import logging
from .models import PurchaseOrder, PurchaseOrderLineItem from .models import PurchaseOrder, PurchaseOrderLineItem
from build.models import Build from build.models import Build
from company.models import Company, SupplierPart from company.models import Company, SupplierPart
@ -22,6 +24,8 @@ from InvenTree.helpers import str2bool
from InvenTree.status_codes import OrderStatus from InvenTree.status_codes import OrderStatus
logger = logging.getLogger(__name__)
class PurchaseOrderIndex(ListView): class PurchaseOrderIndex(ListView):
""" List view for all purchase orders """ """ List view for all purchase orders """
@ -323,7 +327,6 @@ class OrderParts(AjaxView):
supplier_part = SupplierPart.objects.get(id=supplier_part_id) supplier_part = SupplierPart.objects.get(id=supplier_part_id)
except (SupplierPart.DoesNotExist, ValueError): except (SupplierPart.DoesNotExist, ValueError):
supplier_part = None supplier_part = None
print('Error getting supplier part for ID', supplier_part_id)
# Ensure a valid quantity is passed # Ensure a valid quantity is passed
try: try:
@ -350,8 +353,6 @@ class OrderParts(AjaxView):
# Which purchase order is selected for a given supplier? # Which purchase order is selected for a given supplier?
pk = item.replace('purchase-order-', '') pk = item.replace('purchase-order-', '')
print(item)
# Check that the Supplier actually exists # Check that the Supplier actually exists
try: try:
supplier = Company.objects.get(id=pk) supplier = Company.objects.get(id=pk)
@ -379,6 +380,8 @@ class OrderParts(AjaxView):
# Map parts to suppliers # Map parts to suppliers
self.get_suppliers() self.get_suppliers()
valid = False
if form_step == 'select_parts': if form_step == 'select_parts':
# No errors? Proceed to PO selection form # No errors? Proceed to PO selection form
if part_errors == False: if part_errors == False:
@ -389,15 +392,55 @@ class OrderParts(AjaxView):
elif form_step == 'select_purchase_orders': elif form_step == 'select_purchase_orders':
self.ajax_template_name = 'order/order_wizard/select_pos.html' self.ajax_template_name = 'order/order_wizard/select_pos.html'
valid = part_errors is False and supplier_errors is False
# Form wizard is complete! Add items to purchase orders
if valid:
self.order_items()
data = { data = {
'form_valid': False, 'form_valid': valid,
'success': 'Ordered {n} parts'.format(n=len(self.parts))
} }
return self.renderJsonResponse(self.request, data=data) return self.renderJsonResponse(self.request, data=data)
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)
class POLineItemCreate(AjaxCreateView): class POLineItemCreate(AjaxCreateView):
""" AJAX view for creating a new PurchaseOrderLineItem object """ AJAX view for creating a new PurchaseOrderLineItem object