django-cfg 1.2.31__py3-none-any.whl → 1.3.3__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 (264) 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 -10
  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 +526 -222
  9. django_cfg/apps/payments/admin/filters.py +306 -199
  10. django_cfg/apps/payments/admin/payments_admin.py +465 -70
  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/cleanup_expired_data.py +419 -0
  39. django_cfg/apps/payments/management/commands/currency_stats.py +297 -225
  40. django_cfg/apps/payments/management/commands/manage_currencies.py +303 -151
  41. django_cfg/apps/payments/management/commands/manage_providers.py +333 -160
  42. django_cfg/apps/payments/management/commands/process_pending_payments.py +357 -0
  43. django_cfg/apps/payments/management/commands/test_providers.py +434 -0
  44. django_cfg/apps/payments/middleware/__init__.py +3 -1
  45. django_cfg/apps/payments/middleware/api_access.py +329 -222
  46. django_cfg/apps/payments/middleware/rate_limiting.py +342 -152
  47. django_cfg/apps/payments/middleware/usage_tracking.py +249 -240
  48. django_cfg/apps/payments/migrations/0001_initial.py +708 -536
  49. django_cfg/apps/payments/models/__init__.py +13 -18
  50. django_cfg/apps/payments/models/api_keys.py +121 -43
  51. django_cfg/apps/payments/models/balance.py +153 -115
  52. django_cfg/apps/payments/models/base.py +68 -15
  53. django_cfg/apps/payments/models/currencies.py +172 -148
  54. django_cfg/apps/payments/models/managers/__init__.py +44 -0
  55. django_cfg/apps/payments/models/managers/api_key_managers.py +329 -0
  56. django_cfg/apps/payments/models/managers/balance_managers.py +599 -0
  57. django_cfg/apps/payments/models/managers/currency_managers.py +385 -0
  58. django_cfg/apps/payments/models/managers/payment_managers.py +511 -0
  59. django_cfg/apps/payments/models/managers/subscription_managers.py +641 -0
  60. django_cfg/apps/payments/models/payments.py +235 -285
  61. django_cfg/apps/payments/models/subscriptions.py +257 -177
  62. django_cfg/apps/payments/models/tariffs.py +147 -40
  63. django_cfg/apps/payments/services/__init__.py +209 -56
  64. django_cfg/apps/payments/services/cache/__init__.py +6 -6
  65. django_cfg/apps/payments/services/cache_service/__init__.py +143 -0
  66. django_cfg/apps/payments/services/cache_service/api_key_cache.py +37 -0
  67. django_cfg/apps/payments/services/{cache/base.py → cache_service/interfaces.py} +3 -1
  68. django_cfg/apps/payments/services/cache_service/keys.py +49 -0
  69. django_cfg/apps/payments/services/cache_service/rate_limit_cache.py +47 -0
  70. django_cfg/apps/payments/services/cache_service/simple_cache.py +101 -0
  71. django_cfg/apps/payments/services/core/__init__.py +10 -6
  72. django_cfg/apps/payments/services/core/balance_service.py +435 -360
  73. django_cfg/apps/payments/services/core/base.py +166 -0
  74. django_cfg/apps/payments/services/core/currency_service.py +478 -0
  75. django_cfg/apps/payments/services/core/payment_service.py +371 -465
  76. django_cfg/apps/payments/services/core/subscription_service.py +425 -481
  77. django_cfg/apps/payments/services/core/webhook_service.py +410 -0
  78. django_cfg/apps/payments/services/integrations/__init__.py +29 -0
  79. django_cfg/apps/payments/services/integrations/ngrok_service.py +47 -0
  80. django_cfg/apps/payments/services/integrations/providers_config.py +107 -0
  81. django_cfg/apps/payments/services/providers/__init__.py +9 -14
  82. django_cfg/apps/payments/services/providers/base.py +234 -174
  83. django_cfg/apps/payments/services/providers/nowpayments.py +478 -0
  84. django_cfg/apps/payments/services/providers/registry.py +367 -301
  85. django_cfg/apps/payments/services/types/__init__.py +78 -0
  86. django_cfg/apps/payments/services/types/data.py +177 -0
  87. django_cfg/apps/payments/services/types/requests.py +150 -0
  88. django_cfg/apps/payments/services/types/responses.py +156 -0
  89. django_cfg/apps/payments/services/types/webhooks.py +232 -0
  90. django_cfg/apps/payments/signals/__init__.py +33 -8
  91. django_cfg/apps/payments/signals/api_key_signals.py +210 -129
  92. django_cfg/apps/payments/signals/balance_signals.py +174 -0
  93. django_cfg/apps/payments/signals/payment_signals.py +128 -103
  94. django_cfg/apps/payments/signals/subscription_signals.py +194 -142
  95. django_cfg/apps/payments/static/payments/css/components.css +380 -0
  96. django_cfg/apps/payments/static/payments/css/dashboard.css +188 -0
  97. django_cfg/apps/payments/static/payments/js/components.js +545 -0
  98. django_cfg/apps/payments/static/payments/js/utils.js +412 -0
  99. django_cfg/apps/payments/templatetags/__init__.py +1 -1
  100. django_cfg/apps/payments/templatetags/payment_tags.py +466 -0
  101. django_cfg/apps/payments/urls.py +45 -48
  102. django_cfg/apps/payments/urls_admin.py +33 -42
  103. django_cfg/apps/payments/views/api/__init__.py +101 -0
  104. django_cfg/apps/payments/views/api/api_keys.py +387 -0
  105. django_cfg/apps/payments/views/api/balances.py +381 -0
  106. django_cfg/apps/payments/views/api/base.py +298 -0
  107. django_cfg/apps/payments/views/api/currencies.py +402 -0
  108. django_cfg/apps/payments/views/api/payments.py +415 -0
  109. django_cfg/apps/payments/views/api/subscriptions.py +475 -0
  110. django_cfg/apps/payments/views/api/webhooks.py +476 -0
  111. django_cfg/apps/payments/views/serializers/__init__.py +99 -0
  112. django_cfg/apps/payments/views/serializers/api_keys.py +424 -0
  113. django_cfg/apps/payments/views/serializers/balances.py +300 -0
  114. django_cfg/apps/payments/views/serializers/currencies.py +335 -0
  115. django_cfg/apps/payments/views/serializers/payments.py +387 -0
  116. django_cfg/apps/payments/views/serializers/subscriptions.py +429 -0
  117. django_cfg/apps/payments/views/serializers/webhooks.py +137 -0
  118. django_cfg/config.py +1 -1
  119. django_cfg/core/config.py +40 -4
  120. django_cfg/core/generation.py +25 -4
  121. django_cfg/core/integration/README.md +363 -0
  122. django_cfg/core/integration/__init__.py +47 -0
  123. django_cfg/core/integration/commands_collector.py +239 -0
  124. django_cfg/core/integration/display/__init__.py +15 -0
  125. django_cfg/core/integration/display/base.py +157 -0
  126. django_cfg/core/integration/display/ngrok.py +164 -0
  127. django_cfg/core/integration/display/startup.py +815 -0
  128. django_cfg/core/integration/url_integration.py +123 -0
  129. django_cfg/core/integration/version_checker.py +160 -0
  130. django_cfg/management/commands/auto_generate.py +4 -0
  131. django_cfg/management/commands/check_settings.py +6 -0
  132. django_cfg/management/commands/clear_constance.py +5 -2
  133. django_cfg/management/commands/create_token.py +6 -0
  134. django_cfg/management/commands/list_urls.py +6 -0
  135. django_cfg/management/commands/migrate_all.py +6 -0
  136. django_cfg/management/commands/migrator.py +3 -0
  137. django_cfg/management/commands/rundramatiq.py +6 -0
  138. django_cfg/management/commands/runserver_ngrok.py +51 -29
  139. django_cfg/management/commands/script.py +6 -0
  140. django_cfg/management/commands/show_config.py +12 -2
  141. django_cfg/management/commands/show_urls.py +4 -0
  142. django_cfg/management/commands/superuser.py +6 -0
  143. django_cfg/management/commands/task_clear.py +4 -1
  144. django_cfg/management/commands/task_status.py +3 -1
  145. django_cfg/management/commands/test_email.py +3 -0
  146. django_cfg/management/commands/test_telegram.py +6 -0
  147. django_cfg/management/commands/test_twilio.py +6 -0
  148. django_cfg/management/commands/tree.py +6 -0
  149. django_cfg/management/commands/validate_config.py +155 -149
  150. django_cfg/models/constance.py +31 -11
  151. django_cfg/models/payments.py +175 -492
  152. django_cfg/modules/django_logger.py +160 -146
  153. django_cfg/modules/django_unfold/dashboard.py +64 -16
  154. django_cfg/registry/core.py +1 -0
  155. django_cfg/template_archive/django_sample.zip +0 -0
  156. django_cfg/utils/smart_defaults.py +227 -570
  157. django_cfg/utils/toolkit.py +51 -11
  158. {django_cfg-1.2.31.dist-info → django_cfg-1.3.3.dist-info}/METADATA +4 -1
  159. {django_cfg-1.2.31.dist-info → django_cfg-1.3.3.dist-info}/RECORD +162 -185
  160. django_cfg/apps/payments/__init__.py +0 -8
  161. django_cfg/apps/payments/admin/tariffs_admin.py +0 -199
  162. django_cfg/apps/payments/config/module.py +0 -70
  163. django_cfg/apps/payments/config/providers.py +0 -105
  164. django_cfg/apps/payments/config/settings.py +0 -96
  165. django_cfg/apps/payments/config/utils.py +0 -52
  166. django_cfg/apps/payments/decorators.py +0 -291
  167. django_cfg/apps/payments/management/commands/README.md +0 -146
  168. django_cfg/apps/payments/managers/__init__.py +0 -23
  169. django_cfg/apps/payments/managers/api_key_manager.py +0 -35
  170. django_cfg/apps/payments/managers/balance_manager.py +0 -361
  171. django_cfg/apps/payments/managers/currency_manager.py +0 -306
  172. django_cfg/apps/payments/managers/payment_manager.py +0 -192
  173. django_cfg/apps/payments/managers/subscription_manager.py +0 -37
  174. django_cfg/apps/payments/managers/tariff_manager.py +0 -29
  175. django_cfg/apps/payments/migrations/0002_network_providercurrency_and_more.py +0 -241
  176. django_cfg/apps/payments/migrations/0003_add_usd_rate_cache.py +0 -30
  177. django_cfg/apps/payments/models/events.py +0 -73
  178. django_cfg/apps/payments/serializers/__init__.py +0 -57
  179. django_cfg/apps/payments/serializers/api_keys.py +0 -51
  180. django_cfg/apps/payments/serializers/balance.py +0 -59
  181. django_cfg/apps/payments/serializers/currencies.py +0 -63
  182. django_cfg/apps/payments/serializers/payments.py +0 -62
  183. django_cfg/apps/payments/serializers/subscriptions.py +0 -71
  184. django_cfg/apps/payments/serializers/tariffs.py +0 -56
  185. django_cfg/apps/payments/services/billing/__init__.py +0 -8
  186. django_cfg/apps/payments/services/cache/simple_cache.py +0 -135
  187. django_cfg/apps/payments/services/core/fallback_service.py +0 -432
  188. django_cfg/apps/payments/services/internal_types.py +0 -461
  189. django_cfg/apps/payments/services/middleware/__init__.py +0 -8
  190. django_cfg/apps/payments/services/monitoring/__init__.py +0 -22
  191. django_cfg/apps/payments/services/monitoring/api_schemas.py +0 -76
  192. django_cfg/apps/payments/services/monitoring/provider_health.py +0 -372
  193. django_cfg/apps/payments/services/providers/cryptapi/__init__.py +0 -4
  194. django_cfg/apps/payments/services/providers/cryptapi/config.py +0 -8
  195. django_cfg/apps/payments/services/providers/cryptapi/models.py +0 -192
  196. django_cfg/apps/payments/services/providers/cryptapi/provider.py +0 -439
  197. django_cfg/apps/payments/services/providers/cryptomus/__init__.py +0 -4
  198. django_cfg/apps/payments/services/providers/cryptomus/models.py +0 -176
  199. django_cfg/apps/payments/services/providers/cryptomus/provider.py +0 -429
  200. django_cfg/apps/payments/services/providers/cryptomus/provider_v2.py +0 -564
  201. django_cfg/apps/payments/services/providers/models/__init__.py +0 -34
  202. django_cfg/apps/payments/services/providers/models/currencies.py +0 -190
  203. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +0 -4
  204. django_cfg/apps/payments/services/providers/nowpayments/models.py +0 -196
  205. django_cfg/apps/payments/services/providers/nowpayments/provider.py +0 -380
  206. django_cfg/apps/payments/services/providers/stripe/__init__.py +0 -4
  207. django_cfg/apps/payments/services/providers/stripe/models.py +0 -184
  208. django_cfg/apps/payments/services/providers/stripe/provider.py +0 -109
  209. django_cfg/apps/payments/services/security/__init__.py +0 -34
  210. django_cfg/apps/payments/services/security/error_handler.py +0 -635
  211. django_cfg/apps/payments/services/security/payment_notifications.py +0 -342
  212. django_cfg/apps/payments/services/security/webhook_validator.py +0 -474
  213. django_cfg/apps/payments/static/payments/css/payments.css +0 -340
  214. django_cfg/apps/payments/static/payments/js/notifications.js +0 -202
  215. django_cfg/apps/payments/static/payments/js/payment-utils.js +0 -318
  216. django_cfg/apps/payments/static/payments/js/theme.js +0 -86
  217. django_cfg/apps/payments/tasks/__init__.py +0 -12
  218. django_cfg/apps/payments/tasks/webhook_processing.py +0 -177
  219. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +0 -50
  220. django_cfg/apps/payments/templates/payments/base.html +0 -182
  221. django_cfg/apps/payments/templates/payments/components/payment_card.html +0 -201
  222. django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +0 -109
  223. django_cfg/apps/payments/templates/payments/components/progress_bar.html +0 -43
  224. django_cfg/apps/payments/templates/payments/components/provider_stats.html +0 -40
  225. django_cfg/apps/payments/templates/payments/components/status_badge.html +0 -34
  226. django_cfg/apps/payments/templates/payments/components/status_overview.html +0 -148
  227. django_cfg/apps/payments/templates/payments/dashboard.html +0 -258
  228. django_cfg/apps/payments/templates/payments/dashboard_simple_test.html +0 -35
  229. django_cfg/apps/payments/templates/payments/payment_create.html +0 -579
  230. django_cfg/apps/payments/templates/payments/payment_detail.html +0 -373
  231. django_cfg/apps/payments/templates/payments/payment_list.html +0 -354
  232. django_cfg/apps/payments/templates/payments/stats.html +0 -261
  233. django_cfg/apps/payments/templates/payments/test.html +0 -213
  234. django_cfg/apps/payments/templatetags/payments_tags.py +0 -315
  235. django_cfg/apps/payments/utils/__init__.py +0 -43
  236. django_cfg/apps/payments/utils/billing_utils.py +0 -342
  237. django_cfg/apps/payments/utils/config_utils.py +0 -239
  238. django_cfg/apps/payments/utils/middleware_utils.py +0 -228
  239. django_cfg/apps/payments/utils/validation_utils.py +0 -94
  240. django_cfg/apps/payments/views/__init__.py +0 -63
  241. django_cfg/apps/payments/views/api_key_views.py +0 -164
  242. django_cfg/apps/payments/views/balance_views.py +0 -75
  243. django_cfg/apps/payments/views/currency_views.py +0 -122
  244. django_cfg/apps/payments/views/payment_views.py +0 -149
  245. django_cfg/apps/payments/views/subscription_views.py +0 -135
  246. django_cfg/apps/payments/views/tariff_views.py +0 -131
  247. django_cfg/apps/payments/views/templates/__init__.py +0 -25
  248. django_cfg/apps/payments/views/templates/ajax.py +0 -451
  249. django_cfg/apps/payments/views/templates/base.py +0 -212
  250. django_cfg/apps/payments/views/templates/dashboard.py +0 -60
  251. django_cfg/apps/payments/views/templates/payment_detail.py +0 -102
  252. django_cfg/apps/payments/views/templates/payment_management.py +0 -158
  253. django_cfg/apps/payments/views/templates/qr_code.py +0 -174
  254. django_cfg/apps/payments/views/templates/stats.py +0 -244
  255. django_cfg/apps/payments/views/templates/utils.py +0 -181
  256. django_cfg/apps/payments/views/webhook_views.py +0 -266
  257. django_cfg/apps/payments/viewsets.py +0 -66
  258. django_cfg/core/integration.py +0 -160
  259. django_cfg/template_archive/.gitignore +0 -1
  260. django_cfg/template_archive/__init__.py +0 -0
  261. django_cfg/urls.py +0 -33
  262. {django_cfg-1.2.31.dist-info → django_cfg-1.3.3.dist-info}/WHEEL +0 -0
  263. {django_cfg-1.2.31.dist-info → django_cfg-1.3.3.dist-info}/entry_points.txt +0 -0
  264. {django_cfg-1.2.31.dist-info → django_cfg-1.3.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,291 +0,0 @@
1
- """
2
- Decorators for API access control and endpoint registration.
3
- """
4
-
5
- import functools
6
- from django_cfg.modules.django_logger import get_logger
7
- from typing import Optional, List, Callable, Any
8
- from django.http import JsonResponse
9
- from django.conf import settings
10
- from django.utils import timezone
11
- from .models import EndpointGroup, Subscription
12
-
13
- logger = get_logger("decorators")
14
-
15
-
16
- def require_api_key(func: Callable) -> Callable:
17
- """
18
- Decorator to require valid API key for function-based views.
19
- Works with APIAccessMiddleware.
20
- """
21
- @functools.wraps(func)
22
- def wrapper(request, *args, **kwargs):
23
- if not hasattr(request, 'payment_api_key'):
24
- return JsonResponse({
25
- 'error': {
26
- 'code': 'MISSING_API_KEY',
27
- 'message': 'Valid API key required',
28
- 'timestamp': timezone.now().isoformat(),
29
- }
30
- }, status=401)
31
-
32
- return func(request, *args, **kwargs)
33
-
34
- return wrapper
35
-
36
-
37
- def require_subscription(endpoint_group_name: str):
38
- """
39
- Decorator to require active subscription for specific endpoint group.
40
-
41
- Args:
42
- endpoint_group_name: Name of the endpoint group to check
43
- """
44
- def decorator(func: Callable) -> Callable:
45
- @functools.wraps(func)
46
- def wrapper(request, *args, **kwargs):
47
- # Check if middleware already validated subscription
48
- if hasattr(request, 'payment_subscription'):
49
- subscription = request.payment_subscription
50
- if subscription.endpoint_group.name == endpoint_group_name:
51
- return func(request, *args, **kwargs)
52
-
53
- # If not validated by middleware, check manually
54
- if not hasattr(request, 'payment_api_key'):
55
- return JsonResponse({
56
- 'error': {
57
- 'code': 'MISSING_API_KEY',
58
- 'message': 'Valid API key required',
59
- 'timestamp': timezone.now().isoformat(),
60
- }
61
- }, status=401)
62
-
63
- try:
64
- endpoint_group = EndpointGroup.objects.get(
65
- name=endpoint_group_name,
66
- is_active=True
67
- )
68
-
69
- subscription = Subscription.objects.filter(
70
- user=request.payment_api_key.user,
71
- endpoint_group=endpoint_group,
72
- status='active',
73
- expires_at__gt=timezone.now()
74
- ).first()
75
-
76
- if not subscription:
77
- return JsonResponse({
78
- 'error': {
79
- 'code': 'NO_SUBSCRIPTION',
80
- 'message': f'Active subscription required for {endpoint_group.display_name}',
81
- 'timestamp': timezone.now().isoformat(),
82
- }
83
- }, status=403)
84
-
85
- # Store subscription in request
86
- request.payment_subscription = subscription
87
-
88
- return func(request, *args, **kwargs)
89
-
90
- except EndpointGroup.DoesNotExist:
91
- logger.error(f"Endpoint group '{endpoint_group_name}' not found")
92
- return JsonResponse({
93
- 'error': {
94
- 'code': 'INVALID_ENDPOINT_GROUP',
95
- 'message': 'Invalid endpoint group',
96
- 'timestamp': timezone.now().isoformat(),
97
- }
98
- }, status=500)
99
-
100
- return wrapper
101
- return decorator
102
-
103
-
104
- def require_tier(minimum_tier: str):
105
- """
106
- Decorator to require minimum subscription tier.
107
-
108
- Args:
109
- minimum_tier: Minimum required tier (basic, premium, enterprise)
110
- """
111
- tier_hierarchy = {
112
- 'basic': 1,
113
- 'premium': 2,
114
- 'enterprise': 3,
115
- }
116
-
117
- def decorator(func: Callable) -> Callable:
118
- @functools.wraps(func)
119
- def wrapper(request, *args, **kwargs):
120
- if not hasattr(request, 'payment_subscription'):
121
- return JsonResponse({
122
- 'error': {
123
- 'code': 'NO_SUBSCRIPTION',
124
- 'message': 'Active subscription required',
125
- 'timestamp': timezone.now().isoformat(),
126
- }
127
- }, status=403)
128
-
129
- subscription = request.payment_subscription
130
- current_tier_level = tier_hierarchy.get(subscription.tier, 0)
131
- required_tier_level = tier_hierarchy.get(minimum_tier, 999)
132
-
133
- if current_tier_level < required_tier_level:
134
- return JsonResponse({
135
- 'error': {
136
- 'code': 'INSUFFICIENT_TIER',
137
- 'message': f'Tier {minimum_tier} or higher required',
138
- 'current_tier': subscription.tier,
139
- 'required_tier': minimum_tier,
140
- 'timestamp': timezone.now().isoformat(),
141
- }
142
- }, status=403)
143
-
144
- return func(request, *args, **kwargs)
145
-
146
- return wrapper
147
- return decorator
148
-
149
-
150
- def track_usage(cost_per_request: float = 0.0):
151
- """
152
- Decorator to track API usage and deduct costs.
153
-
154
- Args:
155
- cost_per_request: Cost to deduct per successful request
156
- """
157
- def decorator(func: Callable) -> Callable:
158
- @functools.wraps(func)
159
- def wrapper(request, *args, **kwargs):
160
- # Execute the function
161
- response = func(request, *args, **kwargs)
162
-
163
- # Track usage if successful and we have subscription
164
- if (hasattr(request, 'payment_subscription') and
165
- hasattr(response, 'status_code') and
166
- 200 <= response.status_code < 300 and
167
- cost_per_request > 0):
168
-
169
- try:
170
- from .models import Transaction
171
-
172
- subscription = request.payment_subscription
173
-
174
- # Create billing transaction
175
- Transaction.objects.create(
176
- user=subscription.user,
177
- subscription=subscription,
178
- transaction_type='debit',
179
- amount_usd=-cost_per_request,
180
- description=f"API usage: {request.method} {request.path}",
181
- metadata={
182
- 'endpoint': request.path,
183
- 'method': request.method,
184
- 'cost_per_request': cost_per_request,
185
- }
186
- )
187
-
188
- except Exception as e:
189
- logger.error(f"Error tracking usage: {e}")
190
-
191
- return response
192
-
193
- return wrapper
194
- return decorator
195
-
196
-
197
- def register_endpoint(endpoint_group_name: str,
198
- display_name: Optional[str] = None,
199
- description: Optional[str] = None,
200
- require_api_key: bool = True):
201
- """
202
- Decorator to automatically register endpoint with the system.
203
- This creates or updates EndpointGroup records.
204
-
205
- Args:
206
- endpoint_group_name: Internal name for the endpoint group
207
- display_name: Human-readable name
208
- description: Description of the endpoint functionality
209
- require_api_key: Whether this endpoint requires API key
210
- """
211
- def decorator(func: Callable) -> Callable:
212
- @functools.wraps(func)
213
- def wrapper(*args, **kwargs):
214
- # Auto-register endpoint group if it doesn't exist
215
- try:
216
- endpoint_group, created = EndpointGroup.objects.get_or_create(
217
- name=endpoint_group_name,
218
- defaults={
219
- 'display_name': display_name or endpoint_group_name.replace('_', ' ').title(),
220
- 'description': description or f'Auto-registered endpoint group: {endpoint_group_name}',
221
- 'require_api_key': require_api_key,
222
- 'is_active': True,
223
- }
224
- )
225
-
226
- if created:
227
- logger.info(f"Auto-registered endpoint group: {endpoint_group_name}")
228
-
229
- except Exception as e:
230
- logger.error(f"Error auto-registering endpoint group: {e}")
231
-
232
- return func(*args, **kwargs)
233
-
234
- return wrapper
235
- return decorator
236
-
237
-
238
- def check_usage_limit(func: Callable) -> Callable:
239
- """
240
- Decorator to check subscription usage limits before processing request.
241
- """
242
- @functools.wraps(func)
243
- def wrapper(request, *args, **kwargs):
244
- if hasattr(request, 'payment_subscription'):
245
- subscription = request.payment_subscription
246
-
247
- # Check if usage limit exceeded
248
- if (subscription.usage_limit > 0 and
249
- subscription.usage_current >= subscription.usage_limit):
250
-
251
- return JsonResponse({
252
- 'error': {
253
- 'code': 'USAGE_EXCEEDED',
254
- 'message': 'Monthly usage limit exceeded',
255
- 'current_usage': subscription.usage_current,
256
- 'usage_limit': subscription.usage_limit,
257
- 'reset_date': subscription.next_billing.isoformat() if subscription.next_billing else None,
258
- 'timestamp': timezone.now().isoformat(),
259
- }
260
- }, status=429)
261
-
262
- return func(request, *args, **kwargs)
263
-
264
- return wrapper
265
-
266
-
267
- # Utility decorator combinations
268
- def api_endpoint(endpoint_group_name: str,
269
- minimum_tier: str = 'basic',
270
- cost_per_request: float = 0.0):
271
- """
272
- Combination decorator for typical API endpoint protection.
273
-
274
- Args:
275
- endpoint_group_name: Name of the endpoint group
276
- minimum_tier: Minimum subscription tier required
277
- cost_per_request: Cost to charge per successful request
278
- """
279
- def decorator(func: Callable) -> Callable:
280
- # Apply decorators in reverse order (they wrap from inside out)
281
- decorated_func = func
282
- decorated_func = track_usage(cost_per_request)(decorated_func)
283
- decorated_func = check_usage_limit(decorated_func)
284
- decorated_func = require_tier(minimum_tier)(decorated_func)
285
- decorated_func = require_subscription(endpoint_group_name)(decorated_func)
286
- decorated_func = require_api_key(decorated_func)
287
- decorated_func = register_endpoint(endpoint_group_name)(decorated_func)
288
-
289
- return decorated_func
290
-
291
- return decorator
@@ -1,146 +0,0 @@
1
- # Payment Management Commands
2
-
3
- Optimized management commands for Django CFG payments system.
4
-
5
- ## Available Commands
6
-
7
- ### 1. `manage_currencies` - Currency and Rate Management
8
-
9
- Universal command for all currency-related operations.
10
-
11
- #### Usage Examples:
12
-
13
- ```bash
14
- # Update USD exchange rates only
15
- python manage.py manage_currencies --rates-only
16
-
17
- # Update specific currency rate
18
- python manage.py manage_currencies --rates-only --currency ETH
19
-
20
- # Initial population (empty database)
21
- python manage.py manage_currencies --populate
22
-
23
- # Full update with fresh rates
24
- python manage.py manage_currencies --force
25
-
26
- # Dry run to see what would be updated
27
- python manage.py manage_currencies --dry-run
28
-
29
- # Limit number of currencies processed
30
- python manage.py manage_currencies --populate --max-crypto 100 --max-fiat 20
31
- ```
32
-
33
- #### Options:
34
- - `--populate` - Initial population mode for empty database
35
- - `--rates-only` - Only update USD exchange rates
36
- - `--currency CODE` - Update specific currency (e.g., BTC, ETH)
37
- - `--force` - Force refresh all data even if fresh
38
- - `--dry-run` - Show what would be done without changes
39
- - `--max-crypto N` - Limit crypto currencies (default: 200)
40
- - `--max-fiat N` - Limit fiat currencies (default: 50)
41
-
42
- ---
43
-
44
- ### 2. `manage_providers` - Payment Provider Management
45
-
46
- Universal command for all provider-related operations.
47
-
48
- #### Usage Examples:
49
-
50
- ```bash
51
- # Sync all active providers
52
- python manage.py manage_providers
53
-
54
- # Sync specific provider
55
- python manage.py manage_providers --provider nowpayments
56
-
57
- # Sync multiple providers
58
- python manage.py manage_providers --provider nowpayments,cryptomus
59
-
60
- # Sync providers + update USD rates
61
- python manage.py manage_providers --with-rates
62
-
63
- # Show provider statistics
64
- python manage.py manage_providers --stats
65
-
66
- # Dry run to see what would be synced
67
- python manage.py manage_providers --dry-run --verbose
68
- ```
69
-
70
- #### Options:
71
- - `--provider NAME` - Specific provider(s) to sync (comma-separated)
72
- - `--all` - Sync all available providers
73
- - `--with-rates` - Also update USD exchange rates after sync
74
- - `--stats` - Show provider statistics
75
- - `--dry-run` - Show what would be synced without changes
76
- - `--verbose` - Show detailed progress information
77
-
78
- ---
79
-
80
- ### 3. `currency_stats` - Statistics and Reports
81
-
82
- Display currency database statistics and health information.
83
-
84
- #### Usage Examples:
85
-
86
- ```bash
87
- # Basic statistics
88
- python manage.py currency_stats
89
-
90
- # Detailed breakdown
91
- python manage.py currency_stats --detailed
92
-
93
- # Top currencies by value
94
- python manage.py currency_stats --top 10
95
-
96
- # Check rate freshness
97
- python manage.py currency_stats --check-rates
98
- ```
99
-
100
- ---
101
-
102
- ## Migration from Old Commands
103
-
104
- | Old Command | New Command |
105
- |-------------|-------------|
106
- | `populate_currencies` | `manage_currencies --populate` |
107
- | `update_currencies` | `manage_currencies` |
108
- | `update_currency_rates` | `manage_currencies --rates-only` |
109
- | `sync_providers` | `manage_providers` |
110
- | `currency_stats` | `currency_stats` (unchanged) |
111
-
112
- ## Automation Examples
113
-
114
- ### Daily Rate Updates (Crontab)
115
- ```bash
116
- # Update rates every 6 hours
117
- 0 */6 * * * cd /path/to/project && python manage.py manage_currencies --rates-only
118
-
119
- # Sync providers once daily
120
- 0 2 * * * cd /path/to/project && python manage.py manage_providers --with-rates
121
- ```
122
-
123
- ### Initial Setup
124
- ```bash
125
- # 1. Populate base currencies
126
- python manage.py manage_currencies --populate
127
-
128
- # 2. Sync payment providers
129
- python manage.py manage_providers
130
-
131
- # 3. Check statistics
132
- python manage.py manage_providers --stats
133
- python manage.py currency_stats
134
- ```
135
-
136
- ---
137
-
138
- ## Features
139
-
140
- - **🚀 Fast**: Optimized database queries and caching
141
- - **📊 Progress**: Real-time progress reporting and statistics
142
- - **🔄 Atomic**: Transaction safety with rollback on errors
143
- - **🎯 Flexible**: Multiple operation modes and options
144
- - **📈 Pydantic**: Full type safety with Pydantic models
145
- - **🛡️ Safe**: Dry-run mode for testing changes
146
- - **📝 Verbose**: Detailed logging and error reporting
@@ -1,23 +0,0 @@
1
- """
2
- Django model managers for universal payments.
3
- """
4
-
5
- from .payment_manager import UniversalPaymentManager
6
- from .balance_manager import UserBalanceManager
7
- from .subscription_manager import SubscriptionManager, EndpointGroupManager
8
- from .tariff_manager import TariffManager, TariffEndpointGroupManager
9
- from .api_key_manager import APIKeyManager
10
- from .currency_manager import CurrencyManager, NetworkManager, ProviderCurrencyManager
11
-
12
- __all__ = [
13
- 'UniversalPaymentManager',
14
- 'UserBalanceManager',
15
- 'SubscriptionManager',
16
- 'EndpointGroupManager',
17
- 'TariffManager',
18
- 'TariffEndpointGroupManager',
19
- 'APIKeyManager',
20
- 'CurrencyManager',
21
- 'NetworkManager',
22
- 'ProviderCurrencyManager',
23
- ]
@@ -1,35 +0,0 @@
1
- """
2
- API key managers.
3
- """
4
-
5
- from django.db import models
6
- from django.utils import timezone
7
-
8
-
9
- class APIKeyManager(models.Manager):
10
- """Manager for APIKey model."""
11
-
12
- def get_active_keys(self, user=None):
13
- """Get active API keys."""
14
- queryset = self.filter(is_active=True)
15
- if user:
16
- queryset = queryset.filter(user=user)
17
- return queryset
18
-
19
- def get_expired_keys(self):
20
- """Get expired API keys."""
21
- return self.filter(
22
- expires_at__lte=timezone.now()
23
- )
24
-
25
- def get_valid_keys(self, user=None):
26
- """Get valid (active and not expired) API keys."""
27
- now = timezone.now()
28
- queryset = self.filter(
29
- is_active=True
30
- ).filter(
31
- models.Q(expires_at__isnull=True) | models.Q(expires_at__gt=now)
32
- )
33
- if user:
34
- queryset = queryset.filter(user=user)
35
- return queryset