Skip to content

Commit

Permalink
job_seekers_views: disconnect jobseeker update views from apply
Browse files Browse the repository at this point in the history
The UpdateJobSeeker* views do not inherit from `apply` views anymore.
The URL is changed to use the `session_uuid` parameter.
  • Loading branch information
EwenKorr committed Dec 5, 2024
1 parent 46a14f9 commit ca4e8fa
Show file tree
Hide file tree
Showing 9 changed files with 1,229 additions and 1,074 deletions.
2 changes: 1 addition & 1 deletion itou/templates/apply/submit/application/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ <h1 class="flex-grow-1">{% include 'apply/includes/_submit_title.html' %}</h1>
<p>
Dernière actualisation du profil : {{ job_seeker.last_checked_at|date }} à {{ job_seeker.last_checked_at|time }}
{% if can_view_personal_information and not request.user.is_job_seeker %}
<a class="btn btn-link" href="{% url "job_seekers_views:update_job_seeker_step_1" company_pk=siae.pk job_seeker_public_id=job_seeker.public_id %}">Vérifier le profil</a>
<a class="btn btn-link" href="{{ update_job_seeker_url }}">Vérifier le profil</a>
{% endif %}
{% if new_check_needed %}<i class="ri-information-line ri-xl text-warning"></i>{% endif %}
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ <h1>
<div class="c-box my-4">
<h2>
Informations personnelles
<a class="btn btn-outline-primary float-end" href="{% url "job_seekers_views:update_job_seeker_step_1_for_hire" company_pk=siae.pk job_seeker_public_id=job_seeker.public_id %}">Mettre à jour</a>
<a class="btn btn-outline-primary float-end" href="{{ update_job_seeker_url }}">Mettre à jour</a>
</h2>

{% include "apply/includes/profile_infos.html" %}
Expand Down
38 changes: 38 additions & 0 deletions itou/www/apply/views/submit_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,33 @@ def setup(self, request, *args, **kwargs):
self.job_seeker, for_company
)

# Init a job_seeker_session to create links to update job seeker.
if self.apply_session.exists() and not self.apply_session.get("job_seeker_session_name"):
job_seeker_session = self.init_job_seeker_session(request)
job_seeker_session.set("job_seeker_pk", self.job_seeker.pk)
self.apply_session.set("job_seeker_session_name", job_seeker_session.name)

def update_job_seeker_session_config(self, new_config):
job_seeker_session = SessionNamespace(self.request.session, self.apply_session.get("job_seeker_session_name"))
if not job_seeker_session.exists():
job_seeker_session.init(
{
"config": {
"reset_url": self.get_reset_url(),
},
"apply": {"company_pk": self.company.pk},
}
)
job_seeker_session.set("config", new_config)

def get_update_job_seeker_url(self):
view_name = (
"job_seekers_views:update_job_seeker_step_1_for_hire"
if self.hire_process
else "job_seekers_views:update_job_seeker_step_1"
)
return reverse(view_name, kwargs={"session_uuid": self.apply_session.get("job_seeker_session_name")})

def get_context_data(self, **kwargs):
return super().get_context_data(**kwargs) | {
"job_seeker": self.job_seeker,
Expand All @@ -226,6 +253,7 @@ def get_context_data(self, **kwargs):
not self.request.user.is_job_seeker
and self.job_seeker.last_checked_at < timezone.now() - JOB_SEEKER_INFOS_CHECK_PERIOD
),
"update_job_seeker_url": self.get_update_job_seeker_url(),
}

def get_previous_applications_queryset(self):
Expand Down Expand Up @@ -422,6 +450,16 @@ def setup(self, request, *args, **kwargs):
data=request.POST or None,
)

if self.job_seeker:
self.update_job_seeker_session_config(
{
"reset_url": reverse(
"apply:application_jobs",
kwargs={"company_pk": self.company.pk, "job_seeker_public_id": self.job_seeker.public_id},
)
}
)

