django-cfg 1.2.31__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 (256) 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/manage_currencies.py +303 -151
  39. django_cfg/apps/payments/management/commands/manage_providers.py +333 -160
  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 +342 -152
  43. django_cfg/apps/payments/middleware/usage_tracking.py +249 -240
  44. django_cfg/apps/payments/migrations/0001_initial.py +708 -536
  45. django_cfg/apps/payments/models/__init__.py +13 -18
  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 +172 -148
  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 -285
  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 +346 -467
  67. django_cfg/apps/payments/services/core/subscription_service.py +425 -481
  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 +234 -174
  74. django_cfg/apps/payments/services/providers/nowpayments.py +478 -0
  75. django_cfg/apps/payments/services/providers/registry.py +367 -301
  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 +210 -129
  83. django_cfg/apps/payments/signals/balance_signals.py +174 -0
  84. django_cfg/apps/payments/signals/payment_signals.py +128 -103
  85. django_cfg/apps/payments/signals/subscription_signals.py +194 -142
  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 +45 -48
  93. django_cfg/apps/payments/urls_admin.py +33 -42
  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/config.py +1 -1
  110. django_cfg/core/config.py +40 -4
  111. django_cfg/core/generation.py +25 -4
  112. django_cfg/core/integration/README.md +363 -0
  113. django_cfg/core/integration/__init__.py +47 -0
  114. django_cfg/core/integration/commands_collector.py +239 -0
  115. django_cfg/core/integration/display/__init__.py +15 -0
  116. django_cfg/core/integration/display/base.py +157 -0
  117. django_cfg/core/integration/display/ngrok.py +164 -0
  118. django_cfg/core/integration/display/startup.py +815 -0
  119. django_cfg/core/integration/url_integration.py +123 -0
  120. django_cfg/core/integration/version_checker.py +160 -0
  121. django_cfg/management/commands/auto_generate.py +4 -0
  122. django_cfg/management/commands/check_settings.py +6 -0
  123. django_cfg/management/commands/clear_constance.py +5 -2
  124. django_cfg/management/commands/create_token.py +6 -0
  125. django_cfg/management/commands/list_urls.py +6 -0
  126. django_cfg/management/commands/migrate_all.py +6 -0
  127. django_cfg/management/commands/migrator.py +3 -0
  128. django_cfg/management/commands/rundramatiq.py +6 -0
  129. django_cfg/management/commands/runserver_ngrok.py +51 -29
  130. django_cfg/management/commands/script.py +6 -0
  131. django_cfg/management/commands/show_config.py +12 -2
  132. django_cfg/management/commands/show_urls.py +4 -0
  133. django_cfg/management/commands/superuser.py +6 -0
  134. django_cfg/management/commands/task_clear.py +4 -1
  135. django_cfg/management/commands/task_status.py +3 -1
  136. django_cfg/management/commands/test_email.py +3 -0
  137. django_cfg/management/commands/test_telegram.py +6 -0
  138. django_cfg/management/commands/test_twilio.py +6 -0
  139. django_cfg/management/commands/tree.py +6 -0
  140. django_cfg/management/commands/validate_config.py +155 -149
  141. django_cfg/models/constance.py +31 -11
  142. django_cfg/models/payments.py +175 -492
  143. django_cfg/modules/django_logger.py +160 -146
  144. django_cfg/modules/django_unfold/dashboard.py +64 -16
  145. django_cfg/registry/core.py +1 -0
  146. django_cfg/template_archive/django_sample.zip +0 -0
  147. django_cfg/utils/smart_defaults.py +222 -571
  148. django_cfg/utils/toolkit.py +51 -11
  149. {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/METADATA +4 -1
  150. {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/RECORD +153 -185
  151. django_cfg/apps/payments/__init__.py +0 -8
  152. django_cfg/apps/payments/admin/tariffs_admin.py +0 -199
  153. django_cfg/apps/payments/config/module.py +0 -70
  154. django_cfg/apps/payments/config/providers.py +0 -105
  155. django_cfg/apps/payments/config/settings.py +0 -96
  156. django_cfg/apps/payments/config/utils.py +0 -52
  157. django_cfg/apps/payments/decorators.py +0 -291
  158. django_cfg/apps/payments/management/commands/README.md +0 -146
  159. django_cfg/apps/payments/management/commands/currency_stats.py +0 -304
  160. django_cfg/apps/payments/managers/__init__.py +0 -23
  161. django_cfg/apps/payments/managers/api_key_manager.py +0 -35
  162. django_cfg/apps/payments/managers/balance_manager.py +0 -361
  163. django_cfg/apps/payments/managers/currency_manager.py +0 -306
  164. django_cfg/apps/payments/managers/payment_manager.py +0 -192
  165. django_cfg/apps/payments/managers/subscription_manager.py +0 -37
  166. django_cfg/apps/payments/managers/tariff_manager.py +0 -29
  167. django_cfg/apps/payments/migrations/0002_network_providercurrency_and_more.py +0 -241
  168. django_cfg/apps/payments/migrations/0003_add_usd_rate_cache.py +0 -30
  169. django_cfg/apps/payments/models/events.py +0 -73
  170. django_cfg/apps/payments/serializers/__init__.py +0 -57
  171. django_cfg/apps/payments/serializers/api_keys.py +0 -51
  172. django_cfg/apps/payments/serializers/balance.py +0 -59
  173. django_cfg/apps/payments/serializers/currencies.py +0 -63
  174. django_cfg/apps/payments/serializers/payments.py +0 -62
  175. django_cfg/apps/payments/serializers/subscriptions.py +0 -71
  176. django_cfg/apps/payments/serializers/tariffs.py +0 -56
  177. django_cfg/apps/payments/services/billing/__init__.py +0 -8
  178. django_cfg/apps/payments/services/cache/base.py +0 -30
  179. django_cfg/apps/payments/services/core/fallback_service.py +0 -432
  180. django_cfg/apps/payments/services/internal_types.py +0 -461
  181. django_cfg/apps/payments/services/middleware/__init__.py +0 -8
  182. django_cfg/apps/payments/services/monitoring/__init__.py +0 -22
  183. django_cfg/apps/payments/services/monitoring/api_schemas.py +0 -76
  184. django_cfg/apps/payments/services/monitoring/provider_health.py +0 -372
  185. django_cfg/apps/payments/services/providers/cryptapi/__init__.py +0 -4
  186. django_cfg/apps/payments/services/providers/cryptapi/config.py +0 -8
  187. django_cfg/apps/payments/services/providers/cryptapi/models.py +0 -192
  188. django_cfg/apps/payments/services/providers/cryptapi/provider.py +0 -439
  189. django_cfg/apps/payments/services/providers/cryptomus/__init__.py +0 -4
  190. django_cfg/apps/payments/services/providers/cryptomus/models.py +0 -176
  191. django_cfg/apps/payments/services/providers/cryptomus/provider.py +0 -429
  192. django_cfg/apps/payments/services/providers/cryptomus/provider_v2.py +0 -564
  193. django_cfg/apps/payments/services/providers/models/__init__.py +0 -34
  194. django_cfg/apps/payments/services/providers/models/currencies.py +0 -190
  195. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +0 -4
  196. django_cfg/apps/payments/services/providers/nowpayments/models.py +0 -196
  197. django_cfg/apps/payments/services/providers/nowpayments/provider.py +0 -380
  198. django_cfg/apps/payments/services/providers/stripe/__init__.py +0 -4
  199. django_cfg/apps/payments/services/providers/stripe/models.py +0 -184
  200. django_cfg/apps/payments/services/providers/stripe/provider.py +0 -109
  201. django_cfg/apps/payments/services/security/__init__.py +0 -34
  202. django_cfg/apps/payments/services/security/error_handler.py +0 -635
  203. django_cfg/apps/payments/services/security/payment_notifications.py +0 -342
  204. django_cfg/apps/payments/services/security/webhook_validator.py +0 -474
  205. django_cfg/apps/payments/static/payments/css/payments.css +0 -340
  206. django_cfg/apps/payments/static/payments/js/notifications.js +0 -202
  207. django_cfg/apps/payments/static/payments/js/payment-utils.js +0 -318
  208. django_cfg/apps/payments/static/payments/js/theme.js +0 -86
  209. django_cfg/apps/payments/tasks/__init__.py +0 -12
  210. django_cfg/apps/payments/tasks/webhook_processing.py +0 -177
  211. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +0 -50
  212. django_cfg/apps/payments/templates/payments/base.html +0 -182
  213. django_cfg/apps/payments/templates/payments/components/payment_card.html +0 -201
  214. django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +0 -109
  215. django_cfg/apps/payments/templates/payments/components/progress_bar.html +0 -43
  216. django_cfg/apps/payments/templates/payments/components/provider_stats.html +0 -40
  217. django_cfg/apps/payments/templates/payments/components/status_badge.html +0 -34
  218. django_cfg/apps/payments/templates/payments/components/status_overview.html +0 -148
  219. django_cfg/apps/payments/templates/payments/dashboard.html +0 -258
  220. django_cfg/apps/payments/templates/payments/dashboard_simple_test.html +0 -35
  221. django_cfg/apps/payments/templates/payments/payment_create.html +0 -579
  222. django_cfg/apps/payments/templates/payments/payment_detail.html +0 -373
  223. django_cfg/apps/payments/templates/payments/payment_list.html +0 -354
  224. django_cfg/apps/payments/templates/payments/stats.html +0 -261
  225. django_cfg/apps/payments/templates/payments/test.html +0 -213
  226. django_cfg/apps/payments/templatetags/payments_tags.py +0 -315
  227. django_cfg/apps/payments/utils/__init__.py +0 -43
  228. django_cfg/apps/payments/utils/billing_utils.py +0 -342
  229. django_cfg/apps/payments/utils/config_utils.py +0 -239
  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 -63
  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 -122
  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 -451
  241. django_cfg/apps/payments/views/templates/base.py +0 -212
  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 -158
  245. django_cfg/apps/payments/views/templates/qr_code.py +0 -174
  246. django_cfg/apps/payments/views/templates/stats.py +0 -244
  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 -66
  250. django_cfg/core/integration.py +0 -160
  251. django_cfg/template_archive/.gitignore +0 -1
  252. django_cfg/template_archive/__init__.py +0 -0
  253. django_cfg/urls.py +0 -33
  254. {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/WHEEL +0 -0
  255. {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/entry_points.txt +0 -0
  256. {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,192 +0,0 @@
1
- """
2
- Enhanced Payment manager for UniversalPayment model with query optimizations.
3
- """
4
-
5
- from django.db import models
6
- from django.utils import timezone
7
- from datetime import timedelta
8
- from django_cfg.modules.django_logger import get_logger
9
-
10
- logger = get_logger("payment_manager")
11
-
12
-
13
- class PaymentQuerySet(models.QuerySet):
14
- """Custom QuerySet for UniversalPayment with optimizations."""
15
-
16
- def with_user(self):
17
- """Select related user to prevent N+1 queries."""
18
- return self.select_related('user')
19
-
20
- def with_events(self):
21
- """Skip prefetch for events since they use CharField payment_id, not ForeignKey."""
22
- # PaymentEvent uses CharField payment_id, not ForeignKey, so no reverse relation exists
23
- # Events should be fetched separately when needed
24
- return self
25
-
26
- def optimized(self):
27
- """Get optimized queryset for admin and API views."""
28
- return self.select_related('user').with_events()
29
-
30
- def active(self):
31
- """Get active payments (not failed, cancelled, or refunded)."""
32
- return self.exclude(
33
- status__in=['failed', 'cancelled', 'refunded', 'expired']
34
- )
35
-
36
- def completed(self):
37
- """Get only completed payments."""
38
- return self.filter(status='completed')
39
-
40
- def pending(self):
41
- """Get pending payments."""
42
- return self.filter(status='pending')
43
-
44
- def by_provider(self, provider):
45
- """Filter by payment provider."""
46
- return self.filter(provider=provider)
47
-
48
- def recent(self, days=30):
49
- """Get payments from last N days."""
50
- cutoff_date = timezone.now() - timedelta(days=days)
51
- return self.filter(created_at__gte=cutoff_date)
52
-
53
- def by_amount_range(self, min_amount=None, max_amount=None):
54
- """Filter by USD amount range."""
55
- queryset = self
56
- if min_amount is not None:
57
- queryset = queryset.filter(amount_usd__gte=min_amount)
58
- if max_amount is not None:
59
- queryset = queryset.filter(amount_usd__lte=max_amount)
60
- return queryset
61
-
62
- def by_user(self, user):
63
- """Filter by user."""
64
- return self.filter(user=user)
65
-
66
- def expired(self):
67
- """Get expired payments."""
68
- return self.filter(
69
- expires_at__lt=timezone.now(),
70
- status__in=['pending', 'confirming']
71
- )
72
-
73
-
74
- class UniversalPaymentManager(models.Manager):
75
- """Enhanced manager for UniversalPayment with optimization methods."""
76
-
77
- def get_queryset(self):
78
- """Return custom QuerySet."""
79
- return PaymentQuerySet(self.model, using=self._db)
80
-
81
- def with_user(self):
82
- """Get payments with user data preloaded."""
83
- return self.get_queryset().with_user()
84
-
85
- def optimized(self):
86
- """Get optimized queryset for admin views."""
87
- return self.get_queryset().optimized()
88
-
89
- def active(self):
90
- """Get active payments."""
91
- return self.get_queryset().active()
92
-
93
- def completed(self):
94
- """Get completed payments."""
95
- return self.get_queryset().completed()
96
-
97
- def pending(self):
98
- """Get pending payments."""
99
- return self.get_queryset().pending()
100
-
101
- def recent(self, days=30):
102
- """Get recent payments."""
103
- return self.get_queryset().recent(days)
104
-
105
- def by_provider(self, provider):
106
- """Get payments by provider."""
107
- return self.get_queryset().by_provider(provider)
108
-
109
- def create_payment(self, user, amount_usd: float, currency_code: str, provider: str, **kwargs):
110
- """Create a payment with automatic field generation."""
111
- from uuid import uuid4
112
-
113
- # Generate unique internal payment ID if not provided
114
- internal_payment_id = kwargs.pop('internal_payment_id', f"PAY_{uuid4().hex[:8].upper()}")
115
-
116
- payment = self.create(
117
- user=user,
118
- internal_payment_id=internal_payment_id,
119
- amount_usd=amount_usd,
120
- currency_code=currency_code.upper(),
121
- provider=provider,
122
- status=self.model.PaymentStatus.PENDING,
123
- **kwargs
124
- )
125
-
126
- return payment
127
-
128
- def get_pending_payments(self, user=None):
129
- """Get pending payments for user or all users."""
130
- queryset = self.pending()
131
- if user:
132
- queryset = queryset.by_user(user)
133
- return queryset.with_user()
134
-
135
- def get_completed_payments(self, user=None):
136
- """Get completed payments for user or all users."""
137
- queryset = self.completed()
138
- if user:
139
- queryset = queryset.by_user(user)
140
- return queryset.with_user()
141
-
142
- def get_failed_payments(self, user=None):
143
- """Get failed/expired payments for user or all users."""
144
- queryset = self.filter(status__in=[
145
- self.model.PaymentStatus.FAILED,
146
- self.model.PaymentStatus.EXPIRED
147
- ])
148
- if user:
149
- queryset = queryset.by_user(user)
150
- return queryset.with_user()
151
-
152
- def get_user_stats(self, user):
153
- """Get payment statistics for a user."""
154
- user_payments = self.by_user(user)
155
-
156
- return {
157
- 'total_payments': user_payments.count(),
158
- 'completed_payments': user_payments.completed().count(),
159
- 'pending_payments': user_payments.pending().count(),
160
- 'failed_payments': user_payments.filter(status='failed').count(),
161
- 'total_amount_usd': user_payments.completed().aggregate(
162
- total=models.Sum('amount_usd')
163
- )['total'] or 0,
164
- 'recent_payments_30d': user_payments.recent(30).count(),
165
- }
166
-
167
- def get_provider_stats(self, provider=None):
168
- """Get payment statistics by provider."""
169
- if provider:
170
- payments = self.by_provider(provider)
171
- else:
172
- payments = self.all()
173
-
174
- return {
175
- 'total_payments': payments.count(),
176
- 'completed_payments': payments.completed().count(),
177
- 'pending_payments': payments.pending().count(),
178
- 'success_rate': (
179
- payments.completed().count() / max(payments.count(), 1) * 100
180
- ),
181
- 'total_volume_usd': payments.completed().aggregate(
182
- total=models.Sum('amount_usd')
183
- )['total'] or 0,
184
- }
185
-
186
- def mark_expired_payments(self):
187
- """Mark expired payments as expired."""
188
- expired_count = self.expired().update(
189
- status=self.model.PaymentStatus.EXPIRED,
190
- updated_at=timezone.now()
191
- )
192
- return expired_count
@@ -1,37 +0,0 @@
1
- """
2
- Subscription managers.
3
- """
4
-
5
- from django.db import models
6
- from django.utils import timezone
7
-
8
-
9
- class SubscriptionManager(models.Manager):
10
- """Manager for Subscription model."""
11
-
12
- def get_active_subscriptions(self, user=None):
13
- """Get active subscriptions."""
14
- queryset = self.filter(
15
- status='active',
16
- expires_at__gt=timezone.now()
17
- )
18
- if user:
19
- queryset = queryset.filter(user=user)
20
- return queryset
21
-
22
- def get_expired_subscriptions(self, user=None):
23
- """Get expired subscriptions."""
24
- queryset = self.filter(
25
- expires_at__lte=timezone.now()
26
- )
27
- if user:
28
- queryset = queryset.filter(user=user)
29
- return queryset
30
-
31
-
32
- class EndpointGroupManager(models.Manager):
33
- """Manager for EndpointGroup model."""
34
-
35
- def get_active_groups(self):
36
- """Get active endpoint groups."""
37
- return self.filter(is_active=True)
@@ -1,29 +0,0 @@
1
- """
2
- Tariff managers.
3
- """
4
-
5
- from django.db import models
6
-
7
-
8
- class TariffManager(models.Manager):
9
- """Manager for Tariff model."""
10
-
11
- def get_active_tariffs(self):
12
- """Get active tariffs."""
13
- return self.filter(is_active=True).order_by('monthly_price')
14
-
15
- def get_free_tariffs(self):
16
- """Get free tariffs."""
17
- return self.filter(monthly_price=0, is_active=True)
18
-
19
- def get_paid_tariffs(self):
20
- """Get paid tariffs."""
21
- return self.filter(monthly_price__gt=0, is_active=True)
22
-
23
-
24
- class TariffEndpointGroupManager(models.Manager):
25
- """Manager for TariffEndpointGroup model."""
26
-
27
- def get_enabled_for_tariff(self, tariff):
28
- """Get enabled endpoint groups for tariff."""
29
- return self.filter(tariff=tariff, is_enabled=True)
@@ -1,241 +0,0 @@
1
- # Generated by Django 5.2.6 on 2025-09-24 19:54
2
-
3
- import django.db.models.deletion
4
- from django.db import migrations, models
5
-
6
-
7
- class Migration(migrations.Migration):
8
- dependencies = [
9
- ("django_cfg_payments", "0001_initial"),
10
- ]
11
-
12
- operations = [
13
- migrations.CreateModel(
14
- name="Network",
15
- fields=[
16
- (
17
- "id",
18
- models.BigAutoField(
19
- auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
20
- ),
21
- ),
22
- ("created_at", models.DateTimeField(auto_now_add=True, db_index=True)),
23
- ("updated_at", models.DateTimeField(auto_now=True)),
24
- (
25
- "code",
26
- models.CharField(
27
- help_text="Network code: ethereum, bitcoin, tron, bsc",
28
- max_length=20,
29
- unique=True,
30
- ),
31
- ),
32
- (
33
- "name",
34
- models.CharField(
35
- help_text="Network name: Ethereum, Bitcoin, TRON, BSC", max_length=100
36
- ),
37
- ),
38
- ],
39
- options={
40
- "verbose_name": "Network",
41
- "verbose_name_plural": "Networks",
42
- "db_table": "payment_networks",
43
- "ordering": ["name"],
44
- },
45
- ),
46
- migrations.CreateModel(
47
- name="ProviderCurrency",
48
- fields=[
49
- (
50
- "id",
51
- models.BigAutoField(
52
- auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
53
- ),
54
- ),
55
- ("created_at", models.DateTimeField(auto_now_add=True, db_index=True)),
56
- ("updated_at", models.DateTimeField(auto_now=True)),
57
- (
58
- "provider_name",
59
- models.CharField(
60
- help_text="Provider: nowpayments, stripe, cryptomus", max_length=50
61
- ),
62
- ),
63
- (
64
- "provider_currency_code",
65
- models.CharField(
66
- help_text="Provider code: USDTERC20, USDTBSC, usd", max_length=20
67
- ),
68
- ),
69
- (
70
- "min_amount",
71
- models.DecimalField(
72
- blank=True,
73
- decimal_places=8,
74
- help_text="Minimum payment amount",
75
- max_digits=20,
76
- null=True,
77
- ),
78
- ),
79
- (
80
- "max_amount",
81
- models.DecimalField(
82
- blank=True,
83
- decimal_places=8,
84
- help_text="Maximum payment amount (null = no limit)",
85
- max_digits=20,
86
- null=True,
87
- ),
88
- ),
89
- ("is_enabled", models.BooleanField(default=True, help_text="Enabled by provider")),
90
- (
91
- "available_for_payment",
92
- models.BooleanField(default=True, help_text="Can receive payments"),
93
- ),
94
- (
95
- "available_for_payout",
96
- models.BooleanField(default=True, help_text="Can send payouts"),
97
- ),
98
- (
99
- "is_popular",
100
- models.BooleanField(default=False, help_text="Popular/recommended by provider"),
101
- ),
102
- (
103
- "is_stable",
104
- models.BooleanField(default=False, help_text="Stable coin (USDT, USDC, etc.)"),
105
- ),
106
- (
107
- "priority",
108
- models.IntegerField(
109
- default=0, help_text="Display priority (higher = shown first)"
110
- ),
111
- ),
112
- (
113
- "logo_url",
114
- models.URLField(blank=True, help_text="Currency logo/icon URL from provider"),
115
- ),
116
- (
117
- "metadata",
118
- models.JSONField(
119
- blank=True,
120
- default=dict,
121
- help_text="All provider-specific data: logo_url, smart_contract, wallet_regex, commission_percent, etc.",
122
- ),
123
- ),
124
- ],
125
- options={
126
- "verbose_name": "Provider Currency",
127
- "verbose_name_plural": "Provider Currencies",
128
- "db_table": "payment_provider_currencies",
129
- "ordering": ["-priority", "provider_name", "base_currency__code"],
130
- },
131
- ),
132
- migrations.AlterUniqueTogether(
133
- name="currencynetwork",
134
- unique_together=None,
135
- ),
136
- migrations.RemoveField(
137
- model_name="currencynetwork",
138
- name="currency",
139
- ),
140
- migrations.AlterModelOptions(
141
- name="currency",
142
- options={
143
- "ordering": ["currency_type", "code"],
144
- "verbose_name": "Currency",
145
- "verbose_name_plural": "Currencies",
146
- },
147
- ),
148
- migrations.RemoveIndex(
149
- model_name="currency",
150
- name="payment_cur_code_e2a506_idx",
151
- ),
152
- migrations.RemoveIndex(
153
- model_name="currency",
154
- name="payment_cur_currenc_6057a9_idx",
155
- ),
156
- migrations.RemoveIndex(
157
- model_name="currency",
158
- name="payment_cur_is_acti_8d558f_idx",
159
- ),
160
- migrations.RemoveField(
161
- model_name="currency",
162
- name="decimal_places",
163
- ),
164
- migrations.RemoveField(
165
- model_name="currency",
166
- name="is_active",
167
- ),
168
- migrations.RemoveField(
169
- model_name="currency",
170
- name="min_payment_amount",
171
- ),
172
- migrations.RemoveField(
173
- model_name="currency",
174
- name="rate_updated_at",
175
- ),
176
- migrations.RemoveField(
177
- model_name="currency",
178
- name="symbol",
179
- ),
180
- migrations.RemoveField(
181
- model_name="currency",
182
- name="usd_rate",
183
- ),
184
- migrations.AlterField(
185
- model_name="currency",
186
- name="code",
187
- field=models.CharField(
188
- help_text="Clean currency code: BTC, USDT, ETH, USD (NO network suffixes)",
189
- max_length=10,
190
- unique=True,
191
- ),
192
- ),
193
- migrations.AlterField(
194
- model_name="currency",
195
- name="currency_type",
196
- field=models.CharField(
197
- choices=[("fiat", "Fiat Currency"), ("crypto", "Cryptocurrency")],
198
- help_text="fiat or crypto",
199
- max_length=10,
200
- ),
201
- ),
202
- migrations.AlterField(
203
- model_name="currency",
204
- name="name",
205
- field=models.CharField(
206
- help_text="Currency name: Bitcoin, Tether USD, Ethereum", max_length=100
207
- ),
208
- ),
209
- migrations.AddField(
210
- model_name="providercurrency",
211
- name="base_currency",
212
- field=models.ForeignKey(
213
- help_text="Base currency: BTC, USDT, ETH",
214
- on_delete=django.db.models.deletion.CASCADE,
215
- related_name="provider_mappings",
216
- to="django_cfg_payments.currency",
217
- ),
218
- ),
219
- migrations.AddField(
220
- model_name="providercurrency",
221
- name="network",
222
- field=models.ForeignKey(
223
- blank=True,
224
- help_text="Network for crypto (null for fiat)",
225
- null=True,
226
- on_delete=django.db.models.deletion.CASCADE,
227
- related_name="provider_currencies",
228
- to="django_cfg_payments.network",
229
- ),
230
- ),
231
- migrations.DeleteModel(
232
- name="CurrencyNetwork",
233
- ),
234
- migrations.AlterUniqueTogether(
235
- name="providercurrency",
236
- unique_together={
237
- ("provider_name", "base_currency", "network"),
238
- ("provider_name", "provider_currency_code"),
239
- },
240
- ),
241
- ]
@@ -1,30 +0,0 @@
1
- # Generated by Django 5.2.6 on 2025-09-25 06:06
2
-
3
- from django.db import migrations, models
4
-
5
-
6
- class Migration(migrations.Migration):
7
- dependencies = [
8
- ("django_cfg_payments", "0002_network_providercurrency_and_more"),
9
- ]
10
-
11
- operations = [
12
- migrations.AddField(
13
- model_name="currency",
14
- name="rate_updated_at",
15
- field=models.DateTimeField(
16
- blank=True, help_text="When the USD rate was last updated", null=True
17
- ),
18
- ),
19
- migrations.AddField(
20
- model_name="currency",
21
- name="usd_rate",
22
- field=models.DecimalField(
23
- blank=True,
24
- decimal_places=8,
25
- help_text="Cached USD exchange rate (1 CURRENCY = X USD)",
26
- max_digits=20,
27
- null=True,
28
- ),
29
- ),
30
- ]
@@ -1,73 +0,0 @@
1
- """
2
- Event sourcing models for the universal payments system.
3
- """
4
-
5
- from django.db import models
6
- from .base import UUIDTimestampedModel
7
-
8
-
9
- class PaymentEvent(UUIDTimestampedModel):
10
- """Event sourcing for payment operations - immutable audit trail."""
11
-
12
- class EventType(models.TextChoices):
13
- PAYMENT_CREATED = 'payment_created', 'Payment Created'
14
- WEBHOOK_RECEIVED = 'webhook_received', 'Webhook Received'
15
- WEBHOOK_PROCESSED = 'webhook_processed', 'Webhook Processed'
16
- BALANCE_UPDATED = 'balance_updated', 'Balance Updated'
17
- REFUND_PROCESSED = 'refund_processed', 'Refund Processed'
18
- STATUS_CHANGED = 'status_changed', 'Status Changed'
19
- ERROR_OCCURRED = 'error_occurred', 'Error Occurred'
20
-
21
- # Event identification
22
- payment_id = models.CharField(
23
- max_length=255,
24
- db_index=True,
25
- help_text="Payment identifier"
26
- )
27
- event_type = models.CharField(
28
- max_length=50,
29
- choices=EventType.choices,
30
- db_index=True,
31
- help_text="Type of event"
32
- )
33
- sequence_number = models.PositiveBigIntegerField(
34
- help_text="Sequential number per payment"
35
- )
36
-
37
- # Event data (JSON for flexibility)
38
- event_data = models.JSONField(
39
- help_text="Event data payload"
40
- )
41
-
42
- # Operational metadata
43
- processed_by = models.CharField(
44
- max_length=100,
45
- help_text="Worker/server that processed this event"
46
- )
47
- correlation_id = models.CharField(
48
- max_length=255,
49
- null=True,
50
- blank=True,
51
- help_text="Correlation ID for tracing"
52
- )
53
- idempotency_key = models.CharField(
54
- max_length=255,
55
- unique=True,
56
- help_text="Idempotency key to prevent duplicates"
57
- )
58
-
59
- class Meta:
60
- db_table = 'payment_events'
61
- verbose_name = "Payment Event"
62
- verbose_name_plural = "Payment Events"
63
- indexes = [
64
- models.Index(fields=['payment_id', 'sequence_number']),
65
- models.Index(fields=['event_type', 'created_at']),
66
- models.Index(fields=['idempotency_key']),
67
- models.Index(fields=['correlation_id']),
68
- models.Index(fields=['created_at']),
69
- ]
70
- ordering = ['sequence_number']
71
-
72
- def __str__(self):
73
- return f"Event {self.sequence_number}: {self.event_type} for {self.payment_id}"
@@ -1,57 +0,0 @@
1
- """
2
- DRF serializers for the universal payments system.
3
- """
4
-
5
- from .balance import (
6
- UserBalanceSerializer, TransactionSerializer, TransactionListSerializer
7
- )
8
- from .payments import (
9
- UniversalPaymentSerializer, PaymentCreateSerializer, PaymentListSerializer
10
- )
11
- from .subscriptions import (
12
- SubscriptionSerializer, SubscriptionCreateSerializer, SubscriptionListSerializer,
13
- EndpointGroupSerializer
14
- )
15
- from .api_keys import (
16
- APIKeySerializer, APIKeyCreateSerializer, APIKeyListSerializer
17
- )
18
- from .currencies import (
19
- CurrencySerializer, NetworkSerializer, ProviderCurrencySerializer, CurrencyListSerializer
20
- )
21
- from .tariffs import (
22
- TariffSerializer, TariffEndpointGroupSerializer, TariffListSerializer
23
- )
24
-
25
- __all__ = [
26
- # Balance
27
- 'UserBalanceSerializer',
28
- 'TransactionSerializer',
29
- 'TransactionListSerializer',
30
-
31
- # Payments
32
- 'UniversalPaymentSerializer',
33
- 'PaymentCreateSerializer',
34
- 'PaymentListSerializer',
35
-
36
- # Subscriptions
37
- 'SubscriptionSerializer',
38
- 'SubscriptionCreateSerializer',
39
- 'SubscriptionListSerializer',
40
- 'EndpointGroupSerializer',
41
-
42
- # API Keys
43
- 'APIKeySerializer',
44
- 'APIKeyCreateSerializer',
45
- 'APIKeyListSerializer',
46
-
47
- # Currencies
48
- 'CurrencySerializer',
49
- 'NetworkSerializer',
50
- 'ProviderCurrencySerializer',
51
- 'CurrencyListSerializer',
52
-
53
- # Tariffs
54
- 'TariffSerializer',
55
- 'TariffEndpointGroupSerializer',
56
- 'TariffListSerializer',
57
- ]