Django:在 post_save 信号中实现资金逆转

问题描述 投票:0回答:1

我正在使用 django

post_save
信号根据是否收到资金来更新交易的
status
。问题是
funds_received
没有按预期工作。问题在于使用
.exists()
,因为它会检查是否有任何帐户的余额等于交易金额。如果有人有建议或知道检查是否收到资金的更好方法,我将非常感谢您的指导。

from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Transaction, Account

@receiver(post_save, sender=Transaction)
def transaction_status(sender, instance, created, **kwargs):
    if created:
        amount = instance.amount
        sender_account = instance.sender.account
        receiver_account_number = instance.account_number
        receiver_account = account.objects.get(account_number=receiver_account_number)

        check_if_funds_received = Account.objects.filter(account_balance=amount).exists()

        funds_received = check_if_funds_received

        if funds_received:
            instance.status = 'Success'
            instance.save()
        else:
            instance.status = 'Reversed'
            instance.save()
            # return funds to sender
            sender_account.account_balance += amount
            sender_account.save()

我的模特

class Account(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    account_number = models.BigIntegerField(unique=True)
    account_balance = models.DecimalField(max_digits=12, decimal_places=6)
    account_id = models.CharField(max_length=15, unique=True)
    user_qrcode = models.ImageField()
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    account_status = models.CharField(max_length=50, choices=ACCOUNT_STATUS)
    pin = models.CharField(max_length=4)
    
    def __str__(self):
        return str(self.user.first_name)


class Transaction(models.Model):
    STATUS = (
        ('Success', 'Success'),
        ('Reversed', 'Reversed')
    )
    sender = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='sender')
    receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='receiver')
    amount = models.DecimalField(max_digits=12, decimal_places=6)
    account_number = models.BigIntegerField()
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    status = models.CharField(max_length=50, choices=STATUS)
    reference = models.CharField(max_length=30, default=reference_number, unique=True)
    pin = models.CharField(max_length=4)
python django django-signals banking
1个回答
0
投票

IMO 你对这个问题的解决方案首先就是错误的。

在您的情况下,交易被视为成功,因为帐户余额已更新。但应该是相反的。

余额应该更新,因为交易成功了。

您甚至可以将余额作为帐户的属性来实现。它将根据该账户成功交易的总和进行实时计算。

您的交易模型字段接收者和发送者也应该指向帐户而不是用户配置文件。将其链接到正确的帐户会更简单。账户已经有FK给用户

这是简化的情况。我认为这将是一个很好的开始方式

class Transaction(models.Model):
    amount = models.DecimalField(max_digits=10, decimal_places=2, null=False, blank=False)
    status = models.CharField(max_length=255)
    timestamp = models.DateTimeField(auto_now_add=True)
    receiver = models.ForeignKey(Account, related_name="received_transactions", on_delete=models.CASCADE)
    sender = models.ForeignKey(Account, related_name="sent_transactions", on_delete=models.CASCADE)

class Account(models.Model):
    @property
    def account_balance(self):
        debit_balance = self.received_transactions.filter(status=SUCCESS).aggregate(debit=Sum("amount", default=0))["debit"]
        credit_balance = self.sent_transactions.filter(status=SUCCESS).aggregate(credit=Sum("amount", default=0))["credit"]

        return debit_balance - credit_balance
© www.soinside.com 2019 - 2024. All rights reserved.