Coverage for src/backend/InvenTree/stock/filters.py: 86%
12 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
1"""Custom query filters for the Stock models."""
3from typing import Optional
5from django.db.models import F, Func, IntegerField, OuterRef, Q, Subquery
6from django.db.models.functions import Coalesce
8import stock.models
11def annotate_location_items(filter: Optional[Q] = None):
12 """Construct a queryset annotation which returns the number of stock items in a particular location.
14 - Includes items in subcategories also
15 - Requires subquery to perform annotation
16 """
17 # Construct a subquery to provide all items in this location and any sublocations
18 subquery = stock.models.StockItem.objects.exclude(location=None).filter(
19 location__tree_id=OuterRef('tree_id'),
20 location__lft__gte=OuterRef('lft'),
21 location__rght__lte=OuterRef('rght'),
22 location__level__gte=OuterRef('level'),
23 )
25 # Optionally apply extra filter to returned results
26 if filter is not None: 26 ↛ 27line 26 didn't jump to line 27 because the condition on line 26 was never true
27 subquery = subquery.filter(filter)
29 return Coalesce(
30 Subquery(
31 subquery
32 .annotate(
33 total=Func(F('pk'), function='COUNT', output_field=IntegerField())
34 )
35 .values('total')
36 .order_by()
37 ),
38 0,
39 output_field=IntegerField(),
40 )
43def annotate_sub_locations():
44 """Construct a queryset annotation which returns the number of sub-locations below a certain StockLocation node in a StockLocation tree."""
45 subquery = stock.models.StockLocation.objects.filter(
46 tree_id=OuterRef('tree_id'),
47 lft__gt=OuterRef('lft'),
48 rght__lt=OuterRef('rght'),
49 level__gt=OuterRef('level'),
50 )
52 return Coalesce(
53 Subquery(
54 subquery
55 .annotate(
56 count=Func(F('pk'), function='COUNT', output_field=IntegerField())
57 )
58 .values('count')
59 .order_by()
60 ),
61 0,
62 output_field=IntegerField(),
63 )