mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Unit test fixes
This commit is contained in:
parent
d7c87300c6
commit
88fce1e813
@ -617,11 +617,34 @@ class SalesOrder(Order):
|
|||||||
def is_completed(self):
|
def is_completed(self):
|
||||||
"""
|
"""
|
||||||
Check if this order is "shipped" (all line items delivered),
|
Check if this order is "shipped" (all line items delivered),
|
||||||
and mark it as "shipped" if so.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self.lines.count() > 0 and all([line.is_completed() for line in self.lines.all()])
|
return self.lines.count() > 0 and all([line.is_completed() for line in self.lines.all()])
|
||||||
|
|
||||||
|
def complete_order(self, user):
|
||||||
|
"""
|
||||||
|
Mark this order as "complete"
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.lines.count() == 0:
|
||||||
|
# Order without line items cannot be completed
|
||||||
|
raise ValidationError(_('Order cannot be completed as no parts have been assigned'))
|
||||||
|
|
||||||
|
if self.status != SalesOrderStatus.PENDING:
|
||||||
|
# Only a PENDING order can be marked as SHIPPED
|
||||||
|
raise ValidationError(_('Only a pending order can be marked as complete'))
|
||||||
|
|
||||||
|
# Check if there are any incomplete shipments
|
||||||
|
for shipment in self.shipments.all():
|
||||||
|
if not shipment.shipment_date:
|
||||||
|
raise ValidationError(_('Order cannot be completed as there are pending shipments'))
|
||||||
|
|
||||||
|
self.status = SalesOrderStatus.SHIPPED
|
||||||
|
self.shipped_by = user
|
||||||
|
self.shipment_date = datetime.now()
|
||||||
|
|
||||||
|
self.save()
|
||||||
|
|
||||||
def can_cancel(self):
|
def can_cancel(self):
|
||||||
"""
|
"""
|
||||||
Return True if this order can be cancelled
|
Return True if this order can be cancelled
|
||||||
@ -988,6 +1011,9 @@ class SalesOrderShipment(models.Model):
|
|||||||
help_text=_('Shipment tracking information'),
|
help_text=_('Shipment tracking information'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def is_complete(self):
|
||||||
|
return self.shipment_date is not None
|
||||||
|
|
||||||
def check_can_complete(self):
|
def check_can_complete(self):
|
||||||
|
|
||||||
if self.shipment_date:
|
if self.shipment_date:
|
||||||
|
@ -26,7 +26,7 @@ from InvenTree.serializers import InvenTreeModelSerializer
|
|||||||
from InvenTree.serializers import InvenTreeDecimalField
|
from InvenTree.serializers import InvenTreeDecimalField
|
||||||
from InvenTree.serializers import InvenTreeMoneySerializer
|
from InvenTree.serializers import InvenTreeMoneySerializer
|
||||||
from InvenTree.serializers import ReferenceIndexingSerializerMixin
|
from InvenTree.serializers import ReferenceIndexingSerializerMixin
|
||||||
from InvenTree.status_codes import StockStatus, SalesOrderStatus
|
from InvenTree.status_codes import StockStatus
|
||||||
|
|
||||||
import order.models
|
import order.models
|
||||||
|
|
||||||
@ -745,11 +745,11 @@ class SalesOrderCompleteSerializer(serializers.Serializer):
|
|||||||
|
|
||||||
request = self.context['request']
|
request = self.context['request']
|
||||||
order = self.context['order']
|
order = self.context['order']
|
||||||
data = self.validated_data
|
# data = self.validated_data
|
||||||
|
|
||||||
# Mark this order as complete!
|
user = getattr(request, 'user', None)
|
||||||
order.status = SalesOrderStatus.SHIPPED
|
|
||||||
order.save()
|
order.complete_order(user)
|
||||||
|
|
||||||
|
|
||||||
class SOShipmentAllocationSerializer(serializers.Serializer):
|
class SOShipmentAllocationSerializer(serializers.Serializer):
|
||||||
|
@ -4,7 +4,6 @@ Unit tests for the 'order' model data migrations
|
|||||||
|
|
||||||
from django_test_migrations.contrib.unittest_case import MigratorTestCase
|
from django_test_migrations.contrib.unittest_case import MigratorTestCase
|
||||||
|
|
||||||
from InvenTree import helpers
|
|
||||||
from InvenTree.status_codes import SalesOrderStatus
|
from InvenTree.status_codes import SalesOrderStatus
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ from company.models import Company
|
|||||||
|
|
||||||
from InvenTree import status_codes as status
|
from InvenTree import status_codes as status
|
||||||
|
|
||||||
from order.models import SalesOrder, SalesOrderLineItem, SalesOrderAllocation
|
from order.models import SalesOrder, SalesOrderLineItem, SalesOrderAllocation, SalesOrderShipment
|
||||||
|
|
||||||
from part.models import Part
|
from part.models import Part
|
||||||
|
|
||||||
@ -42,6 +42,12 @@ class SalesOrderTest(TestCase):
|
|||||||
customer_reference='ABC 55555'
|
customer_reference='ABC 55555'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Create a Shipment against this SalesOrder
|
||||||
|
self.shipment = SalesOrderShipment.objects.create(
|
||||||
|
order=self.order,
|
||||||
|
reference='001',
|
||||||
|
)
|
||||||
|
|
||||||
# Create a line item
|
# Create a line item
|
||||||
self.line = SalesOrderLineItem.objects.create(quantity=50, order=self.order, part=self.part)
|
self.line = SalesOrderLineItem.objects.create(quantity=50, order=self.order, part=self.part)
|
||||||
|
|
||||||
@ -86,11 +92,13 @@ class SalesOrderTest(TestCase):
|
|||||||
# Allocate stock to the order
|
# Allocate stock to the order
|
||||||
SalesOrderAllocation.objects.create(
|
SalesOrderAllocation.objects.create(
|
||||||
line=self.line,
|
line=self.line,
|
||||||
|
shipment=self.shipment,
|
||||||
item=StockItem.objects.get(pk=self.Sa.pk),
|
item=StockItem.objects.get(pk=self.Sa.pk),
|
||||||
quantity=25)
|
quantity=25)
|
||||||
|
|
||||||
SalesOrderAllocation.objects.create(
|
SalesOrderAllocation.objects.create(
|
||||||
line=self.line,
|
line=self.line,
|
||||||
|
shipment=self.shipment,
|
||||||
item=StockItem.objects.get(pk=self.Sb.pk),
|
item=StockItem.objects.get(pk=self.Sb.pk),
|
||||||
quantity=25 if full else 20
|
quantity=25 if full else 20
|
||||||
)
|
)
|
||||||
@ -126,9 +134,9 @@ class SalesOrderTest(TestCase):
|
|||||||
|
|
||||||
# Now try to ship it - should fail
|
# Now try to ship it - should fail
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
self.order.ship_order(None)
|
self.order.complete_order(None)
|
||||||
|
|
||||||
def test_ship_order(self):
|
def test_complete_order(self):
|
||||||
# Allocate line items, then ship the order
|
# Allocate line items, then ship the order
|
||||||
|
|
||||||
# Assert some stuff before we run the test
|
# Assert some stuff before we run the test
|
||||||
@ -140,7 +148,22 @@ class SalesOrderTest(TestCase):
|
|||||||
|
|
||||||
self.assertEqual(SalesOrderAllocation.objects.count(), 2)
|
self.assertEqual(SalesOrderAllocation.objects.count(), 2)
|
||||||
|
|
||||||
self.order.ship_order(None)
|
# Attempt to complete the order (but shipments are not completed!)
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
self.order.complete_order(None)
|
||||||
|
|
||||||
|
self.assertIsNone(self.shipment.shipment_date)
|
||||||
|
self.assertFalse(self.shipment.is_complete())
|
||||||
|
|
||||||
|
# Mark the shipments as complete
|
||||||
|
self.shipment.complete_shipment(None)
|
||||||
|
self.assertTrue(self.shipment.is_complete())
|
||||||
|
|
||||||
|
# Now, should be OK to ship
|
||||||
|
self.order.complete_order(None)
|
||||||
|
|
||||||
|
self.assertEqual(self.order.status, status.SalesOrderStatus.SHIPPED)
|
||||||
|
self.assertIsNotNone(self.order.shipment_date)
|
||||||
|
|
||||||
# There should now be 4 stock items
|
# There should now be 4 stock items
|
||||||
self.assertEqual(StockItem.objects.count(), 4)
|
self.assertEqual(StockItem.objects.count(), 4)
|
||||||
@ -162,12 +185,12 @@ class SalesOrderTest(TestCase):
|
|||||||
self.assertEqual(sa.sales_order, None)
|
self.assertEqual(sa.sales_order, None)
|
||||||
self.assertEqual(sb.sales_order, None)
|
self.assertEqual(sb.sales_order, None)
|
||||||
|
|
||||||
# And no allocations
|
# And the allocations still exist
|
||||||
self.assertEqual(SalesOrderAllocation.objects.count(), 0)
|
self.assertEqual(SalesOrderAllocation.objects.count(), 2)
|
||||||
|
|
||||||
self.assertEqual(self.order.status, status.SalesOrderStatus.SHIPPED)
|
self.assertEqual(self.order.status, status.SalesOrderStatus.SHIPPED)
|
||||||
|
|
||||||
self.assertTrue(self.order.is_fully_allocated())
|
self.assertTrue(self.order.is_fully_allocated())
|
||||||
self.assertTrue(self.line.is_fully_allocated())
|
self.assertTrue(self.line.is_fully_allocated())
|
||||||
self.assertEqual(self.line.fulfilled_quantity(), 50)
|
self.assertEqual(self.line.fulfilled_quantity(), 50)
|
||||||
self.assertEqual(self.line.allocated_quantity(), 0)
|
self.assertEqual(self.line.allocated_quantity(), 50)
|
||||||
|
@ -792,14 +792,12 @@ class OrderParts(AjaxView):
|
|||||||
order.add_line_item(supplier_part, quantity, purchase_price=purchase_price)
|
order.add_line_item(supplier_part, quantity, purchase_price=purchase_price)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### TODO: This class MUST be converted to the API forms!
|
|
||||||
#### TODO: We MUST select the shipment
|
|
||||||
class SalesOrderAssignSerials(AjaxView, FormMixin):
|
class SalesOrderAssignSerials(AjaxView, FormMixin):
|
||||||
"""
|
"""
|
||||||
View for assigning stock items to a sales order,
|
View for assigning stock items to a sales order,
|
||||||
by serial number lookup.
|
by serial number lookup.
|
||||||
"""
|
"""
|
||||||
|
# TODO: Remove this class and replace with an API endpoint
|
||||||
|
|
||||||
model = SalesOrderAllocation
|
model = SalesOrderAllocation
|
||||||
role_required = 'sales_order.change'
|
role_required = 'sales_order.change'
|
||||||
|
Loading…
Reference in New Issue
Block a user