django-ledger 0.7.10__py3-none-any.whl → 0.8.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.

Files changed (115) hide show
  1. django_ledger/__init__.py +1 -1
  2. django_ledger/context.py +12 -0
  3. django_ledger/forms/bill.py +0 -4
  4. django_ledger/forms/closing_entry.py +13 -1
  5. django_ledger/forms/data_import.py +1 -1
  6. django_ledger/forms/estimate.py +3 -6
  7. django_ledger/forms/invoice.py +3 -7
  8. django_ledger/forms/item.py +10 -18
  9. django_ledger/forms/purchase_order.py +2 -4
  10. django_ledger/io/io_core.py +25 -32
  11. django_ledger/io/io_generator.py +7 -6
  12. django_ledger/io/io_library.py +1 -2
  13. django_ledger/migrations/0024_billmodel_entity_model_invoicemodel_entity_model.py +24 -0
  14. django_ledger/migrations/0025_alter_billmodel_cash_account_and_more.py +70 -0
  15. django_ledger/models/accounts.py +109 -69
  16. django_ledger/models/bank_account.py +40 -23
  17. django_ledger/models/bill.py +89 -63
  18. django_ledger/models/chart_of_accounts.py +173 -105
  19. django_ledger/models/closing_entry.py +99 -48
  20. django_ledger/models/customer.py +60 -39
  21. django_ledger/models/data_import.py +55 -41
  22. django_ledger/models/deprecations.py +61 -0
  23. django_ledger/models/entity.py +18 -16
  24. django_ledger/models/estimate.py +57 -28
  25. django_ledger/models/invoice.py +58 -28
  26. django_ledger/models/items.py +503 -142
  27. django_ledger/models/journal_entry.py +61 -47
  28. django_ledger/models/ledger.py +106 -42
  29. django_ledger/models/mixins.py +16 -10
  30. django_ledger/models/purchase_order.py +39 -17
  31. django_ledger/models/transactions.py +152 -113
  32. django_ledger/models/unit.py +57 -30
  33. django_ledger/models/vendor.py +75 -43
  34. django_ledger/report/core.py +2 -14
  35. django_ledger/settings.py +56 -71
  36. django_ledger/static/django_ledger/bundle/djetler.bundle.js +1 -1
  37. django_ledger/static/django_ledger/bundle/djetler.bundle.js.LICENSE.txt +25 -0
  38. django_ledger/static/django_ledger/bundle/styles.bundle.js +1 -1
  39. django_ledger/static/django_ledger/css/djl_styles.css +273 -0
  40. django_ledger/templates/django_ledger/bills/includes/card_bill.html +2 -2
  41. django_ledger/templates/django_ledger/components/menu.html +41 -26
  42. django_ledger/templates/django_ledger/customer/tags/customer_table.html +5 -5
  43. django_ledger/templates/django_ledger/entity/includes/card_entity.html +12 -6
  44. django_ledger/templates/django_ledger/financial_statements/balance_sheet.html +1 -1
  45. django_ledger/templates/django_ledger/financial_statements/cash_flow.html +4 -1
  46. django_ledger/templates/django_ledger/financial_statements/income_statement.html +4 -1
  47. django_ledger/templates/django_ledger/financial_statements/tags/balance_sheet_statement.html +27 -3
  48. django_ledger/templates/django_ledger/financial_statements/tags/cash_flow_statement.html +16 -4
  49. django_ledger/templates/django_ledger/financial_statements/tags/income_statement.html +73 -18
  50. django_ledger/templates/django_ledger/includes/widget_ratios.html +18 -24
  51. django_ledger/templates/django_ledger/invoice/includes/card_invoice.html +3 -3
  52. django_ledger/templates/django_ledger/layouts/base.html +6 -1
  53. django_ledger/templates/django_ledger/vendor/tags/vendor_table.html +9 -5
  54. django_ledger/tests/test_accounts.py +1 -2
  55. django_ledger/tests/test_io.py +17 -0
  56. django_ledger/tests/test_purchase_order.py +3 -3
  57. django_ledger/tests/test_transactions.py +1 -2
  58. django_ledger/urls/__init__.py +0 -4
  59. django_ledger/views/bill.py +8 -13
  60. django_ledger/views/chart_of_accounts.py +6 -4
  61. django_ledger/views/closing_entry.py +11 -7
  62. django_ledger/views/customer.py +13 -17
  63. django_ledger/views/data_import.py +7 -6
  64. django_ledger/views/djl_api.py +3 -5
  65. django_ledger/views/entity.py +2 -4
  66. django_ledger/views/estimate.py +3 -7
  67. django_ledger/views/inventory.py +3 -5
  68. django_ledger/views/invoice.py +4 -6
  69. django_ledger/views/item.py +7 -11
  70. django_ledger/views/journal_entry.py +1 -2
  71. django_ledger/views/mixins.py +25 -19
  72. django_ledger/views/purchase_order.py +24 -35
  73. django_ledger/views/unit.py +1 -2
  74. django_ledger/views/vendor.py +1 -2
  75. {django_ledger-0.7.10.dist-info → django_ledger-0.8.0.dist-info}/METADATA +43 -75
  76. {django_ledger-0.7.10.dist-info → django_ledger-0.8.0.dist-info}/RECORD +80 -108
  77. {django_ledger-0.7.10.dist-info → django_ledger-0.8.0.dist-info}/WHEEL +1 -1
  78. django_ledger-0.8.0.dist-info/top_level.txt +1 -0
  79. django_ledger/contrib/django_ledger_graphene/__init__.py +0 -0
  80. django_ledger/contrib/django_ledger_graphene/accounts/schema.py +0 -33
  81. django_ledger/contrib/django_ledger_graphene/api.py +0 -42
  82. django_ledger/contrib/django_ledger_graphene/apps.py +0 -6
  83. django_ledger/contrib/django_ledger_graphene/auth/mutations.py +0 -49
  84. django_ledger/contrib/django_ledger_graphene/auth/schema.py +0 -6
  85. django_ledger/contrib/django_ledger_graphene/bank_account/mutations.py +0 -61
  86. django_ledger/contrib/django_ledger_graphene/bank_account/schema.py +0 -34
  87. django_ledger/contrib/django_ledger_graphene/bill/mutations.py +0 -0
  88. django_ledger/contrib/django_ledger_graphene/bill/schema.py +0 -34
  89. django_ledger/contrib/django_ledger_graphene/coa/mutations.py +0 -0
  90. django_ledger/contrib/django_ledger_graphene/coa/schema.py +0 -30
  91. django_ledger/contrib/django_ledger_graphene/customers/__init__.py +0 -0
  92. django_ledger/contrib/django_ledger_graphene/customers/mutations.py +0 -71
  93. django_ledger/contrib/django_ledger_graphene/customers/schema.py +0 -43
  94. django_ledger/contrib/django_ledger_graphene/data_import/mutations.py +0 -0
  95. django_ledger/contrib/django_ledger_graphene/data_import/schema.py +0 -0
  96. django_ledger/contrib/django_ledger_graphene/entity/mutations.py +0 -0
  97. django_ledger/contrib/django_ledger_graphene/entity/schema.py +0 -94
  98. django_ledger/contrib/django_ledger_graphene/item/mutations.py +0 -0
  99. django_ledger/contrib/django_ledger_graphene/item/schema.py +0 -31
  100. django_ledger/contrib/django_ledger_graphene/journal_entry/mutations.py +0 -0
  101. django_ledger/contrib/django_ledger_graphene/journal_entry/schema.py +0 -35
  102. django_ledger/contrib/django_ledger_graphene/ledger/mutations.py +0 -0
  103. django_ledger/contrib/django_ledger_graphene/ledger/schema.py +0 -32
  104. django_ledger/contrib/django_ledger_graphene/purchase_order/mutations.py +0 -0
  105. django_ledger/contrib/django_ledger_graphene/purchase_order/schema.py +0 -31
  106. django_ledger/contrib/django_ledger_graphene/transaction/mutations.py +0 -0
  107. django_ledger/contrib/django_ledger_graphene/transaction/schema.py +0 -36
  108. django_ledger/contrib/django_ledger_graphene/unit/mutations.py +0 -0
  109. django_ledger/contrib/django_ledger_graphene/unit/schema.py +0 -27
  110. django_ledger/contrib/django_ledger_graphene/vendor/mutations.py +0 -0
  111. django_ledger/contrib/django_ledger_graphene/vendor/schema.py +0 -37
  112. django_ledger/contrib/django_ledger_graphene/views.py +0 -12
  113. django_ledger-0.7.10.dist-info/top_level.txt +0 -4
  114. {django_ledger-0.7.10.dist-info → django_ledger-0.8.0.dist-info/licenses}/AUTHORS.md +0 -0
  115. {django_ledger-0.7.10.dist-info → django_ledger-0.8.0.dist-info/licenses}/LICENSE +0 -0
