Esempio n. 1
0
def edit_user_preferences(request, template_name="dashboard/edit_user_preferences.html"):
    if not request.user.is_siae_staff:
        raise PermissionDenied

    current_siae_pk = request.session.get(settings.ITOU_SESSION_CURRENT_SIAE_KEY)
    siae = get_object_or_404(Siae, pk=current_siae_pk)
    membership = request.user.siaemembership_set.get(siae=siae)
    new_job_app_notification_form = EditNewJobAppEmployersNotificationForm(
        recipient=membership, siae=siae, data=request.POST or None
    )

    dashboard_url = reverse_lazy("dashboard:index")
    back_url = get_safe_url(request, "back_url", fallback_url=dashboard_url)

    if request.method == "POST" and new_job_app_notification_form.is_valid():
        new_job_app_notification_form.save()
        messages.success(request, "Vos préférences ont été modifiées.")
        success_url = get_safe_url(request, "success_url", fallback_url=dashboard_url)
        return HttpResponseRedirect(success_url)

    context = {
        "new_job_app_notification_form": new_job_app_notification_form,
        "back_url": back_url,
    }

    return render(request, template_name, context)
Esempio n. 2
0
    def test_get_safe_url(self):
        """Test `urls.get_safe_url()`."""

        request = RequestFactory().get(
            "/?next=/siae/search%3Fdistance%3D100%26city%3Dstrasbourg-67"
        )
        url = get_safe_url(request, "next")
        expected = "/siae/search?distance=100&city=strasbourg-67"
        self.assertEqual(url, expected)

        request = RequestFactory().post(
            "/", data={"next": "/siae/search?distance=100&city=strasbourg-67"}
        )
        url = get_safe_url(request, "next")
        expected = "/siae/search?distance=100&city=strasbourg-67"
        self.assertEqual(url, expected)

        request = RequestFactory().get("/?next=https://evil.com/siae/search")
        url = get_safe_url(request, "next")
        expected = None
        self.assertEqual(url, expected)

        request = RequestFactory().post("/", data={"next": "https://evil.com"})
        url = get_safe_url(request, "next", fallback_url="/fallback")
        expected = "/fallback"
        self.assertEqual(url, expected)
Esempio n. 3
0
def suspension_update(request, suspension_id, template_name="approvals/suspension_update.html"):
    """
    Edit the given suspension.
    """

    siae = get_current_siae_or_404(request)
    suspension = get_object_or_404(Suspension, pk=suspension_id)

    if not suspension.can_be_handled_by_siae(siae):
        raise PermissionDenied()

    back_url = get_safe_url(request, "back_url", fallback_url=reverse("dashboard:index"))

    form = SuspensionForm(approval=suspension.approval, siae=siae, instance=suspension, data=request.POST or None)

    if request.method == "POST" and form.is_valid():
        suspension = form.save(commit=False)
        suspension.updated_by = request.user
        suspension.save()
        messages.success(request, "Modification de suspension effectuée.")
        return HttpResponseRedirect(back_url)

    context = {
        "suspension": suspension,
        "back_url": back_url,
        "form": form,
    }
    return render(request, template_name, context)
Esempio n. 4
0
def job_seeker_nir(request,
                   template_name="signup/job_seeker_nir.html",
                   redirect_field_name=REDIRECT_FIELD_NAME):
    form = forms.JobSeekerNirForm(data=request.POST or None)

    if request.method == "POST":
        next_url = reverse("signup:job_seeker")
        if form.is_valid():
            request.session[
                settings.ITOU_SESSION_NIR_KEY] = form.cleaned_data["nir"]

            # forward next page
            if redirect_field_name in form.data:
                next_url = f"{next_url}?{redirect_field_name}={form.data[redirect_field_name]}"

            return HttpResponseRedirect(next_url)

        if form.data.get("skip"):
            return HttpResponseRedirect(next_url)

    context = {
        "form": form,
        "redirect_field_name": redirect_field_name,
        "redirect_field_value": get_safe_url(request, redirect_field_name),
    }
    return render(request, template_name, context)
