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

File without changes
django_ledger/__init__.py CHANGED
@@ -9,7 +9,7 @@ Contributions to this module:
9
9
  default_app_config = 'django_ledger.apps.DjangoLedgerConfig'
10
10
 
11
11
  """Django Ledger"""
12
- __version__ = '0.6.0.2'
12
+ __version__ = '0.6.2'
13
13
  __license__ = 'GPLv3 License'
14
14
 
15
15
  __author__ = 'Miguel Sanda'
@@ -6,9 +6,7 @@ Contributions to this module:
6
6
  Miguel Sanda <msanda@arrobalytics.com>
7
7
  """
8
8
 
9
- from django_ledger.io.io_digest import *
9
+ from django_ledger.io.io_context import *
10
10
  from django_ledger.io.io_middleware import *
11
11
  from django_ledger.io.ratios import *
12
12
  from django_ledger.io.roles import *
13
- # due to circular import
14
- # from django_ledger.io.io_library import IOLibrary
@@ -38,6 +38,10 @@ class IODigestContextManager:
38
38
  def get_strftime_format(self):
39
39
  return self.STRFTIME_FORMAT
40
40
 
41
+ @property
42
+ def from_datetime(self):
43
+ return self.get_from_datetime()
44
+
41
45
  def get_from_datetime(self, as_str: bool = False, fmt=None) -> Optional[datetime]:
42
46
  from_date = self.IO_DATA['from_date']
43
47
  if from_date:
@@ -47,6 +51,10 @@ class IODigestContextManager:
47
51
  return from_date.strftime(fmt)
48
52
  return from_date
49
53
 
54
+ @property
55
+ def to_datetime(self):
56
+ return self.get_to_datetime()
57
+
50
58
  def get_to_datetime(self, as_str: bool = False, fmt=None) -> datetime:
51
59
  if as_str:
52
60
  if not fmt:
@@ -36,7 +36,7 @@ from django.utils.translation import gettext_lazy as _
36
36
  from django_ledger import settings
37
37
  from django_ledger.exceptions import InvalidDateInputError, TransactionNotInBalanceError
38
38
  from django_ledger.io import roles as roles_module
39
- from django_ledger.io.io_digest import IODigestContextManager
39
+ from django_ledger.io.io_context import IODigestContextManager
40
40
  from django_ledger.io.io_middleware import (
41
41
  AccountRoleIOMiddleware,
42
42
  AccountGroupIOMiddleware,
@@ -343,7 +343,7 @@ class IODatabaseMixIn:
343
343
  Returns results aggregated by accounting if needed. Defaults to False.
344
344
  by_unit: bool
345
345
  Returns results aggregated by unit if needed. Defaults to False.
346
- use_closing_entry: bool
346
+ use_closing_entries: bool
347
347
  Overrides the DJANGO_LEDGER_USE_CLOSING_ENTRIES setting.
348
348
  Returns
349
349
  -------
@@ -587,7 +587,7 @@ class IODatabaseMixIn:
587
587
  signs: bool
588
588
  Changes the balance of an account to negative if it represents a "negative" for display purposes.
589
589
  (i.e. Expense accounts will show balance as negative and Income accounts as positive.)
590
- force_closing_entry_use: bool
590
+ use_closing_entries: bool
591
591
  Forces the use of closing entries if DJANGO_LEDGER_USE_CLOSING_ENTRIES setting is set to False.
592
592
  force_queryset_sorting: bool
593
593
  Forces sorting of the TransactionModelQuerySet before aggregation balances.
@@ -116,7 +116,7 @@ class EntityModelManager(MP_NodeManager):
116
116
  qs = EntityModelQuerySet(self.model, using=self._db).order_by('path')
117
117
  return qs.order_by('path').select_related('admin', 'default_coa')
118
118
 
119
- def for_user(self, user_model):
119
+ def for_user(self, user_model, authorized_superuser: bool = False):
120
120
  """
121
121
  This QuerySet guarantees that Users do not access or operate on EntityModels that don't have access to.
122
122
  This is the recommended initial QuerySet.
@@ -125,6 +125,8 @@ class EntityModelManager(MP_NodeManager):
125
125
  ----------
126
126
  user_model
127
127
  The Django User Model making the request.
128
+ authorized_superuser
129
+ Allows any superuser to access the EntityModel. Default is False.
128
130
 
129
131
  Returns
130
132
  -------
@@ -134,7 +136,7 @@ class EntityModelManager(MP_NodeManager):
134
136
  2. Is a manager.
