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.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/accounts/admin/__init__.py +24 -8
- django_cfg/apps/accounts/admin/activity_admin.py +146 -0
- django_cfg/apps/accounts/admin/filters.py +98 -22
- django_cfg/apps/accounts/admin/group_admin.py +86 -0
- django_cfg/apps/accounts/admin/inlines.py +42 -13
- django_cfg/apps/accounts/admin/otp_admin.py +115 -0
- django_cfg/apps/accounts/admin/registration_admin.py +173 -0
- django_cfg/apps/accounts/admin/resources.py +123 -19
- django_cfg/apps/accounts/admin/twilio_admin.py +327 -0
- django_cfg/apps/accounts/admin/user_admin.py +362 -0
- django_cfg/apps/agents/admin/__init__.py +17 -4
- django_cfg/apps/agents/admin/execution_admin.py +204 -183
- django_cfg/apps/agents/admin/registry_admin.py +230 -255
- django_cfg/apps/agents/admin/toolsets_admin.py +274 -321
- django_cfg/apps/agents/core/__init__.py +1 -1
- django_cfg/apps/agents/core/django_agent.py +221 -0
- django_cfg/apps/agents/core/exceptions.py +14 -0
- django_cfg/apps/agents/core/orchestrator.py +18 -3
- django_cfg/apps/knowbase/admin/__init__.py +1 -1
- django_cfg/apps/knowbase/admin/archive_admin.py +352 -640
- django_cfg/apps/knowbase/admin/chat_admin.py +258 -192
- django_cfg/apps/knowbase/admin/document_admin.py +269 -262
- django_cfg/apps/knowbase/admin/external_data_admin.py +271 -489
- django_cfg/apps/knowbase/config/settings.py +21 -4
- django_cfg/apps/knowbase/views/chat_views.py +3 -0
- django_cfg/apps/leads/admin/__init__.py +3 -1
- django_cfg/apps/leads/admin/leads_admin.py +235 -35
- django_cfg/apps/maintenance/admin/__init__.py +2 -2
- django_cfg/apps/maintenance/admin/api_key_admin.py +125 -63
- django_cfg/apps/maintenance/admin/log_admin.py +143 -61
- django_cfg/apps/maintenance/admin/scheduled_admin.py +212 -301
- django_cfg/apps/maintenance/admin/site_admin.py +213 -352
- django_cfg/apps/newsletter/admin/__init__.py +29 -2
- django_cfg/apps/newsletter/admin/newsletter_admin.py +531 -193
- django_cfg/apps/payments/admin/__init__.py +18 -27
- django_cfg/apps/payments/admin/api_keys_admin.py +179 -546
- django_cfg/apps/payments/admin/balance_admin.py +166 -632
- django_cfg/apps/payments/admin/currencies_admin.py +235 -607
- django_cfg/apps/payments/admin/endpoint_groups_admin.py +127 -0
- django_cfg/apps/payments/admin/filters.py +83 -3
- django_cfg/apps/payments/admin/networks_admin.py +258 -0
- django_cfg/apps/payments/admin/payments_admin.py +171 -461
- django_cfg/apps/payments/admin/subscriptions_admin.py +119 -636
- django_cfg/apps/payments/admin/tariffs_admin.py +248 -0
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +105 -34
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +12 -16
- django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +13 -18
- django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
- django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
- django_cfg/apps/payments/middleware/api_access.py +32 -6
- django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +26 -0
- django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +28 -0
- django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +30 -0
- django_cfg/apps/payments/models/balance.py +12 -0
- django_cfg/apps/payments/models/currencies.py +106 -32
- django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
- django_cfg/apps/payments/services/core/currency_service.py +35 -28
- django_cfg/apps/payments/services/core/payment_service.py +1 -1
- django_cfg/apps/payments/services/providers/__init__.py +3 -0
- django_cfg/apps/payments/services/providers/base.py +95 -39
- django_cfg/apps/payments/services/providers/models/__init__.py +40 -0
- django_cfg/apps/payments/services/providers/models/base.py +122 -0
- django_cfg/apps/payments/services/providers/models/providers.py +87 -0
- django_cfg/apps/payments/services/providers/models/universal.py +48 -0
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
- django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
- django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
- django_cfg/apps/payments/services/providers/{nowpayments.py → nowpayments/provider.py} +240 -209
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
- django_cfg/apps/payments/services/providers/registry.py +4 -32
- django_cfg/apps/payments/services/providers/sync_service.py +277 -0
- django_cfg/apps/payments/static/payments/js/api-client.js +23 -5
- django_cfg/apps/payments/static/payments/js/payment-form.js +65 -8
- django_cfg/apps/payments/tasks/__init__.py +39 -0
- django_cfg/apps/payments/tasks/types.py +73 -0
- django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
- django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
- django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
- django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
- django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
- django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
- django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
- django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
- django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
- django_cfg/apps/payments/urls_admin.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +5 -5
- django_cfg/apps/payments/views/overview/services.py +2 -2
- django_cfg/apps/payments/views/serializers/currencies.py +4 -3
- django_cfg/apps/support/admin/__init__.py +10 -1
- django_cfg/apps/support/admin/support_admin.py +338 -141
- django_cfg/apps/tasks/admin/__init__.py +11 -0
- django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
- django_cfg/apps/urls.py +1 -2
- django_cfg/config.py +1 -1
- django_cfg/core/config.py +10 -5
- django_cfg/core/generation.py +1 -1
- django_cfg/management/commands/__init__.py +13 -1
- django_cfg/management/commands/app_agent_diagnose.py +470 -0
- django_cfg/management/commands/app_agent_generate.py +342 -0
- django_cfg/management/commands/app_agent_info.py +308 -0
- django_cfg/management/commands/migrate_all.py +9 -3
- django_cfg/management/commands/migrator.py +11 -6
- django_cfg/management/commands/rundramatiq.py +3 -2
- django_cfg/middleware/__init__.py +0 -2
- django_cfg/models/api_keys.py +115 -0
- django_cfg/modules/django_admin/__init__.py +64 -0
- django_cfg/modules/django_admin/decorators/__init__.py +13 -0
- django_cfg/modules/django_admin/decorators/actions.py +106 -0
- django_cfg/modules/django_admin/decorators/display.py +106 -0
- django_cfg/modules/django_admin/mixins/__init__.py +14 -0
- django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
- django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
- django_cfg/modules/django_admin/models/__init__.py +20 -0
- django_cfg/modules/django_admin/models/action_models.py +33 -0
- django_cfg/modules/django_admin/models/badge_models.py +20 -0
- django_cfg/modules/django_admin/models/base.py +26 -0
- django_cfg/modules/django_admin/models/display_models.py +31 -0
- django_cfg/modules/django_admin/utils/badges.py +159 -0
- django_cfg/modules/django_admin/utils/displays.py +247 -0
- django_cfg/modules/django_app_agent/__init__.py +87 -0
- django_cfg/modules/django_app_agent/agents/__init__.py +40 -0
- django_cfg/modules/django_app_agent/agents/base/__init__.py +24 -0
- django_cfg/modules/django_app_agent/agents/base/agent.py +354 -0
- django_cfg/modules/django_app_agent/agents/base/context.py +236 -0
- django_cfg/modules/django_app_agent/agents/base/executor.py +430 -0
- django_cfg/modules/django_app_agent/agents/generation/__init__.py +12 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +15 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +147 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +99 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +32 -0
- django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +290 -0
- django_cfg/modules/django_app_agent/agents/interfaces.py +376 -0
- django_cfg/modules/django_app_agent/core/__init__.py +33 -0
- django_cfg/modules/django_app_agent/core/config.py +300 -0
- django_cfg/modules/django_app_agent/core/exceptions.py +359 -0
- django_cfg/modules/django_app_agent/models/__init__.py +71 -0
- django_cfg/modules/django_app_agent/models/base.py +283 -0
- django_cfg/modules/django_app_agent/models/context.py +496 -0
- django_cfg/modules/django_app_agent/models/enums.py +481 -0
- django_cfg/modules/django_app_agent/models/requests.py +500 -0
- django_cfg/modules/django_app_agent/models/responses.py +585 -0
- django_cfg/modules/django_app_agent/pytest.ini +6 -0
- django_cfg/modules/django_app_agent/services/__init__.py +42 -0
- django_cfg/modules/django_app_agent/services/app_generator/__init__.py +30 -0
- django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +133 -0
- django_cfg/modules/django_app_agent/services/app_generator/context.py +40 -0
- django_cfg/modules/django_app_agent/services/app_generator/main.py +202 -0
- django_cfg/modules/django_app_agent/services/app_generator/structure.py +316 -0
- django_cfg/modules/django_app_agent/services/app_generator/validation.py +125 -0
- django_cfg/modules/django_app_agent/services/base.py +437 -0
- django_cfg/modules/django_app_agent/services/context_builder/__init__.py +34 -0
- django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +141 -0
- django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +276 -0
- django_cfg/modules/django_app_agent/services/context_builder/main.py +272 -0
- django_cfg/modules/django_app_agent/services/context_builder/models.py +40 -0
- django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +85 -0
- django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +31 -0
- django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +311 -0
- django_cfg/modules/django_app_agent/services/project_scanner/main.py +221 -0
- django_cfg/modules/django_app_agent/services/project_scanner/models.py +59 -0
- django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +94 -0
- django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +28 -0
- django_cfg/modules/django_app_agent/services/questioning_service/main.py +273 -0
- django_cfg/modules/django_app_agent/services/questioning_service/models.py +111 -0
- django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +251 -0
- django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +347 -0
- django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +356 -0
- django_cfg/modules/django_app_agent/services/report_service.py +332 -0
- django_cfg/modules/django_app_agent/services/template_manager/__init__.py +18 -0
- django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +236 -0
- django_cfg/modules/django_app_agent/services/template_manager/main.py +159 -0
- django_cfg/modules/django_app_agent/services/template_manager/models.py +36 -0
- django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +100 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +105 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +31 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +44 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +81 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +107 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +139 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +91 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +195 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +35 -0
- django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +211 -0
- django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +200 -0
- django_cfg/modules/django_app_agent/services/validation_service/__init__.py +25 -0
- django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +333 -0
- django_cfg/modules/django_app_agent/services/validation_service/main.py +242 -0
- django_cfg/modules/django_app_agent/services/validation_service/models.py +66 -0
- django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +352 -0
- django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +272 -0
- django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +203 -0
- django_cfg/modules/django_app_agent/ui/__init__.py +25 -0
- django_cfg/modules/django_app_agent/ui/cli.py +419 -0
- django_cfg/modules/django_app_agent/ui/rich_components.py +622 -0
- django_cfg/modules/django_app_agent/utils/__init__.py +38 -0
- django_cfg/modules/django_app_agent/utils/logging.py +360 -0
- django_cfg/modules/django_app_agent/utils/validation.py +417 -0
- django_cfg/modules/django_currency/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
- django_cfg/modules/django_currency/core/converter.py +12 -12
- django_cfg/modules/django_currency/database/__init__.py +2 -2
- django_cfg/modules/django_currency/database/database_loader.py +93 -42
- django_cfg/modules/django_llm/llm/client.py +10 -2
- django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
- django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
- django_cfg/modules/django_unfold/dashboard.py +14 -13
- django_cfg/modules/django_unfold/models/config.py +1 -1
- django_cfg/registry/core.py +3 -0
- django_cfg/registry/third_party.py +2 -2
- django_cfg/template_archive/django_sample.zip +0 -0
- {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/METADATA +2 -1
- {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/RECORD +224 -118
- django_cfg/apps/accounts/admin/activity.py +0 -96
- django_cfg/apps/accounts/admin/group.py +0 -17
- django_cfg/apps/accounts/admin/otp.py +0 -59
- django_cfg/apps/accounts/admin/registration_source.py +0 -97
- django_cfg/apps/accounts/admin/twilio_response.py +0 -227
- django_cfg/apps/accounts/admin/user.py +0 -300
- django_cfg/apps/agents/core/agent.py +0 -281
- django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
- django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
- django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
- django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
- django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
- django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
- django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
- django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
- django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
- django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
- django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
- django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
- django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
- django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
- django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
- django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
- django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
- django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
- django_cfg/apps/tasks/admin.py +0 -320
- django_cfg/middleware/static_nocache.py +0 -55
- django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
- /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
- {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.5.dist-info → django_cfg-1.3.9.dist-info}/entry_points.txt +0 -0
- {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)
|