Esempio n. 5
0
def job_seeker_situation(request,
                         template_name="signup/job_seeker_situation.html",
                         redirect_field_name=REDIRECT_FIELD_NAME):
    """
    Second step of the signup process for jobseeker.

    The user is asked to choose at least one eligibility criterion to continue the signup process.
    """

    form = forms.JobSeekerSituationForm(data=request.POST or None)

    if request.method == "POST" and form.is_valid():
        next_url = reverse("signup:job_seeker_situation_not_eligible")

        # If at least one of the eligibility choices is selected, go to the signup form.
        if any(choice in forms.JobSeekerSituationForm.ELIGIBLE_SITUATION
               for choice in form.cleaned_data["situation"]):
            next_url = reverse("signup:job_seeker_nir")

        # forward next page
        if redirect_field_name in form.data:
            next_url = f"{next_url}?{redirect_field_name}={form.data[redirect_field_name]}"

        return HttpResponseRedirect(next_url)

    context = {
        "form": form,
        "redirect_field_name": redirect_field_name,
        "redirect_field_value": get_safe_url(request, redirect_field_name),
    }
    return render(request, template_name, context)
Esempio n. 6
0
def card(request, org_id, template_name="prescribers/card.html"):
    """
    Prescriber organization's card (or "Fiche" in French).
    """
    prescriber_org = get_object_or_404(PrescriberOrganization, pk=org_id, is_authorized=True)
    back_url = get_safe_url(request, "back_url")
    context = {"prescriber_org": prescriber_org, "back_url": back_url}
    return render(request, template_name, context)
Esempio n. 7
0
 def get_email_confirmation_redirect_url(self, request):
     """
     Redirection performed after a user confirmed its email address.
     """
     next_url = request.POST.get("next") or request.GET.get("next")
     url = super().get_email_confirmation_redirect_url(request)
     if next_url:
         url = get_safe_url(request, "next")
     return url
Esempio n. 8
0
def new_user(request,
             invitation_type,
             invitation_id,
             template_name="invitations_views/new_user.html"):
    invitation_type = InvitationAbstract.get_model_from_string(invitation_type)
    invitation = get_object_or_404(invitation_type, pk=invitation_id)
    context = {"invitation": invitation}
    next_step = None

    if request.user.is_authenticated:
        if not request.user.email == invitation.email:
            message = (
                "Un utilisateur est déjà connecté.<br>"
                "Merci de déconnecter ce compte en cliquant sur le bouton ci-dessous. "
                "La page d'accueil se chargera automatiquement, n'en tenez pas compte.<br>"
                "Retournez dans votre boite mail et cliquez de nouveau sur le lien "
                "reçu pour accepter l'invitation.")
            message = safestring.mark_safe(message)
            messages.error(request, message)
            return redirect("account_logout")

    if invitation.can_be_accepted:
        user = User.objects.filter(email__iexact=invitation.email)
        if user:
            # The user exists but he should log in first
            next_step_url = "{url}?account_type={account_type}&next={redirect_to}".format(
                url=reverse("account_login"),
                account_type=invitation.SIGNIN_ACCOUNT_TYPE,
                redirect_to=get_safe_url(request, "redirect_to"),
            )
            next_step = redirect(next_step_url)
        else:
            # A new user should be created before joining
            form = NewUserInvitationForm(data=request.POST or None,
                                         invitation=invitation)
            context["form"] = form
            if form.is_valid():
                user = form.save(request)
                get_adapter().login(request, user)
                next_step = redirect(get_safe_url(request, "redirect_to"))
    else:
        messages.error(request, "Cette invitation n'est plus valide.")

    return next_step or render(request, template_name, context=context)
Esempio n. 9
0
def card(request, siae_id, template_name="siaes/card.html"):
    """
    SIAE's card (or "Fiche" in French).
    """
    queryset = Siae.active_objects.prefetch_job_description_through(
        is_active=True)
    siae = get_object_or_404(queryset, pk=siae_id)
    back_url = get_safe_url(request, "back_url")
    context = {"siae": siae, "back_url": back_url}
    return render(request, template_name, context)