135
137
  """
136
138
  qs = self.get_queryset()
137
- if user_model.is_superuser:
139
+ if user_model.is_superuser and authorized_superuser:
138
140
  return qs
139
141
  return qs.filter(
140
142
  Q(admin=user_model) |
@@ -881,8 +881,6 @@ class ItemTransactionModelManager(models.Manager):
881
881
 
882
882
  def for_user(self, user_model):
883
883
  qs = self.get_queryset()
884
- if user_model.is_superuser:
885
- return qs
886
884
  return qs.filter(
887
885
  Q(item_model__entity__admin=user_model) |
888
886
  Q(item_model__entity__managers__in=[user_model])
@@ -891,7 +889,7 @@ class ItemTransactionModelManager(models.Manager):
891
889
  def for_entity(self, user_model, entity_slug):
892
890
  qs = self.for_user(user_model)
893
891
  if isinstance(entity_slug, lazy_loader.get_entity_model()):
894
- qs.filter(
892
+ return qs.filter(
895
893
  Q(item_model__entity=entity_slug)
896
894
  )
897
895
  return qs.filter(
@@ -226,7 +226,6 @@ class LedgerModelAbstract(CreateUpdateMixIn, IOMixIn):
226
226
  ledger_str = f'LedgerModel: {self.uuid}'
227
227
  return f'{ledger_str} | Posted: {self.posted} | Locked: {self.locked}'
228
228
 
229
-
230
229
  def has_wrapped_model_info(self):
231
230
  if self.additional_info is not None:
232
231
  return self._WRAPPED_MODEL_KEY in self.additional_info
@@ -523,7 +522,7 @@ class LedgerModelAbstract(CreateUpdateMixIn, IOMixIn):
523
522
  je_model_qs.bulk_update(objs=je_model_qs, fields=['locked', 'updated'])
524
523
  return je_model_qs
525
524
 
526
- def unlock(self, commit: bool = False, **kwargs):
525
+ def unlock(self, commit: bool = False, raise_exception: bool = True, **kwargs):
527
526
  """
528
527
  Un-locks the LedgerModel.
529
528
 
@@ -532,13 +531,19 @@ class LedgerModelAbstract(CreateUpdateMixIn, IOMixIn):
532
531
  commit: bool
533
532
  If True, saves the LedgerModel instance instantly. Defaults to False.
534
533
  """
535
- if self.can_unlock():
536
- self.locked = False
537
- if commit:
538
- self.save(update_fields=[
539
- 'locked',
540
- 'updated'
541
- ])
534
+ if not self.can_unlock():
535
+ if raise_exception:
536
+ raise LedgerModelValidationError(
537
+ message=_(f'Ledger {self.name} cannot be un-locked. UUID: {self.uuid}')
538
+ )
539
+ return
540
+
541
+ self.locked = False
542
+ if commit:
543
+ self.save(update_fields=[
544
+ 'locked',
545
+ 'updated'
546
+ ])
542
547
 
543
548
  def hide(self, commit: bool = False, raise_exception: bool = True, **kwargs):
544
549
  if not self.can_hide():
@@ -487,7 +487,8 @@ class AccrualMixIn(models.Model):
487
487
  if ledger_model.locked:
488
488
  if raise_exception:
489
489
  raise ValidationError(f'Bill ledger {ledger_model.name} is already locked...')
490
- ledger_model.lock(commit)
490
+ return
491
+ ledger_model.lock(commit, raise_exception=raise_exception)
491
492
 
492
493
  def unlock_ledger(self, commit: bool = False, raise_exception: bool = True, **kwargs):
493
494
  """
@@ -501,10 +502,11 @@ class AccrualMixIn(models.Model):
501
502
  If True, raises ValidationError if LedgerModel already locked.
502
503
  """
503
504
  ledger_model = self.ledger
504
- if not ledger_model.locked:
505
+ if not ledger_model.is_locked():
505
506
  if raise_exception:
506
507
  raise ValidationError(f'Bill ledger {ledger_model.name} is already unlocked...')
507
- ledger_model.unlock(commit)
508
+ return
509
+ ledger_model.unlock(commit, raise_exception=raise_exception)
508
510
 
509
511
  # POST/UNPOST Ledger...
510
512
  def post_ledger(self, commit: bool = False, raise_exception: bool = True, **kwargs):
@@ -522,7 +524,8 @@ class AccrualMixIn(models.Model):
522
524
  if ledger_model.posted:
523
525
  if raise_exception:
524
526
  raise ValidationError(f'Bill ledger {ledger_model.name} is already posted...')
525
- ledger_model.post(commit)
527
+ return
528
+ ledger_model.post(commit, raise_exception=raise_exception)
526
529
 
527
530
  def unpost_ledger(self, commit: bool = False, raise_exception: bool = True, **kwargs):
528
531
  """
@@ -536,13 +539,14 @@ class AccrualMixIn(models.Model):
536
539
  If True, raises ValidationError if LedgerModel already locked.
537
540
  """
538
541
  ledger_model = self.ledger
539
- if not ledger_model.posted:
542
+ if not ledger_model.is_posted():
540
543
  if raise_exception:
541
544
  raise ValidationError(f'Bill ledger {ledger_model.name} is not posted...')
542
- ledger_model.post(commit)
545
+ return
546
+ ledger_model.post(commit, raise_exception=raise_exception)
543
547
 
544
548
  def migrate_state(self,
545
- # todo: remove usermodel param...
549
+ # todo: remove usermodel param...?
546
550
  user_model,
547
551
  entity_slug: str,
548
552
  itemtxs_qs: Optional[QuerySet] = None,
@@ -49,35 +49,6 @@ class TransactionModelQuerySet(QuerySet):
49
49
  """
50
50
  A custom QuerySet class for TransactionModels implementing methods to effectively and safely read
51
51
  TransactionModels from the database.
