Skip to content

Commit

Permalink
implement test and fix bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
mrmurilo75 committed Mar 21, 2024
1 parent dc1fa89 commit 19aaf60
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 11 deletions.
35 changes: 35 additions & 0 deletions development_notebook/2024-03-21.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# State Of Work

* Project has been fully configured from cookiecutter-django using MySQL.
* Deployed to production at [negligentoctopus.pythonanywhere.com](negligentoctopus.pythonanywhere.com).

Core models are being defined and added to the django-admin.
Account and Transactions are implemented with balance as prefix-sum.

## Update

Testing has been defined.

# Today

Implement testings and fix bugs found.

__To Continue__
Define categories architecture for transactions

## Work Log
__InProgress__

__ToDo__

__Done__
* Add testing -- Functions are defined in class. Follow the one implemented as example.
* Test business logic
* Test balance is correct
* Test balance on account is safe for one, for many transaction, with or withput inital balance
* Test balance is same on change initial balance and change of a transaction
* Test that changing acc or timestamp fails

__Discarded__

# To Do
20 changes: 16 additions & 4 deletions negligent_octopus/core/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from django.db import models
from django.db import transaction as db_transaction
from django.utils import timezone
from django.utils.functional import cached_property
from model_utils.models import SoftDeletableModel
from model_utils.models import TimeStampedModel

Expand All @@ -13,11 +12,24 @@ class Account(TimeStampedModel, SoftDeletableModel):
name = models.CharField(max_length=255)
initial_balance = models.FloatField(default=0.0)

@cached_property
@property
def balance(self):
last_transaction = self.transaction_set.first()
return last_transaction.balance if last_transaction else self.initial_balance

def save(self, *args, **kwargs):
try:
old_model = self.__class__.objects.get(pk=self.pk)
if (
old_model.initial_balance != self.initial_balance
and hasattr(self, "transaction_set")
and self.transaction_set.last() is not None
):
self.transaction_set.last().save() # Trigger update balance
except self.__class__.DoesNotExist:
pass
super().save(*args, **kwargs)

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

Expand Down Expand Up @@ -76,8 +88,8 @@ def save(self, *args, update_balance=True, **kwargs):
return

universe = self.account.transaction_set.filter(
models.Q(timestamp__gte=self.timestamp)
& models.Q(created__gt=self.created),
models.Q(timestamp__gt=self.timestamp)
| (models.Q(timestamp=self.timestamp) & models.Q(created__gt=self.created)),
)

previous = self
Expand Down
120 changes: 113 additions & 7 deletions negligent_octopus/core/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import timedelta

import pytest
from django.utils import timezone
from faker import Faker
Expand All @@ -21,17 +23,121 @@ def test_account_balance(self, account: Account):
)
assert account.balance == balance

def test_transaction_balance(self, account: Account):
balance = account.initial_balance
for i in range(10):
TransactionFactory(
account=account,
amount=i,
timestamp=timezone.now(), # Make sure they are in order
)
for i, transaction in zip(
range(10),
account.transaction_set.all().reverse(),
strict=False,
):
balance += i
assert transaction.balance == balance

def test_account_initial_balance_change(self, account: Account):
raise NotImplementedError
balance = account.initial_balance
for i in range(10):
TransactionFactory(
account=account,
amount=i,
timestamp=timezone.now(), # Make sure they are in order
)
account.initial_balance += 1
account.save()

for i, transaction in zip(
range(10),
account.transaction_set.all().reverse(),
strict=False,
):
balance += i
assert transaction.balance == balance + 1

def test_transaction_added_last(self, account: Account):
raise NotImplementedError
def test_transaction_added_before(self, account: Account):
now = timezone.now()
TransactionFactory(
account=account,
amount=10,
timestamp=now,
)
transaction = TransactionFactory(
account=account,
amount=10,
timestamp=now,
)
old_balance = account.balance

def test_transaction_added_first(self, account: Account):
raise NotImplementedError
transaction_before = TransactionFactory(
account=account,
amount=11,
timestamp=now - timedelta(minutes=1),
)
TransactionFactory(
account=account,
amount=11,
timestamp=now - timedelta(minutes=1),
)

assert account.transaction_set.first().pk == transaction.pk
assert account.transaction_set.last().pk == transaction_before.pk

assert old_balance == account.initial_balance + 20
assert account.balance == old_balance + 22

def test_transaction_added_middle(self, account: Account):
raise NotImplementedError
now = timezone.now()
first_transaction = TransactionFactory(
account=account,
amount=1,
timestamp=now,
)
third_transaction = TransactionFactory(
account=account,
amount=100,
timestamp=now + timedelta(minutes=2),
)
TransactionFactory(
account=account,
amount=10,
timestamp=now + timedelta(minutes=1),
)

# Reload instances
first_transaction = account.transaction_set.get(pk=first_transaction.pk)
third_transaction = account.transaction_set.get(pk=third_transaction.pk)

assert first_transaction.balance == account.initial_balance + 1
assert third_transaction.balance == account.initial_balance + 1 + 10 + 100

def test_transaction_change_amount(self, account: Account):
raise NotImplementedError
now = timezone.now()
first_transaction = TransactionFactory(
account=account,
amount=1,
timestamp=now,
)
second_transaction = TransactionFactory(
account=account,
amount=10,
timestamp=now + timedelta(minutes=1),
)
third_transaction = TransactionFactory(
account=account,
amount=100,
timestamp=now + timedelta(minutes=2),
)
second_transaction.amount += 10
second_transaction.save()

# Reload instances
first_transaction = account.transaction_set.get(pk=first_transaction.pk)
third_transaction = account.transaction_set.get(pk=third_transaction.pk)

assert first_transaction.balance == account.initial_balance + 1
assert second_transaction.balance == account.initial_balance + 1 + 20
assert third_transaction.balance == account.initial_balance + 1 + 20 + 100

0 comments on commit 19aaf60

Please sign in to comment.