# -*- coding: utf-8 -*- from __future__ import unicode_literals from decimal import Decimal from django.db import models, connection from django.utils import timezone class Category(models.Model): cat_name = models.CharField("Category", max_length=50) cat_type = models.CharField( "Type", max_length=1, choices=(("I", "Income"), ("E", "Expence")) ) user = models.ForeignKey("auth.user", null=True, blank=True) budget_type = models.CharField( "Type", max_length=1, choices=(("W", "Weekly"), ("M", "Monthly"), ("Y", "Yearly")), default="M", ) budget_amount = models.DecimalField( "Amount", max_digits=10, decimal_places=2, default=0 ) def natural_key(self): return self.cat_name def __unicode__(self): return self.cat_name def cat_sum(self): from django.db.models import Sum data = Transaction.objects.filter( tr_cat=self.id, tr_date__gte=timezone.now().replace( day=1, hour=0, minute=0, second=0, microsecond=0 ), ).aggregate(Sum("tr_amount")) return float(data["tr_amount__sum"]) if data["tr_amount__sum"] else 0 def minus_sum(self): return self.cat_sum() * (-1) def balance(self): return -self.budget() def ratio(self): if self.budget_amount == 0: return 100 return min(100, int(Decimal(self.cat_sum()) / self.budget_amount * 100)) class Meta: verbose_name_plural = "Categories" class Account(models.Model): acc_name = models.CharField("Account", max_length=50) acc_balance = models.DecimalField("Balance", max_digits=10, decimal_places=2) acc_currency = models.CharField("Currency", max_length=3) user = models.ForeignKey("auth.user", null=True, blank=True) def natural_key(self): return self.acc_name def __unicode__(self): return self.acc_name SQL_exp = """SELECT SUM(tr_amount) from pfm_transaction as t JOIN pfm_account as a ON t.tr_acc_id = a.id WHERE tr_type='E' AND tr_acc_id=%s""" SQL_inc = """SELECT SUM(tr_amount) from pfm_transaction as t JOIN pfm_account as a ON t.tr_acc_id = a.id WHERE tr_type='I' AND tr_acc_id=%s""" def count(self, SQL): cur = connection.cursor() cur.execute(SQL, (self.id,)) try: return float(cur.fetchone()[0]) except TypeError: return 0 cur.close() def exp(self): return self.count(Account.SQL_exp) def inc(self): return self.count(Account.SQL_inc) def tr_in(self): cur = connection.cursor() cur.execute( """SELECT SUM(tr_amount) from pfm_transfer as t JOIN pfm_account as a ON t.to_acc_id = a.id WHERE to_acc_id=%s""", (self.id,), ) try: return float(cur.fetchone()[0]) except TypeError: return 0 cur.close() def tr_out(self): cur = connection.cursor() cur.execute( """SELECT SUM(tr_amount) from pfm_transfer as t JOIN pfm_account as a ON t.from_acc_id = a.id WHERE from_acc_id=%s""", (self.id,), ) try: return float(cur.fetchone()[0]) except TypeError: return 0 cur.close() def rest(self): return ( float(self.acc_balance) - self.count(Account.SQL_exp) - self.tr_out() + self.count(Account.SQL_inc) + self.tr_in() ) class Transaction(models.Model): tr_acc = models.ForeignKey(Account) tr_cat = models.ForeignKey(Category) tr_type = models.CharField( "Type", max_length=1, choices=(("I", "Income"), ("E", "Expence")), default="E" ) tr_amount = models.DecimalField( "Amount", max_digits=10, decimal_places=2, default="0.00" ) tr_note = models.CharField(max_length=100, null=True, blank=True) tr_date = models.DateField(default=timezone.now) pub_date = models.DateTimeField(blank=True, null=True) user = models.ForeignKey("auth.user", blank=True, null=True) def publish(self): self.pub_date = timezone.now() self.save() def __unicode__(self): return "%s,%s,%s,%s" % ( self.tr_cat, self.tr_acc, self.tr_amount, self.tr_date.strftime("%d.%m.%Y"), ) class Transfer(models.Model): from_acc = models.ForeignKey(Account, related_name="to_acc") to_acc = models.ForeignKey(Account, related_name="from_acc") tr_amount = models.DecimalField("Amount", max_digits=10, decimal_places=2) tr_date = models.DateTimeField(default=timezone.now) user = models.ForeignKey("auth.user", blank=True, null=True) def publish(self): self.save() def __unicode__(self): return "%s >>> %s, %s" % (self.from_acc, self.to_acc, self.tr_amount)