Coverage for src/backend/InvenTree/stock/admin.py: 87%

38 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 17:47 +0000

1"""Admin for stock app.""" 

2 

3from django.contrib import admin 

4from django.db.models import Count 

5 

6from .models import ( 

7 StockItem, 

8 StockItemTestResult, 

9 StockItemTracking, 

10 StockLocation, 

11 StockLocationType, 

12) 

13 

14 

15class LocationInline(admin.TabularInline): 

16 """Inline for sub-locations.""" 

17 

18 model = StockLocation 

19 

20 

21@admin.register(StockLocation) 

22class LocationAdmin(admin.ModelAdmin): 

23 """Admin class for Location.""" 

24 

25 list_display = ('name', 'pathstring', 'description') 

26 

27 search_fields = ('name', 'description') 

28 

29 inlines = [LocationInline] 

30 

31 autocomplete_fields = ['parent'] 

32 

33 

34@admin.register(StockLocationType) 

35class LocationTypeAdmin(admin.ModelAdmin): 

36 """Admin class for StockLocationType.""" 

37 

38 list_display = ('name', 'description', 'icon', 'location_count') 

39 readonly_fields = ('location_count',) 

40 

41 def get_queryset(self, request): 

42 """Annotate queryset to fetch location count.""" 

43 return ( 

44 super() 

45 .get_queryset(request) 

46 .annotate(location_count=Count('stock_locations')) 

47 ) 

48 

49 def location_count(self, obj): 

50 """Returns the number of locations this location type is assigned to.""" 

51 return obj.location_count 

52 

53 

54@admin.register(StockItem) 

55class StockItemAdmin(admin.ModelAdmin): 

56 """Admin class for StockItem.""" 

57 

58 list_display = ('part', 'quantity', 'location', 'status', 'updated') 

59 

60 # A list of search fields which can be used for lookup on matching 'autocomplete' fields 

61 search_fields = ['part__name', 'part__description', 'serial', 'batch'] 

62 

63 autocomplete_fields = [ 

64 'belongs_to', 

65 'build', 

66 'customer', 

67 'location', 

68 'parent', 

69 'part', 

70 'purchase_order', 

71 'sales_order', 

72 'stocktake_user', 

73 'supplier_part', 

74 'consumed_by', 

75 ] 

76 

77 

78@admin.register(StockItemTracking) 

79class StockTrackingAdmin(admin.ModelAdmin): 

80 """Admin class for StockTracking - read-only to preserve audit trail integrity.""" 

81 

82 list_display = ('item', 'date', 'label') 

83 

84 autocomplete_fields = ['item'] 

85 

86 def has_add_permission(self, request): 

87 """Prevent addition of new tracking entries via the admin interface.""" 

88 return False 

89 

90 def has_change_permission(self, request, obj=None): 

91 """Prevent modification of tracking entries via the admin interface.""" 

92 return False 

93 

94 def has_delete_permission(self, request, obj=None): 

95 """Prevent deletion of tracking entries via the admin interface.""" 

96 return False 

97 

98 

99@admin.register(StockItemTestResult) 

100class StockItemTestResultAdmin(admin.ModelAdmin): 

101 """Admin class for StockItemTestResult.""" 

102 

103 list_display = ('stock_item', 'test_name', 'result', 'value') 

104 

105 autocomplete_fields = ['stock_item']