diff --git a/.idea/misc.xml b/.idea/misc.xml index 6ba69809..d56657ad 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/.idea/unicoding.iml b/.idea/unicoding.iml index 3e4215da..09dec57c 100644 --- a/.idea/unicoding.iml +++ b/.idea/unicoding.iml @@ -13,8 +13,10 @@ - - + + + + diff --git a/accounting/api/account.py b/accounting/api/account.py index e843e616..053dee32 100644 --- a/accounting/api/account.py +++ b/accounting/api/account.py @@ -57,8 +57,6 @@ def get_account_balances(request): return status.HTTP_200_OK, result - - class Balance: def __init__(self, balances): balance1 = balances[0] @@ -85,3 +83,23 @@ def __add__(self, other): 'sum': self.balanceIQD }] + def __sub__(self, other): + self.balanceIQD -= other.balanceIQD + self.balanceUSD -= other.balanceUSD + return [{ + 'currency': 'USD', + 'sum': self.balanceUSD + }, { + 'currency': 'IQD', + 'sum': self.balanceIQD + }] + + def __gt__(self, other): + return self.balanceUSD > other.balanceUSD, self.balanceIQD > other.balanceIQD + + def __lt__(self, other): + return self.balanceUSD < other.balanceUSD, self.balanceIQD < other.balanceIQD + + def is_zero(self): + return self.balanceUSD == 0 and self.balanceIQD == 0 + diff --git a/accounting/migrations/0001_initial.py b/accounting/migrations/0001_initial.py index ee702c1f..49f26655 100644 --- a/accounting/migrations/0001_initial.py +++ b/accounting/migrations/0001_initial.py @@ -1,7 +1,8 @@ -# Generated by Django 4.0.6 on 2022-07-20 14:33 +# Generated by Django 4.0.6 on 2022-08-02 19:21 from django.db import migrations, models import django.db.models.deletion +import mptt.fields class Migration(migrations.Migration): @@ -16,17 +17,26 @@ class Migration(migrations.Migration): name='Account', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('type', models.CharField(choices=[('ASSETS', 'ASSETS'), ('LIABILITIES', 'LIABILITIES'), ('INCOME', 'INCOME'), ('EXPENSES', 'EXPENSES')], max_length=255)), - ('code', models.CharField(max_length=20)), - ('full_code', models.CharField(max_length=25)), - ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounting.account')), + ('type', models.CharField(choices=[('ASSETS', 'Assets'), ('LIABILITIES', 'Liabilities'), ('INCOME', 'Income'), ('EXPENSES', 'Expenses')], max_length=255)), + ('name', models.CharField(max_length=255)), + ('code', models.CharField(blank=True, max_length=20, null=True)), + ('full_code', models.CharField(blank=True, max_length=25, null=True)), + ('extra', models.JSONField(blank=True, default=dict, null=True)), + ('lft', models.PositiveIntegerField(editable=False)), + ('rght', models.PositiveIntegerField(editable=False)), + ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), + ('level', models.PositiveIntegerField(editable=False)), + ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounting.account')), ], + options={ + 'abstract': False, + }, ), migrations.CreateModel( name='Transaction', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('type', models.CharField(choices=[('invoice', 'invoice'), ('income', 'income'), ('expense', 'expense'), ('bill', 'bill')], max_length=255)), + ('type', models.CharField(choices=[('invoice', 'Invoice'), ('income', 'Income'), ('expense', 'Expense'), ('bill', 'Bill')], max_length=255)), ('description', models.CharField(max_length=255)), ], ), @@ -36,8 +46,11 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('amount', models.DecimalField(decimal_places=2, max_digits=19)), ('currency', models.CharField(choices=[('USD', 'USD'), ('IQD', 'IQD')], max_length=3)), - ('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounting.account')), - ('transaction', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounting.transaction')), + ('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='journal_entries', to='accounting.account')), + ('transaction', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='journal_entries', to='accounting.transaction')), ], + options={ + 'verbose_name_plural': 'Journal Entries', + }, ), ] diff --git a/accounting/migrations/0002_alter_journalentry_options_account_name.py b/accounting/migrations/0002_alter_journalentry_options_account_name.py deleted file mode 100644 index 5b499031..00000000 --- a/accounting/migrations/0002_alter_journalentry_options_account_name.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 4.0.6 on 2022-07-20 14:46 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounting', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='journalentry', - options={'verbose_name_plural': 'Journal Entries'}, - ), - migrations.AddField( - model_name='account', - name='name', - field=models.CharField(default='', max_length=255), - preserve_default=False, - ), - ] diff --git a/accounting/migrations/0003_account_extra_alter_account_type.py b/accounting/migrations/0003_account_extra_alter_account_type.py deleted file mode 100644 index a06b8aa7..00000000 --- a/accounting/migrations/0003_account_extra_alter_account_type.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 4.0.6 on 2022-07-20 16:12 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounting', '0002_alter_journalentry_options_account_name'), - ] - - operations = [ - migrations.AddField( - model_name='account', - name='extra', - field=models.JSONField(default=dict), - ), - migrations.AlterField( - model_name='account', - name='type', - field=models.CharField(choices=[('ASSETS', 'Assets'), ('LIABILITIES', 'Liabilities'), ('INCOME', 'Income'), ('EXPENSES', 'Expenses')], max_length=255), - ), - ] diff --git a/accounting/migrations/0004_alter_account_extra.py b/accounting/migrations/0004_alter_account_extra.py deleted file mode 100644 index 6944ee6d..00000000 --- a/accounting/migrations/0004_alter_account_extra.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.0.6 on 2022-07-23 10:57 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounting', '0003_account_extra_alter_account_type'), - ] - - operations = [ - migrations.AlterField( - model_name='account', - name='extra', - field=models.JSONField(default=dict, null=True), - ), - ] diff --git a/accounting/migrations/0005_alter_account_extra_alter_journalentry_account_and_more.py b/accounting/migrations/0005_alter_account_extra_alter_journalentry_account_and_more.py deleted file mode 100644 index 2c929883..00000000 --- a/accounting/migrations/0005_alter_account_extra_alter_journalentry_account_and_more.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 4.0.6 on 2022-07-25 14:57 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounting', '0004_alter_account_extra'), - ] - - operations = [ - migrations.AlterField( - model_name='account', - name='extra', - field=models.JSONField(blank=True, default=dict, null=True), - ), - migrations.AlterField( - model_name='journalentry', - name='account', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='journal_entries', to='accounting.account'), - ), - migrations.AlterField( - model_name='transaction', - name='type', - field=models.CharField(choices=[('invoice', 'Invoice'), ('income', 'Income'), ('expense', 'Expense'), ('bill', 'Bill')], max_length=255), - ), - ] diff --git a/accounting/migrations/0006_alter_account_code_alter_account_full_code_and_more.py b/accounting/migrations/0006_alter_account_code_alter_account_full_code_and_more.py deleted file mode 100644 index ff9ec80e..00000000 --- a/accounting/migrations/0006_alter_account_code_alter_account_full_code_and_more.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 4.0.6 on 2022-07-26 14:44 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounting', '0005_alter_account_extra_alter_journalentry_account_and_more'), - ] - - operations = [ - migrations.AlterField( - model_name='account', - name='code', - field=models.CharField(blank=True, max_length=20, null=True), - ), - migrations.AlterField( - model_name='account', - name='full_code', - field=models.CharField(blank=True, max_length=25, null=True), - ), - migrations.AlterField( - model_name='journalentry', - name='transaction', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='journal_entries', to='accounting.transaction'), - ), - ] diff --git a/accounting/models.py b/accounting/models.py index a7d49b7f..f4e5c66c 100644 --- a/accounting/models.py +++ b/accounting/models.py @@ -3,6 +3,7 @@ from django.dispatch import receiver from django.db.models.signals import post_save from accounting.exceptions import AccountingEquationError +from mptt.models import MPTTModel, TreeForeignKey ''' @@ -48,8 +49,8 @@ class CurrencyChoices(models.TextChoices): IQD = 'IQD', 'IQD' -class Account(models.Model): - parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL) +class Account(MPTTModel): + parent = TreeForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL) type = models.CharField(max_length=255, choices=AccountTypeChoices.choices) name = models.CharField(max_length=255) code = models.CharField(max_length=20, null=True, blank=True) @@ -60,7 +61,11 @@ def __str__(self): return f'{self.full_code} - {self.name}' def balance(self): - return self.journal_entries.values('currency').annotate(sum=Sum('amount')).order_by() + result = [ + account.journal_entries.values('currency').annotate(sum=Sum('amount')).order_by() + for account in self.get_descendants(include_self=True) + ] + return Sum(result) # def save( # self, force_insert=False, force_update=False, using=None, update_fields=None diff --git a/requirements.txt b/requirements.txt index d1d09d01..e69de29b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,18 +0,0 @@ -asgiref==3.5.2 -Django==4.0.6 -django-ninja==0.19.0 -django-rest-framework==0.1.0 -djangorestframework==3.13.1 -dnspython==2.2.1 -ecdsa==0.18.0 -email-validator==1.2.1 -idna==3.3 -psycopg2-binary==2.9.3 -pyasn1==0.4.8 -pydantic==1.9.1 -python-jose==3.3.0 -pytz==2022.1 -rsa==4.9 -six==1.16.0 -sqlparse==0.4.2 -typing_extensions==4.3.0