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.
- 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 +269 -0
- django_cfg/apps/payments/admin/payments_admin.py +183 -460
- 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 +153 -34
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +43 -17
- django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
- django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +109 -63
- django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
- django_cfg/apps/payments/config/__init__.py +14 -15
- django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
- django_cfg/apps/payments/config/helpers.py +8 -13
- 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/0001_initial.py +33 -46
- django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
- django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -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/models/managers/payment_managers.py +142 -25
- django_cfg/apps/payments/models/payments.py +94 -0
- django_cfg/apps/payments/services/core/base.py +4 -4
- django_cfg/apps/payments/services/core/currency_service.py +35 -28
- django_cfg/apps/payments/services/core/payment_service.py +266 -39
- django_cfg/apps/payments/services/providers/__init__.py +3 -0
- django_cfg/apps/payments/services/providers/base.py +303 -41
- django_cfg/apps/payments/services/providers/models/__init__.py +42 -0
- django_cfg/apps/payments/services/providers/models/base.py +145 -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/provider.py +557 -0
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
- django_cfg/apps/payments/services/providers/registry.py +9 -37
- django_cfg/apps/payments/services/providers/sync_service.py +277 -0
- django_cfg/apps/payments/services/types/requests.py +19 -7
- django_cfg/apps/payments/signals/payment_signals.py +31 -2
- django_cfg/apps/payments/static/payments/js/api-client.js +29 -6
- django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
- django_cfg/apps/payments/static/payments/js/payment-form.js +98 -32
- 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/templatetags/payment_tags.py +8 -0
- django_cfg/apps/payments/urls.py +3 -2
- django_cfg/apps/payments/urls_admin.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +8 -5
- django_cfg/apps/payments/views/overview/services.py +2 -2
- django_cfg/apps/payments/views/serializers/currencies.py +22 -8
- 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/tasks/static/tasks/css/dashboard.css +68 -217
- django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
- django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
- django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
- django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
- django_cfg/apps/tasks/tasks/__init__.py +10 -0
- django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
- django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
- django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
- django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
- django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
- django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
- django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
- django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
- django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
- django_cfg/apps/tasks/urls.py +2 -2
- django_cfg/apps/tasks/urls_admin.py +2 -2
- django_cfg/apps/tasks/utils/__init__.py +1 -0
- django_cfg/apps/tasks/utils/simulator.py +356 -0
- django_cfg/apps/tasks/views/__init__.py +16 -0
- django_cfg/apps/tasks/views/api.py +569 -0
- django_cfg/apps/tasks/views/dashboard.py +58 -0
- django_cfg/config.py +1 -1
- django_cfg/core/config.py +10 -5
- django_cfg/core/generation.py +1 -1
- django_cfg/core/integration/__init__.py +21 -0
- django_cfg/management/commands/__init__.py +13 -1
- 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/management/commands/rundramatiq_simulator.py +430 -0
- django_cfg/middleware/__init__.py +0 -2
- django_cfg/models/api_keys.py +115 -0
- django_cfg/models/constance.py +0 -11
- django_cfg/models/payments.py +137 -3
- 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_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_tasks.py +54 -21
- 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 +7 -9
- django_cfg/registry/third_party.py +2 -2
- django_cfg/template_archive/django_sample.zip +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/METADATA +2 -1
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/RECORD +198 -160
- 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/payments/config/constance/__init__.py +0 -22
- django_cfg/apps/payments/config/constance/config_service.py +0 -123
- django_cfg/apps/payments/config/constance/fields.py +0 -69
- django_cfg/apps/payments/config/constance/settings.py +0 -160
- django_cfg/apps/payments/services/providers/nowpayments.py +0 -478
- django_cfg/apps/tasks/admin.py +0 -320
- django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
- django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
- django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
- django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
- django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
- django_cfg/apps/tasks/templates/tasks/base.html +0 -96
- django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
- django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
- django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
- django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
- django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
- django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
- django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
- django_cfg/apps/tasks/views.py +0 -461
- django_cfg/management/commands/auto_generate.py +0 -486
- 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.7.dist-info → django_cfg-1.3.11.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/licenses/LICENSE +0 -0
@@ -1,96 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
User Activity admin configuration.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from django.contrib import admin
|
6
|
-
from django.utils.html import format_html
|
7
|
-
from django.contrib.humanize.templatetags.humanize import naturaltime
|
8
|
-
from unfold.admin import ModelAdmin
|
9
|
-
|
10
|
-
from ..models import UserActivity
|
11
|
-
from .filters import ActivityTypeFilter
|
12
|
-
|
13
|
-
|
14
|
-
@admin.register(UserActivity)
|
15
|
-
class UserActivityAdmin(ModelAdmin):
|
16
|
-
"""Enhanced admin for UserActivity model."""
|
17
|
-
|
18
|
-
list_display = [
|
19
|
-
'user_display',
|
20
|
-
'activity_type_display',
|
21
|
-
'description_short',
|
22
|
-
'ip_address',
|
23
|
-
'created_at_display'
|
24
|
-
]
|
25
|
-
list_display_links = ['user_display', 'activity_type_display']
|
26
|
-
list_filter = [ActivityTypeFilter, 'activity_type', 'created_at']
|
27
|
-
search_fields = ['user__username', 'user__email', 'description', 'ip_address']
|
28
|
-
readonly_fields = ['created_at']
|
29
|
-
date_hierarchy = 'created_at'
|
30
|
-
ordering = ['-created_at']
|
31
|
-
|
32
|
-
fieldsets = (
|
33
|
-
('Activity', {
|
34
|
-
'fields': ('user', 'activity_type', 'description')
|
35
|
-
}),
|
36
|
-
('Related Object', {
|
37
|
-
'fields': ('object_id', 'object_type'),
|
38
|
-
'classes': ('collapse',),
|
39
|
-
'description': 'Optional reference to related model instance'
|
40
|
-
}),
|
41
|
-
('Request Info', {
|
42
|
-
'fields': ('ip_address', 'user_agent'),
|
43
|
-
'classes': ('collapse',)
|
44
|
-
}),
|
45
|
-
('Timestamp', {
|
46
|
-
'fields': ('created_at',)
|
47
|
-
}),
|
48
|
-
)
|
49
|
-
|
50
|
-
def user_display(self, obj):
|
51
|
-
"""Enhanced user display."""
|
52
|
-
user = obj.user
|
53
|
-
initials = f"{user.first_name[:1]}{user.last_name[:1]}".upper() or user.username[:2].upper()
|
54
|
-
return format_html(
|
55
|
-
'<div style="display: flex; align-items: center; gap: 8px;">'
|
56
|
-
'<div style="width: 20px; height: 20px; border-radius: 50%; background: #6c757d; '
|
57
|
-
'color: white; display: flex; align-items: center; justify-content: center; '
|
58
|
-
'font-weight: bold; font-size: 8px;">{}</div>'
|
59
|
-
'<span>{}</span></div>',
|
60
|
-
initials,
|
61
|
-
user.get_full_name() or user.username
|
62
|
-
)
|
63
|
-
|
64
|
-
user_display.short_description = "User"
|
65
|
-
|
66
|
-
def activity_type_display(self, obj):
|
67
|
-
"""Activity type with icons."""
|
68
|
-
icons = {
|
69
|
-
'login': '🔐',
|
70
|
-
'logout': '🚪',
|
71
|
-
'otp_requested': '📧',
|
72
|
-
'otp_verified': '✅',
|
73
|
-
'profile_updated': '✏️',
|
74
|
-
'registration': '👤',
|
75
|
-
}
|
76
|
-
icon = icons.get(obj.activity_type, '📝')
|
77
|
-
return format_html('{} {}', icon, obj.get_activity_type_display())
|
78
|
-
|
79
|
-
activity_type_display.short_description = "Activity"
|
80
|
-
|
81
|
-
def description_short(self, obj):
|
82
|
-
"""Truncated description."""
|
83
|
-
if len(obj.description) > 50:
|
84
|
-
return f"{obj.description[:47]}..."
|
85
|
-
return obj.description
|
86
|
-
|
87
|
-
description_short.short_description = "Description"
|
88
|
-
|
89
|
-
def created_at_display(self, obj):
|
90
|
-
"""Created time with natural time."""
|
91
|
-
return naturaltime(obj.created_at)
|
92
|
-
|
93
|
-
created_at_display.short_description = "When"
|
94
|
-
|
95
|
-
def get_queryset(self, request):
|
96
|
-
return super().get_queryset(request).select_related("user")
|
@@ -1,17 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Group admin configuration.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from django.contrib import admin
|
6
|
-
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
|
7
|
-
from django.contrib.auth.models import Group
|
8
|
-
from unfold.admin import ModelAdmin
|
9
|
-
|
10
|
-
# Unregister default Group admin and re-register with Unfold
|
11
|
-
admin.site.unregister(Group)
|
12
|
-
|
13
|
-
|
14
|
-
@admin.register(Group)
|
15
|
-
class GroupAdmin(BaseGroupAdmin, ModelAdmin):
|
16
|
-
"""Enhanced Group admin with Unfold styling."""
|
17
|
-
pass
|
@@ -1,59 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
OTP admin configuration.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from django.contrib import admin
|
6
|
-
from django.contrib.humanize.templatetags.humanize import naturaltime
|
7
|
-
from unfold.admin import ModelAdmin
|
8
|
-
|
9
|
-
from ..models import OTPSecret
|
10
|
-
from .filters import OTPStatusFilter
|
11
|
-
|
12
|
-
|
13
|
-
@admin.register(OTPSecret)
|
14
|
-
class OTPSecretAdmin(ModelAdmin):
|
15
|
-
list_display = ["email", "secret", "status", "created", "expires"]
|
16
|
-
list_display_links = ["email", "secret"]
|
17
|
-
list_filter = [OTPStatusFilter, "is_used", "created_at"]
|
18
|
-
search_fields = ["email", "secret"]
|
19
|
-
readonly_fields = ["created_at", "expires_at"]
|
20
|
-
ordering = ["-created_at"]
|
21
|
-
|
22
|
-
fieldsets = (
|
23
|
-
(
|
24
|
-
"OTP Details",
|
25
|
-
{
|
26
|
-
"fields": ("email", "secret", "is_used"),
|
27
|
-
},
|
28
|
-
),
|
29
|
-
(
|
30
|
-
"Timestamps",
|
31
|
-
{
|
32
|
-
"fields": ("created_at", "expires_at"),
|
33
|
-
"classes": ("collapse",),
|
34
|
-
},
|
35
|
-
),
|
36
|
-
)
|
37
|
-
|
38
|
-
def status(self, obj):
|
39
|
-
"""Simple OTP status."""
|
40
|
-
if obj.is_used:
|
41
|
-
return "Used"
|
42
|
-
elif obj.is_valid:
|
43
|
-
return "✅ Valid"
|
44
|
-
else:
|
45
|
-
return "⏰ Expired"
|
46
|
-
|
47
|
-
status.short_description = "Status"
|
48
|
-
|
49
|
-
def created(self, obj):
|
50
|
-
"""Created time with natural time."""
|
51
|
-
return naturaltime(obj.created_at)
|
52
|
-
|
53
|
-
created.short_description = "Created"
|
54
|
-
|
55
|
-
def expires(self, obj):
|
56
|
-
"""Expires time with natural time."""
|
57
|
-
return naturaltime(obj.expires_at)
|
58
|
-
|
59
|
-
expires.short_description = "Expires"
|
@@ -1,97 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Registration Source admin configuration.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from django.contrib import admin
|
6
|
-
from django.contrib.humanize.templatetags.humanize import naturaltime
|
7
|
-
from unfold.admin import ModelAdmin
|
8
|
-
|
9
|
-
from ..models import RegistrationSource, UserRegistrationSource
|
10
|
-
from .filters import RegistrationSourceStatusFilter
|
11
|
-
from .inlines import RegistrationSourceInline
|
12
|
-
|
13
|
-
|
14
|
-
@admin.register(RegistrationSource)
|
15
|
-
class RegistrationSourceAdmin(ModelAdmin):
|
16
|
-
list_display = ["name", "url", "status", "users_count", "created"]
|
17
|
-
list_display_links = ["name", "url"]
|
18
|
-
list_filter = [RegistrationSourceStatusFilter, "is_active", "created_at"]
|
19
|
-
search_fields = ["name", "url", "description"]
|
20
|
-
readonly_fields = ["created_at", "updated_at"]
|
21
|
-
ordering = ["-created_at"]
|
22
|
-
inlines = [RegistrationSourceInline]
|
23
|
-
|
24
|
-
fieldsets = (
|
25
|
-
(
|
26
|
-
"Registration Source Information",
|
27
|
-
{
|
28
|
-
"fields": ("url", "name", "description", "is_active"),
|
29
|
-
},
|
30
|
-
),
|
31
|
-
(
|
32
|
-
"Timestamps",
|
33
|
-
{
|
34
|
-
"fields": ("created_at", "updated_at"),
|
35
|
-
"classes": ("collapse",),
|
36
|
-
},
|
37
|
-
),
|
38
|
-
)
|
39
|
-
|
40
|
-
def status(self, obj):
|
41
|
-
"""Registration source status display."""
|
42
|
-
if obj.is_active:
|
43
|
-
return "✅ Active"
|
44
|
-
else:
|
45
|
-
return "❌ Inactive"
|
46
|
-
|
47
|
-
status.short_description = "Status"
|
48
|
-
|
49
|
-
def users_count(self, obj):
|
50
|
-
"""Show count of users for this source."""
|
51
|
-
count = obj.user_registration_sources.count()
|
52
|
-
if count == 0:
|
53
|
-
return "—"
|
54
|
-
return f"{count} user{'s' if count != 1 else ''}"
|
55
|
-
|
56
|
-
users_count.short_description = "Users"
|
57
|
-
|
58
|
-
def created(self, obj):
|
59
|
-
"""Created time with natural time."""
|
60
|
-
return naturaltime(obj.created_at)
|
61
|
-
|
62
|
-
created.short_description = "Created"
|
63
|
-
|
64
|
-
|
65
|
-
@admin.register(UserRegistrationSource)
|
66
|
-
class UserRegistrationSourceAdmin(ModelAdmin):
|
67
|
-
list_display = ["user", "source", "first_registration", "registration_date"]
|
68
|
-
list_display_links = ["user", "source"]
|
69
|
-
list_filter = ["first_registration", "registration_date", "source__is_active"]
|
70
|
-
search_fields = [
|
71
|
-
"user__email",
|
72
|
-
"user__first_name",
|
73
|
-
"user__last_name",
|
74
|
-
"source__name",
|
75
|
-
"source__url",
|
76
|
-
]
|
77
|
-
readonly_fields = ["registration_date"]
|
78
|
-
ordering = ["-registration_date"]
|
79
|
-
|
80
|
-
fieldsets = (
|
81
|
-
(
|
82
|
-
"User Registration Source Relationship",
|
83
|
-
{
|
84
|
-
"fields": ("user", "source", "first_registration"),
|
85
|
-
},
|
86
|
-
),
|
87
|
-
(
|
88
|
-
"Timestamps",
|
89
|
-
{
|
90
|
-
"fields": ("registration_date",),
|
91
|
-
"classes": ("collapse",),
|
92
|
-
},
|
93
|
-
),
|
94
|
-
)
|
95
|
-
|
96
|
-
def get_queryset(self, request):
|
97
|
-
return super().get_queryset(request).select_related("user", "source")
|
@@ -1,227 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Twilio Response admin configuration.
|
3
|
-
"""
|
4
|
-
|
5
|
-
from django.contrib import admin
|
6
|
-
from django.contrib.humanize.templatetags.humanize import naturaltime
|
7
|
-
from django.utils.html import format_html
|
8
|
-
from unfold.admin import ModelAdmin
|
9
|
-
from django_cfg import ExportMixin, ExportForm
|
10
|
-
|
11
|
-
from ..models import TwilioResponse
|
12
|
-
from .filters import TwilioResponseStatusFilter, TwilioResponseTypeFilter
|
13
|
-
from .resources import TwilioResponseResource
|
14
|
-
|
15
|
-
|
16
|
-
class TwilioResponseInline(admin.TabularInline):
|
17
|
-
"""Inline for showing Twilio responses in related models."""
|
18
|
-
model = TwilioResponse
|
19
|
-
extra = 0
|
20
|
-
readonly_fields = ['created_at', 'status', 'message_sid', 'error_code']
|
21
|
-
fields = ['response_type', 'service_type', 'status', 'message_sid', 'error_code', 'created_at']
|
22
|
-
|
23
|
-
def has_add_permission(self, request, obj=None):
|
24
|
-
return False
|
25
|
-
|
26
|
-
|
27
|
-
@admin.register(TwilioResponse)
|
28
|
-
class TwilioResponseAdmin(ModelAdmin, ExportMixin):
|
29
|
-
# Export-only configuration
|
30
|
-
resource_class = TwilioResponseResource
|
31
|
-
export_form_class = ExportForm
|
32
|
-
list_display = [
|
33
|
-
'identifier',
|
34
|
-
'service_type',
|
35
|
-
'response_type',
|
36
|
-
'status_display',
|
37
|
-
'recipient',
|
38
|
-
'price_display',
|
39
|
-
'created_display',
|
40
|
-
'has_error_display'
|
41
|
-
]
|
42
|
-
list_display_links = ['identifier']
|
43
|
-
list_filter = [
|
44
|
-
TwilioResponseStatusFilter,
|
45
|
-
TwilioResponseTypeFilter,
|
46
|
-
'service_type',
|
47
|
-
'response_type',
|
48
|
-
'created_at',
|
49
|
-
]
|
50
|
-
search_fields = [
|
51
|
-
'message_sid',
|
52
|
-
'verification_sid',
|
53
|
-
'to_number',
|
54
|
-
'error_message',
|
55
|
-
'otp_secret__recipient'
|
56
|
-
]
|
57
|
-
readonly_fields = [
|
58
|
-
'created_at',
|
59
|
-
'updated_at',
|
60
|
-
'twilio_created_at',
|
61
|
-
'response_data_display',
|
62
|
-
'request_data_display'
|
63
|
-
]
|
64
|
-
ordering = ['-created_at']
|
65
|
-
|
66
|
-
fieldsets = (
|
67
|
-
(
|
68
|
-
'Basic Information',
|
69
|
-
{
|
70
|
-
'fields': (
|
71
|
-
'response_type',
|
72
|
-
'service_type',
|
73
|
-
'status',
|
74
|
-
'otp_secret'
|
75
|
-
),
|
76
|
-
},
|
77
|
-
),
|
78
|
-
(
|
79
|
-
'Twilio Identifiers',
|
80
|
-
{
|
81
|
-
'fields': (
|
82
|
-
'message_sid',
|
83
|
-
'verification_sid',
|
84
|
-
),
|
85
|
-
},
|
86
|
-
),
|
87
|
-
(
|
88
|
-
'Recipients',
|
89
|
-
{
|
90
|
-
'fields': (
|
91
|
-
'to_number',
|
92
|
-
'from_number',
|
93
|
-
),
|
94
|
-
},
|
95
|
-
),
|
96
|
-
(
|
97
|
-
'Error Information',
|
98
|
-
{
|
99
|
-
'fields': (
|
100
|
-
'error_code',
|
101
|
-
'error_message',
|
102
|
-
),
|
103
|
-
'classes': ('collapse',),
|
104
|
-
},
|
105
|
-
),
|
106
|
-
(
|
107
|
-
'Pricing',
|
108
|
-
{
|
109
|
-
'fields': (
|
110
|
-
'price',
|
111
|
-
'price_unit',
|
112
|
-
),
|
113
|
-
'classes': ('collapse',),
|
114
|
-
},
|
115
|
-
),
|
116
|
-
(
|
117
|
-
'Request/Response Data',
|
118
|
-
{
|
119
|
-
'fields': (
|
120
|
-
'request_data_display',
|
121
|
-
'response_data_display',
|
122
|
-
),
|
123
|
-
'classes': ('collapse',),
|
124
|
-
},
|
125
|
-
),
|
126
|
-
(
|
127
|
-
'Timestamps',
|
128
|
-
{
|
129
|
-
'fields': (
|
130
|
-
'created_at',
|
131
|
-
'updated_at',
|
132
|
-
'twilio_created_at',
|
133
|
-
),
|
134
|
-
'classes': ('collapse',),
|
135
|
-
},
|
136
|
-
),
|
137
|
-
)
|
138
|
-
|
139
|
-
def identifier(self, obj):
|
140
|
-
"""Get the main identifier for the response."""
|
141
|
-
return obj.message_sid or obj.verification_sid or '—'
|
142
|
-
identifier.short_description = 'Identifier'
|
143
|
-
|
144
|
-
def status_display(self, obj):
|
145
|
-
"""Display status with color coding."""
|
146
|
-
if obj.has_error:
|
147
|
-
return format_html(
|
148
|
-
'<span style="color: #dc3545;">❌ {}</span>',
|
149
|
-
obj.status or 'Error'
|
150
|
-
)
|
151
|
-
elif obj.is_successful:
|
152
|
-
return format_html(
|
153
|
-
'<span style="color: #28a745;">✅ {}</span>',
|
154
|
-
obj.status or 'Success'
|
155
|
-
)
|
156
|
-
else:
|
157
|
-
return format_html(
|
158
|
-
'<span style="color: #ffc107;">⏳ {}</span>',
|
159
|
-
obj.status or 'Unknown'
|
160
|
-
)
|
161
|
-
status_display.short_description = 'Status'
|
162
|
-
|
163
|
-
def recipient(self, obj):
|
164
|
-
"""Display recipient with masking for privacy."""
|
165
|
-
if not obj.to_number:
|
166
|
-
return '—'
|
167
|
-
|
168
|
-
# Mask phone numbers and emails for privacy
|
169
|
-
recipient = obj.to_number
|
170
|
-
if '@' in recipient:
|
171
|
-
# Email masking
|
172
|
-
local, domain = recipient.split('@', 1)
|
173
|
-
masked_local = local[:2] + '*' * (len(local) - 2)
|
174
|
-
return f"{masked_local}@{domain}"
|
175
|
-
else:
|
176
|
-
# Phone masking
|
177
|
-
return f"***{recipient[-4:]}" if len(recipient) > 4 else "***"
|
178
|
-
recipient.short_description = 'Recipient'
|
179
|
-
|
180
|
-
def price_display(self, obj):
|
181
|
-
"""Display price with currency."""
|
182
|
-
if obj.price and obj.price_unit:
|
183
|
-
return f"{obj.price} {obj.price_unit.upper()}"
|
184
|
-
return '—'
|
185
|
-
price_display.short_description = 'Price'
|
186
|
-
|
187
|
-
def created_display(self, obj):
|
188
|
-
"""Display created time with natural time."""
|
189
|
-
return naturaltime(obj.created_at)
|
190
|
-
created_display.short_description = 'Created'
|
191
|
-
|
192
|
-
def has_error_display(self, obj):
|
193
|
-
"""Display error status."""
|
194
|
-
if obj.has_error:
|
195
|
-
return format_html('<span style="color: #dc3545;">❌</span>')
|
196
|
-
return format_html('<span style="color: #28a745;">✅</span>')
|
197
|
-
has_error_display.short_description = 'Error'
|
198
|
-
|
199
|
-
def request_data_display(self, obj):
|
200
|
-
"""Display formatted request data."""
|
201
|
-
if not obj.request_data:
|
202
|
-
return '—'
|
203
|
-
|
204
|
-
import json
|
205
|
-
try:
|
206
|
-
formatted = json.dumps(obj.request_data, indent=2, ensure_ascii=False)
|
207
|
-
return format_html('<pre style="font-size: 12px;">{}</pre>', formatted)
|
208
|
-
except (TypeError, ValueError):
|
209
|
-
return str(obj.request_data)
|
210
|
-
request_data_display.short_description = 'Request Data'
|
211
|
-
|
212
|
-
def response_data_display(self, obj):
|
213
|
-
"""Display formatted response data."""
|
214
|
-
if not obj.response_data:
|
215
|
-
return '—'
|
216
|
-
|
217
|
-
import json
|
218
|
-
try:
|
219
|
-
formatted = json.dumps(obj.response_data, indent=2, ensure_ascii=False)
|
220
|
-
return format_html('<pre style="font-size: 12px;">{}</pre>', formatted)
|
221
|
-
except (TypeError, ValueError):
|
222
|
-
return str(obj.response_data)
|
223
|
-
response_data_display.short_description = 'Response Data'
|
224
|
-
|
225
|
-
def get_queryset(self, request):
|
226
|
-
"""Optimize queryset with select_related."""
|
227
|
-
return super().get_queryset(request).select_related('otp_secret')
|