mirror of
https://github.com/inventree/InvenTree.git
synced 2026-09-10 06:37:17 +00:00
Fix order allocation variant validation logic and serializer read_only_fields (#12738)
* Fix order allocation variant validation logic and serializer defects * Format order models and tests with ruff preview style * Fix TransferOrder destination field in allocation unit tests
This commit is contained in:
@@ -3124,7 +3124,7 @@ class SalesOrderAllocation(models.Model):
|
|||||||
try:
|
try:
|
||||||
if self.line.part != self.item.part:
|
if self.line.part != self.item.part:
|
||||||
variants = self.line.part.get_descendants(include_self=True)
|
variants = self.line.part.get_descendants(include_self=True)
|
||||||
if self.line.part not in variants:
|
if self.item.part not in variants:
|
||||||
errors['item'] = _(
|
errors['item'] = _(
|
||||||
'Cannot allocate stock item to a line with a different part'
|
'Cannot allocate stock item to a line with a different part'
|
||||||
)
|
)
|
||||||
@@ -4127,7 +4127,7 @@ class TransferOrderAllocation(models.Model):
|
|||||||
try:
|
try:
|
||||||
if self.line.part != self.item.part:
|
if self.line.part != self.item.part:
|
||||||
variants = self.line.part.get_descendants(include_self=True)
|
variants = self.line.part.get_descendants(include_self=True)
|
||||||
if self.line.part not in variants:
|
if self.item.part not in variants:
|
||||||
errors['item'] = _(
|
errors['item'] = _(
|
||||||
'Cannot allocate stock item to a line with a different part'
|
'Cannot allocate stock item to a line with a different part'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1584,7 +1584,7 @@ class SalesOrderAllocationSerializer(
|
|||||||
'location_detail',
|
'location_detail',
|
||||||
'shipment_detail',
|
'shipment_detail',
|
||||||
]
|
]
|
||||||
read_only_fields = ['line', '']
|
read_only_fields = ['line']
|
||||||
|
|
||||||
part = serializers.PrimaryKeyRelatedField(source='item.part', read_only=True)
|
part = serializers.PrimaryKeyRelatedField(source='item.part', read_only=True)
|
||||||
order = serializers.PrimaryKeyRelatedField(
|
order = serializers.PrimaryKeyRelatedField(
|
||||||
@@ -2891,7 +2891,7 @@ class TransferOrderAllocationSerializer(
|
|||||||
'order_detail',
|
'order_detail',
|
||||||
'location_detail',
|
'location_detail',
|
||||||
]
|
]
|
||||||
read_only_fields = ['line', '']
|
read_only_fields = ['line']
|
||||||
|
|
||||||
part = serializers.PrimaryKeyRelatedField(source='item.part', read_only=True)
|
part = serializers.PrimaryKeyRelatedField(source='item.part', read_only=True)
|
||||||
order = serializers.PrimaryKeyRelatedField(
|
order = serializers.PrimaryKeyRelatedField(
|
||||||
|
|||||||
@@ -5853,3 +5853,103 @@ class OrderActionMissingPkTest(InvenTreeAPITestCase):
|
|||||||
]:
|
]:
|
||||||
url = reverse(url_name, kwargs={'pk': 999999})
|
url = reverse(url_name, kwargs={'pk': 999999})
|
||||||
self.post(url, {}, expected_code=404)
|
self.post(url, {}, expected_code=404)
|
||||||
|
|
||||||
|
|
||||||
|
class OrderAllocationValidationTest(InvenTreeAPITestCase):
|
||||||
|
"""Unit tests for SalesOrderAllocation and TransferOrderAllocation validation."""
|
||||||
|
|
||||||
|
fixtures = ['company', 'users', 'location']
|
||||||
|
|
||||||
|
roles = [
|
||||||
|
'sales_order.add',
|
||||||
|
'sales_order.change',
|
||||||
|
'transfer_order.add',
|
||||||
|
'transfer_order.change',
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
"""Set up test data with base parts, variant parts, and unrelated parts."""
|
||||||
|
super().setUpTestData()
|
||||||
|
|
||||||
|
cls.customer = models.Company.objects.create(
|
||||||
|
name='Alloc Customer', is_customer=True, description=''
|
||||||
|
)
|
||||||
|
cls.base_part = Part.objects.create(
|
||||||
|
name='Base Widget', salable=True, is_template=True, description=''
|
||||||
|
)
|
||||||
|
cls.variant_part = Part.objects.create(
|
||||||
|
name='Variant Widget A',
|
||||||
|
salable=True,
|
||||||
|
variant_of=cls.base_part,
|
||||||
|
description='',
|
||||||
|
)
|
||||||
|
cls.base_part.refresh_from_db()
|
||||||
|
cls.unrelated_part = Part.objects.create(
|
||||||
|
name='Unrelated Gadget', salable=True, description=''
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.location = StockLocation.objects.first()
|
||||||
|
|
||||||
|
def test_sales_order_allocation_validation(self):
|
||||||
|
"""Test validation when allocating stock to a SalesOrder."""
|
||||||
|
order = models.SalesOrder.objects.create(
|
||||||
|
customer=self.customer, reference='SO-ALLOC-TEST-1'
|
||||||
|
)
|
||||||
|
line = models.SalesOrderLineItem.objects.create(
|
||||||
|
order=order, part=self.base_part, quantity=10
|
||||||
|
)
|
||||||
|
shipment = models.SalesOrderShipment.objects.create(order=order, reference='1')
|
||||||
|
|
||||||
|
# Stock items
|
||||||
|
variant_stock = StockItem.objects.create(
|
||||||
|
part=self.variant_part, quantity=10, location=self.location
|
||||||
|
)
|
||||||
|
unrelated_stock = StockItem.objects.create(
|
||||||
|
part=self.unrelated_part, quantity=10, location=self.location
|
||||||
|
)
|
||||||
|
|
||||||
|
# Allocating valid variant should succeed
|
||||||
|
alloc_variant = models.SalesOrderAllocation(
|
||||||
|
line=line, item=variant_stock, quantity=5, shipment=shipment
|
||||||
|
)
|
||||||
|
alloc_variant.full_clean()
|
||||||
|
alloc_variant.save()
|
||||||
|
|
||||||
|
# Allocating unrelated part should raise ValidationError
|
||||||
|
alloc_invalid = models.SalesOrderAllocation(
|
||||||
|
line=line, item=unrelated_stock, quantity=5, shipment=shipment
|
||||||
|
)
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
alloc_invalid.full_clean()
|
||||||
|
|
||||||
|
def test_transfer_order_allocation_validation(self):
|
||||||
|
"""Test validation when allocating stock to a TransferOrder."""
|
||||||
|
dest_loc = StockLocation.objects.create(name='Dest Location')
|
||||||
|
order = models.TransferOrder.objects.create(
|
||||||
|
destination=dest_loc, reference='TO-ALLOC-TEST-1'
|
||||||
|
)
|
||||||
|
line = models.TransferOrderLineItem.objects.create(
|
||||||
|
order=order, part=self.base_part, quantity=10
|
||||||
|
)
|
||||||
|
|
||||||
|
variant_stock = StockItem.objects.create(
|
||||||
|
part=self.variant_part, quantity=10, location=self.location
|
||||||
|
)
|
||||||
|
unrelated_stock = StockItem.objects.create(
|
||||||
|
part=self.unrelated_part, quantity=10, location=self.location
|
||||||
|
)
|
||||||
|
|
||||||
|
# Allocating valid variant should succeed
|
||||||
|
alloc_variant = models.TransferOrderAllocation(
|
||||||
|
line=line, item=variant_stock, quantity=5
|
||||||
|
)
|
||||||
|
alloc_variant.full_clean()
|
||||||
|
alloc_variant.save()
|
||||||
|
|
||||||
|
# Allocating unrelated part should raise ValidationError
|
||||||
|
alloc_invalid = models.TransferOrderAllocation(
|
||||||
|
line=line, item=unrelated_stock, quantity=5
|
||||||
|
)
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
alloc_invalid.full_clean()
|
||||||
|
|||||||
Reference in New Issue
Block a user