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,
+ """
+
+ Si le pays de naissance est la France, la commune de naissance est obligatoire.
+
""",
+ 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,
+ """
+
+ Il n'est pas possible de saisir une commune de naissance hors de France.
+
""",
+ 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,
+ """
+
+ Si le pays de naissance est la France, la commune de naissance est obligatoire.
+
""",
+ 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,
+ """
+
+ Il n'est pas possible de saisir une commune de naissance hors de France.
+
""",
+ 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,
+ """
+
+ Il n'est pas possible de saisir une commune de naissance hors de France.
+
""",
+ 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,
+ """
+
+ Si le pays de naissance est la France, la commune de naissance est obligatoire.
+
""",
+ 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,
+ """
+
+ Il n'est pas possible de saisir une commune de naissance hors de France.
+
""",
+ 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,
+ """
+
+ Si le pays de naissance est la France, la commune de naissance est obligatoire.
+
""",
+ html=True,
+ count=1,
+ )