From ff27a8b7545589351e63d791cdab47abe235648a Mon Sep 17 00:00:00 2001 From: "J.-S. Caux" <J.S.Caux@uva.nl> Date: Wed, 20 Feb 2019 06:32:47 +0100 Subject: [PATCH] Add SubsidyAttachment management facilities --- finances/forms.py | 36 +++---------------- finances/models.py | 2 ++ .../templates/finances/_subsidy_card.html | 26 ++++++++++++++ .../templates/finances/subsidy_detail.html | 13 ------- finances/templates/finances/subsidy_list.html | 1 + .../subsidyattachment_confirm_delete.html | 30 ++++++++++++++++ .../finances/subsidyattachment_form.html | 23 ++++++++++++ finances/urls.py | 9 +++++ finances/views.py | 33 ++++++++++++++++- partners/forms.py | 2 +- partners/views.py | 1 - 11 files changed, 129 insertions(+), 47 deletions(-) create mode 100644 finances/templates/finances/subsidyattachment_confirm_delete.html create mode 100644 finances/templates/finances/subsidyattachment_form.html diff --git a/finances/forms.py b/finances/forms.py index 9142a9a9e..309d50d23 100644 --- a/finances/forms.py +++ b/finances/forms.py @@ -32,43 +32,17 @@ class SubsidyAttachmentForm(forms.ModelForm): class Meta: model = SubsidyAttachment fields = ( - 'name', + 'subsidy', 'attachment', + 'name', 'publicly_visible', ) - def save(self, to_object, commit=True): - """ - This custom save method will automatically assign the file to the object - given when it is a valid instance type. - """ - attachment = super().save(commit=False) - - # Formset might save an empty Instance - if not attachment.name or not attachment.attachment: - return None - - if isinstance(to_object, Subsidy): - attachment.subsidy = to_object - else: - raise forms.ValidationError('You cannot save Attachments to this type of object.') - if commit: - attachment.save() - return attachment - - -class SubsidyAttachmentFormSet(forms.BaseModelFormSet): - def save(self, to_object, commit=True): - """ - This custom save method will automatically assign the file to the object - given when it is a valid instance type. - """ - returns = [] - for form in self.forms: - returns.append(form.save(to_object)) - return returns +############# +# Work logs # +############# class WorkLogForm(forms.ModelForm): def __init__(self, *args, **kwargs): diff --git a/finances/models.py b/finances/models.py index 3776c57fd..52778c3aa 100644 --- a/finances/models.py +++ b/finances/models.py @@ -66,6 +66,8 @@ class SubsidyAttachment(models.Model): blank=True) publicly_visible = models.BooleanField(default=False) + def __str__(self): + return '%s, attachment to %s' % (self.name, self.subsidy) def get_absolute_url(self): if self.subsidy: diff --git a/finances/templates/finances/_subsidy_card.html b/finances/templates/finances/_subsidy_card.html index e7168adcd..238cf70a4 100644 --- a/finances/templates/finances/_subsidy_card.html +++ b/finances/templates/finances/_subsidy_card.html @@ -39,4 +39,30 @@ </div> </div> + <div class="row"> + <div class="col-12"> + <h3>Attachments</h3> + <table class="table"> + <tr> + <th>File name</th> + <th>Publicly visible?</th> + </tr> + {% for att in subsidy.attachments.all %} + <tr> + <td><a href="{{ att.get_absolute_url }}" target="_blank">{{ att.name }}</a></td> + <td>{{ att.publicly_visible }}</td> + {% if perms.scipost.can_manage_subsidies %} + <td><a href="{% url 'finances:subsidyattachment_update' pk=att.id %}"><span class="text-warning">Update</span></a></td> + <td><a href="{% url 'finances:subsidyattachment_delete' pk=att.id %}"><span class="text-danger">Delete</span></a></td> + {% endif %} + </tr> + {% empty %} + <tr> + <td>No attachment found</td> + </tr> + {% endfor %} + </table> + </div> + </div> + </div> diff --git a/finances/templates/finances/subsidy_detail.html b/finances/templates/finances/subsidy_detail.html index 2dd44bbbb..ab90b4673 100644 --- a/finances/templates/finances/subsidy_detail.html +++ b/finances/templates/finances/subsidy_detail.html @@ -19,17 +19,4 @@ </div> </div> -<div class="row"> - <div class="col-12"> - <h3>Attachments</h3> - <ul> - {% for file in subsidy.attachments.all %} - <li><a href="{{ file.get_absolute_url }}" target="_blank">{{ file.name }}</a></li> - {% empty %} - <li>No attachment found</li> - {% endfor %} - </ul> - </div> -</div> - {% endblock content %} diff --git a/finances/templates/finances/subsidy_list.html b/finances/templates/finances/subsidy_list.html index e8a11c932..7a167e3d8 100644 --- a/finances/templates/finances/subsidy_list.html +++ b/finances/templates/finances/subsidy_list.html @@ -29,6 +29,7 @@ $(document).ready(function($) { {% if perms.scipost.can_manage_subsidies %} <ul> <li><a href="{% url 'finances:subsidy_create' %}">Add a Subsidy</a></li> + <li><a href="{% url 'finances:subsidyattachment_create' %}">Add a SubsidyAttachment</a></li> </ul> {% endif %} </div> diff --git a/finances/templates/finances/subsidyattachment_confirm_delete.html b/finances/templates/finances/subsidyattachment_confirm_delete.html new file mode 100644 index 000000000..282485633 --- /dev/null +++ b/finances/templates/finances/subsidyattachment_confirm_delete.html @@ -0,0 +1,30 @@ +{% extends 'finances/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} +{{ block.super }} +<span class="breadcrumb-item"><a href="{% url 'finances:subsidies' %}">Subsidies</a></span> +<span class="breadcrumb-item">Confirm deletetion</span> +{% endblock %} + +{% block pagetitle %}: Delete SubsidyAttachment{% endblock pagetitle %} + +{% block content %} +<div class="row"> + <div class="col-12"> + <h1 class="highlight">Delete SubsidyAttachment</h1> + {{ object }} + </div> +</div> +<div class="row"> + <div class="col-12"> + <form method="post"> + {% csrf_token %} + <h3 class="mb-2">Are you sure you want to delete this SubsidyAttachment?</h3> + <input type="submit" class="btn btn-danger" value="Yes, delete it" /> + </form> + </div> +</div> + +{% endblock content %} diff --git a/finances/templates/finances/subsidyattachment_form.html b/finances/templates/finances/subsidyattachment_form.html new file mode 100644 index 000000000..2ae24e064 --- /dev/null +++ b/finances/templates/finances/subsidyattachment_form.html @@ -0,0 +1,23 @@ +{% extends 'finances/base.html' %} + +{% load bootstrap %} + +{% block breadcrumb_items %} +{{ block.super }} +<span class="breadcrumb-item"><a href="{% url 'finances:subsidies' %}">Subsidies</a></span> +<span class="breadcrumb-item">{% if form.instance.id %}Update {{ form.instance }}{% else %}Add new SubsidyAttachment{% endif %}</span> +{% endblock %} + +{% block pagetitle %}: SubsidyAttachments{% endblock pagetitle %} + + +{% block content %} +<div class="row"> + <div class="col-12"> + <form enctype="multipart/form-data" action="" method="post"> + {% csrf_token %} + {{ form|bootstrap }} + <input type="submit" value="Submit" class="btn btn-primary"> + </div> +</div> +{% endblock content %} diff --git a/finances/urls.py b/finances/urls.py index 0181a1fc9..243d70235 100644 --- a/finances/urls.py +++ b/finances/urls.py @@ -20,6 +20,15 @@ urlpatterns = [ url(r'^subsidies/(?P<pk>[0-9]+)/$', views.SubsidyDetailView.as_view(), name='subsidy_details'), url(r'^subsidies/(?P<subsidy_id>[0-9]+)/attachments/(?P<attachment_id>[0-9]+)$', views.subsidy_attachment, name='subsidy_attachment'), + url(r'^subsidies/attachments/add/$', + views.SubsidyAttachmentCreateView.as_view(), + name='subsidyattachment_create'), + url(r'^subsidies/attachments/(?P<pk>[0-9]+)/update/$', + views.SubsidyAttachmentUpdateView.as_view(), + name='subsidyattachment_update'), + url(r'^subsidies/attachments/(?P<pk>[0-9]+)/delete/$', + views.SubsidyAttachmentDeleteView.as_view(), + name='subsidyattachment_delete'), # Timesheets url(r'^timesheets$', views.timesheets, name='timesheets'), diff --git a/finances/views.py b/finances/views.py index b0a747ede..f8471a9e5 100644 --- a/finances/views.py +++ b/finances/views.py @@ -15,7 +15,7 @@ from django.views.generic.detail import DetailView from django.views.generic.edit import CreateView, UpdateView, DeleteView from django.views.generic.list import ListView -from .forms import SubsidyForm, LogsFilter +from .forms import SubsidyForm, SubsidyAttachmentForm, LogsFilter from .models import Subsidy, SubsidyAttachment, WorkLog from .utils import slug_to_id @@ -81,6 +81,37 @@ class SubsidyDetailView(DetailView): model = Subsidy +class SubsidyAttachmentCreateView(PermissionsMixin, CreateView): + """ + Create a new SubsidyAttachment. + """ + permission_required = 'scipost.can_manage_subsidies' + model = SubsidyAttachment + form_class = SubsidyAttachmentForm + template_name = 'finances/subsidyattachment_form.html' + success_url = reverse_lazy('finances:subsidies') + + +class SubsidyAttachmentUpdateView(PermissionsMixin, UpdateView): + """ + Update a SubsidyAttachment. + """ + permission_required = 'scipost.can_manage_subsidies' + model = SubsidyAttachment + form_class = SubsidyAttachmentForm + template_name = 'finances/subsidyattachment_form.html' + success_url = reverse_lazy('finances:subsidies') + + +class SubsidyAttachmentDeleteView(PermissionsMixin, DeleteView): + """ + Delete a SubsidyAttachment. + """ + permission_required = 'scipost.can_manage_subsidies' + model = SubsidyAttachment + success_url = reverse_lazy('finances:subsidies') + + def subsidy_attachment(request, subsidy_id, attachment_id): attachment = get_object_or_404(SubsidyAttachment.objects, subsidy__id=subsidy_id, id=attachment_id) diff --git a/partners/forms.py b/partners/forms.py index aa34fb488..531850532 100644 --- a/partners/forms.py +++ b/partners/forms.py @@ -480,7 +480,7 @@ class MembershipQueryForm(forms.Form): captcha = ReCaptchaField(attrs={'theme': 'clean'}, label='*Please verify to continue:') -#done +# done class PartnersAttachmentForm(forms.ModelForm): class Meta: model = PartnersAttachment diff --git a/partners/views.py b/partners/views.py index 9bc5ea824..9ddb4324f 100644 --- a/partners/views.py +++ b/partners/views.py @@ -404,7 +404,6 @@ def agreement_details(request, agreement_id): if request.user.has_perm('scipost.can_manage_SPB'): form = MembershipAgreementForm(request.POST or None, instance=agreement) - PartnersAttachmentFormSet PartnersAttachmentFormset = modelformset_factory(PartnersAttachment, PartnersAttachmentForm, -- GitLab