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
@@ -18,8 +18,10 @@ ItemsTransactionModels constitute the way multiple items and used resources are
18
18
  Purchase Orders and Estimates. Each transaction will record the unit of measure and quantity of each resource.
19
19
  Totals will be calculated and associated with the containing model at the time of update.
20
20
  """
21
+ import warnings
21
22
  from decimal import Decimal
22
23
  from string import ascii_lowercase, digits
24
+ from typing import Dict
23
25
  from uuid import uuid4, UUID
24
26
 
25
27
  from django.core.exceptions import ValidationError, ObjectDoesNotExist
@@ -29,11 +31,14 @@ from django.db.models import Q, Sum, F, ExpressionWrapper, DecimalField, Value,
29
31
  from django.db.models.functions import Coalesce
30
32
  from django.utils.translation import gettext_lazy as _
31
33
 
34
+ from django_ledger.models.deprecations import deprecated_entity_slug_behavior
32
35
  from django_ledger.models.mixins import CreateUpdateMixIn
33
36
  from django_ledger.models.utils import lazy_loader
34
- from django_ledger.settings import (DJANGO_LEDGER_TRANSACTION_MAX_TOLERANCE, DJANGO_LEDGER_DOCUMENT_NUMBER_PADDING,
35
- DJANGO_LEDGER_EXPENSE_NUMBER_PREFIX, DJANGO_LEDGER_INVENTORY_NUMBER_PREFIX,
36
- DJANGO_LEDGER_PRODUCT_NUMBER_PREFIX)
37
+ from django_ledger.settings import (
38
+ DJANGO_LEDGER_TRANSACTION_MAX_TOLERANCE, DJANGO_LEDGER_DOCUMENT_NUMBER_PADDING,
39
+ DJANGO_LEDGER_EXPENSE_NUMBER_PREFIX, DJANGO_LEDGER_INVENTORY_NUMBER_PREFIX,
40
+ DJANGO_LEDGER_PRODUCT_NUMBER_PREFIX, DJANGO_LEDGER_USE_DEPRECATED_BEHAVIOR
41
+ )
37
42
 
38
43
  ITEM_LIST_RANDOM_SLUG_SUFFIX = ascii_lowercase + digits
39
44
 
@@ -43,65 +48,83 @@ class ItemModelValidationError(ValidationError):
43
48
 
44
49
 
45
50
  class UnitOfMeasureModelQuerySet(QuerySet):
46
- pass
51
+
52
+ def for_user(self, user_model) -> 'UnitOfMeasureModelQuerySet':
53
+ return self.filter(
54
+ (
55
+ Q(entity__admin=user_model) |
56
+ Q(entity__managers__in=[user_model])
57
+ )
58
+ )
47
59
 
48
60
 
49
61
  # UNIT OF MEASURES MODEL....
50
62
  class UnitOfMeasureModelManager(Manager):
51
63
  """
52
- A custom defined QuerySet Manager for the UnitOfMeasureModel.
64
+ A custom-defined QuerySet Manager for the UnitOfMeasureModel.
53
65
  """
54
66
 
55
- def for_entity(self, entity_slug: str, user_model) -> QuerySet:
67
+ def get_queryset(self) -> UnitOfMeasureModelQuerySet:
68
+ return UnitOfMeasureModelQuerySet(self.model, using=self._db)
69
+
70
+ @deprecated_entity_slug_behavior
71
+ def for_entity(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs) -> UnitOfMeasureModelQuerySet:
56
72
  """
57
73
  Fetches the UnitOfMeasureModels associated with the provided EntityModel and UserModel.
58
74
 
59
75
  Parameters
60
76
  ----------
61
- entity_slug: str or EntityModel
77
+ entity_model: str or EntityModel
62
78
  The EntityModel slug or EntityModel used to filter the QuerySet.
63
- user_model: UserModel
64
- The Django UserModel to check permissions.
65
79
 
66
80
  Returns
67
81
  -------
68
82
  QuerySet
69
83
  A QuerySet with applied filters.
70
84
  """
85
+
86
+ EntityModel = lazy_loader.get_entity_model()
71
87
  qs = self.get_queryset()
72
- if isinstance(entity_slug, lazy_loader.get_entity_model()):
73
- return qs.filter(
74
- Q(entity=entity_slug) &
75
- (
76
- Q(entity__admin=user_model) |
77
- Q(entity__managers__in=[user_model])
78
- )
88
+
89
+ if 'user_model' in kwargs:
90
+ warnings.warn(
91
+ 'user_model parameter is deprecated and will be removed in a future release. '
92
+ 'Use for_user(user_model).for_entity(entity_model) instead to keep current behavior.',
93
+ DeprecationWarning,
94
+ stacklevel=2
79
95
  )
80
- return qs.filter(
81
- Q(entity__slug__exact=entity_slug) &
82
- (
83
- Q(entity__admin=user_model) |
84
- Q(entity__managers__in=[user_model])
96
+ if DJANGO_LEDGER_USE_DEPRECATED_BEHAVIOR:
97
+ qs = qs.for_user(kwargs['user_model'])
98
+
99
+ if isinstance(entity_model, EntityModel):
100
+ qs = qs.filter(entity=entity_model)
101
+ elif isinstance(entity_model, str):
102
+ qs = qs.filter(entity__slug=entity_model)
103
+ elif isinstance(entity_model, UUID):
104
+ qs = qs.filter(entity_id=entity_model)
105
+ else:
106
+ raise ItemModelValidationError(
107
+ message='Must pass EntityModel, slug or UUID'
85
108
  )
86
- )
109
+ return qs
87
110
 
88
- def for_entity_active(self, entity_slug: str, user_model):
111
+ @deprecated_entity_slug_behavior
112
+ def for_entity_active(
113
+ self, entity_model: 'EntityModel | str | UUID' = None,
114
+ **kwargs) -> UnitOfMeasureModelQuerySet:
89
115
  """
