You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
k4ever/k4ever/transaction/models.py

122 lines
4.3 KiB

# -*- coding: utf-8 -*-
# This file is part of k4ever, a point-of-sale system
# Contact............ <k4ever@lists.someserver.de>
# Website............ http://k4ever.someserver.de/
# Bug tracker........ http://k4ever.someserver.de/report
#
# Licensed under GNU Affero General Public License v3 or later
12 years ago
from decimal import Decimal
12 years ago
from django.core.validators import MinValueValidator
from django.contrib.auth.models import User
12 years ago
from django.db import models
from django.db.models.deletion import SET_NULL
from django.db.models.signals import pre_delete
from validator import validate_notZero
12 years ago
class TransactionType(models.Model):
""" Type for a :class:`Transaction`. States how the money has
been added to the account and if somebody needs to check
if it was payed. """
name = models.CharField(max_length=100)
needsCheck = models.BooleanField(default=True)
def __unicode__(self):
return unicode(self.name)
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(auto_now_add=True)
amount = models.DecimalField(max_digits=8, decimal_places=2, validators=[validate_notZero])
checked = models.BooleanField(default=False)
def __unicode__(self):
return u"%s for user %s (%s),%schecked" % (self.amount, self.user, self.transactionType, (self.checked and " " or " not "))
def save(self, *args, **kwargs):
profile = self.user.get_profile()
if self.id == None:
# insert
profile.balance += self.amount
else:
# update
oldobj = Transaction.objects.get(id=self.id)
if oldobj.user != self.user:
oldprofile = oldobj.user.get_profile()
oldprofile.balance -= oldobj.amount
oldprofile.save()
# just to be save, reget profile
profile = self.user.get_profile()
profile.balance += self.amount
else:
profile.balance += (self.amount-oldobj.amount)
profile.save()
super(Transaction, self).save(*args, **kwargs)
@staticmethod
def pre_delete_signal(sender, instance, **kwargs):
profile = instance.user.get_profile()
profile.balance -= instance.amount
profile.save()
pre_delete.connect(Transaction.pre_delete_signal, sender=Transaction)
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)
@staticmethod
def moveMoney(fromUser, toUser, amount, commit=True):
print fromUser, toUser, fromUser == toUser, fromUser.id, toUser.id
if not (fromUser == toUser):
fromProfile = fromUser.get_profile()
toProfile = toUser.get_profile()
fromProfile.balance -= amount
toProfile.balance += amount
if commit:
fromProfile.save()
toProfile.save()
def save(self, *args, **kwargs):
if self.user and self.recipient:
oldobj = None
try:
oldobj = VirtualTransaction.objects.get(id=self.id)
except VirtualTransaction.DoesNotExist:
pass
if oldobj and (oldobj.user != self.user or oldobj.recipient != self.recipient):
VirtualTransaction.moveMoney(oldobj.recipient, oldobj.user, oldobj.amount)
VirtualTransaction.moveMoney(self.user, self.recipient, self.amount)
else:
tmpAmount = None
if oldobj == None:
tmpAmount = self.amount
else:
tmpAmount = self.amount - oldobj.amount
VirtualTransaction.moveMoney(self.user, self.recipient, tmpAmount)
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
VirtualTransaction.moveMoney(instance.recipient, instance.user, amount)
pre_delete.connect(VirtualTransaction.pre_delete_signal, sender=VirtualTransaction)