From 8663e30f2f612f6021ab73fcb50cadb395436864 Mon Sep 17 00:00:00 2001 From: Xavier Fernandez Date: Wed, 2 Oct 2024 16:29:06 +0200 Subject: [PATCH] job applications: hide job seekers' name from filter for orienteur --- itou/www/apply/forms.py | 28 +++++++++-- itou/www/apply/views/list_views.py | 2 +- .../test_list_prescriptions.ambr | 43 +++++++++-------- tests/www/apply/test_list_prescriptions.py | 46 +++++++++++++++++-- 4 files changed, 91 insertions(+), 28 deletions(-) diff --git a/itou/www/apply/forms.py b/itou/www/apply/forms.py index 8c677f1746..0ea4a884d7 100644 --- a/itou/www/apply/forms.py +++ b/itou/www/apply/forms.py @@ -29,6 +29,7 @@ from itou.users.models import JobSeekerProfile, User from itou.utils import constants as global_constants from itou.utils.emails import redact_email_address +from itou.utils.templatetags.str_filters import mask_unless from itou.utils.types import InclusiveDateRange from itou.utils.validators import validate_nir from itou.utils.widgets import DuetDatePickerWidget @@ -1038,14 +1039,14 @@ def __init__(self, job_applications_qs, *args, **kwargs): self.job_applications_qs = job_applications_qs super().__init__(*args, **kwargs) senders = self.job_applications_qs.get_unique_fk_objects("sender") - self.fields["senders"].choices += self._get_choices_for(senders) + self.fields["senders"].choices += self._get_choices_for_sender(senders) job_seekers = self.job_applications_qs.get_unique_fk_objects("job_seeker") - self.fields["job_seeker"].choices = self._get_choices_for(job_seekers) + self.fields["job_seeker"].choices = self._get_choices_for_job_seeker(job_seekers) self.fields["criteria"].choices = self._get_choices_for_administrativecriteria() self.fields["departments"].choices = self._get_choices_for_departments(job_seekers) self.fields["selected_jobs"].choices = self._get_choices_for_jobs() - def _get_choices_for(self, users): + def _get_choices_for_sender(self, users): users = [user for user in users if user.get_full_name()] users = [(user.id, user.get_full_name().title()) for user in users] return sorted(users, key=lambda user: user[1]) @@ -1131,6 +1132,11 @@ def filter(self, queryset): queryset = queryset.filter(sender_company__id__in=sender_companies) return queryset + def _get_choices_for_job_seeker(self, users): + users = [user for user in users if user.get_full_name()] + users = [(user.id, user.get_full_name().title()) for user in users] + return sorted(users, key=lambda user: user[1]) + def get_sender_prescriber_organization_choices(self): sender_orgs = self.job_applications_qs.get_unique_fk_objects("sender_prescriber_organization") sender_orgs = [sender for sender in sender_orgs if sender.display_name] @@ -1151,10 +1157,24 @@ class PrescriberFilterJobApplicationsForm(CompanyPrescriberFilterJobApplications to_companies = forms.MultipleChoiceField(required=False, label="Organisation", widget=Select2MultipleWidget) - def __init__(self, job_applications_qs, *args, **kwargs): + def __init__(self, job_applications_qs, *args, request_user, **kwargs): + self.request_user = request_user super().__init__(job_applications_qs, *args, **kwargs) self.fields["to_companies"].choices += self.get_to_companies_choices() + def _get_choices_for_job_seeker(self, users): + users = [user for user in users if user.get_full_name()] + users = [ + ( + user.id, + mask_unless( + user.get_full_name().title(), predicate=self.request_user.can_view_personal_information(user) + ), + ) + for user in users + ] + return sorted(users, key=lambda user: user[1]) + def filter(self, queryset): queryset = super().filter(queryset) if to_companies := self.cleaned_data.get("to_companies"): diff --git a/itou/www/apply/views/list_views.py b/itou/www/apply/views/list_views.py index d8ad990430..37aa3c5a1d 100644 --- a/itou/www/apply/views/list_views.py +++ b/itou/www/apply/views/list_views.py @@ -148,7 +148,7 @@ def list_prescriptions(request, template_name="apply/list_prescriptions.html"): """ job_applications = JobApplication.objects.prescriptions_of(request.user, request.current_organization) - filters_form = PrescriberFilterJobApplicationsForm(job_applications, request.GET) + filters_form = PrescriberFilterJobApplicationsForm(job_applications, request.GET, request_user=request.user) # Add related data giving the criteria for adding the necessary annotations job_applications = job_applications.with_list_related_data(criteria=filters_form.data.getlist("criteria", [])) diff --git a/tests/www/apply/__snapshots__/test_list_prescriptions.ambr b/tests/www/apply/__snapshots__/test_list_prescriptions.ambr index b82b7de7ce..75563ff773 100644 --- a/tests/www/apply/__snapshots__/test_list_prescriptions.ambr +++ b/tests/www/apply/__snapshots__/test_list_prescriptions.ambr @@ -300,6 +300,29 @@ ORDER BY "job_applications_jobapplication"."job_seeker_id" ASC ''', }), + dict({ + 'origin': list([ + 'User.is_prescriber_with_authorized_org[users/models.py]', + 'User.can_edit_personal_information[users/models.py]', + 'User.can_view_personal_information[users/models.py]', + 'PrescriberFilterJobApplicationsForm.[www/apply/forms.py]', + 'PrescriberFilterJobApplicationsForm._get_choices_for_job_seeker[www/apply/forms.py]', + 'PrescriberFilterJobApplicationsForm.__init__[www/apply/forms.py]', + 'PrescriberFilterJobApplicationsForm.__init__[www/apply/forms.py]', + 'list_prescriptions[www/apply/views/list_views.py]', + ]), + 'sql': ''' + SELECT %s AS "a" + FROM "prescribers_prescribermembership" + INNER JOIN "users_user" ON ("prescribers_prescribermembership"."user_id" = "users_user"."id") + INNER JOIN "prescribers_prescriberorganization" ON ("prescribers_prescribermembership"."organization_id" = "prescribers_prescriberorganization"."id") + WHERE ("prescribers_prescribermembership"."user_id" = %s + AND "prescribers_prescribermembership"."is_active" + AND "prescribers_prescriberorganization"."is_authorized" + AND "users_user"."is_active") + LIMIT 1 + ''', + }), dict({ 'origin': list([ 'PrescriberFilterJobApplicationsForm._get_choices_for_administrativecriteria[www/apply/forms.py]', @@ -921,26 +944,6 @@ ORDER BY "approvals_approval"."start_at" DESC ''', }), - dict({ - 'origin': list([ - 'User.is_prescriber_with_authorized_org[users/models.py]', - 'User.can_edit_personal_information[users/models.py]', - 'User.can_view_personal_information[users/models.py]', - '_add_user_can_view_personal_information[www/apply/views/list_views.py]', - 'list_prescriptions[www/apply/views/list_views.py]', - ]), - 'sql': ''' - SELECT %s AS "a" - FROM "prescribers_prescribermembership" - INNER JOIN "users_user" ON ("prescribers_prescribermembership"."user_id" = "users_user"."id") - INNER JOIN "prescribers_prescriberorganization" ON ("prescribers_prescribermembership"."organization_id" = "prescribers_prescriberorganization"."id") - WHERE ("prescribers_prescribermembership"."user_id" = %s - AND "prescribers_prescribermembership"."is_active" - AND "prescribers_prescriberorganization"."is_authorized" - AND "users_user"."is_active") - LIMIT 1 - ''', - }), dict({ 'origin': list([ '_add_administrative_criteria[www/apply/views/list_views.py]', diff --git a/tests/www/apply/test_list_prescriptions.py b/tests/www/apply/test_list_prescriptions.py index 7ffc97f5fc..ca3a27f0e1 100644 --- a/tests/www/apply/test_list_prescriptions.py +++ b/tests/www/apply/test_list_prescriptions.py @@ -14,6 +14,7 @@ from itou.utils.urls import add_url_params from tests.job_applications.factories import JobApplicationFactory from tests.prescribers.factories import ( + PrescriberMembershipFactory, PrescriberOrganizationWith2MembershipFactory, ) from tests.users.factories import JobSeekerFactory, PrescriberFactory @@ -98,8 +99,7 @@ def test_as_unauthorized_prescriber(client, snapshot): "job_seekers_views:details", kwargs={"public_id": job_application.job_seeker.public_id} ) assertContains(response, f'S… U…') - # Unfortunately, the job seeker's name is available in the filters - # assertNotContains(response, "Supersecretname") + assertNotContains(response, "Supersecretname") another_job_seeker_detail_url = reverse( "job_seekers_views:details", kwargs={"public_id": another_job_application.job_seeker.public_id} ) @@ -143,7 +143,7 @@ def test_filtered_by_sender(client): def test_filtered_by_job_seeker(client): job_seeker = JobSeekerFactory() - prescriber = PrescriberFactory() + prescriber = PrescriberMembershipFactory(organization__authorized=True).user JobApplicationFactory(sender=prescriber, job_seeker=job_seeker) JobApplicationFactory.create_batch(2, sender=prescriber) client.force_login(prescriber) @@ -153,9 +153,49 @@ def test_filtered_by_job_seeker(client): assert len(applications) == 1 assert applications[0].job_seeker.pk == job_seeker.pk + response = client.get(reverse("apply:list_prescriptions")) + + filters_form = response.context["filters_form"] + assert len(filters_form.fields["job_seeker"].choices) == 3 + + applications = response.context["job_applications_page"].object_list + assert len(applications) == 3 + + +def test_filtered_by_job_seeker_for_unauthorized_prescriber(client): + prescriber = PrescriberFactory() + a_b_job_seeker = JobApplicationFactory( + sender=prescriber, job_seeker__first_name="A_something", job_seeker__last_name="B_something" + ).job_seeker + created_job_seeker = JobApplicationFactory( + sender=prescriber, + job_seeker__created_by=prescriber, + job_seeker__first_name="Zorro", + job_seeker__last_name="Martin", + ).job_seeker + c_d_job_seeker = JobApplicationFactory( + sender=prescriber, + job_seeker__created_by=prescriber, + job_seeker__last_login=timezone.now(), + job_seeker__first_name="C_something", + job_seeker__last_name="D_something", + ).job_seeker + client.force_login(prescriber) + + response = client.get(reverse("apply:list_prescriptions"), {"job_seeker": created_job_seeker.pk}) + applications = response.context["job_applications_page"].object_list + assert len(applications) == 1 + assert applications[0].job_seeker.pk == created_job_seeker.pk + response = client.get(reverse("apply:list_prescriptions")) applications = response.context["job_applications_page"].object_list assert len(applications) == 3 + filters_form = response.context["filters_form"] + assert filters_form.fields["job_seeker"].choices == [ + (a_b_job_seeker.pk, "A… B…"), + (c_d_job_seeker.pk, "C… D…"), + (created_job_seeker.pk, "Zorro Martin"), + ] def test_filtered_by_company(client):