Ejemplo n.º 1
0
def dashboard(request, template_name="dashboard/dashboard.html"):
    job_applications_counter = 0
    prescriber_authorization_status_not_set = None
    prescriber_is_orienter = False

    if request.user.is_siae_staff:
        siae = get_current_siae_or_404(request)
        job_applications_counter = siae.job_applications_received.filter(
            state=JobApplicationWorkflow.STATE_NEW).count()

    # See template for display message while authorized organization is being validated (prescriber path)

    if request.user.is_prescriber_with_org:
        prescriber_organization = get_current_org_or_404(request)
        prescriber_authorization_status_not_set = (
            prescriber_organization.authorization_status ==
            PrescriberOrganization.AuthorizationStatus.NOT_SET)
        # This is to hide the "secret code", except for orienter orgs
        prescriber_is_orienter = (
            prescriber_organization.authorization_status ==
            PrescriberOrganization.AuthorizationStatus.NOT_REQUIRED)

    context = {
        "job_applications_counter": job_applications_counter,
        "prescriber_authorization_status_not_set":
        prescriber_authorization_status_not_set,
        "prescriber_is_orienter": prescriber_is_orienter,
    }

    return render(request, template_name, context)
Ejemplo n.º 2
0
    def assert_invitation_is_accepted(self, response, user, invitation):
        self.assertRedirects(response, DASHBOARD_URL)

        user.refresh_from_db()
        invitation.refresh_from_db()
        self.assertTrue(user.is_prescriber)

        self.assertTrue(invitation.accepted)
        self.assertTrue(invitation.accepted_at)
        self.assertEqual(self.organization.members.count(), 3)

        # Make sure there's a welcome message.
        self.assertContains(
            response, escape(f"Vous êtes désormais membre de l'organisation {self.organization.display_name}.")
        )

        # A confirmation e-mail is sent to the invitation sender.
        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(len(mail.outbox[0].to), 1)
        self.assertEqual(invitation.sender.email, mail.outbox[0].to[0])

        # Assert the user sees his new organization dashboard.
        current_org = get_current_org_or_404(response.wsgi_request)
        # A user can be member of one or more organizations
        self.assertTrue(current_org in user.prescriberorganization_set.all())
Ejemplo n.º 3
0
def list_accredited_organizations(
        request,
        template_name="prescribers/list_accredited_organizations.html"):
    """
    List organizations accredited by a departmental council ("Conseil Départemental").
    """
    prescriber_org = get_current_org_or_404(request)

    required_permissions = [
        prescriber_org.is_authorized,
        prescriber_org.kind == prescriber_org.Kind.DEPT,
        prescriber_org.has_admin(request.user),
    ]

    if not all(required_permissions):
        raise PermissionDenied

    accredited_orgs = PrescriberOrganization.objects.get_accredited_orgs_for(
        prescriber_org).prefetch_active_memberships()

    context = {
        "prescriber_org": prescriber_org,
        "accredited_orgs": accredited_orgs
    }
    return render(request, template_name, context)
Ejemplo n.º 4
0
def members(request, template_name="prescribers/members.html"):
    """
    List members of a prescriber organization.
    """
    organization = get_current_org_or_404(request)

    members = organization.prescribermembership_set.select_related("user").all().order_by("joined_at")

    context = {"organization": organization, "members": members}
    return render(request, template_name, context)
Ejemplo n.º 5
0
def edit_organization(request, template_name="prescribers/edit_organization.html"):
    """
    Edit a prescriber organization.
    """
    organization = get_current_org_or_404(request)

    form = EditPrescriberOrganizationForm(instance=organization, data=request.POST or None)

    if request.method == "POST" and form.is_valid():
        form.save()
        messages.success(request, _("Mise à jour effectuée !"))
        return HttpResponseRedirect(reverse_lazy("dashboard:index"))

    context = {"form": form, "organization": organization}
    return render(request, template_name, context)