django_ledger/__init__.py CHANGED
@@ -6,7 +6,7 @@ Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
6
6
  default_app_config = 'django_ledger.apps.DjangoLedgerConfig'
7
7
 
8
8
  """Django Ledger"""
9
- __version__ = '0.7.10'
9
+ __version__ = '0.8.0'
10
10
  __license__ = 'GPLv3 License'
11
11
 
12
12
  __author__ = 'Miguel Sanda'
@@ -0,0 +1,12 @@
1
+ from django.conf import settings
2
+
3
+ from django_ledger import __version__
4
+ from django_ledger.settings import DJANGO_LEDGER_THEME
5
+
6
+
7
+ def django_ledger_context(request):
8
+ return {
9
+ 'DEBUG': settings.DEBUG,
10
+ 'VERSION': __version__,
11
+ 'DJANGO_LEDGER_THEME': DJANGO_LEDGER_THEME,
12
+ }
@@ -214,10 +214,6 @@ class BillModelConfigureForm(BaseBillModelUpdateForm):
214
214
 
215
215
  class BillItemTransactionForm(ModelForm):
216
216
 
217
- # def __init__(self, entity_unit_qs, *args, **kwargs):
218
- # super().__init__(self, *args, **kwargs)
219
- # self.fields['entity_unit'].queryset = entity_unit_qs
220
-
221
217
  def clean(self):
