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,122 +0,0 @@
1
- """
2
- Currency ViewSets.
3
- """
4
-
5
- from rest_framework import viewsets, permissions, generics
6
- from rest_framework.decorators import action
7
- from rest_framework.response import Response
8
- from django_filters.rest_framework import DjangoFilterBackend
9
- from ..models import Currency, Network, ProviderCurrency
10
- from ..serializers import (
11
- CurrencySerializer, NetworkSerializer, ProviderCurrencySerializer, CurrencyListSerializer
12
- )
13
-
14
-
15
- class CurrencyViewSet(viewsets.ReadOnlyModelViewSet):
16
- """Currency ViewSet: /currencies/"""
17
-
18
- queryset = Currency.objects.all()
19
- serializer_class = CurrencySerializer
20
- permission_classes = [permissions.IsAuthenticated]
21
- filter_backends = [DjangoFilterBackend]
22
- filterset_fields = ['currency_type']
23
-
24
- def get_serializer_class(self):
25
- """Use list serializer for list action."""
26
- if self.action == 'list':
27
- return CurrencyListSerializer
28
- return CurrencySerializer
29
-
30
- @action(detail=False, methods=['get'])
31
- def crypto(self, request):
32
- """Get only cryptocurrencies."""
33
- cryptos = self.get_queryset().filter(currency_type='crypto')
34
- serializer = CurrencyListSerializer(cryptos, many=True)
35
- return Response(serializer.data)
36
-
37
- @action(detail=False, methods=['get'])
38
- def fiat(self, request):
39
- """Get only fiat currencies."""
40
- fiats = self.get_queryset().filter(currency_type='fiat')
41
- serializer = CurrencyListSerializer(fiats, many=True)
42
- return Response(serializer.data)
43
-
44
- @action(detail=True, methods=['get'])
45
- def networks(self, request, pk=None):
46
- """Get networks for specific currency."""
47
- currency = self.get_object()
48
- provider_currencies = ProviderCurrency.objects.filter(
49
- base_currency=currency,
50
- is_enabled=True
51
- ).select_related('network').distinct('network')
52
-
53
- networks = [pc.network for pc in provider_currencies if pc.network]
54
- serializer = NetworkSerializer(networks, many=True)
55
- return Response(serializer.data)
56
-
57
-
58
- class NetworkViewSet(viewsets.ReadOnlyModelViewSet):
59
- """Network ViewSet: /networks/"""
60
-
61
- queryset = Network.objects.all()
62
- serializer_class = NetworkSerializer
63
- permission_classes = [permissions.IsAuthenticated]
64
- filter_backends = [DjangoFilterBackend]
65
- filterset_fields = ['code', 'name']
66
-
67
-
68
- class ProviderCurrencyViewSet(viewsets.ReadOnlyModelViewSet):
69
- """Provider Currency ViewSet: /provider-currencies/"""
70
-
71
- queryset = ProviderCurrency.objects.select_related('base_currency', 'network')
72
- serializer_class = ProviderCurrencySerializer
73
- permission_classes = [permissions.IsAuthenticated]
74
- filter_backends = [DjangoFilterBackend]
75
- filterset_fields = ['provider_name', 'base_currency', 'network', 'is_enabled']
76
-
77
- @action(detail=False, methods=['get'])
78
- def by_currency(self, request):
79
- """Get networks grouped by currency."""
80
- currency_code = request.query_params.get('currency')
81
- if not currency_code:
82
- return Response({'error': 'currency parameter required'}, status=400)
83
-
84
- try:
85
- currency = Currency.objects.get(code=currency_code)
86
- networks = self.get_queryset().filter(currency=currency)
87
- serializer = self.get_serializer(networks, many=True)
88
- return Response(serializer.data)
89
- except Currency.DoesNotExist:
90
- return Response({'error': 'Currency not found'}, status=404)
91
-
92
-
93
- # Generic views for specific use cases
94
- class SupportedCurrenciesView(generics.ListAPIView):
95
- """Generic view to list supported currencies."""
96
-
97
- serializer_class = CurrencyListSerializer
98
- permission_classes = [permissions.IsAuthenticated]
99
-
100
- def get_queryset(self):
101
- """Get active currencies."""
102
- return Currency.objects.all().order_by('code')
103
-
104
-
105
- class CurrencyRatesView(generics.GenericAPIView):
106
- """Generic view to get currency exchange rates."""
107
-
108
- serializer_class = CurrencySerializer # For schema generation
109
- permission_classes = [permissions.IsAuthenticated]
110
-
111
- def get(self, request):
112
- """Get current exchange rates."""
113
- currencies = Currency.objects.all()
114
-
115
- rates = {}
116
- for currency in currencies:
117
- rates[currency.code] = {
118
- 'name': currency.name,
119
- 'currency_type': currency.currency_type,
120
- }
121
-
122
- return Response(rates)
@@ -1,149 +0,0 @@
1
- """
2
- Payment ViewSets with nested routing.
3
- """
4
-
5
- from rest_framework import viewsets, permissions, status, generics
6
- from rest_framework.decorators import action
7
- from rest_framework.response import Response
8
- from django_filters.rest_framework import DjangoFilterBackend
9
- from django.contrib.auth import get_user_model
10
- from ..models import UniversalPayment
11
- from ..serializers import (
12
- UniversalPaymentSerializer, PaymentCreateSerializer, PaymentListSerializer
13
- )
14
-
15
- User = get_user_model()
16
-
17
-
18
- class UserPaymentViewSet(viewsets.ModelViewSet):
19
- """Nested ViewSet for user payments: /users/{user_id}/payments/"""
20
-
21
- serializer_class = UniversalPaymentSerializer
22
- permission_classes = [permissions.IsAuthenticated]
23
- filter_backends = [DjangoFilterBackend]
24
- filterset_fields = ['status', 'provider', 'currency_code']
25
-
26
- def get_queryset(self):
27
- """Filter by user from URL."""
28
- user_id = self.kwargs.get('user_pk')
29
- return UniversalPayment.objects.filter(user_id=user_id).order_by('-created_at')
30
-
31
- def get_serializer_class(self):
32
- """Use different serializers for different actions."""
33
- if self.action == 'create':
34
- return PaymentCreateSerializer
35
- elif self.action == 'list':
36
- return PaymentListSerializer
37
- return UniversalPaymentSerializer
38
-
39
- def perform_create(self, serializer):
40
- """Set user from URL when creating."""
41
- user_id = self.kwargs.get('user_pk')
42
- user = User.objects.get(id=user_id)
43
- serializer.save(user=user)
44
-
45
- @action(detail=True, methods=['post'])
46
- def check_status(self, request, user_pk=None, pk=None):
47
- """Check payment status via provider API."""
48
- payment = self.get_object()
49
-
50
- # Import PaymentService to check status with provider
51
- from ..services.core.payment_service import PaymentService
52
-
53
- try:
54
- payment_service = PaymentService()
55
- status_result = payment_service.get_payment_status(str(payment.id))
56
-
57
- if status_result.success:
58
- # Update local payment status if it changed
59
- if payment.status != status_result.status:
60
- payment.status = status_result.status
61
- payment.save(update_fields=['status', 'updated_at'])
62
-
63
- return Response({
64
- 'payment_id': str(payment.id),
65
- 'status': status_result.status,
66
- 'provider_status': status_result.provider_status,
67
- 'updated': payment.status != status_result.status
68
- })
69
- else:
70
- return Response({
71
- 'payment_id': str(payment.id),
72
- 'status': payment.status,
73
- 'error': status_result.error_message,
74
- 'provider_check_failed': True
75
- }, status=status.HTTP_400_BAD_REQUEST)
76
-
77
- except Exception as e:
78
- # Log error but don't fail completely
79
- from django_cfg.modules.django_logger import get_logger
80
- logger = get_logger("payment_views")
81
- logger.error(f"Payment status check failed for {payment.id}: {e}")
82
-
83
- return Response({
84
- 'payment_id': str(payment.id),
85
- 'status': payment.status,
86
- 'error': 'Status check temporarily unavailable',
87
- 'provider_check_failed': True
88
- })
89
-
90
- @action(detail=False, methods=['get'])
91
- def summary(self, request, user_pk=None):
92
- """Get payment summary for user."""
93
- queryset = self.get_queryset()
94
-
95
- total_payments = queryset.count()
96
- total_amount = sum(p.amount_usd for p in queryset if p.status == 'completed')
97
- pending_amount = sum(p.amount_usd for p in queryset if p.status == 'pending')
98
-
99
- return Response({
100
- 'total_payments': total_payments,
101
- 'total_amount_usd': total_amount,
102
- 'pending_amount_usd': pending_amount,
103
- 'completed_payments': queryset.filter(status='completed').count(),
104
- 'pending_payments': queryset.filter(status='pending').count(),
105
- })
106
-
107
-
108
- class UniversalPaymentViewSet(viewsets.ReadOnlyModelViewSet):
109
- """Global payment ViewSet: /payments/"""
110
-
111
- queryset = UniversalPayment.objects.all()
112
- serializer_class = UniversalPaymentSerializer
113
- permission_classes = [permissions.IsAuthenticated]
114
- filter_backends = [DjangoFilterBackend]
115
- filterset_fields = ['status', 'provider', 'currency_code']
116
-
117
- def get_queryset(self):
118
- """Filter by current user for security."""
119
- return UniversalPayment.objects.filter(user=self.request.user).order_by('-created_at')
120
-
121
- def get_serializer_class(self):
122
- """Use list serializer for list action."""
123
- if self.action == 'list':
124
- return PaymentListSerializer
125
- return UniversalPaymentSerializer
126
-
127
-
128
- # Generic views for specific use cases
129
- class PaymentCreateView(generics.CreateAPIView):
130
- """Generic view to create payment."""
131
-
132
- serializer_class = PaymentCreateSerializer
133
- permission_classes = [permissions.IsAuthenticated]
134
-
135
- def perform_create(self, serializer):
136
- """Set current user when creating."""
137
- serializer.save(user=self.request.user)
138
-
139
-
140
- class PaymentStatusView(generics.RetrieveAPIView):
141
- """Generic view to check payment status."""
142
-
143
- serializer_class = UniversalPaymentSerializer
144
- permission_classes = [permissions.IsAuthenticated]
145
- lookup_field = 'internal_payment_id'
146
-
147
- def get_queryset(self):
148
- """Filter by current user."""
149
- return UniversalPayment.objects.filter(user=self.request.user)
@@ -1,135 +0,0 @@
1
- """
2
- Subscription ViewSets with nested routing.
3
- """
4
-
5
- from rest_framework import viewsets, permissions, status, generics
6
- from rest_framework.decorators import action
7
- from rest_framework.response import Response
8
- from django_filters.rest_framework import DjangoFilterBackend
9
- from django.contrib.auth import get_user_model
10
- from ..models import Subscription, EndpointGroup
11
- from ..serializers import (
12
- SubscriptionSerializer, SubscriptionCreateSerializer, SubscriptionListSerializer,
13
- EndpointGroupSerializer
14
- )
15
-
16
- User = get_user_model()
17
-
18
-
19
- class UserSubscriptionViewSet(viewsets.ModelViewSet):
20
- """Nested ViewSet for user subscriptions: /users/{user_id}/subscriptions/"""
21
-
22
- serializer_class = SubscriptionSerializer
23
- permission_classes = [permissions.IsAuthenticated]
24
- filter_backends = [DjangoFilterBackend]
25
- filterset_fields = ['status', 'tier', 'endpoint_group']
26
-
27
- def get_queryset(self):
28
- """Filter by user from URL."""
29
- user_id = self.kwargs.get('user_pk')
30
- return Subscription.objects.filter(user_id=user_id).order_by('-created_at')
31
-
32
- def get_serializer_class(self):
33
- """Use different serializers for different actions."""
34
- if self.action == 'create':
35
- return SubscriptionCreateSerializer
36
- elif self.action == 'list':
37
- return SubscriptionListSerializer
38
- return SubscriptionSerializer
39
-
40
- def perform_create(self, serializer):
41
- """Set user from URL when creating."""
42
- user_id = self.kwargs.get('user_pk')
43
- user = User.objects.get(id=user_id)
44
- serializer.save(user=user)
45
-
46
- @action(detail=True, methods=['post'])
47
- def cancel(self, request, user_pk=None, pk=None):
48
- """Cancel subscription."""
49
- subscription = self.get_object()
50
- subscription.status = 'cancelled'
51
- subscription.save()
52
-
53
- serializer = self.get_serializer(subscription)
54
- return Response(serializer.data)
55
-
56
- @action(detail=True, methods=['post'])
57
- def renew(self, request, user_pk=None, pk=None):
58
- """Renew subscription."""
59
- subscription = self.get_object()
60
- # TODO: Implement renewal logic
61
- return Response({'message': 'Subscription renewed'})
62
-
63
- @action(detail=False, methods=['get'])
64
- def active(self, request, user_pk=None):
65
- """Get active subscriptions for user."""
66
- queryset = self.get_queryset().filter(status='active')
67
- serializer = SubscriptionListSerializer(queryset, many=True)
68
- return Response(serializer.data)
69
-
70
-
71
- class SubscriptionViewSet(viewsets.ReadOnlyModelViewSet):
72
- """Global subscription ViewSet: /subscriptions/"""
73
-
74
- queryset = Subscription.objects.all()
75
- serializer_class = SubscriptionSerializer
76
- permission_classes = [permissions.IsAuthenticated]
77
- filter_backends = [DjangoFilterBackend]
78
- filterset_fields = ['status', 'tier', 'endpoint_group']
79
-
80
- def get_queryset(self):
81
- """Filter by current user for security."""
82
- return Subscription.objects.filter(user=self.request.user).order_by('-created_at')
83
-
84
- def get_serializer_class(self):
85
- """Use list serializer for list action."""
86
- if self.action == 'list':
87
- return SubscriptionListSerializer
88
- return SubscriptionSerializer
89
-
90
-
91
- class EndpointGroupViewSet(viewsets.ReadOnlyModelViewSet):
92
- """Endpoint groups ViewSet: /endpoint-groups/"""
93
-
94
- queryset = EndpointGroup.objects.filter(is_active=True)
95
- serializer_class = EndpointGroupSerializer
96
- permission_classes = [permissions.IsAuthenticated]
97
-
98
- @action(detail=True, methods=['get'])
99
- def pricing(self, request, pk=None):
100
- """Get pricing for endpoint group."""
101
- endpoint_group = self.get_object()
102
- return Response({
103
- 'basic_price': endpoint_group.basic_price,
104
- 'premium_price': endpoint_group.premium_price,
105
- 'enterprise_price': endpoint_group.enterprise_price,
106
- 'basic_limit': endpoint_group.basic_limit,
107
- 'premium_limit': endpoint_group.premium_limit,
108
- 'enterprise_limit': endpoint_group.enterprise_limit,
109
- })
110
-
111
-
112
- # Generic views for specific use cases
113
- class SubscriptionCreateView(generics.CreateAPIView):
114
- """Generic view to create subscription."""
115
-
116
- serializer_class = SubscriptionCreateSerializer
117
- permission_classes = [permissions.IsAuthenticated]
118
-
119
- def perform_create(self, serializer):
120
- """Set current user when creating."""
121
- serializer.save(user=self.request.user)
122
-
123
-
124
- class ActiveSubscriptionsView(generics.ListAPIView):
125
- """Generic view to list active subscriptions."""
126
-
127
- serializer_class = SubscriptionListSerializer
128
- permission_classes = [permissions.IsAuthenticated]
129
-
130
- def get_queryset(self):
131
- """Get active subscriptions for current user."""
132
- return Subscription.objects.filter(
133
- user=self.request.user,
134
- status='active'
135
- ).order_by('-created_at')
@@ -1,131 +0,0 @@
1
- """
2
- Tariff ViewSets.
3
- """
4
-
5
- from rest_framework import viewsets, permissions, generics
6
- from rest_framework.decorators import action
7
- from rest_framework.response import Response
8
- from django_filters.rest_framework import DjangoFilterBackend
9
- from ..models import Tariff, TariffEndpointGroup
10
- from ..serializers import (
11
- TariffSerializer, TariffEndpointGroupSerializer, TariffListSerializer
12
- )
13
-
14
-
15
- class TariffViewSet(viewsets.ReadOnlyModelViewSet):
16
- """Tariff ViewSet: /tariffs/"""
17
-
18
- queryset = Tariff.objects.filter(is_active=True)
19
- serializer_class = TariffSerializer
20
- permission_classes = [permissions.IsAuthenticated]
21
- filter_backends = [DjangoFilterBackend]
22
- filterset_fields = ['is_active']
23
-
24
- def get_serializer_class(self):
25
- """Use list serializer for list action."""
26
- if self.action == 'list':
27
- return TariffListSerializer
28
- return TariffSerializer
29
-
30
- def get_queryset(self):
31
- """Order by price."""
32
- return super().get_queryset().order_by('monthly_price')
33
-
34
- @action(detail=False, methods=['get'])
35
- def free(self, request):
36
- """Get free tariffs."""
37
- free_tariffs = self.get_queryset().filter(monthly_price=0)
38
- serializer = TariffListSerializer(free_tariffs, many=True)
39
- return Response(serializer.data)
40
-
41
- @action(detail=False, methods=['get'])
42
- def paid(self, request):
43
- """Get paid tariffs."""
44
- paid_tariffs = self.get_queryset().filter(monthly_price__gt=0)
45
- serializer = TariffListSerializer(paid_tariffs, many=True)
46
- return Response(serializer.data)
47
-
48
- @action(detail=True, methods=['get'])
49
- def endpoint_groups(self, request, pk=None):
50
- """Get endpoint groups for tariff."""
51
- tariff = self.get_object()
52
- endpoint_groups = TariffEndpointGroup.objects.filter(
53
- tariff=tariff,
54
- is_enabled=True
55
- )
56
- serializer = TariffEndpointGroupSerializer(endpoint_groups, many=True)
57
- return Response(serializer.data)
58
-
59
-
60
- class TariffEndpointGroupViewSet(viewsets.ReadOnlyModelViewSet):
61
- """Tariff Endpoint Group ViewSet: /tariff-endpoint-groups/"""
62
-
63
- queryset = TariffEndpointGroup.objects.filter(is_enabled=True)
64
- serializer_class = TariffEndpointGroupSerializer
65
- permission_classes = [permissions.IsAuthenticated]
66
- filter_backends = [DjangoFilterBackend]
67
- filterset_fields = ['tariff', 'endpoint_group', 'is_enabled']
68
-
69
- @action(detail=False, methods=['get'])
70
- def by_tariff(self, request):
71
- """Get endpoint groups by tariff."""
72
- tariff_id = request.query_params.get('tariff_id')
73
- if not tariff_id:
74
- return Response({'error': 'tariff_id parameter required'}, status=400)
75
-
76
- groups = self.get_queryset().filter(tariff_id=tariff_id)
77
- serializer = self.get_serializer(groups, many=True)
78
- return Response(serializer.data)
79
-
80
- @action(detail=False, methods=['get'])
81
- def by_endpoint_group(self, request):
82
- """Get tariffs by endpoint group."""
83
- endpoint_group_id = request.query_params.get('endpoint_group_id')
84
- if not endpoint_group_id:
85
- return Response({'error': 'endpoint_group_id parameter required'}, status=400)
86
-
87
- groups = self.get_queryset().filter(endpoint_group_id=endpoint_group_id)
88
- serializer = self.get_serializer(groups, many=True)
89
- return Response(serializer.data)
90
-
91
-
92
- # Generic views for specific use cases
93
- class AvailableTariffsView(generics.ListAPIView):
94
- """Generic view to list available tariffs."""
95
-
96
- serializer_class = TariffListSerializer
97
- permission_classes = [permissions.IsAuthenticated]
98
-
99
- def get_queryset(self):
100
- """Get active tariffs ordered by price."""
101
- return Tariff.objects.filter(is_active=True).order_by('monthly_price')
102
-
103
-
104
- class TariffComparisonView(generics.GenericAPIView):
105
- """Generic view to compare tariffs."""
106
-
107
- serializer_class = TariffSerializer # For schema generation
108
- permission_classes = [permissions.IsAuthenticated]
109
-
110
- def get(self, request):
111
- """Get tariff comparison data."""
112
- tariffs = Tariff.objects.filter(is_active=True).order_by('monthly_price')
113
-
114
- comparison = []
115
- for tariff in tariffs:
116
- endpoint_groups_count = TariffEndpointGroup.objects.filter(
117
- tariff=tariff,
118
- is_enabled=True
119
- ).count()
120
-
121
- comparison.append({
122
- 'id': tariff.id,
123
- 'name': tariff.name,
124
- 'display_name': tariff.display_name,
125
- 'monthly_price': tariff.monthly_price,
126
- 'request_limit': tariff.request_limit,
127
- 'is_free': tariff.is_free,
128
- 'endpoint_groups_count': endpoint_groups_count,
129
- })
130
-
131
- return Response(comparison)
@@ -1,25 +0,0 @@
1
- """
2
- Template views package for Payment Dashboard.
3
-
4
- All views require superuser access as this is an internal admin tool.
5
- """
6
-
7
- from .dashboard import PaymentDashboardView
8
- from .payment_detail import PaymentDetailView
9
- from .payment_management import PaymentCreateView, PaymentListView
10
- from .stats import PaymentStatsView
11
- from .qr_code import PaymentQRCodeView
12
- from .ajax import payment_status_ajax, payment_events_ajax
13
- from .utils import PaymentTestView
14
-
15
- __all__ = [
16
- 'PaymentDashboardView',
17
- 'PaymentDetailView',
18
- 'PaymentCreateView',
19
- 'PaymentListView',
20
- 'PaymentStatsView',
21
- 'PaymentQRCodeView',
22
- 'PaymentTestView',
23
- 'payment_status_ajax',
24
- 'payment_events_ajax',
25
- ]