def get_next_url(self):
# dispatching to IAE or GEIQ eligibility
path_name = (
Expand Down
16 changes: 8 additions & 8 deletions itou/www/job_seekers_views/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,25 +73,25 @@
kwargs={"hire_process": True},
),
path(
"<int:company_pk>/hire/update/<uuid:job_seeker_public_id>/1",
"<uuid:session_uuid>/hire/update/1",
views.UpdateJobSeekerStep1View.as_view(),
name="update_job_seeker_step_1_for_hire",
kwargs={"hire_process": True},
),
path(
"<int:company_pk>/hire/update/<uuid:job_seeker_public_id>/2",
"<uuid:session_uuid>/hire/update/2",
views.UpdateJobSeekerStep2View.as_view(),
name="update_job_seeker_step_2_for_hire",
kwargs={"hire_process": True},
),
path(
"<int:company_pk>/hire/update/<uuid:job_seeker_public_id>/3",
"<uuid:session_uuid>/hire/update/3",
views.UpdateJobSeekerStep3View.as_view(),
name="update_job_seeker_step_3_for_hire",
kwargs={"hire_process": True},
),
path(
"<int:company_pk>/hire/update/<uuid:job_seeker_public_id>/end",
"<uuid:session_uuid>/hire/update/end",
views.UpdateJobSeekerStepEndView.as_view(),
name="update_job_seeker_step_end_for_hire",
kwargs={"hire_process": True},
Expand All @@ -110,22 +110,22 @@
),
# Job seeker check/updates
path(
"<int:company_pk>/update/<uuid:job_seeker_public_id>/1",
"<uuid:session_uuid>/update/1",
views.UpdateJobSeekerStep1View.as_view(),
name="update_job_seeker_step_1",
),
path(
"<int:company_pk>/update/<uuid:job_seeker_public_id>/2",
"<uuid:session_uuid>/update/2",
views.UpdateJobSeekerStep2View.as_view(),
name="update_job_seeker_step_2",
),
path(
"<int:company_pk>/update/<uuid:job_seeker_public_id>/3",
"<uuid:session_uuid>/update/3",
views.UpdateJobSeekerStep3View.as_view(),
name="update_job_seeker_step_3",
),
path(
"<int:company_pk>/update/<uuid:job_seeker_public_id>/end",
"<uuid:session_uuid>/update/end",
views.UpdateJobSeekerStepEndView.as_view(),
name="update_job_seeker_step_end",
),
Expand Down
76 changes: 54 additions & 22 deletions itou/www/job_seekers_views/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
from itou.utils.apis.exceptions import AddressLookupError
from itou.utils.emails import redact_email_address
from itou.utils.pagination import ItouPaginator
from itou.utils.session import SessionNamespace, SessionNamespaceRequiredMixin
from itou.utils.session import SessionNamespace
from itou.utils.urls import get_safe_url
from itou.www.apply.views.submit_views import ApplicationBaseView, ApplyStepBaseView
from itou.www.apply.views.submit_views import ApplicationBaseView