222
218
  cleaned_data = super(BillItemTransactionForm, self).clean()
223
219
  itemtxs_model: ItemTransactionModel = self.instance
@@ -1,15 +1,25 @@
1
- from django.forms import DateInput, ValidationError, ModelForm, Textarea
1
+ from django.forms import DateInput, ValidationError, ModelForm, Textarea, HiddenInput
2
2
  from django.utils.translation import gettext_lazy as _
3
3
 
4
4
  from django_ledger.io.io_core import get_localdate
5
5
  from django_ledger.models.closing_entry import ClosingEntryModel
6
+ from django_ledger.models.entity import EntityModel
6
7
  from django_ledger.settings import DJANGO_LEDGER_FORM_INPUT_CLASSES
7
8
 
8
9
 
9
10
  class ClosingEntryCreateForm(ModelForm):
10
11
 
12
+ def __init__(self, entity_model: EntityModel, *args, **kwargs):
13
+ super().__init__(*args, **kwargs)
14
+ self.ENTITY_MODEL: EntityModel = entity_model
15
+ self.fields['entity_model'].disabled = True
16
+
17
+ def clean_entity_model(self):
18
+ return self.ENTITY_MODEL
19
+
11
20
  def clean_closing_date(self):
12
21
  closing_date = self.cleaned_data['closing_date']
22
+
13
23
  if closing_date > get_localdate():
