django-ledger 0.7.3__py3-none-any.whl → 0.7.4.1__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.

Files changed (42) hide show
  1. django_ledger/__init__.py +1 -1
  2. django_ledger/contrib/django_ledger_graphene/journal_entry/schema.py +2 -3
  3. django_ledger/contrib/django_ledger_graphene/transaction/schema.py +9 -7
  4. django_ledger/forms/journal_entry.py +19 -12
  5. django_ledger/forms/transactions.py +8 -12
  6. django_ledger/io/io_core.py +14 -11
  7. django_ledger/io/io_library.py +3 -3
  8. django_ledger/migrations/0001_initial.py +1 -1
  9. django_ledger/migrations/0019_alter_transactionmodel_amount_and_more.py +33 -0
  10. django_ledger/models/bill.py +17 -2
  11. django_ledger/models/chart_of_accounts.py +4 -0
  12. django_ledger/models/closing_entry.py +8 -6
  13. django_ledger/models/invoice.py +12 -4
  14. django_ledger/models/journal_entry.py +843 -481
  15. django_ledger/models/ledger.py +45 -4
  16. django_ledger/models/transactions.py +303 -305
  17. django_ledger/models/unit.py +42 -22
  18. django_ledger/templates/django_ledger/account/tags/accounts_table.html +1 -1
  19. django_ledger/templates/django_ledger/bills/bill_detail.html +1 -1
  20. django_ledger/templates/django_ledger/invoice/invoice_detail.html +1 -1
  21. django_ledger/templates/django_ledger/journal_entry/je_create.html +2 -3
  22. django_ledger/templates/django_ledger/journal_entry/je_delete.html +2 -3
  23. django_ledger/templates/django_ledger/journal_entry/je_detail.html +1 -1
  24. django_ledger/templates/django_ledger/journal_entry/je_detail_txs.html +8 -8
  25. django_ledger/templates/django_ledger/journal_entry/je_list.html +16 -13
  26. django_ledger/templates/django_ledger/journal_entry/je_update.html +2 -3
  27. django_ledger/templates/django_ledger/journal_entry/tags/je_table.html +24 -24
  28. django_ledger/templates/django_ledger/journal_entry/tags/je_txs_table.html +17 -14
  29. django_ledger/templates/django_ledger/ledger/tags/ledgers_table.html +38 -37
  30. django_ledger/templates/django_ledger/transactions/tags/txs_table.html +69 -0
  31. django_ledger/templatetags/django_ledger.py +25 -45
  32. django_ledger/urls/account.py +4 -4
  33. django_ledger/views/account.py +7 -7
  34. django_ledger/views/journal_entry.py +84 -101
  35. django_ledger/views/ledger.py +16 -21
  36. django_ledger/views/mixins.py +11 -10
  37. {django_ledger-0.7.3.dist-info → django_ledger-0.7.4.1.dist-info}/METADATA +8 -3
  38. {django_ledger-0.7.3.dist-info → django_ledger-0.7.4.1.dist-info}/RECORD +42 -40
  39. {django_ledger-0.7.3.dist-info → django_ledger-0.7.4.1.dist-info}/AUTHORS.md +0 -0
  40. {django_ledger-0.7.3.dist-info → django_ledger-0.7.4.1.dist-info}/LICENSE +0 -0
  41. {django_ledger-0.7.3.dist-info → django_ledger-0.7.4.1.dist-info}/WHEEL +0 -0
  42. {django_ledger-0.7.3.dist-info → django_ledger-0.7.4.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,69 @@
1
+ {% load i18n %}
2
+ {% load django_ledger %}
3
+
4
+ {% if style == 'detail' %}
5
+ <div class="table-container">
6
+ <table class="table is-fullwidth is-narrow is-striped is-bordered django-ledger-table-bottom-margin-75">
7
+ <tr>
8
+ <th>{% trans 'Timestamp' %}</th>
9
+ <th>{% trans 'Account' %}</th>
10
+ <th>{% trans 'Account Name' %}</th>
11
+ <th>{% trans 'Unit' %}</th>
12
+ <th>{% trans 'Credit' %}</th>
13
+ <th>{% trans 'Debit' %}</th>
14
+ <th>{% trans 'Description' %}</th>
15
+ </tr>
16
+ {% for transaction_model in transaction_model_qs %}
17
+ <tr>
18
+ <td>{{ transaction_model.timestamp }}</td>
19
+ <td>{{ transaction_model.account_code }}</td>
20
+ <td>{{ transaction_model.account_name }}</td>
21
+ <td>{% if transaction_model.entity_unit_name %}
22
+ {{ transaction_model.entity_unit_name }}{% endif %}</td>
23
+ <td>{% if transaction_model.is_credit %}$
24
+ {{ transaction_model.amount | currency_format }}{% endif %}</td>
25
+ <td>{% if transaction_model.is_debit %}$
26
+ {{ transaction_model.amount | currency_format }}{% endif %}</td>
27
+ <td>{% if transaction_model.description %}{{ transaction_model.description }}{% endif %}</td>
28
+ </tr>
29
+ {% endfor %}
30
+ <tr class="has-text-weight-bold">
31
+ <td></td>
32
+ <td></td>
33
+ <td></td>
34
+ <td class="has-text-right">Total</td>
35
+ <td>{% currency_symbol %}{{ total_credits | currency_format }}</td>
36
+ <td>{% currency_symbol %}{{ total_debits | currency_format }}</td>
37
+ <td></td>
38
+ </tr>
39
+ </table>
40
+ </div>
41
+ {% elif style == 'compact' %}
42
+ <div class="table-container">
43
+ <table class="table is-fullwidth is-narrow is-striped is-bordered django-ledger-table-bottom-margin-75">
44
+ <tr>
45
+ <th>{% trans 'Account' %}</th>
46
+ <th>{% trans 'Account Name' %}</th>
47
+ <th>{% trans 'Credit' %}</th>
48
+ <th>{% trans 'Debit' %}</th>
49
+ <th>{% trans 'Description' %}</th>
50
+ </tr>
51
+ {% for transaction_model in transaction_model_qs %}
52
+ <tr>
53
+ <td>{{ transaction_model.account_code }}</td>
54
+ <td>{{ transaction_model.account_name }}</td>
55
+ <td>{% if transaction_model.is_credit %}${{ transaction_model.amount | currency_format }}{% endif %}</td>
56
+ <td>{% if transaction_model.is_debit %}${{ transaction_model.amount | currency_format }}{% endif %}</td>
57
+ <td>{% if transaction_model.description %}{{ transaction_model.description }}{% endif %}</td>
58
+ </tr>
59
+ {% endfor %}
60
+ <tr class="has-text-weight-bold">
61
+ <td></td>
62
+ <td class="has-text-right">{% trans 'Total' %}</td>
63
+ <td>{% currency_symbol %}{{ total_credits | currency_format }}</td>
64
+ <td>{% currency_symbol %}{{ total_debits | currency_format }}</td>
65
+ <td></td>
66
+ </tr>
67
+ </table>
68
+ </div>
69
+ {% endif %}
@@ -8,8 +8,10 @@ Miguel Sanda <msanda@arrobalytics.com>
8
8
 
9
9
  from calendar import month_abbr
10
10
  from random import randint
11
+ from typing import Union
11
12
 
12
13
  from django import template
14
+ from django.core.exceptions import ValidationError
13
15
  from django.db.models import Sum
14
16
  from django.urls import reverse
15
17
  from django.utils.formats import number_format
@@ -17,9 +19,9 @@ from django.utils.formats import number_format
17
19
  from django_ledger import __version__
18
20
  from django_ledger.forms.app_filters import EntityFilterForm, ActivityFilterForm
19
21
  from django_ledger.forms.feedback import BugReportForm, RequestNewFeatureForm
20
- from django_ledger.io import CREDIT, DEBIT, ROLES_ORDER_ALL
22
+ from django_ledger.io import ROLES_ORDER_ALL
21
23
  from django_ledger.io.io_core import validate_activity, get_localdate
22
- from django_ledger.models import TransactionModel, BillModel, InvoiceModel, EntityUnitModel
24
+ from django_ledger.models import BillModel, InvoiceModel, JournalEntryModel
23
25
  from django_ledger.settings import (
24
26
  DJANGO_LEDGER_FINANCIAL_ANALYSIS, DJANGO_LEDGER_CURRENCY_SYMBOL,
25
27
  DJANGO_LEDGER_SPACED_CURRENCY_SYMBOL)
@@ -216,65 +218,43 @@ def jes_table(context, journal_entry_qs, next_url=None):
216
218
  'ledger_pk': ledger_pk
217
219
  })
