Skip to content
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

Candidature : N'utiliser que les diagnostiques considérés comme valides pour la SIAE #4229

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions itou/job_applications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,12 @@ def with_accepted_at(self):
def with_jobseeker_eligibility_diagnosis(self):
"""
Gives the "eligibility_diagnosis" linked to the job application or if none is found
the last eligibility diagnosis for jobseeker
the last valid eligibility diagnosis for this job seeker and this SIAE
"""
rsebille marked this conversation as resolved.
Show resolved Hide resolved
sub_query = Subquery(
(
EligibilityDiagnosis.objects.filter(job_seeker=OuterRef("job_seeker"))
.order_by("-created_at")
EligibilityDiagnosis.objects.valid()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je vais changer légèrement cette logique pour https://www.notion.so/plateforme-inclusion/Investigation-Cacher-les-diags-SIAE-aux-prescripteurs-lors-des-candidatures-3227290de5b248759a5fe43079868292

On va avoir un viewing_user qui va décider de la visibilité d’un diag pour l’utilisateur courant. Mais a priori, je mettrais juste à jour cette section pour passer le viewing_user.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'était ma supposition, d'où ton ajout à la PR pour être sûr que ça allais plus ou moins dans le même sens ;).

.for_job_seeker_and_siae(job_seeker=OuterRef("job_seeker"), siae=OuterRef("to_company"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je me demande si on ne voudrait pas prendre le diagnostique du prescripteur en premier, comme dans EligibilityDiagnosis.objects.last_considered_valid() ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sans doute, mais alors faut aussi modifier le .eligibility_validated() juste en dessous, ou mettre le tri directement dans .for_job_seeker_and_siae() ?

.values("id")[:1]
),
output_field=models.IntegerField(),
Expand Down
6 changes: 4 additions & 2 deletions tests/approvals/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from itou.companies.enums import SIAE_WITH_CONVENTION_KINDS, CompanyKind
from itou.job_applications.enums import JobApplicationState, SenderKind
from tests.companies.factories import CompanyFactory
from tests.eligibility.factories import EligibilityDiagnosisFactory
from tests.eligibility.factories import IAEEligibilityDiagnosisFactory
from tests.files.factories import FileFactory
from tests.prescribers.factories import PrescriberOrganizationFactory
from tests.users.factories import JobSeekerFactory, JobSeekerProfileFactory, PrescriberFactory
Expand Down Expand Up @@ -66,7 +66,9 @@ class Params:
number = factory.fuzzy.FuzzyText(length=7, chars=string.digits, prefix=Approval.ASP_ITOU_PREFIX)
start_at = factory.LazyFunction(datetime.date.today)
end_at = factory.LazyAttribute(lambda obj: Approval.get_default_end_date(obj.start_at))
eligibility_diagnosis = factory.SubFactory(EligibilityDiagnosisFactory, job_seeker=factory.SelfAttribute("..user"))
eligibility_diagnosis = factory.SubFactory(
IAEEligibilityDiagnosisFactory, from_prescriber=True, job_seeker=factory.SelfAttribute("..user")
)

@factory.post_generation
def with_jobapplication(self, create, extracted, **kwargs):
Expand Down
6 changes: 3 additions & 3 deletions tests/approvals/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
SuspensionFactory,
)
from tests.companies.factories import CompanyFactory
from tests.eligibility.factories import EligibilityDiagnosisFactory
from tests.eligibility.factories import IAEEligibilityDiagnosisFactory
from tests.employee_record.factories import EmployeeRecordFactory
from tests.job_applications.factories import JobApplicationFactory, JobApplicationSentByJobSeekerFactory
from tests.users.factories import ItouStaffFactory, JobSeekerFactory
Expand Down Expand Up @@ -838,7 +838,7 @@ def test_create_approval_with_a_wrong_number(self):

url = reverse("admin:approvals_approval_add")

diagnosis = EligibilityDiagnosisFactory()
diagnosis = IAEEligibilityDiagnosisFactory(from_prescriber=True)
post_data = {
"start_at": "01/01/2100",
"end_at": "31/12/2102",
Expand Down Expand Up @@ -931,7 +931,7 @@ def test_create_approval(self):
user.user_permissions.add(permission)
self.client.force_login(user)

diagnosis = EligibilityDiagnosisFactory()
diagnosis = IAEEligibilityDiagnosisFactory(from_prescriber=True)
other_job_seeker = JobSeekerFactory()
url = reverse("admin:approvals_approval_add")

Expand Down
4 changes: 2 additions & 2 deletions tests/companies/test_import_siae_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from itou.companies.models import Company
from tests.approvals.factories import ApprovalFactory
from tests.companies.factories import CompanyFactory, CompanyWith2MembershipsFactory, SiaeConventionFactory
from tests.eligibility.factories import EligibilityDiagnosisMadeBySiaeFactory
from tests.eligibility.factories import IAEEligibilityDiagnosisFactory
from tests.job_applications.factories import JobApplicationFactory
from tests.utils.test import TestCase

Expand Down Expand Up @@ -240,7 +240,7 @@ def test_with_eligibility_diagnosis(self):
assert could_siae_be_deleted(company)

# An eligibility diagnosis without related approval
EligibilityDiagnosisMadeBySiaeFactory(author_siae=company, author=company.members.first())
IAEEligibilityDiagnosisFactory(from_employer=True, author_siae=company, author=company.members.first())
assert could_siae_be_deleted(company)

# Approval with eligibility diagnosis authored by SIAE
Expand Down
79 changes: 35 additions & 44 deletions tests/eligibility/factories.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import random

import factory
from django.utils import timezone

Expand All @@ -9,21 +11,12 @@
from tests.users.factories import JobSeekerFactory


class GEIQEligibilityDiagnosisFactory(factory.django.DjangoModelFactory):
"""Same as factories below, but :
- with all possible author types
- tailored for GEIQ tests."""

class AbstractEligibilityDiagnosisModelFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.GEIQEligibilityDiagnosis
abstract = True

class Params:
with_geiq = factory.Trait(
author_kind=AuthorKind.GEIQ,
author_geiq=factory.SubFactory(CompanyWith2MembershipsFactory, kind=CompanyKind.GEIQ, with_jobs=True),
author=factory.LazyAttribute(lambda obj: obj.author_geiq.members.first()),
)
with_prescriber = factory.Trait(
from_prescriber = factory.Trait(
author_kind=AuthorKind.PRESCRIBER,
author_prescriber_organization=factory.SubFactory(
PrescriberOrganizationWithMembershipFactory, authorized=True
Expand All @@ -36,45 +29,43 @@ class Params:
job_seeker = factory.SubFactory(JobSeekerFactory)


class EligibilityDiagnosisFactory(factory.django.DjangoModelFactory):
"""Generate an EligibilityDiagnosis() object whose author is an authorized prescriber organization."""

class Meta:
model = models.EligibilityDiagnosis

created_at = factory.LazyFunction(timezone.now)
author = factory.LazyAttribute(lambda obj: obj.author_prescriber_organization.members.first())
author_kind = AuthorKind.PRESCRIBER
author_prescriber_organization = factory.SubFactory(PrescriberOrganizationWithMembershipFactory, authorized=True)
job_seeker = factory.SubFactory(JobSeekerFactory)


class EligibilityDiagnosisMadeBySiaeFactory(factory.django.DjangoModelFactory):
"""Generate an EligibilityDiagnosis() object whose author is an SIAE."""
class GEIQEligibilityDiagnosisFactory(AbstractEligibilityDiagnosisModelFactory):
"""Same as factories below, but :
- with all possible author types
- tailored for GEIQ tests."""

class Meta:
model = models.EligibilityDiagnosis

created_at = factory.LazyFunction(timezone.now)
author = factory.LazyAttribute(lambda obj: obj.author_siae.members.first())
author_kind = AuthorKind.EMPLOYER
author_siae = factory.SubFactory(CompanyFactory, with_membership=True)
job_seeker = factory.SubFactory(JobSeekerFactory)
model = models.GEIQEligibilityDiagnosis

class Params:
from_geiq = factory.Trait(
author_kind=AuthorKind.GEIQ,
author_geiq=factory.SubFactory(CompanyWith2MembershipsFactory, kind=CompanyKind.GEIQ, with_jobs=True),
author=factory.LazyAttribute(lambda obj: obj.author_geiq.members.first()),
)

class ExpiredEligibilityDiagnosisFactory(EligibilityDiagnosisFactory):
expires_at = factory.SelfAttribute("created_at")

def _get_iae_administrative_criteria(self, create, extracted, **kwargs):
if not create:
# Simple build, do nothing.
return

class ExpiredEligibilityDiagnosisMadeBySiaeFactory(EligibilityDiagnosisMadeBySiaeFactory):
expires_at = factory.SelfAttribute("created_at")
# Pick random results.
criteria = models.AdministrativeCriteria.objects.order_by("?")[: random.randint(2, 5)]
self.administrative_criteria.add(*criteria)


class AdministrativeCriteriaFactory(factory.django.DjangoModelFactory):
"""
The AdministrativeCriteria table is automatically populated with a fixture
after a `post_migrate` signal at the start of the `eligibility` app.
"""
class IAEEligibilityDiagnosisFactory(AbstractEligibilityDiagnosisModelFactory):
"""Generate an EligibilityDiagnosis() object whose author is an authorized prescriber organization."""

class Meta:
model = models.AdministrativeCriteria
model = models.EligibilityDiagnosis
skip_postgeneration_save = True

class Params:
from_employer = factory.Trait(
author_kind=AuthorKind.EMPLOYER,
author_siae=factory.SubFactory(CompanyFactory, subject_to_eligibility=True, with_membership=True),
author=factory.LazyAttribute(lambda obj: obj.author_siae.members.first()),
)
with_criteria = factory.Trait(romes=factory.PostGeneration(_get_iae_administrative_criteria))
50 changes: 25 additions & 25 deletions tests/eligibility/test_geiq.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,12 @@ def test_update_geiq_eligibility_diagnosis(administrative_criteria_annex_1):
GEIQEligibilityDiagnosis.update_eligibility_diagnosis(None, None, ())

# Trying to update an expired diagnosis
diagnosis = GEIQEligibilityDiagnosisFactory(with_prescriber=True, expired=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_prescriber=True, expired=True)
with pytest.raises(ValueError, match="Impossible de modifier un diagnostic GEIQ expiré"):
GEIQEligibilityDiagnosis.update_eligibility_diagnosis(diagnosis, diagnosis.author, administrative_criteria=())

# correct update case:
diagnosis = GEIQEligibilityDiagnosisFactory(with_prescriber=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_prescriber=True)
GEIQEligibilityDiagnosis.update_eligibility_diagnosis(
diagnosis, diagnosis.author, [administrative_criteria_annex_1]
)
Expand All @@ -110,7 +110,7 @@ def test_update_geiq_eligibility_diagnosis(administrative_criteria_annex_1):


def test_update_geiq_eligibility_diagnosis_author():
diagnosis = GEIQEligibilityDiagnosisFactory(with_prescriber=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_prescriber=True)
other_user = ItouStaffFactory()
GEIQEligibilityDiagnosis.update_eligibility_diagnosis(diagnosis, other_user, ())
diagnosis.refresh_from_db()
Expand All @@ -119,10 +119,10 @@ def test_update_geiq_eligibility_diagnosis_author():


def test_geiq_eligibility_diagnosis_validation():
diagnosis = GEIQEligibilityDiagnosisFactory(with_geiq=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_geiq=True)
diagnosis.clean()

diagnosis = GEIQEligibilityDiagnosisFactory(with_prescriber=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_prescriber=True)
diagnosis.clean()

# Only prescriber org or GEIQ are possible authors
Expand Down Expand Up @@ -150,7 +150,7 @@ def test_geiq_administrative_criteria_validation(
administrative_criteria_annex_2_level_2,
):
# GEIQ diagnosis can be created with all kind of administrative criteria
diagnosis = GEIQEligibilityDiagnosisFactory(with_geiq=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_geiq=True)
diagnosis.administrative_criteria.set(
[
administrative_criteria_annex_1,
Expand Down Expand Up @@ -230,13 +230,13 @@ def test_geiq_eligibility_diagnosis_allowance_and_eligibility(
annex=AdministrativeCriteriaAnnex.ANNEX_2,
level=AdministrativeCriteriaLevel.LEVEL_2,
)[:2]
diagnosis = GEIQEligibilityDiagnosisFactory(with_prescriber=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_prescriber=True)

# Prescriber author gets it all
assert diagnosis.eligibility_confirmed
assert diagnosis.allowance_amount == GEIQ_ALLOWANCE_AMOUNT_1400

diagnosis = GEIQEligibilityDiagnosisFactory(with_geiq=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_geiq=True)

assert not diagnosis.eligibility_confirmed
assert diagnosis.allowance_amount == 0
Expand All @@ -253,13 +253,13 @@ def test_geiq_eligibility_diagnosis_allowance_and_eligibility(
assert diagnosis.allowance_amount == GEIQ_ALLOWANCE_AMOUNT_1400

# One L1 is enough to get max allowance
diagnosis = GEIQEligibilityDiagnosisFactory(with_geiq=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_geiq=True)
diagnosis.administrative_criteria.add(administrative_criteria_annex_2_level_1)

assert diagnosis.eligibility_confirmed
assert diagnosis.allowance_amount == GEIQ_ALLOWANCE_AMOUNT_1400

diagnosis = GEIQEligibilityDiagnosisFactory(with_geiq=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_geiq=True)
diagnosis.administrative_criteria.add(administrative_criteria_annex_1)

assert diagnosis.eligibility_confirmed
Expand All @@ -274,7 +274,7 @@ def test_geiq_eligibility_diagnosis_allowance_and_eligibility(
# Special case of dual-annex criteria:

# Counts as Annex 1 criterion...
diagnosis = GEIQEligibilityDiagnosisFactory(with_geiq=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_geiq=True)
diagnosis.administrative_criteria.add(administrative_criteria_both_annexes)

assert diagnosis.eligibility_confirmed
Expand All @@ -287,18 +287,18 @@ def test_geiq_eligibility_diagnosis_allowance_and_eligibility(
assert diagnosis.allowance_amount == GEIQ_ALLOWANCE_AMOUNT_1400

# GEIQ eligibility is not confirmed with valid criteria and expired diagnosis
diagnosis = GEIQEligibilityDiagnosisFactory(with_prescriber=True, expires_at=timezone.now())
diagnosis = GEIQEligibilityDiagnosisFactory(from_prescriber=True, expires_at=timezone.now())
assert not diagnosis.eligibility_confirmed


def test_create_duplicate_diagnosis_in_same_geiq():
diagnosis = GEIQEligibilityDiagnosisFactory(with_geiq=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_geiq=True)

# Check for duplicates : *valid* diagnosis, with same author structure for the same job seeker
# Should have been nice as a unique constraint but does not work as expected because of mutable timestamps
with pytest.raises(ValidationError, match="Il existe déjà un diagnostic GEIQ valide pour "):
GEIQEligibilityDiagnosisFactory(
with_geiq=True,
from_geiq=True,
author_geiq=diagnosis.author_geiq,
job_seeker=diagnosis.job_seeker,
author=diagnosis.author_geiq.members.first(),
Expand All @@ -310,12 +310,12 @@ def test_invalidate_obsolete_diagnosis():
# and hiring must occur during validity period of the diagnosis
job_application = JobApplicationFactory(with_geiq_eligibility_diagnosis=True)
diagnosis_with_hiring = job_application.geiq_eligibility_diagnosis
diagnosis_without_hiring = GEIQEligibilityDiagnosisFactory(with_geiq=True, job_seeker=job_application.job_seeker)
diagnosis_without_hiring = GEIQEligibilityDiagnosisFactory(from_geiq=True, job_seeker=job_application.job_seeker)

assert diagnosis_with_hiring.is_valid
assert diagnosis_without_hiring.is_valid

GEIQEligibilityDiagnosisFactory(with_prescriber=True, job_seeker=job_application.job_seeker)
GEIQEligibilityDiagnosisFactory(from_prescriber=True, job_seeker=job_application.job_seeker)

diagnosis_with_hiring.refresh_from_db()
diagnosis_without_hiring.refresh_from_db()
Expand All @@ -330,7 +330,7 @@ def test_invalidate_obsolete_diagnosis():

def test_create_dup_geiq_eligibility_diagnosis_with_geiq_and_prescriber(new_geiq, administrative_criteria_annex_1):
# Create a diagnosis with a prescriber author
diagnosis = GEIQEligibilityDiagnosisFactory(with_prescriber=True)
diagnosis = GEIQEligibilityDiagnosisFactory(from_prescriber=True)

# If the diagnosis is valid, then new GEIQ authored diagnoses are not allowed
with pytest.raises(ValidationError, match=r"Il existe déjà un diagnostic GEIQ valide"):
Expand All @@ -355,14 +355,14 @@ def test_create_dup_geiq_eligibility_diagnosis_with_geiq_and_prescriber(new_geiq

def test_create_dup_geiq_eligibility_diagnosis_with_two_geiq():
# Creating duplicate GEIQ diagnosis with the same GEIQ and job seeker is not allowed
geiq_diagnosis = GEIQEligibilityDiagnosisFactory(with_geiq=True)
geiq_diagnosis = GEIQEligibilityDiagnosisFactory(from_geiq=True)

with pytest.raises(
ValidationError,
match="Il existe déjà un diagnostic GEIQ valide pour cet utilisateur",
):
GEIQEligibilityDiagnosisFactory(
with_geiq=True,
from_geiq=True,
author_geiq=geiq_diagnosis.author_geiq,
job_seeker=geiq_diagnosis.job_seeker,
)
Expand All @@ -372,7 +372,7 @@ def test_create_dup_geiq_eligibility_diagnosis_with_two_geiq():
geiq_diagnosis.save()

assert GEIQEligibilityDiagnosisFactory(
with_geiq=True,
from_geiq=True,
author_geiq=geiq_diagnosis.author_geiq,
job_seeker=geiq_diagnosis.job_seeker,
)
Expand All @@ -382,9 +382,9 @@ def test_prescriber_geiq_diagnosis_priority():
# If there are existing valid GEIQ diagnoses for the same job seeker and created by GEIQs,
# they are automatically "expired" when a prescriber creates a new diagnosis (it has priority over GEIQ ones)
# GEIQ diagnoses linked to a hiring are kept valid
geiq_diagnosis = GEIQEligibilityDiagnosisFactory(with_geiq=True)
geiq_diagnosis = GEIQEligibilityDiagnosisFactory(from_geiq=True)
job_seeker = geiq_diagnosis.job_seeker
geiq_diagnosis_with_hiring = GEIQEligibilityDiagnosisFactory(with_geiq=True, job_seeker=job_seeker)
geiq_diagnosis_with_hiring = GEIQEligibilityDiagnosisFactory(from_geiq=True, job_seeker=job_seeker)
JobApplicationFactory(
with_geiq_eligibility_diagnosis=True,
job_seeker=job_seeker,
Expand All @@ -394,7 +394,7 @@ def test_prescriber_geiq_diagnosis_priority():
assert geiq_diagnosis.is_valid
assert geiq_diagnosis_with_hiring.is_valid

prescriber_diagnosis = GEIQEligibilityDiagnosisFactory(with_prescriber=True, job_seeker=job_seeker)
prescriber_diagnosis = GEIQEligibilityDiagnosisFactory(from_prescriber=True, job_seeker=job_seeker)
geiq_diagnosis.refresh_from_db()
geiq_diagnosis_with_hiring.refresh_from_db()

Expand All @@ -406,14 +406,14 @@ def test_prescriber_geiq_diagnosis_priority():
def test_authored_by_prescriber_or_geiq():
# When using this query set method, if there are multiple valid GEIQ diagnoses,
# the prescriber diagnosis must come out in first position
geiq_diagnosis_with_hiring = GEIQEligibilityDiagnosisFactory(with_geiq=True)
geiq_diagnosis_with_hiring = GEIQEligibilityDiagnosisFactory(from_geiq=True)
JobApplicationFactory(
with_geiq_eligibility_diagnosis=True,
geiq_eligibility_diagnosis=geiq_diagnosis_with_hiring,
)
# Order matters
prescriber_diagnosis = GEIQEligibilityDiagnosisFactory(
with_prescriber=True,
from_prescriber=True,
job_seeker=geiq_diagnosis_with_hiring.job_seeker,
)

Expand Down
Loading