We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add purchase price to Part Stock table
Add column `purchase_price` to "Part Stock" table and make it sortable.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `InvenTree/stock/serializers.py`
Content:
```
1 """
2 JSON serializers for Stock app
3 """
4 
5 from rest_framework import serializers
6 
7 from .models import StockItem, StockLocation
8 from .models import StockItemTracking
9 from .models import StockItemAttachment
10 from .models import StockItemTestResult
11 
12 from django.db.models.functions import Coalesce
13 
14 from django.db.models import Case, When, Value
15 from django.db.models import BooleanField
16 from django.db.models import Q
17 
18 from sql_util.utils import SubquerySum, SubqueryCount
19 
20 from decimal import Decimal
21 
22 from datetime import datetime, timedelta
23 
24 import common.models
25 from company.serializers import SupplierPartSerializer
26 from part.serializers import PartBriefSerializer
27 from InvenTree.serializers import UserSerializerBrief, InvenTreeModelSerializer
28 from InvenTree.serializers import InvenTreeAttachmentSerializerField
29 
30 
31 class LocationBriefSerializer(InvenTreeModelSerializer):
32     """
33     Provides a brief serializer for a StockLocation object
34     """
35 
36     class Meta:
37         model = StockLocation
38         fields = [
39             'pk',
40             'name',
41             'pathstring',
42         ]
43 
44 
45 class StockItemSerializerBrief(InvenTreeModelSerializer):
46     """ Brief serializers for a StockItem """
47 
48     location_name = serializers.CharField(source='location', read_only=True)
49     part_name = serializers.CharField(source='part.full_name', read_only=True)
50     quantity = serializers.FloatField()
51 
52     class Meta:
53         model = StockItem
54         fields = [
55             'pk',
56             'uid',
57             'part',
58             'part_name',
59             'supplier_part',
60             'location',
61             'location_name',
62             'quantity',
63         ]
64 
65 
66 class StockItemSerializer(InvenTreeModelSerializer):
67     """ Serializer for a StockItem:
68 
69     - Includes serialization for the linked part
70     - Includes serialization for the item location
71     """
72 
73     @staticmethod
74     def prefetch_queryset(queryset):
75         """
76         Prefetch related database tables,
77         to reduce database hits.
78         """
79 
80         return queryset.prefetch_related(
81             'belongs_to',
82             'build',
83             'customer',
84             'sales_order',
85             'supplier_part',
86             'supplier_part__supplier',
87             'supplier_part__manufacturer_part__manufacturer',
88             'allocations',
89             'sales_order_allocations',
90             'location',
91             'part',
92             'tracking_info',
93         )
94 
95     @staticmethod
96     def annotate_queryset(queryset):
97         """
98         Add some extra annotations to the queryset,
99         performing database queries as efficiently as possible.
100         """
101 
102         # Annotate the queryset with the total allocated to sales orders
103         queryset = queryset.annotate(
104             allocated=Coalesce(
105                 SubquerySum('sales_order_allocations__quantity'), Decimal(0)
106             ) + Coalesce(
107                 SubquerySum('allocations__quantity'), Decimal(0)
108             )
109         )
110 
111         # Annotate the queryset with the number of tracking items
112         queryset = queryset.annotate(
113             tracking_items=SubqueryCount('tracking_info')
114         )
115 
116         # Add flag to indicate if the StockItem has expired
117         queryset = queryset.annotate(
118             expired=Case(
119                 When(
120                     StockItem.EXPIRED_FILTER, then=Value(True, output_field=BooleanField()),
121                 ),
122                 default=Value(False, output_field=BooleanField())
123             )
124         )
125 
126         # Add flag to indicate if the StockItem is stale
127         stale_days = common.models.InvenTreeSetting.get_setting('STOCK_STALE_DAYS')
128         stale_date = datetime.now().date() + timedelta(days=stale_days)
129         stale_filter = StockItem.IN_STOCK_FILTER & ~Q(expiry_date=None) & Q(expiry_date__lt=stale_date)
130 
131         queryset = queryset.annotate(
132             stale=Case(
133                 When(
134                     stale_filter, then=Value(True, output_field=BooleanField()),
135                 ),
136                 default=Value(False, output_field=BooleanField()),
137             )
138         )
139 
140         return queryset
141 
142     status_text = serializers.CharField(source='get_status_display', read_only=True)
143 
144     supplier_part_detail = SupplierPartSerializer(source='supplier_part', many=False, read_only=True)
145 
146     part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
147 
148     location_detail = LocationBriefSerializer(source='location', many=False, read_only=True)
149 
150     tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True, required=False)
151 
152     quantity = serializers.FloatField()
153 
154     allocated = serializers.FloatField(source='allocation_count', required=False)
155 
156     expired = serializers.BooleanField(required=False, read_only=True)
157 
158     stale = serializers.BooleanField(required=False, read_only=True)
159 
160     serial = serializers.CharField(required=False)
161 
162     required_tests = serializers.IntegerField(source='required_test_count', read_only=True, required=False)
163 
164     def __init__(self, *args, **kwargs):
165 
166         part_detail = kwargs.pop('part_detail', False)
167         location_detail = kwargs.pop('location_detail', False)
168         supplier_part_detail = kwargs.pop('supplier_part_detail', False)
169         test_detail = kwargs.pop('test_detail', False)
170 
171         super(StockItemSerializer, self).__init__(*args, **kwargs)
172 
173         if part_detail is not True:
174             self.fields.pop('part_detail')
175 
176         if location_detail is not True:
177             self.fields.pop('location_detail')
178 
179         if supplier_part_detail is not True:
180             self.fields.pop('supplier_part_detail')
181 
182         if test_detail is not True:
183             self.fields.pop('required_tests')
184 
185     class Meta:
186         model = StockItem
187         fields = [
188             'allocated',
189             'batch',
190             'belongs_to',
191             'build',
192             'customer',
193             'expired',
194             'expiry_date',
195             'in_stock',
196             'is_building',
197             'link',
198             'location',
199             'location_detail',
200             'notes',
201             'packaging',
202             'part',
203             'part_detail',
204             'pk',
205             'quantity',
206             'required_tests',
207             'sales_order',
208             'serial',
209             'stale',
210             'status',
211             'status_text',
212             'stocktake_date',
213             'supplier_part',
214             'supplier_part_detail',
215             'tracking_items',
216             'uid',
217             'updated',
218         ]
219 
220         """ These fields are read-only in this context.
221         They can be updated by accessing the appropriate API endpoints
222         """
223         read_only_fields = [
224             'allocated',
225             'stocktake_date',
226             'stocktake_user',
227             'updated',
228             'in_stock'
229         ]
230 
231 
232 class StockQuantitySerializer(InvenTreeModelSerializer):
233 
234     class Meta:
235         model = StockItem
236         fields = ('quantity',)
237 
238 
239 class LocationSerializer(InvenTreeModelSerializer):
240     """ Detailed information about a stock location
241     """
242 
243     url = serializers.CharField(source='get_absolute_url', read_only=True)
244 
245     items = serializers.IntegerField(source='item_count', read_only=True)
246 
247     class Meta:
248         model = StockLocation
249         fields = [
250             'pk',
251             'url',
252             'name',
253             'description',
254             'parent',
255             'pathstring',
256             'items',
257         ]
258 
259 
260 class StockItemAttachmentSerializer(InvenTreeModelSerializer):
261     """ Serializer for StockItemAttachment model """
262 
263     def __init__(self, *args, **kwargs):
264         user_detail = kwargs.pop('user_detail', False)
265 
266         super().__init__(*args, **kwargs)
267 
268         if user_detail is not True:
269             self.fields.pop('user_detail')
270 
271     user_detail = UserSerializerBrief(source='user', read_only=True)
272 
273     attachment = InvenTreeAttachmentSerializerField(required=True)
274 
275     class Meta:
276         model = StockItemAttachment
277 
278         fields = [
279             'pk',
280             'stock_item',
281             'attachment',
282             'comment',
283             'upload_date',
284             'user',
285             'user_detail',
286         ]
287 
288         read_only_fields = [
289             'upload_date',
290             'user',
291             'user_detail'
292         ]
293 
294 
295 class StockItemTestResultSerializer(InvenTreeModelSerializer):
296     """ Serializer for the StockItemTestResult model """
297 
298     user_detail = UserSerializerBrief(source='user', read_only=True)
299 
300     key = serializers.CharField(read_only=True)
301 
302     attachment = InvenTreeAttachmentSerializerField(required=False)
303 
304     def __init__(self, *args, **kwargs):
305         user_detail = kwargs.pop('user_detail', False)
306 
307         super().__init__(*args, **kwargs)
308 
309         if user_detail is not True:
310             self.fields.pop('user_detail')
311 
312     class Meta:
313         model = StockItemTestResult
314 
315         fields = [
316             'pk',
317             'stock_item',
318             'key',
319             'test',
320             'result',
321             'value',
322             'attachment',
323             'notes',
324             'user',
325             'user_detail',
326             'date'
327         ]
328 
329         read_only_fields = [
330             'pk',
331             'user',
332             'date',
333         ]
334 
335 
336 class StockTrackingSerializer(InvenTreeModelSerializer):
337     """ Serializer for StockItemTracking model """
338 
339     def __init__(self, *args, **kwargs):
340 
341         item_detail = kwargs.pop('item_detail', False)
342         user_detail = kwargs.pop('user_detail', False)
343 
344         super().__init__(*args, **kwargs)
345 
346         if item_detail is not True:
347             self.fields.pop('item_detail')
348 
349         if user_detail is not True:
350             self.fields.pop('user_detail')
351 
352     label = serializers.CharField(read_only=True)
353 
354     item_detail = StockItemSerializerBrief(source='item', many=False, read_only=True)
355 
356     user_detail = UserSerializerBrief(source='user', many=False, read_only=True)
357 
358     deltas = serializers.JSONField(read_only=True)
359 
360     class Meta:
361         model = StockItemTracking
362         fields = [
363             'pk',
364             'item',
365             'item_detail',
366             'date',
367             'deltas',
368             'label',
369             'notes',
370             'tracking_type',
371             'user',
372             'user_detail',
373         ]
374 
375         read_only_fields = [
376             'date',
377             'user',
378             'label',
379             'tracking_type',
380         ]
381
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py
--- a/InvenTree/stock/serializers.py
+++ b/InvenTree/stock/serializers.py
@@ -161,6 +161,13 @@
 
     required_tests = serializers.IntegerField(source='required_test_count', read_only=True, required=False)
 
+    purchase_price = serializers.SerializerMethodField()
+
+    def get_purchase_price(self, obj):
+        """ Return purchase_price (Money field) as string (includes currency) """
+
+        return str(obj.purchase_price) if obj.purchase_price else '-'
+
     def __init__(self, *args, **kwargs):
 
         part_detail = kwargs.pop('part_detail', False)
@@ -215,6 +222,7 @@
             'tracking_items',
             'uid',
             'updated',
+            'purchase_price',
         ]
 
         """ These fields are read-only in this context.

{"golden_diff": "diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py\n--- a/InvenTree/stock/serializers.py\n+++ b/InvenTree/stock/serializers.py\n@@ -161,6 +161,13 @@\n \n     required_tests = serializers.IntegerField(source='required_test_count', read_only=True, required=False)\n \n+    purchase_price = serializers.SerializerMethodField()\n+\n+    def get_purchase_price(self, obj):\n+        \"\"\" Return purchase_price (Money field) as string (includes currency) \"\"\"\n+\n+        return str(obj.purchase_price) if obj.purchase_price else '-'\n+\n     def __init__(self, *args, **kwargs):\n \n         part_detail = kwargs.pop('part_detail', False)\n@@ -215,6 +222,7 @@\n             'tracking_items',\n             'uid',\n             'updated',\n+            'purchase_price',\n         ]\n \n         \"\"\" These fields are read-only in this context.\n", "issue": "Add purchase price to Part Stock table\nAdd column `purchase_price` to \"Part Stock\" table and make it sortable.\n", "before_files": [{"content": "\"\"\"\nJSON serializers for Stock app\n\"\"\"\n\nfrom rest_framework import serializers\n\nfrom .models import StockItem, StockLocation\nfrom .models import StockItemTracking\nfrom .models import StockItemAttachment\nfrom .models import StockItemTestResult\n\nfrom django.db.models.functions import Coalesce\n\nfrom django.db.models import Case, When, Value\nfrom django.db.models import BooleanField\nfrom django.db.models import Q\n\nfrom sql_util.utils import SubquerySum, SubqueryCount\n\nfrom decimal import Decimal\n\nfrom datetime import datetime, timedelta\n\nimport common.models\nfrom company.serializers import SupplierPartSerializer\nfrom part.serializers import PartBriefSerializer\nfrom InvenTree.serializers import UserSerializerBrief, InvenTreeModelSerializer\nfrom InvenTree.serializers import InvenTreeAttachmentSerializerField\n\n\nclass LocationBriefSerializer(InvenTreeModelSerializer):\n    \"\"\"\n    Provides a brief serializer for a StockLocation object\n    \"\"\"\n\n    class Meta:\n        model = StockLocation\n        fields = [\n            'pk',\n            'name',\n            'pathstring',\n        ]\n\n\nclass StockItemSerializerBrief(InvenTreeModelSerializer):\n    \"\"\" Brief serializers for a StockItem \"\"\"\n\n    location_name = serializers.CharField(source='location', read_only=True)\n    part_name = serializers.CharField(source='part.full_name', read_only=True)\n    quantity = serializers.FloatField()\n\n    class Meta:\n        model = StockItem\n        fields = [\n            'pk',\n            'uid',\n            'part',\n            'part_name',\n            'supplier_part',\n            'location',\n            'location_name',\n            'quantity',\n        ]\n\n\nclass StockItemSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializer for a StockItem:\n\n    - Includes serialization for the linked part\n    - Includes serialization for the item location\n    \"\"\"\n\n    @staticmethod\n    def prefetch_queryset(queryset):\n        \"\"\"\n        Prefetch related database tables,\n        to reduce database hits.\n        \"\"\"\n\n        return queryset.prefetch_related(\n            'belongs_to',\n            'build',\n            'customer',\n            'sales_order',\n            'supplier_part',\n            'supplier_part__supplier',\n            'supplier_part__manufacturer_part__manufacturer',\n            'allocations',\n            'sales_order_allocations',\n            'location',\n            'part',\n            'tracking_info',\n        )\n\n    @staticmethod\n    def annotate_queryset(queryset):\n        \"\"\"\n        Add some extra annotations to the queryset,\n        performing database queries as efficiently as possible.\n        \"\"\"\n\n        # Annotate the queryset with the total allocated to sales orders\n        queryset = queryset.annotate(\n            allocated=Coalesce(\n                SubquerySum('sales_order_allocations__quantity'), Decimal(0)\n            ) + Coalesce(\n                SubquerySum('allocations__quantity'), Decimal(0)\n            )\n        )\n\n        # Annotate the queryset with the number of tracking items\n        queryset = queryset.annotate(\n            tracking_items=SubqueryCount('tracking_info')\n        )\n\n        # Add flag to indicate if the StockItem has expired\n        queryset = queryset.annotate(\n            expired=Case(\n                When(\n                    StockItem.EXPIRED_FILTER, then=Value(True, output_field=BooleanField()),\n                ),\n                default=Value(False, output_field=BooleanField())\n            )\n        )\n\n        # Add flag to indicate if the StockItem is stale\n        stale_days = common.models.InvenTreeSetting.get_setting('STOCK_STALE_DAYS')\n        stale_date = datetime.now().date() + timedelta(days=stale_days)\n        stale_filter = StockItem.IN_STOCK_FILTER & ~Q(expiry_date=None) & Q(expiry_date__lt=stale_date)\n\n        queryset = queryset.annotate(\n            stale=Case(\n                When(\n                    stale_filter, then=Value(True, output_field=BooleanField()),\n                ),\n                default=Value(False, output_field=BooleanField()),\n            )\n        )\n\n        return queryset\n\n    status_text = serializers.CharField(source='get_status_display', read_only=True)\n\n    supplier_part_detail = SupplierPartSerializer(source='supplier_part', many=False, read_only=True)\n\n    part_detail = PartBriefSerializer(source='part', many=False, read_only=True)\n\n    location_detail = LocationBriefSerializer(source='location', many=False, read_only=True)\n\n    tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True, required=False)\n\n    quantity = serializers.FloatField()\n\n    allocated = serializers.FloatField(source='allocation_count', required=False)\n\n    expired = serializers.BooleanField(required=False, read_only=True)\n\n    stale = serializers.BooleanField(required=False, read_only=True)\n\n    serial = serializers.CharField(required=False)\n\n    required_tests = serializers.IntegerField(source='required_test_count', read_only=True, required=False)\n\n    def __init__(self, *args, **kwargs):\n\n        part_detail = kwargs.pop('part_detail', False)\n        location_detail = kwargs.pop('location_detail', False)\n        supplier_part_detail = kwargs.pop('supplier_part_detail', False)\n        test_detail = kwargs.pop('test_detail', False)\n\n        super(StockItemSerializer, self).__init__(*args, **kwargs)\n\n        if part_detail is not True:\n            self.fields.pop('part_detail')\n\n        if location_detail is not True:\n            self.fields.pop('location_detail')\n\n        if supplier_part_detail is not True:\n            self.fields.pop('supplier_part_detail')\n\n        if test_detail is not True:\n            self.fields.pop('required_tests')\n\n    class Meta:\n        model = StockItem\n        fields = [\n            'allocated',\n            'batch',\n            'belongs_to',\n            'build',\n            'customer',\n            'expired',\n            'expiry_date',\n            'in_stock',\n            'is_building',\n            'link',\n            'location',\n            'location_detail',\n            'notes',\n            'packaging',\n            'part',\n            'part_detail',\n            'pk',\n            'quantity',\n            'required_tests',\n            'sales_order',\n            'serial',\n            'stale',\n            'status',\n            'status_text',\n            'stocktake_date',\n            'supplier_part',\n            'supplier_part_detail',\n            'tracking_items',\n            'uid',\n            'updated',\n        ]\n\n        \"\"\" These fields are read-only in this context.\n        They can be updated by accessing the appropriate API endpoints\n        \"\"\"\n        read_only_fields = [\n            'allocated',\n            'stocktake_date',\n            'stocktake_user',\n            'updated',\n            'in_stock'\n        ]\n\n\nclass StockQuantitySerializer(InvenTreeModelSerializer):\n\n    class Meta:\n        model = StockItem\n        fields = ('quantity',)\n\n\nclass LocationSerializer(InvenTreeModelSerializer):\n    \"\"\" Detailed information about a stock location\n    \"\"\"\n\n    url = serializers.CharField(source='get_absolute_url', read_only=True)\n\n    items = serializers.IntegerField(source='item_count', read_only=True)\n\n    class Meta:\n        model = StockLocation\n        fields = [\n            'pk',\n            'url',\n            'name',\n            'description',\n            'parent',\n            'pathstring',\n            'items',\n        ]\n\n\nclass StockItemAttachmentSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializer for StockItemAttachment model \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        user_detail = kwargs.pop('user_detail', False)\n\n        super().__init__(*args, **kwargs)\n\n        if user_detail is not True:\n            self.fields.pop('user_detail')\n\n    user_detail = UserSerializerBrief(source='user', read_only=True)\n\n    attachment = InvenTreeAttachmentSerializerField(required=True)\n\n    class Meta:\n        model = StockItemAttachment\n\n        fields = [\n            'pk',\n            'stock_item',\n            'attachment',\n            'comment',\n            'upload_date',\n            'user',\n            'user_detail',\n        ]\n\n        read_only_fields = [\n            'upload_date',\n            'user',\n            'user_detail'\n        ]\n\n\nclass StockItemTestResultSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializer for the StockItemTestResult model \"\"\"\n\n    user_detail = UserSerializerBrief(source='user', read_only=True)\n\n    key = serializers.CharField(read_only=True)\n\n    attachment = InvenTreeAttachmentSerializerField(required=False)\n\n    def __init__(self, *args, **kwargs):\n        user_detail = kwargs.pop('user_detail', False)\n\n        super().__init__(*args, **kwargs)\n\n        if user_detail is not True:\n            self.fields.pop('user_detail')\n\n    class Meta:\n        model = StockItemTestResult\n\n        fields = [\n            'pk',\n            'stock_item',\n            'key',\n            'test',\n            'result',\n            'value',\n            'attachment',\n            'notes',\n            'user',\n            'user_detail',\n            'date'\n        ]\n\n        read_only_fields = [\n            'pk',\n            'user',\n            'date',\n        ]\n\n\nclass StockTrackingSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializer for StockItemTracking model \"\"\"\n\n    def __init__(self, *args, **kwargs):\n\n        item_detail = kwargs.pop('item_detail', False)\n        user_detail = kwargs.pop('user_detail', False)\n\n        super().__init__(*args, **kwargs)\n\n        if item_detail is not True:\n            self.fields.pop('item_detail')\n\n        if user_detail is not True:\n            self.fields.pop('user_detail')\n\n    label = serializers.CharField(read_only=True)\n\n    item_detail = StockItemSerializerBrief(source='item', many=False, read_only=True)\n\n    user_detail = UserSerializerBrief(source='user', many=False, read_only=True)\n\n    deltas = serializers.JSONField(read_only=True)\n\n    class Meta:\n        model = StockItemTracking\n        fields = [\n            'pk',\n            'item',\n            'item_detail',\n            'date',\n            'deltas',\n            'label',\n            'notes',\n            'tracking_type',\n            'user',\n            'user_detail',\n        ]\n\n        read_only_fields = [\n            'date',\n            'user',\n            'label',\n            'tracking_type',\n        ]\n", "path": "InvenTree/stock/serializers.py"}], "after_files": [{"content": "\"\"\"\nJSON serializers for Stock app\n\"\"\"\n\nfrom rest_framework import serializers\n\nfrom .models import StockItem, StockLocation\nfrom .models import StockItemTracking\nfrom .models import StockItemAttachment\nfrom .models import StockItemTestResult\n\nfrom django.db.models.functions import Coalesce\n\nfrom django.db.models import Case, When, Value\nfrom django.db.models import BooleanField\nfrom django.db.models import Q\n\nfrom sql_util.utils import SubquerySum, SubqueryCount\n\nfrom decimal import Decimal\n\nfrom datetime import datetime, timedelta\n\nimport common.models\nfrom company.serializers import SupplierPartSerializer\nfrom part.serializers import PartBriefSerializer\nfrom InvenTree.serializers import UserSerializerBrief, InvenTreeModelSerializer\nfrom InvenTree.serializers import InvenTreeAttachmentSerializerField\n\n\nclass LocationBriefSerializer(InvenTreeModelSerializer):\n    \"\"\"\n    Provides a brief serializer for a StockLocation object\n    \"\"\"\n\n    class Meta:\n        model = StockLocation\n        fields = [\n            'pk',\n            'name',\n            'pathstring',\n        ]\n\n\nclass StockItemSerializerBrief(InvenTreeModelSerializer):\n    \"\"\" Brief serializers for a StockItem \"\"\"\n\n    location_name = serializers.CharField(source='location', read_only=True)\n    part_name = serializers.CharField(source='part.full_name', read_only=True)\n    quantity = serializers.FloatField()\n\n    class Meta:\n        model = StockItem\n        fields = [\n            'pk',\n            'uid',\n            'part',\n            'part_name',\n            'supplier_part',\n            'location',\n            'location_name',\n            'quantity',\n        ]\n\n\nclass StockItemSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializer for a StockItem:\n\n    - Includes serialization for the linked part\n    - Includes serialization for the item location\n    \"\"\"\n\n    @staticmethod\n    def prefetch_queryset(queryset):\n        \"\"\"\n        Prefetch related database tables,\n        to reduce database hits.\n        \"\"\"\n\n        return queryset.prefetch_related(\n            'belongs_to',\n            'build',\n            'customer',\n            'sales_order',\n            'supplier_part',\n            'supplier_part__supplier',\n            'supplier_part__manufacturer_part__manufacturer',\n            'allocations',\n            'sales_order_allocations',\n            'location',\n            'part',\n            'tracking_info',\n        )\n\n    @staticmethod\n    def annotate_queryset(queryset):\n        \"\"\"\n        Add some extra annotations to the queryset,\n        performing database queries as efficiently as possible.\n        \"\"\"\n\n        # Annotate the queryset with the total allocated to sales orders\n        queryset = queryset.annotate(\n            allocated=Coalesce(\n                SubquerySum('sales_order_allocations__quantity'), Decimal(0)\n            ) + Coalesce(\n                SubquerySum('allocations__quantity'), Decimal(0)\n            )\n        )\n\n        # Annotate the queryset with the number of tracking items\n        queryset = queryset.annotate(\n            tracking_items=SubqueryCount('tracking_info')\n        )\n\n        # Add flag to indicate if the StockItem has expired\n        queryset = queryset.annotate(\n            expired=Case(\n                When(\n                    StockItem.EXPIRED_FILTER, then=Value(True, output_field=BooleanField()),\n                ),\n                default=Value(False, output_field=BooleanField())\n            )\n        )\n\n        # Add flag to indicate if the StockItem is stale\n        stale_days = common.models.InvenTreeSetting.get_setting('STOCK_STALE_DAYS')\n        stale_date = datetime.now().date() + timedelta(days=stale_days)\n        stale_filter = StockItem.IN_STOCK_FILTER & ~Q(expiry_date=None) & Q(expiry_date__lt=stale_date)\n\n        queryset = queryset.annotate(\n            stale=Case(\n                When(\n                    stale_filter, then=Value(True, output_field=BooleanField()),\n                ),\n                default=Value(False, output_field=BooleanField()),\n            )\n        )\n\n        return queryset\n\n    status_text = serializers.CharField(source='get_status_display', read_only=True)\n\n    supplier_part_detail = SupplierPartSerializer(source='supplier_part', many=False, read_only=True)\n\n    part_detail = PartBriefSerializer(source='part', many=False, read_only=True)\n\n    location_detail = LocationBriefSerializer(source='location', many=False, read_only=True)\n\n    tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True, required=False)\n\n    quantity = serializers.FloatField()\n\n    allocated = serializers.FloatField(source='allocation_count', required=False)\n\n    expired = serializers.BooleanField(required=False, read_only=True)\n\n    stale = serializers.BooleanField(required=False, read_only=True)\n\n    serial = serializers.CharField(required=False)\n\n    required_tests = serializers.IntegerField(source='required_test_count', read_only=True, required=False)\n\n    purchase_price = serializers.SerializerMethodField()\n\n    def get_purchase_price(self, obj):\n        \"\"\" Return purchase_price (Money field) as string (includes currency) \"\"\"\n\n        return str(obj.purchase_price) if obj.purchase_price else '-'\n\n    def __init__(self, *args, **kwargs):\n\n        part_detail = kwargs.pop('part_detail', False)\n        location_detail = kwargs.pop('location_detail', False)\n        supplier_part_detail = kwargs.pop('supplier_part_detail', False)\n        test_detail = kwargs.pop('test_detail', False)\n\n        super(StockItemSerializer, self).__init__(*args, **kwargs)\n\n        if part_detail is not True:\n            self.fields.pop('part_detail')\n\n        if location_detail is not True:\n            self.fields.pop('location_detail')\n\n        if supplier_part_detail is not True:\n            self.fields.pop('supplier_part_detail')\n\n        if test_detail is not True:\n            self.fields.pop('required_tests')\n\n    class Meta:\n        model = StockItem\n        fields = [\n            'allocated',\n            'batch',\n            'belongs_to',\n            'build',\n            'customer',\n            'expired',\n            'expiry_date',\n            'in_stock',\n            'is_building',\n            'link',\n            'location',\n            'location_detail',\n            'notes',\n            'packaging',\n            'part',\n            'part_detail',\n            'pk',\n            'quantity',\n            'required_tests',\n            'sales_order',\n            'serial',\n            'stale',\n            'status',\n            'status_text',\n            'stocktake_date',\n            'supplier_part',\n            'supplier_part_detail',\n            'tracking_items',\n            'uid',\n            'updated',\n            'purchase_price',\n        ]\n\n        \"\"\" These fields are read-only in this context.\n        They can be updated by accessing the appropriate API endpoints\n        \"\"\"\n        read_only_fields = [\n            'allocated',\n            'stocktake_date',\n            'stocktake_user',\n            'updated',\n            'in_stock'\n        ]\n\n\nclass StockQuantitySerializer(InvenTreeModelSerializer):\n\n    class Meta:\n        model = StockItem\n        fields = ('quantity',)\n\n\nclass LocationSerializer(InvenTreeModelSerializer):\n    \"\"\" Detailed information about a stock location\n    \"\"\"\n\n    url = serializers.CharField(source='get_absolute_url', read_only=True)\n\n    items = serializers.IntegerField(source='item_count', read_only=True)\n\n    class Meta:\n        model = StockLocation\n        fields = [\n            'pk',\n            'url',\n            'name',\n            'description',\n            'parent',\n            'pathstring',\n            'items',\n        ]\n\n\nclass StockItemAttachmentSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializer for StockItemAttachment model \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        user_detail = kwargs.pop('user_detail', False)\n\n        super().__init__(*args, **kwargs)\n\n        if user_detail is not True:\n            self.fields.pop('user_detail')\n\n    user_detail = UserSerializerBrief(source='user', read_only=True)\n\n    attachment = InvenTreeAttachmentSerializerField(required=True)\n\n    class Meta:\n        model = StockItemAttachment\n\n        fields = [\n            'pk',\n            'stock_item',\n            'attachment',\n            'comment',\n            'upload_date',\n            'user',\n            'user_detail',\n        ]\n\n        read_only_fields = [\n            'upload_date',\n            'user',\n            'user_detail'\n        ]\n\n\nclass StockItemTestResultSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializer for the StockItemTestResult model \"\"\"\n\n    user_detail = UserSerializerBrief(source='user', read_only=True)\n\n    key = serializers.CharField(read_only=True)\n\n    attachment = InvenTreeAttachmentSerializerField(required=False)\n\n    def __init__(self, *args, **kwargs):\n        user_detail = kwargs.pop('user_detail', False)\n\n        super().__init__(*args, **kwargs)\n\n        if user_detail is not True:\n            self.fields.pop('user_detail')\n\n    class Meta:\n        model = StockItemTestResult\n\n        fields = [\n            'pk',\n            'stock_item',\n            'key',\n            'test',\n            'result',\n            'value',\n            'attachment',\n            'notes',\n            'user',\n            'user_detail',\n            'date'\n        ]\n\n        read_only_fields = [\n            'pk',\n            'user',\n            'date',\n        ]\n\n\nclass StockTrackingSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializer for StockItemTracking model \"\"\"\n\n    def __init__(self, *args, **kwargs):\n\n        item_detail = kwargs.pop('item_detail', False)\n        user_detail = kwargs.pop('user_detail', False)\n\n        super().__init__(*args, **kwargs)\n\n        if item_detail is not True:\n            self.fields.pop('item_detail')\n\n        if user_detail is not True:\n            self.fields.pop('user_detail')\n\n    label = serializers.CharField(read_only=True)\n\n    item_detail = StockItemSerializerBrief(source='item', many=False, read_only=True)\n\n    user_detail = UserSerializerBrief(source='user', many=False, read_only=True)\n\n    deltas = serializers.JSONField(read_only=True)\n\n    class Meta:\n        model = StockItemTracking\n        fields = [\n            'pk',\n            'item',\n            'item_detail',\n            'date',\n            'deltas',\n            'label',\n            'notes',\n            'tracking_type',\n            'user',\n            'user_detail',\n        ]\n\n        read_only_fields = [\n            'date',\n            'user',\n            'label',\n            'tracking_type',\n        ]\n", "path": "InvenTree/stock/serializers.py"}]}