views.py 8.47 KB
Newer Older
1
import json
2
from datetime import date
3
from django.conf import settings
4
from django.contrib import messages
5
from django.contrib.auth.mixins import LoginRequiredMixin
6
from django.forms.models import modelform_factory
7
from django.http import HttpResponseRedirect
8 9
from django.http.response import HttpResponse
from django.shortcuts import render, redirect
10
from django.urls import reverse, reverse_lazy
11 12 13 14 15
from django.utils.translation import gettext_lazy as _
from django.views.generic import (
    DetailView,
    FormView,
    ListView,
16
    RedirectView,
17 18 19 20
    TemplateView,
    View,
)
from django.views.generic.edit import CreateView, UpdateView, DeleteView
21
from django_summernote.widgets import SummernoteWidget
22

23 24
from templated_email import send_templated_mail

25
from .forms import InvitacionForm, ProyectoForm
26 27 28 29 30 31 32 33 34
from .models import (
    Convocatoria,
    Evento,
    ParticipanteProyecto,
    Proyecto,
    Registro,
    TipoParticipacion,
)

35

36 37 38 39 40 41
class AyudaView(TemplateView):
    template_name = "ayuda.html"


class HomePageView(TemplateView):
    template_name = "home.html"
42 43


44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
class InvitacionView(LoginRequiredMixin, CreateView):
    """Formulario para invitar a una persona a un proyecto determinado."""

    # TODO: Comprobar permisos, estado del proyecto, fecha.
    form_class = InvitacionForm
    model = ParticipanteProyecto
    template_name = "participante-proyecto/invitar.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        proyecto_id = self.kwargs["proyecto_id"]
        context["proyecto"] = Proyecto.objects.get(id=proyecto_id)
        return context

    def get_form_kwargs(self, **kwargs):
        kwargs = super().get_form_kwargs()
        # Update the kwargs for the form init method with ours
61
        kwargs.update(self.kwargs)  # self.kwargs contains all URL conf params
62
        kwargs["request"] = self.request
63 64 65
        return kwargs

    def get_success_url(self, **kwargs):
66 67 68
        return reverse_lazy(
            "proyecto_detail", kwargs={"pk": self.kwargs["proyecto_id"]}
        )
69 70


71 72 73 74 75 76 77 78 79 80
class ParticipanteDeleteView(LoginRequiredMixin, DeleteView):
    """Borrar un registro de ParticipanteProyecto"""

    model = ParticipanteProyecto
    template_name = "participante-proyecto/confirm_delete.html"

    def get_success_url(self):
        return reverse_lazy("proyecto_detail", args=[self.object.proyecto.id])


81 82 83
class ProyectoCreateView(LoginRequiredMixin, CreateView):
    """Crea una nueva solicitud de proyecto"""

84 85 86
    # TODO: Comprobar usuario para Proyectos de titulación y POU.
    # TODO: Comprobar fecha

87 88
    model = Proyecto
    template_name = "proyecto/new.html"
89 90
    # fields = ["titulo", "descripcion", "programa", "linea", "centro", "estudio"]
    form_class = ProyectoForm
91 92

    def form_valid(self, form):
93 94
        # This method is called when valid form data has been POSTed, to do custom logic on form data.
        # It should return an HttpResponse.
95 96 97 98 99
        proyecto = form.save()
        self._guardar_coordinador(proyecto)
        self._registrar_creacion(proyecto)
        return redirect("proyecto_detail", proyecto.id)

100 101 102 103 104 105
    def get_form(self, form_class=None):
        """Devuelve el formulario añadiendo automáticamente el campo Convocatoria, que es requerido."""
        form = super(ProyectoCreateView, self).get_form(form_class)
        form.instance.convocatoria = Convocatoria(date.today().year)
        return form

106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
    def _guardar_coordinador(self, proyecto):
        # Los PIET debe solicitarlos uno de los coordinadores del estudio ("coordinador principal")
        # quien podrá nombrar a otro coordinador.
        if proyecto.programa.nombre_corto == "PIET":
            tipo_participacion = "coordinador_principal"
        else:
            tipo_participacion = "coordinador"

        participanteProyecto = ParticipanteProyecto(
            proyecto=proyecto,
            tipo_participacion=TipoParticipacion(nombre=tipo_participacion),
            usuario=self.request.user,
        )
        participanteProyecto.save()

    def _registrar_creacion(self, proyecto):
        evento = Evento.objects.get(nombre="creacion_solicitud")
        registro = Registro(
            descripcion="Creación inicial de la solicitud",
            evento=evento,
            proyecto=proyecto,
        )
        registro.save()


