django-cfg 1.2.29__py3-none-any.whl → 1.3.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.
Files changed (258) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/api/health/views.py +4 -2
  3. django_cfg/apps/knowbase/config/settings.py +16 -15
  4. django_cfg/apps/payments/README.md +326 -0
  5. django_cfg/apps/payments/admin/__init__.py +20 -9
  6. django_cfg/apps/payments/admin/api_keys_admin.py +521 -237
  7. django_cfg/apps/payments/admin/balance_admin.py +592 -297
  8. django_cfg/apps/payments/admin/currencies_admin.py +600 -108
  9. django_cfg/apps/payments/admin/filters.py +306 -199
  10. django_cfg/apps/payments/admin/payments_admin.py +470 -64
  11. django_cfg/apps/payments/admin/subscriptions_admin.py +578 -128
  12. django_cfg/apps/payments/admin_interface/__init__.py +18 -0
  13. django_cfg/apps/payments/admin_interface/templates/payments/base.html +162 -0
  14. django_cfg/apps/payments/admin_interface/templates/payments/components/dev_tool_card.html +38 -0
  15. django_cfg/apps/payments/admin_interface/templates/payments/components/loading_spinner.html +16 -0
  16. django_cfg/apps/payments/admin_interface/templates/payments/components/notification.html +27 -0
  17. django_cfg/apps/payments/admin_interface/templates/payments/components/provider_card.html +86 -0
  18. django_cfg/apps/payments/admin_interface/templates/payments/components/status_card.html +39 -0
  19. django_cfg/apps/payments/admin_interface/templates/payments/currency_converter.html +382 -0
  20. django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +300 -0
  21. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +303 -0
  22. django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +382 -0
  23. django_cfg/apps/payments/admin_interface/templates/payments/payment_status.html +500 -0
  24. django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +594 -0
  25. django_cfg/apps/payments/admin_interface/views/__init__.py +23 -0
  26. django_cfg/apps/payments/admin_interface/views/payment_views.py +259 -0
  27. django_cfg/apps/payments/admin_interface/views/webhook_dashboard.py +37 -0
  28. django_cfg/apps/payments/apps.py +34 -9
  29. django_cfg/apps/payments/config/__init__.py +28 -51
  30. django_cfg/apps/payments/config/constance/__init__.py +22 -0
  31. django_cfg/apps/payments/config/constance/config_service.py +123 -0
  32. django_cfg/apps/payments/config/constance/fields.py +69 -0
  33. django_cfg/apps/payments/config/constance/settings.py +160 -0
  34. django_cfg/apps/payments/config/django_cfg_integration.py +202 -0
  35. django_cfg/apps/payments/config/helpers.py +130 -0
  36. django_cfg/apps/payments/management/__init__.py +1 -3
  37. django_cfg/apps/payments/management/commands/__init__.py +1 -3
  38. django_cfg/apps/payments/management/commands/manage_currencies.py +381 -0
  39. django_cfg/apps/payments/management/commands/manage_providers.py +408 -0
  40. django_cfg/apps/payments/middleware/__init__.py +3 -1
  41. django_cfg/apps/payments/middleware/api_access.py +329 -222
  42. django_cfg/apps/payments/middleware/rate_limiting.py +343 -163
  43. django_cfg/apps/payments/middleware/usage_tracking.py +250 -238
  44. django_cfg/apps/payments/migrations/0001_initial.py +708 -536
  45. django_cfg/apps/payments/models/__init__.py +16 -20
  46. django_cfg/apps/payments/models/api_keys.py +121 -43
  47. django_cfg/apps/payments/models/balance.py +150 -115
  48. django_cfg/apps/payments/models/base.py +68 -15
  49. django_cfg/apps/payments/models/currencies.py +207 -67
  50. django_cfg/apps/payments/models/managers/__init__.py +44 -0
  51. django_cfg/apps/payments/models/managers/api_key_managers.py +329 -0
  52. django_cfg/apps/payments/models/managers/balance_managers.py +599 -0
  53. django_cfg/apps/payments/models/managers/currency_managers.py +385 -0
  54. django_cfg/apps/payments/models/managers/payment_managers.py +511 -0
  55. django_cfg/apps/payments/models/managers/subscription_managers.py +641 -0
  56. django_cfg/apps/payments/models/payments.py +235 -284
  57. django_cfg/apps/payments/models/subscriptions.py +257 -177
  58. django_cfg/apps/payments/models/tariffs.py +147 -40
  59. django_cfg/apps/payments/services/__init__.py +209 -56
  60. django_cfg/apps/payments/services/cache/__init__.py +6 -6
  61. django_cfg/apps/payments/services/cache/{simple_cache.py → cache_service.py} +112 -12
  62. django_cfg/apps/payments/services/core/__init__.py +10 -6
  63. django_cfg/apps/payments/services/core/balance_service.py +435 -360
  64. django_cfg/apps/payments/services/core/base.py +166 -0
  65. django_cfg/apps/payments/services/core/currency_service.py +478 -0
  66. django_cfg/apps/payments/services/core/payment_service.py +344 -468
  67. django_cfg/apps/payments/services/core/subscription_service.py +425 -484
  68. django_cfg/apps/payments/services/core/webhook_service.py +410 -0
  69. django_cfg/apps/payments/services/integrations/__init__.py +29 -0
  70. django_cfg/apps/payments/services/integrations/ngrok_service.py +47 -0
  71. django_cfg/apps/payments/services/integrations/providers_config.py +107 -0
  72. django_cfg/apps/payments/services/providers/__init__.py +9 -14
  73. django_cfg/apps/payments/services/providers/base.py +232 -71
  74. django_cfg/apps/payments/services/providers/nowpayments.py +404 -219
  75. django_cfg/apps/payments/services/providers/registry.py +429 -80
  76. django_cfg/apps/payments/services/types/__init__.py +78 -0
  77. django_cfg/apps/payments/services/types/data.py +177 -0
  78. django_cfg/apps/payments/services/types/requests.py +150 -0
  79. django_cfg/apps/payments/services/types/responses.py +156 -0
  80. django_cfg/apps/payments/services/types/webhooks.py +232 -0
  81. django_cfg/apps/payments/signals/__init__.py +33 -8
  82. django_cfg/apps/payments/signals/api_key_signals.py +211 -130
  83. django_cfg/apps/payments/signals/balance_signals.py +174 -0
  84. django_cfg/apps/payments/signals/payment_signals.py +129 -98
  85. django_cfg/apps/payments/signals/subscription_signals.py +195 -143
  86. django_cfg/apps/payments/static/payments/css/components.css +380 -0
  87. django_cfg/apps/payments/static/payments/css/dashboard.css +188 -0
  88. django_cfg/apps/payments/static/payments/js/components.js +545 -0
  89. django_cfg/apps/payments/static/payments/js/utils.js +412 -0
  90. django_cfg/apps/payments/templatetags/__init__.py +1 -1
  91. django_cfg/apps/payments/templatetags/payment_tags.py +466 -0
  92. django_cfg/apps/payments/urls.py +46 -47
  93. django_cfg/apps/payments/urls_admin.py +49 -0
  94. django_cfg/apps/payments/views/api/__init__.py +101 -0
  95. django_cfg/apps/payments/views/api/api_keys.py +387 -0
  96. django_cfg/apps/payments/views/api/balances.py +381 -0
  97. django_cfg/apps/payments/views/api/base.py +298 -0
  98. django_cfg/apps/payments/views/api/currencies.py +402 -0
  99. django_cfg/apps/payments/views/api/payments.py +415 -0
  100. django_cfg/apps/payments/views/api/subscriptions.py +475 -0
  101. django_cfg/apps/payments/views/api/webhooks.py +476 -0
  102. django_cfg/apps/payments/views/serializers/__init__.py +99 -0
  103. django_cfg/apps/payments/views/serializers/api_keys.py +424 -0
  104. django_cfg/apps/payments/views/serializers/balances.py +300 -0
  105. django_cfg/apps/payments/views/serializers/currencies.py +335 -0
  106. django_cfg/apps/payments/views/serializers/payments.py +387 -0
  107. django_cfg/apps/payments/views/serializers/subscriptions.py +429 -0
  108. django_cfg/apps/payments/views/serializers/webhooks.py +137 -0
  109. django_cfg/apps/tasks/urls.py +0 -2
  110. django_cfg/apps/tasks/urls_admin.py +14 -0
  111. django_cfg/apps/urls.py +4 -4
  112. django_cfg/config.py +1 -1
  113. django_cfg/core/config.py +75 -4
  114. django_cfg/core/generation.py +25 -4
  115. django_cfg/core/integration/README.md +363 -0
  116. django_cfg/core/integration/__init__.py +47 -0
  117. django_cfg/core/integration/commands_collector.py +239 -0
  118. django_cfg/core/integration/display/__init__.py +15 -0
  119. django_cfg/core/integration/display/base.py +157 -0
  120. django_cfg/core/integration/display/ngrok.py +164 -0
  121. django_cfg/core/integration/display/startup.py +815 -0
  122. django_cfg/core/integration/url_integration.py +123 -0
  123. django_cfg/core/integration/version_checker.py +160 -0
  124. django_cfg/management/commands/auto_generate.py +4 -0
  125. django_cfg/management/commands/check_settings.py +6 -0
  126. django_cfg/management/commands/clear_constance.py +5 -2
  127. django_cfg/management/commands/create_token.py +6 -0
  128. django_cfg/management/commands/list_urls.py +6 -0
  129. django_cfg/management/commands/migrate_all.py +6 -0
  130. django_cfg/management/commands/migrator.py +3 -0
  131. django_cfg/management/commands/rundramatiq.py +6 -0
  132. django_cfg/management/commands/runserver_ngrok.py +51 -29
  133. django_cfg/management/commands/script.py +6 -0
  134. django_cfg/management/commands/show_config.py +12 -2
  135. django_cfg/management/commands/show_urls.py +4 -0
  136. django_cfg/management/commands/superuser.py +6 -0
  137. django_cfg/management/commands/task_clear.py +4 -1
  138. django_cfg/management/commands/task_status.py +3 -1
  139. django_cfg/management/commands/test_email.py +3 -0
  140. django_cfg/management/commands/test_telegram.py +6 -0
  141. django_cfg/management/commands/test_twilio.py +6 -0
  142. django_cfg/management/commands/tree.py +6 -0
  143. django_cfg/management/commands/validate_config.py +155 -149
  144. django_cfg/models/constance.py +31 -11
  145. django_cfg/models/payments.py +175 -498
  146. django_cfg/modules/django_currency/__init__.py +16 -11
  147. django_cfg/modules/django_currency/clients/__init__.py +4 -4
  148. django_cfg/modules/django_currency/clients/coinpaprika_client.py +289 -0
  149. django_cfg/modules/django_currency/clients/yahoo_client.py +157 -0
  150. django_cfg/modules/django_currency/core/__init__.py +1 -7
  151. django_cfg/modules/django_currency/core/converter.py +18 -23
  152. django_cfg/modules/django_currency/core/models.py +122 -11
  153. django_cfg/modules/django_currency/database/__init__.py +4 -4
  154. django_cfg/modules/django_currency/database/database_loader.py +190 -309
  155. django_cfg/modules/django_logger.py +160 -146
  156. django_cfg/modules/django_unfold/dashboard.py +65 -12
  157. django_cfg/registry/core.py +1 -0
  158. django_cfg/template_archive/django_sample.zip +0 -0
  159. django_cfg/templates/admin/components/action_grid.html +9 -9
  160. django_cfg/templates/admin/components/metric_card.html +5 -5
  161. django_cfg/templates/admin/components/status_badge.html +2 -2
  162. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +152 -24
  163. django_cfg/templates/admin/snippets/components/quick_actions.html +3 -3
  164. django_cfg/templates/admin/snippets/components/system_health.html +1 -1
  165. django_cfg/templates/admin/snippets/tabs/overview_tab.html +49 -52
  166. django_cfg/utils/smart_defaults.py +222 -571
  167. django_cfg/utils/toolkit.py +51 -11
  168. {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/METADATA +5 -4
  169. {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/RECORD +172 -182
  170. django_cfg/apps/payments/__init__.py +0 -8
  171. django_cfg/apps/payments/admin/tariffs_admin.py +0 -199
  172. django_cfg/apps/payments/config/module.py +0 -70
  173. django_cfg/apps/payments/config/providers.py +0 -105
  174. django_cfg/apps/payments/config/settings.py +0 -96
  175. django_cfg/apps/payments/config/utils.py +0 -52
  176. django_cfg/apps/payments/decorators.py +0 -291
  177. django_cfg/apps/payments/management/commands/README.md +0 -178
  178. django_cfg/apps/payments/management/commands/currency_stats.py +0 -323
  179. django_cfg/apps/payments/management/commands/populate_currencies.py +0 -246
  180. django_cfg/apps/payments/management/commands/update_currencies.py +0 -336
  181. django_cfg/apps/payments/managers/__init__.py +0 -22
  182. django_cfg/apps/payments/managers/api_key_manager.py +0 -35
  183. django_cfg/apps/payments/managers/balance_manager.py +0 -361
  184. django_cfg/apps/payments/managers/currency_manager.py +0 -83
  185. django_cfg/apps/payments/managers/payment_manager.py +0 -44
  186. django_cfg/apps/payments/managers/subscription_manager.py +0 -37
  187. django_cfg/apps/payments/managers/tariff_manager.py +0 -29
  188. django_cfg/apps/payments/models/events.py +0 -73
  189. django_cfg/apps/payments/serializers/__init__.py +0 -56
  190. django_cfg/apps/payments/serializers/api_keys.py +0 -51
  191. django_cfg/apps/payments/serializers/balance.py +0 -59
  192. django_cfg/apps/payments/serializers/currencies.py +0 -55
  193. django_cfg/apps/payments/serializers/payments.py +0 -62
  194. django_cfg/apps/payments/serializers/subscriptions.py +0 -71
  195. django_cfg/apps/payments/serializers/tariffs.py +0 -56
  196. django_cfg/apps/payments/services/billing/__init__.py +0 -8
  197. django_cfg/apps/payments/services/cache/base.py +0 -30
  198. django_cfg/apps/payments/services/core/fallback_service.py +0 -432
  199. django_cfg/apps/payments/services/internal_types.py +0 -297
  200. django_cfg/apps/payments/services/middleware/__init__.py +0 -8
  201. django_cfg/apps/payments/services/monitoring/__init__.py +0 -22
  202. django_cfg/apps/payments/services/monitoring/api_schemas.py +0 -222
  203. django_cfg/apps/payments/services/monitoring/provider_health.py +0 -372
  204. django_cfg/apps/payments/services/providers/cryptapi.py +0 -273
  205. django_cfg/apps/payments/services/providers/cryptomus.py +0 -311
  206. django_cfg/apps/payments/services/security/__init__.py +0 -34
  207. django_cfg/apps/payments/services/security/error_handler.py +0 -637
  208. django_cfg/apps/payments/services/security/payment_notifications.py +0 -342
  209. django_cfg/apps/payments/services/security/webhook_validator.py +0 -475
  210. django_cfg/apps/payments/services/validators/__init__.py +0 -8
  211. django_cfg/apps/payments/static/payments/css/payments.css +0 -340
  212. django_cfg/apps/payments/static/payments/js/notifications.js +0 -202
  213. django_cfg/apps/payments/static/payments/js/payment-utils.js +0 -318
  214. django_cfg/apps/payments/static/payments/js/theme.js +0 -86
  215. django_cfg/apps/payments/tasks/__init__.py +0 -12
  216. django_cfg/apps/payments/tasks/webhook_processing.py +0 -177
  217. django_cfg/apps/payments/templates/payments/base.html +0 -182
  218. django_cfg/apps/payments/templates/payments/components/payment_card.html +0 -201
  219. django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +0 -109
  220. django_cfg/apps/payments/templates/payments/components/progress_bar.html +0 -36
  221. django_cfg/apps/payments/templates/payments/components/provider_stats.html +0 -40
  222. django_cfg/apps/payments/templates/payments/components/status_badge.html +0 -27
  223. django_cfg/apps/payments/templates/payments/components/status_overview.html +0 -144
  224. django_cfg/apps/payments/templates/payments/dashboard.html +0 -346
  225. django_cfg/apps/payments/templatetags/payments_tags.py +0 -315
  226. django_cfg/apps/payments/urls_templates.py +0 -52
  227. django_cfg/apps/payments/utils/__init__.py +0 -45
  228. django_cfg/apps/payments/utils/billing_utils.py +0 -342
  229. django_cfg/apps/payments/utils/config_utils.py +0 -245
  230. django_cfg/apps/payments/utils/middleware_utils.py +0 -228
  231. django_cfg/apps/payments/utils/validation_utils.py +0 -94
  232. django_cfg/apps/payments/views/__init__.py +0 -62
  233. django_cfg/apps/payments/views/api_key_views.py +0 -164
  234. django_cfg/apps/payments/views/balance_views.py +0 -75
  235. django_cfg/apps/payments/views/currency_views.py +0 -111
  236. django_cfg/apps/payments/views/payment_views.py +0 -149
  237. django_cfg/apps/payments/views/subscription_views.py +0 -135
  238. django_cfg/apps/payments/views/tariff_views.py +0 -131
  239. django_cfg/apps/payments/views/templates/__init__.py +0 -25
  240. django_cfg/apps/payments/views/templates/ajax.py +0 -312
  241. django_cfg/apps/payments/views/templates/base.py +0 -204
  242. django_cfg/apps/payments/views/templates/dashboard.py +0 -60
  243. django_cfg/apps/payments/views/templates/payment_detail.py +0 -102
  244. django_cfg/apps/payments/views/templates/payment_management.py +0 -164
  245. django_cfg/apps/payments/views/templates/qr_code.py +0 -174
  246. django_cfg/apps/payments/views/templates/stats.py +0 -240
  247. django_cfg/apps/payments/views/templates/utils.py +0 -181
  248. django_cfg/apps/payments/views/webhook_views.py +0 -266
  249. django_cfg/apps/payments/viewsets.py +0 -65
  250. django_cfg/core/integration.py +0 -160
  251. django_cfg/modules/django_currency/clients/coingecko_client.py +0 -257
  252. django_cfg/modules/django_currency/clients/yfinance_client.py +0 -246
  253. django_cfg/template_archive/.gitignore +0 -1
  254. django_cfg/template_archive/__init__.py +0 -0
  255. django_cfg/urls.py +0 -33
  256. {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/WHEEL +0 -0
  257. {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/entry_points.txt +0 -0
  258. {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,30 +1,83 @@
1
1
  """
2
- Base model classes for the universal payments system.
2
+ Base models for the Universal Payment System v2.0.
3
+
4
+ Provides common functionality for all payment-related models.
3
5
  """
4
6
 
5
7
  import uuid
6
8
  from django.db import models
7
-
8
-
9
- class TimestampedModel(models.Model):
10
- """Base model with automatic timestamps."""
11
- created_at = models.DateTimeField(auto_now_add=True, db_index=True)
12
- updated_at = models.DateTimeField(auto_now=True)
13
-
14
- class Meta:
15
- abstract = True
9
+ from django.utils import timezone
16
10
 
17
11
 
18
12
  class UUIDTimestampedModel(models.Model):
19
- """Base model with UUID primary key and automatic timestamps."""
13
+ """
14
+ Abstract base model with UUID primary key and timestamps.
15
+
16
+ Provides:
17
+ - UUID primary key for security and scalability
18
+ - Created/updated timestamps with timezone awareness
19
+ - Common functionality for all payment models
20
+ """
21
+
20
22
  id = models.UUIDField(
21
23
  primary_key=True,
22
24
  default=uuid.uuid4,
23
25
  editable=False,
24
- help_text="Unique identifier"
26
+ help_text="Unique identifier for this record"
27
+ )
28
+
29
+ created_at = models.DateTimeField(
30
+ auto_now_add=True,
31
+ db_index=True,
32
+ help_text="When this record was created"
33
+ )
34
+
35
+ updated_at = models.DateTimeField(
36
+ auto_now=True,
37
+ help_text="When this record was last updated"
25
38
  )
26
- created_at = models.DateTimeField(auto_now_add=True, db_index=True)
27
- updated_at = models.DateTimeField(auto_now=True)
28
39
 
29
40
  class Meta:
30
- abstract = True
41
+ abstract = True
42
+ ordering = ['-created_at']
43
+
44
+ def __str__(self):
45
+ """String representation showing ID and creation time."""
46
+ return f"{self.__class__.__name__}({str(self.id)[:8]}...)"
47
+
48
+ def __repr__(self):
49
+ """Developer-friendly representation."""
50
+ return f"<{self.__class__.__name__}: {str(self.id)}>"
51
+
52
+ @property
53
+ def age_in_seconds(self) -> int:
54
+ """Get age of this record in seconds."""
55
+ return int((timezone.now() - self.created_at).total_seconds())
56
+
57
+ @property
58
+ def is_recent(self) -> bool:
59
+ """Check if record was created in the last hour."""
60
+ return self.age_in_seconds < 3600
61
+
62
+
63
+ class TimestampedModel(models.Model):
64
+ """
65
+ Abstract base model with auto-incrementing ID and timestamps.
66
+
67
+ Use this for models that don't need UUID (like configuration models).
68
+ """
69
+
70
+ created_at = models.DateTimeField(
71
+ auto_now_add=True,
72
+ db_index=True,
73
+ help_text="When this record was created"
74
+ )
75
+
76
+ updated_at = models.DateTimeField(
77
+ auto_now=True,
78
+ help_text="When this record was last updated"
79
+ )
80
+
81
+ class Meta:
82
+ abstract = True
83
+ ordering = ['-created_at']
@@ -1,13 +1,21 @@
1
1
  """
2
- Currency models for the universal payments system.
2
+ Currency models for the Universal Payment System v2.0.
3
+
4
+ Handles multi-provider currency support with integration to django_currency module.
3
5
  """
4
6
 
5
7
  from django.db import models
8
+ from django.core.validators import MinLengthValidator, MaxLengthValidator
9
+ from django.core.exceptions import ValidationError
6
10
  from .base import TimestampedModel
7
11
 
8
12
 
9
13
  class Currency(TimestampedModel):
10
- """Supported currencies for payments."""
14
+ """
15
+ Universal currency model supporting both fiat and crypto.
16
+
17
+ Integrates with django_currency module for rate conversion.
18
+ """
11
19
 
12
20
  class CurrencyType(models.TextChoices):
13
21
  FIAT = "fiat", "Fiat Currency"
@@ -16,123 +24,255 @@ class Currency(TimestampedModel):
16
24
  code = models.CharField(
17
25
  max_length=10,
18
26
  unique=True,
19
- help_text="Currency code (e.g., USD, BTC, ETH)"
27
+ validators=[MinLengthValidator(3), MaxLengthValidator(10)],
28
+ help_text="Currency code (e.g., BTC, USD, ETH)"
20
29
  )
30
+
21
31
  name = models.CharField(
22
32
  max_length=100,
23
- help_text="Full currency name"
24
- )
25
- symbol = models.CharField(
26
- max_length=10,
27
- help_text="Currency symbol (e.g., $, ₿, Ξ)"
33
+ help_text="Full currency name (e.g., Bitcoin, US Dollar)"
28
34
  )
35
+
29
36
  currency_type = models.CharField(
30
37
  max_length=10,
31
38
  choices=CurrencyType.choices,
32
39
  help_text="Type of currency"
33
40
  )
41
+
42
+ symbol = models.CharField(
43
+ max_length=10,
44
+ blank=True,
45
+ help_text="Currency symbol (e.g., $, ₿, Ξ)"
46
+ )
47
+
34
48
  decimal_places = models.PositiveSmallIntegerField(
35
- default=2,
49
+ default=8,
36
50
  help_text="Number of decimal places for this currency"
37
51
  )
52
+
38
53
  is_active = models.BooleanField(
39
54
  default=True,
40
- help_text="Whether this currency is active for payments"
41
- )
42
- min_payment_amount = models.FloatField(
43
- default=1.0,
44
- help_text="Minimum payment amount for this currency"
55
+ help_text="Whether this currency is available for payments"
45
56
  )
46
57
 
47
- # Exchange rate to USD (base currency)
48
- usd_rate = models.FloatField(
49
- default=1.0,
50
- help_text="Exchange rate to USD (1 unit of this currency = X USD)"
51
- )
52
- rate_updated_at = models.DateTimeField(
53
- null=True,
58
+ # Integration with django_currency
59
+ exchange_rate_source = models.CharField(
60
+ max_length=50,
54
61
  blank=True,
55
- help_text="When the exchange rate was last updated"
62
+ help_text="Source for exchange rates (auto-detected by django_currency)"
56
63
  )
57
64
 
58
- # Import and assign manager
59
- from ..managers import CurrencyManager
65
+ # Manager
66
+ from .managers.currency_managers import CurrencyManager
60
67
  objects = CurrencyManager()
61
68
 
62
69
  class Meta:
63
- db_table = 'payment_currencies'
64
- verbose_name = "Currency"
65
- verbose_name_plural = "Currencies"
70
+ db_table = 'payments_currencies'
71
+ verbose_name = 'Currency'
72
+ verbose_name_plural = 'Currencies'
73
+ ordering = ['currency_type', 'code']
66
74
  indexes = [
75
+ models.Index(fields=['currency_type', 'is_active']),
67
76
  models.Index(fields=['code']),
68
- models.Index(fields=['currency_type']),
69
- models.Index(fields=['is_active']),
70
77
  ]
71
- ordering = ['code']
72
78
 
73
79
  def __str__(self):
74
- return f"{self.code} - {self.name}"
80
+ return f"{self.code} ({self.name})"
75
81
 
76
- @property
77
- def is_fiat(self) -> bool:
78
- """Check if this is a fiat currency."""
79
- return self.currency_type == self.CurrencyType.FIAT
82
+ def clean(self):
83
+ """Validate currency data."""
84
+ if self.code:
85
+ self.code = self.code.upper()
86
+
87
+ # Validate decimal places based on currency type
88
+ if self.currency_type == self.CurrencyType.FIAT and self.decimal_places > 4:
89
+ raise ValidationError("Fiat currencies should not have more than 4 decimal places")
90
+
91
+ if self.currency_type == self.CurrencyType.CRYPTO and self.decimal_places > 18:
92
+ raise ValidationError("Crypto currencies should not have more than 18 decimal places")
80
93
 
81
94
  @property
82
95
  def is_crypto(self) -> bool:
83
96
  """Check if this is a cryptocurrency."""
84
97
  return self.currency_type == self.CurrencyType.CRYPTO
85
98
 
86
- def to_usd(self, amount: float) -> float:
87
- """Convert amount of this currency to USD."""
88
- return amount * self.usd_rate
99
+ @property
100
+ def is_fiat(self) -> bool:
101
+ """Check if this is a fiat currency."""
102
+ return self.currency_type == self.CurrencyType.FIAT
103
+
104
+
105
+ class Network(TimestampedModel):
106
+ """
107
+ Blockchain network model for cryptocurrency payments.
108
+
109
+ Represents different networks like Ethereum, Bitcoin, Polygon, etc.
110
+ """
111
+
112
+ name = models.CharField(
113
+ max_length=50,
114
+ unique=True,
115
+ help_text="Network name (e.g., Ethereum, Bitcoin, Polygon)"
116
+ )
117
+
118
+ code = models.CharField(
119
+ max_length=20,
120
+ unique=True,
121
+ help_text="Network code (e.g., ETH, BTC, MATIC)"
122
+ )
123
+
124
+ native_currency = models.ForeignKey(
125
+ Currency,
126
+ on_delete=models.PROTECT,
127
+ related_name='native_networks',
128
+ help_text="Native currency of this network"
129
+ )
130
+
131
+ block_explorer_url = models.URLField(
132
+ blank=True,
133
+ help_text="Block explorer URL template (use {tx} for transaction hash)"
134
+ )
89
135
 
90
- def from_usd(self, usd_amount: float) -> float:
91
- """Convert USD amount to this currency."""
92
- if self.usd_rate == 0:
93
- return 0
94
- return usd_amount / self.usd_rate
136
+ is_active = models.BooleanField(
137
+ default=True,
138
+ help_text="Whether this network is available for payments"
139
+ )
140
+
141
+ # Network-specific settings
142
+ confirmation_blocks = models.PositiveIntegerField(
143
+ default=1,
144
+ help_text="Number of confirmations required for this network"
145
+ )
146
+
147
+ average_block_time = models.PositiveIntegerField(
148
+ default=600, # 10 minutes in seconds
149
+ help_text="Average block time in seconds"
150
+ )
151
+
152
+ class Meta:
153
+ db_table = 'payments_networks'
154
+ verbose_name = 'Network'
155
+ verbose_name_plural = 'Networks'
156
+ ordering = ['name']
157
+ indexes = [
158
+ models.Index(fields=['is_active']),
159
+ models.Index(fields=['code']),
160
+ ]
161
+
162
+ def __str__(self):
163
+ return f"{self.name} ({self.code})"
164
+
165
+ def clean(self):
166
+ """Validate network data."""
167
+ if self.code:
168
+ self.code = self.code.upper()
169
+
170
+ @property
171
+ def estimated_confirmation_time(self) -> int:
172
+ """Estimated time for confirmations in seconds."""
173
+ return self.confirmation_blocks * self.average_block_time
95
174
 
96
175
 
97
- class CurrencyNetwork(TimestampedModel):
98
- """Networks/blockchains for cryptocurrencies."""
176
+ class ProviderCurrency(TimestampedModel):
177
+ """
178
+ Provider-specific currency configuration.
179
+
180
+ Maps currencies to specific providers and networks.
181
+ """
182
+
183
+ provider = models.CharField(
184
+ max_length=50,
185
+ help_text="Payment provider name (e.g., nowpayments)"
186
+ )
99
187
 
100
188
  currency = models.ForeignKey(
101
189
  Currency,
102
190
  on_delete=models.CASCADE,
103
- related_name='networks',
104
- help_text="Currency this network supports"
191
+ related_name='provider_configs'
105
192
  )
106
- network_name = models.CharField(
107
- max_length=50,
108
- help_text="Network name (e.g., mainnet, polygon, bsc)"
193
+
194
+ network = models.ForeignKey(
195
+ Network,
196
+ on_delete=models.CASCADE,
197
+ related_name='provider_configs',
198
+ null=True,
199
+ blank=True,
200
+ help_text="Network for crypto currencies (null for fiat)"
109
201
  )
110
- network_code = models.CharField(
202
+
203
+ # Provider-specific settings
204
+ provider_currency_code = models.CharField(
111
205
  max_length=20,
112
- help_text="Network code for API integration"
206
+ help_text="Currency code as used by the provider"
113
207
  )
114
- is_active = models.BooleanField(
208
+
209
+ min_amount = models.DecimalField(
210
+ max_digits=20,
211
+ decimal_places=8,
212
+ null=True,
213
+ blank=True,
214
+ help_text="Minimum payment amount for this currency"
215
+ )
216
+
217
+ max_amount = models.DecimalField(
218
+ max_digits=20,
219
+ decimal_places=8,
220
+ null=True,
221
+ blank=True,
222
+ help_text="Maximum payment amount for this currency"
223
+ )
224
+
225
+ is_enabled = models.BooleanField(
115
226
  default=True,
116
- help_text="Whether this network is active"
227
+ help_text="Whether this currency is enabled for this provider"
117
228
  )
118
- confirmation_blocks = models.PositiveIntegerField(
119
- default=1,
120
- help_text="Number of confirmations required"
229
+
230
+ # Fee configuration
231
+ fee_percentage = models.DecimalField(
232
+ max_digits=5,
233
+ decimal_places=4,
234
+ default=0,
235
+ help_text="Fee percentage (0.0250 = 2.5%)"
121
236
  )
122
237
 
123
- # Import and assign manager
124
- from ..managers import CurrencyNetworkManager
125
- objects = CurrencyNetworkManager()
238
+ fixed_fee = models.DecimalField(
239
+ max_digits=20,
240
+ decimal_places=8,
241
+ default=0,
242
+ help_text="Fixed fee amount in this currency"
243
+ )
126
244
 
127
245
  class Meta:
128
- db_table = 'payment_currency_networks'
129
- verbose_name = "Currency Network"
130
- verbose_name_plural = "Currency Networks"
131
- unique_together = [['currency', 'network_code']]
246
+ db_table = 'payments_provider_currencies'
247
+ verbose_name = 'Provider Currency'
248
+ verbose_name_plural = 'Provider Currencies'
249
+ unique_together = [['provider', 'currency', 'network']]
250
+ ordering = ['provider', 'currency__code']
132
251
  indexes = [
133
- models.Index(fields=['currency', 'is_active']),
134
- models.Index(fields=['network_code']),
252
+ models.Index(fields=['provider', 'is_enabled']),
253
+ models.Index(fields=['currency', 'is_enabled']),
135
254
  ]
136
255
 
137
256
  def __str__(self):
138
- return f"{self.currency.code} - {self.network_name}"
257
+ network_part = f" ({self.network.code})" if self.network else ""
258
+ return f"{self.provider}: {self.currency.code}{network_part}"
259
+
260
+ def clean(self):
261
+ """Validate provider currency configuration."""
262
+ # Crypto currencies must have a network
263
+ if self.currency and self.currency.is_crypto and not self.network:
264
+ raise ValidationError("Crypto currencies must specify a network")
265
+
266
+ # Fiat currencies should not have a network
267
+ if self.currency and self.currency.is_fiat and self.network:
268
+ raise ValidationError("Fiat currencies should not specify a network")
269
+
270
+ # Validate amount limits
271
+ if self.min_amount and self.max_amount and self.min_amount > self.max_amount:
272
+ raise ValidationError("Minimum amount cannot be greater than maximum amount")
273
+
274
+ @property
275
+ def display_name(self) -> str:
276
+ """Human-readable display name."""
277
+ network_part = f" on {self.network.name}" if self.network else ""
278
+ return f"{self.currency.name}{network_part}"
@@ -0,0 +1,44 @@
1
+ """
2
+ Django ORM Managers for the Universal Payment System v2.0.
3
+
4
+ Optimized managers and querysets for all payment-related models.
5
+ Follows the data typing requirements: Django ORM for database layer.
6
+ """
7
+
8
+ # Payment managers
9
+ from .payment_managers import PaymentQuerySet, PaymentManager
10
+
11
+ # Balance managers
12
+ from .balance_managers import UserBalanceManager, TransactionQuerySet, TransactionManager
13
+
14
+ # Subscription managers
15
+ from .subscription_managers import SubscriptionQuerySet, SubscriptionManager
16
+
17
+ # Currency managers
18
+ from .currency_managers import CurrencyQuerySet, CurrencyManager
19
+
20
+ # API Key managers
21
+ from .api_key_managers import APIKeyQuerySet, APIKeyManager
22
+
23
+ __all__ = [
24
+ # Payment managers
25
+ 'PaymentQuerySet',
26
+ 'PaymentManager',
27
+
28
+ # Balance managers
29
+ 'UserBalanceManager',
30
+ 'TransactionQuerySet',
31
+ 'TransactionManager',
32
+
33
+ # Subscription managers
34
+ 'SubscriptionQuerySet',
35
+ 'SubscriptionManager',
36
+
37
+ # Currency managers
38
+ 'CurrencyQuerySet',
39
+ 'CurrencyManager',
40
+
41
+ # API Key managers
42
+ 'APIKeyQuerySet',
43
+ 'APIKeyManager',
44
+ ]