简体   繁体   English

Django 计算模型中所有对象的复利

[英]Django calculate compounded interest for all objects in model

Using Python 3.8.1, and Django 3.0.1.使用 Python 3.8.1 和 Django 3.0.1。

I'm busy with a finance application to track outstanding debits and calculate the interest on the outstanding balances.我正忙于一个财务应用程序,以跟踪未偿还的借项并计算未偿还余额的利息。

I have three models:我有三个模型:

  • Debtor - which contains the client's personal information as well as the applicable interest rate, compounding period etc.债务人 - 包含客户的个人信息以及适用的利率、复利期等。
  • DebtorAccount – is created whenever a new client is created. DebtorAccount – 在创建新客户时创建。 It also keeps a running balance and accrued interest.它还保持运行平衡和应计利息。
  • DebtorTransaction – records the type of transaction description, debit/credit, amount etc. DebtorTransaction – 记录交易类型、借记/贷记、金额等。

models.py模型.py

class Debtor(models.Model):
    name = models.CharField(max_length=200, default="")
    period = models.DecimalField(max_digits=100, decimal_places=2, default=0, null=True)
    interestrate = models.DecimalField(max_digits=100, decimal_places=2, default=0, null=True, blank=True)

    def __str__(self):
        return self.name


@property
def unique_id(self):
    return str(self.pk)


class DebtorAccount(models.Model):
    accountname = models.OneToOneField(Debtor, on_delete=models.CASCADE)
    balance = models.DecimalField(max_digits=100, decimal_places=2, default=0)
    interest = models.DecimalField(max_digits=100, decimal_places=2, default=0)
    rate = models.DecimalField(max_digits=100, decimal_places=2, default=0)
    period = models.DecimalField(max_digits=100, decimal_places=2, default=0)

    def __str__(self):
        return str(self.accountname)


def create_debtoraccount(sender, **kwargs):
    if kwargs['created']:
        debtor_account = DebtorAccount.objects.create(accountname=kwargs['instance'])


post_save.connect(create_debtoraccount, sender=Debtor)


class DebtorTransaction(models.Model):
    CREDIT = 'CREDIT'
    DEBIT = 'DEBIT'
    TRANSACTION_TYPES = (
        ("CREDIT", "Credit"),
        ("DEBIT", "Debit"),
    )

    debtor = models.ForeignKey(DebtorAccount, on_delete=models.CASCADE, blank=True, null=True)
    amount = models.DecimalField(max_digits=100, decimal_places=2, default=0)
    description = models.CharField(max_length=200, blank=True, default="Transaction Description")
    date = models.DateTimeField(auto_now_add=True)
    type = models.CharField(choices=TRANSACTION_TYPES, max_length=6)
    transaction_balance = models.DecimalField(max_digits=100, decimal_places=2, default=0, null=True, blank=True)

    def __str__(self):
        return str(self.debtor)


    @property
    def calculate_interest(user_account):
        user_account = DebtorAccount.objects.all()
        for account in user_account:
            user_interest = (account.balance * (1 + (account.rate / account.period))) - account.balance
            account.save()
            return user_interest

    @property
    def get_transaction_balance(self):
        user_account = DebtorAccount.objects.get(accountname=self.debtor.id)
        if self.type == DebtorTransaction.DEBIT:
            user_balance = user_account.balance + self.amount + self.initiationfee
        else:
            user_balance = user_account.balance - self.amount
        return user_balance


    def save(self, *args, **kwargs):
        self.interest = self.calculate_interest
        self.transaction_balance = self.get_transaction_balance
        super(DebtorTransaction, self).save(*args, **kwargs)


@receiver(post_save, sender=DebtorTransaction, dispatch_uid="transaction log entry")
def update_user_account(sender, instance, **kwargs):
    user_account = DebtorAccount.objects.get(accountname=instance.debtor.id)
    if instance.type == DebtorTransaction.CREDIT:
        user_account.balance = F('balance') - instance.amount
    else:
        user_account.balance = F('balance') + instance.amount

    user_account.save()

Examples of Tables表格示例

Clients Table客户表

Transaction Table交易表

I'm using Django Tables2 to display the clients and the transactions.我正在使用 Django Tables2 来显示客户端和交易。 I don't know if it was necessary to have the get_transaction_balance function but it was the only way I was able to have the running balance with the transaction in the Transaction Table.我不知道是否有必要使用 get_transaction_balance 函数,但这是我能够在事务表中获得事务运行余额的唯一方法。

I now want to calculate the compounded interest on the outstanding balance for each client.我现在想计算每个客户未结余额的复利。 I want this to automatically be calculated on the first day of each month for each client.我希望每个客户在每个月的第一天自动计算。 From what I've read Celery is the best way to accomplish this but I haven't used it before and haven't started research just yet.从我读过的内容来看,Celery 是实现这一目标的最佳方式,但我以前从未使用过它,也尚未开始研究。

For now I just want to calculate the interest on each client's outstanding balance.现在我只想计算每个客户未结余额的利息。 Later on I'll also refine the interest formula to adjust for different compounding periods for different clients.稍后我还将细化利息公式,以针对不同客户的不同复利期进行调整。

I'm completely stuck on how to accomplish this.我完全被困在如何实现这一点上。 The calculate_interest function is my latest attempt to try and solve this but it doesn't work. calculate_interest 函数是我尝试解决这个问题的最新尝试,但它不起作用。

The interest only gets calculated on the outstanding balance of the last client and then applied to the specific instance.利息仅根据最后一个客户的未结余额计算,然后应用于特定实例。 It is not calculated for each client individually and saved.它不会为每个客户端单独计算并保存。

I know the problem is with my for loop and when the save method is overwritten.我知道问题出在我的 for 循环和保存方法被覆盖时。 I just don't know how to solve it.我只是不知道如何解决它。

How do I calculate the interest on the outstanding balance of each client?我如何计算每个客户的未偿还余额的利息?

Your immediate problem is that you're only calculating the interest for the first instance of DebtorAccount then returning.您当前的问题是您只计算 DebtorAccount 第一个实例的利息,然后返回。 However, I don't really understand why this is a property that's doing a calculation.但是,我真的不明白为什么这是一个进行计算的属性。 This should be a method so the user knows that data is being changed.这应该是一种方法,以便用户知道数据正在更改。 It's unusual for a property to change data.属性更改数据是不寻常的。

@property
def calculate_interest(self): # Use the self argument for properties.
    user_accounts = DebtorAccount.objects.all()
    for account in user_accounts:
        # No need for both the subtraction and the 1 + portion.
        user_interest = account.balance * (account.rate / account.period)
        account.save()
    return # I don't know what you want to return from this

Also, I don't really know why a property on a single instance of DebtorTransaction would perform a change on completely unrelated instances of DebtorAccount.此外,我真的不知道为什么 DebtorTransaction 的单个实例上的属性会在完全不相关的 DebtorAccount 实例上执行更改。 Perhaps you mean to do:也许你的意思是:

def calculate_interest(self):
    account = self.debtor
    # No need for both the subtraction and the 1 + portion.
    user_interest = account.balance * (account.rate / account.period)
    account.interest = user_interest
    account.save()
    return user_interest

All that said, I'm still not sure your data model is correct due to my lack of understanding of your scenario.尽管如此,由于我对您的场景缺乏了解,我仍然不确定您的数据模型是否正确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM