Zach Cook
Zach Cook

Reputation: 63

How to implement a transaction and account system in Django?

I am building a personal finance app that stores transactions and accounts. Each transaction will affect the balance of the account. How would I implement this in my app? I haven't found a specific answer despite searching the internet for a while.

models.py

class Account(models.Model):
    DateCreated = models.DateTimeField()
    AccountName = models.SlugField(max_length= 100, primary_key=True)
    UserID = models.ForeignKey(MyUser, on_delete=models.CASCADE)      
    Type = models.CharField(max_length= 20)
    Balance = models.DecimalField(max_digits=19, decimal_places=8)
    Value = models.DecimalField(max_digits=19, decimal_places=8)

class Transaction(models.Model):

    TypeChoices = (
                    ('Income', 'Income'),
                    ('Expense', 'Expense'),
                    ('Transfer', 'Transfer'),
                    )

    CategoryChoices = (
                        ('Rent', 'Rent'),
                        ('Utilities', 'Utilities'),
                        ('Food', 'Food'),
                        ('Leisure', 'Leisure'),
                        ('Insurance', 'Insurance'),
                        ('Gas', 'Gas'),
                        ('Savings', 'Savings'),
                        ('Investment', 'Investment'),
                        ('Phone Payment', 'Phone Payment'),
                        ('Gym Payment','Gym Payment'),
                        ('Salary', 'Salary'),
                        ('Asset', 'Asset'),
                        ('Miscellaneous', 'Miscellaneous'),
                        ('Transfer', 'Transfer'),
                        )

    AccountName = models.ForeignKey(Account, on_delete=models.CASCADE)
    UserID = models.ForeignKey(MyUser, on_delete=models.CASCADE)
    Date = models.DateField()
    Type = models.CharField(max_length = 8, choices = TypeChoices)
    Entity = models.CharField(max_length = 100)
    Description = models.CharField(max_length = 200)
    BudgetType = models.CharField(max_length = 20, choices = CategoryChoices)
    Amount = models.DecimalField(max_digits=19, decimal_places=8)

I currently have created views that will allow the user to create, update, and delete transactions and accounts, but do not have the transactions affecting the balances of the account. What is the best way to implement this?

Upvotes: 2

Views: 1647

Answers (1)

Hmdbbgh
Hmdbbgh

Reputation: 3486

You can use below code in Transaction model (I tested it)

def save(self, *args, **kwargs):
       self.AccountName.Balance += self.Amount
       self.AccountName.save()
       super(Transaction, self).save(*args, **kwargs) # Call the real save() method

This function will reduce the amount from balance before deleting the object.

def delete(self, *args, **kwargs):
       self.AccountName.Balance -= self.Amount
       self.AccountName.save()
       super(Transaction, self).delete(*args, **kwargs) 

if you want change balance after updating amount you can use below signal:

@receiver(pre_save, sender=Transaction)
def update_balance_account(sender, instance, update_fields=None, **kwargs):
    trans = Transaction.objects.get(AccountName=instance.AccountName, id=instance.id, UserID=instance.UserID)
    instance.AccountName.Balance -= trans.Amount
    instance.AccountName.save()

Upvotes: 3

Related Questions