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 commit3e27a3b739
) * Update table filters (cherry picked from commit196c675585
) * Adds API filtering * Bump API version * Hide project code field from build form if project codes not enabled (cherry picked from commit4e210e3dfa
) * 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:
@ -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',
|
||||
]
|
||||
|
||||
|
20
InvenTree/build/migrations/0048_build_project_code.py
Normal file
20
InvenTree/build/migrations/0048_build_project_code.py
Normal 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'),
|
||||
),
|
||||
]
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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')
|
||||
|
Reference in New Issue
Block a user