Esempio n. 10
0
File: views.py Progetto: ronnix/itou
def signup(request, template_name="signup/signup.html", redirect_field_name="next"):
    """
    Override allauth `account_signup` URL
    (the route is defined in config.urls).
    """
    context = {
        "redirect_field_name": redirect_field_name,
        "redirect_field_value": get_safe_url(request, redirect_field_name),
    }
    return render(request, template_name, context)
Esempio n. 11
0
File: views.py Progetto: ronnix/itou
def edit_user_info(request, template_name="dashboard/edit_user_info.html"):
    """
    Edit a user.
    """

    dashboard_url = reverse_lazy("dashboard:index")
    prev_url = get_safe_url(request, "prev_url", fallback_url=dashboard_url)
    form = EditUserInfoForm(instance=request.user, data=request.POST or None)

    if request.method == "POST" and form.is_valid():
        form.save()
        messages.success(request,
                         _("Mise à jour de vos informations effectuée !"))
        success_url = get_safe_url(request,
                                   "success_url",
                                   fallback_url=dashboard_url)
        return HttpResponseRedirect(success_url)

    context = {"form": form, "prev_url": prev_url}
    return render(request, template_name, context)
Esempio n. 12
0
def card(request, siae_id, template_name="siaes/card.html"):
    """
    SIAE's card (or "Fiche" in French).

    # COVID-19 "Operation ETTI".
    Public view (previously private, made public during COVID-19).
    """
    queryset = Siae.objects.prefetch_job_description_through(is_active=True)
    siae = get_object_or_404(queryset, pk=siae_id)
    back_url = get_safe_url(request, "back_url")
    context = {"siae": siae, "back_url": back_url}
    return render(request, template_name, context)
Esempio n. 13
0
def new_user(request,
             invitation_type,
             invitation_id,
             template_name="invitations_views/new_user.html"):

    invitation_type = InvitationAbstract.get_model_from_string(invitation_type)
    invitation = get_object_or_404(invitation_type, pk=invitation_id)
    context = {"invitation": invitation}
    next_step = None

    if request.user.is_authenticated:
        if not request.user.email == invitation.email:
            message = (
                "Un utilisateur précédent est déjà connecté.<br>"
                "Veuillez déconnecter ce compte en cliquant sur le bouton ci-dessous "
                "(ne tenez pas compte de la page d'accueil qui se chargera automatiquement) "
                "puis cliquez de nouveau sur le lien envoyé par e-mail pour accepter votre invitation."
            )
            message = safestring.mark_safe(message)
            messages.error(request, _(message))
            return redirect("account_logout")

    if invitation.can_be_accepted:
        user = get_user_model().objects.filter(email=invitation.email)
        if not user:
            form = NewUserForm(data=request.POST or None,
                               invitation=invitation)
            context["form"] = form
            if form.is_valid():
                user = form.save(request)
                DefaultAccountAdapter().login(request, user)
                next_step = redirect(get_safe_url(request, "redirect_to"))
        else:
            next_step = "{}?account_type={}&next={}".format(
                reverse("account_login"), invitation.SIGNIN_ACCOUNT_TYPE,
                get_safe_url(request, "redirect_to"))
            next_step = redirect(next_step)

    return next_step or render(request, template_name, context=context)
Esempio n. 14
0
def pe_approval_search_user(request, pe_approval_id, template_name="approvals/pe_approval_search_user.html"):
    """
    2nd step of the PoleEmploiApproval's conversion process.

    Search for a given user by email address.
    """
    pe_approval = get_object_or_404(PoleEmploiApproval, pk=pe_approval_id)

    back_url = get_safe_url(request, "back_url", fallback_url=reverse("dashboard:index"))

    form = UserExistsForm(data=None)

    context = {"back_url": back_url, "form": form, "pe_approval": pe_approval}
    return render(request, template_name, context)
Esempio n. 15
0
def job_description_card(request,
                         job_description_id,
                         template_name="siaes/job_description_card.html"):
    """
    SIAE's job description card (or "Fiche" in French).
    """
    job_description = get_object_or_404(SiaeJobDescription,
                                        pk=job_description_id)
    back_url = get_safe_url(request, "back_url")
    context = {
        "job": job_description,
        "siae": job_description.siae,
        "back_url": back_url,
    }
    return render(request, template_name, context)
