From c3100ad09ada066b7ca06adb925c53e17199676c Mon Sep 17 00:00:00 2001 From: Sebastian Lohff Date: Tue, 25 Oct 2011 15:47:10 +0200 Subject: [PATCH] Implemented first part for VirtualTransactions. See Ticket #4 --- k4ever/transaction/admin.py | 3 +- k4ever/transaction/forms.py | 26 +++++++++- k4ever/transaction/models.py | 46 ++++++++++++++++- .../templates/transaction/overview.html | 18 ++++++- k4ever/transaction/views.py | 50 ++++++++++++------- 5 files changed, 119 insertions(+), 24 deletions(-) diff --git a/k4ever/transaction/admin.py b/k4ever/transaction/admin.py index 9de41da..83cb3ed 100644 --- a/k4ever/transaction/admin.py +++ b/k4ever/transaction/admin.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from models import Transaction, TransactionType +from models import Transaction, TransactionType, VirtualTransaction from django.contrib import admin class TransactionAdmin(admin.ModelAdmin): @@ -23,3 +23,4 @@ class TransactionAdmin(admin.ModelAdmin): admin.site.register(Transaction, TransactionAdmin) admin.site.register(TransactionType) +admin.site.register(VirtualTransaction) diff --git a/k4ever/transaction/forms.py b/k4ever/transaction/forms.py index 31afec7..3191ee7 100644 --- a/k4ever/transaction/forms.py +++ b/k4ever/transaction/forms.py @@ -1,9 +1,13 @@ +# -*- coding: utf-8 -*- from django import forms -from models import Transaction +from models import Transaction, VirtualTransaction from main.fields import CurrencyField +from django.contrib.auth.models import User +from django.core.exceptions import ValidationError + class TransactionForm(forms.ModelForm): - """ ModelForm for :class:`Transactions ` with a currency field """ + """ ModelForm for :class:`Transactions ` with a currency field. """ amount = CurrencyField(label='Betrag') class Meta: model = Transaction @@ -12,6 +16,24 @@ class TransactionForm(forms.ModelForm): data = self.cleaned_data['amount'] return data def clean(self): + # needed to enforce TransactionTypes needsCheck "default value" cleaned_data = super(TransactionForm, self).clean() self.instance.checked = not cleaned_data['transactionType'].needsCheck return cleaned_data + +class VirtualTransactionForm(forms.ModelForm): + """ ModelForm for :class:`Virtual Transactions ` with a + currency field. """ + + recipient = forms.CharField(max_length=100) + amount = CurrencyField(label='Betrag') + class Meta: + model = VirtualTransaction + exclude = ('user', 'dateTime') + + def clean_recipient(self): + try: + user = User.objects.get(username=self.cleaned_data['recipient']) + except User.DoesNotExist: + raise ValidationError(u"Emfpänger '%s' konnte nicht gefunden werden" % self.cleaned_data['user']) + return user diff --git a/k4ever/transaction/models.py b/k4ever/transaction/models.py index b7dccc1..63d8aeb 100644 --- a/k4ever/transaction/models.py +++ b/k4ever/transaction/models.py @@ -1,7 +1,9 @@ +# -*- coding: utf-8 -*- from django.db import models from django.core.validators import * from django.contrib.auth.models import User - +from django.db.models.deletion import SET_NULL +from django.db.models.signals import pre_delete from decimal import Decimal @@ -19,7 +21,7 @@ class Transaction(models.Model): """Represents a money transaction into the users account. """ user = models.ForeignKey(User) transactionType = models.ForeignKey(TransactionType, verbose_name='Typ') - dateTime = models.DateTimeField() + dateTime = models.DateTimeField(auto_now_add=True) amount = models.DecimalField(max_digits=8, decimal_places=2, validators=[MinValueValidator(Decimal("0.01"))]) checked = models.BooleanField(default=False) @@ -44,4 +46,44 @@ class Transaction(models.Model): profile.save() super(Transaction, self).delete(*args, **kwargs) +class VirtualTransaction(models.Model): + """ Represents a transaction between two users. """ + user = models.ForeignKey(User, null=True, on_delete=SET_NULL) + recipient = models.ForeignKey(User, related_name='receivedtransaction', null=True, on_delete=SET_NULL, verbose_name=u'Empfänger') + dateTime = models.DateTimeField(auto_now_add=True) + amount = models.DecimalField(max_digits=8, decimal_places=2, validators=[MinValueValidator(Decimal("0.01"))], verbose_name='Betrag') + comment = models.CharField(max_length=100, verbose_name='Verwendungszweck') + + def __unicode__(self): + return u"%s ==> %s: %s Euro" % (self.user, self.recipient, self.amount) + def save(self, *args, **kwargs): + userProfile = self.user.get_profile() + recipientProfile = self.recipient.get_profile() + amount = None + if self.id == None: + amount = self.amount + else: + oldobj = VirtualTransaction.objects.get(id=self.id) + amount = self.amount - oldobj.amount + userProfile.balance -= amount + recipientProfile.balance += amount + userProfile.save() + recipientProfile.save() + super(VirtualTransaction, self).save(*args, **kwargs) + + @staticmethod + def pre_delete_signal(sender, instance, **kwargs): + """ Pre delete signal to ensure consistent balances on object delete. """ + # Only revert if both users exist. + if instance.user and instance.recipient: + # revert transaction + print instance.user + print dir(instance) + userProfile = instance.user.get_profile() + recipientProfile = instance.recipient.get_profile() + userProfile.balance += instance.amount + recipientProfile.balance -= instance.amount + userProfile.save() + recipientProfile.save() +pre_delete.connect(VirtualTransaction.pre_delete_signal, sender=VirtualTransaction) diff --git a/k4ever/transaction/templates/transaction/overview.html b/k4ever/transaction/templates/transaction/overview.html index 6ffb938..c1f40dd 100644 --- a/k4ever/transaction/templates/transaction/overview.html +++ b/k4ever/transaction/templates/transaction/overview.html @@ -11,8 +11,9 @@

