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 : postuler pour un candidat depuis l'espace "Mes candidats" #4860

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

EwenKorr
Copy link
Contributor

@EwenKorr EwenKorr commented Oct 1, 2024

🤔 Pourquoi ?

ETQU, lorsque je clique sur le bouton postuler depuis une ligne de la liste candidat ou depuis une page de détail d’un candidat,

je peux faire une recherche d’emploi et postuler sans avoir à renseigner l’adresse e-mail, le NIR du candidat ou les informations personnelles du candidat.

🍰 Comment ?

On passe l'identifiant public du candidat en paramètre GET (job_seeker=UUID).
Une mixin permet d'ajouter aux vues utilisées la variable job_seeker dans le contexte, si l'utilisateur connecté a la permission (user.can_view_personal_info). Quand cette variable existe, les URLs utilisées contiennent paramètre GET, et un bandeau d'information rappelle que l'on postule pour un candidat.

🚨 À vérifier

  • Mettre à jour le CHANGELOG_breaking_changes.md ?

🏝️ Comment tester

Les instructions pour reproduire le problème, les profils de test, le parcours spécifique à utiliser, etc. Si vous disposez d'une recette jetable, mettre l'URL pour tester dans cette partie.

💻 Captures d'écran

@EwenKorr EwenKorr added the ajouté Ajouté dans le changelog. label Oct 1, 2024
@EwenKorr EwenKorr self-assigned this Oct 1, 2024
@EwenKorr EwenKorr changed the title Candidature : postuler pour un candidat depuis l'espace "Mes candiats" Candidature : postuler pour un candidat depuis l'espace "Mes candidats" Oct 1, 2024
@EwenKorr EwenKorr force-pushed the ewen/postuler-mes-candidats branch 4 times, most recently from fa19835 to 5f62cce Compare October 4, 2024 10:21
@EwenKorr EwenKorr added the 1-recette-jetable [Payé à l’heure] Crée une recette jetable sur CC label Oct 4, 2024
Copy link

github-actions bot commented Oct 4, 2024

🥁 La recette jetable est prête ! 👉 Je veux tester cette PR !

<p class="mb-0 text-start w-100">
<i class="ri-arrow-right-line pe-2"></i><strong>Vous postulez actuellement pour {{ job_seeker.get_full_name }}</strong>
</p>
<a href="{% if request.user.is_prescriber %}{% url "job_seekers_views:list" %}{% else %}{% url "apply:list_prescriptions" %}{% endif %}"
Copy link
Contributor Author

@EwenKorr EwenKorr Oct 4, 2024

Choose a reason for hiding this comment

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

Quitter :
Si prescripteur : retour à la liste des candidats
Si employeur : retour à la liste des orientations