from .forms import (
CheckJobSeekerInfoForm,
Expand Down Expand Up @@ -771,7 +771,7 @@ def get_context_data(self, **kwargs):
return super().get_context_data(**kwargs) | {"profile": self.profile, "progress": "80"}


class UpdateJobSeekerBaseView(SessionNamespaceRequiredMixin, ApplyStepBaseView):
class UpdateJobSeekerBaseView(JobSeekerBaseView):
def __init__(self):
super().__init__()
self.job_seeker_session = None
Expand All @@ -780,14 +780,35 @@ def get_job_seeker_queryset(self):
return User.objects.filter(kind=UserKind.JOB_SEEKER)

def setup(self, request, *args, **kwargs):
self.job_seeker = get_object_or_404(self.get_job_seeker_queryset(), public_id=kwargs["job_seeker_public_id"])
self.job_seeker_session = SessionNamespace(request.session, f"job_seeker-{self.job_seeker.public_id}")
super().setup(request, *args, **kwargs)
self.job_seeker = get_object_or_404(
self.get_job_seeker_queryset(), pk=self.job_seeker_session.get("job_seeker_pk")
)
if request.user.is_authenticated and (
request.user.is_job_seeker or not request.user.can_view_personal_information(self.job_seeker)
):
# Since the link leading to this process isn't visible to those users, this should never happen
raise PermissionDenied("Votre utilisateur n'est pas autorisé à vérifier les informations de ce candidat")
super().setup(request, *args, **kwargs)

def dispatch(self, request, *args, **kwargs):
if not self.is_gps:
if request.user.is_authenticated:
if self.hire_process and request.user.kind != UserKind.EMPLOYER:
raise PermissionDenied("Seuls les employeurs sont autorisés à déclarer des embauches")
elif self.hire_process and not self.company.has_member(request.user):
raise PermissionDenied("Vous ne pouvez déclarer une embauche que dans votre structure.")
elif request.user.kind not in [
UserKind.JOB_SEEKER,
UserKind.PRESCRIBER,
UserKind.EMPLOYER,
]:
raise PermissionDenied("Vous n'êtes pas autorisé à déposer de candidature.")

if not self.company.has_active_members:
raise PermissionDenied(
"Cet employeur n'est pas inscrit, vous ne pouvez pas déposer de candidatures en ligne."
)
return super().dispatch(request, *args, **kwargs)

def get_context_data(self, **kwargs):
return super().get_context_data(**kwargs) | {
Expand All @@ -797,31 +818,31 @@ def get_context_data(self, **kwargs):
"job_seekers_views:update_job_seeker_step_3_for_hire"
if self.hire_process
else "job_seekers_views:update_job_seeker_step_3",
kwargs={"company_pk": self.company.pk, "job_seeker_public_id": self.job_seeker.public_id},
),
"reset_url": reverse(
"apply:application_jobs",
kwargs={"company_pk": self.company.pk, "job_seeker_public_id": self.job_seeker.public_id},
kwargs={"session_uuid": self.job_seeker_session.name},
),
"reset_url": self.get_reset_url(),
"readonly_form": False,
}

def _disable_form(self):
for field in self.form:
field.field.disabled = True

def get_reset_url(self):
return self.job_seeker_session.get("config").get("reset_url")

def get_back_url(self):
view_name = self.previous_hire_url if self.hire_process else self.previous_apply_url
return reverse(
view_name,
kwargs={"company_pk": self.company.pk, "job_seeker_public_id": self.job_seeker.public_id},
kwargs={"session_uuid": self.job_seeker_session.name},
)

def get_next_url(self):
view_name = self.next_hire_url if self.hire_process else self.next_apply_url
return reverse(
view_name,
kwargs={"company_pk": self.company.pk, "job_seeker_public_id": self.job_seeker.public_id},
kwargs={"session_uuid": self.job_seeker_session.name},
)


Expand All @@ -845,8 +866,8 @@ def setup(self, request, *args, **kwargs):
if not request.user.is_authenticated:
# Do nothing, LoginRequiredMixin will raise in dispatch()
return
if not self.job_seeker_session.exists():
self.job_seeker_session.init({"user": {}})
if not self.job_seeker_session.get("user"):
self.job_seeker_session.set("user", {})
session_nir = self.job_seeker_session.get("profile", {}).get("nir")
session_lack_of_nir_reason = self.job_seeker_session.get("profile", {}).get("lack_of_nir_reason")

Expand Down Expand Up @@ -882,6 +903,9 @@ def post(self, request, *args, **kwargs):

return self.render_to_response(self.get_context_data(**kwargs))

def get_back_url(self):
return self.get_reset_url()

