diff --git a/InvenTree/InvenTree/api_version.py b/InvenTree/InvenTree/api_version.py index c89fb1b799..88ffd0c4a4 100644 --- a/InvenTree/InvenTree/api_version.py +++ b/InvenTree/InvenTree/api_version.py @@ -2,17 +2,23 @@ # InvenTree API version -INVENTREE_API_VERSION = 120 +INVENTREE_API_VERSION = 121 """ Increment this API version number whenever there is a significant change to the API that any clients need to know about +v121 -> 2023-06-14 : https://github.com/inventree/InvenTree/pull/4808 + - Adds "ProjectCode" link to Build model + v120 -> 2023-06-07 : https://github.com/inventree/InvenTree/pull/4855 - Major overhaul of the build order API - Adds new BuildLine model +v120 -> 2023-06-12 : https://github.com/inventree/InvenTree/pull/4804 + - Adds 'project_code' field to build order API endpoints + v119 -> 2023-06-01 : https://github.com/inventree/InvenTree/pull/4898 - - Add Metadata to: Part test templates, Part parameters, Part category parameter templates, BOM item substitute, Part relateds, Stock item test result + - Add Metadata to: Part test templates, Part parameters, Part category parameter templates, BOM item substitute, Related Parts, Stock item test result v118 -> 2023-06-01 : https://github.com/inventree/InvenTree/pull/4935 - Adds extra fields for the PartParameterTemplate model @@ -30,6 +36,7 @@ v115 - > 2023-05-18 : https://github.com/inventree/InvenTree/pull/4846 v114 -> 2023-05-16 : https://github.com/inventree/InvenTree/pull/4825 - Adds "delivery_date" to shipments +>>>>>>> inventree/master v113 -> 2023-05-13 : https://github.com/inventree/InvenTree/pull/4800 - Adds API endpoints for scrapping a build output diff --git a/InvenTree/InvenTree/middleware.py b/InvenTree/InvenTree/middleware.py index 540748a4e8..b31f6c96f0 100644 --- a/InvenTree/InvenTree/middleware.py +++ b/InvenTree/InvenTree/middleware.py @@ -14,7 +14,6 @@ from allauth_2fa.middleware import (AllauthTwoFactorMiddleware, from error_report.middleware import ExceptionProcessor from rest_framework.authtoken.models import Token -from common.models import InvenTreeSetting from InvenTree.urls import frontendpatterns logger = logging.getLogger("inventree") @@ -123,6 +122,9 @@ class Check2FAMiddleware(BaseRequire2FAMiddleware): """Check if user is required to have MFA enabled.""" def require_2fa(self, request): """Use setting to check if MFA should be enforced for frontend page.""" + + from common.models import InvenTreeSetting + try: if url_matcher.resolve(request.path[1:]): return InvenTreeSetting.get_setting('LOGIN_ENFORCE_MFA') diff --git a/InvenTree/InvenTree/serializers.py b/InvenTree/InvenTree/serializers.py index b59b2ddf04..8260fb05ef 100644 --- a/InvenTree/InvenTree/serializers.py +++ b/InvenTree/InvenTree/serializers.py @@ -21,7 +21,7 @@ from rest_framework.serializers import DecimalField from rest_framework.utils import model_meta from taggit.serializers import TaggitSerializer -from common.models import InvenTreeSetting +import common.models as common_models from common.settings import currency_code_default, currency_code_mappings from InvenTree.fields import InvenTreeRestURLField, InvenTreeURLField from InvenTree.helpers_model import download_image_from_url @@ -724,7 +724,7 @@ class RemoteImageMixin(metaclass=serializers.SerializerMetaclass): if not url: return - if not InvenTreeSetting.get_setting('INVENTREE_DOWNLOAD_FROM_URL'): + if not common_models.InvenTreeSetting.get_setting('INVENTREE_DOWNLOAD_FROM_URL'): raise ValidationError(_("Downloading images from remote URL is not enabled")) try: diff --git a/InvenTree/InvenTree/unit_test.py b/InvenTree/InvenTree/unit_test.py index 448ca90427..d609dc88f8 100644 --- a/InvenTree/InvenTree/unit_test.py +++ b/InvenTree/InvenTree/unit_test.py @@ -233,6 +233,11 @@ class ExchangeRateMixin: Rate.objects.bulk_create(items) +class InvenTreeTestCase(ExchangeRateMixin, UserMixin, TestCase): + """Testcase with user setup buildin.""" + pass + + class InvenTreeAPITestCase(ExchangeRateMixin, UserMixin, APITestCase): """Base class for running InvenTree API tests.""" @@ -408,8 +413,3 @@ class InvenTreeAPITestCase(ExchangeRateMixin, UserMixin, APITestCase): data.append(entry) return data - - -class InvenTreeTestCase(ExchangeRateMixin, UserMixin, TestCase): - """Testcase with user setup buildin.""" - pass diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index d4e364fcf4..9cb04e09d1 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -31,8 +31,8 @@ from allauth_2fa.views import TwoFactorRemove from djmoney.contrib.exchange.models import ExchangeBackend, Rate from user_sessions.views import SessionDeleteOtherView, SessionDeleteView -from common.models import ColorTheme, InvenTreeSetting -from common.settings import currency_code_default, currency_codes +import common.models as common_models +import common.settings as common_settings from part.models import PartCategory from users.models import RuleSet, check_user_role @@ -514,10 +514,10 @@ class SettingsView(TemplateView): """Add data for template.""" ctx = super().get_context_data(**kwargs).copy() - ctx['settings'] = InvenTreeSetting.objects.all().order_by('key') + ctx['settings'] = common_models.InvenTreeSetting.objects.all().order_by('key') - ctx["base_currency"] = currency_code_default() - ctx["currencies"] = currency_codes + ctx["base_currency"] = common_settings.currency_code_default() + ctx["currencies"] = common_settings.currency_codes ctx["rates"] = Rate.objects.filter(backend="InvenTreeExchange") @@ -622,8 +622,8 @@ class AppearanceSelectView(RedirectView): def get_user_theme(self): """Get current user color theme.""" try: - user_theme = ColorTheme.objects.filter(user=self.request.user).get() - except ColorTheme.DoesNotExist: + user_theme = common_models.ColorTheme.objects.filter(user=self.request.user).get() + except common_models.ColorTheme.DoesNotExist: user_theme = None return user_theme @@ -637,7 +637,7 @@ class AppearanceSelectView(RedirectView): # Create theme entry if user did not select one yet if not user_theme: - user_theme = ColorTheme() + user_theme = common_models.ColorTheme() user_theme.user = request.user user_theme.name = theme diff --git a/InvenTree/build/api.py b/InvenTree/build/api.py index c973884c9d..01c55f5e00 100644 --- a/InvenTree/build/api.py +++ b/InvenTree/build/api.py @@ -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', ] diff --git a/InvenTree/build/migrations/0048_build_project_code.py b/InvenTree/build/migrations/0048_build_project_code.py new file mode 100644 index 0000000000..fcc7153bc7 --- /dev/null +++ b/InvenTree/build/migrations/0048_build_project_code.py @@ -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'), + ), + ] diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index b382e65bda..b4ee51f80e 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -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, diff --git a/InvenTree/build/serializers.py b/InvenTree/build/serializers.py index 1bc881d629..4ea3a1bb18 100644 --- a/InvenTree/build/serializers.py +++ b/InvenTree/build/serializers.py @@ -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. diff --git a/InvenTree/build/templates/build/build_base.html b/InvenTree/build/templates/build/build_base.html index fc692408c6..2f1ea421b6 100644 --- a/InvenTree/build/templates/build/build_base.html +++ b/InvenTree/build/templates/build/build_base.html @@ -108,6 +108,7 @@ src="{% static 'img/blank_image.png' %}" {% trans "Build Description" %} {{ build.title }} + {% include "project_code_data.html" with instance=build %} {% include "barcode_data.html" with instance=build %} diff --git a/InvenTree/build/test_migrations.py b/InvenTree/build/test_migrations.py index af094db7f2..440074d4d7 100644 --- a/InvenTree/build/test_migrations.py +++ b/InvenTree/build/test_migrations.py @@ -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') diff --git a/InvenTree/common/api.py b/InvenTree/common/api.py index 030630778f..abde58501f 100644 --- a/InvenTree/common/api.py +++ b/InvenTree/common/api.py @@ -525,7 +525,7 @@ settings_api_urls = [ path(r'/', NotificationUserSettingsDetail.as_view(), name='api-notification-setting-detail'), # Notification Settings List - re_path(r'^.*$', NotificationUserSettingsList.as_view(), name='api-notifcation-setting-list'), + re_path(r'^.*$', NotificationUserSettingsList.as_view(), name='api-notification-setting-list'), ])), # Global settings diff --git a/InvenTree/common/notifications.py b/InvenTree/common/notifications.py index 07148e6267..6abf8999d8 100644 --- a/InvenTree/common/notifications.py +++ b/InvenTree/common/notifications.py @@ -8,8 +8,8 @@ from django.contrib.auth import get_user_model from django.contrib.auth.models import Group from django.utils.translation import gettext_lazy as _ +import common.models import InvenTree.helpers -from common.models import NotificationEntry, NotificationMessage from InvenTree.ready import isImportingData from plugin import registry from plugin.models import NotificationUserSetting, PluginConfig @@ -247,7 +247,7 @@ class UIMessageNotification(SingleNotificationMethod): def send(self, target): """Send a UI notification to a user.""" - NotificationMessage.objects.create( + common.models.NotificationMessage.objects.create( target_object=self.obj, source_object=target, user=target, @@ -338,7 +338,7 @@ def trigger_notification(obj, category=None, obj_ref='pk', **kwargs): # Check if we have notified recently... delta = timedelta(days=1) - if NotificationEntry.check_recent(category, obj_ref_value, delta): + if common.models.NotificationEntry.check_recent(category, obj_ref_value, delta): logger.info(f"Notification '{category}' has recently been sent for '{str(obj)}' - SKIPPING") return @@ -398,7 +398,7 @@ def trigger_notification(obj, category=None, obj_ref='pk', **kwargs): logger.error(error) # Set delivery flag - NotificationEntry.notify(category, obj_ref_value) + common.models.NotificationEntry.notify(category, obj_ref_value) else: logger.info(f"No possible users for notification '{category}'") diff --git a/InvenTree/common/serializers.py b/InvenTree/common/serializers.py index 8dc911f506..10616c251a 100644 --- a/InvenTree/common/serializers.py +++ b/InvenTree/common/serializers.py @@ -6,9 +6,7 @@ from django.urls import reverse from flags.state import flag_state from rest_framework import serializers -from common.models import (InvenTreeSetting, InvenTreeUserSetting, - NewsFeedEntry, NotesImage, NotificationMessage, - ProjectCode) +import common.models as common_models from InvenTree.helpers import get_objectreference from InvenTree.helpers_model import construct_absolute_url from InvenTree.serializers import (InvenTreeImageSerializerField, @@ -64,7 +62,7 @@ class GlobalSettingsSerializer(SettingsSerializer): class Meta: """Meta options for GlobalSettingsSerializer.""" - model = InvenTreeSetting + model = common_models.InvenTreeSetting fields = [ 'pk', 'key', @@ -85,7 +83,7 @@ class UserSettingsSerializer(SettingsSerializer): class Meta: """Meta options for UserSettingsSerializer.""" - model = InvenTreeUserSetting + model = common_models.InvenTreeUserSetting fields = [ 'pk', 'key', @@ -148,7 +146,7 @@ class NotificationMessageSerializer(InvenTreeModelSerializer): class Meta: """Meta options for NotificationMessageSerializer.""" - model = NotificationMessage + model = common_models.NotificationMessage fields = [ 'pk', 'target', @@ -209,7 +207,7 @@ class NewsFeedEntrySerializer(InvenTreeModelSerializer): class Meta: """Meta options for NewsFeedEntrySerializer.""" - model = NewsFeedEntry + model = common_models.NewsFeedEntry fields = [ 'pk', 'feed_id', @@ -243,7 +241,7 @@ class NotesImageSerializer(InvenTreeModelSerializer): class Meta: """Meta options for NotesImageSerializer.""" - model = NotesImage + model = common_models.NotesImage fields = [ 'pk', 'image', @@ -265,7 +263,7 @@ class ProjectCodeSerializer(InvenTreeModelSerializer): class Meta: """Meta options for ProjectCodeSerializer.""" - model = ProjectCode + model = common_models.ProjectCode fields = [ 'pk', 'code', diff --git a/InvenTree/common/tests.py b/InvenTree/common/tests.py index f854b63514..4402a16933 100644 --- a/InvenTree/common/tests.py +++ b/InvenTree/common/tests.py @@ -226,7 +226,7 @@ class SettingsTest(InvenTreeTestCase): cache.clear() - # Generate a number of new usesr + # Generate a number of new users for idx in range(5): get_user_model().objects.create( username=f"User_{idx}", @@ -417,7 +417,7 @@ class UserSettingsApiTest(InvenTreeAPITestCase): self.assertTrue(str2bool(response.data['value'])) - # Assign some falsey values + # Assign some false(ish) values for v in ['false', False, '0', 'n', 'FalSe']: self.patch( url, @@ -535,7 +535,7 @@ class NotificationUserSettingsApiTest(InvenTreeAPITestCase): def test_api_list(self): """Test list URL.""" - url = reverse('api-notifcation-setting-list') + url = reverse('api-notification-setting-list') self.get(url, expected_code=200) @@ -583,7 +583,7 @@ class PluginSettingsApiTest(PluginMixin, InvenTreeAPITestCase): # Failure mode tests - # Non - exsistant plugin + # Non-existent plugin url = reverse('api-plugin-setting-detail', kwargs={'plugin': 'doesnotexist', 'key': 'doesnotmatter'}) response = self.get(url, expected_code=404) self.assertIn("Plugin 'doesnotexist' not installed", str(response.data)) @@ -729,7 +729,7 @@ class WebhookMessageTests(TestCase): class NotificationTest(InvenTreeAPITestCase): - """Tests for NotificationEntriy.""" + """Tests for NotificationEntry.""" fixtures = [ 'users', @@ -785,7 +785,7 @@ class NotificationTest(InvenTreeAPITestCase): messages = NotificationMessage.objects.all() # As there are three staff users (including the 'test' user) we expect 30 notifications - # However, one user is marked as i nactive + # However, one user is marked as inactive self.assertEqual(messages.count(), 20) # Only 10 messages related to *this* user diff --git a/InvenTree/company/test_api.py b/InvenTree/company/test_api.py index 4f98686111..4fa3ba595a 100644 --- a/InvenTree/company/test_api.py +++ b/InvenTree/company/test_api.py @@ -468,7 +468,7 @@ class SupplierPartTest(InvenTreeAPITestCase): self.assertIsNone(sp.availability_updated) self.assertEqual(sp.available, 0) - # Now, *update* the availabile quantity via the API + # Now, *update* the available quantity via the API self.patch( reverse('api-supplier-part-detail', kwargs={'pk': sp.pk}), { diff --git a/InvenTree/company/test_migrations.py b/InvenTree/company/test_migrations.py index fb38e9e695..1d9a9f88cf 100644 --- a/InvenTree/company/test_migrations.py +++ b/InvenTree/company/test_migrations.py @@ -48,7 +48,8 @@ class TestManufacturerField(MigratorTestCase): # Create an initial part part = Part.objects.create( name='Screw', - description='A single screw' + description='A single screw', + level=0, tree_id=0, lft=0, rght=0 ) # Create a company to act as the supplier diff --git a/InvenTree/order/api.py b/InvenTree/order/api.py index 0e6071ebab..b4a60a95ae 100644 --- a/InvenTree/order/api.py +++ b/InvenTree/order/api.py @@ -13,7 +13,7 @@ from rest_framework import status from rest_framework.exceptions import ValidationError from rest_framework.response import Response -from common.models import InvenTreeSetting, ProjectCode +import common.models as common_models from common.settings import settings from company.models import SupplierPart from generic.states import StatusView @@ -139,7 +139,7 @@ class OrderFilter(rest_filters.FilterSet): return queryset.exclude(status__in=self.Meta.model.get_status_class().OPEN) project_code = rest_filters.ModelChoiceFilter( - queryset=ProjectCode.objects.all(), + queryset=common_models.ProjectCode.objects.all(), field_name='project_code' ) @@ -1457,7 +1457,7 @@ class OrderCalendarExport(ICalFeed): else: ordertype_title = _('Unknown') - return f'{InvenTreeSetting.get_setting("INVENTREE_COMPANY_NAME")} {ordertype_title}' + return f'{common_models.InvenTreeSetting.get_setting("INVENTREE_COMPANY_NAME")} {ordertype_title}' def product_id(self, obj): """Return calendar product id.""" diff --git a/InvenTree/order/models.py b/InvenTree/order/models.py index f9992b4d83..93f431d43f 100644 --- a/InvenTree/order/models.py +++ b/InvenTree/order/models.py @@ -22,6 +22,7 @@ from djmoney.contrib.exchange.models import convert_money from djmoney.money import Money from mptt.models import TreeForeignKey +import common.models as common_models import InvenTree.helpers import InvenTree.ready import InvenTree.tasks @@ -29,7 +30,6 @@ import InvenTree.validators import order.validators import stock.models import users.models as UserModels -from common.models import ProjectCode from common.notifications import InvenTreeNotificationBodies from common.settings import currency_code_default from company.models import Company, Contact, SupplierPart @@ -231,7 +231,11 @@ class Order(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, Reference description = models.CharField(max_length=250, blank=True, verbose_name=_('Description'), help_text=_('Order description (optional)')) - project_code = models.ForeignKey(ProjectCode, on_delete=models.SET_NULL, blank=True, null=True, verbose_name=_('Project Code'), help_text=_('Select project code for this order')) + project_code = models.ForeignKey( + common_models.ProjectCode, on_delete=models.SET_NULL, + blank=True, null=True, + verbose_name=_('Project Code'), help_text=_('Select project code for this order') + ) link = InvenTreeURLField(blank=True, verbose_name=_('Link'), help_text=_('Link to external page')) diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py index d0dee4740b..116f0fb7b0 100644 --- a/InvenTree/order/serializers.py +++ b/InvenTree/order/serializers.py @@ -13,11 +13,11 @@ from rest_framework import serializers from rest_framework.serializers import ValidationError from sql_util.utils import SubqueryCount -import common.serializers import order.models import part.filters import stock.models import stock.serializers +from common.serializers import ProjectCodeSerializer from company.serializers import (CompanyBriefSerializer, ContactSerializer, SupplierPartSerializer) from InvenTree.helpers import (extract_serial_numbers, hash_barcode, normalize, @@ -73,7 +73,7 @@ class AbstractOrderSerializer(serializers.Serializer): responsible_detail = OwnerSerializer(source='responsible', read_only=True, many=False) # Detail for project code field - project_code_detail = common.serializers.ProjectCodeSerializer(source='project_code', read_only=True, many=False) + project_code_detail = ProjectCodeSerializer(source='project_code', read_only=True, many=False) # Boolean field indicating if this order is overdue (Note: must be annotated) overdue = serializers.BooleanField(required=False, read_only=True) diff --git a/InvenTree/plugin/test_api.py b/InvenTree/plugin/test_api.py index 817995de4d..bb4d5b3290 100644 --- a/InvenTree/plugin/test_api.py +++ b/InvenTree/plugin/test_api.py @@ -54,7 +54,7 @@ class PluginDetailAPITest(PluginMixin, InvenTreeAPITestCase): ).data self.assertEqual(data['success'], True) - # valid - github url and packagename + # valid - github url and package name data = self.post( url, { diff --git a/InvenTree/templates/js/translated/build.js b/InvenTree/templates/js/translated/build.js index 9b40bcd87b..3d70cb9347 100644 --- a/InvenTree/templates/js/translated/build.js +++ b/InvenTree/templates/js/translated/build.js @@ -14,6 +14,7 @@ FullCalendar, getFormFieldValue, getTableData, + global_settings, handleFormErrors, handleFormSuccess, imageHoverIcon, @@ -64,7 +65,7 @@ function buildFormFields() { - return { + let fields = { reference: { icon: 'fa-hashtag', }, @@ -76,6 +77,9 @@ function buildFormFields() { }, title: {}, quantity: {}, + project_code: { + icon: 'fa-list', + }, priority: {}, parent: { filters: { @@ -111,6 +115,12 @@ function buildFormFields() { icon: 'fa-users', }, }; + + if (!global_settings.PROJECT_CODES_ENABLED) { + delete fields.project_code; + } + + return fields; } /* @@ -2020,6 +2030,18 @@ function loadBuildTable(table, options) { title: '{% trans "Description" %}', switchable: true, }, + { + field: 'project_code', + title: '{% trans "Project Code" %}', + sortable: true, + switchable: global_settings.PROJECT_CODES_ENABLED, + visible: global_settings.PROJECT_CODES_ENABLED, + formatter: function(value, row) { + if (row.project_code_detail) { + return `${row.project_code_detail.code}`; + } + } + }, { field: 'priority', title: '{% trans "Priority" %}', diff --git a/InvenTree/templates/js/translated/table_filters.js b/InvenTree/templates/js/translated/table_filters.js index c24b90c15c..6b12133a09 100644 --- a/InvenTree/templates/js/translated/table_filters.js +++ b/InvenTree/templates/js/translated/table_filters.js @@ -440,7 +440,7 @@ function getPluginTableFilters() { // Return a dictionary of filters for the "build" table function getBuildTableFilters() { - return { + let filters = { status: { title: '{% trans "Build status" %}', options: buildCodes, @@ -477,6 +477,13 @@ function getBuildTableFilters() { }, }, }; + + if (global_settings.PROJECT_CODES_ENABLED) { + filters['has_project_code'] = constructHasProjectCodeFilter(); + filters['project_code'] = constructProjectCodeFilter(); + } + + return filters; }