90
116
  Fetches the Active UnitOfMeasureModels associated with the provided EntityModel and UserModel.
91
117
 
92
118
  Parameters
93
119
  ----------
94
- entity_slug: str or EntityModel
120
+ entity_model: str or EntityModel
95
121
  The EntityModel slug or EntityModel used to filter the QuerySet.
96
- user_model: UserModel
97
- The Django UserModel to check permissions.
98
-
99
122
  Returns
100
123
  -------
101
124
  QuerySet
102
125
  A QuerySet with applied filters.
103
126
  """
104
- qs = self.for_entity(entity_slug=entity_slug, user_model=user_model)
127
+ qs = self.for_entity(entity_model=entity_model, **kwargs)
105
128
  return qs.filter(is_active=True)
106
129
 
107
130
 
@@ -154,6 +177,14 @@ class ItemModelQuerySet(QuerySet):
154
177
  A custom-defined ItemModelQuerySet that implements custom QuerySet methods related to the ItemModel.
155
178
  """
156
179
 
180
+ def for_user(self, user_model) -> 'ItemModelQuerySet':
181
+ if user_model.is_superuser:
182
+ return self
183
+ return self.filter(
184
+ Q(entity__managers__in=[user_model]) |
185
+ Q(entity__admin=user_model)
186
+ )
187
+
157
188
  def active(self):
158
189
  """
159
190
  Filters the QuerySet to only active Item Models.
@@ -165,7 +196,7 @@ class ItemModelQuerySet(QuerySet):
165
196
  """
166
197
  return self.filter(is_active=True)
167
198
 
168
- def products(self):
199
+ def products(self) -> 'ItemModelQuerySet':
169
200
  """
170
201
  Filters the QuerySet to ItemModels that only qualify as products.
171
202
 
@@ -182,7 +213,7 @@ class ItemModelQuerySet(QuerySet):
182
213
  Q(item_role=ItemModel.ITEM_ROLE_PRODUCT)
183
214
  )
184
215
 
185
- def services(self):
216
+ def services(self) -> 'ItemModelQuerySet':
186
217
  """
187
218
  Filters the QuerySet to ItemModels that only qualify as services.
188
219
 
@@ -199,7 +230,7 @@ class ItemModelQuerySet(QuerySet):
199
230
  Q(item_role=ItemModel.ITEM_ROLE_SERVICE)
200
231
  )
201
232
 
202
- def expenses(self):
233
+ def expenses(self) -> 'ItemModelQuerySet':
203
234
  """
204
235
  Filters the QuerySet to ItemModels that only qualify as expenses.
205
236
 
@@ -215,7 +246,7 @@ class ItemModelQuerySet(QuerySet):
215
246
  ) | Q(item_role=ItemModel.ITEM_ROLE_EXPENSE)
216
247
  )
217
248
 
218
- def inventory_wip(self):
249
+ def inventory_wip(self) -> 'ItemModelQuerySet':
219
250
  """
220
251
  Filters the QuerySet to ItemModels that only qualify as inventory.
221
252
  These types of items cannot be sold as they are not considered a finished product.
@@ -232,7 +263,7 @@ class ItemModelQuerySet(QuerySet):
232
263
  ) | Q(item_role=ItemModel.ITEM_ROLE_INVENTORY)
233
264
  )
234
265
 
235
- def inventory_all(self):
266
+ def inventory_all(self) -> 'ItemModelQuerySet':
236
267
  """
237
268
  Filters the QuerySet to ItemModels that only qualify as inventory.
238
269
  These types of items may be finished or unfinished.
@@ -260,7 +291,7 @@ class ItemModelQuerySet(QuerySet):
260
291
  )
261
292
  )
262
293
 
263
- def bills(self):
294
+ def bills(self) -> 'ItemModelQuerySet':
264
295
  """
265
296
  Filters the QuerySet to ItemModels that are eligible only for bills..
266
297
 
@@ -277,13 +308,13 @@ class ItemModelQuerySet(QuerySet):
277
308
  Q(for_inventory=True)
278
309
  )
279
310
 
280
- def invoices(self):
311
+ def invoices(self) -> 'ItemModelQuerySet':
281
312
  return self.filter(is_product_or_service=True)
282
313
 
283
- def estimates(self):
314
+ def estimates(self) -> 'ItemModelQuerySet':
284
315
  return self.invoices()
285
316
 
286
- def purchase_orders(self):
317
+ def purchase_orders(self) -> 'ItemModelQuerySet':
287
318
  return self.inventory_all()
288
319
 
289
320
 
@@ -292,61 +323,87 @@ class ItemModelManager(Manager):
292
323
  A custom defined ItemModelManager that implement custom QuerySet methods related to the ItemModel