Esempio n. 16
0
def siae_select(request, template_name="signup/siae_select.html"):
    """
    Entry point of the signup process for SIAEs which consists of 2 steps.

    The user is asked to select an SIAE based on a selection that match a given SIREN number.
    """

    siaes_without_members = None
    siaes_with_members = None

    next_url = get_safe_url(request, "next")

    siren_form = forms.SiaeSearchBySirenForm(data=request.GET or None)
    siae_select_form = None

    # The SIREN, when available, is always passed in the querystring.
    if request.method in ["GET", "POST"] and siren_form.is_valid():
        # Make sure to look only for active structures.
        siaes_for_siren = Siae.objects.active().filter(
            siret__startswith=siren_form.cleaned_data["siren"])
        # A user cannot join structures that already have members.
        # Show these structures in the template to make that clear.
        siaes_with_members = siaes_for_siren.exclude(members=None)
        siaes_without_members = siaes_for_siren.filter(members=None)
        siae_select_form = forms.SiaeSelectForm(data=request.POST or None,
                                                siaes=siaes_without_members)

    if request.method == "POST" and siae_select_form and siae_select_form.is_valid(
    ):
        siae_selected = siae_select_form.cleaned_data["siaes"]
        siae_selected.new_signup_activation_email_to_official_contact(
            request).send()
        message = (
            f"Nous venons d'envoyer un e-mail à l'adresse {siae_selected.obfuscated_auth_email} "
            f"pour continuer votre inscription. Veuillez consulter votre boite "
            f"de réception.")
        messages.success(request, message)
        return HttpResponseRedirect(next_url or "/")

    context = {
        "next_url": next_url,
        "siaes_without_members": siaes_without_members,
        "siaes_with_members": siaes_with_members,
        "siae_select_form": siae_select_form,
        "siren_form": siren_form,
    }
    return render(request, template_name, context)
Esempio n. 17
0
def details_for_siae(request, job_application_id, template_name="apply/process_details_siae.html"):
    """
    Detail of an application for an SIAE with the ability:
    - to update start date of a contract (provided given date is in the future),
    - to give an answer.
    """
    queryset = (
        JobApplication.objects.siae_member_required(request.user)
        .not_archived()
        .select_related(
            "job_seeker",
            "eligibility_diagnosis",
            "sender",
            "sender_siae",
            "sender_prescriber_organization",
            "to_siae",
            "approval",
        )
        .prefetch_related("selected_jobs__appellation")
    )
    job_application = get_object_or_404(queryset, id=job_application_id)

    transition_logs = job_application.logs.select_related("user").all().order_by("timestamp")

    approval_can_be_suspended_by_siae = job_application.approval and job_application.approval.can_be_suspended_by_siae(
        job_application.to_siae
    )
    approval_can_be_prolonged_by_siae = job_application.approval and job_application.approval.can_be_prolonged_by_siae(
        job_application.to_siae
    )
    expired_eligibility_diagnosis = EligibilityDiagnosis.objects.last_expired(
        job_seeker=job_application.job_seeker, for_siae=job_application.to_siae
    )
    back_url = get_safe_url(request, "back_url", fallback_url=reverse_lazy("apply:list_for_siae"))

    context = {
        "approvals_wrapper": job_application.job_seeker.approvals_wrapper,
        "approval_can_be_suspended_by_siae": approval_can_be_suspended_by_siae,
        "approval_can_be_prolonged_by_siae": approval_can_be_prolonged_by_siae,
        "eligibility_diagnosis": job_application.get_eligibility_diagnosis(),
        "expired_eligibility_diagnosis": expired_eligibility_diagnosis,
        "job_application": job_application,
        "transition_logs": transition_logs,
        "back_url": back_url,
    }
    return render(request, template_name, context)