218
220
  return {
219
- 'jes': journal_entry_qs,
221
+ 'journal_entry_qs': journal_entry_qs,
220
222
  'entity_slug': entity_slug,
221
223
  'ledger_pk': ledger_pk,
222
224
  'next_url': next_url
223
225
  }
224
226
 
225
227
 
226
- @register.inclusion_tag('django_ledger/journal_entry/tags/je_txs_table.html')
227
- def journal_entry_txs_table(journal_entry_model, style='detail'):
228
- txs_queryset = journal_entry_model.transactionmodel_set.all().select_related('account').order_by('account__code')
229
- total_credits = sum(tx.amount for tx in txs_queryset if tx.tx_type == 'credit')
230
- total_debits = sum(tx.amount for tx in txs_queryset if tx.tx_type == 'debit')
231
- return {
232
- 'txs': txs_queryset,
233
- 'total_debits': total_debits,
234
- 'total_credits': total_credits,
235
- 'style': style
236
- }
237
-
238
-
239
- @register.inclusion_tag('django_ledger/journal_entry/tags/je_txs_table.html', takes_context=True)
240
- def bill_txs_table(context, bill_model: BillModel):
241
- # todo: move this to bill model...
242
- txs_queryset = TransactionModel.objects.for_bill(
243
- bill_model=bill_model.uuid,
244
- user_model=context['request'].user,
245
- entity_slug=context['view'].kwargs['entity_slug']
246
- ).select_related('journal_entry', 'journal_entry__entity_unit', 'account').order_by('-journal_entry__timestamp')
247
- total_credits = sum(tx.amount for tx in txs_queryset if tx.tx_type == CREDIT)
248
- total_debits = sum(tx.amount for tx in txs_queryset if tx.tx_type == DEBIT)
249
- return {
250
- 'style': 'detail',
251
- 'txs': txs_queryset,
252
- 'total_debits': total_debits,
253
- 'total_credits': total_credits
254
- }
228
+ @register.inclusion_tag('django_ledger/transactions/tags/txs_table.html')
229
+ def transactions_table(object_type: Union[JournalEntryModel, BillModel, InvoiceModel], style='detail'):
230
+ if isinstance(object_type, JournalEntryModel):
231
+ transaction_model_qs = object_type.transactionmodel_set.all().with_annotated_details().order_by(
232
+ '-timestamp')
233
+ elif isinstance(object_type, BillModel):
234
+ transaction_model_qs = object_type.get_transaction_queryset(annotated=True).order_by('-timestamp')
235
+ elif isinstance(object_type, InvoiceModel):
236
+ transaction_model_qs = object_type.get_transaction_queryset(annotated=True).order_by('-timestamp')
237
+ else:
238
+ raise ValidationError(
239
+ 'Cannot handle object of type {} to get transaction model queryset'.format(type(object_type))
240
+ )
255
241
 