293
324
  """
294
325
 
295
- def for_entity(self, entity_slug, user_model):
326
+ def get_queryset(self) -> ItemModelQuerySet:
327
+ return ItemModelQuerySet(self.model, using=self._db).select_related('uom')
328
+
329
+ @deprecated_entity_slug_behavior
330
+ def for_entity(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs) -> ItemModelQuerySet:
296
331
  """
297
- Returns a QuerySet of ItemModel associated with a specific EntityModel & UserModel.
298
- May pass an instance of EntityModel or a String representing the EntityModel slug.
332
+ Marks the `for_entity` method as deprecated in behavior and provides an updated usage approach.
333
+
334
+ This method allows querying a `QuerySet` filtered by various representations of an entity, such as an
335
+ instance of `EntityModel`, a string slug, or a UUID. Leveraging this method with deprecated parameters
336
+ may lead to a warning and compatibility concerns in future releases.
299
337
 
300
338
  Parameters
301
339
  ----------
302
- entity_slug: str or EntityModel
303
- The entity slug or EntityModel used for filtering the QuerySet.
304
- user_model
305
- The request UserModel to check for privileges.
340
+ entity_model : EntityModel | str | UUID, optional
341
+ The entity to filter the queryset by. Can be an instance of `EntityModel`, a slug (`str`), or
342
+ a unique identifier (`UUID`). If not provided, no filtering is applied.
343
+ kwargs : dict
344
+ Additional keyword arguments, though currently only the `user_model` parameter is recognized but
345
+ deprecated. The `user_model` behavior will be removed in future releases.
306
346
 
307
347
  Returns
308
348
  -------
309
349
  ItemModelQuerySet
310
- A Filtered ItemModelQuerySet.
350
+ A filtered queryset corresponding to the specified entity.
351
+
352
+ Raises
353
+ ------
354
+ ItemModelValidationError
355
+ If the `entity_model` parameter is not of type `EntityModel`, `str`, or `UUID`.
356
+ DeprecationWarning
357
+ When the `user_model` parameter is used, indicating behavior slated for future removal.
311
358
  """
359
+ EntityModel = lazy_loader.get_entity_model()
312
360
  qs = self.get_queryset()
313
- if isinstance(entity_slug, lazy_loader.get_entity_model()):
314
- return qs.filter(
315
- Q(entity=entity_slug) &
316
- (
317
- Q(entity__managers__in=[user_model]) |
318
- Q(entity__admin=user_model)
319
- )
320
- ).select_related('uom')
321
- return qs.filter(
322
- Q(entity__slug__exact=entity_slug) &
323
- (
324
- Q(entity__managers__in=[user_model]) |
325
- Q(entity__admin=user_model)
361
+ if 'user_model' in kwargs:
362
+ warnings.warn(
363
+ 'user_model parameter is deprecated and will be removed in a future release. '
364
+ 'Use for_user(user_model).for_entity(entity_model) instead to keep current behavior.',
365
+ DeprecationWarning,
366
+ stacklevel=2
367
+ )
368
+ if DJANGO_LEDGER_USE_DEPRECATED_BEHAVIOR:
369
+ qs = qs.for_user(kwargs['user_model'])
370
+
371
+ if isinstance(entity_model, EntityModel):
372
+ qs = qs.filter(entity=entity_model)
373
+ elif isinstance(entity_model, str):
374
+ qs = qs.filter(entity__slug__exact=entity_model)
375
+ elif isinstance(entity_model, UUID):
376
+ qs = qs.filter(entity_id=entity_model)
377
+ else:
378
+ raise ItemModelValidationError(
379
+ message='entity_model parameter must be of type str or EntityModel or UUID'
326
380
  )
327
- ).select_related('uom')
381
+ return qs
328
382
 
329
- def for_entity_active(self, entity_slug, user_model):
383
+ @deprecated_entity_slug_behavior
384
+ def for_entity_active(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs) -> ItemModelQuerySet:
330
385
  """
331
386
  Returns a QuerySet of Active ItemModel associated with a specific EntityModel & UserModel.
332
387
  May pass an instance of EntityModel or a String representing the EntityModel slug.
333
388
 
334
389
  Parameters
335
390
  ----------
336
- entity_slug: str or EntityModel
391
+ entity_model: str or EntityModel
337
392
  The entity slug or EntityModel used for filtering the QuerySet.
338
- user_model
339
- The request UserModel to check for privileges.
340
393
 
341
394
  Returns
342
395
  -------
343
396
  ItemModelQuerySet
344
397
  A Filtered ItemModelQuerySet.
345
398
  """
346
- qs = self.for_entity(entity_slug=entity_slug, user_model=user_model)
399
+ qs = self.for_entity(
400
+ entity_model=entity_model,
401
+ **kwargs
402
+ )
347
403
  return qs.filter(is_active=True)
348
404
 
349
- def for_invoice(self, entity_slug, user_model):
405
+ @deprecated_entity_slug_behavior
406
+ def for_invoice(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs) -> ItemModelQuerySet:
350
407
  """
351
408
  Returns a QuerySet of ItemModels that can only be used for InvoiceModels for a specific EntityModel &
352
409
  UserModel. These types of items qualify as products or services sold.
@@ -354,20 +411,19 @@ class ItemModelManager(Manager):
354
411
 
355
412
  Parameters
356
413
  ----------
357
- entity_slug: str or EntityModel
414
+ entity_model: str or EntityModel
358
415
  The entity slug or EntityModel used for filtering the QuerySet.