Esempio n. 18
0
def declare_prolongation(request, approval_id, template_name="approvals/declare_prolongation.html"):
    """
    Declare a prolongation for the given approval.
    """

    siae = get_current_siae_or_404(request)
    approval = get_object_or_404(Approval, pk=approval_id)

    if not approval.can_be_prolonged_by_siae(siae):
        raise PermissionDenied()

    back_url = get_safe_url(request, "back_url", fallback_url=reverse("dashboard:index"))
    preview = False

    form = DeclareProlongationForm(approval=approval, siae=siae, data=request.POST or None)

    if request.method == "POST" and form.is_valid():

        prolongation = form.save(commit=False)
        prolongation.created_by = request.user
        prolongation.declared_by = request.user
        prolongation.declared_by_siae = form.siae
        prolongation.validated_by = form.validated_by

        if request.POST.get("edit"):
            preview = False
        if request.POST.get("preview"):
            preview = True
        elif request.POST.get("save"):
            prolongation.save()

            if form.cleaned_data.get("email"):
                # Send an email w/o DB changes
                prolongation.notify_authorized_prescriber()

            messages.success(request, "Déclaration de prolongation enregistrée.")
            return HttpResponseRedirect(back_url)

    context = {
        "approval": approval,
        "back_url": back_url,
        "form": form,
        "preview": preview,
    }
    return render(request, template_name, context)
Esempio n. 19
0
def step_application_sent(
        request,
        siae_pk,
        template_name="apply/submit_step_application_sent.html"):
    if request.user.is_siae_staff:
        dashboard_url = reverse("apply:list_for_siae")
        messages.success(request, "Candidature bien envoyée !")
        return HttpResponseRedirect(dashboard_url)

    session_data = request.session[settings.ITOU_SESSION_JOB_APPLICATION_KEY]
    back_url = get_safe_url(request=request, url=session_data["back_url"])
    job_seeker = get_object_or_404(User, pk=session_data["job_seeker_pk"])
    siae = get_object_or_404(Siae, pk=session_data["to_siae_pk"])

    context = {
        "back_url": back_url,
        "job_seeker": job_seeker,
        "siae": siae,
    }
    return render(request, template_name, context)
Esempio n. 20
0
def details_for_prescriber(request, job_application_id, template_name="apply/process_details_prescriber.html"):
    """
    Detail of an application for an SIAE with the ability:
    - to update start date of a contract (provided given date is in the future),
    - to give an answer.
    """
    job_applications = get_all_available_job_applications_as_prescriber(request)

    queryset = job_applications.select_related(
        "job_seeker",
        "eligibility_diagnosis",
        "sender",
        "sender_siae",
        "sender_prescriber_organization",
        "to_siae",
        "approval",
    ).prefetch_related("selected_jobs__appellation")
    job_application = get_object_or_404(queryset, id=job_application_id)

    transition_logs = job_application.logs.select_related("user").all().order_by("timestamp")

    # We are looking for the most plausible availability date for eligibility criterions
    before_date = job_application.hiring_end_at

    if before_date is None and job_application.approval and job_application.approval.end_at is not None:
        before_date = job_application.approval.end_at
    else:
        before_date = datetime.datetime.now()

    back_url = get_safe_url(request, "back_url", fallback_url=reverse_lazy("apply:list_for_prescriber"))

    context = {
        "approvals_wrapper": job_application.job_seeker.approvals_wrapper,
        "eligibility_diagnosis": job_application.get_eligibility_diagnosis(),
        "job_application": job_application,
        "transition_logs": transition_logs,
        "back_url": back_url,
    }
    return render(request, template_name, context)
Esempio n. 21
0
def job_description_card(request,
                         job_description_id,
                         template_name="siaes/job_description_card.html"):
    """
    SIAE's job description card (or "Fiche" in French).

    Public view.
    """
    job_description = get_object_or_404(SiaeJobDescription,
                                        pk=job_description_id)
    back_url = get_safe_url(request, "back_url")
    siae = job_description.siae
    others_active_jobs = (
        SiaeJobDescription.objects.select_related("appellation").filter(
            is_active=True, siae=siae).exclude(id=job_description_id).order_by(
                "-updated_at", "-created_at"))
    context = {
        "job": job_description,
        "siae": siae,
        "others_active_jobs": others_active_jobs,
        "back_url": back_url,
    }
    return render(request, template_name, context)
