-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PASS IAE: La date de début du contrat doit être avant la date de fin du PASS [GEN-2225] #5248
base: master
Are you sure you want to change the base?
PASS IAE: La date de début du contrat doit être avant la date de fin du PASS [GEN-2225] #5248
Conversation
Useful when providing a DateField to a query on the DateTimeField of another field/model Refactor make_date_timezone_aware to use duck-typing
…igibility Extend tests for PASS IAE validity
last_valid_diagnosis = self.last_considered_valid(job_seeker, for_siae=for_siae) | ||
return job_seeker.has_valid_approval_for_date(on_date) or ( | ||
last_valid_diagnosis and last_valid_diagnosis.expires_at > make_date_timezone_aware(on_date) | ||
) | ||
|
||
def last_considered_valid(self, job_seeker, for_siae=None, prefetch=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
last_considered_valid
m'a posé une colle. Avec la description du méthode, il me semble que c'est la dernière diagnostique aujourd'hui pour le candidat, et que je devrais ignorer le fonction dans ce PR.
Par contre, c'est utilisé dans le modèle JobApplication
, dans get_eligibility_diagnosis
:
return EligibilityDiagnosis.objects.last_considered_valid(self.job_seeker, for_siae=self.to_company)
Donc c'est possible que ce fonction devrait produire une éligibilité qui est valide pour la date de début d'embauche
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pour moi, tu devrais ajouter un on_date=
dans last_considered_valid()
car c'est utilisé dans hire_confirmation()
@@ -423,6 +423,14 @@ def test_list_for_siae_filtered_by_eligibility_validated(self, client): | |||
response = client.get(reverse("apply:list_for_siae"), {"eligibility_validated": True}) | |||
assert response.context["job_applications_page"].object_list == [] | |||
|
|||
# Not expired, but will be when the job starts | |||
diagnosis.expires_at = timezone.now() + datetime.timedelta(days=1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dans une autre assertion de ce test nous avons :
# Make sure the diagnostic expired - it should be ignored
diagnosis.expires_at = timezone.now() - datetime.timedelta(days=diagnosis.EXPIRATION_DELAY_MONTHS * 31 + 1)
Pourquoi on utilise EXPIRATION_DELAY_MONTHS
ici ? Ce n'est pas considéré expiré si c'est un jour après le expires_at
?
@@ -6,3 +6,15 @@ | |||
def monday_of_the_week(value=None): | |||
the_day = timezone.localdate(value) | |||
return the_day - datetime.timedelta(days=the_day.weekday()) | |||
|
|||
|
|||
def make_date_timezone_aware(value, tz=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Je ne suis pas certain de saisir l'utilité de cette fonction, on ne devrait avoir que des datetime avec timezone dans notre base de code et notre base de données.
Reste la conversion de date vers datetime: le mieux serait sûrement de ne pas avoir à les comparer et pour cela #5210 me semble une meilleure solution et devrait faciliter cette PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Je rejoins le commentaire de @xavfernandez sur le make_date_timezone_aware
.
Pour le reste, par contre, c'est top 👍
last_valid_diagnosis = self.last_considered_valid(job_seeker, for_siae=for_siae) | ||
return job_seeker.has_valid_approval_for_date(on_date) or ( | ||
last_valid_diagnosis and last_valid_diagnosis.expires_at > make_date_timezone_aware(on_date) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
C'est dommage : avec ton changement on fait les requêtes de last_considered_valid
même si job_seeker.has_valid_approval_for_date(on_date)
est True
last_valid_diagnosis = self.last_considered_valid(job_seeker, for_siae=for_siae) | |
return job_seeker.has_valid_approval_for_date(on_date) or ( | |
last_valid_diagnosis and last_valid_diagnosis.expires_at > make_date_timezone_aware(on_date) | |
) | |
if job_seeker.has_valid_approval_for_date(on_date): | |
return True | |
last_valid_diagnosis = self.last_considered_valid(job_seeker, for_siae=for_siae) | |
return last_valide_diagnosis and last_valid_diagnosis.expires_at > make_date_timezone_aware(on_date) | |
) |
last_valid_diagnosis = self.last_considered_valid(job_seeker, for_siae=for_siae) | ||
return job_seeker.has_valid_approval_for_date(on_date) or ( | ||
last_valid_diagnosis and last_valid_diagnosis.expires_at > make_date_timezone_aware(on_date) | ||
) | ||
|
||
def last_considered_valid(self, job_seeker, for_siae=None, prefetch=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pour moi, tu devrais ajouter un on_date=
dans last_considered_valid()
car c'est utilisé dans hire_confirmation()
return self.to_company.is_subject_to_eligibility_rules and not self.job_seeker.has_valid_diagnosis( | ||
for_siae=self.to_company | ||
return ( | ||
not self.hiring_without_approval |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bien vu pour cet ajout
@@ -511,6 +512,10 @@ def latest_common_approval(self): | |||
|
|||
return self.latest_approval or self.latest_pe_approval | |||
|
|||
def has_valid_approval_for_date(self, on_date): | |||
on_date = make_date_timezone_aware(on_date) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
quel intérêt de rendre on_date
et self.latest_approval.end_at
aware pour les comparer.
Ce ne sont pas tous les deux des datetime.date
?
diagnosis = IAEEligibilityDiagnosisFactory( | ||
from_prescriber=True, job_seeker=self.job_seeker, expires_at=expires_at | ||
) | ||
has_considered_valid = EligibilityDiagnosis.objects.has_considered_valid(job_seeker=diagnosis.job_seeker) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pourquoi ne pas mettre les assert sans variable intermédiaire ?
assert EligibilityDiagnosis.objects.has_considered_valid(job_seeker=diagnosis.job_seeker)
@@ -957,7 +810,7 @@ | |||
# --- | |||
# name: TestProcessViews.test_details_for_company_from_approval[job application detail for company] | |||
dict({ | |||
'num_queries': 21, | |||
'num_queries': 23, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ici 'et à d'autres endroits) on ajoute 2 queries, est-ce normal ?
je n'ai pas creusé, mais c'est sans doute le point que j'ai relevé plus haut sur la requête faite en plus
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Désolé je fait l'hélicoptère mais vu qu'on en a discuté (longuement) en atelier métier bah j'ai dû y mettre mon nez plus que je le voulais et le changement me semble bizarre par rapport au problème de base.
On se retrouve à faire des modifications profondes au niveau de la logique de validité des diagnostiques et des PASS IAE (et donc de si on en délivre un nouveau ou pas, toussa toussa) alors que le problème c'est de bloquer les employeurs d'accepter une candidature avec une date de début après la date de fin d'un PASS IAE et qui j'ai l'impression (mais je suis peut-être naif) pourrais se régler avec quelques lignes dans JobApplication.accept()
:
if self.hiring_start_at > self.approval.end_at:
raise xwf_models.AbortTransition(...)
et de faire grosso modo la même chose dans le formulaire pour afficher une erreur à l'utilisateur avant même d'arriver dans JobApplication.accept()
if job_seeker.has_valid_diagnosis(for_siae=job_application.to_company, on_date=timezone.now()): | ||
messages.error(request, "Le contrat doit débuter sur la période couverte par le PASS IAE.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
timezone.now()
? Ça devrais pas être self.hiring_start_at
justement ?
Et le lien de causalité entre has_valid_diagnosis()
et le message d'erreur n'est absolument pas clair, je dirais même qu'il n'y a aucun rapport car dans l'un on parle explicitement de "PASS IAE" et pas de "Diagnostique d'élégibilité".
EligibilityDiagnosis.objects.for_job_seeker_and_siae( | ||
job_seeker=OuterRef("job_seeker"), siae=OuterRef("to_company") | ||
) | ||
.filter(expires_at__gt=OuterRef("hiring_start_at")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hiring_start_at
n'est renseignée qu'une fois que la candidature est acceptée par l'employeur donc la comparaison avec NULL
sera toujours fausse donc aucun diagnostique ne sera renvoyé tant que le champ n'est pas remplis.
# required assumptions for the test case | ||
assert self.company.is_subject_to_eligibility_rules | ||
assert self.job_seeker.has_valid_diagnosis(for_siae=self.company) # valid today | ||
# not valid on the day the job starts | ||
assert ( | ||
not EligibilityDiagnosis.objects.for_job_seeker_and_siae(self.job_seeker, siae=self.company) | ||
.valid(job_application.hiring_start_at) | ||
.exists() | ||
) | ||
assert not self.job_seeker.has_valid_diagnosis( | ||
for_siae=job_application.to_company, on_date=job_application.hiring_start_at | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dans les tests, les suppositions ne sont pas à faire avec des assert
mais dans la mise en place.
# required assumptions for the test case | |
assert self.company.is_subject_to_eligibility_rules | |
assert self.job_seeker.has_valid_diagnosis(for_siae=self.company) # valid today | |
# not valid on the day the job starts | |
assert ( | |
not EligibilityDiagnosis.objects.for_job_seeker_and_siae(self.job_seeker, siae=self.company) | |
.valid(job_application.hiring_start_at) | |
.exists() | |
) | |
assert not self.job_seeker.has_valid_diagnosis( | |
for_siae=job_application.to_company, on_date=job_application.hiring_start_at | |
) | |
assert self.job_seeker.has_valid_diagnosis(for_siae=self.company) # valid today | |
assert not self.job_seeker.has_valid_diagnosis( | |
for_siae=job_application.to_company, on_date=job_application.hiring_start_at | |
) # not valid on the day the job starts |
assert "Le contrat doit débuter sur la période couverte par le PASS IAE." == str( | ||
list(response.context["messages"])[-1] | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assertMessages()
?
on_date = on_date or timezone.now() | ||
last_valid_diagnosis = self.last_considered_valid(job_seeker, for_siae=for_siae) | ||
return job_seeker.has_valid_approval_for_date(on_date) or ( | ||
last_valid_diagnosis and last_valid_diagnosis.expires_at > make_date_timezone_aware(on_date) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A confirmer avec le métier mais pour les diagnostiques il me semble qu'on veux qu'il soit valide au moment où on accepte la candidature et on s'en fiche qu'il le soit encore le jour de l'embauche car il aura un PASS IAE à ce moment là.
🤔 Pourquoi ?
En ce moment c'est possible d'embaucher un candidat après son PASS IAE est expiré, car notre logique cible
timezone.now()
quand il devrait ciblerhiring_start_at
de la poste.🍰 Comment ?
J'ai extendé les utilités des modèles et ses managers à considérer la date d'embauche où nécessaire.
J'ai rélu la logique autor des approbations et des diagnostiques d'éligibilité et j'ai fais des fixes impliqués par la cause du bug (que le
hiring_start_at
est impliqué dans la validité du pass).Le champ
expires_at
utiliseDateTimeField
maishiring_start_at
du JobApplication utiliseDateField
. J'ai inclus un fonction utilitairemake_date_timezone_aware
pour soutenir le gestion des dates.Finalement j'ai fais quelques petites optimisations sur les queries, qui a causé des groses changements aux snapshots.
🚨 À vérifier