Elaboración de las memorias (2)

Guardar los cambios
parent d5f287bb
Pipeline #613 failed with stage
in 0 seconds
......@@ -23,6 +23,7 @@ python3-saml = "*"
social-auth-app-django = "*"
social-auth-core = {extras = ["saml"],version = "*"}
zeep = "*"
python-magic = "*"
[requires]
python_version = "3.7"
This diff is collapsed.
# Generated by Django 3.1.2 on 2020-10-30 14:10
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [('indo', '0013_auto_20201026_1053')]
operations = [
migrations.AlterModelOptions(
name='memoriasubapartado',
options={
'ordering': ('apartado__numero', 'peso'),
'verbose_name': 'subapartado de la memoria',
'verbose_name_plural': 'subapartados de la memoria',
},
),
migrations.AlterField(
model_name='memoriarespuesta',
name='fichero',
field=models.FileField(
blank=True,
null=True,
upload_to='anexos_memoria/%Y/',
validators=[
django.core.validators.FileExtensionValidator(allowed_extensions=['pdf'])
],
verbose_name='fichero PDF',
),
),
]
from django.core.validators import FileExtensionValidator
from django.db import connection, models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
......@@ -642,7 +643,13 @@ class MemoriaRespuesta(models.Model):
'MemoriaSubapartado', on_delete=models.PROTECT, related_name='respuestas'
)
texto = models.TextField(_('texto'), blank=True, null=True)
fichero = models.FileField('fichero PDF', upload_to='anexos_memoria', blank=True, null=True)
fichero = models.FileField(
'fichero PDF',
upload_to='anexos_memoria/%Y/',
blank=True,
null=True,
validators=[FileExtensionValidator(allowed_extensions=['pdf'])],
)
class Meta:
ordering = ('-proyecto__id', 'subapartado')
......
# Standard library
import csv
import json
import magic
from datetime import date
from os.path import splitext
# Third-party
from annoying.functions import get_config, get_object_or_None
......@@ -42,6 +44,8 @@ from .models import (
Criterio,
Evento,
MemoriaApartado,
MemoriaRespuesta,
MemoriaSubapartado,
ParticipanteProyecto,
Plan,
Proyecto,
......@@ -598,7 +602,7 @@ class ProyectoAnularView(LoginRequiredMixin, ChecksMixin, RedirectView):
return self.es_coordinador(self.kwargs['pk'])
class MemoriaDetailView(LoginRequiredMixin, TemplateView): # TODO: permisos
class MemoriaDetailView(LoginRequiredMixin, ChecksMixin, TemplateView):
"""Muestra la memoria del proyecto indicado."""
template_name = 'memoria/detail.html'
......@@ -612,6 +616,49 @@ class MemoriaDetailView(LoginRequiredMixin, TemplateView): # TODO: permisos
context['dict_respuestas'] = proyecto.get_dict_respuestas_memoria()
return context
def post(self, request, *args, **kwargs):
proyecto = get_object_or_404(Proyecto, pk=kwargs['pk'])
subapartados = MemoriaSubapartado.objects.filter(
apartado__convocatoria_id=proyecto.convocatoria_id
).all()
dict_respuestas = proyecto.get_dict_respuestas_memoria()
for subapartado in subapartados:
respuesta = dict_respuestas.get(subapartado.id)
if not respuesta:
respuesta = MemoriaRespuesta(
proyecto_id=proyecto.id, subapartado_id=subapartado.id
)
if subapartado.tipo == 'texto':
respuesta.texto = request.POST.get(str(subapartado.id))
elif subapartado.tipo == 'fichero':
fichero = request.FILES.get('fichero')
if fichero:
ext = splitext(fichero.name)[1].lower()
if ext != '.pdf':
raise ValidationError(_('El fichero debe tener extensión .pdf .'))
filetype = magic.from_buffer(fichero.read(2048), mime=True)
fichero.seek(0)
if 'pdf' not in filetype: # application/pdf, x-pdf, x-bzpdf, x-gzpdf
raise ValidationError(_('El fichero no es un PDF.'))
# fichero.name = f'{proyecto.id}.pdf'
respuesta.fichero = fichero
respuesta.save()
messages.success(
request, _(f'Se ha guardado la memoria del proyecto «{proyecto.titulo}».')
)
return redirect('proyecto_detail', proyecto.id)
def test_func(self):
# TODO: Comprobar fecha y estado
return self.es_coordinador(self.kwargs['pk']) # TODO: Permitir a los correctores?
class MemoriaPresentarView(LoginRequiredMixin, ChecksMixin, RedirectView):
"""Presenta la memoria final de proyecto.
......
......@@ -18,7 +18,16 @@
{% trans 'Pulse el botón «<strong>Guardar</strong>» para almacenar sus cambios.' %}
{% trans 'Puede editar su memoria tantas veces como desee.' %}<br />
{% trans 'Cuando esté satisfecho, pulse el botón «<strong>Presentar</strong>».' %}
{% trans 'Una vez haya presentado la memoria, ya no podrá modificarla.' %}
{% trans 'Una vez haya presentado la memoria para su corrección, ya no podrá modificarla.' %}<br /><br />
{% blocktrans with fecha=proyecto.convocatoria.fecha_max_memorias %}
Recuerde que la fecha límite para la presentación de memorias es el {{ fecha }}.
{% endblocktrans %}<br />
<strong>{% trans 'No se admitirá ninguna memoria fuera de plazo.' %}</strong>
<!--
<strong>{% trans '¡No espere hasta el último momento para presentar la memoria!' %}</strong><br />
{% blocktrans %}En caso de que el corrector rechace la memoria, podrá subsanar sus defectos
<strong>sólo</strong> mientras esté dentro del plazo de presentación.{% endblocktrans %}
-->
</div>
<br />
......@@ -140,23 +149,29 @@
</div>
<br />
<form action="" method="post">
<form action="" enctype="multipart/form-data" method="post">
{% csrf_token %}
{% for apartado in apartados %}
<h3>{{ apartado.numero }}. {{ apartado.descripcion }}</h3>
{% for subapartado in apartado.subapartados.all %}
<p><strong>{{ subapartado.descripcion }}</strong></p>
<p class="noprint" style="color: gray;">{{ subapartado.ayuda }}</p>
{% with respuesta=dict_respuestas|get_item:subapartado.id %}
{% if subapartado.tipo == 'texto' %}
<textarea class="textarea form-control" name="{{ subapartado.id }}"
placeholder="{% trans 'Introduzca sus comentarios.' %}" rows="10"
cols="80">{% if respuesta %}{{ respuesta.texto }}{% endif %}</textarea>
{% elif subapartado.tipo == 'fichero' %}
TODO: Enviar PDF
{% if respuesta.fichero %}
<p><a href="{{ respuesta.fichero.url }}">{% trans 'PDF actual' %}</a></p>
{% endif %}
<input type="file" name="fichero" accept=".pdf">
{% endif %}
{% endwith %}
<br />
{% endfor %}
{% endfor %}
......@@ -164,18 +179,18 @@
<!-- Botones -->
<br style="clear: both;" />
<div class="btn-group noprint" role="group" aria-label="Botones">
<a href="{% url 'proyecto_detail' proyecto.id %}" class="btn btn-info"
title="{% trans 'Cancelar' %}">
<a href="{% url 'proyecto_detail' proyecto.id %}" class="btn btn-warning"
title="{% trans 'Cancelar - Se perderán los cambios no guardados' %}">
<span class="fas fa-times"></span> {% trans 'Cancelar' %}
</a>
{# TODO if permitir_edicion #}
<button class="btn btn-success" type="button">
<button class="btn btn-success" type="submit" title="{% trans 'Guardar cambios' %}">
<span class="far fa-save"></span> {% trans 'Guardar' %}
</button>
{# endif #}
{# TODO if es_coordinador #}
<button class="btn btn-warning" data-toggle="modal" data-target="#presentarModal"
<button class="btn btn-danger" data-toggle="modal" data-target="#presentarModal"
type="button">
<span class="fas fa-file-export"></span> {% trans 'Presentar' %}
</button>
......
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