Konto aufladen

{% csrf_token %} + {{ form.as_table }} - +

Kontodaten:

@@ -31,6 +32,21 @@ +

Geld überweisen

+ {% if transacted %} + {% if error %} +

Beim überweisen ist ein Fehler aufgetreten..

+ {% else %} +

Du hast Geld überwiesen.

+ {% endif %} + {% endif %} +
+ {% csrf_token %} + + {{ vform.as_table }} + +
+

Vergangene Transaktionen

diff --git a/k4ever/transaction/views.py b/k4ever/transaction/views.py index 4276a6e..3c801db 100644 --- a/k4ever/transaction/views.py +++ b/k4ever/transaction/views.py @@ -2,28 +2,42 @@ from django.shortcuts import render_to_response from django.template import RequestContext from django.contrib.auth.decorators import login_required from django.http import HttpResponseRedirect -from models import Transaction, TransactionType -from forms import TransactionForm +from models import Transaction, TransactionType, VirtualTransaction +from forms import TransactionForm, VirtualTransactionForm import datetime @login_required def overview(request): - """ Creates an overview over the users trasnactions, also handles adding money. """ + """ Creates an overview over the users transactions, also handles adding and transfering money. """ + # create history history = Transaction.objects.filter(user=request.user).order_by("-dateTime") - transacted = False - error = False - if request.method == 'POST': - transacted = True - transaction = Transaction(user=request.user, dateTime=datetime.datetime.now()) - form = TransactionForm(request.POST, instance=transaction) - if form.is_valid(): - form.save() - form = TransactionForm() + + # create forms + form = TransactionForm() + vform = VirtualTransactionForm() + transacted = vtransacted = False + error = verror = False + if request.method == 'POST' and request.POST.has_key('_formtype'): + if request.POST['_formtype'] == "normal": transacted = True - else: - error = True - form = TransactionForm() - else: - form = TransactionForm() - return render_to_response("transaction/overview.html", {'history': history, 'form': form, 'transacted': transacted, 'error': error}, RequestContext(request)) + transaction = Transaction(user=request.user) + form = TransactionForm(request.POST, instance=transaction) + if form.is_valid(): + form.save() + form = TransactionForm() + transacted = True + else: + error = True + form = TransactionForm() + elif request.POST['_formtype'] == "virtual": + vtransacted = True + vtransaction = VirtualTransaction(user=request.user) + vform = VirtualTransactionForm(request.POST, instance=vtransaction) + if vform.is_valid(): + vform.save() + vform = VirtualTransactionForm() + vtransacted = True + else: + error = True + return render_to_response("transaction/overview.html", {'history': history, 'form': form, 'transacted': transacted, 'error': error, 'vform': vform, 'vtransacted': vtransacted, 'verror': verror}, RequestContext(request))