242
+ total_credits = sum(tx.amount for tx in transaction_model_qs if tx.is_credit())
243
+ total_debits = sum(tx.amount for tx in transaction_model_qs if tx.is_debit())
256
244
 
257
- @register.inclusion_tag('django_ledger/journal_entry/tags/je_txs_table.html', takes_context=True)
258
- def invoice_txs_table(context, invoice_model: InvoiceModel):
259
- txs_queryset = TransactionModel.objects.for_invoice(
260
- invoice_model=invoice_model,
261
- user_model=context['request'].user,
262
- entity_slug=context['view'].kwargs['entity_slug']
263
- ).select_related('journal_entry', 'journal_entry__entity_unit', 'account').order_by('-journal_entry__timestamp')
264
- total_credits = sum(tx.amount for tx in txs_queryset if tx.tx_type == CREDIT)
265
- total_debits = sum(tx.amount for tx in txs_queryset if tx.tx_type == DEBIT)
266
245
  return {
267
- 'style': 'detail',
268
- 'txs': txs_queryset,
246
+ 'style': style,
247
+ 'transaction_model_qs': transaction_model_qs,
269
248
  'total_debits': total_debits,
270
- 'total_credits': total_credits
249
+ 'total_credits': total_credits,
250
+ 'object': object_type
271
251
  }
