We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add "issued_by" and "resposible_for" fields to Build Order table


--- 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/build/serializers.py`
Content:
```
1 """
2 JSON serializers for Build API
3 """
4 
5 # -*- coding: utf-8 -*-
6 from __future__ import unicode_literals
7 
8 from django.db.models import Case, When, Value
9 from django.db.models import BooleanField
10 
11 from rest_framework import serializers
12 
13 from InvenTree.serializers import InvenTreeModelSerializer, InvenTreeAttachmentSerializerField
14 
15 from stock.serializers import StockItemSerializerBrief
16 from stock.serializers import LocationSerializer
17 from part.serializers import PartSerializer, PartBriefSerializer
18 
19 from .models import Build, BuildItem, BuildOrderAttachment
20 
21 
22 class BuildSerializer(InvenTreeModelSerializer):
23     """ Serializes a Build object """
24 
25     url = serializers.CharField(source='get_absolute_url', read_only=True)
26     status_text = serializers.CharField(source='get_status_display', read_only=True)
27 
28     part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
29 
30     quantity = serializers.FloatField()
31 
32     overdue = serializers.BooleanField(required=False, read_only=True)
33 
34     @staticmethod
35     def annotate_queryset(queryset):
36         """
37         Add custom annotations to the BuildSerializer queryset,
38         performing database queries as efficiently as possible.
39 
40         The following annoted fields are added:
41 
42         - overdue: True if the build is outstanding *and* the completion date has past
43 
44         """
45 
46         # Annotate a boolean 'overdue' flag
47 
48         queryset = queryset.annotate(
49             overdue=Case(
50                 When(
51                     Build.OVERDUE_FILTER, then=Value(True, output_field=BooleanField()),
52                 ),
53                 default=Value(False, output_field=BooleanField())
54             )
55         )
56 
57         return queryset
58 
59     def __init__(self, *args, **kwargs):
60         part_detail = kwargs.pop('part_detail', False)
61 
62         super().__init__(*args, **kwargs)
63 
64         if part_detail is not True:
65             self.fields.pop('part_detail')
66 
67     class Meta:
68         model = Build
69         fields = [
70             'pk',
71             'url',
72             'title',
73             'creation_date',
74             'completed',
75             'completion_date',
76             'part',
77             'part_detail',
78             'overdue',
79             'reference',
80             'sales_order',
81             'quantity',
82             'status',
83             'status_text',
84             'target_date',
85             'notes',
86             'link',
87         ]
88 
89         read_only_fields = [
90             'completed',
91             'creation_date',
92             'completion_data',
93             'status',
94             'status_text',
95         ]
96 
97 
98 class BuildItemSerializer(InvenTreeModelSerializer):
99     """ Serializes a BuildItem object """
100 
101     bom_part = serializers.IntegerField(source='bom_item.sub_part.pk', read_only=True)
102     part = serializers.IntegerField(source='stock_item.part.pk', read_only=True)
103     location = serializers.IntegerField(source='stock_item.location.pk', read_only=True)
104 
105     # Extra (optional) detail fields
106     part_detail = PartSerializer(source='stock_item.part', many=False, read_only=True)
107     build_detail = BuildSerializer(source='build', many=False, read_only=True)
108     stock_item_detail = StockItemSerializerBrief(source='stock_item', read_only=True)
109     location_detail = LocationSerializer(source='stock_item.location', read_only=True)
110 
111     quantity = serializers.FloatField()
112 
113     def __init__(self, *args, **kwargs):
114 
115         build_detail = kwargs.pop('build_detail', False)
116         part_detail = kwargs.pop('part_detail', False)
117         location_detail = kwargs.pop('location_detail', False)
118 
119         super().__init__(*args, **kwargs)
120 
121         if not build_detail:
122             self.fields.pop('build_detail')
123 
124         if not part_detail:
125             self.fields.pop('part_detail')
126 
127         if not location_detail:
128             self.fields.pop('location_detail')
129 
130     class Meta:
131         model = BuildItem
132         fields = [
133             'pk',
134             'bom_part',
135             'build',
136             'build_detail',
137             'install_into',
138             'location',
139             'location_detail',
140             'part',
141             'part_detail',
142             'stock_item',
143             'stock_item_detail',
144             'quantity'
145         ]
146 
147 
148 class BuildAttachmentSerializer(InvenTreeModelSerializer):
149     """
150     Serializer for a BuildAttachment
151     """
152 
153     attachment = InvenTreeAttachmentSerializerField(required=True)
154 
155     class Meta:
156         model = BuildOrderAttachment
157 
158         fields = [
159             'pk',
160             'build',
161             'attachment',
162             'comment',
163             'upload_date',
164         ]
165 
166         read_only_fields = [
167             'upload_date',
168         ]
169
```

Path: `InvenTree/build/api.py`
Content:
```
1 """
2 JSON API for the Build app
3 """
4 
5 # -*- coding: utf-8 -*-
6 from __future__ import unicode_literals
7 
8 from django_filters.rest_framework import DjangoFilterBackend
9 from rest_framework import filters
10 from rest_framework import generics
11 
12 from django.conf.urls import url, include
13 
14 from InvenTree.api import AttachmentMixin
15 from InvenTree.helpers import str2bool, isNull
16 from InvenTree.status_codes import BuildStatus
17 
18 from .models import Build, BuildItem, BuildOrderAttachment
19 from .serializers import BuildAttachmentSerializer, BuildSerializer, BuildItemSerializer
20 
21 
22 class BuildList(generics.ListCreateAPIView):
23     """ API endpoint for accessing a list of Build objects.
24 
25     - GET: Return list of objects (with filters)
26     - POST: Create a new Build object
27     """
28 
29     queryset = Build.objects.all()
30     serializer_class = BuildSerializer
31 
32     filter_backends = [
33         DjangoFilterBackend,
34         filters.SearchFilter,
35         filters.OrderingFilter,
36     ]
37 
38     filter_fields = [
39         'sales_order',
40     ]
41 
42     ordering_fields = [
43         'reference',
44         'part__name',
45         'status',
46         'creation_date',
47         'target_date',
48         'completion_date',
49         'quantity',
50     ]
51 
52     search_fields = [
53         'reference',
54         'part__name',
55         'title',
56     ]
57 
58     def get_queryset(self):
59         """
60         Override the queryset filtering,
61         as some of the fields don't natively play nicely with DRF
62         """
63 
64         queryset = super().get_queryset().prefetch_related('part')
65 
66         queryset = BuildSerializer.annotate_queryset(queryset)
67 
68         return queryset
69 
70     def filter_queryset(self, queryset):
71 
72         queryset = super().filter_queryset(queryset)
73 
74         params = self.request.query_params
75 
76         # Filter by "parent"
77         parent = params.get('parent', None)
78 
79         if parent is not None:
80             queryset = queryset.filter(parent=parent)
81 
82         # Filter by "ancestor" builds
83         ancestor = params.get('ancestor', None)
84 
85         if ancestor is not None:
86             try:
87                 ancestor = Build.objects.get(pk=ancestor)
88 
89                 descendants = ancestor.get_descendants(include_self=True)
90 
91                 queryset = queryset.filter(
92                     parent__pk__in=[b.pk for b in descendants]
93                 )
94 
95             except (ValueError, Build.DoesNotExist):
96                 pass
97 
98         # Filter by build status?
99         status = params.get('status', None)
100 
101         if status is not None:
102             queryset = queryset.filter(status=status)
103 
104         # Filter by "pending" status
105         active = params.get('active', None)
106 
107         if active is not None:
108             active = str2bool(active)
109 
110             if active:
111                 queryset = queryset.filter(status__in=BuildStatus.ACTIVE_CODES)
112             else:
113                 queryset = queryset.exclude(status__in=BuildStatus.ACTIVE_CODES)
114 
115         # Filter by "overdue" status?
116         overdue = params.get('overdue', None)
117 
118         if overdue is not None:
119             overdue = str2bool(overdue)
120 
121             if overdue:
122                 queryset = queryset.filter(Build.OVERDUE_FILTER)
123             else:
124                 queryset = queryset.exclude(Build.OVERDUE_FILTER)
125 
126         # Filter by associated part?
127         part = params.get('part', None)
128 
129         if part is not None:
130             queryset = queryset.filter(part=part)
131 
132         # Filter by 'date range'
133         min_date = params.get('min_date', None)
134         max_date = params.get('max_date', None)
135 
136         if min_date is not None and max_date is not None:
137             queryset = Build.filterByDate(queryset, min_date, max_date)
138 
139         return queryset
140 
141     def get_serializer(self, *args, **kwargs):
142 
143         try:
144             part_detail = str2bool(self.request.GET.get('part_detail', None))
145         except AttributeError:
146             part_detail = None
147 
148         kwargs['part_detail'] = part_detail
149 
150         return self.serializer_class(*args, **kwargs)
151 
152 
153 class BuildDetail(generics.RetrieveUpdateAPIView):
154     """ API endpoint for detail view of a Build object """
155 
156     queryset = Build.objects.all()
157     serializer_class = BuildSerializer
158 
159 
160 class BuildItemList(generics.ListCreateAPIView):
161     """ API endpoint for accessing a list of BuildItem objects
162 
163     - GET: Return list of objects
164     - POST: Create a new BuildItem object
165     """
166 
167     serializer_class = BuildItemSerializer
168 
169     def get_serializer(self, *args, **kwargs):
170 
171         try:
172             params = self.request.query_params
173 
174             kwargs['part_detail'] = str2bool(params.get('part_detail', False))
175             kwargs['build_detail'] = str2bool(params.get('build_detail', False))
176             kwargs['location_detail'] = str2bool(params.get('location_detail', False))
177         except AttributeError:
178             pass
179         
180         return self.serializer_class(*args, **kwargs)
181 
182     def get_queryset(self):
183         """ Override the queryset method,
184         to allow filtering by stock_item.part
185         """
186 
187         query = BuildItem.objects.all()
188 
189         query = query.select_related('stock_item')
190         query = query.prefetch_related('stock_item__part')
191         query = query.prefetch_related('stock_item__part__category')
192 
193         return query
194 
195     def filter_queryset(self, queryset):
196 
197         queryset = super().filter_queryset(queryset)
198 
199         params = self.request.query_params
200 
201         # Does the user wish to filter by part?
202         part_pk = params.get('part', None)
203 
204         if part_pk:
205             queryset = queryset.filter(stock_item__part=part_pk)
206 
207         # Filter by output target
208         output = params.get('output', None)
209 
210         if output:
211 
212             if isNull(output):
213                 queryset = queryset.filter(install_into=None)
214             else:
215                 queryset = queryset.filter(install_into=output)
216 
217         return queryset
218 
219     filter_backends = [
220         DjangoFilterBackend,
221     ]
222 
223     filter_fields = [
224         'build',
225         'stock_item',
226         'install_into',
227     ]
228 
229 
230 class BuildAttachmentList(generics.ListCreateAPIView, AttachmentMixin):
231     """
232     API endpoint for listing (and creating) BuildOrderAttachment objects
233     """
234 
235     queryset = BuildOrderAttachment.objects.all()
236     serializer_class = BuildAttachmentSerializer
237 
238 
239 class BuildAttachmentDetail(generics.RetrieveUpdateDestroyAPIView, AttachmentMixin):
240     """
241     Detail endpoint for a BuildOrderAttachment object
242     """
243 
244     queryset = BuildOrderAttachment.objects.all()
245     serializer_class = BuildAttachmentSerializer
246 
247 
248 build_api_urls = [
249 
250     # Attachments
251     url(r'^attachment/', include([
252         url(r'^(?P<pk>\d+)/', BuildAttachmentDetail.as_view(), name='api-build-attachment-detail'),
253         url('^.*$', BuildAttachmentList.as_view(), name='api-build-attachment-list'),
254     ])),
255 
256     # Build Items
257     url(r'^item/', include([
258         url('^.*$', BuildItemList.as_view(), name='api-build-item-list')
259     ])),
260 
261     # Build Detail
262     url(r'^(?P<pk>\d+)/', BuildDetail.as_view(), name='api-build-detail'),
263 
264     # Build List
265     url(r'^.*$', BuildList.as_view(), name='api-build-list'),
266 ]
267
```
--- 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/build/api.py b/InvenTree/build/api.py
--- a/InvenTree/build/api.py
+++ b/InvenTree/build/api.py
@@ -47,6 +47,8 @@
         'target_date',
         'completion_date',
         'quantity',
+        'issued_by',
+        'responsible',
     ]
 
     search_fields = [
diff --git a/InvenTree/build/serializers.py b/InvenTree/build/serializers.py
--- a/InvenTree/build/serializers.py
+++ b/InvenTree/build/serializers.py
@@ -10,11 +10,12 @@
 
 from rest_framework import serializers
 
-from InvenTree.serializers import InvenTreeModelSerializer, InvenTreeAttachmentSerializerField
+from InvenTree.serializers import InvenTreeModelSerializer, InvenTreeAttachmentSerializerField, UserSerializerBrief
 
 from stock.serializers import StockItemSerializerBrief
 from stock.serializers import LocationSerializer
 from part.serializers import PartSerializer, PartBriefSerializer
+from users.serializers import OwnerSerializer
 
 from .models import Build, BuildItem, BuildOrderAttachment
 
@@ -31,6 +32,10 @@
 
     overdue = serializers.BooleanField(required=False, read_only=True)
 
+    issued_by_detail = UserSerializerBrief(source='issued_by', read_only=True)
+
+    responsible_detail = OwnerSerializer(source='responsible', read_only=True)
+
     @staticmethod
     def annotate_queryset(queryset):
         """
@@ -84,6 +89,10 @@
             'target_date',
             'notes',
             'link',
+            'issued_by',
+            'issued_by_detail',
+            'responsible',
+            'responsible_detail',
         ]
 
         read_only_fields = [

{"golden_diff": "diff --git a/InvenTree/build/api.py b/InvenTree/build/api.py\n--- a/InvenTree/build/api.py\n+++ b/InvenTree/build/api.py\n@@ -47,6 +47,8 @@\n         'target_date',\n         'completion_date',\n         'quantity',\n+        'issued_by',\n+        'responsible',\n     ]\n \n     search_fields = [\ndiff --git a/InvenTree/build/serializers.py b/InvenTree/build/serializers.py\n--- a/InvenTree/build/serializers.py\n+++ b/InvenTree/build/serializers.py\n@@ -10,11 +10,12 @@\n \n from rest_framework import serializers\n \n-from InvenTree.serializers import InvenTreeModelSerializer, InvenTreeAttachmentSerializerField\n+from InvenTree.serializers import InvenTreeModelSerializer, InvenTreeAttachmentSerializerField, UserSerializerBrief\n \n from stock.serializers import StockItemSerializerBrief\n from stock.serializers import LocationSerializer\n from part.serializers import PartSerializer, PartBriefSerializer\n+from users.serializers import OwnerSerializer\n \n from .models import Build, BuildItem, BuildOrderAttachment\n \n@@ -31,6 +32,10 @@\n \n     overdue = serializers.BooleanField(required=False, read_only=True)\n \n+    issued_by_detail = UserSerializerBrief(source='issued_by', read_only=True)\n+\n+    responsible_detail = OwnerSerializer(source='responsible', read_only=True)\n+\n     @staticmethod\n     def annotate_queryset(queryset):\n         \"\"\"\n@@ -84,6 +89,10 @@\n             'target_date',\n             'notes',\n             'link',\n+            'issued_by',\n+            'issued_by_detail',\n+            'responsible',\n+            'responsible_detail',\n         ]\n \n         read_only_fields = [\n", "issue": "Add \"issued_by\" and \"resposible_for\" fields to Build Order table\n\n", "before_files": [{"content": "\"\"\"\nJSON serializers for Build API\n\"\"\"\n\n# -*- coding: utf-8 -*-\nfrom __future__ import unicode_literals\n\nfrom django.db.models import Case, When, Value\nfrom django.db.models import BooleanField\n\nfrom rest_framework import serializers\n\nfrom InvenTree.serializers import InvenTreeModelSerializer, InvenTreeAttachmentSerializerField\n\nfrom stock.serializers import StockItemSerializerBrief\nfrom stock.serializers import LocationSerializer\nfrom part.serializers import PartSerializer, PartBriefSerializer\n\nfrom .models import Build, BuildItem, BuildOrderAttachment\n\n\nclass BuildSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializes a Build object \"\"\"\n\n    url = serializers.CharField(source='get_absolute_url', read_only=True)\n    status_text = serializers.CharField(source='get_status_display', read_only=True)\n\n    part_detail = PartBriefSerializer(source='part', many=False, read_only=True)\n\n    quantity = serializers.FloatField()\n\n    overdue = serializers.BooleanField(required=False, read_only=True)\n\n    @staticmethod\n    def annotate_queryset(queryset):\n        \"\"\"\n        Add custom annotations to the BuildSerializer queryset,\n        performing database queries as efficiently as possible.\n\n        The following annoted fields are added:\n\n        - overdue: True if the build is outstanding *and* the completion date has past\n\n        \"\"\"\n\n        # Annotate a boolean 'overdue' flag\n\n        queryset = queryset.annotate(\n            overdue=Case(\n                When(\n                    Build.OVERDUE_FILTER, then=Value(True, output_field=BooleanField()),\n                ),\n                default=Value(False, output_field=BooleanField())\n            )\n        )\n\n        return queryset\n\n    def __init__(self, *args, **kwargs):\n        part_detail = kwargs.pop('part_detail', False)\n\n        super().__init__(*args, **kwargs)\n\n        if part_detail is not True:\n            self.fields.pop('part_detail')\n\n    class Meta:\n        model = Build\n        fields = [\n            'pk',\n            'url',\n            'title',\n            'creation_date',\n            'completed',\n            'completion_date',\n            'part',\n            'part_detail',\n            'overdue',\n            'reference',\n            'sales_order',\n            'quantity',\n            'status',\n            'status_text',\n            'target_date',\n            'notes',\n            'link',\n        ]\n\n        read_only_fields = [\n            'completed',\n            'creation_date',\n            'completion_data',\n            'status',\n            'status_text',\n        ]\n\n\nclass BuildItemSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializes a BuildItem object \"\"\"\n\n    bom_part = serializers.IntegerField(source='bom_item.sub_part.pk', read_only=True)\n    part = serializers.IntegerField(source='stock_item.part.pk', read_only=True)\n    location = serializers.IntegerField(source='stock_item.location.pk', read_only=True)\n\n    # Extra (optional) detail fields\n    part_detail = PartSerializer(source='stock_item.part', many=False, read_only=True)\n    build_detail = BuildSerializer(source='build', many=False, read_only=True)\n    stock_item_detail = StockItemSerializerBrief(source='stock_item', read_only=True)\n    location_detail = LocationSerializer(source='stock_item.location', read_only=True)\n\n    quantity = serializers.FloatField()\n\n    def __init__(self, *args, **kwargs):\n\n        build_detail = kwargs.pop('build_detail', False)\n        part_detail = kwargs.pop('part_detail', False)\n        location_detail = kwargs.pop('location_detail', False)\n\n        super().__init__(*args, **kwargs)\n\n        if not build_detail:\n            self.fields.pop('build_detail')\n\n        if not part_detail:\n            self.fields.pop('part_detail')\n\n        if not location_detail:\n            self.fields.pop('location_detail')\n\n    class Meta:\n        model = BuildItem\n        fields = [\n            'pk',\n            'bom_part',\n            'build',\n            'build_detail',\n            'install_into',\n            'location',\n            'location_detail',\n            'part',\n            'part_detail',\n            'stock_item',\n            'stock_item_detail',\n            'quantity'\n        ]\n\n\nclass BuildAttachmentSerializer(InvenTreeModelSerializer):\n    \"\"\"\n    Serializer for a BuildAttachment\n    \"\"\"\n\n    attachment = InvenTreeAttachmentSerializerField(required=True)\n\n    class Meta:\n        model = BuildOrderAttachment\n\n        fields = [\n            'pk',\n            'build',\n            'attachment',\n            'comment',\n            'upload_date',\n        ]\n\n        read_only_fields = [\n            'upload_date',\n        ]\n", "path": "InvenTree/build/serializers.py"}, {"content": "\"\"\"\nJSON API for the Build app\n\"\"\"\n\n# -*- coding: utf-8 -*-\nfrom __future__ import unicode_literals\n\nfrom django_filters.rest_framework import DjangoFilterBackend\nfrom rest_framework import filters\nfrom rest_framework import generics\n\nfrom django.conf.urls import url, include\n\nfrom InvenTree.api import AttachmentMixin\nfrom InvenTree.helpers import str2bool, isNull\nfrom InvenTree.status_codes import BuildStatus\n\nfrom .models import Build, BuildItem, BuildOrderAttachment\nfrom .serializers import BuildAttachmentSerializer, BuildSerializer, BuildItemSerializer\n\n\nclass BuildList(generics.ListCreateAPIView):\n    \"\"\" API endpoint for accessing a list of Build objects.\n\n    - GET: Return list of objects (with filters)\n    - POST: Create a new Build object\n    \"\"\"\n\n    queryset = Build.objects.all()\n    serializer_class = BuildSerializer\n\n    filter_backends = [\n        DjangoFilterBackend,\n        filters.SearchFilter,\n        filters.OrderingFilter,\n    ]\n\n    filter_fields = [\n        'sales_order',\n    ]\n\n    ordering_fields = [\n        'reference',\n        'part__name',\n        'status',\n        'creation_date',\n        'target_date',\n        'completion_date',\n        'quantity',\n    ]\n\n    search_fields = [\n        'reference',\n        'part__name',\n        'title',\n    ]\n\n    def get_queryset(self):\n        \"\"\"\n        Override the queryset filtering,\n        as some of the fields don't natively play nicely with DRF\n        \"\"\"\n\n        queryset = super().get_queryset().prefetch_related('part')\n\n        queryset = BuildSerializer.annotate_queryset(queryset)\n\n        return queryset\n\n    def filter_queryset(self, queryset):\n\n        queryset = super().filter_queryset(queryset)\n\n        params = self.request.query_params\n\n        # Filter by \"parent\"\n        parent = params.get('parent', None)\n\n        if parent is not None:\n            queryset = queryset.filter(parent=parent)\n\n        # Filter by \"ancestor\" builds\n        ancestor = params.get('ancestor', None)\n\n        if ancestor is not None:\n            try:\n                ancestor = Build.objects.get(pk=ancestor)\n\n                descendants = ancestor.get_descendants(include_self=True)\n\n                queryset = queryset.filter(\n                    parent__pk__in=[b.pk for b in descendants]\n                )\n\n            except (ValueError, Build.DoesNotExist):\n                pass\n\n        # Filter by build status?\n        status = params.get('status', None)\n\n        if status is not None:\n            queryset = queryset.filter(status=status)\n\n        # Filter by \"pending\" status\n        active = params.get('active', None)\n\n        if active is not None:\n            active = str2bool(active)\n\n            if active:\n                queryset = queryset.filter(status__in=BuildStatus.ACTIVE_CODES)\n            else:\n                queryset = queryset.exclude(status__in=BuildStatus.ACTIVE_CODES)\n\n        # Filter by \"overdue\" status?\n        overdue = params.get('overdue', None)\n\n        if overdue is not None:\n            overdue = str2bool(overdue)\n\n            if overdue:\n                queryset = queryset.filter(Build.OVERDUE_FILTER)\n            else:\n                queryset = queryset.exclude(Build.OVERDUE_FILTER)\n\n        # Filter by associated part?\n        part = params.get('part', None)\n\n        if part is not None:\n            queryset = queryset.filter(part=part)\n\n        # Filter by 'date range'\n        min_date = params.get('min_date', None)\n        max_date = params.get('max_date', None)\n\n        if min_date is not None and max_date is not None:\n            queryset = Build.filterByDate(queryset, min_date, max_date)\n\n        return queryset\n\n    def get_serializer(self, *args, **kwargs):\n\n        try:\n            part_detail = str2bool(self.request.GET.get('part_detail', None))\n        except AttributeError:\n            part_detail = None\n\n        kwargs['part_detail'] = part_detail\n\n        return self.serializer_class(*args, **kwargs)\n\n\nclass BuildDetail(generics.RetrieveUpdateAPIView):\n    \"\"\" API endpoint for detail view of a Build object \"\"\"\n\n    queryset = Build.objects.all()\n    serializer_class = BuildSerializer\n\n\nclass BuildItemList(generics.ListCreateAPIView):\n    \"\"\" API endpoint for accessing a list of BuildItem objects\n\n    - GET: Return list of objects\n    - POST: Create a new BuildItem object\n    \"\"\"\n\n    serializer_class = BuildItemSerializer\n\n    def get_serializer(self, *args, **kwargs):\n\n        try:\n            params = self.request.query_params\n\n            kwargs['part_detail'] = str2bool(params.get('part_detail', False))\n            kwargs['build_detail'] = str2bool(params.get('build_detail', False))\n            kwargs['location_detail'] = str2bool(params.get('location_detail', False))\n        except AttributeError:\n            pass\n        \n        return self.serializer_class(*args, **kwargs)\n\n    def get_queryset(self):\n        \"\"\" Override the queryset method,\n        to allow filtering by stock_item.part\n        \"\"\"\n\n        query = BuildItem.objects.all()\n\n        query = query.select_related('stock_item')\n        query = query.prefetch_related('stock_item__part')\n        query = query.prefetch_related('stock_item__part__category')\n\n        return query\n\n    def filter_queryset(self, queryset):\n\n        queryset = super().filter_queryset(queryset)\n\n        params = self.request.query_params\n\n        # Does the user wish to filter by part?\n        part_pk = params.get('part', None)\n\n        if part_pk:\n            queryset = queryset.filter(stock_item__part=part_pk)\n\n        # Filter by output target\n        output = params.get('output', None)\n\n        if output:\n\n            if isNull(output):\n                queryset = queryset.filter(install_into=None)\n            else:\n                queryset = queryset.filter(install_into=output)\n\n        return queryset\n\n    filter_backends = [\n        DjangoFilterBackend,\n    ]\n\n    filter_fields = [\n        'build',\n        'stock_item',\n        'install_into',\n    ]\n\n\nclass BuildAttachmentList(generics.ListCreateAPIView, AttachmentMixin):\n    \"\"\"\n    API endpoint for listing (and creating) BuildOrderAttachment objects\n    \"\"\"\n\n    queryset = BuildOrderAttachment.objects.all()\n    serializer_class = BuildAttachmentSerializer\n\n\nclass BuildAttachmentDetail(generics.RetrieveUpdateDestroyAPIView, AttachmentMixin):\n    \"\"\"\n    Detail endpoint for a BuildOrderAttachment object\n    \"\"\"\n\n    queryset = BuildOrderAttachment.objects.all()\n    serializer_class = BuildAttachmentSerializer\n\n\nbuild_api_urls = [\n\n    # Attachments\n    url(r'^attachment/', include([\n        url(r'^(?P<pk>\\d+)/', BuildAttachmentDetail.as_view(), name='api-build-attachment-detail'),\n        url('^.*$', BuildAttachmentList.as_view(), name='api-build-attachment-list'),\n    ])),\n\n    # Build Items\n    url(r'^item/', include([\n        url('^.*$', BuildItemList.as_view(), name='api-build-item-list')\n    ])),\n\n    # Build Detail\n    url(r'^(?P<pk>\\d+)/', BuildDetail.as_view(), name='api-build-detail'),\n\n    # Build List\n    url(r'^.*$', BuildList.as_view(), name='api-build-list'),\n]\n", "path": "InvenTree/build/api.py"}], "after_files": [{"content": "\"\"\"\nJSON serializers for Build API\n\"\"\"\n\n# -*- coding: utf-8 -*-\nfrom __future__ import unicode_literals\n\nfrom django.db.models import Case, When, Value\nfrom django.db.models import BooleanField\n\nfrom rest_framework import serializers\n\nfrom InvenTree.serializers import InvenTreeModelSerializer, InvenTreeAttachmentSerializerField, UserSerializerBrief\n\nfrom stock.serializers import StockItemSerializerBrief\nfrom stock.serializers import LocationSerializer\nfrom part.serializers import PartSerializer, PartBriefSerializer\nfrom users.serializers import OwnerSerializer\n\nfrom .models import Build, BuildItem, BuildOrderAttachment\n\n\nclass BuildSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializes a Build object \"\"\"\n\n    url = serializers.CharField(source='get_absolute_url', read_only=True)\n    status_text = serializers.CharField(source='get_status_display', read_only=True)\n\n    part_detail = PartBriefSerializer(source='part', many=False, read_only=True)\n\n    quantity = serializers.FloatField()\n\n    overdue = serializers.BooleanField(required=False, read_only=True)\n\n    issued_by_detail = UserSerializerBrief(source='issued_by', read_only=True)\n\n    responsible_detail = OwnerSerializer(source='responsible', read_only=True)\n\n    @staticmethod\n    def annotate_queryset(queryset):\n        \"\"\"\n        Add custom annotations to the BuildSerializer queryset,\n        performing database queries as efficiently as possible.\n\n        The following annoted fields are added:\n\n        - overdue: True if the build is outstanding *and* the completion date has past\n\n        \"\"\"\n\n        # Annotate a boolean 'overdue' flag\n\n        queryset = queryset.annotate(\n            overdue=Case(\n                When(\n                    Build.OVERDUE_FILTER, then=Value(True, output_field=BooleanField()),\n                ),\n                default=Value(False, output_field=BooleanField())\n            )\n        )\n\n        return queryset\n\n    def __init__(self, *args, **kwargs):\n        part_detail = kwargs.pop('part_detail', False)\n\n        super().__init__(*args, **kwargs)\n\n        if part_detail is not True:\n            self.fields.pop('part_detail')\n\n    class Meta:\n        model = Build\n        fields = [\n            'pk',\n            'url',\n            'title',\n            'creation_date',\n            'completed',\n            'completion_date',\n            'part',\n            'part_detail',\n            'overdue',\n            'reference',\n            'sales_order',\n            'quantity',\n            'status',\n            'status_text',\n            'target_date',\n            'notes',\n            'link',\n            'issued_by',\n            'issued_by_detail',\n            'responsible',\n            'responsible_detail',\n        ]\n\n        read_only_fields = [\n            'completed',\n            'creation_date',\n            'completion_data',\n            'status',\n            'status_text',\n        ]\n\n\nclass BuildItemSerializer(InvenTreeModelSerializer):\n    \"\"\" Serializes a BuildItem object \"\"\"\n\n    bom_part = serializers.IntegerField(source='bom_item.sub_part.pk', read_only=True)\n    part = serializers.IntegerField(source='stock_item.part.pk', read_only=True)\n    location = serializers.IntegerField(source='stock_item.location.pk', read_only=True)\n\n    # Extra (optional) detail fields\n    part_detail = PartSerializer(source='stock_item.part', many=False, read_only=True)\n    build_detail = BuildSerializer(source='build', many=False, read_only=True)\n    stock_item_detail = StockItemSerializerBrief(source='stock_item', read_only=True)\n    location_detail = LocationSerializer(source='stock_item.location', read_only=True)\n\n    quantity = serializers.FloatField()\n\n    def __init__(self, *args, **kwargs):\n\n        build_detail = kwargs.pop('build_detail', False)\n        part_detail = kwargs.pop('part_detail', False)\n        location_detail = kwargs.pop('location_detail', False)\n\n        super().__init__(*args, **kwargs)\n\n        if not build_detail:\n            self.fields.pop('build_detail')\n\n        if not part_detail:\n            self.fields.pop('part_detail')\n\n        if not location_detail:\n            self.fields.pop('location_detail')\n\n    class Meta:\n        model = BuildItem\n        fields = [\n            'pk',\n            'bom_part',\n            'build',\n            'build_detail',\n            'install_into',\n            'location',\n            'location_detail',\n            'part',\n            'part_detail',\n            'stock_item',\n            'stock_item_detail',\n            'quantity'\n        ]\n\n\nclass BuildAttachmentSerializer(InvenTreeModelSerializer):\n    \"\"\"\n    Serializer for a BuildAttachment\n    \"\"\"\n\n    attachment = InvenTreeAttachmentSerializerField(required=True)\n\n    class Meta:\n        model = BuildOrderAttachment\n\n        fields = [\n            'pk',\n            'build',\n            'attachment',\n            'comment',\n            'upload_date',\n        ]\n\n        read_only_fields = [\n            'upload_date',\n        ]\n", "path": "InvenTree/build/serializers.py"}, {"content": "\"\"\"\nJSON API for the Build app\n\"\"\"\n\n# -*- coding: utf-8 -*-\nfrom __future__ import unicode_literals\n\nfrom django_filters.rest_framework import DjangoFilterBackend\nfrom rest_framework import filters\nfrom rest_framework import generics\n\nfrom django.conf.urls import url, include\n\nfrom InvenTree.api import AttachmentMixin\nfrom InvenTree.helpers import str2bool, isNull\nfrom InvenTree.status_codes import BuildStatus\n\nfrom .models import Build, BuildItem, BuildOrderAttachment\nfrom .serializers import BuildAttachmentSerializer, BuildSerializer, BuildItemSerializer\n\n\nclass BuildList(generics.ListCreateAPIView):\n    \"\"\" API endpoint for accessing a list of Build objects.\n\n    - GET: Return list of objects (with filters)\n    - POST: Create a new Build object\n    \"\"\"\n\n    queryset = Build.objects.all()\n    serializer_class = BuildSerializer\n\n    filter_backends = [\n        DjangoFilterBackend,\n        filters.SearchFilter,\n        filters.OrderingFilter,\n    ]\n\n    filter_fields = [\n        'sales_order',\n    ]\n\n    ordering_fields = [\n        'reference',\n        'part__name',\n        'status',\n        'creation_date',\n        'target_date',\n        'completion_date',\n        'quantity',\n        'issued_by',\n        'responsible',\n    ]\n\n    search_fields = [\n        'reference',\n        'part__name',\n        'title',\n    ]\n\n    def get_queryset(self):\n        \"\"\"\n        Override the queryset filtering,\n        as some of the fields don't natively play nicely with DRF\n        \"\"\"\n\n        queryset = super().get_queryset().prefetch_related('part')\n\n        queryset = BuildSerializer.annotate_queryset(queryset)\n\n        return queryset\n\n    def filter_queryset(self, queryset):\n\n        queryset = super().filter_queryset(queryset)\n\n        params = self.request.query_params\n\n        # Filter by \"parent\"\n        parent = params.get('parent', None)\n\n        if parent is not None:\n            queryset = queryset.filter(parent=parent)\n\n        # Filter by \"ancestor\" builds\n        ancestor = params.get('ancestor', None)\n\n        if ancestor is not None:\n            try:\n                ancestor = Build.objects.get(pk=ancestor)\n\n                descendants = ancestor.get_descendants(include_self=True)\n\n                queryset = queryset.filter(\n                    parent__pk__in=[b.pk for b in descendants]\n                )\n\n            except (ValueError, Build.DoesNotExist):\n                pass\n\n        # Filter by build status?\n        status = params.get('status', None)\n\n        if status is not None:\n            queryset = queryset.filter(status=status)\n\n        # Filter by \"pending\" status\n        active = params.get('active', None)\n\n        if active is not None:\n            active = str2bool(active)\n\n            if active:\n                queryset = queryset.filter(status__in=BuildStatus.ACTIVE_CODES)\n            else:\n                queryset = queryset.exclude(status__in=BuildStatus.ACTIVE_CODES)\n\n        # Filter by \"overdue\" status?\n        overdue = params.get('overdue', None)\n\n        if overdue is not None:\n            overdue = str2bool(overdue)\n\n            if overdue:\n                queryset = queryset.filter(Build.OVERDUE_FILTER)\n            else:\n                queryset = queryset.exclude(Build.OVERDUE_FILTER)\n\n        # Filter by associated part?\n        part = params.get('part', None)\n\n        if part is not None:\n            queryset = queryset.filter(part=part)\n\n        # Filter by 'date range'\n        min_date = params.get('min_date', None)\n        max_date = params.get('max_date', None)\n\n        if min_date is not None and max_date is not None:\n            queryset = Build.filterByDate(queryset, min_date, max_date)\n\n        return queryset\n\n    def get_serializer(self, *args, **kwargs):\n\n        try:\n            part_detail = str2bool(self.request.GET.get('part_detail', None))\n        except AttributeError:\n            part_detail = None\n\n        kwargs['part_detail'] = part_detail\n\n        return self.serializer_class(*args, **kwargs)\n\n\nclass BuildDetail(generics.RetrieveUpdateAPIView):\n    \"\"\" API endpoint for detail view of a Build object \"\"\"\n\n    queryset = Build.objects.all()\n    serializer_class = BuildSerializer\n\n\nclass BuildItemList(generics.ListCreateAPIView):\n    \"\"\" API endpoint for accessing a list of BuildItem objects\n\n    - GET: Return list of objects\n    - POST: Create a new BuildItem object\n    \"\"\"\n\n    serializer_class = BuildItemSerializer\n\n    def get_serializer(self, *args, **kwargs):\n\n        try:\n            params = self.request.query_params\n\n            kwargs['part_detail'] = str2bool(params.get('part_detail', False))\n            kwargs['build_detail'] = str2bool(params.get('build_detail', False))\n            kwargs['location_detail'] = str2bool(params.get('location_detail', False))\n        except AttributeError:\n            pass\n        \n        return self.serializer_class(*args, **kwargs)\n\n    def get_queryset(self):\n        \"\"\" Override the queryset method,\n        to allow filtering by stock_item.part\n        \"\"\"\n\n        query = BuildItem.objects.all()\n\n        query = query.select_related('stock_item')\n        query = query.prefetch_related('stock_item__part')\n        query = query.prefetch_related('stock_item__part__category')\n\n        return query\n\n    def filter_queryset(self, queryset):\n\n        queryset = super().filter_queryset(queryset)\n\n        params = self.request.query_params\n\n        # Does the user wish to filter by part?\n        part_pk = params.get('part', None)\n\n        if part_pk:\n            queryset = queryset.filter(stock_item__part=part_pk)\n\n        # Filter by output target\n        output = params.get('output', None)\n\n        if output:\n\n            if isNull(output):\n                queryset = queryset.filter(install_into=None)\n            else:\n                queryset = queryset.filter(install_into=output)\n\n        return queryset\n\n    filter_backends = [\n        DjangoFilterBackend,\n    ]\n\n    filter_fields = [\n        'build',\n        'stock_item',\n        'install_into',\n    ]\n\n\nclass BuildAttachmentList(generics.ListCreateAPIView, AttachmentMixin):\n    \"\"\"\n    API endpoint for listing (and creating) BuildOrderAttachment objects\n    \"\"\"\n\n    queryset = BuildOrderAttachment.objects.all()\n    serializer_class = BuildAttachmentSerializer\n\n\nclass BuildAttachmentDetail(generics.RetrieveUpdateDestroyAPIView, AttachmentMixin):\n    \"\"\"\n    Detail endpoint for a BuildOrderAttachment object\n    \"\"\"\n\n    queryset = BuildOrderAttachment.objects.all()\n    serializer_class = BuildAttachmentSerializer\n\n\nbuild_api_urls = [\n\n    # Attachments\n    url(r'^attachment/', include([\n        url(r'^(?P<pk>\\d+)/', BuildAttachmentDetail.as_view(), name='api-build-attachment-detail'),\n        url('^.*$', BuildAttachmentList.as_view(), name='api-build-attachment-list'),\n    ])),\n\n    # Build Items\n    url(r'^item/', include([\n        url('^.*$', BuildItemList.as_view(), name='api-build-item-list')\n    ])),\n\n    # Build Detail\n    url(r'^(?P<pk>\\d+)/', BuildDetail.as_view(), name='api-build-detail'),\n\n    # Build List\n    url(r'^.*$', BuildList.as_view(), name='api-build-list'),\n]\n", "path": "InvenTree/build/api.py"}]}