mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-04 15:15:42 +00:00 
			
		
		
		
	Add some unit testing for the new model
This commit is contained in:
		@@ -1281,7 +1281,6 @@ class BomItemValidate(generics.UpdateAPIView):
 | 
				
			|||||||
        return Response(serializer.data)
 | 
					        return Response(serializer.data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
class BomItemSubstituteList(generics.ListCreateAPIView):
 | 
					class BomItemSubstituteList(generics.ListCreateAPIView):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    API endpoint for accessing a list of BomItemSubstitute objects
 | 
					    API endpoint for accessing a list of BomItemSubstitute objects
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2629,6 +2629,12 @@ class BomItemSubstitute(models.Model):
 | 
				
			|||||||
        # Prevent duplication of substitute parts
 | 
					        # Prevent duplication of substitute parts
 | 
				
			||||||
        unique_together = ('part', 'bom_item')
 | 
					        unique_together = ('part', 'bom_item')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def save(self, *args, **kwargs):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.full_clean()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super().save(*args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def validate_unique(self, exclude=None):
 | 
					    def validate_unique(self, exclude=None):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Ensure that this BomItemSubstitute is "unique":
 | 
					        Ensure that this BomItemSubstitute is "unique":
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,13 @@
 | 
				
			|||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					from django.db import transaction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.test import TestCase
 | 
					from django.test import TestCase
 | 
				
			||||||
import django.core.exceptions as django_exceptions
 | 
					import django.core.exceptions as django_exceptions
 | 
				
			||||||
from decimal import Decimal
 | 
					from decimal import Decimal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .models import Part, BomItem
 | 
					from .models import Part, BomItem, BomItemSubstitute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BomItemTest(TestCase):
 | 
					class BomItemTest(TestCase):
 | 
				
			||||||
@@ -130,3 +135,67 @@ class BomItemTest(TestCase):
 | 
				
			|||||||
            self.bob.get_bom_price_range(1, internal=True),
 | 
					            self.bob.get_bom_price_range(1, internal=True),
 | 
				
			||||||
            (Decimal(27.5), Decimal(87.5))
 | 
					            (Decimal(27.5), Decimal(87.5))
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_substitutes(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Tests for BOM item substitutes
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # We will make some subtitute parts for the "orphan" part
 | 
				
			||||||
 | 
					        bom_item = BomItem.objects.get(
 | 
				
			||||||
 | 
					            part=self.bob,
 | 
				
			||||||
 | 
					            sub_part=self.orphan
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # No substitute parts available
 | 
				
			||||||
 | 
					        self.assertEqual(bom_item.substitutes.count(), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        subs = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for ii in range(5):
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            # Create a new part
 | 
				
			||||||
 | 
					            sub_part = Part.objects.create(
 | 
				
			||||||
 | 
					                name=f"Orphan {ii}",
 | 
				
			||||||
 | 
					                description="A substitute part for the orphan part",
 | 
				
			||||||
 | 
					                component=True,
 | 
				
			||||||
 | 
					                is_template=False,
 | 
				
			||||||
 | 
					                assembly=False,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            subs.append(sub_part)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Link it as a substitute part
 | 
				
			||||||
 | 
					            BomItemSubstitute.objects.create(
 | 
				
			||||||
 | 
					                bom_item=bom_item,
 | 
				
			||||||
 | 
					                part=sub_part
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Try to link it again (this should fail as it is a duplicate substitute)
 | 
				
			||||||
 | 
					            with self.assertRaises(django_exceptions.ValidationError):
 | 
				
			||||||
 | 
					                with transaction.atomic():
 | 
				
			||||||
 | 
					                    BomItemSubstitute.objects.create(
 | 
				
			||||||
 | 
					                        bom_item=bom_item,
 | 
				
			||||||
 | 
					                        part=sub_part
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # There should be now 5 substitute parts available
 | 
				
			||||||
 | 
					        self.assertEqual(bom_item.substitutes.count(), 5)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        # Try to create a substitute which points to the same sub-part (should fail)
 | 
				
			||||||
 | 
					        with self.assertRaises(django_exceptions.ValidationError):
 | 
				
			||||||
 | 
					            BomItemSubstitute.objects.create(
 | 
				
			||||||
 | 
					                bom_item=bom_item,
 | 
				
			||||||
 | 
					                part=self.orphan,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Remove one substitute part
 | 
				
			||||||
 | 
					        bom_item.substitutes.last().delete()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(bom_item.substitutes.count(), 4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for sub in subs:
 | 
				
			||||||
 | 
					            sub.delete()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # The substitution links should have been automatically removed
 | 
				
			||||||
 | 
					        self.assertEqual(bom_item.substitutes.count(), 0)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -161,7 +161,9 @@ function bomSubstitutesDialog(bom_item_id, substitutes, options={}) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        var pk = substitute.pk;
 | 
					        var pk = substitute.pk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var thumb = thumbnailImage(substitute.part_detail.thumbnail || substitute.part_detail.image);
 | 
					        var part = substitute.part_detail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var thumb = thumbnailImage(part.thumbnail || part.image);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var buttons = '';
 | 
					        var buttons = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -170,8 +172,12 @@ function bomSubstitutesDialog(bom_item_id, substitutes, options={}) {
 | 
				
			|||||||
        // Render a single row
 | 
					        // Render a single row
 | 
				
			||||||
        var html = `
 | 
					        var html = `
 | 
				
			||||||
        <tr id='substitute-row-${pk}' class='substitute-row'>
 | 
					        <tr id='substitute-row-${pk}' class='substitute-row'>
 | 
				
			||||||
            <td id='part-${pk}'>${thumb} ${substitute.part_detail.full_name}</td>
 | 
					            <td id='part-${pk}'>
 | 
				
			||||||
            <td id='description-${pk}'><em>${substitute.part_detail.description}</em></td>
 | 
					                <a href='/part/${part.pk}/'>
 | 
				
			||||||
 | 
					                    ${thumb} ${part.full_name}
 | 
				
			||||||
 | 
					                </a>
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					            <td id='description-${pk}'><em>${part.description}</em></td>
 | 
				
			||||||
            <td>${buttons}</td>
 | 
					            <td>${buttons}</td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        `;
 | 
					        `;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user