272
252
 
273
253
 
274
254
  @register.inclusion_tag('django_ledger/ledger/tags/ledgers_table.html', takes_context=True)
275
255
  def ledgers_table(context, ledger_model_qs):
276
256
  return {
277
- 'ledgers': ledger_model_qs,
257
+ 'ledger_model_qs': ledger_model_qs,
278
258
  'entity_slug': context['view'].kwargs['entity_slug'],
279
259
  }
280
260
 
@@ -36,15 +36,15 @@ urlpatterns = [
36
36
 
37
37
  # Account Actions...
38
38
  path('<slug:entity_slug>/<slug:coa_slug>/action/<uuid:account_pk>/activate/',
39
- views.AccountModelModelActionView.as_view(action_name='activate'),
39
+ views.BaseAccountModelActionView.as_view(action_name='activate'),
40
40
  name='account-action-activate'),
41
41
  path('<slug:entity_slug>/<slug:coa_slug>/action/<uuid:account_pk>/deactivate/',
42
- views.AccountModelModelActionView.as_view(action_name='deactivate'),
42
+ views.BaseAccountModelActionView.as_view(action_name='deactivate'),
43
43
  name='account-action-deactivate'),
44
44
  path('<slug:entity_slug>/<slug:coa_slug>/action/<uuid:account_pk>/lock/',
45
- views.AccountModelModelActionView.as_view(action_name='lock'),
45
+ views.BaseAccountModelActionView.as_view(action_name='lock'),
46
46
  name='account-action-lock'),
47
47
  path('<slug:entity_slug>/<slug:coa_slug>/action/<uuid:account_pk>/unlock/',
48
- views.AccountModelModelActionView.as_view(action_name='unlock'),
48
+ views.BaseAccountModelActionView.as_view(action_name='unlock'),
49
49
  name='account-action-unlock')
50
50
  ]
