mirror of
https://github.com/inventree/InvenTree.git
synced 2025-05-04 14:28:48 +00:00
Automatically add line items to an order
This commit is contained in:
parent
f52aa0af21
commit
52b7051060
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user