django-ledger 0.5.6.2__py3-none-any.whl → 0.5.6.4__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/coa.py +3 -3
- django_ledger/forms/account.py +2 -0
- django_ledger/forms/coa.py +1 -6
- django_ledger/forms/transactions.py +3 -1
- django_ledger/io/io_core.py +95 -79
- django_ledger/io/io_digest.py +4 -5
- django_ledger/io/io_generator.py +5 -4
- django_ledger/io/io_library.py +241 -16
- django_ledger/io/roles.py +32 -10
- django_ledger/migrations/0015_remove_chartofaccountmodel_locked_and_more.py +22 -0
- django_ledger/models/accounts.py +13 -9
- django_ledger/models/bill.py +3 -3
- django_ledger/models/closing_entry.py +39 -28
- django_ledger/models/coa.py +244 -35
- django_ledger/models/entity.py +119 -51
- django_ledger/models/invoice.py +3 -2
- django_ledger/models/journal_entry.py +8 -4
- django_ledger/models/ledger.py +63 -11
- django_ledger/models/mixins.py +2 -2
- django_ledger/models/transactions.py +20 -11
- django_ledger/report/balance_sheet.py +1 -1
- django_ledger/report/cash_flow_statement.py +5 -5
- django_ledger/report/core.py +2 -2
- django_ledger/report/income_statement.py +2 -2
- django_ledger/static/django_ledger/bundle/djetler.bundle.js +1 -1
- django_ledger/static/django_ledger/bundle/djetler.bundle.js.LICENSE.txt +10 -11
- django_ledger/templates/django_ledger/account/account_create.html +17 -11
- django_ledger/templates/django_ledger/account/account_list.html +12 -9
- django_ledger/templates/django_ledger/account/tags/account_txs_table.html +6 -1
- django_ledger/templates/django_ledger/account/tags/accounts_table.html +97 -93
- django_ledger/templates/django_ledger/chart_of_accounts/coa_list.html +17 -0
- django_ledger/templates/django_ledger/{code_of_accounts → chart_of_accounts}/coa_update.html +1 -4
- django_ledger/templates/django_ledger/chart_of_accounts/includes/coa_card.html +74 -0
- django_ledger/templates/django_ledger/financial_statements/tags/cash_flow_statement.html +1 -1
- django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html +6 -6
- django_ledger/templates/django_ledger/includes/widget_ic.html +1 -1
- django_ledger/templates/django_ledger/invoice/invoice_list.html +91 -94
- django_ledger/templates/django_ledger/journal_entry/includes/card_journal_entry.html +16 -7
- django_ledger/templates/django_ledger/journal_entry/je_detail.html +1 -1
- django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html +10 -0
- django_ledger/templatetags/django_ledger.py +9 -8
- django_ledger/tests/base.py +134 -8
- django_ledger/tests/test_accounts.py +16 -0
- django_ledger/tests/test_auth.py +5 -7
- django_ledger/tests/test_bill.py +1 -1
- django_ledger/tests/test_chart_of_accounts.py +46 -0
- django_ledger/tests/test_closing_entry.py +16 -19
- django_ledger/tests/test_entity.py +3 -3
- django_ledger/tests/test_io.py +192 -2
- django_ledger/tests/test_transactions.py +290 -0
- django_ledger/urls/account.py +18 -3
- django_ledger/urls/chart_of_accounts.py +21 -1
- django_ledger/urls/ledger.py +7 -0
- django_ledger/views/account.py +29 -4
- django_ledger/views/coa.py +79 -4
- django_ledger/views/djl_api.py +4 -1
- django_ledger/views/journal_entry.py +1 -1
- django_ledger/views/mixins.py +3 -0
- {django_ledger-0.5.6.2.dist-info → django_ledger-0.5.6.4.dist-info}/METADATA +1 -1
- {django_ledger-0.5.6.2.dist-info → django_ledger-0.5.6.4.dist-info}/RECORD +65 -59
- {django_ledger-0.5.6.2.dist-info → django_ledger-0.5.6.4.dist-info}/AUTHORS.md +0 -0
- {django_ledger-0.5.6.2.dist-info → django_ledger-0.5.6.4.dist-info}/LICENSE +0 -0
- {django_ledger-0.5.6.2.dist-info → django_ledger-0.5.6.4.dist-info}/WHEEL +0 -0
- {django_ledger-0.5.6.2.dist-info → django_ledger-0.5.6.4.dist-info}/top_level.txt +0 -0
|
@@ -95,14 +95,24 @@ class ClosingEntryModelAbstract(CreateUpdateMixIn, MarkdownNotesMixIn):
|
|
|
95
95
|
return make_aware(datetime.combine(self.closing_date, time.max))
|
|
96
96
|
|
|
97
97
|
def migrate(self):
|
|
98
|
-
ce_txs = self.closingentrytransactionmodel_set.all().
|
|
98
|
+
ce_txs = self.closingentrytransactionmodel_set.all().select_related(
|
|
99
|
+
'account_model',
|
|
100
|
+
'unit_model'
|
|
101
|
+
).order_by(
|
|
99
102
|
'tx_type',
|
|
100
103
|
'account_model',
|
|
101
104
|
'unit_model',
|
|
102
105
|
)
|
|
106
|
+
|
|
107
|
+
# evaluate the QS...
|
|
108
|
+
ce_txs = list(ce_txs)
|
|
109
|
+
|
|
110
|
+
# grouping by DEBIT/CREDIT
|
|
103
111
|
ce_txs_gb = groupby(ce_txs, key=lambda k: k.tx_type)
|
|
104
|
-
|
|
105
|
-
|
|
112
|
+
|
|
113
|
+
# adding DEBITS and CREDITS...
|
|
114
|
+
# ce_txs_gb = {k: list(l) for k, l in ce_txs_gb}
|
|
115
|
+
ce_txs_sum = {k: sum(v.balance for v in l) for k, l in ce_txs_gb}
|
|
106
116
|
|
|
107
117
|
if len(ce_txs_sum) and ce_txs_sum[TransactionModel.DEBIT] != ce_txs_sum[TransactionModel.CREDIT]:
|
|
108
118
|
raise ClosingEntryValidationError(
|
|
@@ -110,20 +120,17 @@ class ClosingEntryModelAbstract(CreateUpdateMixIn, MarkdownNotesMixIn):
|
|
|
110
120
|
f'do not equal Debits {ce_txs_sum[TransactionModel.DEBIT]}'
|
|
111
121
|
)
|
|
112
122
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
key_func = lambda i: (str(i.unit_model_id) if i.unit_model_id else '', i.activity if i.activity else '')
|
|
126
|
+
|
|
118
127
|
ce_txs.sort(key=key_func)
|
|
119
128
|
ce_txs_gb = groupby(ce_txs, key=key_func)
|
|
120
|
-
ce_txs_gb = {
|
|
121
|
-
unit_model_id: list(je_txs) for unit_model_id, je_txs in ce_txs_gb
|
|
122
|
-
}
|
|
129
|
+
ce_txs_gb = {unit_model_id: list(je_txs) for unit_model_id, je_txs in ce_txs_gb}
|
|
123
130
|
|
|
124
131
|
ce_txs_journal_entries = {
|
|
125
132
|
(unit_model_id, activity): JournalEntryModel(
|
|
126
|
-
|
|
133
|
+
ledger_id=self.ledger_model_id,
|
|
127
134
|
timestamp=self.get_closing_date_as_timestamp(),
|
|
128
135
|
activity=activity if activity else None,
|
|
129
136
|
entity_unit_id=unit_model_id if unit_model_id else None,
|
|
@@ -177,7 +184,7 @@ class ClosingEntryModelAbstract(CreateUpdateMixIn, MarkdownNotesMixIn):
|
|
|
177
184
|
def can_post(self) -> bool:
|
|
178
185
|
return not self.is_posted()
|
|
179
186
|
|
|
180
|
-
def mark_as_posted(self, commit: bool = False, **kwargs):
|
|
187
|
+
def mark_as_posted(self, commit: bool = False, update_entity_meta: bool = False, **kwargs):
|
|
181
188
|
if not self.can_post():
|
|
182
189
|
raise ClosingEntryValidationError(
|
|
183
190
|
message=_(f'Closing Entry {self.closing_date} is already posted.')
|
|
@@ -186,12 +193,14 @@ class ClosingEntryModelAbstract(CreateUpdateMixIn, MarkdownNotesMixIn):
|
|
|
186
193
|
self.migrate()
|
|
187
194
|
self.posted = True
|
|
188
195
|
if commit:
|
|
189
|
-
self.save(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
196
|
+
self.save(
|
|
197
|
+
update_fields=[
|
|
198
|
+
'posted',
|
|
199
|
+
'ledger_model',
|
|
200
|
+
'updated'
|
|
201
|
+
])
|
|
202
|
+
if update_entity_meta:
|
|
203
|
+
self.entity_model.save_closing_entry_dates_meta(commit=True)
|
|
195
204
|
|
|
196
205
|
def get_mark_as_posted_html_id(self) -> str:
|
|
197
206
|
return f'closing_entry_post_{self.uuid}'
|
|
@@ -212,7 +221,7 @@ class ClosingEntryModelAbstract(CreateUpdateMixIn, MarkdownNotesMixIn):
|
|
|
212
221
|
def can_unpost(self) -> bool:
|
|
213
222
|
return self.is_posted()
|
|
214
223
|
|
|
215
|
-
def mark_as_unposted(self, commit: bool = False, **kwargs):
|
|
224
|
+
def mark_as_unposted(self, commit: bool = False, update_entity_meta: bool = False, **kwargs):
|
|
216
225
|
if not self.can_unpost():
|
|
217
226
|
raise ClosingEntryValidationError(
|
|
218
227
|
message=_(f'Closing Entry {self.closing_date} is not posted.')
|
|
@@ -224,12 +233,14 @@ class ClosingEntryModelAbstract(CreateUpdateMixIn, MarkdownNotesMixIn):
|
|
|
224
233
|
).delete()
|
|
225
234
|
self.ledger_model.journal_entries.all().delete()
|
|
226
235
|
if commit:
|
|
227
|
-
self.save(
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
236
|
+
self.save(
|
|
237
|
+
update_fields=[
|
|
238
|
+
'posted',
|
|
239
|
+
'ledger_model',
|
|
240
|
+
'updated'
|
|
241
|
+
])
|
|
242
|
+
if update_entity_meta:
|
|
243
|
+
self.entity_model.save_closing_entry_dates_meta(commit=True)
|
|
233
244
|
|
|
234
245
|
def get_mark_as_unposted_html_id(self) -> str:
|
|
235
246
|
return f'closing_entry_unpost_{self.uuid}'
|
|
@@ -250,7 +261,7 @@ class ClosingEntryModelAbstract(CreateUpdateMixIn, MarkdownNotesMixIn):
|
|
|
250
261
|
def can_update_txs(self) -> bool:
|
|
251
262
|
return not self.is_posted()
|
|
252
263
|
|
|
253
|
-
def update_transactions(self, force_update: bool = False,
|
|
264
|
+
def update_transactions(self, force_update: bool = False, post_closing_entry: bool = True, **kwargs):
|
|
254
265
|
if not self.can_update_txs():
|
|
255
266
|
raise ClosingEntryValidationError(
|
|
256
267
|
message=_('Cannot update transactions of a posted Closing Entry.')
|
|
@@ -259,7 +270,7 @@ class ClosingEntryModelAbstract(CreateUpdateMixIn, MarkdownNotesMixIn):
|
|
|
259
270
|
entity_model.close_entity_books(
|
|
260
271
|
closing_entry_model=self,
|
|
261
272
|
force_update=force_update,
|
|
262
|
-
|
|
273
|
+
post_closing_entry=post_closing_entry
|
|
263
274
|
)
|
|
264
275
|
|
|
265
276
|
def get_update_transactions_html_id(self) -> str:
|
django_ledger/models/coa.py
CHANGED
|
@@ -31,7 +31,7 @@ from django.contrib.auth import get_user_model
|
|
|
31
31
|
from django.core.exceptions import ValidationError
|
|
32
32
|
from django.db import models
|
|
33
33
|
from django.db.models import Q
|
|
34
|
-
from django.
|
|
34
|
+
from django.urls import reverse
|
|
35
35
|
from django.utils.translation import gettext_lazy as _
|
|
36
36
|
|
|
37
37
|
from django_ledger.io import (ROOT_COA, ROOT_GROUP_LEVEL_2, ROOT_GROUP_META, ROOT_ASSETS,
|
|
@@ -40,7 +40,6 @@ from django_ledger.io import (ROOT_COA, ROOT_GROUP_LEVEL_2, ROOT_GROUP_META, ROO
|
|
|
40
40
|
from django_ledger.models import lazy_loader
|
|
41
41
|
from django_ledger.models.accounts import AccountModel, AccountModelQuerySet
|
|
42
42
|
from django_ledger.models.mixins import CreateUpdateMixIn, SlugNameMixIn
|
|
43
|
-
from django_ledger.settings import logger
|
|
44
43
|
|
|
45
44
|
UserModel = get_user_model()
|
|
46
45
|
|
|
@@ -150,10 +149,10 @@ class ChartOfAccountModelAbstract(SlugNameMixIn, CreateUpdateMixIn):
|
|
|
150
149
|
entity: EntityModel
|
|
151
150
|
The EntityModel associated with this Chart of Accounts.
|
|
152
151
|
|
|
153
|
-
|
|
152
|
+
active: bool
|
|
154
153
|
This determines whether any changes can be done to the Chart of Accounts.
|
|
155
|
-
|
|
156
|
-
Default value is set to False (
|
|
154
|
+
Inactive Chart of Accounts will not be able to be used in new Transactions.
|
|
155
|
+
Default value is set to False (inactive).
|
|
157
156
|
|
|
158
157
|
description: str
|
|
159
158
|
A user generated description for this Chart of Accounts.
|
|
@@ -164,7 +163,7 @@ class ChartOfAccountModelAbstract(SlugNameMixIn, CreateUpdateMixIn):
|
|
|
164
163
|
editable=False,
|
|
165
164
|
verbose_name=_('Entity'),
|
|
166
165
|
on_delete=models.CASCADE)
|
|
167
|
-
|
|
166
|
+
active = models.BooleanField(default=True, verbose_name=_('Is Active'))
|
|
168
167
|
description = models.TextField(verbose_name=_('CoA Description'), null=True, blank=True)
|
|
169
168
|
objects = ChartOfAccountModelManager.from_queryset(queryset_class=ChartOfAccountModelQuerySet)()
|
|
170
169
|
|
|
@@ -194,7 +193,7 @@ class ChartOfAccountModelAbstract(SlugNameMixIn, CreateUpdateMixIn):
|
|
|
194
193
|
root_account_qs: Optional[AccountModelQuerySet] = None,
|
|
195
194
|
as_queryset: bool = False) -> Union[AccountModelQuerySet, AccountModel]:
|
|
196
195
|
|
|
197
|
-
if not account_model.
|
|
196
|
+
if not account_model.is_root_account():
|
|
198
197
|
|
|
199
198
|
if not root_account_qs:
|
|
200
199
|
root_account_qs = self.get_coa_root_accounts_qs()
|
|
@@ -262,8 +261,9 @@ class ChartOfAccountModelAbstract(SlugNameMixIn, CreateUpdateMixIn):
|
|
|
262
261
|
locked=True,
|
|
263
262
|
balance_type=role_meta['balance_type']
|
|
264
263
|
)
|
|
265
|
-
|
|
264
|
+
AccountModel.add_root(instance=root_account)
|
|
266
265
|
|
|
266
|
+
# must retrieve root model after added pero django-treebeard documentation...
|
|
267
267
|
coa_root_account_model = AccountModel.objects.get(uuid__exact=account_pk)
|
|
268
268
|
|
|
269
269
|
for root_role in ROOT_GROUP_LEVEL_2:
|
|
@@ -284,10 +284,11 @@ class ChartOfAccountModelAbstract(SlugNameMixIn, CreateUpdateMixIn):
|
|
|
284
284
|
))
|
|
285
285
|
|
|
286
286
|
def is_default(self) -> bool:
|
|
287
|
-
if self.entity_id is None:
|
|
288
|
-
return False
|
|
289
287
|
return self.entity.default_coa_id == self.uuid
|
|
290
288
|
|
|
289
|
+
def is_active(self) -> bool:
|
|
290
|
+
return self.active is True
|
|
291
|
+
|
|
291
292
|
def validate_account_model_qs(self, account_model_qs: AccountModelQuerySet):
|
|
292
293
|
if not isinstance(account_model_qs, AccountModelQuerySet):
|
|
293
294
|
raise ChartOfAccountsModelValidationError(
|
|
@@ -299,23 +300,72 @@ class ChartOfAccountModelAbstract(SlugNameMixIn, CreateUpdateMixIn):
|
|
|
299
300
|
message=f'Invalid root queryset for CoA {self.name}'
|
|
300
301
|
)
|
|
301
302
|
|
|
302
|
-
def
|
|
303
|
-
|
|
303
|
+
def allocate_account(self,
|
|
304
|
+
account_model: AccountModel,
|
|
305
|
+
root_account_qs: Optional[AccountModelQuerySet] = None):
|
|
306
|
+
"""
|
|
307
|
+
Allocates a given account model to the appropriate root account depending on the Account Model Role.
|
|
304
308
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
+
Parameters
|
|
310
|
+
----------
|
|
311
|
+
account_model: AccountModel
|
|
312
|
+
The Account Model to Allocate
|
|
313
|
+
root_account_qs:
|
|
314
|
+
The Root Account QuerySet of the Chart Of Accounts to use.
|
|
315
|
+
Will be validated against current CoA Model.
|
|
309
316
|
|
|
310
|
-
|
|
317
|
+
Returns
|
|
318
|
+
-------
|
|
319
|
+
AccountModel
|
|
320
|
+
The saved and allocated AccountModel.
|
|
321
|
+
"""
|
|
311
322
|
|
|
312
|
-
|
|
313
|
-
account_model
|
|
323
|
+
if account_model.coa_model_id:
|
|
324
|
+
if account_model.coa_model_id != self.uuid:
|
|
325
|
+
raise ChartOfAccountsModelValidationError(
|
|
326
|
+
message=f'Invalid Account Model {account_model} for CoA {self}'
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
if not root_account_qs:
|
|
330
|
+
root_account_qs = self.get_coa_root_accounts_qs()
|
|
331
|
+
else:
|
|
332
|
+
self.validate_account_model_qs(root_account_qs)
|
|
333
|
+
|
|
334
|
+
l2_root_node: AccountModel = self.get_coa_l2_root(
|
|
335
|
+
account_model=account_model,
|
|
336
|
+
root_account_qs=root_account_qs
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
account_model.coa_model = self
|
|
340
|
+
l2_root_node.add_child(instance=account_model)
|
|
341
|
+
coa_accounts_qs = self.get_non_root_coa_accounts_qs()
|
|
342
|
+
return coa_accounts_qs.get(uuid__exact=account_model.uuid)
|
|
343
|
+
|
|
344
|
+
def create_account(self,
|
|
345
|
+
code: str,
|
|
346
|
+
role: str,
|
|
347
|
+
name: str,
|
|
348
|
+
balance_type: str,
|
|
349
|
+
active: bool,
|
|
350
|
+
root_account_qs: Optional[AccountModelQuerySet] = None):
|
|
351
|
+
|
|
352
|
+
account_model = AccountModel(
|
|
353
|
+
code=code,
|
|
354
|
+
name=name,
|
|
355
|
+
role=role,
|
|
356
|
+
active=active,
|
|
357
|
+
balance_type=balance_type
|
|
358
|
+
)
|
|
359
|
+
account_model.clean()
|
|
360
|
+
|
|
361
|
+
account_model = self.allocate_account(
|
|
362
|
+
account_model=account_model,
|
|
363
|
+
root_account_qs=root_account_qs
|
|
364
|
+
)
|
|
314
365
|
return account_model
|
|
315
366
|
|
|
316
367
|
# ACTIONS -----
|
|
317
|
-
|
|
318
|
-
# todo: use these methods once multi CoA fetures are enabled...
|
|
368
|
+
# todo: use these methods once multi CoA features are enabled...
|
|
319
369
|
def lock_all_accounts(self) -> AccountModelQuerySet:
|
|
320
370
|
non_root_accounts_qs = self.get_non_root_coa_accounts_qs()
|
|
321
371
|
non_root_accounts_qs.update(locked=True)
|
|
@@ -326,25 +376,184 @@ class ChartOfAccountModelAbstract(SlugNameMixIn, CreateUpdateMixIn):
|
|
|
326
376
|
non_root_accounts_qs.update(locked=False)
|
|
327
377
|
return non_root_accounts_qs
|
|
328
378
|
|
|
329
|
-
def
|
|
330
|
-
|
|
379
|
+
def mark_as_default(self, commit: bool = False, raise_exception: bool = False, **kwargs):
|
|
380
|
+
"""
|
|
381
|
+
Marks the current Chart of Accounts instances as default for the EntityModel.
|
|
382
|
+
|
|
383
|
+
Parameters
|
|
384
|
+
----------
|
|
385
|
+
commit: bool
|
|
386
|
+
Commit the action into the Database. Default is False.
|
|
387
|
+
raise_exception: bool
|
|
388
|
+
Raises exception if Chart of Account model instance is already marked as default.
|
|
389
|
+
"""
|
|
390
|
+
if self.is_default():
|
|
391
|
+
if raise_exception:
|
|
392
|
+
raise ChartOfAccountsModelValidationError(
|
|
393
|
+
message=_(f'The Chart of Accounts {self.slug} is already default')
|
|
394
|
+
)
|
|
395
|
+
return
|
|
396
|
+
self.entity.default_coa_id = self.uuid
|
|
397
|
+
self.clean()
|
|
398
|
+
if commit:
|
|
399
|
+
self.entity.save(
|
|
400
|
+
update_fields=[
|
|
401
|
+
'default_coa_id',
|
|
402
|
+
'updated'
|
|
403
|
+
]
|
|
404
|
+
)
|
|
331
405
|
|
|
406
|
+
def mark_as_default_url(self) -> str:
|
|
407
|
+
"""
|
|
408
|
+
Returns the URL to mark the current Chart of Accounts instances as Default for the EntityModel.
|
|
332
409
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
410
|
+
Returns
|
|
411
|
+
-------
|
|
412
|
+
str
|
|
413
|
+
The URL as a String.
|
|
414
|
+
"""
|
|
415
|
+
return reverse(
|
|
416
|
+
viewname='django_ledger:coa-action-mark-as-default',
|
|
417
|
+
kwargs={
|
|
418
|
+
'entity_slug': self.entity.slug,
|
|
419
|
+
'coa_slug': self.slug
|
|
420
|
+
}
|
|
421
|
+
)
|
|
422
|
+
|
|
423
|
+
def can_activate(self) -> bool:
|
|
424
|
+
return self.active is False
|
|
425
|
+
|
|
426
|
+
def can_deactivate(self) -> bool:
|
|
427
|
+
return all([
|
|
428
|
+
self.is_active(),
|
|
429
|
+
not self.is_default()
|
|
430
|
+
])
|
|
431
|
+
|
|
432
|
+
def mark_as_active(self, commit: bool = False, raise_exception: bool = False, **kwargs):
|
|
433
|
+
"""
|
|
434
|
+
Marks the current Chart of Accounts as Active.
|
|
435
|
+
|
|
436
|
+
Parameters
|
|
437
|
+
----------
|
|
438
|
+
commit: bool
|
|
439
|
+
Commit the action into the Database. Default is False.
|
|
440
|
+
raise_exception: bool
|
|
441
|
+
Raises exception if Chart of Account model instance is already active. Default is False.
|
|
442
|
+
"""
|
|
443
|
+
if self.is_active():
|
|
444
|
+
if raise_exception:
|
|
445
|
+
raise ChartOfAccountsModelValidationError(
|
|
446
|
+
message=_('The Chart of Accounts is currently active.')
|
|
447
|
+
)
|
|
448
|
+
return
|
|
449
|
+
|
|
450
|
+
self.active = True
|
|
451
|
+
self.clean()
|
|
452
|
+
if commit:
|
|
453
|
+
self.save(
|
|
454
|
+
update_fields=[
|
|
455
|
+
'active',
|
|
456
|
+
'updated'
|
|
457
|
+
])
|
|
458
|
+
|
|
459
|
+
def mark_as_active_url(self) -> str:
|
|
460
|
+
"""
|
|
461
|
+
Returns the URL to mark the current Chart of Accounts instances as active.
|
|
462
|
+
|
|
463
|
+
Returns
|
|
464
|
+
-------
|
|
465
|
+
str
|
|
466
|
+
The URL as a String.
|
|
467
|
+
"""
|
|
468
|
+
return reverse(
|
|
469
|
+
viewname='django_ledger:coa-action-mark-as-active',
|
|
470
|
+
kwargs={
|
|
471
|
+
'entity_slug': self.entity.slug,
|
|
472
|
+
'coa_slug': self.slug
|
|
473
|
+
}
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
def mark_as_inactive(self, commit: bool = False, raise_exception: bool = False, **kwargs):
|
|
477
|
+
"""
|
|
478
|
+
Marks the current Chart of Accounts as Active.
|
|
479
|
+
|
|
480
|
+
Parameters
|
|
481
|
+
----------
|
|
482
|
+
commit: bool
|
|
483
|
+
Commit the action into the Database. Default is False.
|
|
484
|
+
raise_exception: bool
|
|
485
|
+
Raises exception if Chart of Account model instance is already active. Default is False.
|
|
486
|
+
"""
|
|
487
|
+
if not self.is_active():
|
|
488
|
+
if raise_exception:
|
|
489
|
+
raise ChartOfAccountsModelValidationError(
|
|
490
|
+
message=_('The Chart of Accounts is currently not active.')
|
|
491
|
+
)
|
|
492
|
+
return
|
|
337
493
|
|
|
494
|
+
self.active = False
|
|
495
|
+
self.clean()
|
|
496
|
+
if commit:
|
|
497
|
+
self.save(
|
|
498
|
+
update_fields=[
|
|
499
|
+
'active',
|
|
500
|
+
'updated'
|
|
501
|
+
])
|
|
338
502
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
503
|
+
def mark_as_inactive_url(self) -> str:
|
|
504
|
+
"""
|
|
505
|
+
Returns the URL to mark the current Chart of Accounts instances as inactive.
|
|
342
506
|
|
|
507
|
+
Returns
|
|
508
|
+
-------
|
|
509
|
+
str
|
|
510
|
+
The URL as a String.
|
|
511
|
+
"""
|
|
512
|
+
return reverse(
|
|
513
|
+
viewname='django_ledger:coa-action-mark-as-inactive',
|
|
514
|
+
kwargs={
|
|
515
|
+
'entity_slug': self.entity.slug,
|
|
516
|
+
'coa_slug': self.slug
|
|
517
|
+
}
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
def get_absolute_url(self) -> str:
|
|
521
|
+
return reverse(
|
|
522
|
+
viewname='django_ledger:coa-detail',
|
|
523
|
+
kwargs={
|
|
524
|
+
'coa_slug': self.slug,
|
|
525
|
+
'entity_slug': self.entity.slug
|
|
526
|
+
}
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
def get_account_list_url(self):
|
|
530
|
+
return reverse(
|
|
531
|
+
viewname='django_ledger:account-list-coa',
|
|
532
|
+
kwargs={
|
|
533
|
+
'entity_slug': self.entity.slug,
|
|
534
|
+
'coa_slug': self.slug
|
|
535
|
+
}
|
|
536
|
+
)
|
|
537
|
+
|
|
538
|
+
def get_create_coa_account_url(self):
|
|
539
|
+
return reverse(
|
|
540
|
+
viewname='django_ledger:account-create-coa',
|
|
541
|
+
kwargs={
|
|
542
|
+
'coa_slug': self.slug,
|
|
543
|
+
'entity_slug': self.entity.slug
|
|
544
|
+
}
|
|
545
|
+
)
|
|
343
546
|
|
|
344
|
-
def
|
|
345
|
-
|
|
346
|
-
|
|
547
|
+
def clean(self):
|
|
548
|
+
self.generate_slug()
|
|
549
|
+
|
|
550
|
+
if self.is_default() and not self.active:
|
|
551
|
+
raise ChartOfAccountsModelValidationError(
|
|
552
|
+
_('Default Chart of Accounts cannot be deactivated.')
|
|
553
|
+
)
|
|
347
554
|
|
|
348
555
|
|
|
349
|
-
|
|
350
|
-
|
|
556
|
+
class ChartOfAccountModel(ChartOfAccountModelAbstract):
|
|
557
|
+
"""
|
|
558
|
+
Base ChartOfAccounts Model
|
|
559
|
+
"""
|