Skip to content

Commit

Permalink
job_description: Rename popular to overwhelmed
Browse files Browse the repository at this point in the history
  • Loading branch information
dejafait committed Jan 20, 2025
1 parent 5dc9241 commit 278ab51
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 46 deletions.
8 changes: 4 additions & 4 deletions itou/companies/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ def with_job_applications_count(self, filters=None):
),
)

def with_annotation_is_popular(self):
def with_annotation_is_overwhelmed(self):
# Avoid a circular import
from itou.job_applications.models import JobApplicationWorkflow

Expand All @@ -566,8 +566,8 @@ def with_annotation_is_popular(self):
"jobapplication__archived_at": None,
}
annotation = self.with_job_applications_count(filters=job_apps_filters).annotate(
is_popular=Case(
When(job_applications_count__gte=self.model.POPULAR_THRESHOLD, then=True),
is_overwhelmed=Case(
When(job_applications_count__gte=self.model.OVERWHELMED_THRESHOLD, then=True),
default=False,
output_field=BooleanField(),
)
Expand Down Expand Up @@ -604,7 +604,7 @@ class JobDescription(models.Model):
"""

MAX_UI_RANK = 32767
POPULAR_THRESHOLD = 20
OVERWHELMED_THRESHOLD = 20
# Max number or workable hours per week in France (Code du Travail)
MAX_WORKED_HOURS_PER_WEEK = 48

Expand Down
2 changes: 1 addition & 1 deletion itou/templates/apply/submit/application/jobs.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<label class="fw-bold stretched-link order-2 order-md-1 m-0" for="{{ choice.id_for_label }}">
{{ choice.choice_label }}
</label>
{% if job_description.is_popular %}
{% if job_description.is_overwhelmed %}
<div class="order-1 order-md-2">
<span class="badge badge-sm rounded-pill bg-accent-03 text-primary ms-0 ms-lg-2 mt-1 mt-lg-0"><i class="ri-group-line"></i>20+ candidatures</span>
</div>
Expand Down
4 changes: 2 additions & 2 deletions itou/templates/companies/includes/_card_jobdescription.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
{% if job_description.is_external %} {% matomo_event "candidature" "clic" "clic-card-fichedeposte-externe" %} rel="noopener" target="_blank" aria-label="Visiter l'offre sur le site d'origine" {% else %} {% matomo_event "candidature" "clic" "clic-card-fichedeposte" %} aria-label="Aller vers la description de ce poste" {% endif %}>
{{ job_description.display_name | capfirst }}
</a>
{% if job_description.is_popular %}
{% if job_description.is_overwhelmed %}
<span class="badge badge-sm rounded-pill bg-accent-03 text-primary">
<i class="ri-group-line me-1" aria-hidden="true"></i>
{{ job_description.POPULAR_THRESHOLD }}+<span class="ms-1">candidatures</span>
{{ job_description.OVERWHELMED_THRESHOLD }}+<span class="ms-1">candidatures</span>
</span>
{% endif %}
<ul class="c-box--results__list-contact flex-md-grow-1 mt-1">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
{% endif %}
<a href="{{ job_url }}" class="fw-bold text-decoration-none stretched-link" {% matomo_event "candidature" "clic" "clic-metiers" %}>{{ job.display_name }}</a>
{% endif %}
{% if job.is_popular %}
{% if job.is_overwhelmed %}
<span class="badge badge-sm rounded-pill bg-accent-03 text-primary">
<i class="ri-group-line me-1" aria-hidden="true"></i>
{{ job.POPULAR_THRESHOLD }}+<span class="ms-1">candidatures</span>
{{ job.OVERWHELMED_THRESHOLD }}+<span class="ms-1">candidatures</span>
</span>
{% endif %}
<p class="fs-sm mb-0 mt-1">
Expand Down
4 changes: 2 additions & 2 deletions itou/templates/companies/includes/_siae_jobdescription.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
class="fw-bold stretched-link order-2 order-md-1"
{% matomo_event "candidature" "clic" "clic-metiers" %}>{{ job.display_name }}</a>
{% endif %}
{% if job.is_popular %}
{% if job.is_overwhelmed %}
<div class="order-1 order-md-2">
<span class="badge badge-sm rounded-pill bg-accent-03 text-primary ms-0 ms-lg-2 mt-1 mt-lg-0"><i class="ri-group-line"></i>{{ job.POPULAR_THRESHOLD }}+ candidatures</span>
<span class="badge badge-sm rounded-pill bg-accent-03 text-primary ms-0 ms-lg-2 mt-1 mt-lg-0"><i class="ri-group-line"></i>{{ job.OVERWHELMED_THRESHOLD }}+ candidatures</span>
</div>
{% endif %}
</div>
Expand Down
2 changes: 1 addition & 1 deletion itou/www/apply/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def __init__(self, company, *args, **kwargs):
super().__init__(*args, **kwargs)

self.fields["selected_jobs"].queryset = (
company.job_description_through.active().with_annotation_is_popular().prefetch_related("appellation")
company.job_description_through.active().with_annotation_is_overwhelmed().prefetch_related("appellation")
)
if not self.initial.get("selected_jobs"):
self.initial["spontaneous_application"] = True
Expand Down
8 changes: 4 additions & 4 deletions itou/www/search/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def get_results_page_and_counts(self, siaes, job_descriptions):
siaes.prefetch_related(
Prefetch(
lookup="job_description_through",
queryset=JobDescription.objects.with_annotation_is_popular()
queryset=JobDescription.objects.with_annotation_is_overwhelmed()
.filter(company__in=siaes, is_active=True)
.select_related("appellation", "location", "company"),
to_attr="active_job_descriptions",
Expand Down Expand Up @@ -255,7 +255,7 @@ def get_results_page_and_counts(self, siaes, job_descriptions):
job_descriptions = job_descriptions.order_by(F("source_kind").asc(nulls_first=True), "-updated_at")

page = pager(job_descriptions, self.request.GET.get("page"), items_per_page=10)
# Prefer a prefetch_related over annotating the entire queryset with_annotation_is_popular().
# Prefer a prefetch_related over annotating the entire queryset with_annotation_is_overwhelmed().
# That annotation is quite expensive and PostgreSQL runs it on the entire queryset, even
# though we don’t sort or group by that column. It would be smarter to apply the limit
# before computing the annotation, but that’s not what PostgreSQL 15 does on 2024-02-21.
Expand All @@ -267,8 +267,8 @@ def get_results_page_and_counts(self, siaes, job_descriptions):
)
)
for job_description in page.object_list:
job_description.is_popular = (
len(job_description.jobapplication_set_pending) >= job_description._meta.model.POPULAR_THRESHOLD
job_description.is_overwhelmed = (
len(job_description.jobapplication_set_pending) >= job_description._meta.model.OVERWHELMED_THRESHOLD
)
return PageAndCounts(
results_page=page,
Expand Down
46 changes: 28 additions & 18 deletions tests/companies/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,42 +347,52 @@ def test_can_have_prior_action(self):


class TestJobDescriptionQuerySet:
def test_with_annotation_is_popular(self):
def test_with_annotation_is_overwhelmed(self):
company = CompanyFactory(with_jobs=True)
job_seeker = JobSeekerFactory() # We don't care if it's always the same
siae_job_descriptions = company.job_description_through.all()

# Test attribute presence
siae_job_description = JobDescription.objects.with_annotation_is_popular().first()
assert hasattr(siae_job_description, "is_popular")

# Test popular threshold: popular job description
popular_job_description = siae_job_descriptions[0]
for _ in range(JobDescription.POPULAR_THRESHOLD + 1):
JobApplicationFactory(to_company=company, selected_jobs=[popular_job_description], job_seeker=job_seeker)

assert JobDescription.objects.with_annotation_is_popular().get(pk=popular_job_description.pk).is_popular
siae_job_description = JobDescription.objects.with_annotation_is_overwhelmed().first()
assert hasattr(siae_job_description, "is_overwhelmed")

# Test overwhelmed threshold: overwhelmed job description
overwhelmed_job_description = siae_job_descriptions[0]
for _ in range(JobDescription.OVERWHELMED_THRESHOLD + 1):
JobApplicationFactory(
to_company=company, selected_jobs=[overwhelmed_job_description], job_seeker=job_seeker
)

assert (
JobDescription.objects.with_annotation_is_overwhelmed()
.get(pk=overwhelmed_job_description.pk)
.is_overwhelmed
)

# Test popular threshold: unpopular job description
unpopular_job_description = siae_job_descriptions[1]
JobApplicationFactory(to_company=company, selected_jobs=[unpopular_job_description])
# Test overwhelmed threshold: non overwhelmed job description
non_overwhelmed_job_description = siae_job_descriptions[1]
JobApplicationFactory(to_company=company, selected_jobs=[non_overwhelmed_job_description])

assert not JobDescription.objects.with_annotation_is_popular().get(pk=unpopular_job_description.pk).is_popular
assert (
not JobDescription.objects.with_annotation_is_overwhelmed()
.get(pk=non_overwhelmed_job_description.pk)
.is_overwhelmed
)

# Popular job descriptions count related **pending** job applications.
# Overwhelmed job descriptions count related **pending** job applications.
# They should ignore other states.
job_description = siae_job_descriptions[2]
threshold_exceeded = JobDescription.POPULAR_THRESHOLD + 1
threshold_exceeded = JobDescription.OVERWHELMED_THRESHOLD + 1

JobApplicationFactory.create_batch(
threshold_exceeded,
to_company=company,
job_seeker=job_seeker,
selected_jobs=[popular_job_description],
selected_jobs=[overwhelmed_job_description],
state=JobApplicationState.ACCEPTED,
)

assert not JobDescription.objects.with_annotation_is_popular().get(pk=job_description.pk).is_popular
assert not JobDescription.objects.with_annotation_is_overwhelmed().get(pk=job_description.pk).is_overwhelmed

def test_with_job_applications_count(self):
company = CompanyFactory(with_jobs=True)
Expand Down
8 changes: 4 additions & 4 deletions tests/www/search/__snapshots__/tests.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -924,7 +924,7 @@
WHERE ("job_applications_jobapplication"."archived_at" IS NULL
AND "job_applications_jobapplication"."state" IN (%s, %s, %s))) >= %s THEN %s
ELSE %s
END AS "is_popular",
END AS "is_overwhelmed",
"jobs_appellation"."updated_at",
"jobs_appellation"."code",
"jobs_appellation"."name",
Expand Down Expand Up @@ -1311,7 +1311,7 @@
WHERE ("job_applications_jobapplication"."archived_at" IS NULL
AND "job_applications_jobapplication"."state" IN (%s, %s, %s))) >= %s THEN %s
ELSE %s
END AS "is_popular",
END AS "is_overwhelmed",
"jobs_appellation"."updated_at",
"jobs_appellation"."code",
"jobs_appellation"."name",
Expand Down Expand Up @@ -1699,7 +1699,7 @@
WHERE ("job_applications_jobapplication"."archived_at" IS NULL
AND "job_applications_jobapplication"."state" IN (%s, %s, %s))) >= %s THEN %s
ELSE %s
END AS "is_popular",
END AS "is_overwhelmed",
"jobs_appellation"."updated_at",
"jobs_appellation"."code",
"jobs_appellation"."name",
Expand Down Expand Up @@ -2086,7 +2086,7 @@
WHERE ("job_applications_jobapplication"."archived_at" IS NULL
AND "job_applications_jobapplication"."state" IN (%s, %s, %s))) >= %s THEN %s
ELSE %s
END AS "is_popular",
END AS "is_overwhelmed",
"jobs_appellation"."updated_at",
"jobs_appellation"."code",
"jobs_appellation"."name",
Expand Down
16 changes: 8 additions & 8 deletions tests/www/search/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,24 +240,24 @@ def test_opcs_displays_card_differently(self, client):
)
assertContains(response, "Offres clauses sociales")

def test_is_popular(self, client):
def test_is_overwhelmed(self, client):
create_test_romes_and_appellations(("N1101", "N1105", "N1103", "N4105"))
city = create_city_saint_andre()
company = CompanyFactory(department="44", coords=city.coords, post_code="44117", with_membership=True)
job = JobDescriptionFactory(company=company)
JobApplicationFactory.create_batch(19, to_company=company, selected_jobs=[job], state="new")
response = client.get(self.URL, {"city": city.slug})
popular_badge = """
overwhelmed_badge = """
<span class="badge badge-sm rounded-pill bg-accent-03 text-primary">
<i class="ri-group-line me-1" aria-hidden="true"></i>
20+<span class="ms-1">candidatures</span>
</span>
"""
assertNotContains(response, popular_badge, html=True)
assertNotContains(response, overwhelmed_badge, html=True)

JobApplicationFactory(to_company=company, selected_jobs=[job], state="new")
response = client.get(self.URL, {"city": city.slug})
assertContains(response, popular_badge, html=True)
assertContains(response, overwhelmed_badge, html=True)

def test_has_no_active_members(self, client):
create_test_romes_and_appellations(["N1101"], appellations_per_rome=1)
Expand Down Expand Up @@ -798,24 +798,24 @@ def test_order_by(self, client):
jobs_results = response.context["results_page"]
assert list(jobs_results) == [job1, job2, job3]

def test_is_popular(self, client):
def test_is_overwhelmed(self, client):
create_test_romes_and_appellations(("N1101", "N1105", "N1103", "N4105"))
city = create_city_saint_andre()
company = CompanyFactory(department="44", coords=city.coords, post_code="44117")
job = JobDescriptionFactory(company=company)
JobApplicationFactory.create_batch(19, to_company=company, selected_jobs=[job], state="new")
response = client.get(self.URL, {"city": city.slug})
popular_badge = """
overwhelmed_badge = """
<span class="badge badge-sm rounded-pill bg-accent-03 text-primary">
<i class="ri-group-line me-1" aria-hidden="true"></i>
20+<span class="ms-1">candidatures</span>
</span>
"""
assertNotContains(response, popular_badge, html=True)
assertNotContains(response, overwhelmed_badge, html=True)

JobApplicationFactory(to_company=company, selected_jobs=[job], state="new")
response = client.get(self.URL, {"city": city.slug})
assertContains(response, popular_badge, html=True)
assertContains(response, overwhelmed_badge, html=True)

def test_no_department(self, client):
create_test_romes_and_appellations(("N1101", "N1105", "N1103", "N4105"))
Expand Down

0 comments on commit 278ab51

Please sign in to comment.