359
- user_model
360
- The request UserModel to check for privileges.
361
416
 
362
417
  Returns
363
418
  -------
364
419
  ItemModelQuerySet
365
420
  A Filtered ItemModelQuerySet.
366
421
  """
367
- qs = self.for_entity_active(entity_slug=entity_slug, user_model=user_model)
422
+ qs = self.for_entity_active(entity_model=entity_model, **kwargs)
368
423
  return qs.filter(is_product_or_service=True)
369
424
 
370
- def for_bill(self, entity_slug, user_model):
425
+ @deprecated_entity_slug_behavior
426
+ def for_bill(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs) -> ItemModelQuerySet:
371
427
  """
372
428
  Returns a QuerySet of ItemModels that can only be used for BillModels for a specific EntityModel &
373
429
  UserModel. These types of items qualify as expenses or inventory purchases.
@@ -375,10 +431,8 @@ class ItemModelManager(Manager):
375
431
 
376
432
  Parameters
377
433
  ----------
378
- entity_slug: str or EntityModel
434
+ entity_model: str or EntityModel
379
435
  The entity slug or EntityModel used for filtering the QuerySet.
380
- user_model
381
- The request UserModel to check for privileges.
382
436
 
383
437
  Returns
384
438
  -------
@@ -386,8 +440,8 @@ class ItemModelManager(Manager):
386
440
  A Filtered ItemModelQuerySet.
387
441
  """
388
442
  qs = self.for_entity_active(
389
- entity_slug=entity_slug,
390
- user_model=user_model
443
+ entity_model=entity_model,
444
+ **kwargs
391
445
  )
392
446
  return qs.filter(
393
447
  (
@@ -397,7 +451,8 @@ class ItemModelManager(Manager):
397
451
  Q(for_inventory=True)
398
452
  )
399
453
 
400
- def for_po(self, entity_slug, user_model):
454
+ @deprecated_entity_slug_behavior
455
+ def for_po(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs) -> ItemModelQuerySet:
401
456
  """
402
457
  Returns a QuerySet of ItemModels that can only be used for PurchaseOrders for a specific EntityModel &
403
458
  UserModel. These types of items qualify as inventory purchases.
@@ -405,20 +460,19 @@ class ItemModelManager(Manager):
405
460
 
406
461
  Parameters
407
462
  ----------
408
- entity_slug: str or EntityModel
463
+ entity_model: str or EntityModel
409
464
  The entity slug or EntityModel used for filtering the QuerySet.
410
- user_model
411
- The request UserModel to check for privileges.
412
465
 
413
466
  Returns
414
467
  -------
415
468
  ItemModelQuerySet
416
469
  A Filtered ItemModelQuerySet.
417
470
  """
418
- qs = self.for_entity(entity_slug=entity_slug, user_model=user_model)
471
+ qs = self.for_entity(entity_model=entity_model, **kwargs)
419
472
  return qs.inventory_all()
420
473
 
421
- def for_estimate(self, entity_slug: str, user_model):
474
+ @deprecated_entity_slug_behavior
475
+ def for_estimate(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs) -> ItemModelQuerySet:
422
476
  """
423
477
  Returns a QuerySet of ItemModels that can only be used for EstimateModels for a specific EntityModel &
424
478
  UserModel. These types of items qualify as products.
@@ -426,17 +480,15 @@ class ItemModelManager(Manager):
426
480
 
427
481
  Parameters
428
482
  ----------
429
- entity_slug: str or EntityModel
483
+ entity_model: str or EntityModel
430
484
  The entity slug or EntityModel used for filtering the QuerySet.
431
- user_model
432
- The request UserModel to check for privileges.
433
485
 
434
486
  Returns
435
487
  -------
436
488
  ItemModelQuerySet
437
489
  A Filtered ItemModelQuerySet.
438
490
  """
439
- qs = self.for_entity_active(entity_slug=entity_slug, user_model=user_model)
491
+ qs = self.for_entity_active(entity_model=entity_model, **kwargs)
440
492
  return qs.products()
441
493
 
442
494
 
@@ -849,25 +901,110 @@ class ItemModelAbstract(CreateUpdateMixIn):
849
901
 
850
902
 
851
903
  # ITEM TRANSACTION MODELS...
904
+
905
+ class ItemTransactionModelValidationError(ValidationError):
906
+ pass
907
+
908
+
852
909
  class ItemTransactionModelQuerySet(QuerySet):
910
+ """
911
+ QuerySet class for handling ItemTransactionModel-specific database queries.
912
+
913
+ This class extends Django's QuerySet to provide additional methods
914
+ to filter and retrieve specific subsets of ItemTransactionModel entries
915
+ based on various criteria such as user permissions, transaction status,
916
+ or custom aggregate calculations.
917
+ """
918
+
919
+ def for_user(self, user_model) -> 'ItemTransactionModelQuerySet':
920
+ """
921
+ Filters the queryset based on the provided user model.
853
922
 