@@ -200,28 +200,28 @@ class AccountModelYearDetailView(BaseAccountModelBaseView,
200
200
  return context
201
201
 
202
202
 
203
- class AccountModelQuarterDetailView(QuarterlyReportMixIn, AccountModelYearDetailView):
203
+ class AccountModelQuarterDetailView(AccountModelYearDetailView, QuarterlyReportMixIn):
204
204
  """
205
205
  Account Model Quarter Detail View
206
206
  """
207
207
 
208
208
 
209
- class AccountModelMonthDetailView(MonthlyReportMixIn, AccountModelYearDetailView):
209
+ class AccountModelMonthDetailView(AccountModelYearDetailView, MonthlyReportMixIn):
210
210
  """
211
211
  Account Model Month Detail View
212
212
  """
213
213
 
214
214
 
215
- class AccountModelDateDetailView(DateReportMixIn, AccountModelYearDetailView):
215
+ class AccountModelDateDetailView(AccountModelYearDetailView, DateReportMixIn):
216
216
  """
217
217
  Account Model Date Detail View
218
218
  """
219
219
 
220
220
 
221
221
  # ACTIONS...
222
- class AccountModelModelActionView(BaseAccountModelBaseView,
223
- RedirectView,
224
- SingleObjectMixin):
222
+ class BaseAccountModelActionView(BaseAccountModelBaseView,
223
+ RedirectView,
224
+ SingleObjectMixin):
225
225
  http_method_names = ['get']
226
226
  pk_url_kwarg = 'account_pk'
227
227
  action_name = None
@@ -235,7 +235,7 @@ class AccountModelModelActionView(BaseAccountModelBaseView,
235
235
  kwargs['user_model'] = self.request.user
236
236
  if not self.action_name:
237
237
  raise ImproperlyConfigured('View attribute action_name is required.')
238
- response = super(AccountModelModelActionView, self).get(request, *args, **kwargs)
238
+ response = super(BaseAccountModelActionView, self).get(request, *args, **kwargs)
239
239
  account_model: AccountModel = self.get_object()
240
240
 
241
241
  try:
@@ -5,75 +5,72 @@ Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
5
5
  Contributions to this module:
6
6
  * Miguel Sanda <msanda@arrobalytics.com>
7
7
  """
8
+ from typing import Optional
9
+
8
10
  from django.contrib import messages
9
11
  from django.core.exceptions import ImproperlyConfigured, ValidationError
10
- from django.db.models import Count
11
12
  from django.http import HttpResponseForbidden
12
13
  from django.urls import reverse
13
14
  from django.utils.translation import gettext_lazy as _
14
- from django.views.generic import (YearArchiveView, MonthArchiveView, DetailView, UpdateView, CreateView, RedirectView,
15
- ArchiveIndexView, DeleteView)
15
+ from django.views.generic import (
16
+ YearArchiveView, MonthArchiveView, DetailView, UpdateView, CreateView, RedirectView,
17
+ ArchiveIndexView, DeleteView
18
+ )
16
19
  from django.views.generic.detail import SingleObjectMixin
17
20
 
18
- from django_ledger.forms.journal_entry import (JournalEntryModelUpdateForm,
19
- JournalEntryModelCannotEditForm,
20
- JournalEntryModelCreateForm)
21
+ from django_ledger.forms.journal_entry import (
22
+ JournalEntryModelUpdateForm,
23
+ JournalEntryModelCannotEditForm,
24
+ JournalEntryModelCreateForm
25
+ )
21
26
  from django_ledger.forms.transactions import get_transactionmodel_formset_class
22
27
  from django_ledger.io.io_core import get_localtime
28
+ from django_ledger.models import EntityModel, LedgerModel
23
29
  from django_ledger.models.journal_entry import JournalEntryModel
24
- from django_ledger.models.ledger import LedgerModel
25
30
  from django_ledger.views.mixins import DjangoLedgerSecurityMixIn
26
31
 
27
32
 
28
- class JournalEntryModelModelViewQuerySetMixIn:
33
+ class JournalEntryModelModelBaseView(DjangoLedgerSecurityMixIn):
29
34
  queryset = None
35
+ ledger_model: Optional[LedgerModel] = None
30
36
 
31
37
  def get_queryset(self):
32
38
  if self.queryset is None:
33
- self.queryset = JournalEntryModel.objects.for_ledger(
34
- ledger_pk=self.kwargs['ledger_pk'],
35
- entity_slug=self.kwargs['entity_slug'],
36
- user_model=self.request.user
37
- ).select_related('entity_unit', 'ledger', 'ledger__entity')
38
- return super().get_queryset()
39
+ ledger_model: LedgerModel = self.get_ledger_model()
40
+ journal_entry_queryset = ledger_model.journal_entries.select_related('entity_unit', 'ledger', 'ledger__entity').order_by('-timestamp')
41
+ self.queryset = journal_entry_queryset
42
+ return self.queryset
43
+
44
+ def get_ledger_model(self) -> LedgerModel:
45
+ if self.ledger_model is None:
46
+ entity_model: EntityModel = self.get_authorized_entity_instance()
47
+ self.ledger_model = entity_model.get_ledgers().get(uuid__exact=self.kwargs['ledger_pk'])
48
+ return self.ledger_model
39
49
 
40
50
 
41
51
  # JE Views ---
42
- class JournalEntryCreateView(DjangoLedgerSecurityMixIn, CreateView, SingleObjectMixin):
52
+ class JournalEntryCreateView(JournalEntryModelModelBaseView, CreateView):
43
53
  template_name = 'django_ledger/journal_entry/je_create.html'
44
54
  PAGE_TITLE = _('Create Journal Entry')
45
55
  extra_context = {
46
56
  'page_title': PAGE_TITLE,
47
57
  'header_title': PAGE_TITLE
48
58
  }
49
- context_object_name = 'ledger_model'
50
- pk_url_kwarg = 'ledger_pk'
51
- ledger_model = None
59
+ ledger_model: Optional[LedgerModel] = None
52
60
 
53
61
  def get_context_data(self, **kwargs):
54
- if self.ledger_model is None:
55
- ledger_model = self.get_object()
56
- self.ledger_model = ledger_model
57
- ctx = super().get_context_data(**kwargs)
58
- ctx['page_title'] = self.PAGE_TITLE
59
- ctx['header_title'] = self.PAGE_TITLE
60
- ctx['header_subtitle'] = self.ledger_model
61
- return ctx
62
-
63
- def get_queryset(self):
64
- return LedgerModel.objects.for_entity(
65
- user_model=self.request.user,
66
- entity_slug=self.kwargs['entity_slug'],
67
- )
62
+ context = super().get_context_data(**kwargs)
63
+ ledger_model: LedgerModel = self.get_ledger_model()
64
+ context['page_title'] = self.PAGE_TITLE
65
+ context['header_title'] = self.PAGE_TITLE
66
+ context['header_subtitle'] = ledger_model.name
67
+ context['ledger_model'] = ledger_model
68
+ return context
68
69
 
69
70
  def get_form(self, form_class=None):
70
- if self.ledger_model is None:
71
- ledger_model = self.get_object()
72
- self.ledger_model = ledger_model
73
71
  return JournalEntryModelCreateForm(
74
- entity_slug=self.kwargs['entity_slug'],
75
- ledger_model=self.ledger_model,
76
- user_model=self.request.user,
72
+ entity_model=self.get_authorized_entity_instance(),
73
+ ledger_model=self.get_ledger_model(),
77
74
  **self.get_form_kwargs()
78
75
  )
79
76
 
@@ -83,42 +80,51 @@ class JournalEntryCreateView(DjangoLedgerSecurityMixIn, CreateView, SingleObject
83
80
  }
84
81
 
85
82
  def get_success_url(self):
86
- return reverse('django_ledger:je-list',
87
- kwargs={
88
- 'entity_slug': self.kwargs.get('entity_slug'),
89
- 'ledger_pk': self.kwargs.get('ledger_pk')
90
- })
83
+ ledger_model = self.get_ledger_model()
84
+ return ledger_model.get_journal_entry_list_url()
91
85
 
92
86
 
93
- class JournalEntryListView(DjangoLedgerSecurityMixIn, JournalEntryModelModelViewQuerySetMixIn, ArchiveIndexView):
94
- context_object_name = 'journal_entry_list'
87
+ # ARCHIVE VIEWS START....
88
+ class JournalEntryListView(JournalEntryModelModelBaseView, ArchiveIndexView):
89
+ context_object_name = 'journal_entry_qs'
95
90
  template_name = 'django_ledger/journal_entry/je_list.html'
96
91
  PAGE_TITLE = _('Journal Entries')
97
- extra_context = {
98
- 'page_title': PAGE_TITLE,
99
- 'header_title': PAGE_TITLE
100
- }
101
92
  http_method_names = ['get']
102
93
  date_field = 'timestamp'
103
94
  paginate_by = 20
104
95
  allow_empty = True
105
96
 
106
- def get_queryset(self):
107
- qs = super().get_queryset()
108
- qs = qs.annotate(txs_count=Count('transactionmodel'))
109
- return qs
97
+ def get_context_data(self, **kwargs):
98
+ context = super().get_context_data(**kwargs)
99
+ entity_model: EntityModel = self.get_authorized_entity_instance()
110
100
 
101
+ ledger_model = self.get_ledger_model()
102
+ context['ledger_model'] = ledger_model
103
+ context['page_title'] = self.PAGE_TITLE
104
+ context['header_title'] = self.PAGE_TITLE
105
+ context['header_subtitle'] = f'{entity_model.name} | Ledger: {ledger_model.name}'
106
+ context['header_subtitle_icon'] = 'bi:journal-check'
111
107
 
112
- class JournalEntryYearListView(YearArchiveView, JournalEntryListView):
108
+ if ledger_model.is_locked():
109
+ messages.add_message(self.request,
110
+ message=_('Locked Journal Entry. Must unlock ledger to add new Journal Entries.'),
111
+ level=messages.WARNING,
112
+ extra_tags='is-warning')
113
+ return context
114
+
115
+
116
+ class JournalEntryYearListView(JournalEntryListView, YearArchiveView):
113
117
  make_object_list = True
114
118
 
115
119
 
116
- class JournalEntryMonthListView(MonthArchiveView, JournalEntryListView):
120
+ class JournalEntryMonthListView(JournalEntryListView, MonthArchiveView):
117
121
  make_object_list = True
118
122
  month_format = '%m'
119
123
 
120
124
 
121
- class JournalEntryUpdateView(DjangoLedgerSecurityMixIn, JournalEntryModelModelViewQuerySetMixIn, UpdateView):
125
+ # ARCHIVE VIEWS END....
126
+
127
+ class JournalEntryUpdateView(JournalEntryModelModelBaseView, UpdateView):
122
128
  context_object_name = 'journal_entry'
123
129
  template_name = 'django_ledger/journal_entry/je_update.html'
124
130
  pk_url_kwarg = 'je_pk'
@@ -128,34 +134,18 @@ class JournalEntryUpdateView(DjangoLedgerSecurityMixIn, JournalEntryModelModelVi
128
134
  'header_title': PAGE_TITLE
129
135
  }
130
136
 
131
- def get_form(self, form_class=None):
137
+ def get_form_class(self, form_class=None):
132
138
  je_model: JournalEntryModel = self.object
133
139
  if not je_model.can_edit():
134
- return JournalEntryModelCannotEditForm(
135
- entity_slug=self.kwargs['entity_slug'],
136
- ledger_model=je_model.ledger,
137
- user_model=self.request.user,
138
- **self.get_form_kwargs()
139
- )
140
- return JournalEntryModelUpdateForm(
141
- entity_slug=self.kwargs['entity_slug'],
142
- ledger_model=je_model.ledger,
143
- user_model=self.request.user,
144
- **self.get_form_kwargs()
145
- )
140
+ return JournalEntryModelCannotEditForm
141
+ return JournalEntryModelUpdateForm
146
142
 
147
143
  def get_success_url(self):
148
- return reverse('django_ledger:je-list', kwargs={
149
- 'entity_slug': self.kwargs['entity_slug'],
150
- 'ledger_pk': self.kwargs['ledger_pk']
151
- })
152
-
153
- def get_queryset(self):
154
- qs = super().get_queryset()
155
- return qs.prefetch_related('transactionmodel_set', 'transactionmodel_set__account')
144
+ je_model: JournalEntryModel = self.object
145
+ return je_model.get_journal_entry_list_url()
156
146
 
157
147
 
158
- class JournalEntryDetailView(DjangoLedgerSecurityMixIn, JournalEntryModelModelViewQuerySetMixIn, DetailView):
148
+ class JournalEntryDetailView(JournalEntryModelModelBaseView, DetailView):
159
149
  context_object_name = 'journal_entry'
160
150
  template_name = 'django_ledger/journal_entry/je_detail.html'
161
151
  slug_url_kwarg = 'je_pk'
@@ -168,28 +158,19 @@ class JournalEntryDetailView(DjangoLedgerSecurityMixIn, JournalEntryModelModelVi
168
158
  }
169
159
  http_method_names = ['get']
170
160
 
171
- def get_queryset(self):
172
- qs = super().get_queryset()
173
- return qs.prefetch_related('transactionmodel_set', 'transactionmodel_set__account')
174
-
175
161
 
176
- class JournalEntryDeleteView(DjangoLedgerSecurityMixIn, JournalEntryModelModelViewQuerySetMixIn, DeleteView):
162
+ class JournalEntryDeleteView(JournalEntryModelModelBaseView, DeleteView):
177
163
  template_name = 'django_ledger/journal_entry/je_delete.html'
178
164
  context_object_name = 'je_model'
179
165
  pk_url_kwarg = 'je_pk'
180
166
 
181
167
  def get_success_url(self) -> str:
182
168
  je_model: JournalEntryModel = self.object
183
- return reverse(
184
- viewname='django_ledger:je-list',
185
- kwargs={
186
- 'entity_slug': self.AUTHORIZED_ENTITY_MODEL.slug,
187
- 'ledger_pk': je_model.ledger_id
188
- }
189
- )
169
+ return je_model.get_journal_entry_list_url()
190
170
 
191
171
 
192
- class JournalEntryModelTXSDetailView(DjangoLedgerSecurityMixIn, JournalEntryModelModelViewQuerySetMixIn, DetailView):
172
+ # todo:.... move this to transaction list view?.....
173
+ class JournalEntryModelTXSDetailView(JournalEntryModelModelBaseView, DetailView):
193
174
  template_name = 'django_ledger/journal_entry/je_detail_txs.html'
194
175
  PAGE_TITLE = _('Edit Transactions')
195
176
  pk_url_kwarg = 'je_pk'
@@ -214,11 +195,8 @@ class JournalEntryModelTXSDetailView(DjangoLedgerSecurityMixIn, JournalEntryMode
214
195
  if not txs_formset:
215
196
  TransactionModelFormSet = get_transactionmodel_formset_class(journal_entry_model=je_model)
216
197
  context['txs_formset'] = TransactionModelFormSet(
217
- user_model=self.request.user,
218
198
  je_model=je_model,
219
- ledger_pk=self.kwargs['ledger_pk'],
220
- entity_slug=self.kwargs['entity_slug'],
221
- queryset=je_model.transactionmodel_set.all().order_by('account__code')
199
+ entity_model=self.get_authorized_entity_instance(),
222
200
  )
223
201
  else:
224
202
  context['txs_formset'] = txs_formset
@@ -234,9 +212,7 @@ class JournalEntryModelTXSDetailView(DjangoLedgerSecurityMixIn, JournalEntryMode
234
212
 
235
213
  TransactionModelFormSet = get_transactionmodel_formset_class(journal_entry_model=je_model)
236
214
  txs_formset = TransactionModelFormSet(request.POST,
237
- user_model=self.request.user,
238
- ledger_pk=kwargs['ledger_pk'],
239
- entity_slug=kwargs['entity_slug'],
215
+ entity_model=self.get_authorized_entity_instance(),
240
216
  je_model=je_model)
241
217
 
242
218
  if je_model.locked:
@@ -271,7 +247,11 @@ class JournalEntryModelTXSDetailView(DjangoLedgerSecurityMixIn, JournalEntryMode
271
247
 
272
248
 
273
249
  # ACTION VIEWS...
274
- class BaseJournalEntryActionView(DjangoLedgerSecurityMixIn, RedirectView, SingleObjectMixin):
250
+ class BaseJournalEntryActionView(
251
+ JournalEntryModelModelBaseView,
252
+ RedirectView,
253
+ SingleObjectMixin
254
+ ):
275
255
  http_method_names = ['get']
276
256
  pk_url_kwarg = 'je_pk'
277
257
  action_name = None
@@ -279,11 +259,14 @@ class BaseJournalEntryActionView(DjangoLedgerSecurityMixIn, RedirectView, Single
279
259
 
280
260
  def get_queryset(self):
281
261
  return JournalEntryModel.objects.for_entity(
282
- entity_slug=self.kwargs['entity_slug'],
262
+ entity_slug=self.get_authorized_entity_instance(),
283
263
  user_model=self.request.user
284
- )
264
+ ).for_ledger(ledger_pk=self.kwargs['ledger_pk'])
285
265
 
286
266
  def get_redirect_url(self, *args, **kwargs):
267
+ next_url = self.request.GET.get('next')
268
+ if next_url:
269
+ return next_url
287
270
  return reverse('django_ledger:je-list',
288
271
  kwargs={
289
272
  'entity_slug': kwargs['entity_slug'],