Ejemplo n.º 6
0
def deactivate_member(request,
                      user_id,
                      template_name="prescribers/deactivate_member.html"):
    organization = get_current_org_or_404(request)
    target_member = User.objects.get(pk=user_id)

    if deactivate_org_member(request=request,
                             target_member=target_member,
                             organization=organization):
        return HttpResponseRedirect(reverse_lazy("prescribers_views:members"))

    context = {
        "structure": organization,
        "target_member": target_member,
    }

    return render(request, template_name, context)
Ejemplo n.º 7
0
def member_list(request, template_name="prescribers/members.html"):
    """
    List members of a prescriber organization.
    """
    organization = get_current_org_or_404(request)

    members = (organization.prescribermembership_set.filter(
        is_active=True).select_related("user").all().order_by(
            "-is_admin", "joined_at"))
    pending_invitations = organization.invitations.pending()

    context = {
        "organization": organization,
        "members": members,
        "pending_invitations": pending_invitations,
    }
    return render(request, template_name, context)
Ejemplo n.º 8
0
def stats_cd(request, template_name=_STATS_HTML_TEMPLATE):
    """
    CD ("Conseil Départemental") stats shown to relevant members.
    They can only view data for their own departement.
    """
    current_org = get_current_org_or_404(request)
    if not request.user.can_view_stats_cd(current_org=current_org):
        raise PermissionDenied
    department = request.user.get_stats_cd_department(current_org=current_org)
    params = {
        DEPARTMENT_FILTER_KEY: DEPARTMENTS[department],
        REGION_FILTER_KEY: DEPARTMENT_TO_REGION[department],
    }
    context = {
        "iframeurl":
        metabase_embedded_url(settings.CD_STATS_DASHBOARD_ID, params=params),
        "page_title":
        f"Données de mon département : {DEPARTMENTS[department]}",
        "stats_base_url":
        settings.METABASE_SITE_URL,
    }
    return render(request, template_name, context)
Ejemplo n.º 9
0
def get_user_info(request):
    """
    Return a namedtuple containing information about the current logged user.
    """

    kind = None
    siae = None
    prescriber_organization = None

    if request.user.is_job_seeker:
        kind = KIND_JOB_SEEKER

    if request.user.is_siae_staff:
        kind = KIND_SIAE_STAFF
        siae = get_current_siae_or_404(request)

    if request.user.is_prescriber:
        kind = KIND_PRESCRIBER
        if request.user.is_prescriber_with_org:
            prescriber_organization = get_current_org_or_404(request)

    is_authorized_prescriber = prescriber_organization.is_authorized if prescriber_organization else False

    return UserInfo(request.user, kind, prescriber_organization, is_authorized_prescriber, siae)
