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,500 @@
1
+ {% extends 'payments/base.html' %}
2
+ {% load static %}
3
+
4
+ {% block title %}Payment Status - Universal Payment System{% endblock %}
5
+
6
+ {% block page_title %}Payment Status{% endblock %}
7
+ {% block page_subtitle %}Track your payment progress in real-time{% endblock %}
8
+
9
+ {% block extra_css %}
10
+ <style>
11
+ .status-timeline {
12
+ position: relative;
13
+ }
14
+
15
+ .status-timeline::before {
16
+ content: '';
17
+ position: absolute;
18
+ left: 16px;
19
+ top: 0;
20
+ bottom: 0;
21
+ width: 2px;
22
+ background: linear-gradient(to bottom, #3b82f6, #e5e7eb);
23
+ }
24
+
25
+ .timeline-item {
26
+ position: relative;
27
+ padding-left: 48px;
28
+ padding-bottom: 24px;
29
+ }
30
+
31
+ .timeline-item:last-child {
32
+ padding-bottom: 0;
33
+ }
34
+
35
+ .timeline-icon {
36
+ position: absolute;
37
+ left: 0;
38
+ top: 0;
39
+ width: 32px;
40
+ height: 32px;
41
+ border-radius: 50%;
42
+ display: flex;
43
+ align-items: center;
44
+ justify-content: center;
45
+ z-index: 1;
46
+ }
47
+
48
+ .timeline-icon.completed {
49
+ background-color: #10b981;
50
+ color: white;
51
+ }
52
+
53
+ .timeline-icon.current {
54
+ background-color: #3b82f6;
55
+ color: white;
56
+ animation: pulse 2s infinite;
57
+ }
58
+
59
+ .timeline-icon.pending {
60
+ background-color: #e5e7eb;
61
+ color: #6b7280;
62
+ }
63
+
64
+ @keyframes pulse {
65
+ 0%, 100% { transform: scale(1); }
66
+ 50% { transform: scale(1.1); }
67
+ }
68
+
69
+ .payment-qr {
70
+ max-width: 200px;
71
+ margin: 0 auto;
72
+ }
73
+
74
+ .countdown {
75
+ font-variant-numeric: tabular-nums;
76
+ }
77
+ </style>
78
+ {% endblock %}
79
+
80
+ {% block content %}
81
+ <div x-data="paymentStatus('{{ payment.id }}')" x-init="init()" class="max-w-4xl mx-auto">
82
+ <!-- Payment Header -->
83
+ <div class="payment-card mb-8">
84
+ <div class="flex items-center justify-between">
85
+ <div class="flex items-center">
86
+ <div class="w-12 h-12 bg-blue-100 dark:bg-blue-900 rounded-full flex items-center justify-center mr-4">
87
+ <span class="material-icons-outlined text-blue-600 dark:text-blue-400">receipt_long</span>
88
+ </div>
89
+ <div>
90
+ <h1 class="text-2xl font-bold text-gray-900 dark:text-white">Payment #{{ payment.external_id|default:payment.id|truncatechars:8 }}</h1>
91
+ <p class="text-gray-600 dark:text-gray-400">Created {{ payment.created_at|date:"M d, Y H:i" }}</p>
92
+ </div>
93
+ </div>
94
+
95
+ <div class="text-right">
96
+ <div class="text-2xl font-bold text-gray-900 dark:text-white">
97
+ ${{ payment.amount_usd|floatformat:2 }}
98
+ </div>
99
+ <div class="text-sm text-gray-600 dark:text-gray-400">
100
+ {{ payment.currency.code }}
101
+ </div>
102
+ </div>
103
+ </div>
104
+ </div>
105
+
106
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
107
+ <!-- Status Timeline -->
108
+ <div class="lg:col-span-2">
109
+ <div class="payment-card">
110
+ <div class="payment-card-header">
111
+ <h2 class="payment-card-title">
112
+ <span class="material-icons-outlined">timeline</span>
113
+ Payment Progress
114
+ </h2>
115
+ <div class="flex items-center">
116
+ <span class="status-indicator" :class="getStatusIndicatorClass(payment.status)"></span>
117
+ <span class="status-badge" :class="getStatusBadgeClass(payment.status)" x-text="payment.status_display"></span>
118
+ </div>
119
+ </div>
120
+
121
+ <div class="payment-card-content">
122
+ <div class="status-timeline">
123
+ <!-- Created -->
124
+ <div class="timeline-item">
125
+ <div class="timeline-icon completed">
126
+ <span class="material-icons-outlined text-sm">add_circle</span>
127
+ </div>
128
+ <div>
129
+ <h3 class="font-medium text-gray-900 dark:text-white">Payment Created</h3>
130
+ <p class="text-sm text-gray-600 dark:text-gray-400">
131
+ Payment request initiated
132
+ </p>
133
+ <p class="text-xs text-gray-500 dark:text-gray-500 mt-1">
134
+ {{ payment.created_at|date:"M d, Y H:i:s" }}
135
+ </p>
136
+ </div>
137
+ </div>
138
+
139
+ <!-- Processing -->
140
+ <div class="timeline-item">
141
+ <div class="timeline-icon" :class="payment.status === 'pending' || payment.status === 'processing' ? 'current' : (payment.status === 'completed' || payment.status === 'confirmed' ? 'completed' : 'pending')">
142
+ <span class="material-icons-outlined text-sm">sync</span>
143
+ </div>
144
+ <div>
145
+ <h3 class="font-medium text-gray-900 dark:text-white">Processing</h3>
146
+ <p class="text-sm text-gray-600 dark:text-gray-400">
147
+ <span x-show="payment.status === 'pending' || payment.status === 'processing'">
148
+ Payment is being processed by {{ payment.provider|title }}
149
+ </span>
150
+ <span x-show="payment.status === 'completed' || payment.status === 'confirmed'">
151
+ Payment processed successfully
152
+ </span>
153
+ <span x-show="payment.status === 'failed' || payment.status === 'cancelled'">
154
+ Payment processing failed
155
+ </span>
156
+ </p>
157
+ <p x-show="payment.updated_at" class="text-xs text-gray-500 dark:text-gray-500 mt-1" x-text="formatDate(payment.updated_at)"></p>
158
+ </div>
159
+ </div>
160
+
161
+ <!-- Confirmation -->
162
+ <div class="timeline-item">
163
+ <div class="timeline-icon" :class="payment.status === 'completed' || payment.status === 'confirmed' ? 'completed' : 'pending'">
164
+ <span class="material-icons-outlined text-sm">check_circle</span>
165
+ </div>
166
+ <div>
167
+ <h3 class="font-medium text-gray-900 dark:text-white">Confirmation</h3>
168
+ <p class="text-sm text-gray-600 dark:text-gray-400">
169
+ <span x-show="payment.status === 'completed' || payment.status === 'confirmed'">
170
+ Payment confirmed and completed
171
+ </span>
172
+ <span x-show="payment.status !== 'completed' && payment.status !== 'confirmed'">
173
+ Waiting for confirmation
174
+ </span>
175
+ </p>
176
+ <p x-show="payment.confirmed_at" class="text-xs text-gray-500 dark:text-gray-500 mt-1" x-text="formatDate(payment.confirmed_at)"></p>
177
+ </div>
178
+ </div>
179
+ </div>
180
+ </div>
181
+ </div>
182
+
183
+ <!-- Transaction Details -->
184
+ <div class="payment-card mt-8">
185
+ <div class="payment-card-header">
186
+ <h2 class="payment-card-title">
187
+ <span class="material-icons-outlined">info</span>
188
+ Transaction Details
189
+ </h2>
190
+ </div>
191
+
192
+ <div class="payment-card-content">
193
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
194
+ <div>
195
+ <h4 class="font-medium text-gray-900 dark:text-white mb-3">Payment Information</h4>
196
+ <div class="space-y-2 text-sm">
197
+ <div class="flex justify-between">
198
+ <span class="text-gray-600 dark:text-gray-400">Payment ID:</span>
199
+ <span class="font-mono" data-copy="{{ payment.id }}">{{ payment.id|truncatechars:12 }}</span>
200
+ </div>
201
+ <div class="flex justify-between">
202
+ <span class="text-gray-600 dark:text-gray-400">External ID:</span>
203
+ <span class="font-mono" x-text="payment.external_id || 'N/A'"></span>
204
+ </div>
205
+ <div class="flex justify-between">
206
+ <span class="text-gray-600 dark:text-gray-400">Provider:</span>
207
+ <span x-text="payment.provider"></span>
208
+ </div>
209
+ <div class="flex justify-between">
210
+ <span class="text-gray-600 dark:text-gray-400">Network:</span>
211
+ <span x-text="payment.network || 'N/A'"></span>
212
+ </div>
213
+ </div>
214
+ </div>
215
+
216
+ <div>
217
+ <h4 class="font-medium text-gray-900 dark:text-white mb-3">Amount Details</h4>
218
+ <div class="space-y-2 text-sm">
219
+ <div class="flex justify-between">
220
+ <span class="text-gray-600 dark:text-gray-400">USD Amount:</span>
221
+ <span class="font-medium">${{ payment.amount_usd|floatformat:2 }}</span>
222
+ </div>
223
+ <div class="flex justify-between">
224
+ <span class="text-gray-600 dark:text-gray-400">Crypto Amount:</span>
225
+ <span class="font-mono" x-text="payment.amount_crypto || 'N/A'"></span>
226
+ </div>
227
+ <div class="flex justify-between">
228
+ <span class="text-gray-600 dark:text-gray-400">Currency:</span>
229
+ <span x-text="payment.currency_code"></span>
230
+ </div>
231
+ <div class="flex justify-between">
232
+ <span class="text-gray-600 dark:text-gray-400">Exchange Rate:</span>
233
+ <span x-text="payment.exchange_rate || 'N/A'"></span>
234
+ </div>
235
+ </div>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ </div>
241
+
242
+ <!-- Payment Actions Sidebar -->
243
+ <div class="space-y-6">
244
+ <!-- Quick Actions -->
245
+ <div class="payment-card">
246
+ <div class="payment-card-header">
247
+ <h3 class="payment-card-title">
248
+ <span class="material-icons-outlined">bolt</span>
249
+ Quick Actions
250
+ </h3>
251
+ </div>
252
+
253
+ <div class="payment-card-content space-y-3">
254
+ <button @click="refreshPayment()"
255
+ :disabled="loading"
256
+ class="btn-primary w-full">
257
+ <span x-show="!loading" class="material-icons-outlined">refresh</span>
258
+ <span x-show="loading" class="loading-spinner sm mr-2"></span>
259
+ <span x-text="loading ? 'Refreshing...' : 'Refresh Status'"></span>
260
+ </button>
261
+
262
+ <button @click="copyPaymentUrl()" class="btn-outline w-full">
263
+ <span class="material-icons-outlined">share</span>
264
+ Share Payment
265
+ </button>
266
+
267
+ <button @click="downloadReceipt()"
268
+ x-show="payment.status === 'completed' || payment.status === 'confirmed'"
269
+ class="btn-outline w-full">
270
+ <span class="material-icons-outlined">download</span>
271
+ Download Receipt
272
+ </button>
273
+ </div>
274
+ </div>
275
+
276
+ <!-- Payment QR Code -->
277
+ <div x-show="payment.qr_code_url || payment.payment_url" class="payment-card">
278
+ <div class="payment-card-header">
279
+ <h3 class="payment-card-title">
280
+ <span class="material-icons-outlined">qr_code</span>
281
+ Payment QR Code
282
+ </h3>
283
+ </div>
284
+
285
+ <div class="payment-card-content text-center">
286
+ <div class="payment-qr mb-4">
287
+ <div x-show="payment.qr_code_url" class="bg-white p-4 rounded-lg inline-block">
288
+ <img :src="payment.qr_code_url" alt="Payment QR Code" class="w-full h-auto">
289
+ </div>
290
+ <div x-show="!payment.qr_code_url" class="bg-gray-100 dark:bg-gray-700 p-8 rounded-lg">
291
+ <span class="material-icons-outlined text-gray-400 text-4xl">qr_code</span>
292
+ <p class="text-sm text-gray-500 mt-2">QR Code not available</p>
293
+ </div>
294
+ </div>
295
+
296
+ <button x-show="payment.payment_url"
297
+ @click="copyToClipboard(payment.payment_url)"
298
+ class="btn-outline w-full text-sm">
299
+ <span class="material-icons-outlined">content_copy</span>
300
+ Copy Payment URL
301
+ </button>
302
+ </div>
303
+ </div>
304
+
305
+ <!-- Auto-refresh Settings -->
306
+ <div class="payment-card">
307
+ <div class="payment-card-header">
308
+ <h3 class="payment-card-title">
309
+ <span class="material-icons-outlined">settings</span>
310
+ Auto-refresh
311
+ </h3>
312
+ </div>
313
+
314
+ <div class="payment-card-content">
315
+ <div class="flex items-center justify-between">
316
+ <span class="text-sm text-gray-600 dark:text-gray-400">Enable auto-refresh</span>
317
+ <label class="relative inline-flex items-center cursor-pointer">
318
+ <input type="checkbox" x-model="autoRefresh" @change="toggleAutoRefresh()" class="sr-only peer">
319
+ <div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600"></div>
320
+ </label>
321
+ </div>
322
+
323
+ <div x-show="autoRefresh" class="mt-3">
324
+ <div class="flex items-center justify-between text-sm">
325
+ <span class="text-gray-600 dark:text-gray-400">Next refresh in:</span>
326
+ <span class="countdown font-mono" x-text="formatCountdown(refreshCountdown)"></span>
327
+ </div>
328
+ <div class="w-full bg-gray-200 rounded-full h-1 mt-2">
329
+ <div class="bg-blue-600 h-1 rounded-full transition-all duration-1000"
330
+ :style="`width: ${(refreshCountdown / refreshInterval) * 100}%`"></div>
331
+ </div>
332
+ </div>
333
+ </div>
334
+ </div>
335
+
336
+ <!-- Support -->
337
+ <div class="payment-card">
338
+ <div class="payment-card-header">
339
+ <h3 class="payment-card-title">
340
+ <span class="material-icons-outlined">support_agent</span>
341
+ Need Help?
342
+ </h3>
343
+ </div>
344
+
345
+ <div class="payment-card-content space-y-3">
346
+ <a href="#" class="flex items-center text-sm text-blue-600 hover:text-blue-800">
347
+ <span class="material-icons-outlined mr-2 text-sm">help</span>
348
+ Payment FAQ
349
+ </a>
350
+ <a href="#" class="flex items-center text-sm text-blue-600 hover:text-blue-800">
351
+ <span class="material-icons-outlined mr-2 text-sm">chat</span>
352
+ Contact Support
353
+ </a>
354
+ <a href="#" class="flex items-center text-sm text-blue-600 hover:text-blue-800">
355
+ <span class="material-icons-outlined mr-2 text-sm">bug_report</span>
356
+ Report Issue
357
+ </a>
358
+ </div>
359
+ </div>
360
+ </div>
361
+ </div>
362
+ </div>
363
+ {% endblock %}
364
+
365
+ {% block extra_js %}
366
+ <script>
367
+ function paymentStatus(paymentId) {
368
+ return {
369
+ payment: {
370
+ id: '{{ payment.id }}',
371
+ external_id: '{{ payment.external_id|default:"" }}',
372
+ status: '{{ payment.status }}',
373
+ status_display: '{{ payment.get_status_display }}',
374
+ amount_usd: {{ payment.amount_usd }},
375
+ currency_code: '{{ payment.currency.code }}',
376
+ provider: '{{ payment.provider }}',
377
+ created_at: '{{ payment.created_at|date:"c" }}',
378
+ updated_at: '{{ payment.updated_at|date:"c" }}',
379
+ payment_url: '{{ payment.payment_url|default:"" }}',
380
+ qr_code_url: '{{ payment.qr_code_url|default:"" }}'
381
+ },
382
+ loading: false,
383
+ autoRefresh: false,
384
+ refreshInterval: 30000, // 30 seconds
385
+ refreshCountdown: 30,
386
+ refreshTimer: null,
387
+ countdownTimer: null,
388
+
389
+ async init() {
390
+ // Auto-enable refresh for pending payments
391
+ if (this.payment.status === 'pending' || this.payment.status === 'processing') {
392
+ this.autoRefresh = true;
393
+ this.toggleAutoRefresh();
394
+ }
395
+ },
396
+
397
+ async refreshPayment() {
398
+ this.loading = true;
399
+ try {
400
+ const response = await fetch(`/payments/api/payments/${this.payment.id}/`);
401
+ const data = await response.json();
402
+
403
+ if (response.ok) {
404
+ this.payment = { ...this.payment, ...data };
405
+ PaymentSystem.Utils.showNotification('Payment status updated', 'success', 'refresh');
406
+
407
+ // Disable auto-refresh if payment is completed
408
+ if (this.payment.status === 'completed' || this.payment.status === 'failed') {
409
+ this.autoRefresh = false;
410
+ this.toggleAutoRefresh();
411
+ }
412
+ } else {
413
+ throw new Error(data.error || 'Failed to refresh payment');
414
+ }
415
+ } catch (error) {
416
+ console.error('Failed to refresh payment:', error);
417
+ PaymentSystem.Utils.showNotification('Failed to refresh payment status', 'error', 'error');
418
+ } finally {
419
+ this.loading = false;
420
+ }
421
+ },
422
+
423
+ toggleAutoRefresh() {
424
+ if (this.autoRefresh) {
425
+ this.startAutoRefresh();
426
+ } else {
427
+ this.stopAutoRefresh();
428
+ }
429
+ },
430
+
431
+ startAutoRefresh() {
432
+ this.refreshCountdown = this.refreshInterval / 1000;
433
+
434
+ this.refreshTimer = setInterval(() => {
435
+ this.refreshPayment();
436
+ this.refreshCountdown = this.refreshInterval / 1000;
437
+ }, this.refreshInterval);
438
+
439
+ this.countdownTimer = setInterval(() => {
440
+ this.refreshCountdown--;
441
+ if (this.refreshCountdown <= 0) {
442
+ this.refreshCountdown = this.refreshInterval / 1000;
443
+ }
444
+ }, 1000);
445
+ },
446
+
447
+ stopAutoRefresh() {
448
+ if (this.refreshTimer) {
449
+ clearInterval(this.refreshTimer);
450
+ this.refreshTimer = null;
451
+ }
452
+ if (this.countdownTimer) {
453
+ clearInterval(this.countdownTimer);
454
+ this.countdownTimer = null;
455
+ }
456
+ },
457
+
458
+ copyPaymentUrl() {
459
+ const url = window.location.href;
460
+ PaymentSystem.Utils.copyToClipboard(url, 'Payment URL copied to clipboard!');
461
+ },
462
+
463
+ copyToClipboard(text) {
464
+ PaymentSystem.Utils.copyToClipboard(text);
465
+ },
466
+
467
+ downloadReceipt() {
468
+ // This would generate and download a PDF receipt
469
+ PaymentSystem.Utils.showNotification('Receipt download started', 'info', 'download');
470
+ },
471
+
472
+ getStatusIndicatorClass(status) {
473
+ const statusMap = {
474
+ 'completed': 'status-active',
475
+ 'confirmed': 'status-active',
476
+ 'pending': 'status-warning',
477
+ 'processing': 'status-warning',
478
+ 'failed': 'status-inactive',
479
+ 'cancelled': 'status-inactive'
480
+ };
481
+ return statusMap[status] || 'status-warning';
482
+ },
483
+
484
+ getStatusBadgeClass(status) {
485
+ return PaymentSystem.Utils.getStatusBadgeClass(status);
486
+ },
487
+
488
+ formatDate(dateString) {
489
+ return PaymentSystem.Utils.formatDate(dateString);
490
+ },
491
+
492
+ formatCountdown(seconds) {
493
+ const mins = Math.floor(seconds / 60);
494
+ const secs = seconds % 60;
495
+ return `${mins}:${secs.toString().padStart(2, '0')}`;
496
+ }
497
+ }
498
+ }
499
+ </script>
500
+ {% endblock %}