@EwenKorr EwenKorr force-pushed the ewen/postuler-mes-candidats branch 2 times, most recently from 5cad6b6 to 17d7693 Compare October 4, 2024 12:21
Comment on lines +1055 to +1057
{
"fields": {
"address_filled_at": null,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Une utilisatrice en plus, orientée par une entreprise vers une autre entreprise
(ça permet de tester des choses là : http://127.0.0.1:8000/apply/prescriptions/list)

@@ -32,7 +49,7 @@ <h2 class="visually-hidden">Actions rapides</h2>
</div>
{% else %}
<div class="form-group col-12 col-lg-auto">
<a href="{% url 'apply:start' company_pk=siae.pk %}"
<a href="{% url 'apply:start' company_pk=siae.pk %}{% if job_seeker %}?job_seeker={{ job_seeker.public_id }}{% endif %}"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Pas mal d'ajouts de ?job_seeker= dans les liens jusqu'à apply:start.

@@ -245,6 +245,37 @@ def get(self, request, *args, **kwargs):
else:
self.apply_session.init({"selected_jobs": [job_description.pk]})

# Go directly to step ApplicationJobsView if we're carrying the job seeker public id with us.
if job_seeker_public_id := request.GET.get("job_seeker"):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

On vérifie ici si on a job_seeker= passé en paramètre.
On vérifie s'il est valide, s'il correspond à un candidat et si l'utilisateur actuel peut voir ses informations personnelles.

A priori, si on peut "Postuler pour ce candidat", on voit ses informations personnelles ?
Je ne suis pas sûr, cela dit.

Copy link
Contributor

@tonial tonial Oct 4, 2024

Choose a reason for hiding this comment

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

je crois bien qu'on peut postuler pour un candidat sans voir ses infos (son nom sera masqué notamment)

EDIT: oui.
Tu peux aller sur la demo, te connecter avec le compte d'orienteur et postuler pour le nir 201105918336235

image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah mais oui ! Et puis je vois que l'espace "Mes candidats" comporte des candidats sans infos personnelles.

image

- added a link in job seekers list ("Mes candidats")
  to apply in the name of a specific job seeker
- all the links up to `apply:start` have been updated
  with a GET param (`job_seeker={public_id}`), this
  allows to keep track of the job seeker we are
  applying for
- when a `job_seeker` GET param is present, and when
  the current `user` is allowed to, an alert is
  displayed at the top of the page to remind that
  we're applying for this job seeker
Comment on lines +1791 to +1792
# Create an empty variable to avoid unknown variable template errors in tests
context["job_seeker"] = None
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Bonne pratique ou pas ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Je trouve ça mieux que de devoir mettre des default partout dans les templates en tout cas :)

Comment on lines +85 to +87
'<a class="btn btn-ico btn-link" data-bs-toggle="tooltip" data-bs-placement="top" '
'title="Postuler pour ce candidat" '
f'href="{reverse("search:employers_results")}?job_seeker={public_id}">'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Peut-être un peu trop de markup ?

Comment on lines +1288 to +1293
f'<a href="{reverse("search:job_descriptions_results")}?city={guerande.slug}'
f'&job_seeker={job_seeker_public_id}" '
'class="btn btn-ico btn-dropdown-filter" aria-label="Réinitialiser les filtres actifs">'
'<i class="ri-eraser-line fw-bold" aria-hidden="true"></i>'
'<span>Effacer tout</span></a>'
)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Peut-être beaucoup trop de markup ?
Le moindre changement de classe fait capoter le test…
Mais en même temps je voudrais être sûr que le bouton "Effacet tout" contient bien l'attribut href avec job_seeker.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Un nouveau fichier de test, séparé du reste (vu que tout va être séparé par la suite).

@EwenKorr EwenKorr marked this pull request as ready for review October 4, 2024 12:46
Copy link
Contributor

@tonial tonial left a comment

Choose a reason for hiding this comment

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

Ça m'a l'air très efficace comme solution :)

Le mixin mérite d'être retravaillé je pense pour gérer la gestion de l'argument au début et non à la fin du traitement de la requête

Comment on lines +11 to +23
{% if job_seeker %}
<div class="alert alert-primary fade show " role="status">
<p class="mb-0 text-start w-100">
<i class="ri-arrow-right-line pe-2"></i><strong>Vous postulez actuellement pour {{ job_seeker.get_full_name }}</strong>
</p>
<a href="{% if request.user.is_prescriber %}{% url "job_seekers_views:list" %}{% else %}{% url "apply:list_prescriptions" %}{% endif %}"
class="btn btn-link-white btn-ico position-absolute top-0 end-0"
aria-label="Quitter">
<i class="ri-close-line ri-lg pe-2" aria-hidden="true"></i>
Quitter
</a>
</div>
{% endif %}
Copy link
Contributor

Choose a reason for hiding this comment

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

c'est présent plusieurs fois : tu devrais le mettre dans un template séparé et l'importer à chaque fois avec un include

@@ -7,7 +7,13 @@
<div class="col-12">
{% include "search/includes/siaes_search_subtitle.html" %}
<div class="d-block w-100">
<form hx-get="{{ request.path }}" hx-trigger="change delay:.5s" hx-include="#id_city" hx-indicator="#job-search-results" hx-target="#job-search-results" hx-swap="outerHTML" hx-push-url="true">
<form hx-get="{{ request.path }}{% if job_seeker %}?job_seeker={{ job_seeker.public_id }}{% endif %}"
Copy link
Contributor

Choose a reason for hiding this comment

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

tu as besoin de transmettre le job_seeker dans hx-get ?

Comment on lines +1791 to +1792
# Create an empty variable to avoid unknown variable template errors in tests
context["job_seeker"] = None
Copy link
Contributor

Choose a reason for hiding this comment

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

Je trouve ça mieux que de devoir mettre des default partout dans les templates en tout cas :)

.select_related("jobseeker_profile")
.first()
)
except ValidationError:
Copy link
Contributor

Choose a reason for hiding this comment

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

Je pense que si le job_seeker n'existe pas (le public_id n'est pas valide) il faudrait lever une 404, ou ou rediriger avec une erreur.

