django-cfg 1.3.5__py3-none-any.whl → 1.3.9__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 (252) 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 +258 -0
  43. django_cfg/apps/payments/admin/payments_admin.py +171 -461
  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 +105 -34
  47. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +12 -16
  48. django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
  49. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +13 -18
  50. django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
  51. django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
  52. django_cfg/apps/payments/middleware/api_access.py +32 -6
  53. django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +26 -0
  54. django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +28 -0
  55. django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +30 -0
  56. django_cfg/apps/payments/models/balance.py +12 -0
  57. django_cfg/apps/payments/models/currencies.py +106 -32
  58. django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
  59. django_cfg/apps/payments/services/core/currency_service.py +35 -28
  60. django_cfg/apps/payments/services/core/payment_service.py +1 -1
  61. django_cfg/apps/payments/services/providers/__init__.py +3 -0
  62. django_cfg/apps/payments/services/providers/base.py +95 -39
  63. django_cfg/apps/payments/services/providers/models/__init__.py +40 -0
  64. django_cfg/apps/payments/services/providers/models/base.py +122 -0
  65. django_cfg/apps/payments/services/providers/models/providers.py +87 -0
  66. django_cfg/apps/payments/services/providers/models/universal.py +48 -0
  67. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
  68. django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
  69. django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
  70. django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
  71. django_cfg/apps/payments/services/providers/{nowpayments.py → nowpayments/provider.py} +240 -209
  72. django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
  73. django_cfg/apps/payments/services/providers/registry.py +4 -32
  74. django_cfg/apps/payments/services/providers/sync_service.py +277 -0
  75. django_cfg/apps/payments/static/payments/js/api-client.js +23 -5
  76. django_cfg/apps/payments/static/payments/js/payment-form.js +65 -8
  77. django_cfg/apps/payments/tasks/__init__.py +39 -0
  78. django_cfg/apps/payments/tasks/types.py +73 -0
  79. django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
  80. django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
  81. django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
  82. django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
  83. django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
  84. django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
  85. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
  86. django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
  87. django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
  88. django_cfg/apps/payments/urls_admin.py +1 -1
  89. django_cfg/apps/payments/views/api/currencies.py +5 -5
  90. django_cfg/apps/payments/views/overview/services.py +2 -2
  91. django_cfg/apps/payments/views/serializers/currencies.py +4 -3
  92. django_cfg/apps/support/admin/__init__.py +10 -1
  93. django_cfg/apps/support/admin/support_admin.py +338 -141
  94. django_cfg/apps/tasks/admin/__init__.py +11 -0
  95. django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
  96. django_cfg/apps/urls.py +1 -2
  97. django_cfg/config.py +1 -1
  98. django_cfg/core/config.py +10 -5
  99. django_cfg/core/generation.py +1 -1
  100. django_cfg/management/commands/__init__.py +13 -1
  101. django_cfg/management/commands/app_agent_diagnose.py +470 -0
  102. django_cfg/management/commands/app_agent_generate.py +342 -0
  103. django_cfg/management/commands/app_agent_info.py +308 -0
  104. django_cfg/management/commands/migrate_all.py +9 -3
  105. django_cfg/management/commands/migrator.py +11 -6
  106. django_cfg/management/commands/rundramatiq.py +3 -2
  107. django_cfg/middleware/__init__.py +0 -2
  108. django_cfg/models/api_keys.py +115 -0
  109. django_cfg/modules/django_admin/__init__.py +64 -0
  110. django_cfg/modules/django_admin/decorators/__init__.py +13 -0
  111. django_cfg/modules/django_admin/decorators/actions.py +106 -0
  112. django_cfg/modules/django_admin/decorators/display.py +106 -0
  113. django_cfg/modules/django_admin/mixins/__init__.py +14 -0
  114. django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
  115. django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
  116. django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
  117. django_cfg/modules/django_admin/models/__init__.py +20 -0
  118. django_cfg/modules/django_admin/models/action_models.py +33 -0
  119. django_cfg/modules/django_admin/models/badge_models.py +20 -0
  120. django_cfg/modules/django_admin/models/base.py +26 -0
  121. django_cfg/modules/django_admin/models/display_models.py +31 -0
  122. django_cfg/modules/django_admin/utils/badges.py +159 -0
  123. django_cfg/modules/django_admin/utils/displays.py +247 -0
  124. django_cfg/modules/django_app_agent/__init__.py +87 -0
  125. django_cfg/modules/django_app_agent/agents/__init__.py +40 -0
  126. django_cfg/modules/django_app_agent/agents/base/__init__.py +24 -0
  127. django_cfg/modules/django_app_agent/agents/base/agent.py +354 -0
  128. django_cfg/modules/django_app_agent/agents/base/context.py +236 -0
  129. django_cfg/modules/django_app_agent/agents/base/executor.py +430 -0
  130. django_cfg/modules/django_app_agent/agents/generation/__init__.py +12 -0
  131. django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +15 -0
  132. django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +147 -0
  133. django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +99 -0
  134. django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +32 -0
  135. django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +290 -0
  136. django_cfg/modules/django_app_agent/agents/interfaces.py +376 -0
  137. django_cfg/modules/django_app_agent/core/__init__.py +33 -0
  138. django_cfg/modules/django_app_agent/core/config.py +300 -0
  139. django_cfg/modules/django_app_agent/core/exceptions.py +359 -0
  140. django_cfg/modules/django_app_agent/models/__init__.py +71 -0
  141. django_cfg/modules/django_app_agent/models/base.py +283 -0
  142. django_cfg/modules/django_app_agent/models/context.py +496 -0
  143. django_cfg/modules/django_app_agent/models/enums.py +481 -0
  144. django_cfg/modules/django_app_agent/models/requests.py +500 -0
  145. django_cfg/modules/django_app_agent/models/responses.py +585 -0
  146. django_cfg/modules/django_app_agent/pytest.ini +6 -0
  147. django_cfg/modules/django_app_agent/services/__init__.py +42 -0
  148. django_cfg/modules/django_app_agent/services/app_generator/__init__.py +30 -0
  149. django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +133 -0
  150. django_cfg/modules/django_app_agent/services/app_generator/context.py +40 -0
  151. django_cfg/modules/django_app_agent/services/app_generator/main.py +202 -0
  152. django_cfg/modules/django_app_agent/services/app_generator/structure.py +316 -0
  153. django_cfg/modules/django_app_agent/services/app_generator/validation.py +125 -0
  154. django_cfg/modules/django_app_agent/services/base.py +437 -0
  155. django_cfg/modules/django_app_agent/services/context_builder/__init__.py +34 -0
  156. django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +141 -0
  157. django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +276 -0
  158. django_cfg/modules/django_app_agent/services/context_builder/main.py +272 -0
  159. django_cfg/modules/django_app_agent/services/context_builder/models.py +40 -0
  160. django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +85 -0
  161. django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +31 -0
  162. django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +311 -0
  163. django_cfg/modules/django_app_agent/services/project_scanner/main.py +221 -0
  164. django_cfg/modules/django_app_agent/services/project_scanner/models.py +59 -0
  165. django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +94 -0
  166. django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +28 -0
  167. django_cfg/modules/django_app_agent/services/questioning_service/main.py +273 -0
  168. django_cfg/modules/django_app_agent/services/questioning_service/models.py +111 -0
  169. django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +251 -0
  170. django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +347 -0
  171. django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +356 -0
  172. django_cfg/modules/django_app_agent/services/report_service.py +332 -0
  173. django_cfg/modules/django_app_agent/services/template_manager/__init__.py +18 -0
  174. django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +236 -0
  175. django_cfg/modules/django_app_agent/services/template_manager/main.py +159 -0
  176. django_cfg/modules/django_app_agent/services/template_manager/models.py +36 -0
  177. django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +100 -0
  178. django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +105 -0
  179. django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +31 -0
  180. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +44 -0
  181. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +81 -0
  182. django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +107 -0
  183. django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +139 -0
  184. django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +91 -0
  185. django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +195 -0
  186. django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +35 -0
  187. django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +211 -0
  188. django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +200 -0
  189. django_cfg/modules/django_app_agent/services/validation_service/__init__.py +25 -0
  190. django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +333 -0
  191. django_cfg/modules/django_app_agent/services/validation_service/main.py +242 -0
  192. django_cfg/modules/django_app_agent/services/validation_service/models.py +66 -0
  193. django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +352 -0
  194. django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +272 -0
  195. django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +203 -0
  196. django_cfg/modules/django_app_agent/ui/__init__.py +25 -0
  197. django_cfg/modules/django_app_agent/ui/cli.py +419 -0
  198. django_cfg/modules/django_app_agent/ui/rich_components.py +622 -0
  199. django_cfg/modules/django_app_agent/utils/__init__.py +38 -0
  200. django_cfg/modules/django_app_agent/utils/logging.py +360 -0
  201. django_cfg/modules/django_app_agent/utils/validation.py +417 -0
  202. django_cfg/modules/django_currency/__init__.py +2 -2
  203. django_cfg/modules/django_currency/clients/__init__.py +2 -2
  204. django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
  205. django_cfg/modules/django_currency/core/converter.py +12 -12
  206. django_cfg/modules/django_currency/database/__init__.py +2 -2
  207. django_cfg/modules/django_currency/database/database_loader.py +93 -42
  208. django_cfg/modules/django_llm/llm/client.py +10 -2
  209. django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
  210. django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
  211. django_cfg/modules/django_unfold/dashboard.py +14 -13
  212. django_cfg/modules/django_unfold/models/config.py +1 -1
  213. django_cfg/registry/core.py +3 -0
  214. django_cfg/registry/third_party.py +2 -2
  215. django_cfg/template_archive/django_sample.zip +0 -0
  216. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/METADATA +2 -1
  217. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/RECORD +224 -118
  218. django_cfg/apps/accounts/admin/activity.py +0 -96
  219. django_cfg/apps/accounts/admin/group.py +0 -17
  220. django_cfg/apps/accounts/admin/otp.py +0 -59
  221. django_cfg/apps/accounts/admin/registration_source.py +0 -97
  222. django_cfg/apps/accounts/admin/twilio_response.py +0 -227
  223. django_cfg/apps/accounts/admin/user.py +0 -300
  224. django_cfg/apps/agents/core/agent.py +0 -281
  225. django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
  226. django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
  227. django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
  228. django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
  229. django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
  230. django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
  231. django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
  232. django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
  233. django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
  234. django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
  235. django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
  236. django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
  237. django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
  238. django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
  239. django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
  240. django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
  241. django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
  242. django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
  243. django_cfg/apps/tasks/admin.py +0 -320
  244. django_cfg/middleware/static_nocache.py +0 -55
  245. django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
  246. /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
  247. /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
  248. /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
  249. /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
  250. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/WHEEL +0 -0
  251. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/entry_points.txt +0 -0
  252. {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.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,258 @@
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
+ 'network_display',
147
+ 'provider_display',
148
+ 'fees_display',
149
+ 'limits_display',
150
+ 'status_display',
151
+ 'created_at_display'
152
+ ]
153
+
154
+ list_filter = [
155
+ 'is_enabled',
156
+ 'provider',
157
+ 'currency__symbol',
158
+ 'network__name',
159
+ 'created_at'
160
+ ]
161
+
162
+ search_fields = [
163
+ 'currency__name',
164
+ 'currency__symbol',
165
+ 'network__name',
166
+ 'provider'
167
+ ]
168
+
169
+ readonly_fields = [
170
+ 'created_at',
171
+ 'updated_at'
172
+ ]
173
+
174
+ # Display methods
175
+ @display(description="Currency")
176
+ def currency_display(self, obj: ProviderCurrency):
177
+ """Currency display."""
178
+ return StatusBadge.create(
179
+ text=f"{obj.currency.symbol} ({obj.currency.name})",
180
+ variant="primary",
181
+ icon=Icons.CURRENCY_BITCOIN
182
+ )
183
+
184
+ @display(description="Network")
185
+ def network_display(self, obj: ProviderCurrency):
186
+ """Network display."""
187
+ if obj.network:
188
+ return StatusBadge.create(
189
+ text=obj.network.name,
190
+ variant="info",
191
+ icon=Icons.LINK
192
+ )
193
+ return "—"
194
+
195
+ @display(description="Provider")
196
+ def provider_display(self, obj: ProviderCurrency):
197
+ """Provider display."""
198
+ return StatusBadge.create(
199
+ text=obj.provider.title(),
200
+ variant="secondary",
201
+ icon=Icons.PAYMENT
202
+ )
203
+
204
+ @display(description="Fees")
205
+ def fees_display(self, obj: ProviderCurrency):
206
+ """Fees display."""
207
+ fees = []
208
+
209
+ if obj.deposit_fee_percentage > 0:
210
+ fees.append(f"Deposit: {obj.deposit_fee_percentage}%")
211
+
212
+ if obj.withdrawal_fee_percentage > 0:
213
+ fees.append(f"Withdrawal: {obj.withdrawal_fee_percentage}%")
214
+
215
+ if obj.fixed_fee_usd > 0:
216
+ fees.append(f"Fixed: ${obj.fixed_fee_usd}")
217
+
218
+ return " • ".join(fees) if fees else "No fees"
219
+
220
+ @display(description="Limits")
221
+ def limits_display(self, obj: ProviderCurrency):
222
+ """Limits display."""
223
+ limits = []
224
+
225
+ if obj.min_amount > 0:
226
+ limits.append(f"Min: {obj.min_amount}")
227
+
228
+ if obj.max_amount > 0:
229
+ limits.append(f"Max: {obj.max_amount}")
230
+
231
+ return " • ".join(limits) if limits else "No limits"
232
+
233
+ @display(description="Status")
234
+ def status_display(self, obj: ProviderCurrency):
235
+ """Status display."""
236
+ if obj.is_enabled:
237
+ status = "Enabled"
238
+ variant = "success"
239
+ icon = Icons.CHECK_CIRCLE
240
+ else:
241
+ status = "Disabled"
242
+ variant = "danger"
243
+ icon = Icons.CANCEL
244
+
245
+ return StatusBadge.create(
246
+ text=status,
247
+ variant=variant,
248
+ icon=icon
249
+ )
250
+
251
+ @display(description="Created")
252
+ def created_at_display(self, obj: ProviderCurrency):
253
+ """Created at display."""
254
+ config = DateTimeDisplayConfig(
255
+ show_relative=True,
256
+ show_seconds=False
257
+ )
258
+ return self.display_datetime_relative(obj, 'created_at', config)