From b8e7309ee2a35f5bf0de20bee2cdc8696a2415e7 Mon Sep 17 00:00:00 2001 From: Gabriel Augendre Date: Sat, 4 Jun 2016 03:44:41 +0200 Subject: [PATCH] Add the ability to add refunds --- refunding/admin.py | 4 +-- refunding/forms.py | 27 +++++++++++++++++-- .../migrations/0002_auto_20160604_0140.py | 22 +++++++++++++++ refunding/models.py | 9 +++++-- refunding/templates/refunding/new_refund.html | 27 +++++++++++++++++++ refunding/templates/refunding/refunds.html | 11 +++++++- refunding/urls.py | 7 ++--- refunding/views.py | 21 ++++++++++++++- refunds/settings.py | 1 + requirements.txt | 1 + templates/base.html | 21 ++++++++------- 11 files changed, 130 insertions(+), 21 deletions(-) create mode 100644 refunding/migrations/0002_auto_20160604_0140.py create mode 100644 refunding/templates/refunding/new_refund.html diff --git a/refunding/admin.py b/refunding/admin.py index 44c5ab4..5b31152 100644 --- a/refunding/admin.py +++ b/refunding/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from refunding.forms import RefundForm +from refunding.forms import RefundForm, RefundFormAdmin from refunding.models import Refund, Payment @@ -9,7 +9,7 @@ class RefundAdmin(admin.ModelAdmin): list_display_links = ('title',) search_fields = ('title',) date_hierarchy = 'date' - form = RefundForm + form = RefundFormAdmin readonly_fields = ('eur_value',) diff --git a/refunding/forms.py b/refunding/forms.py index 78583fc..d46f732 100644 --- a/refunding/forms.py +++ b/refunding/forms.py @@ -1,4 +1,6 @@ +from bootstrap3_datetime.widgets import DateTimePicker from django import forms +from django.db.models import Q from refunding.models import Refund, Payment @@ -7,18 +9,39 @@ class RefundForm(forms.ModelForm): model = Refund fields = '__all__' - payments = forms.ModelMultipleChoiceField(queryset=Payment.objects.all()) + payments = forms.ModelMultipleChoiceField(queryset=Payment.objects.none()) def __init__(self, *args, **kwargs): super(RefundForm, self).__init__(*args, **kwargs) if self.instance: self.fields['payments'].initial = self.instance.payment_set.all() + self.fields['payments'].queryset = Payment.objects.filter(Q(refund=None) | Q(refund=self.instance)) def save(self, *args, **kwargs): # Save the refund - instance = super(RefundForm, self).save(commit=False) + instance = super(RefundForm, self).save() # Remove the refund from payments it was previously assigned to self.fields['payments'].initial.update(refund=None) # Add the refund to the selected payments self.cleaned_data['payments'].update(refund=instance) return instance + + +class RefundFormAdmin(RefundForm): + class Meta: + model = Refund + fields = '__all__' + + +class RefundFormPublic(RefundForm): + class Meta: + model = Refund + exclude = ('user',) + + date = forms.DateField( + widget=DateTimePicker( + options={ + 'format': 'YYYY-MM-DD' + } + ) + ) diff --git a/refunding/migrations/0002_auto_20160604_0140.py b/refunding/migrations/0002_auto_20160604_0140.py new file mode 100644 index 0000000..2a2a242 --- /dev/null +++ b/refunding/migrations/0002_auto_20160604_0140.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-06-04 01:40 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('refunding', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='refund', + name='user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/refunding/models.py b/refunding/models.py index f6f4bd8..9470840 100644 --- a/refunding/models.py +++ b/refunding/models.py @@ -12,11 +12,16 @@ class Refund(models.Model): updated_at = models.DateTimeField(auto_now=True) user = models.ForeignKey( AUTH_USER_MODEL, - on_delete=models.PROTECT + on_delete=models.PROTECT, + null=True ) def eur_value(self) -> float: - return self.payment_set.all().aggregate(Sum('value')).get('value__sum') / 100 + value_sum = self.payment_set.all().aggregate(Sum('value')).get('value__sum') + if value_sum: + return value_sum / 100 + else: + return 0 def __str__(self) -> str: return "{0} on {1} for {2}".format(self.title, self.date, self.eur_value()) diff --git a/refunding/templates/refunding/new_refund.html b/refunding/templates/refunding/new_refund.html new file mode 100644 index 0000000..52e7164 --- /dev/null +++ b/refunding/templates/refunding/new_refund.html @@ -0,0 +1,27 @@ +{% extends 'base.html' %} +{% load crispy_forms_filters %} +{% load crispy_forms_field %} + +{% block javascript %} + {{ block.super }} + + +{% endblock %} + +{% block style %} + {{ block.super }} + +{% endblock %} + +{% block content %} +