Esempio n. 22
0
def suspension_delete(request, suspension_id, template_name="approvals/suspension_delete.html"):
    """
    Delete the given suspension.
    """

    siae = get_current_siae_or_404(request)
    suspension = get_object_or_404(Suspension, pk=suspension_id)

    if not suspension.can_be_handled_by_siae(siae):
        raise PermissionDenied()

    back_url = get_safe_url(request, "back_url", fallback_url=reverse("dashboard:index"))

    if request.method == "POST" and request.POST.get("confirm") == "true":
        suspension.delete()
        messages.success(request, "Annulation de suspension effectuée.")
        return HttpResponseRedirect(back_url)

    context = {
        "suspension": suspension,
        "back_url": back_url,
    }
    return render(request, template_name, context)
Esempio n. 23
0
def suspend(request, approval_id, template_name="approvals/suspend.html"):
    """
    Suspend the given approval.
    """

    siae = get_current_siae_or_404(request)
    approval = get_object_or_404(Approval, pk=approval_id)

    if not approval.can_be_suspended_by_siae(siae):
        raise PermissionDenied()

    back_url = get_safe_url(request, "back_url", fallback_url=reverse("dashboard:index"))
    preview = False

    form = SuspensionForm(approval=approval, siae=siae, data=request.POST or None)

    if request.method == "POST" and form.is_valid():

        suspension = form.save(commit=False)
        suspension.created_by = request.user

        if request.POST.get("edit"):
            preview = False
        if request.POST.get("preview"):
            preview = True
        elif request.POST.get("save"):
            suspension.save()
            messages.success(request, "Suspension effectuée.")
            return HttpResponseRedirect(back_url)

    context = {
        "approval": approval,
        "back_url": back_url,
        "form": form,
        "preview": preview,
    }
    return render(request, template_name, context)
Esempio n. 24
0
def start(request, siae_pk):
    """
    Entry point.
    """

    siae = get_object_or_404(Siae, pk=siae_pk)

    if request.user.is_siae_staff and not siae.has_member(request.user):
        raise PermissionDenied(
            "Vous ne pouvez postuler pour un candidat que dans votre structure."
        )

    # Refuse all applications except those issued by the SIAE
    if siae.block_job_applications and not siae.has_member(request.user):
        # Message only visible in DEBUG
        raise Http404(
            "Cette organisation n'accepte plus de candidatures pour le moment."
        )

    back_url = get_safe_url(request, "back_url")

    # Start a fresh session.
    request.session[settings.ITOU_SESSION_JOB_APPLICATION_KEY] = {
        "back_url": back_url,
        "job_seeker_pk": None,
        "nir": None,
        "to_siae_pk": siae.pk,
        "sender_pk": None,
        "sender_kind": None,
        "sender_siae_pk": None,
        "sender_prescriber_organization_pk": None,
        "job_description_id": request.GET.get("job_description_id"),
    }

    next_url = reverse("apply:step_sender", kwargs={"siae_pk": siae.pk})
    return HttpResponseRedirect(next_url)
Esempio n. 25
0
    def inject_context_into_response(self, response, params):
        if isinstance(response, TemplateResponse):
            account_type = params.get("account_type")
            signup_url = reverse(
                ItouLoginView.ACCOUNT_TYPE_TO_SIGNUP_URL.get(
                    account_type, "account_signup"))
            show_sign_in_providers = account_type == "job_seeker"
            show_france_connect = settings.FRANCE_CONNECT_ENABLED
            signup_allowed = account_type != "institution"
            redirect_field_value = get_safe_url(self.request,
                                                REDIRECT_FIELD_NAME)

            context = {
                "account_type": account_type,
                "signup_url": signup_url,
                "show_sign_in_providers": show_sign_in_providers,
                "show_france_connect": show_france_connect,
                "redirect_field_name": REDIRECT_FIELD_NAME,
                "redirect_field_value": redirect_field_value,
                "signup_allowed": signup_allowed,
            }
            response.context_data.update(context)

        return response
