diff --git a/src/backend/InvenTree/InvenTree/helpers_model.py b/src/backend/InvenTree/InvenTree/helpers_model.py index 9e0e207e21..16338266d8 100644 --- a/src/backend/InvenTree/InvenTree/helpers_model.py +++ b/src/backend/InvenTree/InvenTree/helpers_model.py @@ -281,25 +281,6 @@ def getModelsWithMixin(mixin_class) -> list: return [x for x in db_models if x is not None and issubclass(x, mixin_class)] -def getModelChoicesWithMixin( - mixin_class, allow_null: bool = False -) -> list[tuple[str, str]]: - """Return a list of model choices (app_label.model_name, verbose_name) for models that inherit from the given mixin class.""" - choices = [] - - if allow_null: - choices.append((None, _('None'))) - - models = getModelsWithMixin(mixin_class) - - for model in models: - label = f'{model._meta.app_label}.{model._meta.model_name}' - name = model._meta.verbose_name - choices.append((label, name)) - - return choices - - def notify_responsible( instance, sender, diff --git a/src/backend/InvenTree/common/filters.py b/src/backend/InvenTree/common/filters.py index 417d4dad90..a7968dbfc1 100644 --- a/src/backend/InvenTree/common/filters.py +++ b/src/backend/InvenTree/common/filters.py @@ -3,6 +3,7 @@ import re from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ValidationError from django.db.models import ( Case, CharField, @@ -77,7 +78,7 @@ def filter_content_type( ct = determine_content_type(content_type) if ct is None: - raise ValueError(f'Invalid content type: {content_type}') + raise ValidationError(f'Invalid content type: {content_type}') q = Q(**{f'{field_name}': ct}) diff --git a/src/backend/InvenTree/common/test_api.py b/src/backend/InvenTree/common/test_api.py index 73e0262750..c9c62d8bef 100644 --- a/src/backend/InvenTree/common/test_api.py +++ b/src/backend/InvenTree/common/test_api.py @@ -121,6 +121,109 @@ class ParameterAPITests(InvenTreeAPITestCase): self.assertEqual(common.models.ParameterTemplate.objects.count(), N) self.assertFalse(common.models.ParameterTemplate.objects.filter(pk=pk).exists()) + def test_template_filters(self): + """Tests for API filters against ParameterTemplate endpoint.""" + from company.models import Company + + # Create some ParameterTemplate objects + t1 = common.models.ParameterTemplate.objects.create( + name='Template A', + description='Template with choices', + choices='apple,banana,cherry', + enabled=True, + ) + + t2 = common.models.ParameterTemplate.objects.create( + name='Template B', + description='Template without choices', + enabled=True, + units='mm', + model_type=Company.get_content_type(), + ) + + t3 = common.models.ParameterTemplate.objects.create( + name='Template C', description='Another template', enabled=False + ) + + url = reverse('api-parameter-template-list') + + # Filter by 'enabled' status + response = self.get(url, data={'enabled': True}) + self.assertEqual(len(response.data), 2) + + response = self.get(url, data={'enabled': False}) + self.assertEqual(len(response.data), 1) + self.assertEqual(response.data[0]['pk'], t3.pk) + + # Filter by 'has_choices' + response = self.get(url, data={'has_choices': True}) + self.assertEqual(len(response.data), 1) + self.assertEqual(response.data[0]['pk'], t1.pk) + + response = self.get(url, data={'has_choices': False}) + self.assertEqual(len(response.data), 2) + + # Filter by 'model_type' + response = self.get(url, data={'model_type': 'company.company'}) + self.assertEqual(len(response.data), 1) + self.assertEqual(response.data[0]['pk'], t2.pk) + + # Filter by 'has_units' + response = self.get(url, data={'has_units': True}) + self.assertEqual(len(response.data), 1) + self.assertEqual(response.data[0]['pk'], t2.pk) + + response = self.get(url, data={'has_units': False}) + self.assertEqual(len(response.data), 2) + + # Filter by 'for_model' + # Note that a 'blank' model_type is considered to match all models + response = self.get(url, data={'for_model': 'part.part'}) + self.assertEqual(len(response.data), 2) + + response = self.get(url, data={'for_model': 'company'}) + self.assertEqual(len(response.data), 3) + + # Create a Parameter against a specific Company instance + company = Company.objects.create( + name='Test Company', description='A company for testing' + ) + + common.models.Parameter.objects.create( + template=t1, + model_type=company.get_content_type(), + model_id=company.pk, + data='apple', + ) + + model_types = {'company': 3, 'part.part': 2, 'order.purchaseorder': 2} + + for model_name, count in model_types.items(): + response = self.get(url, data={'for_model': model_name}) + self.assertEqual( + len(response.data), + count, + f'Incorrect number of templates for model "{model_name}"', + ) + + # Filter with an invalid 'for_model' + response = self.get( + url, data={'for_model': 'invalid.modelname'}, expected_code=400 + ) + + self.assertIn('Invalid content type: invalid.modelname', str(response.data)) + + # Filter the "exists for model" filter + model_types = {'company': 1, 'part.part': 0, 'order.purchaseorder': 0} + + for model_name, count in model_types.items(): + response = self.get(url, data={'exists_for_model': model_name}) + self.assertEqual( + len(response.data), + count, + f'Incorrect number of templates for model "{model_name}"', + ) + def test_parameter_api(self): """Test Parameter API functionality.""" # Create a simple part to test with