diff --git a/itou/utils/validators.py b/itou/utils/validators.py index 46e4c5104a..41d09af564 100644 --- a/itou/utils/validators.py +++ b/itou/utils/validators.py @@ -93,13 +93,14 @@ def validate_birthdate(birthdate): def validate_birth_location(birth_country, birth_place): - # If birth country is France, then birth place must be provided - if birth_country and birth_country.code == Country.INSEE_CODE_FRANCE and not birth_place: - raise ValidationError("Il n'est pas possible de saisir une commune de naissance hors de France.") - - # If birth country is not France, do not fill a birth place (no ref file) - if birth_country and birth_country.code != Country.INSEE_CODE_FRANCE and birth_place: - raise ValidationError("Si le pays de naissance est la France, la commune de naissance est obligatoire.") + if birth_country: + if birth_country.code == Country.INSEE_CODE_FRANCE: + if not birth_place: + raise ValidationError( + "Si le pays de naissance est la France, la commune de naissance est obligatoire." + ) + elif birth_place: + raise ValidationError("Il n'est pas possible de saisir une commune de naissance hors de France.") AF_NUMBER_PREFIX_REGEXPS = [ diff --git a/tests/www/apply/test_process.py b/tests/www/apply/test_process.py index 0625e0ac95..82bb0621c1 100644 --- a/tests/www/apply/test_process.py +++ b/tests/www/apply/test_process.py @@ -24,7 +24,7 @@ ) from itou.approvals.models import Approval, Suspension -from itou.asp.models import Commune +from itou.asp.models import Commune, Country from itou.cities.models import City from itou.companies.enums import CompanyKind, ContractType, JobDescriptionSource from itou.eligibility.enums import CERTIFIABLE_ADMINISTRATIVE_CRITERIA_KINDS, AuthorKind @@ -49,7 +49,7 @@ ApprovalFactory, SuspensionFactory, ) -from tests.asp.factories import CommuneFactory, CountryFranceFactory +from tests.asp.factories import CommuneFactory, CountryEuropeFactory, CountryFranceFactory from tests.cities.factories import create_test_cities from tests.companies.factories import CompanyFactory, CompanyMembershipFactory, JobDescriptionFactory from tests.eligibility.factories import GEIQEligibilityDiagnosisFactory, IAEEligibilityDiagnosisFactory @@ -2738,6 +2738,57 @@ def test_accept_updated_birthdate_invalidating_birth_place(self, client, mocker) post_data["birthdate"] = birth_place.start_date + datetime.timedelta(days=1) response, _ = self.accept_job_application(client, job_application, post_data=post_data, assert_successful=True) + @freeze_time("2024-09-11") + def test_accept_born_in_france_no_birth_place(self, client, mocker): + birthdate = datetime.date(1995, 12, 27) + job_application = self.create_job_application( + with_certifiable_criteria=True, + job_seeker__jobseeker_profile__birthdate=birthdate, + ) + client.force_login(job_application.to_company.members.get()) + post_data = self._accept_view_post_data(job_application=job_application) + post_data["birth_country"] = Country.objects.get(code=Country.INSEE_CODE_FRANCE).pk + del post_data["birth_place"] + response = client.post( + reverse("apply:accept", kwargs={"job_application_id": job_application.pk}), + headers={"hx-request": "true"}, + data=post_data, + ) + assertContains( + response, + """ + """, + html=True, + count=1, + ) + + @freeze_time("2024-09-11") + def test_accept_born_outside_of_france_specifies_birth_place(self, client, mocker): + birthdate = datetime.date(1995, 12, 27) + job_application = self.create_job_application( + with_certifiable_criteria=True, + job_seeker__jobseeker_profile__birthdate=birthdate, + ) + client.force_login(job_application.to_company.members.get()) + post_data = self._accept_view_post_data(job_application=job_application) + post_data["birth_country"] = CountryEuropeFactory().pk + response = client.post( + reverse("apply:accept", kwargs={"job_application_id": job_application.pk}), + headers={"hx-request": "true"}, + data=post_data, + ) + assertContains( + response, + """ + """, + html=True, + count=1, + ) + class TestProcessTemplates: """ diff --git a/tests/www/employee_record_views/test_create.py b/tests/www/employee_record_views/test_create.py index c9607ee918..276fa07a86 100644 --- a/tests/www/employee_record_views/test_create.py +++ b/tests/www/employee_record_views/test_create.py @@ -232,6 +232,38 @@ def test_birthplace_outside_of_france(self, client): assertRedirects(response, target_url) + def test_born_in_france_no_birthplace(self, client): + client.force_login(self.user) + client.get(self.url) + data = _get_user_form_data(self.job_seeker) + del data["birth_place"] + response = client.post(self.url, data=data) + assertContains( + response, + """ + """, + html=True, + count=1, + ) + + def test_born_outside_of_france_specifies_birthplace(self, client): + client.force_login(self.user) + client.get(self.url) + data = _get_user_form_data(self.job_seeker) + data["birth_country"] = CountryOutsideEuropeFactory().pk + response = client.post(self.url, data=data) + assertContains( + response, + """ + """, + html=True, + count=1, + ) + def test_pass_step_1_without_geolocated_address(self, client): # Do not mess with job seeker profile and geolocation at step 1 # just check user model info diff --git a/tests/www/job_seekers_views/test_create.py b/tests/www/job_seekers_views/test_create.py deleted file mode 100644 index 850816004e..0000000000 --- a/tests/www/job_seekers_views/test_create.py +++ /dev/null @@ -1,79 +0,0 @@ -import datetime - -from django.urls import reverse -from pytest_django.asserts import assertContains, assertRedirects - -from tests.companies.factories import CompanyFactory -from tests.users.factories import ( - JobSeekerFactory, -) -from tests.utils.test import KNOWN_SESSION_KEYS - - -class TestCreateForJobSeeker: - def test_check_nir_with_session(self, client): - company = CompanyFactory(with_membership=True) - user = JobSeekerFactory(jobseeker_profile__birthdate=None, jobseeker_profile__nir="") - reset_url = reverse("companies_views:card", kwargs={"siae_id": company.pk}) - client.force_login(user) - - # Init session - start_url = reverse("apply:start", kwargs={"company_pk": company.pk}) - client.get(start_url) - [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] - - response = client.get( - reverse("job_seekers_views:check_nir_for_job_seeker", kwargs={"session_uuid": job_seeker_session_name}) - ) - - assertContains(response, company.display_name) - assertContains( - response, - f""" - - - Annuler - """, - html=True, - ) - - def test_cannot_check_nir_if_already_set(self, client): - company = CompanyFactory(with_membership=True) - user = JobSeekerFactory( - jobseeker_profile__birthdate=datetime.date(1994, 2, 22), jobseeker_profile__nir="194022734304328" - ) - client.force_login(user) - - # Init session - start_url = reverse("apply:start", kwargs={"company_pk": company.pk}) - client.get(start_url) - [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] - - response = client.get( - reverse("job_seekers_views:check_nir_for_job_seeker", kwargs={"session_uuid": job_seeker_session_name}) - ) - assertRedirects( - response, - reverse( - "job_seekers_views:check_job_seeker_info", - kwargs={"company_pk": company.pk, "job_seeker_public_id": user.public_id}, - ), - ) - - -class TestCreateForSender: - def test_check_nir_with_session(self, client): - company = CompanyFactory(with_membership=True) - client.force_login(company.members.get()) - - # Init session - start_url = reverse("apply:start", kwargs={"company_pk": company.pk}) - client.get(start_url) - [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] - - response = client.get( - reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) - ) - - assertContains(response, company.display_name) diff --git a/tests/www/job_seekers_views/test_create_or_update.py b/tests/www/job_seekers_views/test_create_or_update.py new file mode 100644 index 0000000000..7b1f631b67 --- /dev/null +++ b/tests/www/job_seekers_views/test_create_or_update.py @@ -0,0 +1,291 @@ +import datetime + +import pytest +from django.urls import reverse +from pytest_django.asserts import assertContains, assertRedirects + +from itou.asp.models import Commune, Country +from itou.users.enums import Title +from tests.companies.factories import CompanyFactory +from tests.users.factories import ( + JobSeekerFactory, +) +from tests.utils.test import KNOWN_SESSION_KEYS + + +class TestCreateForJobSeeker: + def test_check_nir_with_session(self, client): + company = CompanyFactory(with_membership=True) + user = JobSeekerFactory(jobseeker_profile__birthdate=None, jobseeker_profile__nir="") + reset_url = reverse("companies_views:card", kwargs={"siae_id": company.pk}) + client.force_login(user) + + # Init session + start_url = reverse("apply:start", kwargs={"company_pk": company.pk}) + client.get(start_url) + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] + + response = client.get( + reverse("job_seekers_views:check_nir_for_job_seeker", kwargs={"session_uuid": job_seeker_session_name}) + ) + + assertContains(response, company.display_name) + assertContains( + response, + f""" + + + Annuler + """, + html=True, + ) + + def test_cannot_check_nir_if_already_set(self, client): + company = CompanyFactory(with_membership=True) + user = JobSeekerFactory( + jobseeker_profile__birthdate=datetime.date(1994, 2, 22), jobseeker_profile__nir="194022734304328" + ) + client.force_login(user) + + # Init session + start_url = reverse("apply:start", kwargs={"company_pk": company.pk}) + client.get(start_url) + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] + + response = client.get( + reverse("job_seekers_views:check_nir_for_job_seeker", kwargs={"session_uuid": job_seeker_session_name}) + ) + assertRedirects( + response, + reverse( + "job_seekers_views:check_job_seeker_info", + kwargs={"company_pk": company.pk, "job_seeker_public_id": user.public_id}, + ), + ) + + +class TestCreateForSender: + def test_check_nir_with_session(self, client): + company = CompanyFactory(with_membership=True) + client.force_login(company.members.get()) + + # Init session + start_url = reverse("apply:start", kwargs={"company_pk": company.pk}) + client.get(start_url) + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] + + response = client.get( + reverse("job_seekers_views:check_nir_for_sender", kwargs={"session_uuid": job_seeker_session_name}) + ) + + assertContains(response, company.display_name) + + @pytest.mark.parametrize( + "born_in_france", [pytest.param(True, id="born_in_france"), pytest.param(False, id="born_outside_france")] + ) + def test_create_step_1(self, born_in_france, client): + company = CompanyFactory(with_membership=True) + client.force_login(company.members.get()) + + # Init session + client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] + + birthdate = datetime.date(1911, 11, 1) + response = client.post( + reverse( + "job_seekers_views:create_job_seeker_step_1_for_sender", + kwargs={"session_uuid": job_seeker_session_name}, + ), + { + "title": Title.M, + "first_name": "Manuel", + "last_name": "Calavera", + "nir": "111116411111144", + "birthdate": birthdate.isoformat(), + **( + { + "birth_place": Commune.objects.by_insee_code_and_period("64483", birthdate).pk, + "birth_country": Country.objects.get(code=Country.INSEE_CODE_FRANCE).pk, + } + if born_in_france + else {"birth_country": Country.objects.exclude(code=Country.INSEE_CODE_FRANCE).first().pk} + ), + }, + ) + assertRedirects( + response, + reverse( + "job_seekers_views:create_job_seeker_step_2_for_sender", + kwargs={"session_uuid": job_seeker_session_name}, + ), + ) + + def test_birth_country_not_france_and_birthplace(self, client): + company = CompanyFactory(with_membership=True) + client.force_login(company.members.get()) + + # Init session + client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] + + birthdate = datetime.date(1911, 11, 1) + response = client.post( + reverse( + "job_seekers_views:create_job_seeker_step_1_for_sender", + kwargs={"session_uuid": job_seeker_session_name}, + ), + { + "title": Title.M, + "first_name": "Manuel", + "last_name": "Calavera", + "nir": "111116411111144", + "birthdate": birthdate.isoformat(), + "birth_place": Commune.objects.by_insee_code_and_period("64483", birthdate).pk, + "birth_country": Country.objects.exclude(code=Country.INSEE_CODE_FRANCE).order_by("?").first().pk, + }, + ) + assertContains( + response, + """ + """, + html=True, + count=1, + ) + + def test_birth_country_france_and_no_birthplace(self, client): + company = CompanyFactory(with_membership=True) + client.force_login(company.members.get()) + + # Init session + client.get(reverse("apply:start", kwargs={"company_pk": company.pk})) + [job_seeker_session_name] = [k for k in client.session.keys() if k not in KNOWN_SESSION_KEYS] + + response = client.post( + reverse( + "job_seekers_views:create_job_seeker_step_1_for_sender", + kwargs={"session_uuid": job_seeker_session_name}, + ), + { + "title": Title.M, + "first_name": "Manuel", + "last_name": "Calavera", + "nir": "111111111111120", + "birthdate": "1911-11-01", + # No birth_place + "birth_country": Country.objects.get(code=Country.INSEE_CODE_FRANCE).pk, + }, + ) + assertContains( + response, + """ + """, + html=True, + count=1, + ) + + +class TestUpdateJobSeekerStep1: + @pytest.mark.parametrize( + "born_in_france", [pytest.param(True, id="born_in_france"), pytest.param(False, id="born_outside_france")] + ) + def test_create_step_1(self, born_in_france, client): + company = CompanyFactory(with_membership=True) + user = company.members.get() + job_seeker = JobSeekerFactory(created_by=user, title=Title.M, jobseeker_profile__nir="111116411111144") + client.force_login(user) + + birthdate = datetime.date(1911, 11, 1) + response = client.post( + reverse( + "job_seekers_views:update_job_seeker_step_1", + kwargs={"job_seeker_public_id": job_seeker.public_id, "company_pk": company.pk}, + ), + { + "title": Title.M, + "first_name": "Manuel", + "last_name": "Calavera", + "birthdate": birthdate.isoformat(), + **( + { + "birth_place": Commune.objects.by_insee_code_and_period("64483", birthdate).pk, + "birth_country": Country.objects.get(code=Country.INSEE_CODE_FRANCE).pk, + } + if born_in_france + else {"birth_country": Country.objects.exclude(code=Country.INSEE_CODE_FRANCE).first().pk} + ), + }, + ) + assertRedirects( + response, + reverse( + "job_seekers_views:update_job_seeker_step_2", + kwargs={"job_seeker_public_id": job_seeker.public_id, "company_pk": company.pk}, + ), + ) + + def test_birth_country_not_france_and_birthplace(self, client): + company = CompanyFactory(with_membership=True) + user = company.members.get() + job_seeker = JobSeekerFactory(created_by=user, title=Title.M, jobseeker_profile__nir="111116411111144") + client.force_login(user) + + birthdate = datetime.date(1911, 11, 1) + response = client.post( + reverse( + "job_seekers_views:update_job_seeker_step_1", + kwargs={"job_seeker_public_id": job_seeker.public_id, "company_pk": company.pk}, + ), + { + "title": Title.M, + "first_name": "Manuel", + "last_name": "Calavera", + "birthdate": birthdate.isoformat(), + "birth_place": Commune.objects.by_insee_code_and_period("64483", birthdate).pk, + "birth_country": Country.objects.exclude(code=Country.INSEE_CODE_FRANCE).order_by("?").first().pk, + }, + ) + assertContains( + response, + """ + """, + html=True, + count=1, + ) + + def test_birth_country_france_and_no_birthplace(self, client): + company = CompanyFactory(with_membership=True) + user = company.members.get() + job_seeker = JobSeekerFactory(created_by=user, title=Title.M, jobseeker_profile__nir="111116411111144") + client.force_login(user) + + response = client.post( + reverse( + "job_seekers_views:update_job_seeker_step_1", + kwargs={"job_seeker_public_id": job_seeker.public_id, "company_pk": company.pk}, + ), + { + "title": Title.M, + "first_name": "Manuel", + "last_name": "Calavera", + "birthdate": "1911-11-01", + # No birth_place + "birth_country": Country.objects.get(code=Country.INSEE_CODE_FRANCE).pk, + }, + ) + assertContains( + response, + """ + """, + html=True, + count=1, + )