django-ledger 0.6.4__py3-none-any.whl → 0.7.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 (93) hide show
  1. django_ledger/__init__.py +1 -4
  2. django_ledger/admin/__init__.py +1 -1
  3. django_ledger/admin/{coa.py → chart_of_accounts.py} +1 -1
  4. django_ledger/admin/entity.py +1 -1
  5. django_ledger/contrib/django_ledger_graphene/accounts/schema.py +1 -1
  6. django_ledger/forms/account.py +43 -38
  7. django_ledger/forms/bank_account.py +5 -2
  8. django_ledger/forms/bill.py +24 -36
  9. django_ledger/forms/chart_of_accounts.py +82 -0
  10. django_ledger/forms/customer.py +1 -1
  11. django_ledger/forms/data_import.py +3 -3
  12. django_ledger/forms/estimate.py +1 -1
  13. django_ledger/forms/invoice.py +5 -7
  14. django_ledger/forms/item.py +24 -15
  15. django_ledger/forms/transactions.py +3 -3
  16. django_ledger/io/io_core.py +4 -2
  17. django_ledger/io/io_library.py +1 -1
  18. django_ledger/io/io_middleware.py +5 -0
  19. django_ledger/migrations/0017_alter_accountmodel_unique_together_and_more.py +31 -0
  20. django_ledger/migrations/0018_transactionmodel_cleared_transactionmodel_reconciled_and_more.py +37 -0
  21. django_ledger/models/__init__.py +1 -1
  22. django_ledger/models/accounts.py +229 -265
  23. django_ledger/models/bank_account.py +6 -6
  24. django_ledger/models/bill.py +7 -6
  25. django_ledger/models/{coa.py → chart_of_accounts.py} +187 -72
  26. django_ledger/models/closing_entry.py +5 -10
  27. django_ledger/models/coa_default.py +10 -9
  28. django_ledger/models/customer.py +6 -6
  29. django_ledger/models/data_import.py +12 -8
  30. django_ledger/models/entity.py +96 -39
  31. django_ledger/models/estimate.py +6 -10
  32. django_ledger/models/invoice.py +14 -11
  33. django_ledger/models/items.py +23 -14
  34. django_ledger/models/journal_entry.py +73 -30
  35. django_ledger/models/ledger.py +8 -8
  36. django_ledger/models/mixins.py +0 -3
  37. django_ledger/models/purchase_order.py +9 -9
  38. django_ledger/models/signals.py +0 -3
  39. django_ledger/models/transactions.py +24 -7
  40. django_ledger/models/unit.py +4 -3
  41. django_ledger/models/utils.py +0 -3
  42. django_ledger/models/vendor.py +4 -3
  43. django_ledger/settings.py +28 -3
  44. django_ledger/templates/django_ledger/account/account_create.html +2 -2
  45. django_ledger/templates/django_ledger/account/account_update.html +1 -1
  46. django_ledger/templates/django_ledger/account/tags/account_txs_table.html +1 -0
  47. django_ledger/templates/django_ledger/account/tags/accounts_table.html +29 -19
  48. django_ledger/templates/django_ledger/bills/bill_detail.html +3 -3
  49. django_ledger/templates/django_ledger/chart_of_accounts/coa_create.html +25 -0
  50. django_ledger/templates/django_ledger/chart_of_accounts/coa_list.html +25 -6
  51. django_ledger/templates/django_ledger/chart_of_accounts/coa_update.html +2 -2
  52. django_ledger/templates/django_ledger/chart_of_accounts/includes/coa_card.html +10 -4
  53. django_ledger/templates/django_ledger/expense/tags/expense_item_table.html +7 -0
  54. django_ledger/templates/django_ledger/financial_statements/tags/balance_sheet_statement.html +2 -2
  55. django_ledger/templates/django_ledger/includes/footer.html +2 -2
  56. django_ledger/templates/django_ledger/invoice/invoice_detail.html +3 -3
  57. django_ledger/templatetags/django_ledger.py +7 -1
  58. django_ledger/tests/base.py +23 -7
  59. django_ledger/tests/test_accounts.py +145 -9
  60. django_ledger/urls/account.py +17 -24
  61. django_ledger/urls/chart_of_accounts.py +6 -0
  62. django_ledger/utils.py +9 -36
  63. django_ledger/views/__init__.py +2 -2
  64. django_ledger/views/account.py +91 -116
  65. django_ledger/views/auth.py +1 -1
  66. django_ledger/views/bank_account.py +9 -11
  67. django_ledger/views/bill.py +91 -80
  68. django_ledger/views/{coa.py → chart_of_accounts.py} +49 -44
  69. django_ledger/views/closing_entry.py +8 -0
  70. django_ledger/views/customer.py +1 -1
  71. django_ledger/views/data_import.py +1 -1
  72. django_ledger/views/entity.py +1 -1
  73. django_ledger/views/estimate.py +13 -8
  74. django_ledger/views/feedback.py +1 -1
  75. django_ledger/views/financial_statement.py +1 -1
  76. django_ledger/views/home.py +1 -1
  77. django_ledger/views/inventory.py +9 -0
  78. django_ledger/views/invoice.py +5 -2
  79. django_ledger/views/item.py +58 -68
  80. django_ledger/views/journal_entry.py +1 -1
  81. django_ledger/views/ledger.py +3 -1
  82. django_ledger/views/mixins.py +25 -13
  83. django_ledger/views/purchase_order.py +1 -1
  84. django_ledger/views/transactions.py +1 -1
  85. django_ledger/views/unit.py +9 -0
  86. django_ledger/views/vendor.py +1 -1
  87. {django_ledger-0.6.4.dist-info → django_ledger-0.7.1.dist-info}/AUTHORS.md +8 -2
  88. {django_ledger-0.6.4.dist-info → django_ledger-0.7.1.dist-info}/METADATA +33 -44
  89. {django_ledger-0.6.4.dist-info → django_ledger-0.7.1.dist-info}/RECORD +92 -89
  90. {django_ledger-0.6.4.dist-info → django_ledger-0.7.1.dist-info}/WHEEL +1 -1
  91. django_ledger/forms/coa.py +0 -47
  92. {django_ledger-0.6.4.dist-info → django_ledger-0.7.1.dist-info}/LICENSE +0 -0
  93. {django_ledger-0.6.4.dist-info → django_ledger-0.7.1.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,11 @@
1
+ """
2
+ Django Ledger created by Miguel Sanda <msanda@arrobalytics.com>.
3
+ Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
4
+
5
+ Contributions to this module:
6
+ * Miguel Sanda <msanda@arrobalytics.com>
7
+ """
8
+
1
9
  from django.contrib.messages import add_message, ERROR
2
10
  from django.core.exceptions import ObjectDoesNotExist
3
11
  from django.db import IntegrityError
@@ -20,19 +28,17 @@ from django_ledger.views.mixins import DjangoLedgerSecurityMixIn
20
28
  # todo: Create delete views...
21
29
 
22
30
  # UNIT OF MEASURE VIEWS....
23
- class UnitOfMeasureModelModelViewQuerySetMixIn:
31
+ class UnitOfMeasureModelModelBaseView(DjangoLedgerSecurityMixIn):
24
32
  queryset = None
25
33
 
26
34
  def get_queryset(self):
27
35
  if self.queryset is None:
28
- self.queryset = UnitOfMeasureModel.objects.for_entity(
29
- entity_slug=self.kwargs['entity_slug'],
30
- user_model=self.request.user
31
- )
36
+ entity_model: EntityModel = self.get_authorized_entity_instance()
37
+ self.queryset = entity_model.unitofmeasuremodel_set.all()
32
38
  return super().get_queryset()
33
39
 
34
40
 
35
- class UnitOfMeasureModelListView(DjangoLedgerSecurityMixIn, UnitOfMeasureModelModelViewQuerySetMixIn, ListView):
41
+ class UnitOfMeasureModelListView(UnitOfMeasureModelModelBaseView, ListView):
36
42
  template_name = 'django_ledger/uom/uom_list.html'
37
43
  PAGE_TITLE = _('Unit of Measures')
38
44
  context_object_name = 'uom_list'
@@ -43,7 +49,7 @@ class UnitOfMeasureModelListView(DjangoLedgerSecurityMixIn, UnitOfMeasureModelMo
43
49
  }
44
50
 
45
51
 
46
- class UnitOfMeasureModelCreateView(DjangoLedgerSecurityMixIn, UnitOfMeasureModelModelViewQuerySetMixIn, CreateView):
52
+ class UnitOfMeasureModelCreateView(UnitOfMeasureModelModelBaseView, CreateView):
47
53
  template_name = 'django_ledger/uom/uom_create.html'
48
54
  PAGE_TITLE = _('Create Unit of Measure')
49
55
  extra_context = {
@@ -92,7 +98,7 @@ class UnitOfMeasureModelCreateView(DjangoLedgerSecurityMixIn, UnitOfMeasureModel
92
98
  return super().form_valid(form)
93
99
 
94
100
 
95
- class UnitOfMeasureModelUpdateView(DjangoLedgerSecurityMixIn, UnitOfMeasureModelModelViewQuerySetMixIn, UpdateView):
101
+ class UnitOfMeasureModelUpdateView(UnitOfMeasureModelModelBaseView, UpdateView):
96
102
  template_name = 'django_ledger/uom/uom_update.html'
97
103
  PAGE_TITLE = _('Update Unit of Measure')
98
104
  context_object_name = 'uom'
@@ -118,7 +124,7 @@ class UnitOfMeasureModelUpdateView(DjangoLedgerSecurityMixIn, UnitOfMeasureModel
118
124
  )
119
125
 
120
126
 
121
- class UnitOfMeasureModelDeleteView(DjangoLedgerSecurityMixIn, UnitOfMeasureModelModelViewQuerySetMixIn, DeleteView):
127
+ class UnitOfMeasureModelDeleteView(UnitOfMeasureModelModelBaseView, DeleteView):
122
128
  pk_url_kwarg = 'uom_pk'
123
129
  template_name = 'django_ledger/uom/uom_delete.html'
124
130
  context_object_name = 'uom_model'
@@ -150,23 +156,21 @@ class UnitOfMeasureModelDeleteView(DjangoLedgerSecurityMixIn, UnitOfMeasureModel
150
156
 
151
157
 
152
158
  # PRODUCTS VIEWS...
153
- class ProductItemModelModelViewQuerySetMixIn:
159
+ class ProductItemModelModelBaseView(DjangoLedgerSecurityMixIn):
154
160
  queryset = None
155
161
 
156
162
  def get_queryset(self):
157
163
  if not self.queryset:
158
- self.queryset = ItemModel.objects.for_entity(
159
- entity_slug=self.kwargs['entity_slug'],
160
- user_model=self.request.user
161
- ).products().select_related(
162
- 'earnings_account', 'cogs_account',
163
- 'inventory_account', 'uom').order_by('-updated')
164
+ entity_model: EntityModel = self.get_authorized_entity_instance()
165
+ self.queryset = entity_model.itemmodel_set.products().select_related(
166
+ 'earnings_account',
167
+ 'cogs_account',
168
+ 'inventory_account',
169
+ 'uom').order_by('-updated')
164
170
  return super().get_queryset()
165
171
 
166
172
 
167
- class ProductListView(DjangoLedgerSecurityMixIn,
168
- ProductItemModelModelViewQuerySetMixIn,
169
- ListView):
173
+ class ProductListView(ProductItemModelModelBaseView, ListView):
170
174
  template_name = 'django_ledger/product/product_list.html'
171
175
  PAGE_TITLE = _('Products')
172
176
  context_object_name = 'product_list'
@@ -177,9 +181,7 @@ class ProductListView(DjangoLedgerSecurityMixIn,
177
181
  }
178
182
 
179
183
 
180
- class ProductCreateView(DjangoLedgerSecurityMixIn,
181
- ProductItemModelModelViewQuerySetMixIn,
182
- CreateView):
184
+ class ProductCreateView(ProductItemModelModelBaseView, CreateView):
183
185
  template_name = 'django_ledger/product/product_create.html'
184
186
  model = ItemModel
185
187
  PAGE_TITLE = _('Create New Product')
@@ -212,9 +214,7 @@ class ProductCreateView(DjangoLedgerSecurityMixIn,
212
214
  return super().form_valid(form=form)
213
215
 
214
216
 
215
- class ProductUpdateView(DjangoLedgerSecurityMixIn,
216
- ProductItemModelModelViewQuerySetMixIn,
217
- UpdateView):
217
+ class ProductUpdateView(ProductItemModelModelBaseView, UpdateView):
218
218
  template_name = 'django_ledger/product/product_update.html'
219
219
  PAGE_TITLE = _('Update Product')
220
220
  context_object_name = 'item'
@@ -226,10 +226,10 @@ class ProductUpdateView(DjangoLedgerSecurityMixIn,
226
226
  }
227
227
 
228
228
  def get_queryset(self):
229
- return ItemModel.objects.products(
230
- entity_slug=self.kwargs['entity_slug'],
229
+ return ItemModel.objects.for_entity(
230
+ entity_slug=self.AUTHORIZED_ENTITY_MODEL,
231
231
  user_model=self.request.user
232
- )
232
+ ).products()
233
233
 
234
234
  def get_form(self, form_class=None):
235
235
  return ProductUpdateForm(
@@ -245,9 +245,7 @@ class ProductUpdateView(DjangoLedgerSecurityMixIn,
245
245
  })
246
246
 
247
247
 
248
- class ProductDeleteView(DjangoLedgerSecurityMixIn,
249
- ProductItemModelModelViewQuerySetMixIn,
250
- DeleteView):
248
+ class ProductDeleteView(ProductItemModelModelBaseView, DeleteView):
251
249
  template_name = 'django_ledger/product/product_delete.html'
252
250
  pk_url_kwarg = 'item_pk'
253
251
  context_object_name = 'item_model'
@@ -280,23 +278,21 @@ class ProductDeleteView(DjangoLedgerSecurityMixIn,
280
278
 
281
279
 
282
280
  # SERVICES VIEWS...
283
- class ServiceItemModelModelViewQuerySetMixIn:
281
+ class ServiceItemModelModelBaseView(DjangoLedgerSecurityMixIn):
284
282
  queryset = None
285
283
 
286
284
  def get_queryset(self):
287
285
  if not self.queryset:
288
- self.queryset = ItemModel.objects.for_entity(
289
- entity_slug=self.kwargs['entity_slug'],
290
- user_model=self.request.user
291
- ).services().select_related(
292
- 'earnings_account', 'cogs_account',
293
- 'inventory_account', 'uom').order_by('-updated')
286
+ entity_model: EntityModel = self.get_authorized_entity_instance()
287
+ self.queryset = entity_model.itemmodel_set.services().select_related(
288
+ 'earnings_account',
289
+ 'cogs_account',
290
+ 'inventory_account',
291
+ 'uom').order_by('-updated')
294
292
  return super().get_queryset()
295
293
 
296
294
 
297
- class ServiceListView(DjangoLedgerSecurityMixIn,
298
- ServiceItemModelModelViewQuerySetMixIn,
299
- ListView):
295
+ class ServiceListView(ServiceItemModelModelBaseView, ListView):
300
296
  template_name = 'django_ledger/service/service_list.html'
301
297
  PAGE_TITLE = _('Services')
302
298
  context_object_name = 'service_list'
@@ -307,9 +303,7 @@ class ServiceListView(DjangoLedgerSecurityMixIn,
307
303
  }
308
304
 
309
305
 
310
- class ServiceCreateView(DjangoLedgerSecurityMixIn,
311
- ServiceItemModelModelViewQuerySetMixIn,
312
- CreateView):
306
+ class ServiceCreateView(ServiceItemModelModelBaseView, CreateView):
313
307
  template_name = 'django_ledger/service/service_create.html'
314
308
  model = ItemModel
315
309
  PAGE_TITLE = _('Create New Service')
@@ -341,9 +335,7 @@ class ServiceCreateView(DjangoLedgerSecurityMixIn,
341
335
  return super().form_valid(form=form)
342
336
 
343
337
 
344
- class ServiceUpdateView(DjangoLedgerSecurityMixIn,
345
- ServiceItemModelModelViewQuerySetMixIn,
346
- UpdateView):
338
+ class ServiceUpdateView(ServiceItemModelModelBaseView, UpdateView):
347
339
  template_name = 'django_ledger/service/service_update.html'
348
340
  PAGE_TITLE = _('Update Service')
349
341
  context_object_name = 'item'
@@ -374,9 +366,7 @@ class ServiceUpdateView(DjangoLedgerSecurityMixIn,
374
366
  })
375
367
 
376
368
 
377
- class ServiceDeleteView(DjangoLedgerSecurityMixIn,
378
- ServiceItemModelModelViewQuerySetMixIn,
379
- DeleteView):
369
+ class ServiceDeleteView(ServiceItemModelModelBaseView, DeleteView):
380
370
  template_name = 'django_ledger/service/service_delete.html'
381
371
  pk_url_kwarg = 'item_pk'
382
372
  context_object_name = 'item_model'
@@ -409,20 +399,19 @@ class ServiceDeleteView(DjangoLedgerSecurityMixIn,
409
399
 
410
400
 
411
401
  # EXPENSE ITEMS VIEW...
412
-
413
- class ExpenseItemItemModelModelViewQuerySetMixIn:
402
+ class ExpenseItemItemModelModelBaseView(DjangoLedgerSecurityMixIn):
414
403
  queryset = None
415
404
 
416
405
  def get_queryset(self):
417
406
  if not self.queryset:
418
- self.queryset = ItemModel.objects.for_entity(
419
- entity_slug=self.kwargs['entity_slug'],
420
- user_model=self.request.user
421
- ).expenses().select_related('expense_account', 'uom').order_by('-updated')
407
+ entity_model: EntityModel = self.get_authorized_entity_instance()
408
+ self.queryset = entity_model.itemmodel_set.expenses().select_related(
409
+ 'expense_account',
410
+ 'uom').order_by('-updated')
422
411
  return super().get_queryset()
423
412
 
424
413
 
425
- class ExpenseItemModelListView(DjangoLedgerSecurityMixIn, ExpenseItemItemModelModelViewQuerySetMixIn, ListView):
414
+ class ExpenseItemModelListView(ExpenseItemItemModelModelBaseView, ListView):
426
415
  template_name = 'django_ledger/expense/expense_list.html'
427
416
  PAGE_TITLE = _('Expense Items')
428
417
  context_object_name = 'expense_list'
@@ -433,7 +422,7 @@ class ExpenseItemModelListView(DjangoLedgerSecurityMixIn, ExpenseItemItemModelMo
433
422
  }
434
423
 
435
424
 
436
- class ExpenseItemCreateView(DjangoLedgerSecurityMixIn, ExpenseItemItemModelModelViewQuerySetMixIn, CreateView):
425
+ class ExpenseItemCreateView(ExpenseItemItemModelModelBaseView, CreateView):
437
426
  template_name = 'django_ledger/expense/expense_create.html'
438
427
  model = ItemModel
439
428
  PAGE_TITLE = _('Create New Expense Item')
@@ -466,7 +455,7 @@ class ExpenseItemCreateView(DjangoLedgerSecurityMixIn, ExpenseItemItemModelModel
466
455
  return super().form_valid(form=form)
467
456
 
468
457
 
469
- class ExpenseItemUpdateView(DjangoLedgerSecurityMixIn, ExpenseItemItemModelModelViewQuerySetMixIn, UpdateView):
458
+ class ExpenseItemUpdateView(ExpenseItemItemModelModelBaseView, UpdateView):
470
459
  template_name = 'django_ledger/expense/expense_update.html'
471
460
  PAGE_TITLE = _('Update Expense Item')
472
461
  context_object_name = 'item'
@@ -493,20 +482,21 @@ class ExpenseItemUpdateView(DjangoLedgerSecurityMixIn, ExpenseItemItemModelModel
493
482
 
494
483
 
495
484
  # INVENTORY VIEWS...
496
-
497
- class InventoryItemItemModelModelViewQuerySetMixIn:
485
+ class InventoryItemItemModelModelBaseView(DjangoLedgerSecurityMixIn):
498
486
  queryset = None
499
487
 
500
488
  def get_queryset(self):
501
489
  if not self.queryset:
502
- self.queryset = ItemModel.objects.for_entity(
503
- entity_slug=self.kwargs['entity_slug'],
504
- user_model=self.request.user
505
- ).inventory_wip().select_related('inventory_account', 'cogs_account', 'uom').order_by('-updated')
490
+ entity_model: EntityModel = self.get_authorized_entity_instance()
491
+ self.queryset = entity_model.itemmodel_set.inventory_wip().select_related(
492
+ 'inventory_account',
493
+ 'cogs_account',
494
+ 'uom'
495
+ ).order_by('-updated')
506
496
  return super().get_queryset()
507
497
 
508
498
 
509
- class InventoryItemModelListView(DjangoLedgerSecurityMixIn, InventoryItemItemModelModelViewQuerySetMixIn, ListView):
499
+ class InventoryItemModelListView(InventoryItemItemModelModelBaseView, ListView):
510
500
  template_name = 'django_ledger/inventory/inventory_item_list.html'
511
501
  PAGE_TITLE = _('Inventory Items')
512
502
  context_object_name = 'inventory_item_list'
@@ -517,7 +507,7 @@ class InventoryItemModelListView(DjangoLedgerSecurityMixIn, InventoryItemItemMod
517
507
  }
518
508
 
519
509
 
520
- class InventoryItemCreateView(DjangoLedgerSecurityMixIn, InventoryItemItemModelModelViewQuerySetMixIn, CreateView):
510
+ class InventoryItemCreateView(InventoryItemItemModelModelBaseView, CreateView):
521
511
  template_name = 'django_ledger/inventory/inventory_item_create.html'
522
512
  model = ItemModel
523
513
  PAGE_TITLE = _('Create New Inventory Item')
@@ -554,7 +544,7 @@ class InventoryItemCreateView(DjangoLedgerSecurityMixIn, InventoryItemItemModelM
554
544
  return super().form_valid(form=form)
555
545
 
556
546
 
557
- class InventoryItemUpdateView(DjangoLedgerSecurityMixIn, InventoryItemItemModelModelViewQuerySetMixIn, UpdateView):
547
+ class InventoryItemUpdateView(InventoryItemItemModelModelBaseView, UpdateView):
558
548
  template_name = 'django_ledger/inventory/inventory_item_update.html'
559
549
  PAGE_TITLE = _('Update Inventory Item')
560
550
  context_object_name = 'item'
@@ -3,7 +3,7 @@ Django Ledger created by Miguel Sanda <msanda@arrobalytics.com>.
3
3
  Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
4
4
 
5
5
  Contributions to this module:
6
- Miguel Sanda <msanda@arrobalytics.com>
6
+ * Miguel Sanda <msanda@arrobalytics.com>
7
7
  """
8
8
  from django.contrib import messages
9
9
  from django.core.exceptions import ImproperlyConfigured, ValidationError
@@ -3,7 +3,7 @@ Django Ledger created by Miguel Sanda <msanda@arrobalytics.com>.
3
3
  Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
4
4
 
5
5
  Contributions to this module:
6
- Miguel Sanda <msanda@arrobalytics.com>
6
+ * Miguel Sanda <msanda@arrobalytics.com>
7
7
  """
8
8
  from django.contrib import messages
9
9
  from django.core.exceptions import ImproperlyConfigured, ValidationError
@@ -38,6 +38,7 @@ class LedgerModelModelViewQuerySetMixIn:
38
38
 
39
39
 
40
40
  class LedgerModelListView(DjangoLedgerSecurityMixIn, LedgerModelModelViewQuerySetMixIn, ArchiveIndexView):
41
+ allow_empty = True
41
42
  context_object_name = 'ledger_list'
42
43
  template_name = 'django_ledger/ledger/ledger_list.html'
43
44
  PAGE_TITLE = _('Entity Ledgers')
@@ -49,6 +50,7 @@ class LedgerModelListView(DjangoLedgerSecurityMixIn, LedgerModelModelViewQuerySe
49
50
  date_field = 'created'
50
51
  ordering = '-created'
51
52
 
53
+
52
54
  show_all = False
53
55
  show_current = False
54
56
  show_visible = False
@@ -3,7 +3,7 @@ Django Ledger created by Miguel Sanda <msanda@arrobalytics.com>.
3
3
  Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
4
4
 
5
5
  Contributions to this module:
6
- Miguel Sanda <msanda@arrobalytics.com>
6
+ * Miguel Sanda <msanda@arrobalytics.com>
7
7
  """
8
8
 
9
9
  from calendar import monthrange
@@ -314,10 +314,20 @@ class SuccessUrlNextMixIn:
314
314
 
315
315
  class DjangoLedgerSecurityMixIn(LoginRequiredMixin, PermissionRequiredMixin):
316
316
  ENTITY_SLUG_URL_KWARG = 'entity_slug'
317
- AUTHORIZED_ENTITY_MODEL: Optional[EntityModel] = None
317
+ ENTITY_MODEL_CONTEXT_NAME = 'entity_model'
318
318
  AUTHORIZE_SUPERUSER: bool = DJANGO_LEDGER_AUTHORIZED_SUPERUSER
319
319
  permission_required = []
320
320
 
321
+ def __init__(self, *args, **kwargs):
322
+ self.AUTHORIZED_ENTITY_MODEL: Optional[EntityModel] = None
323
+ super().__init__(*args, **kwargs)
324
+
325
+ def get_context_data(self, **kwargs):
326
+ context = super().get_context_data(**kwargs)
327
+ context[self.ENTITY_MODEL_CONTEXT_NAME] = self.get_authorized_entity_instance(raise_exception=False)
328
+ return context
329
+
330
+
321
331
  def get_login_url(self):
322
332
  return reverse('django_ledger:login')
323
333
 
@@ -355,12 +365,13 @@ class DjangoLedgerSecurityMixIn(LoginRequiredMixin, PermissionRequiredMixin):
355
365
  return EntityModel.objects.for_user(
356
366
  user_model=self.request.user,
357
367
  authorized_superuser=self.get_superuser_authorization(),
358
- ).only(
359
- 'uuid', 'slug', 'name', 'default_coa', 'admin')
368
+ )
360
369
 
361
- def get_authorized_entity_instance(self) -> Optional[EntityModel]:
370
+ def get_authorized_entity_instance(self, raise_exception: bool = True) -> Optional[EntityModel]:
362
371
  if self.AUTHORIZED_ENTITY_MODEL is None:
363
- raise Http404()
372
+ if raise_exception:
373
+ raise Http404()
374
+ return
364
375
  return self.AUTHORIZED_ENTITY_MODEL
365
376
 
366
377
 
@@ -389,7 +400,6 @@ class EntityUnitMixIn:
389
400
 
390
401
 
391
402
  class DigestContextMixIn:
392
-
393
403
  IO_DIGEST_UNBOUNDED = False
394
404
  IO_DIGEST_BOUNDED = False
395
405
 
@@ -522,7 +532,8 @@ class BaseDateNavigationUrlMixIn:
522
532
  'entity_slug',
523
533
  'unit_slug',
524
534
  'ledger_pk',
525
- 'account_pk'
535
+ 'account_pk',
536
+ 'coa_slug'
526
537
  )
527
538
 
528
539
  def get_context_data(self, **kwargs):
@@ -533,11 +544,12 @@ class BaseDateNavigationUrlMixIn:
533
544
  def get_base_date_nav_url(self, context, **kwargs):
534
545
  view_name = context['view'].request.resolver_match.url_name
535
546
  view_name_base = '-'.join(view_name.split('-')[:2])
536
- context['date_navigation_url'] = reverse(f'django_ledger:{view_name_base}',
537
- kwargs={
538
- k: v for k, v in self.kwargs.items() if
539
- k in self.BASE_DATE_URL_KWARGS
540
- })
547
+ context['date_navigation_url'] = reverse(
548
+ f'django_ledger:{view_name_base}',
549
+ kwargs={
550
+ k: v for k, v in self.kwargs.items() if
551
+ k in self.BASE_DATE_URL_KWARGS
552
+ })
541
553
 
542
554
 
543
555
  class PDFReportMixIn:
@@ -3,7 +3,7 @@ Django Ledger created by Miguel Sanda <msanda@arrobalytics.com>.
3
3
  Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
4
4
 
5
5
  Contributions to this module:
6
- Miguel Sanda <msanda@arrobalytics.com>
6
+ * Miguel Sanda <msanda@arrobalytics.com>
7
7
  """
8
8
  from django.contrib import messages
9
9
  from django.core.exceptions import ImproperlyConfigured, ValidationError
@@ -3,5 +3,5 @@ Django Ledger created by Miguel Sanda <msanda@arrobalytics.com>.
3
3
  Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
4
4
 
5
5
  Contributions to this module:
6
- Miguel Sanda <msanda@arrobalytics.com>
6
+ * Miguel Sanda <msanda@arrobalytics.com>
7
7
  """
@@ -1,3 +1,12 @@
1
+ """
2
+ Django Ledger created by Miguel Sanda <msanda@arrobalytics.com>.
3
+ Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
4
+
5
+ Contributions to this module:
6
+ * Miguel Sanda <msanda@arrobalytics.com>
7
+ """
8
+
9
+
1
10
  from django.http import HttpResponseRedirect
2
11
  from django.shortcuts import get_object_or_404
3
12
  from django.urls import reverse
@@ -3,7 +3,7 @@ Django Ledger created by Miguel Sanda <msanda@arrobalytics.com>.
3
3
  Copyright© EDMA Group Inc licensed under the GPLv3 Agreement.
4
4
 
5
5
  Contributions to this module:
6
- Miguel Sanda <msanda@arrobalytics.com>
6
+ * Miguel Sanda <msanda@arrobalytics.com>
7
7
  """
8
8
  from django.shortcuts import get_object_or_404
9
9
  from django.urls import reverse
@@ -7,12 +7,18 @@ Django Ledger was created by [Miguel Sanda](https://github.com/elarroba).
7
7
  ### Project Maintainers
8
8
  * Miguel Sanda [@elarroba](https://github.com/elarroba)
9
9
 
10
- ### Developers & Contributors
10
+ ### Developers
11
11
  * Miguel Sanda [@elarroba](https://github.com/elarroba)
12
+
13
+ ### Contributors
12
14
  * Michael Noel [@mnooel](https://github.com/mnooel)
13
15
  * Eric Owuor [@Ericpaul](https://github.com/25-do)
16
+ * Pranav P Tulshyan
14
17
 
15
18
  ### Accountants, CPAs & Bookkeepers
16
19
  * Miguel Sanda [@elarroba](https://github.com/elarroba)
17
20
  * Albert Salazar [@Beachwood619](https://github.com/Beachwood619)
18
- * Michael Noel, CPA [@mnooel](https://github.com/mnooel)
21
+ * Michael Noel, CPA [@mnooel](https://github.com/mnooel)
22
+
23
+ ### Documentation Contributors
24
+ * Miguel Sanda [@elarroba](https://github.com/elarroba)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-ledger
3
- Version: 0.6.4
3
+ Version: 0.7.1
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>
@@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3
14
14
  Classifier: Programming Language :: Python :: Implementation :: CPython
15
15
  Classifier: Topic :: Office/Business :: Financial :: Accounting
16
16
  Classifier: Framework :: Django :: 4.0
17
+ Classifier: Framework :: Django :: 5.0
17
18
  Classifier: Intended Audience :: Financial and Insurance Industry
18
19
  Classifier: Intended Audience :: End Users/Desktop
19
20
  Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
@@ -40,59 +41,47 @@ Requires-Dist: furo ; extra == 'dev'
40
41
 
41
42
  ![django ledger logo](https://us-east-1.linodeobjects.com/django-ledger/logo/django-ledger-logo@2x.png)
42
43
 
43
- ### An Accounting, Bookkeeping & Financial Analysis Engine for the Django Framework.
44
+ # Django Ledger
44
45
 
45
- Introducing __Django Ledger__, a powerful double entry accounting system designed for financially driven applications
46
- using the [Django Web Framework](https://www.djangoproject.com). Developed by lead developer Miguel Sanda, this system
47
- offers a simplified, high-level API, making it easier for users to navigate the complexities of accounting.
46
+ ## A Double Entry Accounting Engine for Django
48
47
 
49
- If you have prior experience with Django, you'll find this software even more effective. And, for those interested
50
- in contributing, consider joining our new discord channel for further collaboration and discussions.
48
+ Django Ledger is a powerful financial management system built on the Django Web Framework. It offers a simplified API for handling complex accounting tasks in financially driven applications.
51
49
 
52
- ### Questions? Join our Discord Channel [Here](https://discord.gg/c7PZcbYgrc)
50
+ [Join our Discord](https://discord.gg/c7PZcbYgrc) | [Documentation](https://django-ledger.readthedocs.io/en/latest/) | [QuickStart Notebook](https://github.com/arrobalytics/django-ledger/blob/develop/notebooks/QuickStart%20Notebook.ipynb)
53
51
 
54
- ### Documentation
52
+ ## Key Features
55
53
 
56
- Access the latest documentation and QuickStart guide [here](https://django-ledger.readthedocs.io/en/latest/).
57
- Also, you may download the QuickStart Jupyter Notebook
58
- [here](https://github.com/arrobalytics/django-ledger/blob/develop/notebooks/QuickStart%20Notebook.ipynb).
54
+ - High-level API
55
+ - Double entry accounting
56
+ - Hierarchical Chart of Accounts
57
+ - Financial statements (Income Statement, Balance Sheet, Cash Flow)
58
+ - Purchase Orders, Sales Orders, Bills, and Invoices
59
+ - Financial ratio calculations
60
+ - Multi-tenancy support
61
+ - Ledgers, Journal Entries & Transactions
62
+ - OFX & QFX file import
63
+ - Closing Entries
64
+ - Inventory management
65
+ - Unit of Measures
66
+ - Bank account information
67
+ - Django Admin integration
68
+ - Built-in Entity Management UI
59
69
 
60
- # Main Features
70
+ ## Getting Involved
61
71
 
62
- - High Level API.
63
- - Double entry accounting system.
64
- - Multiple Hierarchical Chart of Accounts.
65
- - Financial Statements (Income Statement, Balance Sheet & Cash Flow Statement).
66
- - Purchase Orders, Sales Orders (Estimates), Bills and Invoices.
67
- - Automatic financial ratio & insight calculations.
68
- - Multi tenancy (multiple companies/users/clients).
69
- - Self-contained Ledgers, Journal Entries & Transactions.
70
- - Basic OFX & QFX file import.
71
- - Closing Entries.
72
- - Items, lists & inventory management.
73
- - Unit of Measures.
74
- - Bank Accounts Information.
75
- - Django Admin Classes.
76
- - Built In Entity Management UI.
72
+ - **Feature Requests/Bug Reports**: Open an issue in the repository
73
+ - **For software customization, advanced features and consulting services**:
74
+ [Contact us](https://www.miguelsanda.com/work-with-me/) or email msanda@arrobalytics.com
75
+ - **Contribute**: See our [contribution guidelines](https://github.com/arrobalytics/django-ledger/blob/master/Contribute.md)
77
76
 
78
- ## Need a new feature or report a bug?
79
- Feel free to initiate an Issue describing your new feature request.
77
+ ## Who Should Contribute?
80
78
 
81
- # Want to contribute?
79
+ We're looking for contributors with:
80
+ - Python and Django programming skills
81
+ - Finance and accounting expertise
82
+ - Interest in developing a robust accounting engine API
82
83
 
83
- Finance and Accounting is a complicated subject. Django Ledger stands out from other Django projects due to its focus
84
- on providing a developer-friendly accounting engine and a reliable, extensible API for financially driven applications.
85
- The project requires expertise in Python, Django programming, finance, and accounting. In essence, the project is
86
- seeking assistance from individuals with the specific skill set needed to contribute effectively.
87
-
88
- The project is actively seeking contributors with financial and/or accounting experience. Prior accounting experience
89
- is a big plus for potential contributors. If you have the relevant experience and want to contribute, feel free to
90
- reach out to me or submit your pull request.
91
-
92
- You can find the contribution guidelines at the specified link.
93
- The project welcomes anyone interested in making a contribution.
94
-
95
- See __[contribution guidelines](https://github.com/arrobalytics/django-ledger/blob/develop/Contribute.md)__.
84
+ If you have relevant experience, especially in accounting, we welcome your pull requests or direct contact.
96
85
 
97
86
  # Installation
98
87