class ProyectoDetailView(DetailView):
132 133 134 135
    """Muestra una solicitud de proyecto."""

    # TODO: Comprobar permisos
    #   - Coordinadores, participantes/invitados, evaluadores.  Gestores.
136 137 138 139 140 141 142 143 144 145 146 147 148 149
    model = Proyecto
    template_name = "proyecto/detail.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        coordinador_principal = self.object.get_participante_or_none(
            "coordinador_principal"
        )
        context["coordinador_principal"] = coordinador_principal

        coordinador = self.object.get_participante_or_none("coordinador")
        context["coordinador"] = coordinador

150 151 152 153 154 155 156 157 158 159 160 161 162 163
        participantes = (
            self.object.participantes.filter(tipo_participacion="participante")
            .order_by("usuario__first_name", "usuario__last_name")
            .all()
        )
        context["participantes"] = participantes

        invitados = (
            self.object.participantes.filter(tipo_participacion="invitado")
            .order_by("usuario__first_name", "usuario__last_name")
            .all()
        )
        context["invitados"] = invitados

164 165
        context["campos"] = json.loads(self.object.programa.campos)

166
        return context
167 168


169 170 171 172 173
class ProyectoPresentarView(LoginRequiredMixin, RedirectView):
    """
    Presentar una solicitud de proyecto.
    El proyecto pasa de estado «Borrador» a estado «Solicitado».
    """
174

175 176 177 178 179 180 181 182 183 184
    # TODO: Comprobar permisos, fecha

    def get_redirect_url(self, *args, **kwargs):
        return reverse_lazy("proyecto_detail", args=[kwargs.get("pk")])

    def post(self, request, *args, **kwargs):
        proyecto_id = kwargs.get("pk")
        proyecto = Proyecto.objects.get(pk=proyecto_id)

        # TODO ¿Chequear el estado actual del proyecto?
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
        # TODO Enviar mensaje a aprobadores

        # Enviar mensaje a los invitados al proyecto
        for invitado in proyecto.participantes.filter(tipo_participacion="invitado"):
            send_templated_mail(
                template_name="invitacion",
                from_email=None,  # settings.DEFAULT_FROM_EMAIL
                recipient_list=[invitado.usuario.email],
                context={
                    "nombre_coordinador": request.user.get_full_name(),
                    "nombre_invitado": invitado.usuario.get_full_name(),
                    "sexo_invitado": invitado.usuario.sexo,
                    "titulo_proyecto": proyecto.titulo,
                    "programa_proyecto": f"{proyecto.programa.nombre_corto} ({proyecto.programa.nombre_largo})",
                    "descripcion_proyecto": proyecto.descripcion,
                },
            )

203 204 205 206 207 208 209 210
        proyecto.estado = "SOLICITADO"
        proyecto.save()

        # TODO Modificar detail.html para no mostrar botones de edición/presentación
        messages.success(request, _("Su solicitud de proyecto ha sido presentada."))
        return super().post(request, *args, **kwargs)


211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
class ProyectoUpdateFieldView(LoginRequiredMixin, UpdateView):
    # TODO: Comprobar permisos - coordinadores
    #       Modificar estado, sólo para gestores
    #       No permitir modificar convocatoria, etc
    # TODO: Comprobar estado/fecha
    model = Proyecto
    template_name = "proyecto/update.html"

    def get_form_class(self, **kwargs):
        campo = self.kwargs["campo"]
        if campo not in (
            "centro",
            "convocatoria",
            "departamento",
            "licencia",
            "linea",
            "programa",
            "ayuda",
            "estado",
        ):
            return modelform_factory(
                Proyecto, fields=(campo,), widgets={campo: SummernoteWidget()}
            )
        self.fields = (campo,)
        return super().get_form_class()
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252


class ProyectosUsuarioListView(LoginRequiredMixin, ListView):
    """Lista los proyectos coordinados por el usuario actual."""

    context_object_name = "proyectos"
    template_name = "proyecto/list.html"

    def get_queryset(self):
        # TODO ¿Listar sólo los de la convocatoria actual?
        usuario = self.request.user
        return Proyecto.objects.filter(
            participantes__tipo_participacion__in=[
                "coordinador",
                "coordinador_principal",
            ]
        ).filter(participantes__usuario=usuario)