Created
March 27, 2023 16:01
-
-
Save tecoholic/bc113f7aaa1994953df13ccca879ffbe to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This entire file is from ChatGPT generated code. | |
Here are the list of prompts that led to this output: | |
1. Create a Django model to record bank transactions from a personal bank | |
account | |
2. add currency, foreign currency related fields to the model to handle | |
international transactions | |
3. Create an account model to hold the bank account information and update | |
the transaction model to include source and destination accounts | |
necessary for double book keeping method of records | |
""" | |
from django.db import models | |
from django.contrib.auth.models import User | |
class Account(models.Model): | |
user = models.ForeignKey(User, on_delete=models.CASCADE) | |
name = models.CharField(max_length=100) | |
account_number = models.CharField(max_length=50) | |
balance = models.DecimalField(max_digits=10, decimal_places=2) | |
def __str__(self): | |
return f"{self.user.username} - {self.name} ({self.account_number})" | |
class BankTransaction(models.Model): | |
TRANSACTION_TYPES = ( | |
("deposit", "Deposit"), | |
("withdrawal", "Withdrawal"), | |
("transfer", "Transfer"), | |
) | |
user = models.ForeignKey(User, on_delete=models.CASCADE) | |
transaction_date = models.DateTimeField() | |
description = models.CharField(max_length=100) | |
transaction_type = models.CharField(max_length=50, choices=TRANSACTION_TYPES) | |
amount = models.DecimalField(max_digits=10, decimal_places=2) | |
currency = models.CharField(max_length=3, default="USD") | |
exchange_rate = models.DecimalField( | |
max_digits=10, decimal_places=4, null=True, blank=True | |
) | |
foreign_amount = models.DecimalField( | |
max_digits=10, decimal_places=2, null=True, blank=True | |
) | |
source_account = models.ForeignKey( | |
Account, | |
on_delete=models.CASCADE, | |
related_name="source_transactions", | |
null=True, | |
blank=True, | |
) | |
destination_account = models.ForeignKey( | |
Account, | |
on_delete=models.CASCADE, | |
related_name="destination_transactions", | |
null=True, | |
blank=True, | |
) | |
balance = models.DecimalField(max_digits=10, decimal_places=2) | |
def __str__(self): | |
return f"{self.user.username} - {self.description}" | |
def save(self, *args, **kwargs): | |
if self.transaction_type == "transfer": | |
if not self.source_account or not self.destination_account: | |
raise ValueError( | |
"Source and destination accounts are required for transfers" | |
) | |
if self.source_account == self.destination_account: | |
raise ValueError("Source and destination accounts cannot be the same") | |
if self.currency != "USD" and not self.exchange_rate: | |
raise ValueError( | |
"Exchange rate is required for foreign currency transfers" | |
) | |
if self.currency == "USD" and self.foreign_amount: | |
raise ValueError("Foreign amount should be empty for USD transfers") | |
if self.exchange_rate and not self.foreign_amount: | |
raise ValueError( | |
"Foreign amount is required for foreign currency transfers" | |
) | |
if self.exchange_rate and self.foreign_amount: | |
self.amount = self.foreign_amount * self.exchange_rate | |
self.source_account.balance -= self.amount | |
self.destination_account.balance += self.amount | |
self.source_account.save() | |
self.destination_account.save() | |
elif self.transaction_type == "deposit": | |
if not self.destination_account: | |
raise ValueError("Destination account is required for deposits") | |
if self.currency != "USD" and not self.exchange_rate: | |
raise ValueError( | |
"Exchange rate is required for foreign currency deposits" | |
) | |
if self.currency == "USD" and self.foreign_amount: | |
raise ValueError("Foreign amount should be empty for USD deposits") | |
if self.exchange_rate and not self.foreign_amount: | |
raise ValueError( | |
"Foreign amount is required for foreign currency deposits" | |
) | |
if self.exchange_rate and self.foreign_amount: | |
self.amount = self.foreign_amount * self.exchange_rate | |
self.destination_account.balance += self.amount | |
self.destination_account.save() | |
elif self.transaction_type == "withdrawal": | |
if not self.source_account: | |
raise ValueError("Source account is required for withdrawals") | |
if self.currency != "USD" and not self.exchange_rate: | |
raise ValueError( | |
"Exchange rate is required for foreign currency withdrawals" | |
) | |
if self.currency == "USD" and self.foreign_amount: | |
raise ValueError("Foreign amount should be empty for USD withdrawals") | |
if self.exchange_rate and not self.foreign_amount: | |
raise ValueError( | |
"Foreign amount is required for foreign currency withdrawals" | |
) | |
if self.exchange_rate and self.foreign_amount: | |
self.amount = self.foreign_amount * self.exchange_rate | |
self.source_account.balance -= self.amount | |
self.source_account.save() | |
# Update balance for source and destination accounts (if applicable) | |
if self.source_account: | |
self.balance = self.source_account.balance | |
elif self.destination_account: | |
self.balance = self.destination_account.balance | |
super().save(*args, **kwargs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Q: Why is the balance field necessary? Can't we just calculate it on the fly?
ChatGPT:
You are correct that the balance field is not strictly necessary and it can be calculated on the fly based on the transactions in the account. However, storing the balance as a field in the
BankTransaction
model can have some advantages, such as:That being said, if you have a small number of transactions and performance is not a concern, it may be fine to calculate the balance on the fly. Ultimately, the decision of whether to store the balance as a field depends on your specific requirements and trade-offs.