Skip to content

Commit

Permalink
Completed taxcharge setup
Browse files Browse the repository at this point in the history
  • Loading branch information
edelgm6 committed Jan 14, 2024
1 parent 73c6fd8 commit 060643b
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 12 deletions.
17 changes: 7 additions & 10 deletions api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ def get_remaining_balance(self):

def amortize(self, date):
starting_amortization_count = len(self.get_related_transactions())
print(starting_amortization_count)

if self.periods - starting_amortization_count == 0 or self.is_closed:
raise ValidationError('Cannot further amortize')
Expand Down Expand Up @@ -96,7 +95,6 @@ def plug_investment_change(self):
GAIN_LOSS_ACCOUNT = Account.objects.get(special_type=Account.SpecialType.UNREALIZED_GAINS_AND_LOSSES)

delta = self.amount - (self.account.get_balance(self.date) - (self.transaction.amount if self.transaction is not None else 0))
print(delta)
if self.transaction:
transaction = self.transaction
transaction.amount = delta
Expand Down Expand Up @@ -236,7 +234,7 @@ class Meta:
def __str__(self):
return str(self.date) + ' ' + self.type

def save(self, *args, **kwargs):
def _get_tax_accounts(self):
tax_accounts = {
self.Type.STATE: {
'expense': Account.objects.get(special_type=Account.SpecialType.STATE_TAXES),
Expand All @@ -255,8 +253,10 @@ def save(self, *args, **kwargs):
'description': 'Property Tax'
}
}
return tax_accounts[self.type]

accounts = tax_accounts[self.type]
def save(self, *args, **kwargs):
accounts = self._get_tax_accounts()

try:
transaction = self.transaction
Expand All @@ -274,26 +274,21 @@ def save(self, *args, **kwargs):
)
self.transaction = transaction

super().save(*args, **kwargs)

try:
journal_entry = self.transaction.journal_entry
except JournalEntry.DoesNotExist:
journal_entry = JournalEntry.objects.create(
date=self.date,
transaction=self.transaction
)

journal_entry_items = JournalEntryItem.objects.filter(journal_entry=journal_entry)
journal_entry_items.delete()
journal_entry.delete_journal_entry_items()

debit = JournalEntryItem.objects.create(
journal_entry=journal_entry,
type=JournalEntryItem.JournalEntryType.DEBIT,
amount=self.transaction.amount,
account=accounts['expense']
)