Esempio n. 26
0
def edit_job_seeker_info(request, job_application_id, template_name="dashboard/edit_job_seeker_info.html"):
    job_application = get_object_or_404(JobApplication.objects.select_related("job_seeker"), pk=job_application_id)
    current_siae_pk = request.session.get(settings.ITOU_SESSION_CURRENT_SIAE_KEY)
    if not user_can_edit_job_seeker_info(request.user, job_application, current_siae_pk):
        raise PermissionDenied

    dashboard_url = reverse_lazy("dashboard:index")
    back_url = get_safe_url(request, "back_url", fallback_url=dashboard_url)
    form = EditUserInfoForm(
        request=request, instance=job_application.job_seeker, editor=request.user, data=request.POST or None
    )

    if request.method == "POST" and form.is_valid():
        form.save()
        messages.success(request, "Les informations du candidat ont été mises à jour.")
        return HttpResponseRedirect(back_url)

    context = {
        "form": form,
        "job_application": job_application,
        "prev_url": back_url,
    }

    return render(request, template_name, context)
Esempio n. 27
0
def prescriber_check_already_exists(
        request, template_name="signup/prescriber_check_already_exists.html"):
    """

    Entry point of the signup process for prescribers/orienteurs.

    The signup process consists of several steps during which the user answers
    a series of questions to determine the `kind` of his organization if any.

    Answers are kept in session.

    At the end of the process a user will be created and he will be:
    - added to the members of a pre-existing Pôle emploi agency ("prescripteur habilité")
    - added to the members of a new authorized organization ("prescripteur habilité")
    - added to the members of a new unauthorized organization ("orienteur")
    - without any organization ("orienteur")

    Step 1: makes it possible to avoid duplicates of prescriber's organizations.
    As 80% of prescribers on Itou are Pôle emploi members, a link is dedicated for users who work for PE.
    """

    # Start a fresh session that will be used during the signup process.
    # Since we can go back-and-forth, or someone always has the option
    # of using a direct link, its state must be kept clean in each step.
    request.session[settings.ITOU_SESSION_PRESCRIBER_SIGNUP_KEY] = {
        "authorization_status": None,
        "kind": None,
        "prescriber_org_data": None,
        "pole_emploi_org_pk": None,
        "safir_code": None,
        "url_history": [request.path],
        "next": get_safe_url(request, "next"),
    }

    prescriber_orgs_with_members_same_siret = None
    prescriber_orgs_with_members_same_siren = None

    form = forms.PrescriberCheckAlreadyExistsForm(data=request.POST or None)

    if request.method == "POST" and form.is_valid():

        # Puts the data from API entreprise and geocoding in session for the last creation step
        session_data = request.session[
            settings.ITOU_SESSION_PRESCRIBER_SIGNUP_KEY]
        session_data["prescriber_org_data"] = form.org_data
        request.session.modified = True

        # Get organizations with members with precisely the same SIRET
        prescriber_orgs_with_members_same_siret = PrescriberOrganization.objects.prefetch_active_memberships(
        ).filter(siret=form.cleaned_data["siret"])

        # Get organizations with members with same SIREN but not the same SIRET
        prescriber_orgs_with_members_same_siren = (
            PrescriberOrganization.objects.prefetch_active_memberships(
            ).filter(siret__startswith=form.cleaned_data["siret"][:9],
                     department=form.cleaned_data["department"]).
            exclude(members=None).exclude(
                pk__in=[p.pk
                        for p in prescriber_orgs_with_members_same_siret]))

        # Redirect to creation steps if no organization with member is found,
        # else, displays the same form with the list of organizations with first member
        # to indicate which person to request an invitation from
        if not prescriber_orgs_with_members_same_siret and not prescriber_orgs_with_members_same_siren:
            return HttpResponseRedirect(
                reverse("signup:prescriber_choose_org"))

    context = {
        "prescriber_orgs_with_members_same_siret":
        prescriber_orgs_with_members_same_siret,
        "prescriber_orgs_with_members_same_siren":
        prescriber_orgs_with_members_same_siren,
        "form": form,
    }
    return render(request, template_name, context)