2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-17 04:25:42 +00:00

Add ProjectCode support to build orders (#4808)

* Add "project_code" field to Build model

* Add "project_code" field to Build model

* build javascript updates

(cherry picked from commit 3e27a3b739)

* Update table filters

(cherry picked from commit 196c675585)

* Adds API filtering

* Bump API version

* Hide project code field from build form if project codes not enabled

(cherry picked from commit 4e210e3dfa)

* refactoring to attempt to fix circular imports

* Upgrade django-test-migrations package

* Fix broken import

* Further fixes for unit tests

* Update unit tests for migration files

* Fix typo in build.js

* Migration test updates

- Need to specify MPTT stuff

* Fix build.js

* Fix migration order

* Update API version
This commit is contained in:
Oliver
2023-06-14 11:23:35 +10:00
committed by GitHub
parent c8365ccd0c
commit 00bb740216
23 changed files with 151 additions and 62 deletions

View File

@ -16,6 +16,7 @@ from InvenTree.helpers import str2bool, isNull, DownloadFile
from InvenTree.status_codes import BuildStatus, BuildStatusGroups
from InvenTree.mixins import CreateAPI, RetrieveUpdateDestroyAPI, ListCreateAPI
import common.models
import build.admin
import build.serializers
from build.models import Build, BuildLine, BuildItem, BuildOrderAttachment
@ -89,6 +90,21 @@ class BuildFilter(rest_filters.FilterSet):
lookup_expr="iexact"
)
project_code = rest_filters.ModelChoiceFilter(
queryset=common.models.ProjectCode.objects.all(),
field_name='project_code'
)
has_project_code = rest_filters.BooleanFilter(label='has_project_code', method='filter_has_project_code')
def filter_has_project_code(self, queryset, name, value):
"""Filter by whether or not the order has a project code"""
if str2bool(value):
return queryset.exclude(project_code=None)
else:
return queryset.filter(project_code=None)
class BuildList(APIDownloadMixin, ListCreateAPI):
"""API endpoint for accessing a list of Build objects.
@ -114,11 +130,13 @@ class BuildList(APIDownloadMixin, ListCreateAPI):
'completed',
'issued_by',
'responsible',
'project_code',
'priority',
]
ordering_field_aliases = {
'reference': ['reference_int', 'reference'],
'project_code': ['project_code__code'],
}
ordering = '-reference'
@ -129,6 +147,7 @@ class BuildList(APIDownloadMixin, ListCreateAPI):
'part__name',
'part__IPN',
'part__description',
'project_code__code',
'priority',
]

View File

@ -0,0 +1,20 @@
# Generated by Django 3.2.19 on 2023-05-14 09:22
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('common', '0019_projectcode_metadata'),
('build', '0047_auto_20230606_1058'),
]
operations = [
migrations.AddField(
model_name='build',
name='project_code',
field=models.ForeignKey(blank=True, help_text='Project code for this build order', null=True, on_delete=django.db.models.deletion.SET_NULL, to='common.projectcode', verbose_name='Project Code'),
),
]

View File

@ -32,9 +32,10 @@ import InvenTree.models
import InvenTree.ready
import InvenTree.tasks
import common.models
from common.notifications import trigger_notification
from plugin.events import trigger_event
import common.notifications
import part.models
import stock.models
import users.models
@ -301,6 +302,14 @@ class Build(MPTTModel, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.
help_text=_('Priority of this build order')
)
project_code = models.ForeignKey(
common.models.ProjectCode,
on_delete=models.SET_NULL,
blank=True, null=True,
verbose_name=_('Project Code'),
help_text=_('Project code for this build order'),
)
def sub_builds(self, cascade=True):
"""Return all Build Order objects under this one."""
if cascade:
@ -547,7 +556,7 @@ class Build(MPTTModel, InvenTree.models.InvenTreeBarcodeMixin, InvenTree.models.
}
}
common.notifications.trigger_notification(
trigger_notification(
build,
'build.completed',
targets=targets,

View File

@ -23,6 +23,7 @@ from InvenTree.status_codes import StockStatus
from stock.models import generate_batch_code, StockItem, StockLocation
from stock.serializers import StockItemSerializerBrief, LocationSerializer
from common.serializers import ProjectCodeSerializer
import part.filters
from part.serializers import BomItemSerializer, PartSerializer, PartBriefSerializer
from users.serializers import OwnerSerializer
@ -49,6 +50,8 @@ class BuildSerializer(InvenTreeModelSerializer):
'parent',
'part',
'part_detail',
'project_code',
'project_code_detail',
'overdue',
'reference',
'sales_order',
@ -90,6 +93,8 @@ class BuildSerializer(InvenTreeModelSerializer):
barcode_hash = serializers.CharField(read_only=True)
project_code_detail = ProjectCodeSerializer(source='project_code', many=False, read_only=True)
@staticmethod
def annotate_queryset(queryset):
"""Add custom annotations to the BuildSerializer queryset, performing database queries as efficiently as possible.

View File

@ -108,6 +108,7 @@ src="{% static 'img/blank_image.png' %}"
<td>{% trans "Build Description" %}</td>
<td>{{ build.title }}</td>
</tr>
{% include "project_code_data.html" with instance=build %}
{% include "barcode_data.html" with instance=build %}
</table>

View File

@ -19,22 +19,15 @@ class TestForwardMigrations(MigratorTestCase):
name='Widget',
description='Buildable Part',
active=True,
level=0, lft=0, rght=0, tree_id=0,
)
with self.assertRaises(TypeError):
# Cannot set the 'assembly' field as it hasn't been added to the db schema
Part.objects.create(
name='Blorb',
description='ABCDE',
assembly=True
)
Build = self.old_state.apps.get_model('build', 'build')
Build.objects.create(
part=buildable_part,
title='A build of some stuff',
quantity=50
quantity=50,
)
def test_items_exist(self):
@ -67,7 +60,8 @@ class TestReferenceMigration(MigratorTestCase):
part = Part.objects.create(
name='Part',
description='A test part'
description='A test part',
level=0, lft=0, rght=0, tree_id=0,
)
Build = self.old_state.apps.get_model('build', 'build')