Add the ability to add refunds

This commit is contained in:
Gabriel Augendre 2016-06-04 03:44:41 +02:00
parent 343bc1fd84
commit b8e7309ee2
No known key found for this signature in database
GPG key ID: D2B6A5B41FC438B1
11 changed files with 130 additions and 21 deletions

View file

@ -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',)

View file

@ -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'
}
)
)

View file

@ -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),
),
]

View file

@ -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())

View file

@ -0,0 +1,27 @@
{% extends 'base.html' %}
{% load crispy_forms_filters %}
{% load crispy_forms_field %}
{% block javascript %}
{{ block.super }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js"
crossorigin="anonymous"></script>
{% endblock %}
{% block style %}
{{ block.super }}
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.min.css">
{% endblock %}
{% block content %}
<h1>{% block title %}New refund{% endblock %}</h1>
<form action="{% url 'new_refund' %}" method="post">
{% csrf_token %}
{{ form.media }}
{{ form|crispy }}
<input class="btn btn-primary" type="submit" value="Submit"/>
</form>
{% endblock %}

View file

@ -2,6 +2,15 @@
{% load l10n %}
{% block content %}
<h1>{% block title %}Latest refunds{% endblock %}</h1>
<h1>
{% block title %}Latest refunds{% endblock %}
{% if user.is_authenticated %}
<div class="btn-group pull-right">
<a class="btn btn-success" href="{% url 'new_refund' %}">
<span class="glyphicon glyphicon-plus"></span>
</a>
</div>
{% endif %}
</h1>
{% include 'refunding/elements_list.html' with elements=refunds %}
{% endblock %}

View file

@ -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'),
]

View file

@ -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)

View file

@ -50,6 +50,7 @@ X_FRAME_OPTIONS = 'DENY'
INSTALLED_APPS = [
'refunding',
'authentication',
'bootstrap3_datetime',
'crispy_forms',
'django.contrib.admin',
'django.contrib.auth',

View file

@ -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

View file

@ -7,9 +7,19 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% block javascript %}
<script src="https://code.jquery.com/jquery-2.2.3.min.js"
integrity="sha256-a23g1Nt4dtEYOj7bR+vTu7+T8VP13humZFBJNIYoEJo="
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
crossorigin="anonymous"></script>
{% endblock javascript %}
{% block style %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700">
<link rel="stylesheet" type="text/css"
href="//fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700">
<link rel="stylesheet" href="{% static 'default_style.css' %}">
{% endblock style %}
</head>
@ -20,14 +30,5 @@
{% block content %}
{% endblock %}
</div>
{% block javascript %}
<script src="https://code.jquery.com/jquery-2.2.3.min.js"
integrity="sha256-a23g1Nt4dtEYOj7bR+vTu7+T8VP13humZFBJNIYoEJo="
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
crossorigin="anonymous"></script>
{% endblock javascript %}
</body>
</html>