52
-
53
- Methods
54
- -------
55
- posted() -> TransactionModelQuerySet:
56
- Fetches a QuerySet of posted transactions only.
57
-
58
- for_accounts(account_list: List[str or AccountModel]) -> TransactionModelQuerySet:
59
- Fetches a QuerySet of TransactionModels which AccountModel has a specific role.
60
-
61
- for_roles(role_list: Union[str, List[str]]) -> TransactionModelQuerySet:
62
- Fetches a QuerySet of TransactionModels which AccountModel has a specific role.
63
-
64
- for_unit(unit_slug: Union[str, EntityUnitModel]) -> TransactionModelQuerySet:
65
- Fetches a QuerySet of TransactionModels associated with a specific EntityUnitModel.
66
-
67
- for_activity(activity_list: Union[str, List[str]]) -> TransactionModelQuerySet:
68
- Fetches a QuerySet of TransactionModels associated with a specific activity or list of activities.
69
-
70
- to_date(to_date: Union[str, date, datetime]) -> TransactionModelQuerySet:
71
- Fetches a QuerySet of TransactionModels associated with a maximum date or timestamp filter.
72
-
73
- from_date(from_date: Union[str, date, datetime]) -> TransactionModelQuerySet:
74
- Fetches a QuerySet of TransactionModels associated with a minimum date or timestamp filter.
75
-
76
- not_closing_entry() -> TransactionModelQuerySet:
77
- Fetches a QuerySet of TransactionModels that are not part of a closing entry.
78
-
79
- is_closing_entry() -> TransactionModelQuerySet:
80
- Fetches a QuerySet of TransactionModels that are part of a closing entry.
81
52
  """
82
53
 
83
54
  def posted(self) -> QuerySet:
@@ -111,7 +82,7 @@ class TransactionModelQuerySet(QuerySet):
111
82
  TransactionModelQuerySet
112
83
  Returns a TransactionModelQuerySet with applied filters.
113
84
  """
114
- if len(account_list) > 0 and isinstance(account_list[0], str):
85
+ if isinstance(account_list, list) > 0 and isinstance(account_list[0], str):
115
86
  return self.filter(account__code__in=account_list)
116
87
  return self.filter(account__in=account_list)
117
88
 
@@ -276,8 +247,6 @@ class TransactionModelManager(models.Manager):
276
247
  ledger or the user is one of the managers of the entity associated with the transaction's ledger.
