mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-04 15:15:42 +00:00 
			
		
		
		
	Inherited BOM fix (#3579)
* Fix logic for get_used_in_bom_item_filter * Include scheduling information for inherited BOMs
This commit is contained in:
		@@ -574,16 +574,33 @@ class PartScheduling(RetrieveAPI):
 | 
			
		||||
        # Grab a list of BomItem objects that this part might be used in
 | 
			
		||||
        bom_items = BomItem.objects.filter(part.get_used_in_bom_item_filter())
 | 
			
		||||
 | 
			
		||||
        # Track all outstanding build orders
 | 
			
		||||
        seen_builds = set()
 | 
			
		||||
 | 
			
		||||
        for bom_item in bom_items:
 | 
			
		||||
            # Find a list of active builds for this BomItem
 | 
			
		||||
 | 
			
		||||
            builds = Build.objects.filter(
 | 
			
		||||
                status__in=BuildStatus.ACTIVE_CODES,
 | 
			
		||||
                part=bom_item.part,
 | 
			
		||||
            )
 | 
			
		||||
            if bom_item.inherited:
 | 
			
		||||
                # An "inherited" BOM item filters down to variant parts also
 | 
			
		||||
                childs = bom_item.part.get_descendants(include_self=True)
 | 
			
		||||
                builds = Build.objects.filter(
 | 
			
		||||
                    status__in=BuildStatus.ACTIVE_CODES,
 | 
			
		||||
                    part__in=childs,
 | 
			
		||||
                )
 | 
			
		||||
            else:
 | 
			
		||||
                builds = Build.objects.filter(
 | 
			
		||||
                    status__in=BuildStatus.ACTIVE_CODES,
 | 
			
		||||
                    part=bom_item.part,
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            for build in builds:
 | 
			
		||||
 | 
			
		||||
                # Ensure we don't double-count any builds
 | 
			
		||||
                if build in seen_builds:
 | 
			
		||||
                    continue
 | 
			
		||||
 | 
			
		||||
                seen_builds.add(build)
 | 
			
		||||
 | 
			
		||||
                if bom_item.sub_part.trackable:
 | 
			
		||||
                    # Trackable parts are allocated against the outputs
 | 
			
		||||
                    required_quantity = build.remaining * bom_item.quantity
 | 
			
		||||
 
 | 
			
		||||
@@ -1436,7 +1436,7 @@ class Part(MetadataMixin, MPTTModel):
 | 
			
		||||
 | 
			
		||||
        return parts
 | 
			
		||||
 | 
			
		||||
    def get_used_in_bom_item_filter(self, include_inherited=True, include_variants=True, include_substitutes=True):
 | 
			
		||||
    def get_used_in_bom_item_filter(self, include_variants=True, include_substitutes=True):
 | 
			
		||||
        """Return a BomItem queryset which returns all BomItem instances which refer to *this* part.
 | 
			
		||||
 | 
			
		||||
        As the BOM allocation logic is somewhat complicted, there are some considerations:
 | 
			
		||||
@@ -1454,21 +1454,13 @@ class Part(MetadataMixin, MPTTModel):
 | 
			
		||||
        # Case A: This part is directly specified in a BomItem (we always use this case)
 | 
			
		||||
        query = Q(
 | 
			
		||||
            sub_part=self,
 | 
			
		||||
            inherited=False,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        if include_inherited:
 | 
			
		||||
            query |= Q(
 | 
			
		||||
                sub_part__in=parents,
 | 
			
		||||
                inherited=True
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        if include_variants:
 | 
			
		||||
            # Case B: This part is a *variant* of a part which is specified in a BomItem which allows variants
 | 
			
		||||
            query |= Q(
 | 
			
		||||
                allow_variants=True,
 | 
			
		||||
                sub_part__in=parents,
 | 
			
		||||
                inherited=False,
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        # Case C: This part is a *substitute* of a part which is directly specified in a BomItem
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user