django-ledger 0.5.6.4__py3-none-any.whl → 0.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of django-ledger might be problematic. Click here for more details.
- django_ledger/__init__.py +1 -1
- django_ledger/admin/entity.py +14 -0
- django_ledger/forms/account.py +13 -4
- django_ledger/io/io_core.py +20 -16
- django_ledger/io/io_digest.py +1 -1
- django_ledger/io/io_middleware.py +2 -4
- django_ledger/models/accounts.py +11 -1
- django_ledger/models/closing_entry.py +4 -4
- django_ledger/models/coa.py +269 -90
- django_ledger/models/entity.py +21 -2
- django_ledger/models/mixins.py +1 -1
- django_ledger/models/transactions.py +209 -111
- django_ledger/models/utils.py +117 -116
- django_ledger/templates/django_ledger/account/account_list.html +2 -2
- django_ledger/templates/django_ledger/account/account_update.html +18 -16
- django_ledger/urls/chart_of_accounts.py +3 -3
- django_ledger/views/account.py +36 -10
- django_ledger/views/coa.py +8 -9
- django_ledger/views/mixins.py +10 -8
- {django_ledger-0.5.6.4.dist-info → django_ledger-0.6.0.dist-info}/METADATA +81 -131
- {django_ledger-0.5.6.4.dist-info → django_ledger-0.6.0.dist-info}/RECORD +25 -26
- django_ledger/static/django_ledger/bundle/djetler.bundle.js.LICENSE.txt +0 -28
- {django_ledger-0.5.6.4.dist-info → django_ledger-0.6.0.dist-info}/AUTHORS.md +0 -0
- {django_ledger-0.5.6.4.dist-info → django_ledger-0.6.0.dist-info}/LICENSE +0 -0
- {django_ledger-0.5.6.4.dist-info → django_ledger-0.6.0.dist-info}/WHEEL +0 -0
- {django_ledger-0.5.6.4.dist-info → django_ledger-0.6.0.dist-info}/top_level.txt +0 -0
django_ledger/__init__.py
CHANGED
django_ledger/admin/entity.py
CHANGED
|
@@ -53,11 +53,13 @@ class EntityModelAdmin(ModelAdmin):
|
|
|
53
53
|
list_display = [
|
|
54
54
|
'slug',
|
|
55
55
|
'name',
|
|
56
|
+
'admin',
|
|
56
57
|
'accrual_method',
|
|
57
58
|
'last_closing_date',
|
|
58
59
|
'hidden',
|
|
59
60
|
'get_coa_count',
|
|
60
61
|
'add_ledger_link',
|
|
62
|
+
'dashboard_link',
|
|
61
63
|
'balance_sheet_link',
|
|
62
64
|
'income_statement_link',
|
|
63
65
|
'cash_flow_statement_link'
|
|
@@ -166,6 +168,18 @@ class EntityModelAdmin(ModelAdmin):
|
|
|
166
168
|
|
|
167
169
|
cash_flow_statement_link.short_description = 'Cash Flow'
|
|
168
170
|
|
|
171
|
+
def dashboard_link(self, obj: EntityModel):
|
|
172
|
+
add_ledger_url = reverse(
|
|
173
|
+
viewname='django_ledger:entity-dashboard',
|
|
174
|
+
kwargs={
|
|
175
|
+
'entity_slug': obj.slug
|
|
176
|
+
})
|
|
177
|
+
return format_html('<a class="viewlink" href="{url}">View</a>',
|
|
178
|
+
url=add_ledger_url,
|
|
179
|
+
slug=obj.slug)
|
|
180
|
+
|
|
181
|
+
dashboard_link.short_description = 'Dashboard'
|
|
182
|
+
|
|
169
183
|
def add_code_of_accounts(self, request, queryset):
|
|
170
184
|
lt = get_localtime().isoformat()
|
|
171
185
|
for entity_model in queryset:
|
django_ledger/forms/account.py
CHANGED
|
@@ -31,8 +31,9 @@ class AccountModelCreateForm(ModelForm):
|
|
|
31
31
|
balance_type: Need to be selected from drop down as "Debit" or Credit"
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
|
-
def __init__(self,
|
|
35
|
-
self.
|
|
34
|
+
def __init__(self, entity_model, coa_model, user_model, *args, **kwargs):
|
|
35
|
+
self.ENTITY = entity_model
|
|
36
|
+
self.COA_MODEL = coa_model
|
|
36
37
|
self.USER_MODEL = user_model
|
|
37
38
|
super().__init__(*args, **kwargs)
|
|
38
39
|
self.fields['role'].choices = ACCOUNT_CHOICES_NO_ROOT
|
|
@@ -44,6 +45,13 @@ class AccountModelCreateForm(ModelForm):
|
|
|
44
45
|
return None
|
|
45
46
|
return role_default
|
|
46
47
|
|
|
48
|
+
def clean_code(self):
|
|
49
|
+
code = self.cleaned_data['code']
|
|
50
|
+
is_code_valid = not self.COA_MODEL.accountmodel_set.filter(code=code).exists()
|
|
51
|
+
if not is_code_valid:
|
|
52
|
+
raise ValidationError(message=_('Code {} already exists for CoA {}').format(code, self.COA_MODEL.slug))
|
|
53
|
+
return code
|
|
54
|
+
|
|
47
55
|
class Meta:
|
|
48
56
|
model = AccountModel
|
|
49
57
|
fields = [
|
|
@@ -92,8 +100,9 @@ class AccountModelUpdateForm(MoveNodeForm):
|
|
|
92
100
|
'class': DJANGO_LEDGER_FORM_INPUT_CLASSES
|
|
93
101
|
}))
|
|
94
102
|
|
|
95
|
-
def __init__(self,
|
|
96
|
-
self.
|
|
103
|
+
def __init__(self, entity_model, coa_model, user_model, *args, **kwargs):
|
|
104
|
+
self.ENTITY = entity_model
|
|
105
|
+
self.COA_MODEL = coa_model
|
|
97
106
|
self.USER_MODEL = user_model
|
|
98
107
|
super().__init__(*args, **kwargs)
|
|
99
108
|
# self.fields['_ref_node_id'].choices = self.mk_dropdown_tree_choices()
|
django_ledger/io/io_core.py
CHANGED
|
@@ -38,8 +38,11 @@ from django_ledger.exceptions import InvalidDateInputError, TransactionNotInBala
|
|
|
38
38
|
from django_ledger.io import roles as roles_module
|
|
39
39
|
from django_ledger.io.io_digest import IODigestContextManager
|
|
40
40
|
from django_ledger.io.io_middleware import (
|
|
41
|
-
AccountRoleIOMiddleware,
|
|
42
|
-
|
|
41
|
+
AccountRoleIOMiddleware,
|
|
42
|
+
AccountGroupIOMiddleware,
|
|
43
|
+
JEActivityIOMiddleware,
|
|
44
|
+
BalanceSheetIOMiddleware,
|
|
45
|
+
IncomeStatementIOMiddleware,
|
|
43
46
|
CashFlowStatementIOMiddleware
|
|
44
47
|
)
|
|
45
48
|
from django_ledger.io.ratios import FinancialRatioManager
|
|
@@ -263,7 +266,7 @@ class IODatabaseMixIn:
|
|
|
263
266
|
return isinstance(self, lazy_loader.get_ledger_model())
|
|
264
267
|
|
|
265
268
|
def is_entity_unit_model(self):
|
|
266
|
-
return isinstance(self, lazy_loader.
|
|
269
|
+
return isinstance(self, lazy_loader.get_entity_unit_model())
|
|
267
270
|
|
|
268
271
|
def get_entity_model_from_io(self):
|
|
269
272
|
if self.is_entity_model():
|
|
@@ -601,6 +604,8 @@ class IODatabaseMixIn:
|
|
|
601
604
|
use_closing_entries=use_closing_entries,
|
|
602
605
|
**kwargs)
|
|
603
606
|
|
|
607
|
+
TransactionModel = lazy_loader.get_txs_model()
|
|
608
|
+
|
|
604
609
|
for tx_model in io_result.txs_queryset:
|
|
605
610
|
if tx_model['account__balance_type'] != tx_model['tx_type']:
|
|
606
611
|
tx_model['balance'] = -tx_model['balance']
|
|
@@ -625,7 +630,6 @@ class IODatabaseMixIn:
|
|
|
625
630
|
acc['balance_abs'] = abs(acc['balance'])
|
|
626
631
|
|
|
627
632
|
if signs:
|
|
628
|
-
TransactionModel = lazy_loader.get_txs_model()
|
|
629
633
|
for acc in accounts_digest:
|
|
630
634
|
if any([
|
|
631
635
|
all([acc['role_bs'] == roles_module.BS_ASSET_ROLE,
|
|
@@ -945,8 +949,8 @@ class IOReportMixIn:
|
|
|
945
949
|
**kwargs
|
|
946
950
|
)
|
|
947
951
|
|
|
948
|
-
|
|
949
|
-
report =
|
|
952
|
+
BalanceSheetReport = lazy_loader.get_balance_sheet_report_class()
|
|
953
|
+
report = BalanceSheetReport(
|
|
950
954
|
self.PDF_REPORT_ORIENTATION,
|
|
951
955
|
self.PDF_REPORT_MEASURE_UNIT,
|
|
952
956
|
self.PDF_REPORT_PAGE_SIZE,
|
|
@@ -1000,8 +1004,8 @@ class IOReportMixIn:
|
|
|
1000
1004
|
txs_queryset=txs_queryset,
|
|
1001
1005
|
**kwargs
|
|
1002
1006
|
)
|
|
1003
|
-
|
|
1004
|
-
report =
|
|
1007
|
+
IncomeStatementReport = lazy_loader.get_income_statement_report_class()
|
|
1008
|
+
report = IncomeStatementReport(
|
|
1005
1009
|
self.PDF_REPORT_ORIENTATION,
|
|
1006
1010
|
self.PDF_REPORT_MEASURE_UNIT,
|
|
1007
1011
|
self.PDF_REPORT_PAGE_SIZE,
|
|
@@ -1054,8 +1058,8 @@ class IOReportMixIn:
|
|
|
1054
1058
|
**kwargs
|
|
1055
1059
|
)
|
|
1056
1060
|
|
|
1057
|
-
|
|
1058
|
-
report =
|
|
1061
|
+
CashFlowStatementReport = lazy_loader.get_cash_flow_statement_report_class()
|
|
1062
|
+
report = CashFlowStatementReport(
|
|
1059
1063
|
self.PDF_REPORT_ORIENTATION,
|
|
1060
1064
|
self.PDF_REPORT_MEASURE_UNIT,
|
|
1061
1065
|
self.PDF_REPORT_PAGE_SIZE,
|
|
@@ -1108,22 +1112,22 @@ class IOReportMixIn:
|
|
|
1108
1112
|
**kwargs
|
|
1109
1113
|
)
|
|
1110
1114
|
|
|
1111
|
-
|
|
1112
|
-
bs_report =
|
|
1115
|
+
BalanceSheetReport = lazy_loader.get_balance_sheet_report_class()
|
|
1116
|
+
bs_report = BalanceSheetReport(
|
|
1113
1117
|
self.PDF_REPORT_ORIENTATION,
|
|
1114
1118
|
self.PDF_REPORT_MEASURE_UNIT,
|
|
1115
1119
|
self.PDF_REPORT_PAGE_SIZE,
|
|
1116
1120
|
io_digest=io_digest
|
|
1117
1121
|
)
|
|
1118
|
-
|
|
1119
|
-
is_report =
|
|
1122
|
+
IncomeStatementReport = lazy_loader.get_income_statement_report_class()
|
|
1123
|
+
is_report = IncomeStatementReport(
|
|
1120
1124
|
self.PDF_REPORT_ORIENTATION,
|
|
1121
1125
|
self.PDF_REPORT_MEASURE_UNIT,
|
|
1122
1126
|
self.PDF_REPORT_PAGE_SIZE,
|
|
1123
1127
|
io_digest=io_digest
|
|
1124
1128
|
)
|
|
1125
|
-
|
|
1126
|
-
cfs_report =
|
|
1129
|
+
CashFlowStatementReport = lazy_loader.get_cash_flow_statement_report_class()
|
|
1130
|
+
cfs_report = CashFlowStatementReport(
|
|
1127
1131
|
self.PDF_REPORT_ORIENTATION,
|
|
1128
1132
|
self.PDF_REPORT_MEASURE_UNIT,
|
|
1129
1133
|
self.PDF_REPORT_PAGE_SIZE,
|
django_ledger/io/io_digest.py
CHANGED
|
@@ -11,9 +11,7 @@ from itertools import groupby, chain
|
|
|
11
11
|
from django.core.exceptions import ValidationError
|
|
12
12
|
|
|
13
13
|
from django_ledger.io import roles as roles_module
|
|
14
|
-
from django_ledger.models.utils import
|
|
15
|
-
|
|
16
|
-
lazy_importer = LazyLoader()
|
|
14
|
+
from django_ledger.models.utils import lazy_loader
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
class AccountRoleIOMiddleware:
|
|
@@ -197,7 +195,7 @@ class JEActivityIOMiddleware:
|
|
|
197
195
|
return (acc for acc in self.ACCOUNTS if acc['activity'] == activity)
|
|
198
196
|
|
|
199
197
|
def process_activity(self):
|
|
200
|
-
JournalEntryModel =
|
|
198
|
+
JournalEntryModel = lazy_loader.get_journal_entry_model()
|
|
201
199
|
for act in JournalEntryModel.VALID_ACTIVITIES:
|
|
202
200
|
acc_list = list(self.get_accounts_generator(act))
|
|
203
201
|
self.ACTIVITY_ACCOUNTS[act] = acc_list
|
django_ledger/models/accounts.py
CHANGED
|
@@ -158,7 +158,10 @@ class AccountModelManager(MP_NodeManager):
|
|
|
158
158
|
"""
|
|
159
159
|
Sets the custom queryset as the default.
|
|
160
160
|
"""
|
|
161
|
-
return AccountModelQuerySet(
|
|
161
|
+
return AccountModelQuerySet(
|
|
162
|
+
self.model,
|
|
163
|
+
using=self._db
|
|
164
|
+
).order_by('path').select_related('coa_model')
|
|
162
165
|
|
|
163
166
|
def for_user(self, user_model):
|
|
164
167
|
qs = self.get_queryset()
|
|
@@ -646,6 +649,13 @@ class AccountModelAbstract(MP_Node, CreateUpdateMixIn):
|
|
|
646
649
|
'updated'
|
|
647
650
|
])
|
|
648
651
|
|
|
652
|
+
def can_transact(self) -> bool:
|
|
653
|
+
return all([
|
|
654
|
+
self.coa_model.is_active(),
|
|
655
|
+
not self.is_locked(),
|
|
656
|
+
self.is_active()
|
|
657
|
+
])
|
|
658
|
+
|
|
649
659
|
def get_code_prefix(self) -> str:
|
|
650
660
|
|
|
651
661
|
if self.is_asset():
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
from datetime import datetime, time
|
|
1
2
|
from decimal import Decimal
|
|
2
3
|
from itertools import groupby, chain
|
|
3
4
|
from typing import Optional
|
|
4
5
|
from uuid import uuid4, UUID
|
|
5
|
-
from datetime import datetime, time
|
|
6
6
|
|
|
7
7
|
from django.core.exceptions import ValidationError
|
|
8
8
|
from django.core.validators import MinValueValidator
|
|
9
9
|
from django.db import models
|
|
10
10
|
from django.db.models import Q
|
|
11
|
-
from django.db.models.signals import pre_save
|
|
11
|
+
from django.db.models.signals import pre_save
|
|
12
12
|
from django.urls import reverse
|
|
13
13
|
from django.utils.timezone import make_aware
|
|
14
14
|
from django.utils.translation import gettext_lazy as _
|
|
@@ -120,8 +120,6 @@ class ClosingEntryModelAbstract(CreateUpdateMixIn, MarkdownNotesMixIn):
|
|
|
120
120
|
f'do not equal Debits {ce_txs_sum[TransactionModel.DEBIT]}'
|
|
121
121
|
)
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
|
|
125
123
|
key_func = lambda i: (str(i.unit_model_id) if i.unit_model_id else '', i.activity if i.activity else '')
|
|
126
124
|
|
|
127
125
|
ce_txs.sort(key=key_func)
|
|
@@ -338,6 +336,8 @@ class ClosingEntryModel(ClosingEntryModelAbstract):
|
|
|
338
336
|
pass
|
|
339
337
|
|
|
340
338
|
|
|
339
|
+
# todo: Remove this model!
|
|
340
|
+
|
|
341
341
|
class ClosingEntryTransactionModelQuerySet(models.QuerySet):
|
|
342
342
|
pass
|
|
343
343
|
|