Reputation: 63
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
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