feat: Introducción de la resolución de la Comisión Evaluadora sobre un proyecto

parent b59a831c
Pipeline #582 failed with stage
in 1 second
......@@ -188,3 +188,9 @@ class EvaluadorForm(forms.ModelForm):
class Meta:
fields = ('evaluador',)
model = Proyecto
class ResolucionForm(forms.ModelForm):
class Meta:
fields = ('aceptacion_comision', 'ayuda_concedida', 'tipo_gasto', 'observaciones')
model = Proyecto
# Generated by Django 3.0.7 on 2020-06-22 06:44
from django.apps import apps as django_apps
from django.db import migrations, models
def add_permission_to_group(apps, schema_editor):
group = apps.get_model('auth', 'Group')
permission = apps.get_model('auth', 'Permission')
gestores = group.objects.get(name='Gestores')
permiso = permission.objects.get(codename='editar_aceptacion')
gestores.permissions.add(permiso)
def geo_post_migrate_signal(apps, schema_editor):
"""Emit the post-migrate signal during the migration.
Permissions are not actually created during or after an individual migration,
but are triggered by a post-migrate signal which is sent after the
`python manage.py migrate` command completes successfully.
This is necessary because this permission is used later in this migration.
"""
indo_config = django_apps.get_app_config('indo')
models.signals.post_migrate.send(
sender=indo_config,
app_config=indo_config,
verbosity=2,
interactive=False,
using=schema_editor.connection.alias,
)
class Migration(migrations.Migration):
dependencies = [('indo', '0008_auto_20200611_1002')]
operations = [
migrations.AlterModelOptions(
name='proyecto',
options={
'permissions': [
('listar_proyectos', 'Puede ver el listado de todos los proyectos.'),
('ver_proyecto', 'Puede ver cualquier proyecto.'),
('editar_proyecto', 'Puede editar cualquier proyecto en cualquier momento.'),
('listar_evaluadores', 'Puede ver el listado de evaluadores.'),
('editar_evaluador', 'Puede editar el evaluador de un proyecto.'),
('editar_aceptacion', 'Puede editar la decisión de la Comisión Evaluadora.'),
]
},
),
migrations.AddField(
model_name='proyecto',
name='aceptacion_comision',
field=models.BooleanField(null=True, verbose_name='Aceptación por la comisión'),
),
migrations.AddField(
model_name='proyecto',
name='ayuda_concedida',
field=models.PositiveIntegerField(null=True, verbose_name='Ayuda económica concedida'),
),
migrations.AddField(
model_name='proyecto',
name='observaciones',
field=models.TextField(
null=True, verbose_name='Observaciones para comunicar al coordinador'
),
),
migrations.AddField(
model_name='proyecto',
name='tipo_gasto',
field=models.TextField(
help_text='Indicar los gastos autorizados indicados por la Comisión.',
null=True,
verbose_name='Tipo de gasto posible',
),
),
migrations.RunPython(geo_post_migrate_signal),
migrations.RunPython(add_permission_to_group),
]
......@@ -445,6 +445,15 @@ class Proyecto(models.Model):
on_delete=models.PROTECT,
related_name='proyectos_evaluados',
)
# Aprobación de la Comisión Evaluadora
aceptacion_comision = models.BooleanField(_('Aceptación por la comisión'), null=True)
ayuda_concedida = models.PositiveIntegerField(_('Ayuda económica concedida'), null=True)
tipo_gasto = models.TextField(
_('Tipo de gasto posible'),
help_text=_('Indicar los gastos autorizados indicados por la Comisión.'),
null=True,
)
observaciones = models.TextField(_('Observaciones para comunicar al coordinador'), null=True)
class Meta:
permissions = [
......@@ -453,6 +462,7 @@ class Proyecto(models.Model):
('editar_proyecto', _('Puede editar cualquier proyecto en cualquier momento.')),
('listar_evaluadores', _('Puede ver el listado de evaluadores.')),
('editar_evaluador', _('Puede editar el evaluador de un proyecto.')),
('editar_aceptacion', _('Puede editar la decisión de la Comisión Evaluadora.')),
]
def __str__(self):
......
......@@ -18,8 +18,8 @@ class EvaluadoresTable(tables.Table):
def render_editar(self, record):
enlace = reverse('evaluador_update', args=[record.id])
return mark_safe(
f'''<a href="{enlace}" title={_("Editar el evaluador")}
aria-label={_("Editar el evaluador")}>
f'''<a href="{enlace}" title="{_('Editar el evaluador')}"
aria-label="{_('Editar el evaluador')}">
<span class="fas fa-pencil-alt"></span>
</a>'''
)
......@@ -46,8 +46,8 @@ class EvaluacionProyectosTable(tables.Table):
def render_evaluacion(self, record):
enlace = reverse('ver_evaluacion', args=[record.id])
return mark_safe(
f'''<a href="{enlace}" title={_('Ver la evaluación')}
aria-label={_('Ver la evaluación')}>
f'''<a href="{enlace}" title="{_('Ver la evaluación')}"
aria-label="{_('Ver la evaluación')}">
<span class="far fa-eye"></span>
</a>'''
if record.valoraciones.first()
......@@ -55,7 +55,15 @@ class EvaluacionProyectosTable(tables.Table):
)
def render_resolucion(self, record):
return 'FIXME'
enlace = reverse('resolucion_update', args=[record.id])
return mark_safe(
f'''<a href="{enlace}" title="{_('Editar la resolución de la Comisión')}"
aria-label="{_('Editar la resolución')}">
<span class="fas fa-pencil-alt"></span>
</a>'''
if record.valoraciones.first()
else '—'
)
class Meta:
attrs = {'class': 'table table-striped table-hover cabecera-azul'}
......@@ -78,8 +86,8 @@ class ProyectosEvaluadosTable(tables.Table):
def render_boton_evaluar(self, record):
enlace = reverse('evaluacion', args=[record.id])
return mark_safe(
f'''<a href="{enlace}" title={_("Evaluar el proyecto")}
aria-label={_('Evaluar el proyecto')} class="btn btn-info btn-sm">
f'''<a href="{enlace}" title="{_('Evaluar el proyecto')}"
aria-label="{_('Evaluar el proyecto')}" class="btn btn-info btn-sm">
<span class="fas fa-balance-scale" aria-hidden="true" style="display: inline;"></span>
&nbsp;{_('Evaluar')}
</a>'''
......@@ -99,7 +107,7 @@ class ProyectosTable(tables.Table):
def render_titulo(self, record):
enlace = reverse('proyecto_detail', args=[record.id])
return mark_safe(f"<a href='{enlace}'>{record.titulo}</a>")
return mark_safe(f'<a href="{enlace}">{record.titulo}</a>')
coordinadores = tables.Column(
empty_values=(), orderable=False, verbose_name=_('Coordinador(es)')
......@@ -107,7 +115,7 @@ class ProyectosTable(tables.Table):
def render_coordinadores(self, record):
coordinadores = record.get_coordinadores()
enlaces = [f"<a href='mailto:{c.email}'>{c.get_full_name()}</a>" for c in coordinadores]
enlaces = [f'<a href="mailto:{c.email}">{c.get_full_name()}</a>' for c in coordinadores]
return mark_safe(', '.join(enlaces))
class Meta:
......
......@@ -19,6 +19,7 @@ from .views import (
ProyectoEvaluacionesTableView,
ProyectoEvaluadorTableView,
ProyectoEvaluadorUpdateView,
ProyectoResolucionUpdateView,
ProyectoTableView,
ProyectoPresentarView,
ProyectoUpdateFieldView,
......@@ -58,6 +59,11 @@ urlpatterns = [
ProyectoEvaluadorUpdateView.as_view(),
name='evaluador_update',
),
path(
'gestion/proyecto/<int:pk>/editar_resolucion/',
ProyectoResolucionUpdateView.as_view(),
name='resolucion_update',
),
path(
'gestion/proyecto/<int:pk>/evaluacion/', EvaluacionVerView.as_view(), name='ver_evaluacion'
),
......
......@@ -21,6 +21,7 @@ from django.contrib.auth.mixins import (
UserPassesTestMixin,
)
from django.contrib.auth.models import Group
from django.contrib.messages.views import SuccessMessageMixin
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.forms.models import modelform_factory
......@@ -34,7 +35,7 @@ from django.views.generic import DetailView, RedirectView, TemplateView
from django.views.generic.edit import CreateView, DeleteView, UpdateView
# Local Django
from .forms import EvaluadorForm, InvitacionForm, ProyectoForm
from .forms import EvaluadorForm, InvitacionForm, ProyectoForm, ResolucionForm
from .models import (
Centro,
Convocatoria,
......@@ -316,6 +317,27 @@ class ProyectoEvaluadorUpdateView(LoginRequiredMixin, PermissionRequiredMixin, U
return reverse('evaluadores_table', kwargs={'anyo': self.object.convocatoria})
class ProyectoResolucionUpdateView(
LoginRequiredMixin, PermissionRequiredMixin, SuccessMessageMixin, UpdateView
):
"""Actualizar la resolución de la Comisión Evaluadora sobre un proyecto."""
permission_required = 'indo.editar_resolucion'
permission_denied_message = _('Sólo los gestores pueden acceder a esta página.')
model = Proyecto
success_message = _(
'Se ha guardado la resolución de la comisión sobre el proyecto «%(titulo)s».'
)
template_name = 'gestion/proyecto/editar_resolucion.html'
form_class = ResolucionForm
def get_success_message(self, cleaned_data):
return self.success_message % dict(cleaned_data, titulo=self.object.titulo)
def get_success_url(self):
return reverse_lazy('evaluaciones_table', args=[self.object.convocatoria_id])
class HomePageView(TemplateView):
template_name = 'home.html'
......
......@@ -60,7 +60,7 @@
{{ form.as_p }}
<br style="clear: both;" />
<div class="btn-group" role="group" aria-label="Botones">
<a href="{% url 'evaluadores_table' proyecto.convocatoria %}" class="btn btn-info">
<a href="{% url 'evaluadores_table' proyecto.convocatoria_id %}" class="btn btn-info">
<span class="fas fa-step-backward"></span> {% trans 'Retroceder' %}
</a>
<button class="btn btn-warning" type="submit">
......
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans 'Actualizar la resolución de la Comisión sobre el proyecto' %}{% endblock title %}
{% block description %}{% trans 'Actualizar la resolución de la Comisión sobre el proyecto' %}{% endblock description %}
{% block extracss %}<style>
label {
display: block;
font-size: 1.75rem;
font-weight: 500;
line-height: 1.2;
margin-bottom: 0.5rem;
margin-top: 0;
}
.helptext {
color: #6c757d !important;
display: block;
}
</style>
{% endblock extracss %}
{% block content %}
<div class="container-blanco">
<h1>{% trans 'Actualizar la resolución de la comisión sobre el proyecto' %}</h1>
<hr />
<br />
<div class="alert-info alert fade-in">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
<span class="fas fa-info-circle"></span>
<p>{% trans 'Aquí puede editar la resolución de la Comisión Evaluadora sobre el proyecto.' %}</p>
</div><br />
<p><label>Proyecto:</label> {{ proyecto.titulo }}</p>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<br style="clear: both;" />
<div class="btn-group" role="group" aria-label="Botones">
<a href="{% url 'evaluaciones_table' proyecto.convocatoria_id %}" class="btn btn-info">
<span class="fas fa-step-backward"></span> {% trans 'Retroceder' %}
</a>
<button class="btn btn-warning" type="submit">
<span class="fas fa-check"></span> {% trans 'Actualizar' %}
</button>
</div>
</form>
</div>
{% endblock content %}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment