From 9e8c24edcca48e60a37c30b4331c27191613ef0e Mon Sep 17 00:00:00 2001 From: Antoine LAURENT Date: Tue, 14 Jan 2025 09:53:24 +0100 Subject: [PATCH] users: Add links in admin to gps objects lists --- itou/gps/admin.py | 10 +++++ itou/users/admin.py | 21 ++++++++- tests/gps/test_admin.py | 44 +++++++++++++++++++ .../users/__snapshots__/test_admin_views.ambr | 25 ++++++++++- 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 tests/gps/test_admin.py diff --git a/itou/gps/admin.py b/itou/gps/admin.py index 306f77f625..a64e95c68b 100644 --- a/itou/gps/admin.py +++ b/itou/gps/admin.py @@ -40,6 +40,11 @@ class FollowUpGroupMembershipAdmin(ItouModelAdmin): readonly_fields = ["member", "creator", "created_at", "updated_at", "ended_at", "created_in_bulk"] ordering = ["-created_at"] + def lookup_allowed(self, lookup, value, request): + if lookup in ["follow_up_group__beneficiary"]: + return True + return super().lookup_allowed(lookup, value) + @admin.register(models.FollowUpGroup) class FollowUpGroupAdmin(ItouModelAdmin): @@ -55,6 +60,11 @@ class FollowUpGroupAdmin(ItouModelAdmin): inlines = (MemberInline,) + def lookup_allowed(self, lookup, value, request): + if lookup in ["memberships__member"]: + return True + return super().lookup_allowed(lookup, value) + @admin.display(description="Département") def beneficiary_department(self, obj): return obj.beneficiary.department diff --git a/itou/users/admin.py b/itou/users/admin.py index ba069917ac..763c2216bf 100644 --- a/itou/users/admin.py +++ b/itou/users/admin.py @@ -17,7 +17,7 @@ from itou.companies.models import CompanyMembership from itou.eligibility.models import EligibilityDiagnosis, GEIQEligibilityDiagnosis from itou.geo.models import QPV -from itou.gps.models import FranceTravailContact +from itou.gps.models import FollowUpGroup, FollowUpGroupMembership, FranceTravailContact from itou.institutions.models import InstitutionMembership from itou.job_applications.models import JobApplication from itou.prescribers.models import PrescriberMembership @@ -40,6 +40,7 @@ get_admin_view_link, get_structure_view_link, ) +from itou.utils.urls import add_url_params class EmailAddressInline(ItouTabularInline): @@ -336,6 +337,7 @@ class Media: "is_staff", "jobseeker_profile_link", "disabled_notifications", + "follow_up_groups_or_members", ) add_fieldsets = ( @@ -429,6 +431,22 @@ def disabled_notifications(self, obj): ) return "Aucune" + @admin.display(description="GPS") + def follow_up_groups_or_members(self, obj): + if obj.pk is None: + return self.get_empty_value_display() + if obj.is_job_seeker: + url = add_url_params( + reverse("admin:gps_followupgroupmembership_changelist"), {"follow_up_group__beneficiary": obj.id} + ) + count = FollowUpGroupMembership.objects.filter(follow_up_group__beneficiary=obj).count() + return format_html('Liste des professionnels suivant ce bénéficiaire ({})', url, count) + if obj.is_prescriber or obj.is_employer: + url = add_url_params(reverse("admin:gps_followupgroup_changelist"), {"memberships__member": obj.id}) + count = FollowUpGroup.objects.filter(memberships__member=obj).count() + return format_html('Liste des groupes de suivi de cet utilisateur ({}) ', url, count) + return "" + @admin.action(description="Désactiver le compte IC / PC pour changement prescripteur <-> employeur") def free_sso_email(self, request, queryset): try: @@ -511,6 +529,7 @@ def get_fieldsets(self, request, obj=None): "identity_provider", "jobseeker_profile_link", "disabled_notifications", + "follow_up_groups_or_members", ) }, ), diff --git a/tests/gps/test_admin.py b/tests/gps/test_admin.py new file mode 100644 index 0000000000..832c23ce1e --- /dev/null +++ b/tests/gps/test_admin.py @@ -0,0 +1,44 @@ +import pytest +from django.urls import reverse +from pytest_django.asserts import assertContains + +from itou.utils.urls import add_url_params +from tests.gps.factories import FollowUpGroupFactory, FollowUpGroupMembershipFactory +from tests.users.factories import EmployerFactory, JobSeekerFactory, PrescriberFactory + + +def test_job_seeker_admin_link(admin_client): + job_seeker = JobSeekerFactory() + + response = admin_client.get(reverse("admin:users_user_change", args=(job_seeker.pk,))) + expected_url = add_url_params( + reverse("admin:gps_followupgroupmembership_changelist"), {"follow_up_group__beneficiary": job_seeker.pk} + ) + assertContains(response, expected_url) + assertContains(response, "Liste des professionnels suivant ce bénéficiaire (0)") + + FollowUpGroupFactory(beneficiary=job_seeker, memberships=2) + response = admin_client.get(reverse("admin:users_user_change", args=(job_seeker.pk,))) + assertContains(response, "Liste des professionnels suivant ce bénéficiaire (2)") + + # Assert that the lookup works + admin_client.get(expected_url) + + +@pytest.mark.parametrize("user_factory", [EmployerFactory, PrescriberFactory]) +def test_participant_admin_link(admin_client, user_factory): + participant = user_factory() + + response = admin_client.get(reverse("admin:users_user_change", args=(participant.pk,))) + expected_url = add_url_params( + reverse("admin:gps_followupgroup_changelist"), {"memberships__member": participant.pk} + ) + assertContains(response, expected_url) + assertContains(response, "Liste des groupes de suivi de cet utilisateur (0)") + + FollowUpGroupMembershipFactory.create_batch(2, member=participant) + response = admin_client.get(reverse("admin:users_user_change", args=(participant.pk,))) + assertContains(response, "Liste des groupes de suivi de cet utilisateur (2)") + + # Assert that the lookup works + admin_client.get(expected_url) diff --git a/tests/users/__snapshots__/test_admin_views.ambr b/tests/users/__snapshots__/test_admin_views.ambr index e28535308b..75b03e9a93 100644 --- a/tests/users/__snapshots__/test_admin_views.ambr +++ b/tests/users/__snapshots__/test_admin_views.ambr @@ -1,7 +1,7 @@ # serializer version: 1 # name: test_num_queries dict({ - 'num_queries': 25, + 'num_queries': 26, 'queries': list([ dict({ 'origin': list([ @@ -661,6 +661,29 @@ "communications_notificationrecord"."name" ASC ''', }), + dict({ + 'origin': list([ + 'ItouUserAdmin.follow_up_groups_or_members[users/admin.py]', + 'VariableNode[admin/includes/fieldset.html]', + 'IfNode[admin/includes/fieldset.html]', + 'IfNode[admin/includes/fieldset.html]', + 'ForNode[admin/includes/fieldset.html]', + 'ForNode[admin/includes/fieldset.html]', + 'IncludeNode[admin/change_form.html]', + 'ForNode[admin/change_form.html]', + 'BlockNode[admin/change_form.html]', + 'BlockNode[admin/base.html]', + 'ExtendsNode[admin/base_site.html]', + 'ExtendsNode[admin/change_form.html]', + 'ExtendsNode[admin/users/change_user_form.html]', + ]), + 'sql': ''' + SELECT COUNT(*) AS "__count" + FROM "gps_followupgroup" + INNER JOIN "gps_followupgroupmembership" ON ("gps_followupgroup"."id" = "gps_followupgroupmembership"."follow_up_group_id") + WHERE "gps_followupgroupmembership"."member_id" = %s + ''', + }), dict({ 'origin': list([ 'Atomic.__enter__[/django/db/transaction.py]',