django-cfg 1.2.31__py3-none-any.whl → 1.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/api/health/views.py +4 -2
  3. django_cfg/apps/knowbase/config/settings.py +16 -15
  4. django_cfg/apps/payments/README.md +326 -0
  5. django_cfg/apps/payments/admin/__init__.py +20 -10
  6. django_cfg/apps/payments/admin/api_keys_admin.py +521 -237
  7. django_cfg/apps/payments/admin/balance_admin.py +592 -297
  8. django_cfg/apps/payments/admin/currencies_admin.py +526 -222
  9. django_cfg/apps/payments/admin/filters.py +306 -199
  10. django_cfg/apps/payments/admin/payments_admin.py +465 -70
  11. django_cfg/apps/payments/admin/subscriptions_admin.py +578 -128
  12. django_cfg/apps/payments/admin_interface/__init__.py +18 -0
  13. django_cfg/apps/payments/admin_interface/templates/payments/base.html +162 -0
  14. django_cfg/apps/payments/admin_interface/templates/payments/components/dev_tool_card.html +38 -0
  15. django_cfg/apps/payments/admin_interface/templates/payments/components/loading_spinner.html +16 -0
  16. django_cfg/apps/payments/admin_interface/templates/payments/components/notification.html +27 -0
  17. django_cfg/apps/payments/admin_interface/templates/payments/components/provider_card.html +86 -0
  18. django_cfg/apps/payments/admin_interface/templates/payments/components/status_card.html +39 -0
  19. django_cfg/apps/payments/admin_interface/templates/payments/currency_converter.html +382 -0
  20. django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +300 -0
  21. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +303 -0
  22. django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +382 -0
  23. django_cfg/apps/payments/admin_interface/templates/payments/payment_status.html +500 -0
  24. django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +594 -0
  25. django_cfg/apps/payments/admin_interface/views/__init__.py +23 -0
  26. django_cfg/apps/payments/admin_interface/views/payment_views.py +259 -0
  27. django_cfg/apps/payments/admin_interface/views/webhook_dashboard.py +37 -0
  28. django_cfg/apps/payments/apps.py +34 -9
  29. django_cfg/apps/payments/config/__init__.py +28 -51
  30. django_cfg/apps/payments/config/constance/__init__.py +22 -0
  31. django_cfg/apps/payments/config/constance/config_service.py +123 -0
  32. django_cfg/apps/payments/config/constance/fields.py +69 -0
  33. django_cfg/apps/payments/config/constance/settings.py +160 -0
  34. django_cfg/apps/payments/config/django_cfg_integration.py +202 -0
  35. django_cfg/apps/payments/config/helpers.py +130 -0
  36. django_cfg/apps/payments/management/__init__.py +1 -3
  37. django_cfg/apps/payments/management/commands/__init__.py +1 -3
  38. django_cfg/apps/payments/management/commands/manage_currencies.py +303 -151
  39. django_cfg/apps/payments/management/commands/manage_providers.py +333 -160
  40. django_cfg/apps/payments/middleware/__init__.py +3 -1
  41. django_cfg/apps/payments/middleware/api_access.py +329 -222
  42. django_cfg/apps/payments/middleware/rate_limiting.py +342 -152
  43. django_cfg/apps/payments/middleware/usage_tracking.py +249 -240
  44. django_cfg/apps/payments/migrations/0001_initial.py +708 -536
  45. django_cfg/apps/payments/models/__init__.py +13 -18
  46. django_cfg/apps/payments/models/api_keys.py +121 -43
  47. django_cfg/apps/payments/models/balance.py +150 -115
  48. django_cfg/apps/payments/models/base.py +68 -15
  49. django_cfg/apps/payments/models/currencies.py +172 -148
  50. django_cfg/apps/payments/models/managers/__init__.py +44 -0
  51. django_cfg/apps/payments/models/managers/api_key_managers.py +329 -0
  52. django_cfg/apps/payments/models/managers/balance_managers.py +599 -0
  53. django_cfg/apps/payments/models/managers/currency_managers.py +385 -0
  54. django_cfg/apps/payments/models/managers/payment_managers.py +511 -0
  55. django_cfg/apps/payments/models/managers/subscription_managers.py +641 -0
  56. django_cfg/apps/payments/models/payments.py +235 -285
  57. django_cfg/apps/payments/models/subscriptions.py +257 -177
  58. django_cfg/apps/payments/models/tariffs.py +147 -40
  59. django_cfg/apps/payments/services/__init__.py +209 -56
  60. django_cfg/apps/payments/services/cache/__init__.py +6 -6
  61. django_cfg/apps/payments/services/cache/{simple_cache.py → cache_service.py} +112 -12
  62. django_cfg/apps/payments/services/core/__init__.py +10 -6
  63. django_cfg/apps/payments/services/core/balance_service.py +435 -360
  64. django_cfg/apps/payments/services/core/base.py +166 -0
  65. django_cfg/apps/payments/services/core/currency_service.py +478 -0
  66. django_cfg/apps/payments/services/core/payment_service.py +346 -467
  67. django_cfg/apps/payments/services/core/subscription_service.py +425 -481
  68. django_cfg/apps/payments/services/core/webhook_service.py +410 -0
  69. django_cfg/apps/payments/services/integrations/__init__.py +29 -0
  70. django_cfg/apps/payments/services/integrations/ngrok_service.py +47 -0
  71. django_cfg/apps/payments/services/integrations/providers_config.py +107 -0
  72. django_cfg/apps/payments/services/providers/__init__.py +9 -14
  73. django_cfg/apps/payments/services/providers/base.py +234 -174
  74. django_cfg/apps/payments/services/providers/nowpayments.py +478 -0
  75. django_cfg/apps/payments/services/providers/registry.py +367 -301
  76. django_cfg/apps/payments/services/types/__init__.py +78 -0
  77. django_cfg/apps/payments/services/types/data.py +177 -0
  78. django_cfg/apps/payments/services/types/requests.py +150 -0
  79. django_cfg/apps/payments/services/types/responses.py +156 -0
  80. django_cfg/apps/payments/services/types/webhooks.py +232 -0
  81. django_cfg/apps/payments/signals/__init__.py +33 -8
  82. django_cfg/apps/payments/signals/api_key_signals.py +210 -129
  83. django_cfg/apps/payments/signals/balance_signals.py +174 -0
  84. django_cfg/apps/payments/signals/payment_signals.py +128 -103
  85. django_cfg/apps/payments/signals/subscription_signals.py +194 -142
  86. django_cfg/apps/payments/static/payments/css/components.css +380 -0
  87. django_cfg/apps/payments/static/payments/css/dashboard.css +188 -0
  88. django_cfg/apps/payments/static/payments/js/components.js +545 -0
  89. django_cfg/apps/payments/static/payments/js/utils.js +412 -0
  90. django_cfg/apps/payments/templatetags/__init__.py +1 -1
  91. django_cfg/apps/payments/templatetags/payment_tags.py +466 -0
  92. django_cfg/apps/payments/urls.py +45 -48
  93. django_cfg/apps/payments/urls_admin.py +33 -42
  94. django_cfg/apps/payments/views/api/__init__.py +101 -0
  95. django_cfg/apps/payments/views/api/api_keys.py +387 -0
  96. django_cfg/apps/payments/views/api/balances.py +381 -0
  97. django_cfg/apps/payments/views/api/base.py +298 -0
  98. django_cfg/apps/payments/views/api/currencies.py +402 -0
  99. django_cfg/apps/payments/views/api/payments.py +415 -0
  100. django_cfg/apps/payments/views/api/subscriptions.py +475 -0
  101. django_cfg/apps/payments/views/api/webhooks.py +476 -0
  102. django_cfg/apps/payments/views/serializers/__init__.py +99 -0
  103. django_cfg/apps/payments/views/serializers/api_keys.py +424 -0
  104. django_cfg/apps/payments/views/serializers/balances.py +300 -0
  105. django_cfg/apps/payments/views/serializers/currencies.py +335 -0
  106. django_cfg/apps/payments/views/serializers/payments.py +387 -0
  107. django_cfg/apps/payments/views/serializers/subscriptions.py +429 -0
  108. django_cfg/apps/payments/views/serializers/webhooks.py +137 -0
  109. django_cfg/config.py +1 -1
  110. django_cfg/core/config.py +40 -4
  111. django_cfg/core/generation.py +25 -4
  112. django_cfg/core/integration/README.md +363 -0
  113. django_cfg/core/integration/__init__.py +47 -0
  114. django_cfg/core/integration/commands_collector.py +239 -0
  115. django_cfg/core/integration/display/__init__.py +15 -0
  116. django_cfg/core/integration/display/base.py +157 -0
  117. django_cfg/core/integration/display/ngrok.py +164 -0
  118. django_cfg/core/integration/display/startup.py +815 -0
  119. django_cfg/core/integration/url_integration.py +123 -0
  120. django_cfg/core/integration/version_checker.py +160 -0
  121. django_cfg/management/commands/auto_generate.py +4 -0
  122. django_cfg/management/commands/check_settings.py +6 -0
  123. django_cfg/management/commands/clear_constance.py +5 -2
  124. django_cfg/management/commands/create_token.py +6 -0
  125. django_cfg/management/commands/list_urls.py +6 -0
  126. django_cfg/management/commands/migrate_all.py +6 -0
  127. django_cfg/management/commands/migrator.py +3 -0
  128. django_cfg/management/commands/rundramatiq.py +6 -0
  129. django_cfg/management/commands/runserver_ngrok.py +51 -29
  130. django_cfg/management/commands/script.py +6 -0
  131. django_cfg/management/commands/show_config.py +12 -2
  132. django_cfg/management/commands/show_urls.py +4 -0
  133. django_cfg/management/commands/superuser.py +6 -0
  134. django_cfg/management/commands/task_clear.py +4 -1
  135. django_cfg/management/commands/task_status.py +3 -1
  136. django_cfg/management/commands/test_email.py +3 -0
  137. django_cfg/management/commands/test_telegram.py +6 -0
  138. django_cfg/management/commands/test_twilio.py +6 -0
  139. django_cfg/management/commands/tree.py +6 -0
  140. django_cfg/management/commands/validate_config.py +155 -149
  141. django_cfg/models/constance.py +31 -11
  142. django_cfg/models/payments.py +175 -492
  143. django_cfg/modules/django_logger.py +160 -146
  144. django_cfg/modules/django_unfold/dashboard.py +64 -16
  145. django_cfg/registry/core.py +1 -0
  146. django_cfg/template_archive/django_sample.zip +0 -0
  147. django_cfg/utils/smart_defaults.py +222 -571
  148. django_cfg/utils/toolkit.py +51 -11
  149. {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/METADATA +4 -1
  150. {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/RECORD +153 -185
  151. django_cfg/apps/payments/__init__.py +0 -8
  152. django_cfg/apps/payments/admin/tariffs_admin.py +0 -199
  153. django_cfg/apps/payments/config/module.py +0 -70
  154. django_cfg/apps/payments/config/providers.py +0 -105
  155. django_cfg/apps/payments/config/settings.py +0 -96
  156. django_cfg/apps/payments/config/utils.py +0 -52
  157. django_cfg/apps/payments/decorators.py +0 -291
  158. django_cfg/apps/payments/management/commands/README.md +0 -146
  159. django_cfg/apps/payments/management/commands/currency_stats.py +0 -304
  160. django_cfg/apps/payments/managers/__init__.py +0 -23
  161. django_cfg/apps/payments/managers/api_key_manager.py +0 -35
  162. django_cfg/apps/payments/managers/balance_manager.py +0 -361
  163. django_cfg/apps/payments/managers/currency_manager.py +0 -306
  164. django_cfg/apps/payments/managers/payment_manager.py +0 -192
  165. django_cfg/apps/payments/managers/subscription_manager.py +0 -37
  166. django_cfg/apps/payments/managers/tariff_manager.py +0 -29
  167. django_cfg/apps/payments/migrations/0002_network_providercurrency_and_more.py +0 -241
  168. django_cfg/apps/payments/migrations/0003_add_usd_rate_cache.py +0 -30
  169. django_cfg/apps/payments/models/events.py +0 -73
  170. django_cfg/apps/payments/serializers/__init__.py +0 -57
  171. django_cfg/apps/payments/serializers/api_keys.py +0 -51
  172. django_cfg/apps/payments/serializers/balance.py +0 -59
  173. django_cfg/apps/payments/serializers/currencies.py +0 -63
  174. django_cfg/apps/payments/serializers/payments.py +0 -62
  175. django_cfg/apps/payments/serializers/subscriptions.py +0 -71
  176. django_cfg/apps/payments/serializers/tariffs.py +0 -56
  177. django_cfg/apps/payments/services/billing/__init__.py +0 -8
  178. django_cfg/apps/payments/services/cache/base.py +0 -30
  179. django_cfg/apps/payments/services/core/fallback_service.py +0 -432
  180. django_cfg/apps/payments/services/internal_types.py +0 -461
  181. django_cfg/apps/payments/services/middleware/__init__.py +0 -8
  182. django_cfg/apps/payments/services/monitoring/__init__.py +0 -22
  183. django_cfg/apps/payments/services/monitoring/api_schemas.py +0 -76
  184. django_cfg/apps/payments/services/monitoring/provider_health.py +0 -372
  185. django_cfg/apps/payments/services/providers/cryptapi/__init__.py +0 -4
  186. django_cfg/apps/payments/services/providers/cryptapi/config.py +0 -8
  187. django_cfg/apps/payments/services/providers/cryptapi/models.py +0 -192
  188. django_cfg/apps/payments/services/providers/cryptapi/provider.py +0 -439
  189. django_cfg/apps/payments/services/providers/cryptomus/__init__.py +0 -4
  190. django_cfg/apps/payments/services/providers/cryptomus/models.py +0 -176
  191. django_cfg/apps/payments/services/providers/cryptomus/provider.py +0 -429
  192. django_cfg/apps/payments/services/providers/cryptomus/provider_v2.py +0 -564
  193. django_cfg/apps/payments/services/providers/models/__init__.py +0 -34
  194. django_cfg/apps/payments/services/providers/models/currencies.py +0 -190
  195. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +0 -4
  196. django_cfg/apps/payments/services/providers/nowpayments/models.py +0 -196
  197. django_cfg/apps/payments/services/providers/nowpayments/provider.py +0 -380
  198. django_cfg/apps/payments/services/providers/stripe/__init__.py +0 -4
  199. django_cfg/apps/payments/services/providers/stripe/models.py +0 -184
  200. django_cfg/apps/payments/services/providers/stripe/provider.py +0 -109
  201. django_cfg/apps/payments/services/security/__init__.py +0 -34
  202. django_cfg/apps/payments/services/security/error_handler.py +0 -635
  203. django_cfg/apps/payments/services/security/payment_notifications.py +0 -342
  204. django_cfg/apps/payments/services/security/webhook_validator.py +0 -474
  205. django_cfg/apps/payments/static/payments/css/payments.css +0 -340
  206. django_cfg/apps/payments/static/payments/js/notifications.js +0 -202
  207. django_cfg/apps/payments/static/payments/js/payment-utils.js +0 -318
  208. django_cfg/apps/payments/static/payments/js/theme.js +0 -86
  209. django_cfg/apps/payments/tasks/__init__.py +0 -12
  210. django_cfg/apps/payments/tasks/webhook_processing.py +0 -177
  211. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +0 -50
  212. django_cfg/apps/payments/templates/payments/base.html +0 -182
  213. django_cfg/apps/payments/templates/payments/components/payment_card.html +0 -201
  214. django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +0 -109
  215. django_cfg/apps/payments/templates/payments/components/progress_bar.html +0 -43
  216. django_cfg/apps/payments/templates/payments/components/provider_stats.html +0 -40
  217. django_cfg/apps/payments/templates/payments/components/status_badge.html +0 -34
  218. django_cfg/apps/payments/templates/payments/components/status_overview.html +0 -148
  219. django_cfg/apps/payments/templates/payments/dashboard.html +0 -258
  220. django_cfg/apps/payments/templates/payments/dashboard_simple_test.html +0 -35
  221. django_cfg/apps/payments/templates/payments/payment_create.html +0 -579
  222. django_cfg/apps/payments/templates/payments/payment_detail.html +0 -373
  223. django_cfg/apps/payments/templates/payments/payment_list.html +0 -354
  224. django_cfg/apps/payments/templates/payments/stats.html +0 -261
  225. django_cfg/apps/payments/templates/payments/test.html +0 -213
  226. django_cfg/apps/payments/templatetags/payments_tags.py +0 -315
  227. django_cfg/apps/payments/utils/__init__.py +0 -43
  228. django_cfg/apps/payments/utils/billing_utils.py +0 -342
  229. django_cfg/apps/payments/utils/config_utils.py +0 -239
  230. django_cfg/apps/payments/utils/middleware_utils.py +0 -228
  231. django_cfg/apps/payments/utils/validation_utils.py +0 -94
  232. django_cfg/apps/payments/views/__init__.py +0 -63
  233. django_cfg/apps/payments/views/api_key_views.py +0 -164
  234. django_cfg/apps/payments/views/balance_views.py +0 -75
  235. django_cfg/apps/payments/views/currency_views.py +0 -122
  236. django_cfg/apps/payments/views/payment_views.py +0 -149
  237. django_cfg/apps/payments/views/subscription_views.py +0 -135
  238. django_cfg/apps/payments/views/tariff_views.py +0 -131
  239. django_cfg/apps/payments/views/templates/__init__.py +0 -25
  240. django_cfg/apps/payments/views/templates/ajax.py +0 -451
  241. django_cfg/apps/payments/views/templates/base.py +0 -212
  242. django_cfg/apps/payments/views/templates/dashboard.py +0 -60
  243. django_cfg/apps/payments/views/templates/payment_detail.py +0 -102
  244. django_cfg/apps/payments/views/templates/payment_management.py +0 -158
  245. django_cfg/apps/payments/views/templates/qr_code.py +0 -174
  246. django_cfg/apps/payments/views/templates/stats.py +0 -244
  247. django_cfg/apps/payments/views/templates/utils.py +0 -181
  248. django_cfg/apps/payments/views/webhook_views.py +0 -266
  249. django_cfg/apps/payments/viewsets.py +0 -66
  250. django_cfg/core/integration.py +0 -160
  251. django_cfg/template_archive/.gitignore +0 -1
  252. django_cfg/template_archive/__init__.py +0 -0
  253. django_cfg/urls.py +0 -33
  254. {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/WHEEL +0 -0
  255. {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/entry_points.txt +0 -0
  256. {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,579 +0,0 @@
1
- {% extends 'payments/base.html' %}
2
- {% load static %}
3
- {% load payments_tags %}
4
-
5
- {% block header_title %}Create New Payment{% endblock %}
6
- {% block header_subtitle %}Set up a new payment transaction{% endblock %}
7
-
8
- {% block content %}
9
- <div class="space-y-6">
10
- <!-- Payment Creation Form -->
11
- <div class="bg-white dark:bg-base-900 border border-base-200 dark:border-base-700 rounded-default shadow-xs">
12
- <div class="p-6 border-b border-base-200 dark:border-base-700">
13
- <h3 class="text-lg font-semibold text-font-important-light dark:text-font-important-dark">Payment Details</h3>
14
- <p class="text-sm text-font-subtle-light dark:text-font-subtle-dark mt-1">Configure the payment parameters</p>
15
- </div>
16
-
17
- <form id="payment-form" class="p-6">
18
- {% csrf_token %}
19
-
20
- <!-- Basic Information -->
21
- <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
22
- <!-- User Selection -->
23
- <div>
24
- <label for="user" class="block text-sm font-medium text-font-default-light dark:text-font-default-dark mb-2">
25
- User <span class="text-red-500">*</span>
26
- </label>
27
- <select id="user" name="user" required
28
- class="w-full px-3 py-2 border border-base-200 dark:border-base-700 rounded-default bg-white dark:bg-base-900 text-font-default-light dark:text-font-default-dark focus:ring-2 focus:ring-primary-500 focus:border-primary-500">
29
- <option value="">Select User</option>
30
- <!-- Users will be loaded dynamically -->
31
- </select>
32
- </div>
33
-
34
- <!-- Amount -->
35
- <div>
36
- <label for="amount_usd" class="block text-sm font-medium text-font-default-light dark:text-font-default-dark mb-2">
37
- Amount (USD) <span class="text-red-500">*</span>
38
- </label>
39
- <div class="relative">
40
- <span class="absolute left-3 top-2 text-font-subtle-light dark:text-font-subtle-dark">$</span>
41
- <input type="number" id="amount_usd" name="amount_usd" step="0.01" min="0.01" required
42
- placeholder="0.00"
43
- class="w-full pl-8 pr-3 py-2 border border-base-200 dark:border-base-700 rounded-default bg-white dark:bg-base-900 text-font-default-light dark:text-font-default-dark placeholder-font-subtle-light dark:placeholder-font-subtle-dark focus:ring-2 focus:ring-primary-500 focus:border-primary-500">
44
- </div>
45
- </div>
46
- </div>
47
-
48
- <!-- Provider Selection -->
49
- <div class="mb-6">
50
- <label class="block text-sm font-medium text-font-default-light dark:text-font-default-dark mb-3">
51
- Payment Provider <span class="text-red-500">*</span>
52
- </label>
53
- <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
54
- <!-- CryptAPI -->
55
- <div class="relative">
56
- <input type="radio" id="cryptapi" name="provider" value="cryptapi" class="sr-only peer" required>
57
- <label for="cryptapi" class="flex flex-col items-center p-4 border-2 border-base-200 dark:border-base-700 rounded-default cursor-pointer hover:bg-base-50 dark:hover:bg-base-800 peer-checked:border-orange-500 peer-checked:bg-orange-50 dark:peer-checked:bg-orange-900/20 transition-all duration-200">
58
- <div class="w-3 h-3 rounded-full bg-orange-500 mb-2"></div>
59
- <span class="text-sm font-medium text-font-important-light dark:text-font-important-dark">CryptAPI</span>
60
- <span class="text-xs text-font-subtle-light dark:text-font-subtle-dark mt-1">Bitcoin payments</span>
61
- </label>
62
- </div>
63
-
64
- <!-- Cryptomus -->
65
- <div class="relative">
66
- <input type="radio" id="cryptomus" name="provider" value="cryptomus" class="sr-only peer">
67
- <label for="cryptomus" class="flex flex-col items-center p-4 border-2 border-base-200 dark:border-base-700 rounded-default cursor-pointer hover:bg-base-50 dark:hover:bg-base-800 peer-checked:border-blue-500 peer-checked:bg-blue-50 dark:peer-checked:bg-blue-900/20 transition-all duration-200">
68
- <div class="w-3 h-3 rounded-full bg-blue-500 mb-2"></div>
69
- <span class="text-sm font-medium text-font-important-light dark:text-font-important-dark">Cryptomus</span>
70
- <span class="text-xs text-font-subtle-light dark:text-font-subtle-dark mt-1">Multi-crypto</span>
71
- </label>
72
- </div>
73
-
74
- <!-- Stripe -->
75
- <div class="relative">
76
- <input type="radio" id="stripe" name="provider" value="stripe" class="sr-only peer">
77
- <label for="stripe" class="flex flex-col items-center p-4 border-2 border-base-200 dark:border-base-700 rounded-default cursor-pointer hover:bg-base-50 dark:hover:bg-base-800 peer-checked:border-purple-500 peer-checked:bg-purple-50 dark:peer-checked:bg-purple-900/20 transition-all duration-200">
78
- <div class="w-3 h-3 rounded-full bg-purple-500 mb-2"></div>
79
- <span class="text-sm font-medium text-font-important-light dark:text-font-important-dark">Stripe</span>
80
- <span class="text-xs text-font-subtle-light dark:text-font-subtle-dark mt-1">Card payments</span>
81
- </label>
82
- </div>
83
-
84
- <!-- NowPayments -->
85
- <div class="relative">
86
- <input type="radio" id="nowpayments" name="provider" value="nowpayments" class="sr-only peer">
87
- <label for="nowpayments" class="flex flex-col items-center p-4 border-2 border-base-200 dark:border-base-700 rounded-default cursor-pointer hover:bg-base-50 dark:hover:bg-base-800 peer-checked:border-green-500 peer-checked:bg-green-50 dark:peer-checked:bg-green-900/20 transition-all duration-200">
88
- <div class="w-3 h-3 rounded-full bg-green-500 mb-2"></div>
89
- <span class="text-sm font-medium text-font-important-light dark:text-font-important-dark">NowPayments</span>
90
- <span class="text-xs text-font-subtle-light dark:text-font-subtle-dark mt-1">Crypto gateway</span>
91
- </label>
92
- </div>
93
- </div>
94
- </div>
95
-
96
- <!-- Crypto-specific fields (shown when crypto provider is selected) -->
97
- <div id="crypto-fields" class="hidden mb-6">
98
- <div class="space-y-6">
99
- <!-- Currency & Network (Combined) -->
100
- <div>
101
- <label for="currency_code" class="block text-sm font-medium text-font-default-light dark:text-font-default-dark mb-2">
102
- Cryptocurrency & Network
103
- </label>
104
- <select id="currency_code" name="currency_code" required
105
- class="w-full px-3 py-2 border border-base-200 dark:border-base-700 rounded-default bg-white dark:bg-base-900 text-font-default-light dark:text-font-default-dark focus:ring-2 focus:ring-primary-500 focus:border-primary-500">
106
- <option value="">Select Currency & Network</option>
107
- <!-- Currency options will be populated dynamically via JavaScript -->
108
- </select>
109
-
110
- <!-- Currency Info Display -->
111
- <div id="currency-info" class="mt-3 hidden">
112
- <div id="currency-details">
113
- <!-- Currency details will be populated via JavaScript -->
114
- </div>
115
- </div>
116
- </div>
117
- </div>
118
- </div>
119
-
120
- <!-- Optional Fields -->
121
- <div class="mb-6">
122
- <h4 class="text-md font-semibold text-font-important-light dark:text-font-important-dark mb-3">Optional Information</h4>
123
-
124
- <!-- Description -->
125
- <div class="mb-4">
126
- <label for="description" class="block text-sm font-medium text-font-default-light dark:text-font-default-dark mb-2">
127
- Description
128
- </label>
129
- <textarea id="description" name="description" rows="3"
130
- placeholder="Payment description or notes..."
131
- class="w-full px-3 py-2 border border-base-200 dark:border-base-700 rounded-default bg-white dark:bg-base-900 text-font-default-light dark:text-font-default-dark placeholder-font-subtle-light dark:placeholder-font-subtle-dark focus:ring-2 focus:ring-primary-500 focus:border-primary-500"></textarea>
132
- </div>
133
-
134
- <!-- Metadata -->
135
- <div>
136
- <label for="metadata" class="block text-sm font-medium text-font-default-light dark:text-font-default-dark mb-2">
137
- Metadata (JSON)
138
- </label>
139
- <textarea id="metadata" name="metadata" rows="3"
140
- placeholder='{"order_id": "12345", "product": "Premium Plan"}'
141
- class="w-full px-3 py-2 border border-base-200 dark:border-base-700 rounded-default bg-white dark:bg-base-900 text-font-default-light dark:text-font-default-dark placeholder-font-subtle-light dark:placeholder-font-subtle-dark focus:ring-2 focus:ring-primary-500 focus:border-primary-500 font-mono text-sm"></textarea>
142
- <p class="text-xs text-font-subtle-light dark:text-font-subtle-dark mt-1">
143
- Optional JSON metadata for the payment
144
- </p>
145
- </div>
146
- </div>
147
-
148
- <!-- Actions -->
149
- <div class="flex items-center justify-between pt-6 border-t border-base-200 dark:border-base-700">
150
- <a href="{% url 'payments_dashboard:list' %}"
151
- class="px-4 py-2 border border-base-300 dark:border-base-600 rounded-default text-font-default-light dark:text-font-default-dark hover:bg-base-50 dark:hover:bg-base-800 transition-colors duration-200">
152
- Cancel
153
- </a>
154
-
155
- <div class="flex space-x-3">
156
- <button type="button" id="preview-btn"
157
- class="px-4 py-2 bg-gray-600 hover:bg-gray-700 text-white rounded-default font-medium transition-colors duration-200">
158
- Preview
159
- </button>
160
- <button type="submit"
161
- class="px-6 py-2 bg-primary-600 hover:bg-primary-700 text-white rounded-default font-medium transition-colors duration-200">
162
- <span class="material-icons text-sm mr-2">add</span>
163
- Create Payment
164
- </button>
165
- </div>
166
- </div>
167
- </form>
168
- </div>
169
-
170
- <!-- Payment Preview (initially hidden) -->
171
- <div id="payment-preview" class="hidden bg-white dark:bg-base-900 border border-base-200 dark:border-base-700 rounded-default shadow-xs">
172
- <div class="p-6 border-b border-base-200 dark:border-base-700">
173
- <h3 class="text-lg font-semibold text-font-important-light dark:text-font-important-dark">Payment Preview</h3>
174
- <p class="text-sm text-font-subtle-light dark:text-font-subtle-dark mt-1">Review payment details before creation</p>
175
- </div>
176
-
177
- <div class="p-6">
178
- <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
179
- <div>
180
- <h4 class="text-sm font-semibold text-font-important-light dark:text-font-important-dark mb-3">Payment Information</h4>
181
- <dl class="space-y-2">
182
- <div class="flex justify-between">
183
- <dt class="text-sm text-font-subtle-light dark:text-font-subtle-dark">User:</dt>
184
- <dd id="preview-user" class="text-sm text-font-default-light dark:text-font-default-dark"></dd>
185
- </div>
186
- <div class="flex justify-between">
187
- <dt class="text-sm text-font-subtle-light dark:text-font-subtle-dark">Amount:</dt>
188
- <dd id="preview-amount" class="text-sm font-semibold text-font-important-light dark:text-font-important-dark"></dd>
189
- </div>
190
- <div class="flex justify-between">
191
- <dt class="text-sm text-font-subtle-light dark:text-font-subtle-dark">Provider:</dt>
192
- <dd id="preview-provider" class="text-sm text-font-default-light dark:text-font-default-dark"></dd>
193
- </div>
194
- <div class="flex justify-between">
195
- <dt class="text-sm text-font-subtle-light dark:text-font-subtle-dark">Currency:</dt>
196
- <dd id="preview-currency" class="text-sm text-font-default-light dark:text-font-default-dark"></dd>
197
- </div>
198
- </dl>
199
- </div>
200
-
201
- <div>
202
- <h4 class="text-sm font-semibold text-font-important-light dark:text-font-important-dark mb-3">Configuration</h4>
203
- <dl class="space-y-2">
204
- <div class="flex justify-between">
205
- <dt class="text-sm text-font-subtle-light dark:text-font-subtle-dark">Network:</dt>
206
- <dd id="preview-network" class="text-sm text-font-default-light dark:text-font-default-dark"></dd>
207
- </div>
208
- <div class="flex justify-between">
209
- <dt class="text-sm text-font-subtle-light dark:text-font-subtle-dark">Status:</dt>
210
- <dd class="text-sm">
211
- <span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200">
212
- Pending
213
- </span>
214
- </dd>
215
- </div>
216
- </dl>
217
- </div>
218
- </div>
219
-
220
- <div id="preview-description-section" class="hidden mt-6">
221
- <h4 class="text-sm font-semibold text-font-important-light dark:text-font-important-dark mb-2">Description</h4>
222
- <p id="preview-description" class="text-sm text-font-default-light dark:text-font-default-dark bg-base-50 dark:bg-base-800 p-3 rounded-default border border-base-200 dark:border-base-700"></p>
223
- </div>
224
- </div>
225
- </div>
226
-
227
- <!-- Quick Actions -->
228
- <div class="bg-white dark:bg-base-900 border border-base-200 dark:border-base-700 rounded-default shadow-xs">
229
- <div class="p-6 border-b border-base-200 dark:border-base-700">
230
- <h3 class="text-lg font-semibold text-font-important-light dark:text-font-important-dark">Quick Actions</h3>
231
- <p class="text-sm text-font-subtle-light dark:text-font-subtle-dark mt-1">Common payment templates</p>
232
- </div>
233
-
234
- <div class="p-6">
235
- <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
236
- <button type="button" class="quick-template p-4 border border-base-200 dark:border-base-700 rounded-default hover:bg-base-50 dark:hover:bg-base-800 transition-all duration-200"
237
- data-amount="10.00" data-provider="cryptapi" data-currency="BTC" data-description="Test payment">
238
- <div class="text-center">
239
- <span class="material-icons text-orange-600 dark:text-orange-400 text-2xl mb-2 block">currency_bitcoin</span>
240
- <h4 class="text-sm font-semibold text-font-important-light dark:text-font-important-dark">Bitcoin Test</h4>
241
- <p class="text-xs text-font-subtle-light dark:text-font-subtle-dark">$10.00 BTC payment</p>
242
- </div>
243
- </button>
244
-
245
- <button type="button" class="quick-template p-4 border border-base-200 dark:border-base-700 rounded-default hover:bg-base-50 dark:hover:bg-base-800 transition-all duration-200"
246
- data-amount="25.00" data-provider="stripe" data-description="Card payment">
247
- <div class="text-center">
248
- <span class="material-icons text-purple-600 dark:text-purple-400 text-2xl mb-2 block">credit_card</span>
249
- <h4 class="text-sm font-semibold text-font-important-light dark:text-font-important-dark">Stripe Card</h4>
250
- <p class="text-xs text-font-subtle-light dark:text-font-subtle-dark">$25.00 card payment</p>
251
- </div>
252
- </button>
253
-
254
- <button type="button" class="quick-template p-4 border border-base-200 dark:border-base-700 rounded-default hover:bg-base-50 dark:hover:bg-base-800 transition-all duration-200"
255
- data-amount="50.00" data-provider="cryptomus" data-currency="ETH" data-description="Ethereum payment">
256
- <div class="text-center">
257
- <span class="material-icons text-blue-600 dark:text-blue-400 text-2xl mb-2 block">account_balance_wallet</span>
258
- <h4 class="text-sm font-semibold text-font-important-light dark:text-font-important-dark">Ethereum</h4>
259
- <p class="text-xs text-font-subtle-light dark:text-font-subtle-dark">$50.00 ETH payment</p>
260
- </div>
261
- </button>
262
- </div>
263
- </div>
264
- </div>
265
- </div>
266
- {% endblock %}
267
-
268
- {% block extra_js %}
269
- {{ block.super }}
270
- <script>
271
- document.addEventListener('DOMContentLoaded', function() {
272
- console.log('Payment create form loaded');
273
-
274
- // Elements
275
- const form = document.getElementById('payment-form');
276
- const providerInputs = document.querySelectorAll('input[name="provider"]');
277
- const cryptoFields = document.getElementById('crypto-fields');
278
- const previewBtn = document.getElementById('preview-btn');
279
- const paymentPreview = document.getElementById('payment-preview');
280
- const quickTemplates = document.querySelectorAll('.quick-template');
281
-
282
- // Provider data loaded dynamically via AJAX
283
- let providerCurrencies = {};
284
- let currencyNetworks = {};
285
- let allProvidersData = {};
286
-
287
- // AJAX endpoints
288
- const ajaxUrls = {
289
- providerCurrencies: "{% url 'payments_dashboard:provider_currencies_ajax' %}",
290
- allProviders: "{% url 'payments_dashboard:all_providers_data_ajax' %}"
291
- };
292
-
293
- // Show/hide crypto fields based on provider selection
294
- providerInputs.forEach(input => {
295
- input.addEventListener('change', function() {
296
- const provider = this.value;
297
- const isCrypto = ['cryptapi', 'cryptomus', 'nowpayments'].includes(provider);
298
- cryptoFields.classList.toggle('hidden', !isCrypto);
299
-
300
- // Update currency options based on provider
301
- updateCurrencyOptions(provider);
302
- });
303
- });
304
-
305
- async function updateCurrencyOptions(provider) {
306
- const currencySelect = document.getElementById('currency_code');
307
-
308
- // Clear existing options
309
- currencySelect.innerHTML = '<option value="">Loading currencies...</option>';
310
-
311
- try {
312
- // Fetch currencies for this provider
313
- const response = await fetch(`${ajaxUrls.providerCurrencies}?provider=${provider}`);
314
- const data = await response.json();
315
-
316
- // New API format: object with currency_options array
317
- if (data && data.success && Array.isArray(data.currency_options)) {
318
- // Clear loading message
319
- currencySelect.innerHTML = '<option value="">Select Currency & Network</option>';
320
-
321
- // Add supported currencies with networks combined
322
- data.currency_options.forEach(currencyOption => {
323
- const option = document.createElement('option');
324
- option.value = currencyOption.provider_currency_code;
325
- option.textContent = currencyOption.display_name; // e.g., "USDT (Ethereum)"
326
- option.dataset.baseCode = currencyOption.base_currency_code;
327
- option.dataset.networkCode = currencyOption.network_code || '';
328
- option.dataset.type = currencyOption.currency_type;
329
- option.dataset.usdRate = currencyOption.usd_rate || 0;
330
- option.dataset.tokensPerUsd = currencyOption.tokens_per_usd || 0;
331
- option.dataset.isPopular = currencyOption.is_popular;
332
- option.dataset.isStable = currencyOption.is_stable;
333
- currencySelect.appendChild(option);
334
- });
335
-
336
- // Store currencies data for this provider
337
- providerCurrencies[provider] = data.currency_options;
338
-
339
- // Set default currency based on provider
340
- if (data.currency_options.length > 0) {
341
- const defaultCurrency = getDefaultProviderCurrency(provider);
342
- const defaultOption = data.currency_options.find(c => c.provider_currency_code === defaultCurrency);
343
- if (defaultOption) {
344
- currencySelect.value = defaultCurrency;
345
- updateCurrencyInfo(defaultOption);
346
- }
347
- }
348
-
349
- console.log(`Loaded ${data.currency_options.length} currency options for ${provider}`);
350
- } else {
351
- currencySelect.innerHTML = '<option value="">Error loading currencies</option>';
352
- console.error(`Invalid API response format for ${provider}:`, data);
353
- }
354
- } catch (error) {
355
- currencySelect.innerHTML = '<option value="">Error loading currencies</option>';
356
- console.error(`Error fetching currencies for ${provider}:`, error);
357
- }
358
- }
359
-
360
- // New function to update currency info display
361
- function updateCurrencyInfo(currencyOption) {
362
- const currencyInfo = document.getElementById('currency-info');
363
- const currencyDetails = document.getElementById('currency-details');
364
-
365
- if (currencyOption && currencyDetails) {
366
- let infoHtml = `
367
- <div class="bg-base-50 dark:bg-base-800 p-3 rounded-default">
368
- <div class="grid grid-cols-2 gap-2 text-sm text-font-default-light dark:text-font-default-dark">
369
- <div><strong class="text-font-important-light dark:text-font-important-dark">Base Currency:</strong> ${currencyOption.base_currency_code}</div>
370
- <div><strong class="text-font-important-light dark:text-font-important-dark">Network:</strong> ${currencyOption.network_code || 'Native'}</div>
371
- <div><strong class="text-font-important-light dark:text-font-important-dark">Type:</strong> <span class="capitalize text-primary-600 dark:text-primary-400">${currencyOption.currency_type}</span></div>
372
- <div><strong class="text-font-important-light dark:text-font-important-dark">USD Rate:</strong> <span class="text-success-600 dark:text-success-400">$${parseFloat(currencyOption.usd_rate || 0).toFixed(8)}</span></div>
373
- </div>
374
- `;
375
-
376
- if (currencyOption.is_stable) {
377
- infoHtml += '<div class="mt-2"><span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-success-100 dark:bg-success-900 text-success-800 dark:text-success-200">💰 Stable Coin</span></div>';
378
- }
379
- if (currencyOption.is_popular) {
380
- infoHtml += '<div class="mt-2"><span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-primary-100 dark:bg-primary-900 text-primary-800 dark:text-primary-200">🚀 Popular</span></div>';
381
- }
382
-
383
- infoHtml += '</div>';
384
- currencyDetails.innerHTML = infoHtml;
385
- currencyInfo.classList.remove('hidden');
386
- } else if (currencyInfo) {
387
- currencyInfo.classList.add('hidden');
388
- }
389
- }
390
-
391
- // Get provider defaults from Django context
392
- const providerDefaults = {{ provider_defaults_json|safe }};
393
-
394
- // Update function to get default provider currency from context
395
- function getDefaultProviderCurrency(provider) {
396
- return providerDefaults[provider] || '';
397
- }
398
-
399
-
400
- // Currency change handler - updated for new architecture
401
- document.getElementById('currency_code').addEventListener('change', function() {
402
- const selectedOption = this.options[this.selectedIndex];
403
-
404
- if (selectedOption && selectedOption.value) {
405
- // Get current provider
406
- const providerInput = document.querySelector('input[name="provider"]:checked');
407
- const provider = providerInput ? providerInput.value : '';
408
-
409
- // Find currency option data from stored provider currencies
410
- if (providerCurrencies[provider]) {
411
- const currencyOption = providerCurrencies[provider].find(
412
- c => c.provider_currency_code === selectedOption.value
413
- );
414
- if (currencyOption) {
415
- updateCurrencyInfo(currencyOption);
416
- }
417
- }
418
- } else {
419
- // Hide currency info if no selection
420
- const currencyInfo = document.getElementById('currency-info');
421
- if (currencyInfo) {
422
- currencyInfo.classList.add('hidden');
423
- }
424
- }
425
- });
426
-
427
- // Preview functionality
428
- previewBtn.addEventListener('click', function() {
429
- updatePreview();
430
- paymentPreview.classList.remove('hidden');
431
- paymentPreview.scrollIntoView({ behavior: 'smooth' });
432
- });
433
-
434
- // Quick template functionality
435
- quickTemplates.forEach(btn => {
436
- btn.addEventListener('click', function() {
437
- const data = this.dataset;
438
-
439
- // Fill form with template data
440
- document.getElementById('amount_usd').value = data.amount;
441
- document.getElementById('description').value = data.description;
442
-
443
- // Select provider
444
- const providerInput = document.querySelector(`input[name="provider"][value="${data.provider}"]`);
445
- if (providerInput) {
446
- providerInput.checked = true;
447
- providerInput.dispatchEvent(new Event('change'));
448
- }
449
-
450
- // Set currency if provided
451
- if (data.currency) {
452
- setTimeout(() => {
453
- document.getElementById('currency_code').value = data.currency;
454
- }, 100);
455
- }
456
-
457
- // Scroll to form
458
- form.scrollIntoView({ behavior: 'smooth' });
459
- });
460
- });
461
-
462
- // Form submission
463
- form.addEventListener('submit', function(e) {
464
- e.preventDefault();
465
-
466
- // Validate form
467
- if (!validateForm()) {
468
- return;
469
- }
470
-
471
- // Show loading state
472
- const submitBtn = form.querySelector('button[type="submit"]');
473
- const originalText = submitBtn.innerHTML;
474
- submitBtn.innerHTML = '<span class="material-icons text-sm mr-2 animate-spin">refresh</span>Creating...';
475
- submitBtn.disabled = true;
476
-
477
- // Collect form data
478
- const formData = new FormData(form);
479
- const paymentData = Object.fromEntries(formData);
480
-
481
- // Parse metadata if provided
482
- if (paymentData.metadata) {
483
- try {
484
- paymentData.metadata = JSON.parse(paymentData.metadata);
485
- } catch (e) {
486
- alert('Invalid JSON in metadata field');
487
- submitBtn.innerHTML = originalText;
488
- submitBtn.disabled = false;
489
- return;
490
- }
491
- }
492
-
493
- console.log('Creating payment:', paymentData);
494
-
495
- // Simulate API call
496
- setTimeout(() => {
497
- // Reset button
498
- submitBtn.innerHTML = originalText;
499
- submitBtn.disabled = false;
500
-
501
- // Show success message
502
- alert('Payment created successfully!');
503
-
504
- // Redirect to payment list
505
- window.location.href = "{% url 'payments_dashboard:list' %}";
506
- }, 2000);
507
- });
508
-
509
- // Load users for dropdown
510
- loadUsers();
511
-
512
- function updatePreview() {
513
- const formData = new FormData(form);
514
-
515
- // Update preview fields
516
- const userSelect = document.getElementById('user');
517
- const selectedUser = userSelect.options[userSelect.selectedIndex];
518
- document.getElementById('preview-user').textContent = selectedUser ? selectedUser.text : 'Not selected';
519
-
520
- document.getElementById('preview-amount').textContent = formData.get('amount_usd') ? `$${formData.get('amount_usd')}` : 'Not set';
521
- document.getElementById('preview-provider').textContent = formData.get('provider') ? formData.get('provider').toUpperCase() : 'Not selected';
522
- document.getElementById('preview-currency').textContent = formData.get('currency_code') || 'USD';
523
- document.getElementById('preview-network').textContent = formData.get('network') || 'N/A';
524
-
525
- // Show/hide description section
526
- const description = formData.get('description');
527
- const descSection = document.getElementById('preview-description-section');
528
- if (description) {
529
- document.getElementById('preview-description').textContent = description;
530
- descSection.classList.remove('hidden');
531
- } else {
532
- descSection.classList.add('hidden');
533
- }
534
- }
535
-
536
- function validateForm() {
537
- const requiredFields = ['user', 'amount_usd', 'provider'];
538
-
539
- for (const field of requiredFields) {
540
- const input = form.querySelector(`[name="${field}"]`);
541
- if (!input || !input.value) {
542
- alert(`Please fill in the ${field.replace('_', ' ')} field`);
543
- input?.focus();
544
- return false;
545
- }
546
- }
547
-
548
- // Validate crypto fields for crypto providers
549
- const provider = form.querySelector('input[name="provider"]:checked')?.value;
550
- if (['cryptapi', 'cryptomus', 'nowpayments'].includes(provider)) {
551
- const currency = form.querySelector('[name="currency_code"]').value;
552
- if (!currency) {
553
- alert('Please select a cryptocurrency');
554
- return false;
555
- }
556
- }
557
-
558
- return true;
559
- }
560
-
561
- function loadUsers() {
562
- // Simulate loading users
563
- const userSelect = document.getElementById('user');
564
- const users = [
565
- { id: 1, name: 'John Doe', email: 'john@example.com' },
566
- { id: 2, name: 'Jane Smith', email: 'jane@example.com' },
567
- { id: 3, name: 'Admin User', email: 'admin@example.com' }
568
- ];
569
-
570
- users.forEach(user => {
571
- const option = document.createElement('option');
572
- option.value = user.id;
573
- option.textContent = `${user.name} (${user.email})`;
574
- userSelect.appendChild(option);
575
- });
576
- }
577
- });
578
- </script>
579
- {% endblock %}