Skip to content

Commit

Permalink
fix(apply forms): ensure clean birthdate for CertifiedCriteriaInfoReq…
Browse files Browse the repository at this point in the history
…uiredForm

fix accept candidate: clean birthdate when passing to CertifiedCriteriaInfoRequiredForm
  • Loading branch information
calummackervoy committed Aug 8, 2024
1 parent bc64a35 commit 602fde2
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 3 deletions.
8 changes: 7 additions & 1 deletion itou/www/apply/views/common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.db import transaction
from django.forms import ValidationError
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render
from django.template.response import TemplateResponse
Expand Down Expand Up @@ -51,7 +52,12 @@ def _accept(request, siae, job_seeker, error_url, back_url, template_name, extra
tally_form_query=f"jobapplication={job_application.pk}" if job_application else None,
)
forms.append(form_personal_data)
birthdate = form_personal_data.data.get("birthdate")
try:
birthdate = JobSeekerPersonalDataForm.base_fields["birthdate"].clean(
form_personal_data.data.get("birthdate")
)
except ValidationError:
pass # will be presented to user later

form_user_address = JobSeekerAddressForm(instance=job_seeker, data=request.POST or None)
forms.append(form_user_address)
Expand Down
57 changes: 55 additions & 2 deletions tests/www/apply/test_forms.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, timedelta

import pytest
from django.urls import reverse
Expand All @@ -13,7 +13,12 @@
from tests.companies.factories import JobDescriptionFactory
from tests.job_applications.factories import JobApplicationFactory
from tests.jobs.factories import create_test_romes_and_appellations
from tests.users.factories import JobSeekerFactory, JobSeekerProfileFactory, PrescriberFactory
from tests.users.factories import (
JobSeekerFactory,
JobSeekerProfileFactory,
JobSeekerWithAddressFactory,
PrescriberFactory,
)
from tests.utils.test import TestCase


Expand Down Expand Up @@ -399,3 +404,51 @@ def _response(kind):
for kind in (CompanyKind.EA, CompanyKind.EATT, CompanyKind.GEIQ, CompanyKind.OPCS):
assertNotContains(_response(kind), self.HELP_START_AT)
assertNotContains(_response(kind), self.HELP_END_AT)


class CertifiedCriteriaInfoRequiredFormTest(TestCase):
def test_submit_valid(self):
job_seeker = JobSeekerWithAddressFactory(
with_ban_api_mocked_address=True,
born_in_france=True,
)

birth_place = job_seeker.jobseeker_profile.birth_place
valid_birthdate = birth_place.start_date + timedelta(days=1)

form_data = {
"address_line_1": job_seeker.address_line_1,
"address_line_2": job_seeker.address_line_2,
"post_code": job_seeker.post_code,
"city": job_seeker.city,
"insee_code": job_seeker.insee_code,
"ban_api_resolved_address": job_seeker.geocoding_address,
"birth_country": job_seeker.jobseeker_profile.birth_country.id,
"birth_place": job_seeker.jobseeker_profile.birth_place.id,
}
form = apply_forms.CertifiedCriteriaInfoRequiredForm(data=form_data, birthdate=valid_birthdate)
assert form.is_valid()

def test_submit_commune_invalid_commune_lookup(self):
job_seeker = JobSeekerWithAddressFactory(with_ban_api_mocked_address=True, born_in_france=True)

birth_place = job_seeker.jobseeker_profile.birth_place
early_date = birth_place.start_date - timedelta(days=1)

form_data = {
"address_line_1": job_seeker.address_line_1,
"address_line_2": job_seeker.address_line_2,
"post_code": job_seeker.post_code,
"city": job_seeker.city,
"insee_code": job_seeker.insee_code,
"ban_api_resolved_address": job_seeker.geocoding_address,
"birth_country": job_seeker.jobseeker_profile.birth_country.id,
"birth_place": birth_place.id,
}
form = apply_forms.CertifiedCriteriaInfoRequiredForm(data=form_data, birthdate=early_date)
assert not form.is_valid()

expected_msg = (
f"Le code INSEE {birth_place.code} n'est pas référencé par l'ASP en date du {early_date:%d/%m/%Y}"
)
assert form.errors["birth_place"] == [expected_msg]
46 changes: 46 additions & 0 deletions tests/www/apply/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -2567,6 +2567,52 @@ def test_criteria__criteria_not_certificable(self):
del post_data["birth_place"]
self.accept_job_application(job_application=job_application, post_data=post_data, assert_successful=True)

def test_accept_updated_birthdate_invalidating_birth_place(self):
# tests for a rare case where the birthdate will be cleaned for sharing between forms during the accept process
job_application = self.create_job_application()

# required assumptions for the test case
assert self.company.is_subject_to_eligibility_rules
ed = EligibilityDiagnosis.objects.last_considered_valid(job_seeker=self.job_seeker, for_siae=self.company)
assert ed and ed.criteria_certification_available()

employer = self.company.members.first()
self.client.force_login(employer)

birth_place = Commune.objects.filter(start_date__gt=datetime.date(1901, 12, 1)).first()
assert birth_place is not None # required by test

early_date = birth_place.start_date - datetime.timedelta(days=1)
post_data = {
"birth_place": birth_place.pk,
"birthdate": early_date, # invalidates birth_place lookup, triggering error
}

response, _ = self.accept_job_application(
job_application=job_application, post_data=post_data, assert_successful=False
)
expected_msg = (
f"Le code INSEE {birth_place.code} n'est pas référencé par l'ASP en date du {early_date:%d/%m/%Y}"
)

assert response.context.get("form_personal_data").errors == {}
assert response.context.get("form_certified_criteria").errors["birth_place"] == [expected_msg]

# assert malformed birthdate does not crash view
post_data["birthdate"] = "20240-001-001"
response, _ = self.accept_job_application(
job_application=job_application, post_data=post_data, assert_successful=False
)

assert response.context.get("form_personal_data").errors == {"birthdate": ["Saisissez une date valide."]}
assert response.context.get("form_certified_criteria").errors == {}

# test that fixing the birthdate fixes the form submission
post_data["birthdate"] = birth_place.start_date + datetime.timedelta(days=1)
response, _ = self.accept_job_application(
job_application=job_application, post_data=post_data, assert_successful=True
)


class ProcessTemplatesTest(TestCase):
"""
Expand Down

0 comments on commit 602fde2

Please sign in to comment.