Du coup j'aurais tendance à traiter le query params job_seeker dans le setup() du mixin (ou dans le dispatch() peut-être, j'ai un doute) et à l'enregistrer dans self.job_seeker
Dans get_context_data() tu n'auras qu'à ajouter job_seeker au context s'il a été trouvé dans le setup()

# If anonymous user, do not show the alert (meaning the context does not contain the job_seeker)
response = self.client.get(url)
self.assertNotContains(
response, f"Vous postulez actuellement pour {job_application.job_seeker.get_full_name()}"
Copy link
Contributor

Choose a reason for hiding this comment

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

Tu devrais définir cette variable une fois au début du test, et la réutiliser par la suite :
BANNER_TXT = f"Vous postulez actuellement pour {job_application.job_seeker.get_full_name()}"

Comme ça, tu auras des assertContains(response, BANNER_TXT) et assertNotContains(response, BANNER_TXT) ce qui t'assures que le jour où ça change, tu modifies bien tout en même temps.

# If anonymous user, do not show the alert (meaning the context does not contain the job_seeker)
response = self.client.get(url)
self.assertNotContains(
response, f"Vous postulez actuellement pour {job_application.job_seeker.get_full_name()}"
Copy link
Contributor

Choose a reason for hiding this comment

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

idem dans ce test-ci

@@ -997,7 +997,7 @@

</ul>

<a class="btn btn-secondary btn-block mt-4" href="/company/[PK of Company]/card">Voir la fiche de l'entreprise</a>
<a class="btn btn-secondary btn-block mt-4" href="/company/[PK of Company]/card?">Voir la fiche de l'entreprise</a>
Copy link
Contributor

Choose a reason for hiding this comment

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

c'est normal que le ? apparaisse même quand il n'y a pas de job_seeker ?

@@ -22,7 +22,7 @@ <h3>{{ company.display_name }}</h3>
<a href="{% url 'apply:job_application_external_transfer_step_1_company_card' job_application_id=job_app_to_transfer company_pk=company.pk %}{% if back_url|default:"" %}?back_url={{ back_url|urlencode }}{% endif %}"
class="btn btn-secondary btn-block mt-4">Voir la fiche de l'entreprise</a>
{% else %}
<a href="{% url 'companies_views:card' siae_id=company.pk %}{% if back_url|default:"" and not open_in_tab|default:False %}?back_url={{ back_url|urlencode }}{% endif %}"
<a href="{% url 'companies_views:card' siae_id=company.pk %}?{% if job_seeker|default:None %}job_seeker={{ job_seeker.public_id }}&{% endif %}{% if back_url|default:"" and not open_in_tab|default:False %}back_url={{ back_url|urlencode }}{% endif %}"
Copy link
Contributor

Choose a reason for hiding this comment

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

hum... ça donne envie d'ajouter un template tag à qui on passe les arguments et qui les ajoute si la valeur est non nulle.
genre {% add_params job_seeker=job_seeker|default:None, back_url=back_url|default:"" %}

# Has link to company card with job_seeker public_id
company_url_with_job_seeker_id = (
f"{guerande_company.get_card_url()}?job_seeker={job_seeker_public_id}"
f"&back_url={urlencode_filter(response.wsgi_request.get_full_path())}"
Copy link
Contributor

Choose a reason for hiding this comment

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

tu peux utiliser urllib.parse.quote à la place de urlencode_filter (c'est la fonction qui est utilisée en dessous)
cf tests/www/apply/test_process_external_transfer.py

.select_related("jobseeker_profile")
.first()
)
except (User.DoesNotExist, ValueError, ValidationError):
Copy link
Contributor

Choose a reason for hiding this comment

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

User.DoesNotExist ne peut pas avoir lieu avec un first().

Le code ressemble beaucoup à celui dans le Mixin du commit précédent.
Il y a peut être moyen de mutualiser dans une fonction séparée ?

# Entry point: job seeker details
# ----------------------------------------------------------------------

response = self.client.get(reverse("job_seekers_views:details", kwargs={"public_id": job_seeker.public_id}))
Copy link
Contributor

Choose a reason for hiding this comment

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

les employeurs n'y ont pas vraiment accès, si ?
Je ne vois pas de lien pour y arriver

@EwenKorr EwenKorr removed the 1-recette-jetable [Payé à l’heure] Crée une recette jetable sur CC label Oct 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ajouté Ajouté dans le changelog.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants