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,545 @@
1
+ /**
2
+ * Universal Payment System v2.0 - Component Functions
3
+ *
4
+ * Reusable Alpine.js components and interactive functionality.
5
+ */
6
+
7
+ // Ensure PaymentSystem namespace exists
8
+ window.PaymentSystem = window.PaymentSystem || {};
9
+
10
+ /**
11
+ * Alpine.js Components
12
+ */
13
+ PaymentSystem.Components = {
14
+ /**
15
+ * Webhook Dashboard Component
16
+ */
17
+ webhookDashboard: function() {
18
+ return {
19
+ loading: true,
20
+ providers: [],
21
+ ngrokStatus: {
22
+ active: false,
23
+ url: null,
24
+ description: 'Checking...'
25
+ },
26
+ healthStatus: {
27
+ healthy: false,
28
+ description: 'Checking...',
29
+ last_check: null
30
+ },
31
+ stats: {
32
+ total_webhooks: 0,
33
+ successful_webhooks: 0,
34
+ failed_webhooks: 0,
35
+ recent_count: 0,
36
+ recent_activity: []
37
+ },
38
+ showTestModal: false,
39
+ testProvider: '',
40
+ testData: '{"payment_id": "test_123", "status": "completed", "amount": "10.00"}',
41
+ testLoading: false,
42
+ lastTest: null,
43
+ testStatus: null,
44
+
45
+ async init() {
46
+ await this.loadData();
47
+ },
48
+
49
+ async loadData() {
50
+ this.loading = true;
51
+ try {
52
+ await Promise.all([
53
+ this.loadProviders(),
54
+ this.checkHealth(),
55
+ this.loadStats()
56
+ ]);
57
+ } catch (error) {
58
+ console.error('Failed to load dashboard data:', error);
59
+ PaymentSystem.Utils.showNotification('Failed to load dashboard data', 'error');
60
+ } finally {
61
+ this.loading = false;
62
+ }
63
+ },
64
+
65
+ async loadProviders() {
66
+ try {
67
+ const response = await fetch('/api/payments/webhooks/providers/');
68
+ const data = await response.json();
69
+
70
+ if (data.success) {
71
+ this.providers = data.providers || [];
72
+ } else {
73
+ throw new Error(data.error || 'Failed to load providers');
74
+ }
75
+ } catch (error) {
76
+ console.error('Failed to load providers:', error);
77
+ this.providers = [];
78
+ }
79
+ },
80
+
81
+ async checkHealth() {
82
+ try {
83
+ const response = await fetch('/api/payments/webhooks/health/');
84
+ const data = await response.json();
85
+
86
+ this.healthStatus = {
87
+ healthy: data.status === 'healthy',
88
+ description: data.status === 'healthy' ? 'Service healthy' : (data.error || 'Unknown status'),
89
+ last_check: new Date().toLocaleString()
90
+ };
91
+
92
+ // Update ngrok status from details
93
+ const ngrokAvailable = data.details?.ngrok_available || false;
94
+ this.ngrokStatus = {
95
+ active: ngrokAvailable,
96
+ url: data.details?.api_base_url || null,
97
+ description: ngrokAvailable ? 'Tunnel active' : 'Tunnel inactive'
98
+ };
99
+ } catch (error) {
100
+ console.error('Failed to check health:', error);
101
+ this.healthStatus = {
102
+ healthy: false,
103
+ description: 'Health check failed',
104
+ last_check: new Date().toLocaleString()
105
+ };
106
+ }
107
+ },
108
+
109
+ async loadStats() {
110
+ try {
111
+ const response = await fetch('/api/payments/webhooks/stats/');
112
+ const data = await response.json();
113
+
114
+ if (data.success) {
115
+ this.stats = {
116
+ total_webhooks: data.stats.total_webhooks || 0,
117
+ successful_webhooks: data.stats.successful_webhooks || 0,
118
+ failed_webhooks: data.stats.failed_webhooks || 0,
119
+ recent_count: data.stats.recent_count || 0,
120
+ recent_activity: data.stats.recent_activity || []
121
+ };
122
+ }
123
+ } catch (error) {
124
+ console.error('Failed to load stats:', error);
125
+ this.stats = {
126
+ total_webhooks: 0,
127
+ successful_webhooks: 0,
128
+ failed_webhooks: 0,
129
+ recent_count: 0,
130
+ recent_activity: []
131
+ };
132
+ }
133
+ },
134
+
135
+ async refreshData() {
136
+ await this.loadData();
137
+ PaymentSystem.Utils.showNotification('Dashboard data refreshed', 'success', 'refresh');
138
+ },
139
+
140
+ async checkNgrokStatus() {
141
+ await this.checkHealth();
142
+ PaymentSystem.Utils.showNotification('Ngrok status updated', 'info', 'network_check');
143
+ },
144
+
145
+ async sendTestWebhook() {
146
+ if (!this.testProvider) {
147
+ PaymentSystem.Utils.showNotification('Please select a provider', 'warning', 'warning');
148
+ return;
149
+ }
150
+
151
+ this.testLoading = true;
152
+ try {
153
+ const provider = this.providers.find(p => p.name === this.testProvider);
154
+ if (!provider) {
155
+ throw new Error('Provider not found');
156
+ }
157
+
158
+ const response = await fetch(provider.webhook_url, {
159
+ method: 'POST',
160
+ headers: {
161
+ 'Content-Type': 'application/json',
162
+ [provider.signature_header]: 'test-signature'
163
+ },
164
+ body: this.testData
165
+ });
166
+
167
+ this.lastTest = new Date().toLocaleString();
168
+ this.testStatus = response.ok ? 'Success' : 'Failed';
169
+
170
+ PaymentSystem.Utils.showNotification(
171
+ `Test webhook ${response.ok ? 'sent successfully' : 'failed'}`,
172
+ response.ok ? 'success' : 'error',
173
+ response.ok ? 'check_circle' : 'error'
174
+ );
175
+
176
+ this.showTestModal = false;
177
+ } catch (error) {
178
+ console.error('Test webhook failed:', error);
179
+ this.testStatus = 'Error';
180
+ PaymentSystem.Utils.showNotification('Failed to send test webhook', 'error', 'error');
181
+ } finally {
182
+ this.testLoading = false;
183
+ }
184
+ },
185
+
186
+ copyToClipboard(text) {
187
+ PaymentSystem.Utils.copyToClipboard(text);
188
+ }
189
+ }
190
+ },
191
+
192
+ /**
193
+ * Payment Form Component
194
+ */
195
+ paymentForm: function() {
196
+ return {
197
+ formData: {
198
+ amount: '',
199
+ currency: 'USD',
200
+ provider: '',
201
+ callback_url: ''
202
+ },
203
+ loading: false,
204
+ errors: {},
205
+ currencies: [],
206
+ providers: [],
207
+
208
+ async init() {
209
+ await this.loadFormData();
210
+ },
211
+
212
+ async loadFormData() {
213
+ try {
214
+ const [currenciesResponse, providersResponse] = await Promise.all([
215
+ fetch('/payments/api/currencies/supported/'),
216
+ fetch('/api/payments/webhooks/providers/')
217
+ ]);
218
+
219
+ const currenciesData = await currenciesResponse.json();
220
+ const providersData = await providersResponse.json();
221
+
222
+ this.currencies = currenciesData.currencies || [];
223
+ this.providers = providersData.providers || [];
224
+ } catch (error) {
225
+ console.error('Failed to load form data:', error);
226
+ PaymentSystem.Utils.showNotification('Failed to load form data', 'error');
227
+ }
228
+ },
229
+
230
+ validateForm() {
231
+ this.errors = {};
232
+
233
+ if (!this.formData.amount || parseFloat(this.formData.amount) <= 0) {
234
+ this.errors.amount = 'Amount must be greater than 0';
235
+ }
236
+
237
+ if (!this.formData.currency) {
238
+ this.errors.currency = 'Currency is required';
239
+ }
240
+
241
+ if (!this.formData.provider) {
242
+ this.errors.provider = 'Provider is required';
243
+ }
244
+
245
+ if (this.formData.callback_url && !PaymentSystem.Utils.isValidUrl(this.formData.callback_url)) {
246
+ this.errors.callback_url = 'Invalid URL format';
247
+ }
248
+
249
+ return Object.keys(this.errors).length === 0;
250
+ },
251
+
252
+ async submitForm() {
253
+ if (!this.validateForm()) {
254
+ PaymentSystem.Utils.showNotification('Please fix form errors', 'warning', 'warning');
255
+ return;
256
+ }
257
+
258
+ this.loading = true;
259
+ try {
260
+ const response = await fetch('/payments/api/payments/create/', {
261
+ method: 'POST',
262
+ headers: {
263
+ 'Content-Type': 'application/json',
264
+ 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
265
+ },
266
+ body: JSON.stringify(this.formData)
267
+ });
268
+
269
+ const data = await response.json();
270
+
271
+ if (response.ok && data.success) {
272
+ PaymentSystem.Utils.showNotification('Payment created successfully', 'success', 'check_circle');
273
+ // Redirect to payment status page
274
+ window.location.href = `/payments/status/${data.payment.id}/`;
275
+ } else {
276
+ throw new Error(data.error || 'Failed to create payment');
277
+ }
278
+ } catch (error) {
279
+ console.error('Payment creation failed:', error);
280
+ PaymentSystem.Utils.showNotification(error.message, 'error', 'error');
281
+ } finally {
282
+ this.loading = false;
283
+ }
284
+ }
285
+ }
286
+ },
287
+
288
+ /**
289
+ * Data Table Component
290
+ */
291
+ dataTable: function(config = {}) {
292
+ return {
293
+ data: [],
294
+ loading: true,
295
+ currentPage: 1,
296
+ perPage: config.perPage || 10,
297
+ totalPages: 1,
298
+ totalItems: 0,
299
+ sortField: config.defaultSort || 'created_at',
300
+ sortDirection: 'desc',
301
+ searchQuery: '',
302
+ filters: {},
303
+ selectedItems: [],
304
+
305
+ async init() {
306
+ await this.loadData();
307
+ },
308
+
309
+ async loadData() {
310
+ this.loading = true;
311
+ try {
312
+ const params = new URLSearchParams({
313
+ page: this.currentPage,
314
+ per_page: this.perPage,
315
+ sort: this.sortField,
316
+ direction: this.sortDirection,
317
+ search: this.searchQuery,
318
+ ...this.filters
319
+ });
320
+
321
+ const response = await fetch(`${config.apiUrl}?${params}`);
322
+ const data = await response.json();
323
+
324
+ if (response.ok) {
325
+ this.data = data.results || data.data || [];
326
+ this.totalPages = Math.ceil((data.count || data.total || 0) / this.perPage);
327
+ this.totalItems = data.count || data.total || 0;
328
+ } else {
329
+ throw new Error(data.error || 'Failed to load data');
330
+ }
331
+ } catch (error) {
332
+ console.error('Failed to load table data:', error);
333
+ PaymentSystem.Utils.showNotification('Failed to load data', 'error');
334
+ } finally {
335
+ this.loading = false;
336
+ }
337
+ },
338
+
339
+ async sort(field) {
340
+ if (this.sortField === field) {
341
+ this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
342
+ } else {
343
+ this.sortField = field;
344
+ this.sortDirection = 'asc';
345
+ }
346
+ this.currentPage = 1;
347
+ await this.loadData();
348
+ },
349
+
350
+ async search() {
351
+ this.currentPage = 1;
352
+ await this.loadData();
353
+ },
354
+
355
+ async goToPage(page) {
356
+ if (page >= 1 && page <= this.totalPages) {
357
+ this.currentPage = page;
358
+ await this.loadData();
359
+ }
360
+ },
361
+
362
+ async applyFilters(newFilters) {
363
+ this.filters = { ...this.filters, ...newFilters };
364
+ this.currentPage = 1;
365
+ await this.loadData();
366
+ },
367
+
368
+ toggleSelection(item) {
369
+ const index = this.selectedItems.findIndex(selected => selected.id === item.id);
370
+ if (index > -1) {
371
+ this.selectedItems.splice(index, 1);
372
+ } else {
373
+ this.selectedItems.push(item);
374
+ }
375
+ },
376
+
377
+ selectAll() {
378
+ if (this.selectedItems.length === this.data.length) {
379
+ this.selectedItems = [];
380
+ } else {
381
+ this.selectedItems = [...this.data];
382
+ }
383
+ },
384
+
385
+ isSelected(item) {
386
+ return this.selectedItems.some(selected => selected.id === item.id);
387
+ }
388
+ }
389
+ },
390
+
391
+ /**
392
+ * Modal Component
393
+ */
394
+ modal: function(config = {}) {
395
+ return {
396
+ show: false,
397
+ title: config.title || 'Modal',
398
+ size: config.size || 'md',
399
+ closable: config.closable !== false,
400
+
401
+ open() {
402
+ this.show = true;
403
+ document.body.style.overflow = 'hidden';
404
+ },
405
+
406
+ close() {
407
+ if (this.closable) {
408
+ this.show = false;
409
+ document.body.style.overflow = '';
410
+ }
411
+ },
412
+
413
+ onEscape(event) {
414
+ if (event.key === 'Escape' && this.closable) {
415
+ this.close();
416
+ }
417
+ }
418
+ }
419
+ },
420
+
421
+ /**
422
+ * Status Monitor Component
423
+ */
424
+ statusMonitor: function(config = {}) {
425
+ return {
426
+ status: 'checking',
427
+ lastCheck: null,
428
+ interval: null,
429
+ checkUrl: config.checkUrl,
430
+ intervalMs: config.intervalMs || 30000,
431
+
432
+ async init() {
433
+ await this.checkStatus();
434
+ this.startMonitoring();
435
+ },
436
+
437
+ async checkStatus() {
438
+ try {
439
+ const response = await fetch(this.checkUrl);
440
+ const data = await response.json();
441
+
442
+ this.status = data.status || 'unknown';
443
+ this.lastCheck = new Date().toLocaleString();
444
+ } catch (error) {
445
+ console.error('Status check failed:', error);
446
+ this.status = 'error';
447
+ this.lastCheck = new Date().toLocaleString();
448
+ }
449
+ },
450
+
451
+ startMonitoring() {
452
+ if (this.interval) {
453
+ clearInterval(this.interval);
454
+ }
455
+
456
+ this.interval = setInterval(() => {
457
+ this.checkStatus();
458
+ }, this.intervalMs);
459
+ },
460
+
461
+ stopMonitoring() {
462
+ if (this.interval) {
463
+ clearInterval(this.interval);
464
+ this.interval = null;
465
+ }
466
+ },
467
+
468
+ getStatusIcon() {
469
+ return PaymentSystem.Utils.getStatusIcon(this.status);
470
+ },
471
+
472
+ getStatusClass() {
473
+ return PaymentSystem.Utils.getStatusBadgeClass(this.status);
474
+ }
475
+ }
476
+ }
477
+ };
478
+
479
+ /**
480
+ * Global Alpine.js data functions
481
+ */
482
+ window.webhookDashboard = PaymentSystem.Components.webhookDashboard;
483
+ window.paymentForm = PaymentSystem.Components.paymentForm;
484
+ window.dataTable = PaymentSystem.Components.dataTable;
485
+ window.modal = PaymentSystem.Components.modal;
486
+ window.statusMonitor = PaymentSystem.Components.statusMonitor;
487
+
488
+ /**
489
+ * Initialize components on page load
490
+ */
491
+ document.addEventListener('DOMContentLoaded', function() {
492
+ // Add global click handlers for common actions
493
+ document.addEventListener('click', function(e) {
494
+ // Handle refresh buttons
495
+ if (e.target.matches('[data-refresh]')) {
496
+ const target = e.target.getAttribute('data-refresh');
497
+ if (target === 'page') {
498
+ location.reload();
499
+ } else {
500
+ // Trigger Alpine.js refresh method if available
501
+ const component = e.target.closest('[x-data]');
502
+ if (component && component._x_dataStack && component._x_dataStack[0].refreshData) {
503
+ component._x_dataStack[0].refreshData();
504
+ }
505
+ }
506
+ }
507
+
508
+ // Handle modal triggers
509
+ if (e.target.matches('[data-modal]')) {
510
+ const modalId = e.target.getAttribute('data-modal');
511
+ const modal = document.querySelector(`[data-modal-id="${modalId}"]`);
512
+ if (modal && modal._x_dataStack && modal._x_dataStack[0].open) {
513
+ modal._x_dataStack[0].open();
514
+ }
515
+ }
516
+ });
517
+
518
+ // Add global form validation
519
+ document.addEventListener('submit', function(e) {
520
+ const form = e.target;
521
+ if (form.hasAttribute('data-validate')) {
522
+ const requiredFields = form.querySelectorAll('[required]');
523
+ let isValid = true;
524
+
525
+ requiredFields.forEach(field => {
526
+ if (!field.value.trim()) {
527
+ field.classList.add('border-red-500');
528
+ isValid = false;
529
+ } else {
530
+ field.classList.remove('border-red-500');
531
+ }
532
+ });
533
+
534
+ if (!isValid) {
535
+ e.preventDefault();
536
+ PaymentSystem.Utils.showNotification('Please fill in all required fields', 'warning', 'warning');
537
+ }
538
+ }
539
+ });
540
+ });
541
+
542
+ // Export for module systems
543
+ if (typeof module !== 'undefined' && module.exports) {
544
+ module.exports = PaymentSystem.Components;
545
+ }