diff --git a/lego/apps/companies/filters.py b/lego/apps/companies/filters.py index 3a259ad40..27ecb52a1 100644 --- a/lego/apps/companies/filters.py +++ b/lego/apps/companies/filters.py @@ -1,6 +1,28 @@ +from django.db.models import Q from django_filters import BooleanFilter, CharFilter, FilterSet -from lego.apps.companies.models import CompanyInterest, Semester +from lego.apps.companies.models import Company, CompanyInterest, Semester + + +class CompanyFilterSet(FilterSet): + search = CharFilter(method="filter_search") + show_inactive = BooleanFilter(method="filter_inactive") + + def filter_search(self, queryset, name, value): + if not value: + return queryset + return queryset.filter( + Q(name__icontains=value) | Q(description__icontains=value) + ) + + def filter_inactive(self, queryset, name, value): + if not value: + return queryset.filter(active=True) + return queryset + + class Meta: + model = Company + fields = ["search", "show_inactive"] class SemesterFilterSet(FilterSet): diff --git a/lego/apps/companies/tests/test_filters.py b/lego/apps/companies/tests/test_filters.py new file mode 100644 index 000000000..71f018597 --- /dev/null +++ b/lego/apps/companies/tests/test_filters.py @@ -0,0 +1,55 @@ +from django.test import TestCase + +from lego.apps.companies.filters import CompanyFilterSet +from lego.apps.companies.models import Company + + +class CompanyFilterSetTestCase(TestCase): + fixtures = ["test_abakus_groups.yaml", "test_users.yaml", "test_companies.yaml"] + + def setUp(self): + self.filter_set = CompanyFilterSet + self.queryset = Company.objects.all() + + def test_filter_search_empty(self): + """Test that empty search returns full queryset""" + filtered = self.filter_set({"search": ""}, queryset=self.queryset).qs + self.assertEqual(filtered.count(), self.queryset.count()) + + def test_filter_search_name(self): + """Test search filtering by company name""" + filtered = self.filter_set({"search": "Facebook"}, queryset=self.queryset).qs + self.assertEqual(filtered.count(), 1) + self.assertEqual(filtered.first().name, "Facebook") + + def test_filter_search_description(self): + """Test search filtering by company description""" + filtered = self.filter_set( + {"search": "webkom er webkom"}, queryset=self.queryset + ).qs + self.assertEqual(filtered.count(), 1) + self.assertEqual(filtered.first().name, "Webkom") + + def test_filter_search_case_insensitive(self): + """Test that search is case insensitive""" + filtered = self.filter_set({"search": "facebook"}, queryset=self.queryset).qs + self.assertEqual(filtered.count(), 1) + self.assertEqual(filtered.first().name, "Facebook") + + def test_filter_inactive_default(self): + """Test that by default only active companies are shown""" + company = Company.objects.get(name="Facebook") + company.active = False + company.save() + + filtered = self.filter_set({"show_inactive": False}, queryset=self.queryset).qs + self.assertNotIn(company, filtered) + + def test_filter_show_inactive(self): + """Test that inactive companies can be shown when requested""" + company = Company.objects.get(name="Facebook") + company.active = False + company.save() + + filtered = self.filter_set({"show_inactive": True}, queryset=self.queryset).qs + self.assertIn(company, filtered) diff --git a/lego/apps/companies/views.py b/lego/apps/companies/views.py index 70b498bfb..dcd9ae5a9 100644 --- a/lego/apps/companies/views.py +++ b/lego/apps/companies/views.py @@ -7,7 +7,11 @@ from rest_framework.mixins import ListModelMixin, RetrieveModelMixin from rest_framework.response import Response -from lego.apps.companies.filters import CompanyInterestFilterSet, SemesterFilterSet +from lego.apps.companies.filters import ( + CompanyFilterSet, + CompanyInterestFilterSet, + SemesterFilterSet, +) from lego.apps.companies.models import ( Company, CompanyContact, @@ -72,6 +76,7 @@ class CompanyViewSet( viewsets.GenericViewSet, ): queryset = Company.objects.all().filter(active=True) + filterset_class = CompanyFilterSet ordering = "name" def get_serializer_class(self):