diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5b6fd718c..c286a162a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,10 @@ Unreleased ---------- * nothing unreleased +[4.23.9] +---------- +* feat: Add option to show soft deleted group memberships in django admin + [4.23.8] ---------- * feat: updating enterprise-customer-support endpoint diff --git a/enterprise/__init__.py b/enterprise/__init__.py index 70734e28c..adeac8bbd 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.23.8" +__version__ = "4.23.9" diff --git a/enterprise/admin/__init__.py b/enterprise/admin/__init__.py index e4849bbaa..cc3defcb2 100644 --- a/enterprise/admin/__init__.py +++ b/enterprise/admin/__init__.py @@ -1254,7 +1254,8 @@ class EnterpriseGroupMembershipAdmin(admin.ModelAdmin): Django admin for EnterpriseGroupMembership model. """ model = models.EnterpriseGroupMembership - list_display = ('group', 'membership_user',) + list_display = ('group', 'membership_user', 'is_removed') + list_filter = ('is_removed',) search_fields = ( 'uuid', 'group__uuid', @@ -1268,6 +1269,22 @@ class EnterpriseGroupMembershipAdmin(admin.ModelAdmin): 'pending_enterprise_customer_user', ) + def get_queryset(self, request): + """ + Return a QuerySet of all model instances. + """ + show_soft_deletes = request.GET.get('is_removed__exact', False) + if show_soft_deletes: + qs = self.model.all_objects.get_queryset() + else: + qs = self.model.available_objects.get_queryset() + + ordering = self.get_ordering(request) + if ordering: + qs = qs.order_by(*ordering) + + return qs + @admin.register(models.LearnerCreditEnterpriseCourseEnrollment) class LearnerCreditEnterpriseCourseEnrollmentAdmin(admin.ModelAdmin): diff --git a/tests/test_admin/test_admin.py b/tests/test_admin/test_admin.py index 2a38bdca3..5566f78ca 100644 --- a/tests/test_admin/test_admin.py +++ b/tests/test_admin/test_admin.py @@ -1,12 +1,13 @@ """ Tests for the IntegratedChannelAPIRequest admin module in `edx-enterprise`. """ - from django.contrib.admin.sites import AdminSite from django.db import connection -from django.test import TestCase +from django.test import RequestFactory, TestCase from django.test.utils import CaptureQueriesContext +from enterprise.admin import EnterpriseGroupMembershipAdmin +from enterprise.models import EnterpriseGroupMembership from integrated_channels.integrated_channel.admin import IntegratedChannelAPIRequestLogAdmin from integrated_channels.integrated_channel.models import IntegratedChannelAPIRequestLogs from test_utils import factories @@ -75,3 +76,50 @@ def test_get_queryset_optimization(self): _ = log_entry.payload self.assertEqual(len(queries), 1, "Accessing unselected field should cause exactly one additional query") + + +class EnterpriseGroupMembershipAdminTest(TestCase): + """ + Test the admin functionality for the EnterpriseGroupMembership model. + """ + + def setUp(self): + """ + Set up the test environment by creating a test admin instance and sample data. + """ + self.site = AdminSite() + self.admin = EnterpriseGroupMembershipAdmin(EnterpriseGroupMembership, self.site) + + self.egm_1 = factories.EnterpriseGroupMembershipFactory() + self.egm_2 = factories.EnterpriseGroupMembershipFactory() + + # mark enterprise group membership 2 to is_removed = True + self.egm_2.is_removed = True + self.egm_2.save() + + def test_get_queryset(self): + """ + Test that the get_queryset method optimizes query by using select_related and only selecting specified fields. + """ + request = RequestFactory().get("/") + # ROUND 1 - set `is_removed__exact` = False + request.GET = {'is_removed__exact': False} + queryset = self.admin.get_queryset(request) + results = list(queryset) + + # should only return the non-removed results + self.assertEqual(len(results), 1) + result_egm = results[0] + self.assertEqual(self.egm_1.uuid, result_egm.uuid) + # ensure is_removed = True, i.e. matching egm_1 + self.assertEqual(self.egm_1.is_removed, result_egm.is_removed) + + # ROUND 2 - set `is_removed__exact` = True + request.GET = {'is_removed__exact': True} + queryset = self.admin.get_queryset(request) + results = list(queryset) + + # should return both results + self.assertEqual(len(results), 2) + # is_removed value should differ between the two results + self.assertNotEqual(results[0].is_removed, results[1].is_removed)