Ejemplo n.º 10
0
def dashboard(request, template_name="dashboard/dashboard.html"):
    can_show_financial_annexes = False
    can_show_employee_records = False
    job_applications_categories = []

    # `current_org` can be a Siae, a PrescriberOrganization or an Institution.
    current_org = None

    if request.user.is_siae_staff:
        current_org = get_current_siae_or_404(request)
        can_show_financial_annexes = current_org.convention_can_be_accessed_by(request.user)
        can_show_employee_records = current_org.can_use_employee_record

        job_applications_categories = [
            {
                "name": "Candidatures à traiter",
                "states": [JobApplicationWorkflow.STATE_NEW, JobApplicationWorkflow.STATE_PROCESSING],
                "icon": "user-plus",
                "badge": "badge-danger",
            },
            {
                "name": "Candidatures acceptées ou mises en liste d'attente",
                "states": [JobApplicationWorkflow.STATE_ACCEPTED, JobApplicationWorkflow.STATE_POSTPONED],
                "icon": "user-check",
                "badge": "badge-secondary",
            },
            {
                "name": "Candidatures refusées/annulées",
                "states": [
                    JobApplicationWorkflow.STATE_REFUSED,
                    JobApplicationWorkflow.STATE_CANCELLED,
                    JobApplicationWorkflow.STATE_OBSOLETE,
                ],
                "icon": "user-x",
                "badge": "badge-secondary",
            },
        ]
        job_applications = current_org.job_applications_received.values("state").all()
        for category in job_applications_categories:
            category["counter"] = len([ja for ja in job_applications if ja["state"] in category["states"]])
            category[
                "url"
            ] = f"{reverse('apply:list_for_siae')}?{'&'.join([f'states={c}' for c in category['states']])}"

    if request.user.is_prescriber:
        try:
            current_org = get_current_org_or_404(request)
        except Http404:
            pass

    if request.user.is_labor_inspector:
        current_org = get_current_institution_or_404(request)

    context = {
        "lemarche_regions": settings.LEMARCHE_OPEN_REGIONS,
        "job_applications_categories": job_applications_categories,
        "can_create_siae_antenna": request.user.can_create_siae_antenna(parent_siae=current_org),
        "can_show_financial_annexes": can_show_financial_annexes,
        "can_show_employee_records": can_show_employee_records,
        "can_view_stats_dashboard_widget": request.user.can_view_stats_dashboard_widget(current_org=current_org),
        "can_view_stats_siae": request.user.can_view_stats_siae(current_org=current_org),
        "can_view_stats_cd": request.user.can_view_stats_cd(current_org=current_org),
        "can_view_stats_ddets": request.user.can_view_stats_ddets(current_org=current_org),
        "can_view_stats_dreets": request.user.can_view_stats_dreets(current_org=current_org),
        "can_view_stats_dgefp": request.user.can_view_stats_dgefp(current_org=current_org),
    }

    return render(request, template_name, context)
Ejemplo n.º 11
0
def invite_prescriber_with_org(request,
                               template_name="invitations_views/create.html"):
    organization = get_current_org_or_404(request)
    form_kwargs = {"sender": request.user, "organization": organization}

    # Initial data can be passed by GET params to ease invitation of new members
    request_invitation_form = signup_forms.PrescriberRequestInvitationForm(
        data=request.GET)
    if request_invitation_form.is_valid():
        # The prescriber has accepted the request for an invitation of an external user.
        # The form will be pre-filled with the new user information.
        initial_data = [{
            "first_name":
            request_invitation_form.cleaned_data.get("first_name"),
            "last_name":
            request_invitation_form.cleaned_data.get("last_name"),
            "email":
            request_invitation_form.cleaned_data.get("email"),
        }]
    else:
        initial_data = None

    formset = PrescriberWithOrgInvitationFormSet(data=request.POST or None,
                                                 initial=initial_data,
                                                 form_kwargs=form_kwargs)
    if request.POST:
        if formset.is_valid():
            # We don't need atomicity here (invitations are independent)
            invitations = formset.save()

            for invitation in invitations:
                invitation.send()

            count = len(formset.forms)
            if count == 1:
                message = (
                    "Votre invitation a été envoyée par courriel.<br>"
                    "Pour rejoindre votre organisation, il suffira simplement à votre invité(e) "
                    "de cliquer sur le lien de validation contenu dans le courriel.<br>"
                )
            else:
                message = (
                    "Vos invitations ont été envoyées par courriel.<br>"
                    "Pour rejoindre votre organisation, il suffira simplement à vos invités "
                    "de cliquer sur le lien de validation contenu dans le courriel.<br>"
                )

            expiration_date = formats.date_format(
                invitations[0].expiration_date)
            message += f"Le lien de validation est valable jusqu'au {expiration_date}."
            message = safestring.mark_safe(message)
            messages.success(request, message)

            return redirect(request.path)

    form_post_url = reverse("invitations_views:invite_prescriber_with_org")
    back_url = reverse("prescribers_views:members")
    context = {
        "back_url": back_url,
        "form_post_url": form_post_url,
        "formset": formset
    }

    return render(request, template_name, context)