def get_context_data(self, **kwargs):
return super().get_context_data(**kwargs) | {
"confirmation_needed": False,
Expand All @@ -894,7 +918,6 @@ def get_context_data(self, **kwargs):

class UpdateJobSeekerStep2View(UpdateJobSeekerBaseView):
template_name = "job_seekers_views/create_or_update_job_seeker/step_2.html"
required_session_namespaces = ["job_seeker_session"] + UpdateJobSeekerBaseView.required_session_namespaces

previous_apply_url = "job_seekers_views:update_job_seeker_step_1"
previous_hire_url = "job_seekers_views:update_job_seeker_step_1_for_hire"
Expand All @@ -907,6 +930,9 @@ def __init__(self):

def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)
if not request.user.is_authenticated:
# Do nothing, LoginRequiredMixin will raise in dispatch()
return
self.form = CreateOrUpdateJobSeekerStep2Form(
instance=self.job_seeker,
initial=self.job_seeker_session.get("user", {}),
Expand Down Expand Up @@ -934,7 +960,6 @@ def get_context_data(self, **kwargs):

class UpdateJobSeekerStep3View(UpdateJobSeekerBaseView):
template_name = "job_seekers_views/create_or_update_job_seeker/step_3.html"
required_session_namespaces = ["job_seeker_session"] + UpdateJobSeekerBaseView.required_session_namespaces

previous_apply_url = "job_seekers_views:update_job_seeker_step_2"
previous_hire_url = "job_seekers_views:update_job_seeker_step_2_for_hire"
Expand All @@ -950,6 +975,9 @@ def get_job_seeker_queryset(self):

def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)
if not request.user.is_authenticated:
# Do nothing, LoginRequiredMixin will raise in dispatch()
return

session_pole_emploi_id = self.job_seeker_session.get("profile", {}).get("pole_emploi_id")
session_lack_of_pole_emploi_id_reason = self.job_seeker_session.get("profile", {}).get(
Expand Down Expand Up @@ -989,12 +1017,9 @@ def get_context_data(self, **kwargs):

class UpdateJobSeekerStepEndView(UpdateJobSeekerBaseView):
template_name = "job_seekers_views/create_or_update_job_seeker/step_end.html"
required_session_namespaces = ["job_seeker_session"] + UpdateJobSeekerBaseView.required_session_namespaces

previous_apply_url = "job_seekers_views:update_job_seeker_step_3"
previous_hire_url = "job_seekers_views:update_job_seeker_step_3_for_hire"
next_apply_url = "apply:application_jobs"
next_hire_url = "job_seekers_views:check_job_seeker_info_for_hire"

def __init__(self):
super().__init__()
Expand Down Expand Up @@ -1027,6 +1052,9 @@ def _get_profile_data_from_session(self):

def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)
if not request.user.is_authenticated:
# Do nothing, LoginRequiredMixin will raise in dispatch()
return

allowed_user_fields_to_update = []
if self.request.user.can_edit_personal_information(self.job_seeker):
Expand Down Expand Up @@ -1068,14 +1096,18 @@ def post(self, request, *args, **kwargs):
messages.error(request, " ".join(e.messages))
url = reverse(
"job_seekers_views:update_job_seeker_step_1",
kwargs={"company_pk": self.company.pk, "job_seeker_public_id": self.job_seeker.public_id},
kwargs={"session_uuid": self.job_seeker_session.name},
)
else:
self.profile.save()
self.job_seeker_session.delete()
url = self.get_next_url()
self.job_seeker_session.delete()
return HttpResponseRedirect(url)

def get_next_url(self):
# In Update views, when finished, we go back to where we were.
return self.job_seeker_session.get("config").get("reset_url")

def get_context_data(self, **kwargs):
return super().get_context_data(**kwargs) | {"profile": self.profile, "progress": "80"}

Expand Down
Loading

0 comments on commit ca4e8fa

Please sign in to comment.