django-cfg 1.3.7__py3-none-any.whl → 1.3.11__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 (246) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/admin/__init__.py +24 -8
  3. django_cfg/apps/accounts/admin/activity_admin.py +146 -0
  4. django_cfg/apps/accounts/admin/filters.py +98 -22
  5. django_cfg/apps/accounts/admin/group_admin.py +86 -0
  6. django_cfg/apps/accounts/admin/inlines.py +42 -13
  7. django_cfg/apps/accounts/admin/otp_admin.py +115 -0
  8. django_cfg/apps/accounts/admin/registration_admin.py +173 -0
  9. django_cfg/apps/accounts/admin/resources.py +123 -19
  10. django_cfg/apps/accounts/admin/twilio_admin.py +327 -0
  11. django_cfg/apps/accounts/admin/user_admin.py +362 -0
  12. django_cfg/apps/agents/admin/__init__.py +17 -4
  13. django_cfg/apps/agents/admin/execution_admin.py +204 -183
  14. django_cfg/apps/agents/admin/registry_admin.py +230 -255
  15. django_cfg/apps/agents/admin/toolsets_admin.py +274 -321
  16. django_cfg/apps/agents/core/__init__.py +1 -1
  17. django_cfg/apps/agents/core/django_agent.py +221 -0
  18. django_cfg/apps/agents/core/exceptions.py +14 -0
  19. django_cfg/apps/agents/core/orchestrator.py +18 -3
  20. django_cfg/apps/knowbase/admin/__init__.py +1 -1
  21. django_cfg/apps/knowbase/admin/archive_admin.py +352 -640
  22. django_cfg/apps/knowbase/admin/chat_admin.py +258 -192
  23. django_cfg/apps/knowbase/admin/document_admin.py +269 -262
  24. django_cfg/apps/knowbase/admin/external_data_admin.py +271 -489
  25. django_cfg/apps/knowbase/config/settings.py +21 -4
  26. django_cfg/apps/knowbase/views/chat_views.py +3 -0
  27. django_cfg/apps/leads/admin/__init__.py +3 -1
  28. django_cfg/apps/leads/admin/leads_admin.py +235 -35
  29. django_cfg/apps/maintenance/admin/__init__.py +2 -2
  30. django_cfg/apps/maintenance/admin/api_key_admin.py +125 -63
  31. django_cfg/apps/maintenance/admin/log_admin.py +143 -61
  32. django_cfg/apps/maintenance/admin/scheduled_admin.py +212 -301
  33. django_cfg/apps/maintenance/admin/site_admin.py +213 -352
  34. django_cfg/apps/newsletter/admin/__init__.py +29 -2
  35. django_cfg/apps/newsletter/admin/newsletter_admin.py +531 -193
  36. django_cfg/apps/payments/admin/__init__.py +18 -27
  37. django_cfg/apps/payments/admin/api_keys_admin.py +179 -546
  38. django_cfg/apps/payments/admin/balance_admin.py +166 -632
  39. django_cfg/apps/payments/admin/currencies_admin.py +235 -607
  40. django_cfg/apps/payments/admin/endpoint_groups_admin.py +127 -0
  41. django_cfg/apps/payments/admin/filters.py +83 -3
  42. django_cfg/apps/payments/admin/networks_admin.py +269 -0
  43. django_cfg/apps/payments/admin/payments_admin.py +183 -460
  44. django_cfg/apps/payments/admin/subscriptions_admin.py +119 -636
  45. django_cfg/apps/payments/admin/tariffs_admin.py +248 -0
  46. django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +153 -34
  47. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
  48. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
  49. django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
  50. django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
  51. django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
  52. django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
  53. django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
  54. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +43 -17
  55. django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
  56. django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
  57. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +109 -63
  58. django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
  59. django_cfg/apps/payments/config/__init__.py +14 -15
  60. django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
  61. django_cfg/apps/payments/config/helpers.py +8 -13
  62. django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
  63. django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
  64. django_cfg/apps/payments/middleware/api_access.py +32 -6
  65. django_cfg/apps/payments/migrations/0001_initial.py +33 -46
  66. django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
  67. django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
  68. django_cfg/apps/payments/models/balance.py +12 -0
  69. django_cfg/apps/payments/models/currencies.py +106 -32
  70. django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
  71. django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
  72. django_cfg/apps/payments/models/payments.py +94 -0
  73. django_cfg/apps/payments/services/core/base.py +4 -4
  74. django_cfg/apps/payments/services/core/currency_service.py +35 -28
  75. django_cfg/apps/payments/services/core/payment_service.py +266 -39
  76. django_cfg/apps/payments/services/providers/__init__.py +3 -0
  77. django_cfg/apps/payments/services/providers/base.py +303 -41
  78. django_cfg/apps/payments/services/providers/models/__init__.py +42 -0
  79. django_cfg/apps/payments/services/providers/models/base.py +145 -0
  80. django_cfg/apps/payments/services/providers/models/providers.py +87 -0
  81. django_cfg/apps/payments/services/providers/models/universal.py +48 -0
  82. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
  83. django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
  84. django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
  85. django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
  86. django_cfg/apps/payments/services/providers/nowpayments/provider.py +557 -0
  87. django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
  88. django_cfg/apps/payments/services/providers/registry.py +9 -37
  89. django_cfg/apps/payments/services/providers/sync_service.py +277 -0
  90. django_cfg/apps/payments/services/types/requests.py +19 -7
  91. django_cfg/apps/payments/signals/payment_signals.py +31 -2
  92. django_cfg/apps/payments/static/payments/js/api-client.js +29 -6
  93. django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
  94. django_cfg/apps/payments/static/payments/js/payment-form.js +98 -32
  95. django_cfg/apps/payments/tasks/__init__.py +39 -0
  96. django_cfg/apps/payments/tasks/types.py +73 -0
  97. django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
  98. django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
  99. django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
  100. django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
  101. django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
  102. django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
  103. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
  104. django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
  105. django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
  106. django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
  107. django_cfg/apps/payments/urls.py +3 -2
  108. django_cfg/apps/payments/urls_admin.py +1 -1
  109. django_cfg/apps/payments/views/api/currencies.py +8 -5
  110. django_cfg/apps/payments/views/overview/services.py +2 -2
  111. django_cfg/apps/payments/views/serializers/currencies.py +22 -8
  112. django_cfg/apps/support/admin/__init__.py +10 -1
  113. django_cfg/apps/support/admin/support_admin.py +338 -141
  114. django_cfg/apps/tasks/admin/__init__.py +11 -0
  115. django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
  116. django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
  117. django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
  118. django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
  119. django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
  120. django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
  121. django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
  122. django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
  123. django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
  124. django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
  125. django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
  126. django_cfg/apps/tasks/tasks/__init__.py +10 -0
  127. django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
  128. django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
  129. django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
  130. django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
  131. django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
  132. django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
  133. django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
  134. django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
  135. django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
  136. django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
  137. django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
  138. django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
  139. django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
  140. django_cfg/apps/tasks/urls.py +2 -2
  141. django_cfg/apps/tasks/urls_admin.py +2 -2
  142. django_cfg/apps/tasks/utils/__init__.py +1 -0
  143. django_cfg/apps/tasks/utils/simulator.py +356 -0
  144. django_cfg/apps/tasks/views/__init__.py +16 -0
  145. django_cfg/apps/tasks/views/api.py +569 -0
  146. django_cfg/apps/tasks/views/dashboard.py +58 -0
  147. django_cfg/config.py +1 -1
  148. django_cfg/core/config.py +10 -5
  149. django_cfg/core/generation.py +1 -1
  150. django_cfg/core/integration/__init__.py +21 -0
  151. django_cfg/management/commands/__init__.py +13 -1
  152. django_cfg/management/commands/migrate_all.py +9 -3
  153. django_cfg/management/commands/migrator.py +11 -6
  154. django_cfg/management/commands/rundramatiq.py +3 -2
  155. django_cfg/management/commands/rundramatiq_simulator.py +430 -0
  156. django_cfg/middleware/__init__.py +0 -2
  157. django_cfg/models/api_keys.py +115 -0
  158. django_cfg/models/constance.py +0 -11
  159. django_cfg/models/payments.py +137 -3
  160. django_cfg/modules/django_admin/__init__.py +64 -0
  161. django_cfg/modules/django_admin/decorators/__init__.py +13 -0
  162. django_cfg/modules/django_admin/decorators/actions.py +106 -0
  163. django_cfg/modules/django_admin/decorators/display.py +106 -0
  164. django_cfg/modules/django_admin/mixins/__init__.py +14 -0
  165. django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
  166. django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
  167. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
  168. django_cfg/modules/django_admin/models/__init__.py +20 -0
  169. django_cfg/modules/django_admin/models/action_models.py +33 -0
  170. django_cfg/modules/django_admin/models/badge_models.py +20 -0
  171. django_cfg/modules/django_admin/models/base.py +26 -0
  172. django_cfg/modules/django_admin/models/display_models.py +31 -0
  173. django_cfg/modules/django_admin/utils/badges.py +159 -0
  174. django_cfg/modules/django_admin/utils/displays.py +247 -0
  175. django_cfg/modules/django_currency/__init__.py +2 -2
  176. django_cfg/modules/django_currency/clients/__init__.py +2 -2
  177. django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
  178. django_cfg/modules/django_currency/core/converter.py +12 -12
  179. django_cfg/modules/django_currency/database/__init__.py +2 -2
  180. django_cfg/modules/django_currency/database/database_loader.py +93 -42
  181. django_cfg/modules/django_llm/llm/client.py +10 -2
  182. django_cfg/modules/django_tasks.py +54 -21
  183. django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
  184. django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
  185. django_cfg/modules/django_unfold/dashboard.py +14 -13
  186. django_cfg/modules/django_unfold/models/config.py +1 -1
  187. django_cfg/registry/core.py +7 -9
  188. django_cfg/registry/third_party.py +2 -2
  189. django_cfg/template_archive/django_sample.zip +0 -0
  190. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/METADATA +2 -1
  191. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/RECORD +198 -160
  192. django_cfg/apps/accounts/admin/activity.py +0 -96
  193. django_cfg/apps/accounts/admin/group.py +0 -17
  194. django_cfg/apps/accounts/admin/otp.py +0 -59
  195. django_cfg/apps/accounts/admin/registration_source.py +0 -97
  196. django_cfg/apps/accounts/admin/twilio_response.py +0 -227
  197. django_cfg/apps/accounts/admin/user.py +0 -300
  198. django_cfg/apps/agents/core/agent.py +0 -281
  199. django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
  200. django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
  201. django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
  202. django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
  203. django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
  204. django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
  205. django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
  206. django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
  207. django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
  208. django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
  209. django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
  210. django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
  211. django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
  212. django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
  213. django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
  214. django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
  215. django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
  216. django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
  217. django_cfg/apps/payments/config/constance/__init__.py +0 -22
  218. django_cfg/apps/payments/config/constance/config_service.py +0 -123
  219. django_cfg/apps/payments/config/constance/fields.py +0 -69
  220. django_cfg/apps/payments/config/constance/settings.py +0 -160
  221. django_cfg/apps/payments/services/providers/nowpayments.py +0 -478
  222. django_cfg/apps/tasks/admin.py +0 -320
  223. django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
  224. django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
  225. django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
  226. django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
  227. django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
  228. django_cfg/apps/tasks/templates/tasks/base.html +0 -96
  229. django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
  230. django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
  231. django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
  232. django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
  233. django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
  234. django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
  235. django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
  236. django_cfg/apps/tasks/views.py +0 -461
  237. django_cfg/management/commands/auto_generate.py +0 -486
  238. django_cfg/middleware/static_nocache.py +0 -55
  239. django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
  240. /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
  241. /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
  242. /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
  243. /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
  244. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/WHEEL +0 -0
  245. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/entry_points.txt +0 -0
  246. {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,127 @@
1
+ """
2
+ Endpoint Groups Admin interface using Django Admin Utilities.
3
+
4
+ Clean endpoint group management for API access control.
5
+ """
6
+
7
+ from django.contrib import admin
8
+ from django.db.models import Count, Q
9
+ from django.utils import timezone
10
+ from datetime import timedelta
11
+
12
+ from unfold.admin import ModelAdmin
13
+
14
+ from django_cfg.modules.django_admin import (
15
+ OptimizedModelAdmin,
16
+ DisplayMixin,
17
+ UserDisplayConfig,
18
+ StatusBadgeConfig,
19
+ MoneyDisplayConfig,
20
+ DateTimeDisplayConfig,
21
+ Icons,
22
+ display,
23
+ action,
24
+ ActionVariant
25
+ )
26
+ from django_cfg.modules.django_admin.utils.displays import (
27
+ UserDisplay,
28
+ MoneyDisplay,
29
+ StatusDisplay,
30
+ DateTimeDisplay
31
+ )
32
+ from django_cfg.modules.django_admin.utils.badges import StatusBadge
33
+
34
+ from ..models.subscriptions import EndpointGroup
35
+
36
+
37
+ @admin.register(EndpointGroup)
38
+ class EndpointGroupAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
39
+ """
40
+ Admin interface for EndpointGroup model.
41
+
42
+ Features:
43
+ - Endpoint group information
44
+ - Pattern and description display
45
+ - Status management
46
+ - Automatic query optimization
47
+ """
48
+
49
+ # Performance optimization
50
+ select_related_fields = []
51
+ annotations = {}
52
+
53
+ # List configuration
54
+ list_display = [
55
+ 'name_display',
56
+ 'pattern_display',
57
+ 'description_display',
58
+ 'status_display',
59
+ 'created_at_display'
60
+ ]
61
+
62
+ list_filter = [
63
+ 'is_enabled',
64
+ 'created_at'
65
+ ]
66
+
67
+ search_fields = ['name', 'pattern', 'description']
68
+
69
+ readonly_fields = [
70
+ 'created_at',
71
+ 'updated_at'
72
+ ]
73
+
74
+ # Display methods
75
+ @display(description="Name")
76
+ def name_display(self, obj):
77
+ """Endpoint group name display."""
78
+ return StatusBadge.create(
79
+ text=obj.name,
80
+ variant="primary",
81
+ icon=Icons.GROUP
82
+ )
83
+
84
+ @display(description="Pattern")
85
+ def pattern_display(self, obj):
86
+ """Pattern display."""
87
+ return StatusBadge.create(
88
+ text=obj.pattern,
89
+ variant="info",
90
+ icon=Icons.CODE
91
+ )
92
+
93
+ @display(description="Description")
94
+ def description_display(self, obj):
95
+ """Description display."""
96
+ if obj.description:
97
+ # Truncate long descriptions
98
+ desc = obj.description[:50] + "..." if len(obj.description) > 50 else obj.description
99
+ return desc
100
+ return "—"
101
+
102
+ @display(description="Status")
103
+ def status_display(self, obj):
104
+ """Status display."""
105
+ if obj.is_enabled:
106
+ status = "Enabled"
107
+ variant = "success"
108
+ icon = Icons.CHECK_CIRCLE
109
+ else:
110
+ status = "Disabled"
111
+ variant = "danger"
112
+ icon = Icons.CANCEL
113
+
114
+ return StatusBadge.create(
115
+ text=status,
116
+ variant=variant,
117
+ icon=icon
118
+ )
119
+
120
+ @display(description="Created")
121
+ def created_at_display(self, obj):
122
+ """Created at display."""
123
+ config = DateTimeDisplayConfig(
124
+ show_relative=True,
125
+ show_absolute=True
126
+ )
127
+ return self.display_datetime_relative(obj, 'created_at', config)
@@ -8,10 +8,12 @@ from django.contrib import admin
8
8
  from django.utils.translation import gettext_lazy as _
9
9
  from django.utils import timezone
10
10
  from django.db.models import Q, Count
11
+ from django.contrib.auth import get_user_model
12
+
11
13
  from datetime import timedelta
12
14
  from typing import List, Tuple, Optional
13
15
 
14
- from ..models import Currency, UniversalPayment, UserBalance, Subscription, APIKey
16
+ from ..models import Currency, UniversalPayment, UserBalance, Subscription, APIKey, ProviderCurrency
15
17
 
16
18
 
17
19
  class CurrencyTypeFilter(admin.SimpleListFilter):
@@ -87,6 +89,86 @@ class CurrencyRateStatusFilter(admin.SimpleListFilter):
87
89
  return queryset
88
90
 
89
91
 
92
+ class CurrencyProviderFilter(admin.SimpleListFilter):
93
+ """Filter currencies by payment provider support."""
94
+
95
+ title = _('Provider Support')
96
+ parameter_name = 'provider_support'
97
+
98
+ def lookups(self, request, model_admin) -> List[Tuple[str, str]]:
99
+ """Get available providers from database."""
100
+ try:
101
+ # Get unique providers from ProviderCurrency
102
+ providers = ProviderCurrency.objects.values_list('provider', flat=True).distinct().order_by('provider')
103
+
104
+ lookups = []
105
+
106
+ # Add provider-specific filters
107
+ for provider in providers:
108
+ if provider:
109
+ provider_display = provider.replace('_', ' ').title()
110
+ # Get count of currencies for this provider
111
+ count = Currency.objects.filter(
112
+ provider_configs__provider=provider,
113
+ provider_configs__is_enabled=True
114
+ ).distinct().count()
115
+
116
+ if count > 0:
117
+ lookups.append((
118
+ provider,
119
+ f'🔗 {provider_display} ({count})'
120
+ ))
121
+
122
+ # Add special filters
123
+ lookups.extend([
124
+ ('any_provider', _('🌐 Any Provider')),
125
+ ('no_provider', _('❌ No Provider')),
126
+ ('multiple_providers', _('🔄 Multiple Providers')),
127
+ ('enabled_only', _('✅ Enabled Providers Only')),
128
+ ])
129
+
130
+ return lookups
131
+
132
+ except Exception as e:
133
+ # Fallback if database query fails
134
+ return [
135
+ ('nowpayments', _('🔗 NowPayments')),
136
+ ('any_provider', _('🌐 Any Provider')),
137
+ ('no_provider', _('❌ No Provider')),
138
+ ]
139
+
140
+ def queryset(self, request, queryset):
141
+ """Filter queryset based on provider selection."""
142
+ if not self.value():
143
+ return queryset
144
+
145
+ if self.value() == 'any_provider':
146
+ # Currencies that have at least one provider
147
+ return queryset.filter(provider_configs__isnull=False).distinct()
148
+
149
+ elif self.value() == 'no_provider':
150
+ # Currencies that have no provider configurations
151
+ return queryset.filter(provider_configs__isnull=True).distinct()
152
+
153
+ elif self.value() == 'multiple_providers':
154
+ # Currencies supported by multiple providers
155
+ return queryset.annotate(
156
+ provider_count=Count('provider_configs__provider', distinct=True)
157
+ ).filter(provider_count__gt=1)
158
+
159
+ elif self.value() == 'enabled_only':
160
+ # Currencies with at least one enabled provider
161
+ return queryset.filter(
162
+ provider_configs__is_enabled=True
163
+ ).distinct()
164
+
165
+ else:
166
+ # Specific provider filter
167
+ return queryset.filter(
168
+ provider_configs__provider=self.value()
169
+ ).distinct()
170
+
171
+
90
172
  class PaymentStatusFilter(admin.SimpleListFilter):
91
173
  """Enhanced payment status filter with groupings."""
92
174
 
@@ -112,7 +194,6 @@ class PaymentStatusFilter(admin.SimpleListFilter):
112
194
  return queryset.filter(
113
195
  status__in=[
114
196
  UniversalPayment.PaymentStatus.PENDING,
115
- UniversalPayment.PaymentStatus.WAITING_FOR_PAYMENT,
116
197
  UniversalPayment.PaymentStatus.CONFIRMING
117
198
  ]
118
199
  )
@@ -166,7 +247,6 @@ class UserEmailFilter(admin.SimpleListFilter):
166
247
 
167
248
  def lookups(self, request, model_admin) -> List[Tuple[str, str]]:
168
249
  # Get top email domains from the database
169
- from django.contrib.auth import get_user_model
170
250
  User = get_user_model()
171
251
 
172
252
  try:
@@ -0,0 +1,269 @@
1
+ """
2
+ Networks Admin interface using Django Admin Utilities.
3
+
4
+ Clean network and provider currency management.
5
+ """
6
+
7
+ from django.contrib import admin
8
+ from django.db.models import Count, Q
9
+ from django.utils import timezone
10
+ from datetime import timedelta
11
+
12
+ from unfold.admin import ModelAdmin
13
+
14
+ from django_cfg.modules.django_admin import (
15
+ OptimizedModelAdmin,
16
+ DisplayMixin,
17
+ UserDisplayConfig,
18
+ StatusBadgeConfig,
19
+ MoneyDisplayConfig,
20
+ DateTimeDisplayConfig,
21
+ Icons,
22
+ display,
23
+ action,
24
+ ActionVariant
25
+ )
26
+ from django_cfg.modules.django_admin.utils.displays import (
27
+ UserDisplay,
28
+ MoneyDisplay,
29
+ StatusDisplay,
30
+ DateTimeDisplay
31
+ )
32
+ from django_cfg.modules.django_admin.utils.badges import StatusBadge
33
+
34
+ from ..models.currencies import Network, ProviderCurrency
35
+
36
+
37
+ @admin.register(Network)
38
+ class NetworkAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
39
+ """
40
+ Admin interface for Network model.
41
+
42
+ Features:
43
+ - Network information display
44
+ - Chain ID and explorer links
45
+ - Status management
46
+ - Automatic query optimization
47
+ """
48
+
49
+ # Performance optimization
50
+ select_related_fields = ['native_currency']
51
+ annotations = {}
52
+
53
+ # List configuration
54
+ list_display = [
55
+ 'name_display',
56
+ 'code_display',
57
+ 'native_currency_display',
58
+ 'explorer_display',
59
+ 'status_display',
60
+ 'created_at_display'
61
+ ]
62
+
63
+ list_filter = [
64
+ 'is_active',
65
+ 'created_at'
66
+ ]
67
+
68
+ search_fields = ['name', 'code']
69
+
70
+ readonly_fields = [
71
+ 'created_at',
72
+ 'updated_at'
73
+ ]
74
+
75
+ # Display methods
76
+ @display(description="Network", ordering="name")
77
+ def name_display(self, obj):
78
+ """Network name display."""
79
+ return obj.name
80
+
81
+ @display(description="Code")
82
+ def code_display(self, obj):
83
+ """Network code display."""
84
+ return obj.code
85
+
86
+ @display(description="Native Currency")
87
+ def native_currency_display(self, obj):
88
+ """Native currency display."""
89
+ if obj.native_currency:
90
+ return f"{obj.native_currency.code} ({obj.native_currency.name})"
91
+ return "—"
92
+
93
+ @display(description="Explorer")
94
+ def explorer_display(self, obj: Network):
95
+ """Explorer link display."""
96
+ if obj.block_explorer_url:
97
+ return "View Explorer"
98
+ return "—"
99
+
100
+ @display(description="Status")
101
+ def status_display(self, obj: Network):
102
+ """Status display."""
103
+ if obj.is_active:
104
+ status = "Active"
105
+ variant = "success"
106
+ icon = Icons.CHECK_CIRCLE
107
+ else:
108
+ status = "Inactive"
109
+ variant = "danger"
110
+ icon = Icons.CANCEL
111
+
112
+ return StatusBadge.create(
113
+ text=status,
114
+ variant=variant,
115
+ icon=icon
116
+ )
117
+
118
+ @display(description="Created")
119
+ def created_at_display(self, obj: Network):
120
+ """Created at display."""
121
+ config = DateTimeDisplayConfig(
122
+ show_relative=True,
123
+ show_seconds=False
124
+ )
125
+ return self.display_datetime_relative(obj, 'created_at', config)
126
+
127
+
128
+ @admin.register(ProviderCurrency)
129
+ class ProviderCurrencyAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
130
+ """
131
+ Admin interface for ProviderCurrency model.
132
+
133
+ Features:
134
+ - Provider and currency relationships
135
+ - Fee and limit display
136
+ - Status management
137
+ """
138
+
139
+ # Performance optimization
140
+ select_related_fields = ['currency', 'network']
141
+ annotations = {}
142
+
143
+ # List configuration
144
+ list_display = [
145
+ 'currency_display',
146
+ 'provider_currency_code_display',
147
+ 'network_display',
148
+ 'provider_display',
149
+ 'fees_display',
150
+ 'limits_display',
151
+ 'status_display',
152
+ 'created_at_display'
153
+ ]
154
+
155
+ list_filter = [
156
+ 'is_enabled',
157
+ 'provider',
158
+ 'currency__symbol',
159
+ 'network__name',
160
+ 'created_at'
161
+ ]
162
+
163
+ search_fields = [
164
+ 'currency__name',
165
+ 'currency__symbol',
166
+ 'network__name',
167
+ 'provider',
168
+ 'provider_currency_code'
169
+ ]
170
+
171
+ readonly_fields = [
172
+ 'created_at',
173
+ 'updated_at'
174
+ ]
175
+
176
+ # Display methods
177
+ @display(description="Currency")
178
+ def currency_display(self, obj: ProviderCurrency):
179
+ """Currency display."""
180
+ return StatusBadge.create(
181
+ text=f"{obj.currency.symbol} ({obj.currency.name})",
182
+ variant="primary",
183
+ icon=Icons.CURRENCY_BITCOIN
184
+ )
185
+
186
+ @display(description="Provider Code")
187
+ def provider_currency_code_display(self, obj: ProviderCurrency):
188
+ """Provider currency code display."""
189
+ return StatusBadge.create(
190
+ text=obj.provider_currency_code,
191
+ variant="warning",
192
+ icon=Icons.CODE
193
+ )
194
+
195
+ @display(description="Network")
196
+ def network_display(self, obj: ProviderCurrency):
197
+ """Network display."""
198
+ if obj.network:
199
+ return StatusBadge.create(
200
+ text=obj.network.name,
201
+ variant="info",
202
+ icon=Icons.LINK
203
+ )
204
+ return "—"
205
+
206
+ @display(description="Provider")
207
+ def provider_display(self, obj: ProviderCurrency):
208
+ """Provider display."""
209
+ return StatusBadge.create(
210
+ text=obj.provider.title(),
211
+ variant="secondary",
212
+ icon=Icons.PAYMENT
213
+ )
214
+
215
+ @display(description="Fees")
216
+ def fees_display(self, obj: ProviderCurrency):
217
+ """Fees display."""
218
+ fees = []
219
+
220
+ if obj.deposit_fee_percentage > 0:
221
+ fees.append(f"Deposit: {obj.deposit_fee_percentage}%")
222
+
223
+ if obj.withdrawal_fee_percentage > 0:
224
+ fees.append(f"Withdrawal: {obj.withdrawal_fee_percentage}%")
225
+
226
+ if obj.fixed_fee_usd > 0:
227
+ fees.append(f"Fixed: ${obj.fixed_fee_usd}")
228
+
229
+ return " • ".join(fees) if fees else "No fees"
230
+
231
+ @display(description="Limits")
232
+ def limits_display(self, obj: ProviderCurrency):
233
+ """Limits display."""
234
+ limits = []
235
+
236
+ if obj.min_amount > 0:
237
+ limits.append(f"Min: {obj.min_amount}")
238
+
239
+ if obj.max_amount > 0:
240
+ limits.append(f"Max: {obj.max_amount}")
241
+
242
+ return " • ".join(limits) if limits else "No limits"
243
+
244
+ @display(description="Status")
245
+ def status_display(self, obj: ProviderCurrency):
246
+ """Status display."""
247
+ if obj.is_enabled:
248
+ status = "Enabled"
249
+ variant = "success"
250
+ icon = Icons.CHECK_CIRCLE
251
+ else:
252
+ status = "Disabled"
253
+ variant = "danger"
254
+ icon = Icons.CANCEL
255
+
256
+ return StatusBadge.create(
257
+ text=status,
258
+ variant=variant,
259
+ icon=icon
260
+ )
261
+
262
+ @display(description="Created")
263
+ def created_at_display(self, obj: ProviderCurrency):
264
+ """Created at display."""
265
+ config = DateTimeDisplayConfig(
266
+ show_relative=True,
267
+ show_seconds=False
268
+ )
269
+ return self.display_datetime_relative(obj, 'created_at', config)