credit = JournalEntryItem.objects.create(
journal_entry=journal_entry,
type=JournalEntryItem.JournalEntryType.CREDIT,
Expand All @@ -311,6 +306,8 @@ def save(self, *args, **kwargs):
except Reconciliation.DoesNotExist:
pass

super().save(*args, **kwargs)

class Account(models.Model):

class SpecialType(models.TextChoices):
Expand Down
112 changes: 112 additions & 0 deletions api/tests/models/test_taxcharge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
from django.test import TestCase
from django.db import IntegrityError
from api.tests.testing_factories import TransactionFactory, AccountFactory, ReconciliationFactory
from api.models import TaxCharge, Account, JournalEntry, JournalEntryItem
from datetime import date
from decimal import Decimal

class TaxChargeModelTests(TestCase):

def setUp(self):
self.property_tax_account = AccountFactory(special_type=Account.SpecialType.PROPERTY_TAXES, type=Account.Type.EXPENSE)
self.property_tax_payable_account = AccountFactory(special_type=Account.SpecialType.PROPERTY_TAXES_PAYABLE, type=Account.Type.LIABILITY)
AccountFactory(special_type=Account.SpecialType.STATE_TAXES, type=Account.Type.EXPENSE)
AccountFactory(special_type=Account.SpecialType.STATE_TAXES_PAYABLE, type=Account.Type.LIABILITY)
AccountFactory(special_type=Account.SpecialType.FEDERAL_TAXES, type=Account.Type.EXPENSE)
AccountFactory(special_type=Account.SpecialType.FEDERAL_TAXES_PAYABLE, type=Account.Type.LIABILITY)

def test_create_tax_charge(self):
# Test creating a TaxCharge instance using the factory
tax_charge = TaxCharge.objects.create(
type=TaxCharge.Type.PROPERTY,
date=date.today(),
amount=Decimal('100.00')
)
self.assertEqual(tax_charge.type, TaxCharge.Type.PROPERTY)
self.assertEqual(tax_charge.amount, Decimal('100.00'))
self.assertEqual(str(tax_charge), str(date.today()) + ' ' + TaxCharge.Type.PROPERTY)

def test_blocks_duplicate_tax_charges(self):
TaxCharge.objects.create(
type=TaxCharge.Type.PROPERTY,
date=date.today(),
amount=Decimal('100.00')
)

with self.assertRaises(IntegrityError):
# Creating another TaxCharge with the same type and date
duplicate_tax_charge = TaxCharge.objects.create(
type=TaxCharge.Type.PROPERTY,
date=date.today(),
amount=Decimal('200.00')
)

def test_creates_tax_charge_side_effects(self):
tax_charge = TaxCharge.objects.create(
type=TaxCharge.Type.PROPERTY,
date=date.today(),
amount=Decimal('100.00')
)

self.assertTrue(tax_charge.transaction)
self.assertEqual(tax_charge.transaction.amount, Decimal(100.00))
self.assertEqual(self.property_tax_account.get_balance(end_date=date.today(), start_date = date.today()), Decimal(100.00))
self.assertEqual(self.property_tax_payable_account.get_balance(end_date=date.today()), Decimal(100.00))

def test_creates_tax_charge_side_effects_with_existing_transaction_and_jes(self):
transaction = TransactionFactory(amount=10, account=self.property_tax_account)

journal_entry = JournalEntry.objects.create(
date=date.today(),
transaction=transaction
)

debit = JournalEntryItem.objects.create(
journal_entry=journal_entry,
type=JournalEntryItem.JournalEntryType.DEBIT,
amount=transaction.amount,
account=self.property_tax_account
)
credit = JournalEntryItem.objects.create(
journal_entry=journal_entry,
type=JournalEntryItem.JournalEntryType.CREDIT,
amount=transaction.amount,
account=self.property_tax_payable_account
)

tax_charge = TaxCharge.objects.create(
type=TaxCharge.Type.PROPERTY,
date=date.today(),
amount=Decimal('100.00'),
transaction=transaction
)

self.assertTrue(tax_charge.transaction)
self.assertEqual(tax_charge.transaction.amount, Decimal(100.00))
self.assertEqual(self.property_tax_account.get_balance(end_date=date.today(), start_date = date.today()), Decimal(100.00))
self.assertEqual(self.property_tax_payable_account.get_balance(end_date=date.today()), Decimal(100.00))

def test_creates_tax_charge_side_effects_with_existing_reconciliation(self):
transaction = TransactionFactory(amount=10, account=self.property_tax_account)
reconciliation = ReconciliationFactory(
account=self.property_tax_payable_account,
date=date.today(),
amount=5,
transaction=None
)

tax_charge = TaxCharge.objects.create(
type=TaxCharge.Type.PROPERTY,
date=date.today(),
amount=Decimal('100.00'),
transaction=transaction
)

self.assertTrue(tax_charge.transaction)
self.assertEqual(tax_charge.transaction.amount, Decimal(100.00))
self.assertEqual(self.property_tax_account.get_balance(end_date=date.today(), start_date = date.today()), Decimal(100.00))
self.assertEqual(self.property_tax_payable_account.get_balance(end_date=date.today()), Decimal(100.00))
reconciliation.refresh_from_db()
self.assertEqual(reconciliation.amount, Decimal(100.00))

# Add more tests as needed, for example, to test other fields or behaviors
4 changes: 2 additions & 2 deletions api/tests/testing_factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Meta:
type = factory.Iterator(Account.Type.choices, getter=lambda c: c[0])
sub_type = factory.Iterator(Account.SubType.choices, getter=lambda c: c[0])
csv_profile = factory.SubFactory(CSVProfileFactory)
special_type = factory.Iterator(Account.SpecialType.choices, getter=lambda c: c[0], cycle=True)
special_type = None
is_closed = factory.Faker('boolean')

# Transaction Factory
Expand All @@ -31,7 +31,7 @@ class Meta:
amount = factory.Faker('pydecimal', left_digits=5, right_digits=2, positive=True)
description = factory.Faker('sentence')
category = factory.Faker('word')
is_closed = False
is_closed = factory.Faker('boolean')
date_closed = factory.Maybe('is_closed', yes_declaration=factory.Faker('date_object'), no_declaration=None)
suggested_account = factory.SubFactory(AccountFactory)
type = factory.Iterator(Transaction.TransactionType.choices, getter=lambda c: c[0])
Expand Down

0 comments on commit 060643b

Please sign in to comment.