Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
eligibility: Improve eligibility diagnosis data consistancy
Browse files Browse the repository at this point in the history
tonial committed Jan 28, 2025

Verified

This commit was signed with the committer’s verified signature. The key has expired.
hoangnt2 Nguyen Thai Hoang
1 parent 4364957 commit eeba4c6
Showing 11 changed files with 120 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated by Django 5.1.5 on 2025-01-28 09:51

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("companies", "0014_company_fields_history_and_more"),
("eligibility", "0009_fix_selectedadministrativecriteria_certification_period"),
("prescribers", "0007_prescriberorganization_automatic_geocoding_update"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.AddConstraint(
model_name="eligibilitydiagnosis",
constraint=models.CheckConstraint(
condition=models.Q(
models.Q(
("author_kind", "employer"),
("author_prescriber_organization__isnull", True),
("author_siae__isnull", False),
),
models.Q(
("author_kind", "prescriber"),
("author_prescriber_organization__isnull", False),
("author_siae__isnull", True),
),
_connector="OR",
),
name="eligibility_iae_diagnosis_author_kind_coherence",
violation_error_message="La structure de l'auteur ne correspond pas à son type",
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 5.1.5 on 2025-01-28 09:52

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("companies", "0014_company_fields_history_and_more"),
("eligibility", "0010_add_eligibilitydiagnosis_author_kind_coherence"),
("prescribers", "0007_prescriberorganization_automatic_geocoding_update"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.RemoveConstraint(
model_name="geiqeligibilitydiagnosis",
name="author_kind_coherence",
),
migrations.AddConstraint(
model_name="geiqeligibilitydiagnosis",
constraint=models.CheckConstraint(
condition=models.Q(
models.Q(
("author_geiq__isnull", False),
("author_kind", "geiq"),
("author_prescriber_organization__isnull", True),
),
models.Q(
("author_geiq__isnull", True),
("author_kind", "prescriber"),
("author_prescriber_organization__isnull", False),
),
_connector="OR",
),
name="author_kind_coherence",
violation_error_message="La structure de l'auteur ne correspond pas à son type",
),
),
]
2 changes: 1 addition & 1 deletion itou/eligibility/models/geiq.py
Original file line number Diff line number Diff line change
@@ -91,7 +91,7 @@ class Meta:
constraints = [
models.CheckConstraint(
name="author_kind_coherence",
violation_error_message="Le diagnostic d'éligibilité GEIQ ne peut avoir 2 structures pour auteur",
violation_error_message="La structure de l'auteur ne correspond pas à son type",
condition=models.Q(
author_kind=AuthorKind.GEIQ,
author_geiq__isnull=False,
16 changes: 16 additions & 0 deletions itou/eligibility/models/iae.py
Original file line number Diff line number Diff line change
@@ -146,6 +146,22 @@ class Meta:
verbose_name = "diagnostic d'éligibilité IAE"
verbose_name_plural = "diagnostics d'éligibilité IAE"
ordering = ["-created_at"]
constraints = [
models.CheckConstraint(
name="eligibility_iae_diagnosis_author_kind_coherence",
violation_error_message="La structure de l'auteur ne correspond pas à son type",
condition=models.Q(
author_kind=AuthorKind.EMPLOYER,
author_siae__isnull=False,
author_prescriber_organization__isnull=True,
)
| models.Q(
author_kind=AuthorKind.PRESCRIBER,
author_prescriber_organization__isnull=False,
author_siae__isnull=True,
),
),
]

@property
def author_organization(self):
2 changes: 1 addition & 1 deletion tests/companies/test_import_siae_command.py
Original file line number Diff line number Diff line change
@@ -258,7 +258,7 @@ def test_with_eligibility_diagnosis(self):
assert could_siae_be_deleted(company)

# Approval with eligibility diagnosis authored by SIAE
ApprovalFactory(eligibility_diagnosis__author_siae=company)
ApprovalFactory(eligibility_diagnosis__author_siae=company, eligibility_diagnosis__from_employer=True)
assert not could_siae_be_deleted(company)

def test_with_job_app(self):
1 change: 1 addition & 0 deletions tests/eligibility/factories.py
Original file line number Diff line number Diff line change
@@ -103,6 +103,7 @@ class Params:
from_employer = factory.Trait(
author_kind=AuthorKind.EMPLOYER,
author_siae=factory.SubFactory(CompanyFactory, subject_to_eligibility=True, with_membership=True),
author_prescriber_organization=None,
author=factory.LazyAttribute(lambda obj: obj.author_siae.members.first()),
)
with_certifiable_criteria = factory.Trait(romes=factory.PostGeneration(_get_iae_certifiable_criteria))
11 changes: 7 additions & 4 deletions tests/eligibility/test_admin.py
Original file line number Diff line number Diff line change
@@ -260,10 +260,13 @@ def test_add_eligibility_not_both_org_and_company(self, admin_client, kind, user

response = admin_client.post(self.get_add_url(kind), data=post_data)
assert response.status_code == 200
expected_errors = [["Vous ne pouvez pas saisir une entreprise et une organisation prescriptrice."]]
if kind == "geiq":
# Additional error thanks to the db constraint
expected_errors[0].append("Le diagnostic d'éligibilité GEIQ ne peut avoir 2 structures pour auteur")
expected_errors = [
[
"Vous ne pouvez pas saisir une entreprise et une organisation prescriptrice.",
"La structure de l'auteur ne correspond pas à son type",
]
]

assert response.context["errors"] == expected_errors
assert not self.get_diag_model(kind).objects.exists()

2 changes: 1 addition & 1 deletion tests/eligibility/test_geiq.py
Original file line number Diff line number Diff line change
@@ -134,7 +134,7 @@ def test_geiq_eligibility_diagnosis_validation():

with pytest.raises(
ValidationError,
match="Le diagnostic d'éligibilité GEIQ ne peut avoir 2 structures pour auteur",
match="La structure de l'auteur ne correspond pas à son type",
):
GEIQEligibilityDiagnosis(
author_geiq=geiq,
23 changes: 14 additions & 9 deletions tests/siae_evaluations/test_models.py
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@
InstitutionWith2MembershipFactory,
)
from tests.job_applications.factories import JobApplicationFactory
from tests.prescribers.factories import PrescriberMembershipFactory
from tests.siae_evaluations.factories import (
EvaluatedAdministrativeCriteriaFactory,
EvaluatedJobApplicationFactory,
@@ -54,7 +55,7 @@ def create_batch_of_job_applications(company):
for _ in range(evaluation_enums.EvaluationJobApplicationsBoundariesNumber.MIN):
approval = ApprovalFactory(
start_at=start,
eligibility_diagnosis__author_kind=AuthorKind.EMPLOYER,
eligibility_diagnosis__from_employer=True,
eligibility_diagnosis__author_siae=company,
)
JobApplicationFactory.create(
@@ -244,6 +245,10 @@ def test_eligibility_diag_not_made_by_employer(self, campaign_eligible_job_app_o
evaluation_campaign = EvaluationCampaignFactory()
diag = campaign_eligible_job_app_objects["diag"]
diag.author_kind = AuthorKind.PRESCRIBER
membership = PrescriberMembershipFactory()
diag.author_prescriber_organization = membership.organization
diag.author_siae = None
diag.author = membership.user
diag.save()
assert [] == list(evaluation_campaign.eligible_job_applications())
assert _eligible_to_siae_evaluations(campaign_eligible_job_app_objects["job_app"]) == "non"
@@ -347,18 +352,18 @@ def test_eligible_siaes(self):
evaluation_campaign = EvaluationCampaignFactory()

# company_1 got 1 job application
company_1 = CompanyFactory(department="14")
company_1 = CompanyFactory(department="14", with_membership=True)
JobApplicationFactory(
with_approval=True,
to_company=company_1,
sender_company=company_1,
eligibility_diagnosis__author_kind=AuthorKind.EMPLOYER,
eligibility_diagnosis__from_employer=True,
eligibility_diagnosis__author_siae=company_1,
hiring_start_at=timezone.localdate() - relativedelta(months=2),
)

# company_2 got 2 job applications
company_2 = CompanyFactory(department="14")
company_2 = CompanyFactory(department="14", with_membership=True)
create_batch_of_job_applications(company_2)

eligible_siaes_res = evaluation_campaign.eligible_siaes()
@@ -387,7 +392,7 @@ def test_eligible_siae_approval_from_past_year(self):
before_evaluated_period = datetime.date(2022, 4, 4)
approval1 = ApprovalFactory(
start_at=before_evaluated_period, # Before evaluated period.
eligibility_diagnosis__author_kind=AuthorKind.EMPLOYER,
eligibility_diagnosis__from_employer=True,
eligibility_diagnosis__author_siae=company,
)
job_app_approval1_args = {
@@ -406,7 +411,7 @@ def test_eligible_siae_approval_from_past_year(self):
within_evaluated_period = datetime.date(2023, 2, 1)
approval2 = ApprovalFactory(
start_at=within_evaluated_period,
eligibility_diagnosis__author_kind=AuthorKind.EMPLOYER,
eligibility_diagnosis__from_employer=True,
eligibility_diagnosis__author_siae=company,
)
JobApplicationFactory.create(
@@ -424,13 +429,13 @@ def test_number_of_siaes_to_select(self):
assert 0 == evaluation_campaign.number_of_siaes_to_select()

for _ in range(3):
company = CompanyFactory(department="14")
company = CompanyFactory(department="14", with_membership=True)
create_batch_of_job_applications(company)

assert 1 == evaluation_campaign.number_of_siaes_to_select()

for _ in range(3):
company = CompanyFactory(department="14")
company = CompanyFactory(department="14", with_membership=True)
create_batch_of_job_applications(company)

assert 2 == evaluation_campaign.number_of_siaes_to_select()
@@ -439,7 +444,7 @@ def test_eligible_siaes_under_ratio(self):
evaluation_campaign = EvaluationCampaignFactory()

for _ in range(6):
company = CompanyFactory(department="14")
company = CompanyFactory(department="14", with_membership=True)
create_batch_of_job_applications(company)

assert 2 == evaluation_campaign.eligible_siaes_under_ratio().count()
2 changes: 1 addition & 1 deletion tests/www/apply/test_process.py
Original file line number Diff line number Diff line change
@@ -1840,7 +1840,7 @@ def create_job_application(self, *args, **kwargs):
kwargs = {
"eligibility_diagnosis__with_certifiable_criteria": True,
"eligibility_diagnosis__author_siae": self.company,
"eligibility_diagnosis__author_kind": AuthorKind.EMPLOYER,
"eligibility_diagnosis__from_employer": True,
} | kwargs
return JobApplicationSentByJobSeekerFactory(**kwargs)

4 changes: 2 additions & 2 deletions tests/www/employees_views/test_detail.py
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ def test_detail_view(self, client, snapshot):
)
assert job_application.is_sent_by_authorized_prescriber
IAEEligibilityDiagnosisFactory(
from_prescriber=True, job_seeker=approval.user, author_siae=job_application.to_company
from_employer=True, job_seeker=approval.user, author_siae=job_application.to_company
)

# Another job applcation on the same SIAE, by a non authorized prescriber
@@ -90,7 +90,7 @@ def test_detail_view_no_job_application(self, client):
employer = company.members.first()
# Make sure the job seeker infos can be edited by the siae member
approval = ApprovalFactory(user__created_by=employer)
IAEEligibilityDiagnosisFactory(from_prescriber=True, job_seeker=approval.user, author_siae=company)
IAEEligibilityDiagnosisFactory(from_prescriber=True, job_seeker=approval.user)

client.force_login(employer)

0 comments on commit eeba4c6

Please sign in to comment.