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
@@ -0,0 +1,387 @@
1
+ """
2
+ Payment serializers for the Universal Payment System v2.0.
3
+
4
+ DRF serializers with Pydantic integration and service layer validation.
5
+ """
6
+
7
+ from rest_framework import serializers
8
+ from decimal import Decimal
9
+ from typing import Dict, Any
10
+ from django.contrib.auth import get_user_model
11
+
12
+ from ...models import UniversalPayment
13
+ from ...services import get_payment_service, PaymentCreateRequest, PaymentStatusRequest
14
+ from django_cfg.modules.django_logger import get_logger
15
+
16
+ User = get_user_model()
17
+ logger = get_logger("payment_serializers")
18
+
19
+
20
+ class PaymentListSerializer(serializers.ModelSerializer):
21
+ """
22
+ Lightweight serializer for payment lists.
23
+
24
+ Optimized for list views with minimal data.
25
+ """
26
+
27
+ status_display = serializers.CharField(source='get_status_display', read_only=True)
28
+ amount_display = serializers.CharField(source='amount_display', read_only=True)
29
+ crypto_amount_display = serializers.CharField(source='crypto_amount_display', read_only=True)
30
+
31
+ class Meta:
32
+ model = UniversalPayment
33
+ fields = [
34
+ 'id',
35
+ 'amount_usd',
36
+ 'crypto_amount',
37
+ 'currency_code',
38
+ 'provider',
39
+ 'status',
40
+ 'status_display',
41
+ 'amount_display',
42
+ 'crypto_amount_display',
43
+ 'created_at',
44
+ 'expires_at',
45
+ ]
46
+ read_only_fields = fields
47
+
48
+
49
+ class PaymentSerializer(serializers.ModelSerializer):
50
+ """
51
+ Complete payment serializer with full details.
52
+
53
+ Used for detail views and updates.
54
+ """
55
+
56
+ user = serializers.StringRelatedField(read_only=True)
57
+ status_display = serializers.CharField(source='get_status_display', read_only=True)
58
+ status_color = serializers.CharField(source='status_color', read_only=True)
59
+ amount_display = serializers.CharField(source='amount_display', read_only=True)
60
+ crypto_amount_display = serializers.CharField(source='crypto_amount_display', read_only=True)
61
+
62
+ # Status check methods
63
+ is_pending = serializers.BooleanField(source='is_pending', read_only=True)
64
+ is_completed = serializers.BooleanField(source='is_completed', read_only=True)
65
+ is_failed = serializers.BooleanField(source='is_failed', read_only=True)
66
+ is_expired = serializers.BooleanField(source='is_expired', read_only=True)
67
+ can_be_cancelled = serializers.BooleanField(source='can_be_cancelled', read_only=True)
68
+ can_be_refunded = serializers.BooleanField(source='can_be_refunded', read_only=True)
69
+
70
+ class Meta:
71
+ model = UniversalPayment
72
+ fields = [
73
+ 'id',
74
+ 'user',
75
+ 'amount_usd',
76
+ 'crypto_amount',
77
+ 'currency_code',
78
+ 'provider',
79
+ 'status',
80
+ 'status_display',
81
+ 'status_color',
82
+ 'amount_display',
83
+ 'crypto_amount_display',
84
+ 'provider_payment_id',
85
+ 'payment_url',
86
+ 'qr_code_url',
87
+ 'wallet_address',
88
+ 'callback_url',
89
+ 'cancel_url',
90
+ 'description',
91
+ 'metadata',
92
+ 'transaction_hash',
93
+ 'confirmation_blocks',
94
+ 'created_at',
95
+ 'updated_at',
96
+ 'expires_at',
97
+ 'completed_at',
98
+ # Status methods
99
+ 'is_pending',
100
+ 'is_completed',
101
+ 'is_failed',
102
+ 'is_expired',
103
+ 'can_be_cancelled',
104
+ 'can_be_refunded',
105
+ ]
106
+ read_only_fields = [
107
+ 'id',
108
+ 'user',
109
+ 'crypto_amount',
110
+ 'provider_payment_id',
111
+ 'payment_url',
112
+ 'qr_code_url',
113
+ 'wallet_address',
114
+ 'transaction_hash',
115
+ 'confirmation_blocks',
116
+ 'created_at',
117
+ 'updated_at',
118
+ 'completed_at',
119
+ 'status_display',
120
+ 'status_color',
121
+ 'amount_display',
122
+ 'crypto_amount_display',
123
+ 'is_pending',
124
+ 'is_completed',
125
+ 'is_failed',
126
+ 'is_expired',
127
+ 'can_be_cancelled',
128
+ 'can_be_refunded',
129
+ ]
130
+
131
+
132
+ class PaymentCreateSerializer(serializers.Serializer):
133
+ """
134
+ Payment creation serializer with Pydantic integration.
135
+
136
+ Validates input and delegates to PaymentService.
137
+ """
138
+
139
+ amount_usd = serializers.FloatField(
140
+ min_value=1.0,
141
+ max_value=50000.0,
142
+ help_text="Amount in USD (1.00 - 50,000.00)"
143
+ )
144
+ currency_code = serializers.ChoiceField(
145
+ choices=[
146
+ ('BTC', 'Bitcoin'),
147
+ ('ETH', 'Ethereum'),
148
+ ('LTC', 'Litecoin'),
149
+ ('XMR', 'Monero'),
150
+ ('USDT', 'Tether'),
151
+ ('USDC', 'USD Coin'),
152
+ ('ADA', 'Cardano'),
153
+ ('DOT', 'Polkadot'),
154
+ ],
155
+ help_text="Cryptocurrency to receive"
156
+ )
157
+ provider = serializers.ChoiceField(
158
+ choices=[('nowpayments', 'NowPayments')],
159
+ default='nowpayments',
160
+ help_text="Payment provider"
161
+ )
162
+ callback_url = serializers.URLField(
163
+ required=False,
164
+ allow_blank=True,
165
+ help_text="Success callback URL"
166
+ )
167
+ cancel_url = serializers.URLField(
168
+ required=False,
169
+ allow_blank=True,
170
+ help_text="Cancellation URL"
171
+ )
172
+ description = serializers.CharField(
173
+ required=False,
174
+ allow_blank=True,
175
+ max_length=500,
176
+ help_text="Payment description"
177
+ )
178
+ metadata = serializers.JSONField(
179
+ required=False,
180
+ default=dict,
181
+ help_text="Additional metadata"
182
+ )
183
+
184
+ def validate(self, attrs: Dict[str, Any]) -> Dict[str, Any]:
185
+ """Validate payment creation data."""
186
+ try:
187
+ # Create Pydantic request for validation
188
+ request = PaymentCreateRequest(
189
+ user_id=self.context['request'].user.id,
190
+ **attrs
191
+ )
192
+
193
+ # Store validated request for create method
194
+ self._validated_request = request
195
+ return attrs
196
+
197
+ except Exception as e:
198
+ logger.error(f"Payment validation failed: {e}")
199
+ raise serializers.ValidationError(f"Invalid payment data: {e}")
200
+
201
+ def create(self, validated_data: Dict[str, Any]) -> UniversalPayment:
202
+ """Create payment using PaymentService."""
203
+ try:
204
+ payment_service = get_payment_service()
205
+
206
+ # Use pre-validated Pydantic request
207
+ result = payment_service.create_payment(self._validated_request)
208
+
209
+ if result.success:
210
+ # Get the created payment from database
211
+ payment = UniversalPayment.objects.get(id=result.payment_id)
212
+
213
+ logger.info(f"Payment created successfully", extra={
214
+ 'payment_id': result.payment_id,
215
+ 'user_id': self._validated_request.user_id,
216
+ 'amount_usd': self._validated_request.amount_usd
217
+ })
218
+
219
+ return payment
220
+ else:
221
+ logger.error(f"Payment creation failed: {result.message}")
222
+ raise serializers.ValidationError(result.message)
223
+
224
+ except Exception as e:
225
+ logger.error(f"Payment creation error: {e}")
226
+ raise serializers.ValidationError(f"Payment creation failed: {e}")
227
+
228
+ def to_representation(self, instance: UniversalPayment) -> Dict[str, Any]:
229
+ """Return full payment data after creation."""
230
+ return PaymentSerializer(instance, context=self.context).data
231
+
232
+
233
+ class PaymentStatusSerializer(serializers.Serializer):
234
+ """
235
+ Payment status check serializer.
236
+
237
+ Used for checking payment status via provider API.
238
+ """
239
+
240
+ force_provider_check = serializers.BooleanField(
241
+ default=False,
242
+ help_text="Force check with payment provider"
243
+ )
244
+
245
+ def validate(self, attrs: Dict[str, Any]) -> Dict[str, Any]:
246
+ """Validate status check request."""
247
+ payment_id = self.context.get('payment_id')
248
+ if not payment_id:
249
+ raise serializers.ValidationError("Payment ID is required")
250
+
251
+ user = self.context['request'].user
252
+
253
+ # Create Pydantic request
254
+ self._status_request = PaymentStatusRequest(
255
+ payment_id=payment_id,
256
+ user_id=user.id,
257
+ force_provider_check=attrs.get('force_provider_check', False)
258
+ )
259
+
260
+ return attrs
261
+
262
+ def save(self) -> Dict[str, Any]:
263
+ """Check payment status using PaymentService."""
264
+ try:
265
+ payment_service = get_payment_service()
266
+ result = payment_service.get_payment_status(self._status_request)
267
+
268
+ if result.success:
269
+ # Get updated payment from database
270
+ payment = UniversalPayment.objects.get(id=result.payment_id)
271
+
272
+ return {
273
+ 'success': True,
274
+ 'payment': PaymentSerializer(payment, context=self.context).data,
275
+ 'provider_checked': self._status_request.force_provider_check,
276
+ 'message': result.message
277
+ }
278
+ else:
279
+ return {
280
+ 'success': False,
281
+ 'error': result.message,
282
+ 'error_code': result.error_code
283
+ }
284
+
285
+ except Exception as e:
286
+ logger.error(f"Payment status check error: {e}")
287
+ return {
288
+ 'success': False,
289
+ 'error': f"Status check failed: {e}",
290
+ 'error_code': 'status_check_error'
291
+ }
292
+
293
+
294
+ class PaymentCancelSerializer(serializers.Serializer):
295
+ """
296
+ Payment cancellation serializer.
297
+
298
+ Used for cancelling payments.
299
+ """
300
+
301
+ reason = serializers.CharField(
302
+ required=False,
303
+ allow_blank=True,
304
+ max_length=500,
305
+ help_text="Cancellation reason"
306
+ )
307
+
308
+ def save(self) -> Dict[str, Any]:
309
+ """Cancel payment using PaymentService."""
310
+ try:
311
+ payment_id = self.context.get('payment_id')
312
+ if not payment_id:
313
+ raise serializers.ValidationError("Payment ID is required")
314
+
315
+ payment_service = get_payment_service()
316
+ result = payment_service.cancel_payment(
317
+ payment_id=payment_id,
318
+ reason=self.validated_data.get('reason')
319
+ )
320
+
321
+ if result.success:
322
+ # Get updated payment
323
+ payment = UniversalPayment.objects.get(id=result.payment_id)
324
+
325
+ return {
326
+ 'success': True,
327
+ 'payment': PaymentSerializer(payment, context=self.context).data,
328
+ 'message': result.message
329
+ }
330
+ else:
331
+ return {
332
+ 'success': False,
333
+ 'error': result.message,
334
+ 'error_code': result.error_code
335
+ }
336
+
337
+ except Exception as e:
338
+ logger.error(f"Payment cancellation error: {e}")
339
+ return {
340
+ 'success': False,
341
+ 'error': f"Cancellation failed: {e}",
342
+ 'error_code': 'cancellation_error'
343
+ }
344
+
345
+
346
+ class PaymentStatsSerializer(serializers.Serializer):
347
+ """
348
+ Payment statistics serializer.
349
+
350
+ Used for payment analytics and reporting.
351
+ """
352
+
353
+ days = serializers.IntegerField(
354
+ default=30,
355
+ min_value=1,
356
+ max_value=365,
357
+ help_text="Number of days to analyze"
358
+ )
359
+
360
+ def save(self) -> Dict[str, Any]:
361
+ """Get payment statistics using PaymentService."""
362
+ try:
363
+ payment_service = get_payment_service()
364
+ result = payment_service.get_payment_stats(
365
+ days=self.validated_data['days']
366
+ )
367
+
368
+ if result.success:
369
+ return {
370
+ 'success': True,
371
+ 'stats': result.data,
372
+ 'message': result.message
373
+ }
374
+ else:
375
+ return {
376
+ 'success': False,
377
+ 'error': result.message,
378
+ 'error_code': result.error_code
379
+ }
380
+
381
+ except Exception as e:
382
+ logger.error(f"Payment stats error: {e}")
383
+ return {
384
+ 'success': False,
385
+ 'error': f"Stats generation failed: {e}",
386
+ 'error_code': 'stats_error'
387
+ }