{% block title %}New refund{% endblock %}

+
+ {% csrf_token %} + {{ form.media }} + {{ form|crispy }} + +
+{% endblock %} diff --git a/refunding/templates/refunding/refunds.html b/refunding/templates/refunding/refunds.html index 4ea7d35..44976bc 100644 --- a/refunding/templates/refunding/refunds.html +++ b/refunding/templates/refunding/refunds.html @@ -2,6 +2,15 @@ {% load l10n %} {% block content %} -

{% block title %}Latest refunds{% endblock %}

+

+ {% block title %}Latest refunds{% endblock %} + {% if user.is_authenticated %} +
+ + + +
+ {% endif %} +

{% include 'refunding/elements_list.html' with elements=refunds %} {% endblock %} \ No newline at end of file diff --git a/refunding/urls.py b/refunding/urls.py index d70d6d5..f16fe76 100644 --- a/refunding/urls.py +++ b/refunding/urls.py @@ -1,7 +1,8 @@ from django.conf.urls import url -from refunding.views import not_refunded_payments, latest_refunds +from refunding import views urlpatterns = [ - url(r'^payments/$', not_refunded_payments, name='not_refunded_payments'), - url(r'^refunds/$', latest_refunds, name='latest_refunds'), + url(r'^payments/$', views.not_refunded_payments, name='not_refunded_payments'), + url(r'^refunds/$', views.latest_refunds, name='latest_refunds'), + url(r'^refunds/new/$', views.new_refund, name='new_refund'), ] diff --git a/refunding/views.py b/refunding/views.py index a4fb96b..f13c56e 100644 --- a/refunding/views.py +++ b/refunding/views.py @@ -1,6 +1,7 @@ from django.contrib.auth.decorators import login_required from django.db.models import Sum -from django.shortcuts import render +from django.shortcuts import render, redirect +from refunding.forms import RefundForm, RefundFormPublic from refunding.models import Payment, Refund @@ -24,3 +25,21 @@ def latest_refunds(request): 'default_nothing': 'No refund to show.' } return render(request, "refunding/refunds.html", context) + + +@login_required +def new_refund(request): + if request.method == 'POST': + form = RefundFormPublic(request.POST) + if form.is_valid(): + refund = form.save() + refund.user = request.user + refund.save() + return redirect('latest_refunds') + else: + form = RefundFormPublic() + + context = { + 'form': form + } + return render(request, "refunding/new_refund.html", context) \ No newline at end of file diff --git a/refunds/settings.py b/refunds/settings.py index 8db70ae..e9f6b66 100644 --- a/refunds/settings.py +++ b/refunds/settings.py @@ -50,6 +50,7 @@ X_FRAME_OPTIONS = 'DENY' INSTALLED_APPS = [ 'refunding', 'authentication', + 'bootstrap3_datetime', 'crispy_forms', 'django.contrib.admin', 'django.contrib.auth', diff --git a/requirements.txt b/requirements.txt index 347e868..6d7d1fb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ dj-database-url==0.4.1 Django==1.9.6 +django-bootstrap3-datetimepicker-2==2.4.2 django-crispy-forms==1.6.0 django-dotenv==1.4.1 gunicorn==19.6.0 diff --git a/templates/base.html b/templates/base.html index d0ded91..c062498 100644 --- a/templates/base.html +++ b/templates/base.html @@ -7,9 +7,19 @@ + {% block javascript %} + + + {% endblock javascript %} + {% block style %} - + {% endblock style %} @@ -20,14 +30,5 @@ {% block content %} {% endblock %} - -{% block javascript %} - - -{% endblock javascript %} \ No newline at end of file