277
248
  """
278
249
  qs = self.get_queryset()
279
- if user_model.is_superuser:
280
- return qs
281
250
  return qs.filter(
282
251
  Q(journal_entry__ledger__entity__admin=user_model) |
283
252
  Q(journal_entry__ledger__entity__managers__in=[user_model])
@@ -4,7 +4,6 @@
4
4
  <div class="table-container">
5
5
  <table class="table is-fullwidth is-narrow is-striped">
6
6
  <tbody>
7
-
8
7
  {% for bs_role, bs_role_data in tx_digest.balance_sheet.items %}
9
8
  {% if bs_role_data.is_block %}
10
9
  <tr>
@@ -137,7 +137,7 @@ def cash_flow_statement(context, io_model):
137
137
 
138
138
  @register.inclusion_tag('django_ledger/financial_statements/tags/income_statement.html', takes_context=True)
139
139
  def income_statement_table(context, io_model, from_date=None, to_date=None):
140
- user_model: EntityUnitModel = context['user']
140
+ user_model = context['user']
141
141
  activity = context['request'].GET.get('activity')
142
142
  activity = validate_activity(activity, raise_404=True)
143
143
  entity_slug = context['view'].kwargs.get('entity_slug')
@@ -199,8 +199,8 @@ class EntityModelDetailBaseView(DjangoLedgerSecurityMixIn,
199
199
  FETCH_UNPAID_BILLS = True
200
200
  FETCH_UNPAID_INVOICES = True
201
201
 
202
- IO_DIGEST = True
203
- IO_DIGEST_EQUITY = True
202
+ IO_DIGEST_UNBOUNDED = True
203
+ IO_DIGEST_BOUNDED = True
204
204
 
205
205
  def get_context_data(self, **kwargs):
206
206
  context = super().get_context_data(**kwargs)
@@ -24,7 +24,18 @@ from django_ledger.models.entity import EntityModelFiscalPeriodMixIn
24
24
  from django_ledger.settings import DJANGO_LEDGER_PDF_SUPPORT_ENABLED, DJANGO_LEDGER_AUTHORIZED_SUPERUSER
25
25
 
26
26
 
27
- class YearlyReportMixIn(YearMixin, EntityModelFiscalPeriodMixIn):
27
+ class ContextFromToDateMixin:
28
+ FROM_DATE_CONTEXT_NAME = 'from_date'
29
+ TO_DATE_CONTEXT_NAME = 'to_date'
30
+
31
+ def get_from_date_context_name(self) -> str:
32
+ return self.FROM_DATE_CONTEXT_NAME
33
+
34
+ def get_to_date_context_name(self) -> str:
35
+ return self.TO_DATE_CONTEXT_NAME
36
+
37
+
38
+ class YearlyReportMixIn(YearMixin, ContextFromToDateMixin, EntityModelFiscalPeriodMixIn):
28
39
 
29
40
  def get_from_date(self, year: int = None, fy_start: int = None, **kwargs) -> date:
30
41
  return self.get_year_start_date(year, fy_start)
@@ -58,16 +69,16 @@ class YearlyReportMixIn(YearMixin, EntityModelFiscalPeriodMixIn):
58
69
  context['year_start'] = year_start
59
70
  context['year_end'] = year_end
60
71
 
61
- if 'from_date' not in context:
62
- context['from_date'] = year_start
63
- if 'to_date' not in context:
64
- context['to_date'] = year_end
72
+ if self.get_from_date_context_name() not in context:
73
+ context[self.get_from_date_context_name()] = year_start
74
+ if self.get_to_date_context_name() not in context:
75
+ context[self.get_to_date_context_name()] = year_end
65
76
 
66
77
  context['has_year'] = True
67
78
  return context
68
79
 
69
80
 
70
- class QuarterlyReportMixIn(YearMixin, EntityModelFiscalPeriodMixIn):
81
+ class QuarterlyReportMixIn(YearMixin, ContextFromToDateMixin, EntityModelFiscalPeriodMixIn):
71
82
  quarter = None
72
83
  quarter_url_kwarg = 'quarter'
73
84
 
@@ -137,10 +148,10 @@ class QuarterlyReportMixIn(YearMixin, EntityModelFiscalPeriodMixIn):
137
148
  context['quarter_start'] = quarter_start
138
149
  context['quarter_end'] = quarter_end
139
150
 
140
- if 'from_date' not in context:
141
- context['from_date'] = quarter_start
142
- if 'to_date' not in context:
143
- context['to_date'] = quarter_end
151
+ if self.get_from_date_context_name() not in context:
152
+ context[self.get_from_date_context_name()] = quarter_start
153
+ if self.get_to_date_context_name() not in context:
154
+ context[self.get_to_date_context_name()] = quarter_end
144
155
 
145
156
  context['has_quarter'] = True
146
157
  return context
@@ -154,7 +165,7 @@ class QuarterlyReportMixIn(YearMixin, EntityModelFiscalPeriodMixIn):
154
165
  return quarter - 1
155
166
 
156
167
 
157
- class MonthlyReportMixIn(YearlyReportMixIn, MonthMixin):
168
+ class MonthlyReportMixIn(YearlyReportMixIn, ContextFromToDateMixin, MonthMixin):
158
169
 
159
170
  def get_from_date(self, month: int = None, year: int = None, **kwargs) -> date:
160
171
  return self.get_month_start_date(month=month, year=year)
@@ -206,13 +217,17 @@ class MonthlyReportMixIn(YearlyReportMixIn, MonthMixin):
206
217
  month_end = self.get_month_end_date(year=year, month=month)
207
218
  context['month_start'] = month_start
208
219
  context['month_end'] = month_end
209
- context['from_date'] = month_start
210
- context['to_date'] = month_end
220
+
221
+ if self.get_from_date_context_name() not in context:
222
+ context[self.get_from_date_context_name()] = month_start
223
+ if self.get_to_date_context_name() not in context:
224
+ context[self.get_to_date_context_name()] = month_end
225
+
211
226
  context['has_month'] = True
212
227
  return context
213
228
 
214
229
 
215
- class DateReportMixIn(MonthlyReportMixIn, DayMixin):
230
+ class DateReportMixIn(MonthlyReportMixIn, ContextFromToDateMixin, DayMixin):
216
231
 
217
232
  def get_context_data(self, **kwargs):
218
233
  context = super(MonthlyReportMixIn, self).get_context_data(**kwargs)
@@ -221,8 +236,12 @@ class DateReportMixIn(MonthlyReportMixIn, DayMixin):
221
236
  context['next_day'] = view_date + timedelta(days=1)
222
237
  context['previous_day'] = view_date - timedelta(days=1)
223
238
  context['view_date'] = view_date
224
- context['from_date'] = view_date
225
- context['to_date'] = view_date
239
+
240
+ if self.get_from_date_context_name() not in context:
241
+ context[self.get_from_date_context_name()] = view_date
242
+ if self.get_to_date_context_name() not in context:
243
+ context[self.get_to_date_context_name()] = view_date
244
+
226
245
  return context
227
246
 
228
247
  def get_date(self) -> date:
@@ -243,7 +262,8 @@ class DateReportMixIn(MonthlyReportMixIn, DayMixin):
243
262
  return dt, dt
244
263
 
245
264
 
246
- class FromToDatesMixIn:
265
+ # todo: need to incorporate in base view...
266
+ class FromToDatesParseMixIn:
247
267
  DJL_FROM_DATE_PARAM: str = 'from_date'
248
268
  DJL_TO_DATE_PARAM: str = 'to_date'
249
269
  DJL_NO_FROM_DATE_RAISE_404: bool = True
@@ -311,25 +331,20 @@ class DjangoLedgerSecurityMixIn(LoginRequiredMixin, PermissionRequiredMixin):
311
331
  )
312
332
  return self.ENTITY_SLUG_URL_KWARG
313
333
 
334
+ def get_superuser_authorization(self):
335
+ return self.AUTHORIZE_SUPERUSER
336
+
314
337
  def has_permission(self):
338
+ has_perm = super().has_permission()
339
+ if not has_perm:
340
+ return False
341
+
315
342
  entity_slug_kwarg = self.get_entity_slug_kwarg()
316
- if self.request.user.is_superuser:
317
- if not self.AUTHORIZE_SUPERUSER:
318
- return False
319
- if entity_slug_kwarg in self.kwargs:
320
- try:
321
- entity_model_qs = self.get_authorized_entity_queryset()
322
- self.AUTHORIZED_ENTITY_MODEL = entity_model_qs.get(slug__exact=self.kwargs[entity_slug_kwarg])
323
- except ObjectDoesNotExist:
324
- return False
325
- return True
326
- elif self.request.user.is_authenticated:
327
- has_perm = super().has_permission()
328
- if not has_perm:
329
- return False
343
+ entity_model_qs = self.get_authorized_entity_queryset()
344
+
345
+ if self.request.user.is_authenticated:
330
346
  if entity_slug_kwarg in self.kwargs:
331
347
  try:
332
- entity_model_qs = self.get_authorized_entity_queryset()
333
348
  self.AUTHORIZED_ENTITY_MODEL = entity_model_qs.get(slug__exact=self.kwargs[entity_slug_kwarg])
334
349
  except ObjectDoesNotExist:
335
350
  return False
@@ -338,7 +353,9 @@ class DjangoLedgerSecurityMixIn(LoginRequiredMixin, PermissionRequiredMixin):
338
353
 
339
354
  def get_authorized_entity_queryset(self):
340
355
  return EntityModel.objects.for_user(
341
- user_model=self.request.user).only(
356
+ user_model=self.request.user,
357
+ authorized_superuser=self.get_superuser_authorization(),
358
+ ).only(
342
359
  'uuid', 'slug', 'name', 'default_coa', 'admin')
343
360
 
344
361
  def get_authorized_entity_instance(self) -> Optional[EntityModel]:
@@ -372,8 +389,27 @@ class EntityUnitMixIn:
372
389
 
373
390
 
374
391
  class DigestContextMixIn:
375
- IO_DIGEST = False
376
- IO_DIGEST_EQUITY = False
392
+
393
+ IO_DIGEST_UNBOUNDED = False
394
+ IO_DIGEST_BOUNDED = False
395
+
396
+ IO_DIGEST_UNBOUNDED_CONTEXT_NAME = 'tx_digest'
397
+ IO_MANAGER_UNBOUNDED_CONTEXT_NAME = 'tx_digest_context'
398
+
399
+ IO_DIGEST_BOUNDED_CONTEXT_NAME = 'equity_digest'
400
+ IO_MANAGER_BOUNDED_CONTEXT_NAME = 'equity_digest_context'
401
+
402
+ def get_io_digest_unbounded_context_name(self):
403
+ return self.IO_DIGEST_UNBOUNDED_CONTEXT_NAME
404
+
405
+ def get_io_manager_unbounded_context_name(self):
406
+ return self.IO_MANAGER_UNBOUNDED_CONTEXT_NAME
407
+
408
+ def get_io_digest_bounded_context_name(self):
409
+ return self.IO_DIGEST_BOUNDED_CONTEXT_NAME
410
+
411
+ def get_io_manager_bounded_context_name(self):
412
+ return self.IO_MANAGER_BOUNDED_CONTEXT_NAME
377
413
 
378
414
  def get_context_data(self, **kwargs):
379
415
  context = super(DigestContextMixIn, self).get_context_data(**kwargs)
@@ -385,8 +421,8 @@ class DigestContextMixIn:
385
421
  to_date=None,
386
422
  **kwargs):
387
423
 
388
- if any([self.IO_DIGEST,
389
- self.IO_DIGEST_EQUITY]):
424
+ if any([self.IO_DIGEST_UNBOUNDED,
425
+ self.IO_DIGEST_BOUNDED]):
390
426
 
391
427
  by_period = self.request.GET.get('by_period')
392
428
  entity_model: EntityModel = self.object
@@ -401,7 +437,7 @@ class DigestContextMixIn:
401
437
  else:
402
438
  unit_slug = None
403
439
 
404
- if self.IO_DIGEST:
440
+ if self.IO_DIGEST_UNBOUNDED:
405
441
  io_digest = entity_model.digest(user_model=self.request.user,
406
442
  to_date=to_date,
407
443
  unit_slug=unit_slug,
@@ -410,22 +446,22 @@ class DigestContextMixIn:
410
446
  process_roles=True,
411
447
  process_groups=True)
412
448
 
413
- context['tx_digest_context'] = io_digest
414
- context['tx_digest'] = io_digest.get_io_data()
449
+ context[self.get_io_manager_unbounded_context_name()] = io_digest
450
+ context[self.get_io_digest_unbounded_context_name()] = io_digest.get_io_data()
415
451
 
416
- if self.IO_DIGEST_EQUITY:
452
+ if self.IO_DIGEST_BOUNDED:
417
453
  io_digest_equity = entity_model.digest(user_model=self.request.user,
418
454
  equity_only=True,
419
455
  to_date=to_date,
420
456
  from_date=from_date,
421
457
  unit_slug=unit_slug,
422
458
  by_period=True if by_period else False,
423
- process_ratios=False,
424
- process_roles=False,
459
+ process_ratios=True,
460
+ process_roles=True,
425
461
  process_groups=True)
426
462
 
427
- context['equity_digest_context'] = io_digest_equity
428
- context['equity_digest'] = io_digest_equity.get_io_data()
463
+ context[self.get_io_manager_bounded_context_name()] = io_digest_equity
464
+ context[self.get_io_digest_bounded_context_name()] = io_digest_equity.get_io_data()
429
465
 
430
466
  # todo: how is this used??....
431
467
  context['date_filter'] = to_date
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-ledger
3
- Version: 0.6.0.2
3
+ Version: 0.6.2
4
4
  Summary: Double entry accounting system built on the Django Web Framework.
5
5
  Author-email: Miguel Sanda <msanda@arrobalytics.com>
6
6
  Maintainer-email: Miguel Sanda <msanda@arrobalytics.com>
@@ -48,7 +48,7 @@ assets/node_modules/node-gyp/gyp/tools/pretty_gyp.py,sha256=2ZCRPW-MZfK7gdnCIaqh
48
48
  assets/node_modules/node-gyp/gyp/tools/pretty_sln.py,sha256=b_Fxm-SXUCPL3Tix4EyNwZNmQ-zkeRIFFmuL0R5wFhw,5482
49
49
  assets/node_modules/node-gyp/gyp/tools/pretty_vcproj.py,sha256=AwQrxK1F-jhjsbbT35XQjrvWNbc3IBFaKXoJogqMh_o,10633
50
50
  assets/node_modules/node-gyp/test/fixtures/test-charmap.py,sha256=5raXzaQnO2eJnrlFtlDtWftryhZX7Fj0amFW3hdSnhE,547
51
- django_ledger/__init__.py,sha256=c-3dvReg1GgIIrDElZzpUfB38BXg2TAKf5d9uhe5WMQ,458
51
+ django_ledger/__init__.py,sha256=XWsm2GPCPw5ayJIKYpT2rO83Yxp4iYr5a0vNyC4ao3Y,456
52
52
  django_ledger/apps.py,sha256=H-zEWUjKGakgSDSZmLIoXChZ2h6e0dth0ZO5SpoT-8U,163
53
53
  django_ledger/exceptions.py,sha256=rML8sQQ0Hq-DYMLZ76dfw2RYSAsXWUoyHuyC_yP9o1o,491
54
54
  django_ledger/settings.py,sha256=bZyPKgjmRcO_Rj7hDi4gGlW0VFr_LP2yKeUVIkmWgQM,6321
@@ -114,9 +114,9 @@ django_ledger/forms/transactions.py,sha256=DD2TJthArTKTuzd4A43ZbugepcB8iuJ4Q_PSR
114
114
  django_ledger/forms/unit.py,sha256=rXUefjpuAmUU0vPOqu1ObO4k-bN-_Q6kOqHJ4kp_Vlg,1131
115
115
  django_ledger/forms/utils.py,sha256=sgkwBZs15_rZ5NT7h-8Z7wi3-ItM1E1sqoVDo3NQ5Jc,513
116
116
  django_ledger/forms/vendor.py,sha256=Nuh8MmSpz4ycMZwiVe--U9Ec6ezIsfACHDkhA2SyiZ4,2215
117
- django_ledger/io/__init__.py,sha256=Y9R-mY4peg8EpxmlXKaBER1IHMU-Nos8_dII41Kj0Ho,445
118
- django_ledger/io/io_core.py,sha256=Cutbj5WQQ0Mrja2_kLw02KL6_JygDdJvDp7JF5KzWJU,46923
119
- django_ledger/io/io_digest.py,sha256=W_bCH6JxGw6eASDb1k43JuGAejvOVfyA7WkCS7AEqDQ,4280
117
+ django_ledger/io/__init__.py,sha256=8m5AoBRiG2ymrX0Y4LVjq0275i7I5Sk7YRa1BTzVofI,369
118
+ django_ledger/io/io_context.py,sha256=xgykRoB6hVSN2q20f62j_4zbOeAHU5ZgbZaSwRaSkOU,4444
119
+ django_ledger/io/io_core.py,sha256=b_-je0NNPkMOglkJwObxfKA6eWa0YvEod9LODm5RRIg,46922
120
120
  django_ledger/io/io_generator.py,sha256=JF4plsABUkCIrtI2X-YD7o5eNghRIgLUseNcBIGOj3U,34613
121
121
  django_ledger/io/io_library.py,sha256=vvQm3IQRLFdH7HS_DYX46Xe-U9IvgZ6MQnHjy0-fyjk,22480
122
122
  django_ledger/io/io_middleware.py,sha256=c-vwpcjg2HbYbb4O36fdf6011dFOnoNsDHOAQXmJgB8,20052
@@ -152,15 +152,15 @@ django_ledger/models/coa.py,sha256=o-VM2XK64djM3px6pJlGrUVTXu5qNb4ENESS70I___0,2
152
152
  django_ledger/models/coa_default.py,sha256=4Zj8OMhgBiYuREjM82cFfyGWd8uCAeqggVkeNhg4SLU,27338
153
153
  django_ledger/models/customer.py,sha256=JQOktcYKUlENJv4frek9rAW6sRerrQ0xXHlC5KPmhWk,11807
154
154
  django_ledger/models/data_import.py,sha256=2H-4oTVLa7qXq03m9fd7T5zSQLkZKOAn2OAeOQBzMPA,19477
155
- django_ledger/models/entity.py,sha256=YYcgiVsC4aDl-htStJRQ6_1Hdmw5oHK4mBP2L0XanwI,121708
155
+ django_ledger/models/entity.py,sha256=VFknz-7FQZu_gVDb5RWqPoCb3eXVzIMgmr4hatUlzBI,121876
156
156
  django_ledger/models/estimate.py,sha256=-qB5t2cEdyYpFUq7tOUQnFqvE6EDUiVdTtzjEbESwEQ,55829
157
157
  django_ledger/models/invoice.py,sha256=h5Jh5KOfYr31Eu9gFW1mdoGoVzx7nW8qBdx7vyiXnZU,61568
158
- django_ledger/models/items.py,sha256=O9ujsut2jiISwKEmYcCTdUdsFywm0S-RKUDPCeXvPgY,55093
158
+ django_ledger/models/items.py,sha256=Wh_zPBnYCdI393nHafT6xd4aSutKBQPwKSjDtXTTPNQ,55042
159
159
  django_ledger/models/journal_entry.py,sha256=VfXXvm3tUFuy2Z6j3PLlDk9ndHqsZgn_PuhrxTNqaiY,50918
160
- django_ledger/models/ledger.py,sha256=q6yWf9jGK05kah_19Cbijc8HZErPM1koPejKO3ZbYXI,23382
161
- django_ledger/models/mixins.py,sha256=SBcSMfFuFzLqFQv298aDOfAJrF5kT91oXyo384auKqc,51903
160
+ django_ledger/models/ledger.py,sha256=kPxyKo5u0-2viifCY87Ms3xglmgrfiDAg0oJgsOrDwc,23603
161
+ django_ledger/models/mixins.py,sha256=s8ZjEjYQfmU88cLyFNKoiFi79_g1rTe1knEccV2WUXw,52122
162
162
  django_ledger/models/purchase_order.py,sha256=CDibi90e7Yhpv_UiyP32mMcsQ0EUElXJ2r8pLzuS7yE,42729
163
- django_ledger/models/transactions.py,sha256=aRZuP-zg-ZrxBi6rt3wx2ELXhsRC-BS9NtNUDCU2DV0,24236
163
+ django_ledger/models/transactions.py,sha256=kOL7s-hiRc6iqS7J62bVJY6ikja9Q8WdkRq0FT0zO2U,22722
164
164
  django_ledger/models/unit.py,sha256=x5FFJXgOi1OdajQejIakW6wGY4DjrJhL3S0Pm5OimMk,8074
165
165
  django_ledger/models/utils.py,sha256=3gkdCrfJp9qwN3Sf8R96AliilzwcKBm31UEao4WJO9o,8436
166
166
  django_ledger/models/vendor.py,sha256=akJCO86GIwjlZ_jPUZCDXlMeuJe-8zKTm-52aJXGFpg,11320
@@ -275,7 +275,7 @@ django_ledger/templates/django_ledger/expense/tags/expense_item_table.html,sha25
275
275
  django_ledger/templates/django_ledger/financial_statements/balance_sheet.html,sha256=rFzmK2-AjV_11fp7b6ou-KtMSwm7jN3vfpd4Ki_9-s0,2793
276
276
  django_ledger/templates/django_ledger/financial_statements/cash_flow.html,sha256=zeu7OcXl2T_vDoFyJvb0htFIjQz0IfyJBiOcck2skus,3031
277
277
  django_ledger/templates/django_ledger/financial_statements/income_statement.html,sha256=pfrv12Bu_PmU-MrL7JXYX7Wv4PZ06fKvOdydzzgeEnw,2731
278
- django_ledger/templates/django_ledger/financial_statements/tags/balance_sheet_statement.html,sha256=76H_MfmbT2If1ycH4k6Zzn_OxpbgmdCOVUqs6unBNys,6431
278
+ django_ledger/templates/django_ledger/financial_statements/tags/balance_sheet_statement.html,sha256=u2o3krlo_I7w-erXI9DO4gNChbYn0KpdeLRZs7UckOQ,6430
279
279
  django_ledger/templates/django_ledger/financial_statements/tags/cash_flow_statement.html,sha256=elJsMVmVJHZbZVhuo-bSykrrLoSZrN0JpUYm0LukY80,8961
280
280
  django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html,sha256=kLmnxHN5G9H7xYKFANLbfM0jAtNsmfhIrdltW-bhoPY,10442
281
281
  django_ledger/templates/django_ledger/includes/breadcrumbs.html,sha256=mSzAPpn7uCx33oXuNhbM-MQdam3QFOxl9TRH93hrS4w,183
@@ -353,7 +353,7 @@ django_ledger/templates/django_ledger/vendor/vendor_update.html,sha256=4kBUlGgrg
353
353
  django_ledger/templates/django_ledger/vendor/includes/card_vendor.html,sha256=oCXyuqyF7CnJnDQdK0G0jdYLqtPWYSzwlv8oddyGJg8,1290
354
354
  django_ledger/templates/django_ledger/vendor/tags/vendor_table.html,sha256=YC-3T5x4oua3VBg1q690CRzoogKL8qFgQRp5jTKLFgk,3400
355
355
  django_ledger/templatetags/__init__.py,sha256=N7iaeMO5xTU-q7RXTVYUy-fu8nMZbiIJ9QEtDCjsTdI,205
356
- django_ledger/templatetags/django_ledger.py,sha256=9lIsihiSJeu7zhdmbgwEaMfQ3c735CYmOv2Rpy-ELno,31693
356
+ django_ledger/templatetags/django_ledger.py,sha256=2fzaHJVc3O9t0UuQICx7YAwAPzsP2lv4rOYFPiRAlfA,31676
357
357
  django_ledger/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
358
358
  django_ledger/tests/base.py,sha256=Be7BS_bc_m-hCTkBRnvHYfvAfgCcVOsU-He9ON6rOCc,10279
359
359
  django_ledger/tests/test_accounts.py,sha256=WznTiYkxGcmeZ0W75ATpMsZGWrtmNV4voe4oLMCpveo,717
@@ -401,7 +401,7 @@ django_ledger/views/coa.py,sha256=WnWQVz-4Ik9v28KHzD_WiKcgix7l6bBj1A60p4k-eos,49
401
401
  django_ledger/views/customer.py,sha256=RoBsXBxZC9b79DSNNHaoSZtQ2AoXf7DJAGmZEO3xdxs,3672
402
402
  django_ledger/views/data_import.py,sha256=_H8gjGRIE2Jm97ivvEQn0uEWrM3VvKkYQeXQ1GbKn3g,11950
403
403
  django_ledger/views/djl_api.py,sha256=6ADX9fBK8DroTeg8UIeCf2x4wt6-AF5xLlDQnqXBfsM,4411
404
- django_ledger/views/entity.py,sha256=egJoB4-HAyzKd_5tZ8gOh8nxMKA09_Ds2H7elGt5_DE,9457
404
+ django_ledger/views/entity.py,sha256=f6Fd5YsGbym5Jf3XvbhYCQVm4o5odNLrqVmch8vpGsg,9468
405
405
  django_ledger/views/estimate.py,sha256=ZFG0k2_nAV10EjO-p8yp7EVMa4x2qOcFSHl2xFpNDaM,12811
406
406
  django_ledger/views/feedback.py,sha256=qoIN44fJnblPx-pJFe5yYeO-dMqp-FReFZiyw0qQb_s,2460
407
407
  django_ledger/views/financial_statement.py,sha256=B4FE9qyBYs8tJvBJ1n9-7kR-pH2EJWn6SnjBdtbRfuE,7335
@@ -411,14 +411,14 @@ django_ledger/views/invoice.py,sha256=iUzTG-EbdYqNX-eYwHBnQRUD_1wTOGutw0BfDMKcI6
411
411
  django_ledger/views/item.py,sha256=FY53vk_giTRgvJ47FRqChQ8vyDYPDp4DGTvVhGAb36E,21347
412
412
  django_ledger/views/journal_entry.py,sha256=21kuiRBlhlkgv8xZKM4mj9djv0Fu0BhB80QOEOHCa-w,12135
413
413
  django_ledger/views/ledger.py,sha256=Yk6uDoYhJs5vf5JRqsy8n0nUNDEHk7NzjR1PglyqaAM,12647
414
- django_ledger/views/mixins.py,sha256=pXiEEen4rKrAluaROMAZC7nLR967LUV5fOiOAfq22tY,21966
414
+ django_ledger/views/mixins.py,sha256=SgsR9XWKgsJoQ2pCKkdHlNt93XiUa8bkTKTD0fjj8NI,23370
415
415
  django_ledger/views/purchase_order.py,sha256=1J3u4QnCkM7z1Y6DePijVdM67x4CQgfmQJcs3Y4kclU,21082
416
416
  django_ledger/views/transactions.py,sha256=5taQRGLSMkM_N8paQJ07HMspI_Nl7PawF8OohCiRmao,206
417
417
  django_ledger/views/unit.py,sha256=_RgPJO9mR6v5ohBXlnL3T8nTWgS1lwlCvERQcHk0wHE,10232
418
418
  django_ledger/views/vendor.py,sha256=gUdBPTFLeSwlNfdHSA1KFdE_y3QpwpkFhEB0r3-UYdI,3461
419
- django_ledger-0.6.0.2.dist-info/AUTHORS.md,sha256=SRM2cynD89ZfEsL09zrbUVeO17r9zE2ZM7y6ReMqVRo,713
420
- django_ledger-0.6.0.2.dist-info/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
421
- django_ledger-0.6.0.2.dist-info/METADATA,sha256=lx74R33LSCnxzSR4EcoICDKCz8vpi04rr1d31KbzoVg,9643
422
- django_ledger-0.6.0.2.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
423
- django_ledger-0.6.0.2.dist-info/top_level.txt,sha256=0U3SjF63ND36grQNWDONVe-T9-T07lFl5e6QkG7bR2E,44
424
- django_ledger-0.6.0.2.dist-info/RECORD,,
419
+ django_ledger-0.6.2.dist-info/AUTHORS.md,sha256=SRM2cynD89ZfEsL09zrbUVeO17r9zE2ZM7y6ReMqVRo,713
420
+ django_ledger-0.6.2.dist-info/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
421
+ django_ledger-0.6.2.dist-info/METADATA,sha256=hGmUnvHJ9byl1Du4AKDEwNxw5aWk1ibCATLKSjM2sDc,9641
422
+ django_ledger-0.6.2.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
423
+ django_ledger-0.6.2.dist-info/top_level.txt,sha256=0U3SjF63ND36grQNWDONVe-T9-T07lFl5e6QkG7bR2E,44
424
+ django_ledger-0.6.2.dist-info/RECORD,,