854
- def is_received(self):
923
+ This method restricts the queryset to items associated with the specified
924
+ user. If the user is a superuser, all items in the queryset are returned.
925
+ Otherwise, only items managed or administered by the user are included.
926
+
927
+ Parameters
928
+ ----------
929
+ user_model : UserModel
930
+ The user model instance used to filter the queryset.
931
+
932
+ Returns
933
+ -------
934
+ ItemTransactionModelQuerySet
935
+ The filtered queryset containing items accessible by the given user.
936
+ """
937
+ if user_model.is_superuser:
938
+ return self
939
+ return self.filter(
940
+ Q(item_model__entity__admin=user_model) |
941
+ Q(item_model__entity__managers__in=[user_model])
942
+ )
943
+
944
+ def is_received(self) -> 'ItemTransactionModelQuerySet':
945
+ """
946
+ Filters the queryset to include only items with the status 'received'.
947
+
948
+ Returns
949
+ -------
950
+ ItemTransactionModelQuerySet
951
+ A queryset containing only the items with the status 'received'.
952
+ """
855
953
  return self.filter(po_item_status=ItemTransactionModel.STATUS_RECEIVED)
856
954
 
857
- def in_transit(self):
955
+ def in_transit(self) -> 'ItemTransactionModelQuerySet':
956
+ """
957
+ Filters and retrieves items in the "in transit" status.
958
+
959
+ Returns
960
+ -------
961
+ ItemTransactionModelQuerySet
962
+ A queryset containing items whose status is "in transit".
963
+ """
858
964
  return self.filter(po_item_status=ItemTransactionModel.STATUS_IN_TRANSIT)
859
965
 
860
- def is_ordered(self):
966
+ def is_ordered(self) -> 'ItemTransactionModelQuerySet':
967
+ """
968
+ Filters the queryset to include only items with the status "ORDERED".
969
+
970
+ Returns
971
+ -------
972
+ ItemTransactionModelQuerySet
973
+ A filtered queryset containing items with the status "ORDERED".
974
+ """
861
975
  return self.filter(po_item_status=ItemTransactionModel.STATUS_ORDERED)
862
976
 
863
- def is_orphan(self):
977
+ def is_orphan(self) -> 'ItemTransactionModelQuerySet':
978
+ """
979
+ Filters the query set for items that are considered "orphan", meaning
980
+ they are not linked to any bill, purchase order, or cost estimate models.
981
+
982
+ Returns
983
+ -------
984
+ ItemTransactionModelQuerySet
985
+ A filtered query set containing only the orphan items.
986
+ """
864
987
  return self.filter(
865
988
  Q(bill_model_id__isnull=True) &
866
989
  Q(po_model_id__isnull=True) &
867
990
  Q(ce_model_id__isnull=True)
868
991
  )
869
992
 
870
- def get_estimate_aggregate(self):
993
+ def get_estimate_aggregate(self) -> Dict[str, int]:
994
+ """
995
+ Calculate aggregated estimates for cost, revenue, and total items.
996
+
997
+ This method computes the sum of `ce_cost_estimate` and `ce_revenue_estimate`
998
+ for all elements in the iterable, as well as the total number of items.
999
+
1000
+ Returns
1001
+ -------
1002
+ Dict[str, int]
1003
+ A dictionary containing the following keys:
1004
+ - 'ce_cost_estimate__sum': The total sum of all `ce_cost_estimate` values.
1005
+ - 'ce_revenue_estimate__sum': The total sum of all `ce_revenue_estimate` values.
1006
+ - 'total_items': The total count of items in the iterable.
1007
+ """
871
1008
  return {
872
1009
  'ce_cost_estimate__sum': sum(i.ce_cost_estimate for i in self),
873
1010
  'ce_revenue_estimate__sum': sum(i.ce_revenue_estimate for i in self),
@@ -877,51 +1014,260 @@ class ItemTransactionModelQuerySet(QuerySet):
877
1014
 
878
1015
  class ItemTransactionModelManager(Manager):
879
1016
 
880
- def for_user(self, user_model):
881
- qs = self.get_queryset()
882
- return qs.filter(
883
- Q(item_model__entity__admin=user_model) |
884
- Q(item_model__entity__managers__in=[user_model])
885
- )
1017
+ def get_queryset(self) -> ItemTransactionModelQuerySet:
1018
+ """
1019
+ Provides a custom queryset for the related ItemTransactionModel.
1020
+
1021
+ This method ensures that the queryset returned is an instance of the custom
1022
+ ItemTransactionModelQuerySet configured for operations on the specific model.
1023
+
1024
+ Returns
1025
+ -------
1026
+ ItemTransactionModelQuerySet
1027
+ An instance of ItemTransactionModelQuerySet customized for the model.
1028
+ """
1029
+ return ItemTransactionModelQuerySet(self.model, using=self._db)
1030
+
1031
+ @deprecated_entity_slug_behavior
1032
+ def for_entity(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs) -> ItemTransactionModelQuerySet:
1033
+ """
1034
+ A method to filter the queryset for a specified entity. The filtering can be performed
1035
+ using an entity model, a slug string, or a UUID. Older deprecated parameters can still
1036
+ be utilized if certain conditions are met. This method applies the necessary filters
1037
+ to the queryset based on the entity information provided.
1038
+
1039
+ Parameters
1040
+ ----------
1041
+ entity_model : EntityModel | str | UUID, optional
1042
+ The entity for which the queryset is being filtered. It can be an instance of
1043
+ EntityModel, a string representing the entity slug, or a UUID corresponding to
1044
+ the entity's identifier.
1045
+ **kwargs :
1046
+ Arbitrary keyword arguments. A specific argument, `user_model`, is deprecated
1047
+ and will trigger a warning if used.
886
1048
 