14
24
  raise ValidationError(
15
25
  message=_('Cannot create a closing entry with a future date.'), code='invalid_date'
@@ -19,10 +29,12 @@ class ClosingEntryCreateForm(ModelForm):
19
29
  class Meta:
20
30
  model = ClosingEntryModel
21
31
  fields = [
32
+ 'entity_model',
22
33
  'closing_date'
23
34
  ]
24
35
 
25
36
  widgets = {
37
+ 'entity_model': HiddenInput(),
26
38
  'closing_date': DateInput(attrs={
27
39
  'class': DJANGO_LEDGER_FORM_INPUT_CLASSES + ' is-large',
28
40
  'placeholder': _('Closing Date (YYYY-MM-DD)...'),
@@ -40,7 +40,7 @@ class ImportJobModelCreateForm(ModelForm):
40
40
  widgets = {
41
41
  'description': TextInput(attrs={
42
42
  'class': DJANGO_LEDGER_FORM_INPUT_CLASSES + ' is-large',
43
- 'placeholder': _('What\'s this import about?...')
43
+ 'placeholder': _('Name this import...')
44
44
  }),
45
45
  'bank_account_model': Select(
46
46
  attrs={
@@ -25,8 +25,7 @@ class EstimateModelCreateForm(forms.ModelForm):
25
25
 
26
26
  def get_customer_queryset(self):
27
27
  return CustomerModel.objects.for_entity(
28
- entity_slug=self.ENTITY_SLUG,
29
- user_model=self.USER_MODEL
28
+ entity_model=self.ENTITY_SLUG,
30
29
  ).active()
31
30
 
32
31
  class Meta:
@@ -116,13 +115,11 @@ class BaseEstimateItemModelFormset(BaseModelFormSet):
116
115
  self.ENTITY_SLUG = entity_slug
117
116
 
118
117
  items_qs = ItemModel.objects.for_estimate(
119
- entity_slug=self.ENTITY_SLUG,
120
- user_model=self.USER_MODEL
118
+ entity_model=self.ENTITY_SLUG
121
119
  )
122
120
 
123
121
  unit_qs = EntityUnitModel.objects.for_entity(
124
- entity_slug=self.ENTITY_SLUG,
125
- user_model=self.USER_MODEL
122
+ entity_model=self.ENTITY_SLUG
126
123
  )
127
124
 
128
125
  for form in self.forms:
@@ -29,8 +29,7 @@ class InvoiceModelCreateForEstimateForm(ModelForm):
29
29
  def get_customer_queryset(self):
30
30
  if 'customer' in self.fields:
31
31
  customer_qs = CustomerModel.objects.for_entity(
32
- user_model=self.USER_MODEL,
33
- entity_slug=self.ENTITY_SLUG
32
+ entity_model=self.ENTITY_SLUG
34
33
  ).active()
35
34
  self.fields['customer'].queryset = customer_qs
36
35
 
@@ -43,7 +42,6 @@ class InvoiceModelCreateForEstimateForm(ModelForm):
43
42
  ]):
44
43
 
45
44
  account_qs = AccountModel.objects.for_entity(
46
- user_model=self.USER_MODEL,
47
45
  entity_model=self.ENTITY_SLUG
48
46
  ).for_invoice()
49
47
 
@@ -237,8 +235,7 @@ class BaseInvoiceItemTransactionFormset(BaseModelFormSet):
237
235
  self.ENTITY_SLUG = entity_slug
238
236
 
239
237
  items_qs = ItemModel.objects.for_invoice(
240
- entity_slug=self.ENTITY_SLUG,
241
- user_model=self.USER_MODEL
238
+ entity_model=self.ENTITY_SLUG
242
239
  )
243
240
 
244
241
  for form in self.forms:
@@ -252,8 +249,7 @@ class BaseInvoiceItemTransactionFormset(BaseModelFormSet):
252
249
  def get_queryset(self):
253
250
  if not self.queryset:
254
251
  self.queryset = ItemTransactionModel.objects.for_invoice(
255
- entity_slug=self.ENTITY_SLUG,
256
- user_model=self.USER_MODEL,
252
+ entity_model=self.ENTITY_SLUG,
257
253
  invoice_pk=self.INVOICE_MODEL.uuid
258
254
  )
259
255
  else:
@@ -1,4 +1,4 @@
1
- from django.forms import ModelForm, TextInput, Select, ChoiceField
1
+ from django.forms import ModelForm, TextInput, Select
2
2
  from django.utils.translation import gettext_lazy as _
3
3
 
4
4
  from django_ledger.io.roles import GROUP_INCOME, ASSET_CA_INVENTORY, GROUP_EXPENSES, GROUP_COGS
@@ -48,7 +48,6 @@ class ProductCreateForm(ModelForm):
48
48
 
49
49
  accounts_qs = AccountModel.objects.for_entity(
50
50
  entity_model=self.ENTITY_SLUG,
51
- user_model=self.USER_MODEL
52
51
  ).with_roles(
53
52
  roles=self.PRODUCT_OR_SERVICE_ROLES
54
53
  ).active()
@@ -62,8 +61,7 @@ class ProductCreateForm(ModelForm):
62
61
 
63
62
  if 'uom' in self.fields:
64
63
  uom_qs = UnitOfMeasureModel.objects.for_entity_active(
65
- entity_slug=self.ENTITY_SLUG,
66
- user_model=self.USER_MODEL
64
+ entity_model=self.ENTITY_SLUG
67
65
  )
68
66
  self.fields['uom'].queryset = uom_qs
69
67
 
@@ -142,8 +140,7 @@ class ServiceCreateForm(ModelForm):
142
140
  super().__init__(*args, **kwargs)
143
141
 
144
142
  accounts_qs = AccountModel.objects.for_entity(
145
- entity_model=self.ENTITY_SLUG,
146
- user_model=self.USER_MODEL
143
+ entity_model=self.ENTITY_SLUG
147
144
  ).with_roles(
148
145
  roles=self.SERVICE_ROLES,
149
146
  ).active()
@@ -156,8 +153,7 @@ class ServiceCreateForm(ModelForm):
156
153
 
157
154
  if 'uom' in self.fields:
158
155
  uom_qs = UnitOfMeasureModel.objects.for_entity_active(
159
- entity_slug=self.ENTITY_SLUG,
160
- user_model=self.USER_MODEL
156
+ entity_model=self.ENTITY_SLUG,
161
157
  )
162
158
  self.fields['uom'].queryset = uom_qs
163
159
 
@@ -229,8 +225,7 @@ class ExpenseItemCreateForm(ModelForm):
229
225
  super().__init__(*args, **kwargs)
230
226
 
231
227
  accounts_qs = AccountModel.objects.for_entity(
232
- entity_model=self.ENTITY_SLUG,
233
- user_model=self.USER_MODEL
228
+ entity_model=self.ENTITY_SLUG
234
229
  ).with_roles(
235
230
  roles=GROUP_EXPENSES
236
231
  ).active()
@@ -239,9 +234,8 @@ class ExpenseItemCreateForm(ModelForm):
239
234
 
240
235
  if 'uom' in self.fields:
241
236
  uom_qs = UnitOfMeasureModel.objects.for_entity(
242
- entity_slug=self.ENTITY_SLUG,
243
- user_model=self.USER_MODEL
244
- )
237
+ entity_model=self.ENTITY_SLUG
238
+ ).for_user(user_model=self.USER_MODEL)
245
239
  self.fields['uom'].queryset = uom_qs
246
240
 
247
241
  class Meta:
@@ -313,18 +307,16 @@ class InventoryItemCreateForm(ModelForm):
313
307
  self.USER_MODEL = user_model
314
308
  super().__init__(*args, **kwargs)
315
309
 
316
- accounts_qs = AccountModel.objects.for_entity(
310
+ inventory_account_qs = AccountModel.objects.for_entity(
317
311
  entity_model=self.ENTITY_SLUG,
318
- user_model=self.USER_MODEL
319
312
  ).with_roles(
320
313
  roles=[ASSET_CA_INVENTORY]
321
314
  ).active()
322
- self.fields['inventory_account'].queryset = accounts_qs
315
+ self.fields['inventory_account'].queryset = inventory_account_qs
323
316
 
324
317
  if 'uom' in self.fields:
325
318
  uom_qs = UnitOfMeasureModel.objects.for_entity_active(
326
- entity_slug=self.ENTITY_SLUG,
327
- user_model=self.USER_MODEL
319
+ entity_model=self.ENTITY_SLUG,
328
320
  )
329
321
  self.fields['uom'].queryset = uom_qs
330
322
 
@@ -155,13 +155,11 @@ class BasePurchaseOrderItemFormset(BaseModelFormSet):
155
155
  self.PO_MODEL = po_model
156
156
 
157
157
  items_qs = ItemModel.objects.for_po(
158
- entity_slug=self.ENTITY_SLUG,
159
- user_model=self.USER_MODEL
158
+ entity_model=self.ENTITY_SLUG,
160
159
  )
161
160
 
162
161
  unit_qs = EntityUnitModel.objects.for_entity(
163
- entity_slug=self.ENTITY_SLUG,
164
- user_model=self.USER_MODEL
162
+ entity_model=self.ENTITY_SLUG
165
163
  )
166
164
 
167
165
  for form in self.forms:
@@ -120,7 +120,6 @@ from django_ledger.io.io_middleware import (
120
120
  )
121
121
  from django_ledger.io.ratios import FinancialRatioManager
122
122
  from django_ledger.models.utils import lazy_loader
123
- from django_ledger.settings import DJANGO_LEDGER_PDF_SUPPORT_ENABLED
124
123
 
125
124
  UserModel = get_user_model()
126
125
 
@@ -224,18 +223,29 @@ def check_tx_balance(tx_data: list, perform_correction: bool = False) -> bool:
224
223
 
225
224
  while not is_valid:
226
225
  tx_type_choice = choice([DEBIT, CREDIT])
227
- txs_candidates = list(tx for tx in tx_data if tx['tx_type'] == tx_type_choice)
226
+
227
+ if IS_TX_MODEL:
228
+ txs_candidates = list(tx for tx in tx_data if tx.tx_type == tx_type_choice)
229
+ else:
230
+ txs_candidates = list(tx for tx in tx_data if tx['tx_type'] == tx_type_choice)
231
+
228
232
  if len(txs_candidates) > 0:
229
- tx = choice(list(tx for tx in tx_data if tx['tx_type'] == tx_type_choice))
230
- if any([diff > 0 and tx_type_choice == DEBIT,
231
- diff < 0 and tx_type_choice == CREDIT]):
233
+
234
+ tx = choice(txs_candidates)
235
+
236
+ if any([
237
+ diff > 0 and tx_type_choice == DEBIT,
238
+ diff < 0 and tx_type_choice == CREDIT
239
+ ]):
232
240
  if IS_TX_MODEL:
233
241
  tx.amount += settings.DJANGO_LEDGER_TRANSACTION_CORRECTION
234
242
  else:
235
243
  tx['amount'] += settings.DJANGO_LEDGER_TRANSACTION_CORRECTION
236
244
 
237
- elif any([diff < 0 and tx_type_choice == DEBIT,
238
- diff > 0 and tx_type_choice == CREDIT]):
245
+ elif any([
246
+ diff < 0 and tx_type_choice == DEBIT,
247
+ diff > 0 and tx_type_choice == CREDIT
248
+ ]):
239
249
  if IS_TX_MODEL:
240
250
  tx.amount -= settings.DJANGO_LEDGER_TRANSACTION_CORRECTION
241
251
  else:
@@ -719,14 +729,12 @@ class IODatabaseMixIn:
719
729
  if unit_slug:
720
730
 
721
731
  txs_queryset_init = TransactionModel.objects.for_entity(
722
- user_model=user_model,
723
- entity_slug=entity_slug or self.slug
732
+ entity_model=entity_slug or self.slug
724
733
  ).for_unit(unit_slug=unit_slug)
725
734
 
726
735
  else:
727
736
  txs_queryset_init = TransactionModel.objects.for_entity(
728
- user_model=user_model,
729
- entity_slug=self
737
+ entity_model=self
730
738
  )
731
739
  elif self.is_entity_unit_model():
732
740
  if not entity_slug:
@@ -734,8 +742,7 @@ class IODatabaseMixIn:
734
742
  'Calling digest from Entity Unit requires entity_slug explicitly for safety')
735
743
 
736
744
  txs_queryset_init = TransactionModel.objects.for_entity(
737
- user_model=user_model,
738
- entity_slug=entity_slug,
745
+ entity_model=entity_slug
739
746
  ).for_unit(unit_slug=unit_slug or self)
740
747
 
741
748
  elif self.is_ledger_model():
@@ -744,8 +751,7 @@ class IODatabaseMixIn:
744
751
  'Calling digest from Ledger Model requires entity_slug explicitly for safety')
745
752
 
746
753
  txs_queryset_init = TransactionModel.objects.for_entity(
747
- entity_slug=entity_slug,
748
- user_model=user_model,
754
+ entity_model=entity_slug
749
755
  ).for_ledger(ledger_model=self)
750
756
 
751
757
  else:
@@ -889,6 +895,10 @@ class IODatabaseMixIn:
889
895
  'tx_type',
890
896
  ]
891
897
 
898
+ if kwargs.get('for_test'):
899
+ VALUES.append('journal_entry__ledger_id')
900
+ VALUES.append('journal_entry__ledger__entity_id')
901
+
892
902
  ANNOTATE = {'balance': Sum('amount')}
893
903
  if io_result.is_bounded:
894
904
  ANNOTATE = {'balance': Sum('amount_io')}
@@ -1587,10 +1597,6 @@ class IOReportMixIn:
1587
1597
  memory or in saved PDF format. If the `save_pdf` option is enabled, the PDF
1588
1598
  report is saved at the specified location.
1589
1599
  """
1590
- if not DJANGO_LEDGER_PDF_SUPPORT_ENABLED:
1591
- raise IOValidationError(
1592
- message=_('PDF support not enabled. Install PDF support from Pipfile.')
1593
- )
1594
1600
 
1595
1601
  io_digest = self.digest_balance_sheet(
1596
1602
  to_date=to_date,
@@ -1716,10 +1722,6 @@ class IOReportMixIn:
1716
1722
  generated income statement report. If `save_pdf` is True, the report will also
1717
1723
  be saved as a PDF file at the specified location.
1718
1724
  """
1719
- if not DJANGO_LEDGER_PDF_SUPPORT_ENABLED:
1720
- raise IOValidationError(
1721
- message=_('PDF support not enabled. Install PDF support from Pipfile.')
1722
- )
1723
1725
 
1724
1726
  io_digest = self.digest_income_statement(
1725
1727
  from_date=from_date,
@@ -1833,10 +1835,6 @@ class IOReportMixIn:
1833
1835
  IOValidationError
1834
1836
  If PDF support is not enabled in the system's Django ledger configuration.
1835
1837
  """
1836
- if not DJANGO_LEDGER_PDF_SUPPORT_ENABLED:
1837
- raise IOValidationError(
1838
- message=_('PDF support not enabled. Install PDF support from Pipfile.')
1839
- )
1840
1838
 
1841
1839
  io_digest = self.digest_cash_flow_statement(
1842
1840
  from_date=from_date,
@@ -1957,11 +1955,6 @@ class IOReportMixIn:
1957
1955
  IOValidationError
1958
1956
  Raised if PDF support is not enabled in the application configuration.
1959
1957
  """
1960
- if not DJANGO_LEDGER_PDF_SUPPORT_ENABLED:
1961
- raise IOValidationError(
1962
- message=_('PDF support not enabled. Install PDF support from Pipfile.')
1963
- )
1964
-
1965
1958
  io_digest = self.digest_financial_statements(
1966
1959
  from_date=from_date,
1967
1960
  to_date=to_date,
@@ -138,8 +138,7 @@ class EntityDataGenerator(LoggingMixIn):
138
138
 
139
139
  self.logger.info('Checking for existing transactions...')
140
140
  txs_qs = TransactionModel.objects.for_entity(
141
- entity_slug=self.entity_model,
142
- user_model=self.user_model
141
+ entity_model=self.entity_model
143
142
  )
144
143
 
145
144
  if txs_qs.count() > 0 and not force_populate:
@@ -546,10 +545,12 @@ class EntityDataGenerator(LoggingMixIn):
546
545
 
547
546
  if random() > 0.50:
548
547
  date_approved = self.get_next_timestamp(date_in_review)
549
- bill_model.mark_as_approved(commit=True,
550
- entity_slug=self.entity_model.slug,
551
- user_model=self.user_model,
552
- date_approved=date_approved)
548
+ bill_model.mark_as_approved(
549
+ commit=True,
550
+ entity_slug=self.entity_model.slug,
551
+ user_model=self.user_model,
552
+ date_approved=date_approved
553
+ )
553
554
 
554
555
  if random() > 0.25:
555
556
  paid_date = self.get_next_timestamp(date_approved)
@@ -116,8 +116,7 @@ class IOCursor:
116
116
  LedgerModelQuerySet
117
117
  """
118
118
  return LedgerModel.objects.for_entity(
119
- self.ENTITY_MODEL,
120
- self.USER_MODEL
119
+ entity_model=self.ENTITY_MODEL
121
120
  )
122
121
 
123
122
  def get_account_model_qs(self) -> AccountModelQuerySet:
@@ -0,0 +1,24 @@
1
+ # Generated by Django 5.2.1 on 2025-08-26 12:40
2
+
3
+ import django.db.models.deletion
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('django_ledger', '0023_customermodel_customer_code_customermodel_picture_and_more'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddField(
15
+ model_name='billmodel',
16
+ name='entity_model',
17
+ field=models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, to='django_ledger.entitymodel'),
18
+ ),
19
+ migrations.AddField(
20
+ model_name='invoicemodel',
21
+ name='entity_model',
22
+ field=models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, to='django_ledger.entitymodel'),
23
+ ),
24
+ ]
@@ -0,0 +1,70 @@
1
+ # Generated by Django 5.2.6 on 2025-09-08 21:32
2
+
3
+ import django.db.models.deletion
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+ dependencies = [
9
+ ('django_ledger', '0024_billmodel_entity_model_invoicemodel_entity_model'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name='billmodel',
15
+ name='cash_account',
16
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT,
17
+ related_name='bill_cash_account', to='django_ledger.accountmodel',
18
+ verbose_name='Cash Account'),
19
+ ),
20
+ migrations.AlterField(
21
+ model_name='billmodel',
22
+ name='prepaid_account',
23
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT,
24
+ related_name='bill_prepaid_account', to='django_ledger.accountmodel',
25
+ verbose_name='Prepaid Account'),
26
+ ),
27
+ migrations.AlterField(
28
+ model_name='billmodel',
29
+ name='unearned_account',
30
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT,
31
+ related_name='bill_unearned_account', to='django_ledger.accountmodel',
32
+ verbose_name='Unearned Account'),
33
+ ),
34
+ migrations.AlterField(
35
+ model_name='customermodel',
36
+ name='address_1',
37
+ field=models.CharField(blank=True, max_length=70, null=True, verbose_name='Address Line 1'),
38
+ ),
39
+ migrations.AlterField(
40
+ model_name='entitymodel',
41
+ name='address_1',
42
+ field=models.CharField(blank=True, max_length=70, null=True, verbose_name='Address Line 1'),
43
+ ),
44
+ migrations.AlterField(
45
+ model_name='invoicemodel',
46
+ name='cash_account',
47
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT,
48
+ related_name='invoice_cash_account', to='django_ledger.accountmodel',
49
+ verbose_name='Cash Account'),
50
+ ),
51
+ migrations.AlterField(
52
+ model_name='invoicemodel',
53
+ name='prepaid_account',
54
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT,
55
+ related_name='invoice_prepaid_account', to='django_ledger.accountmodel',
56
+ verbose_name='Prepaid Account'),
57
+ ),
58
+ migrations.AlterField(
59
+ model_name='invoicemodel',
60
+ name='unearned_account',
61
+ field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT,
62
+ related_name='invoice_unearned_account', to='django_ledger.accountmodel',
63
+ verbose_name='Unearned Account'),
64
+ ),
65
+ migrations.AlterField(
66
+ model_name='vendormodel',
67
+ name='address_1',
68
+ field=models.CharField(blank=True, max_length=70, null=True, verbose_name='Address Line 1'),
69
+ ),
70
+ ]