887
- def for_entity(self, user_model, entity_slug):
888
- qs = self.for_user(user_model)
889
- if isinstance(entity_slug, lazy_loader.get_entity_model()):
890
- return qs.filter(
891
- Q(item_model__entity=entity_slug)
1049
+ Returns
1050
+ -------
1051
+ ItemTransactionModelQuerySet
1052
+ The queryset filtered for the specified entity.
1053
+
1054
+ Raises
1055
+ ------
1056
+ ItemTransactionModelValidationError
1057
+ Raised when `entity_model` is not an instance of EntityModel, a string, or a UUID.
1058
+
1059
+ Warnings
1060
+ --------
1061
+ DeprecationWarning
1062
+ Issued if `user_model` parameter is passed via kwargs. Users are encouraged to update
1063
+ their implementation to utilize `for_user(user_model).for_entity(entity_model)`
1064
+ to avoid this warning.
1065
+
1066
+ Notes
1067
+ -----
1068
+ - Deprecation behavior of certain parameters depends on the `DJANGO_LEDGER_USE_DEPRECATED_BEHAVIOR` flag.
1069
+ - If `entity_model` is None, the method raises an error as entity identification is required.
1070
+ """
1071
+ EntityModel = lazy_loader.get_entity_model()
1072
+
1073
+ qs = self.get_queryset()
1074
+ if 'user_model' in kwargs:
1075
+ warnings.warn(
1076
+ 'user_model parameter is deprecated and will be removed in a future release. '
1077
+ 'Use for_user(user_model).for_entity(entity_model) instead to keep current behavior.',
1078
+ DeprecationWarning,
1079
+ stacklevel=2
892
1080
  )
893
- return qs.filter(
894
- Q(item_model__entity__slug__exact=entity_slug)
895
- )
1081
+ if DJANGO_LEDGER_USE_DEPRECATED_BEHAVIOR:
1082
+ qs = qs.for_user(kwargs['user_model'])
1083
+
1084
+ if isinstance(entity_model, EntityModel):
1085
+ qs = qs.filter(item_model__entity=entity_model)
1086
+ elif isinstance(entity_model, str):
1087
+ qs = qs.filter(item_model__entity__slug__exact=entity_model)
1088
+ elif isinstance(entity_model, UUID):
1089
+ qs = qs.filter(item_model__entity_id=entity_model)
1090
+ else:
1091
+ raise ItemTransactionModelValidationError(
1092
+ message='Must pass EntityModel, slug or UUID'
1093
+ )
1094
+ return qs
1095
+
1096
+ @deprecated_entity_slug_behavior
1097
+ def for_bill(self, bill_pk: UUID, entity_model: 'EntityModel | str | UUID' = None, **kwargs, ):
1098
+ """
1099
+ This function provides filters for fetching data related to a specific bill, based on a given
1100
+ bill primary key, along with optional parameters for an associated entity model.
1101
+
1102
+ Parameters
1103
+ ----------
1104
+ bill_pk : UUID
1105
+ The primary key of the bill to filter.
1106
+ entity_model : EntityModel | str | UUID.
1107
+ Represents the associated entity model, which could be provided as an instance,
1108
+ identifier, or string.
1109
+ **kwargs : dict
1110
+ Additional filtering or query parameters.
896
1111
 
897
- def for_bill(self, user_model, entity_slug, bill_pk):
898
- qs = self.for_entity(user_model=user_model, entity_slug=entity_slug)
1112
+ Returns
1113
+ -------
1114
+ QuerySet
1115
+ A filtered queryset containing data relevant to the specified bill and optional entity
1116
+ constraints.
1117
+
1118
+ Deprecated
1119
+ ----------
1120
+ This function is deprecated in favor of using entity behavior. Please refer to the
1121
+ documentation for updated usage guidelines.
1122
+ """
1123
+ qs = self.for_entity(entity_model=entity_model, **kwargs)
899
1124
  return qs.filter(bill_model_id__exact=bill_pk)
900
1125
 
901
- def for_invoice(self, entity_slug: str, invoice_pk, user_model):
902
- qs = self.for_entity(entity_slug=entity_slug, user_model=user_model)
1126
+ @deprecated_entity_slug_behavior
1127
+ def for_invoice(self, invoice_pk: UUID, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
1128
+ """
1129
+ Marks the behavior as deprecated when filtering queries for a specific invoice.
1130
+
1131
+ This method provides functionality to filter a queryset based on a specified
1132
+ invoice primary key and an entity model. It is marked as deprecated in favor
1133
+ of other entity behavior methods.
1134
+
1135
+ Parameters
1136
+ ----------
1137
+ invoice_pk : UUID
1138
+ The primary key of the invoice to filter the queryset by.
1139
+ entity_model : EntityModel | str | UUID
1140
+ The entity to filter the queryset for. This can be an instance of
1141
+ EntityModel, a UUID, or a string representation of the entity.
1142
+ **kwargs : dict
1143
+ Additional filtering parameters to apply to the queryset.
1144
+
1145
+ Returns
1146
+ -------
1147
+ QuerySet
1148
+ A filtered queryset containing objects associated with the specified invoice.
1149
+
1150
+ Raises
1151
+ ------
1152
+ Any exceptions raised during the call to `for_entity` or filtering process.
1153
+
1154
+ Notes
1155
+ -----
1156
+ The method is slated for deprecation and should be replaced with preferred
1157
+ methods for filtering querysets by entity behavior in the future.
1158
+ """
1159
+ qs = self.for_entity(entity_model=entity_model, **kwargs)
903
1160
  return qs.filter(invoice_model_id__exact=invoice_pk)
904
1161
 
905
- def for_po(self, entity_slug, user_model, po_pk):
906
- qs = self.for_entity(entity_slug=entity_slug, user_model=user_model)
1162
+ @deprecated_entity_slug_behavior
1163
+ def for_po(self, po_pk: UUID, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
1164
+ """
1165
+ Filters and retrieves entity records associated with a specific purchase order (PO) and entity model.
1166
+
1167
+ This method applies additional filtering to an existing queryset by matching the given PO primary
1168
+ key (UUID) with records tied to the corresponding PO model. It leverages an extended filter for
1169
+ entity behavior but is marked deprecated in favor of using alternative entity filtering methods.
1170
+
1171
+ Parameters
1172
+ ----------
1173
+ po_pk : UUID
1174
+ The primary key identifier for the purchase order.
1175
+ entity_model : EntityModel or str or UUID
1176
+ The model representing the associated entity. If not provided, an alternate behavior based on
1177
+ `kwargs` or contextual settings will apply.
1178
+ **kwargs : dict, optional
1179
+ Additional keyword arguments provided for extended filtering.
1180
+
1181
+ Returns
1182
+ -------
1183
+ QuerySet
1184
+ A filtered queryset containing records that match the specified PO `po_pk` and entity model
1185
+ criteria.
1186
+
1187
+ Raises
1188
+ ------
1189
+ None explicitly documented; refer to underlying methods (`for_entity`) for any potential errors.
1190
+
1191
+ Warnings
1192
+ --------
1193
+ This method is deprecated and may be removed in future versions. Use alternative entity filtering
1194
+ methods where applicable.
1195
+ """
1196
+ qs = self.for_entity(entity_model=entity_model, **kwargs)
907
1197
  return qs.filter(po_model__uuid__exact=po_pk)
908
1198
 
909
- def for_estimate(self, user_model, entity_slug, cj_pk):
910
- qs = self.for_entity(entity_slug=entity_slug, user_model=user_model)
911
- return self.filter(ce_model_id__exact=cj_pk)
1199
+ @deprecated_entity_slug_behavior
1200
+ def for_estimate(self, cj_pk: UUID, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
1201
+ """
1202
+ Marks the method as deprecated for estimating behavior in relation to an entity.
1203
+
1204
+ This method is intended to filter a queryset based on a specific entity and a unique
1205
+ identifier (`cj_pk`). It's discouraged to use this method in new implementations as
1206
+ it has been marked deprecated.
912
1207
 
913
- def for_contract(self, user_model, entity_slug, ce_pk):
1208
+ Parameters
1209
+ ----------
1210
+ cj_pk : UUID
1211
+ The unique identifier for the entity model to filter on.
1212
+ entity_model : EntityModel | str | UUID
1213
+ The entity model, which may be provided either as an `EntityModel` instance,
1214
+ a string representing its identifier, or a `UUID`. Defaults to `None`.
1215
+ **kwargs : dict
1216
+ Additional keyword arguments to pass to the entity filtering mechanism.
1217
+
1218
+ Returns
1219
+ -------
1220
+ QuerySet
1221
+ The filtered queryset based on the provided `cj_pk` and the optional
1222
+ `entity_model`.
1223
+
1224
+ Raises
1225
+ ------
1226
+ TypeError
1227
+ If the input parameters are invalid or incompatible with the filtering process.
914
1228
  """
915
- Returns all ItemTransactionModels associated with an EstimateModel.
916
- @param user_model: UserModel requesting data.
917
- @param entity_slug: EntityModel slug field value.
918
- @param ce_pk: EstimateModel UUID.
919
- @return: ItemTransactionModel QuerySet
1229
+ qs = self.for_entity(entity_model=entity_model, **kwargs)
1230
+ return qs.filter(ce_model_id__exact=cj_pk)
1231
+
1232
+ @deprecated_entity_slug_behavior
1233
+ def for_contract(self, ce_pk: UUID, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
920
1234
  """
921
- qs = self.for_entity(
922
- entity_slug=entity_slug,
923
- user_model=user_model
924
- )
1235
+ Provides a method to filter querysets based on the contract entity model to which they are associated.
1236
+
1237
+ Methods
1238
+ -------
1239
+ for_contract(ce_pk: UUID, entity_model: 'EntityModel | str | UUID' = None, **kwargs)
1240
+ Filters a queryset to include records associated with a specific contract entity
1241
+ model by its primary key and optionally narrows it down further using an entity model
1242
+ and additional query parameters.
1243
+
1244
+ Parameters
1245
+ ----------
1246
+ ce_pk : UUID
1247
+ The unique identifier (primary key) of the contract entity model to filter by.
1248
+ entity_model : 'EntityModel | str | UUID'
1249
+ An optional entity model object, string representation, or primary key to use
1250
+ for filtering the queryset.
1251
+ **kwargs : dict
1252
+ Additional keyword arguments that can be passed to further refine the filtered queryset.
1253
+
1254
+ Returns
1255
+ -------
1256
+ qs : QuerySet
1257
+ A filtered queryset containing records associated with the specified contract entity
1258
+ model and additional filter conditions.
1259
+
1260
+ Raises
1261
+ ------
1262
+ Exception
1263
+ Any exception raised while applying additional filters to the queryset or querying
1264
+ against the database.
1265
+
1266
+ Deprecated
1267
+ ----------
1268
+ This function is deprecated for entity behavior.
1269
+ """
1270
+ qs = self.for_entity(entity_model=entity_model, **kwargs)
925
1271
  return qs.filter(
926
1272
  Q(ce_model_id__exact=ce_pk) |
927
1273
  Q(po_model__ce_model_id__exact=ce_pk) |
@@ -930,14 +1276,23 @@ class ItemTransactionModelManager(Manager):
930
1276
  )
931
1277
 
932
1278
  # INVENTORY METHODS....
933
- def for_entity_inventory(self, entity_slug):
934
- qs = self.get_queryset()
935
- return qs.filter(item_model__entity__slug__exact=entity_slug)
936
-
937
- # Todo move this to QuerySet....
938
- def inventory_count(self, entity_slug):
1279
+ @deprecated_entity_slug_behavior
1280
+ def for_entity_inventory(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
1281
+ EntityModel = lazy_loader.get_entity_model()
1282
+
1283
+ qs = self.for_entity(entity_model=entity_model, **kwargs)
1284
+ if isinstance(entity_model, EntityModel):
1285
+ qs = qs.filter(item_model__entity=entity_model)
1286
+ elif isinstance(entity_model, str):
1287
+ qs = qs.filter(item_model__entity__slug__exact=entity_model)
1288
+ elif isinstance(entity_model, UUID):
1289
+ qs = qs.filter(item_model__entity_id=entity_model)
1290
+ return qs
1291
+
1292
+ @deprecated_entity_slug_behavior
1293
+ def inventory_count(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
939
1294
  PurchaseOrderModel = lazy_loader.get_purchase_order_model()
940
- qs = self.for_entity_inventory(entity_slug)
1295
+ qs = self.for_entity_inventory(entity_model=entity_model, **kwargs)
941
1296
  qs = qs.filter(
942
1297
  Q(item_model__for_inventory=True) &
943
1298
  (
@@ -983,8 +1338,9 @@ class ItemTransactionModelManager(Manager):
983
1338
  output_field=DecimalField(decimal_places=3)), Value(0.0), output_field=DecimalField())
984
1339
  )
985
1340
 
986
- def inventory_pipeline(self, entity_slug):
987
- qs = self.for_entity_inventory(entity_slug)
1341
+ @deprecated_entity_slug_behavior
1342
+ def inventory_pipeline(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
1343
+ qs = self.for_entity_inventory(entity_model=entity_model, **kwargs)
988
1344
  return qs.filter(
989
1345
  Q(item_model__for_inventory=True) &
990
1346
  Q(bill_model__isnull=False) &
@@ -995,8 +1351,9 @@ class ItemTransactionModelManager(Manager):
995
1351
  ])
996
1352
  )
997
1353
 
998
- def inventory_pipeline_aggregate(self, entity_slug: str):
999
- qs = self.inventory_pipeline(entity_slug=entity_slug)
1354
+ @deprecated_entity_slug_behavior
1355
+ def inventory_pipeline_aggregate(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
1356
+ qs = self.inventory_pipeline(entity_model=entity_model, **kwargs)
1000
1357
  return qs.values(
1001
1358
  'item_model__name',
1002
1359
  'item_model__uom__name',
@@ -1005,20 +1362,24 @@ class ItemTransactionModelManager(Manager):
1005
1362
  total_value=Sum('total_amount')
1006
1363
  )
1007
1364
 
1008
- def inventory_pipeline_ordered(self, entity_slug):
1009
- qs = self.inventory_pipeline(entity_slug=entity_slug)
1365
+ @deprecated_entity_slug_behavior
1366
+ def inventory_pipeline_ordered(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
1367
+ qs = self.inventory_pipeline(entity_model=entity_model)
1010
1368
  return qs.filter(po_item_status=ItemTransactionModel.STATUS_ORDERED)
1011
1369
 
1012
- def inventory_pipeline_in_transit(self, entity_slug):
1013
- qs = self.inventory_pipeline(entity_slug=entity_slug)
1370
+ @deprecated_entity_slug_behavior
1371
+ def inventory_pipeline_in_transit(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
1372
+ qs = self.inventory_pipeline(entity_model=entity_model)
1014
1373
  return qs.filter(po_item_status=ItemTransactionModel.STATUS_IN_TRANSIT)
1015
1374
 
1016
- def inventory_pipeline_received(self, entity_slug):
1017
- qs = self.inventory_pipeline(entity_slug=entity_slug)
1375
+ @deprecated_entity_slug_behavior
1376
+ def inventory_pipeline_received(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
1377
+ qs = self.inventory_pipeline(entity_model=entity_model)
1018
1378
  return qs.filter(po_item_status=ItemTransactionModel.STATUS_RECEIVED)
1019
1379
 
1020
- def inventory_invoiced(self, entity_slug):
1021
- qs = self.for_entity_inventory(entity_slug)
1380
+ @deprecated_entity_slug_behavior
1381
+ def inventory_invoiced(self, entity_model: 'EntityModel | str | UUID' = None, **kwargs):
1382
+ qs = self.for_entity_inventory(entity_model=entity_model, **kwargs)
1022
1383
  return qs.filter(
1023
1384
  Q(item_model__for_inventory=True) &
1024
1385
  Q(invoice_model__isnull=False)