django-cfg 1.4.20__py3-none-any.whl → 1.4.23__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 +4 -4
- django_cfg/apps/accounts/__init__.py +1 -1
- django_cfg/apps/accounts/__models.py +30 -29
- django_cfg/apps/accounts/admin/__init__.py +14 -3
- django_cfg/apps/accounts/admin/activity_admin.py +19 -19
- django_cfg/apps/accounts/admin/filters.py +7 -6
- django_cfg/apps/accounts/admin/group_admin.py +10 -16
- django_cfg/apps/accounts/admin/inlines.py +21 -19
- django_cfg/apps/accounts/admin/otp_admin.py +12 -12
- django_cfg/apps/accounts/admin/registration_admin.py +24 -24
- django_cfg/apps/accounts/admin/resources.py +49 -48
- django_cfg/apps/accounts/admin/twilio_admin.py +37 -37
- django_cfg/apps/accounts/admin/user_admin.py +45 -41
- django_cfg/apps/accounts/management/commands/otp_test.py +11 -11
- django_cfg/apps/accounts/managers/__init__.py +1 -1
- django_cfg/apps/accounts/managers/user_manager.py +6 -7
- django_cfg/apps/accounts/migrations/0001_initial.py +3 -2
- django_cfg/apps/accounts/models/__init__.py +15 -16
- django_cfg/apps/accounts/models/activity.py +5 -5
- django_cfg/apps/accounts/models/integrations.py +15 -15
- django_cfg/apps/accounts/models/registration.py +3 -2
- django_cfg/apps/accounts/models/user.py +3 -2
- django_cfg/apps/accounts/serializers/__init__.py +10 -3
- django_cfg/apps/accounts/serializers/otp.py +5 -4
- django_cfg/apps/accounts/serializers/profile.py +4 -5
- django_cfg/apps/accounts/serializers/webhook.py +13 -13
- django_cfg/apps/accounts/services/activity_service.py +13 -12
- django_cfg/apps/accounts/services/otp_service.py +16 -14
- django_cfg/apps/accounts/signals.py +18 -16
- django_cfg/apps/accounts/urls.py +10 -5
- django_cfg/apps/accounts/utils/notifications.py +22 -22
- django_cfg/apps/accounts/views/__init__.py +1 -1
- django_cfg/apps/accounts/views/otp.py +15 -14
- django_cfg/apps/accounts/views/profile.py +14 -10
- django_cfg/apps/accounts/views/webhook.py +46 -48
- django_cfg/apps/agents/__init__.py +3 -3
- django_cfg/apps/agents/admin/__init__.py +1 -1
- django_cfg/apps/agents/admin/execution_admin.py +68 -72
- django_cfg/apps/agents/admin/registry_admin.py +50 -54
- django_cfg/apps/agents/admin/toolsets_admin.py +63 -67
- django_cfg/apps/agents/apps.py +3 -3
- django_cfg/apps/agents/core/__init__.py +4 -4
- django_cfg/apps/agents/core/dependencies.py +24 -23
- django_cfg/apps/agents/core/django_agent.py +41 -39
- django_cfg/apps/agents/core/exceptions.py +12 -12
- django_cfg/apps/agents/core/models.py +16 -15
- django_cfg/apps/agents/core/orchestrator.py +58 -58
- django_cfg/apps/agents/examples/simple_example.py +24 -19
- django_cfg/apps/agents/integration/__init__.py +1 -1
- django_cfg/apps/agents/integration/middleware.py +12 -11
- django_cfg/apps/agents/integration/registry.py +52 -49
- django_cfg/apps/agents/integration/signals.py +5 -5
- django_cfg/apps/agents/management/commands/create_agent.py +39 -38
- django_cfg/apps/agents/management/commands/orchestrator_status.py +40 -39
- django_cfg/apps/agents/managers/__init__.py +8 -3
- django_cfg/apps/agents/managers/execution.py +42 -41
- django_cfg/apps/agents/managers/registry.py +40 -39
- django_cfg/apps/agents/managers/toolsets.py +87 -86
- django_cfg/apps/agents/migrations/0001_initial.py +2 -1
- django_cfg/apps/agents/models/__init__.py +2 -2
- django_cfg/apps/agents/models/execution.py +43 -42
- django_cfg/apps/agents/models/registry.py +46 -45
- django_cfg/apps/agents/models/toolsets.py +63 -62
- django_cfg/apps/agents/patterns/__init__.py +5 -5
- django_cfg/apps/agents/patterns/content_agents.py +17 -16
- django_cfg/apps/agents/toolsets/__init__.py +3 -3
- django_cfg/apps/agents/toolsets/cache_toolset.py +56 -55
- django_cfg/apps/agents/toolsets/django_toolset.py +43 -42
- django_cfg/apps/agents/toolsets/file_toolset.py +64 -63
- django_cfg/apps/agents/toolsets/orm_toolset.py +75 -74
- django_cfg/apps/agents/urls.py +3 -2
- django_cfg/apps/api/commands/urls.py +1 -0
- django_cfg/apps/api/commands/views.py +23 -26
- django_cfg/apps/api/endpoints/checker.py +5 -4
- django_cfg/apps/api/endpoints/drf_views.py +2 -2
- django_cfg/apps/api/endpoints/tests.py +6 -5
- django_cfg/apps/api/endpoints/urls.py +2 -1
- django_cfg/apps/api/endpoints/views.py +1 -0
- django_cfg/apps/api/health/drf_views.py +6 -6
- django_cfg/apps/api/health/urls.py +2 -1
- django_cfg/apps/api/health/views.py +41 -41
- django_cfg/{modules/django_ipc_client → apps/ipc}/__init__.py +6 -6
- django_cfg/apps/ipc/apps.py +28 -0
- django_cfg/apps/ipc/serializers/__init__.py +19 -0
- django_cfg/apps/ipc/serializers/serializers.py +229 -0
- django_cfg/apps/ipc/services/__init__.py +7 -0
- django_cfg/apps/ipc/services/client/__init__.py +23 -0
- django_cfg/{modules/django_ipc_client → apps/ipc/services/client}/client.py +7 -6
- django_cfg/{modules/django_ipc_client → apps/ipc/services/client}/exceptions.py +1 -1
- django_cfg/{modules/django_ipc_client/dashboard → apps/ipc/services}/monitor.py +23 -5
- django_cfg/{modules/django_ipc_client/dashboard/static/django_ipc_dashboard/js/dashboard.js → apps/ipc/static/django_cfg_ipc/js/dashboard.mjs} +131 -63
- django_cfg/{modules/django_ipc_client/dashboard/templates/django_ipc_dashboard → apps/ipc/templates/django_cfg_ipc}/base.html +5 -10
- django_cfg/apps/ipc/templates/django_cfg_ipc/dashboard.html +202 -0
- django_cfg/apps/ipc/urls.py +21 -0
- django_cfg/apps/ipc/urls_admin.py +20 -0
- django_cfg/apps/ipc/views/__init__.py +8 -0
- django_cfg/apps/ipc/views/dashboard.py +15 -0
- django_cfg/apps/ipc/views/viewsets.py +245 -0
- django_cfg/apps/knowbase/admin/__init__.py +2 -2
- django_cfg/apps/knowbase/admin/actions/__init__.py +1 -1
- django_cfg/apps/knowbase/admin/actions/visibility_actions.py +2 -1
- django_cfg/apps/knowbase/admin/archive_admin.py +81 -84
- django_cfg/apps/knowbase/admin/chat_admin.py +70 -72
- django_cfg/apps/knowbase/admin/document_admin.py +10 -11
- django_cfg/apps/knowbase/admin/external_data_admin.py +69 -71
- django_cfg/apps/knowbase/admin/helpers/__init__.py +1 -1
- django_cfg/apps/knowbase/admin/helpers/configs.py +2 -2
- django_cfg/apps/knowbase/admin/helpers/statistics.py +1 -1
- django_cfg/apps/knowbase/apps.py +13 -13
- django_cfg/apps/knowbase/config/__init__.py +7 -6
- django_cfg/apps/knowbase/config/constance_fields.py +14 -12
- django_cfg/apps/knowbase/config/constance_settings.py +32 -31
- django_cfg/apps/knowbase/config/settings.py +28 -28
- django_cfg/apps/knowbase/examples/external_data_usage.py +35 -32
- django_cfg/apps/knowbase/management/commands/knowbase_stats.py +33 -32
- django_cfg/apps/knowbase/management/commands/setup_knowbase.py +11 -13
- django_cfg/apps/knowbase/managers/__init__.py +2 -2
- django_cfg/apps/knowbase/managers/archive.py +86 -85
- django_cfg/apps/knowbase/managers/base.py +5 -5
- django_cfg/apps/knowbase/managers/chat.py +29 -28
- django_cfg/apps/knowbase/managers/document.py +39 -39
- django_cfg/apps/knowbase/managers/external_data.py +74 -73
- django_cfg/apps/knowbase/migrations/0001_initial.py +2 -1
- django_cfg/apps/knowbase/migrations/0002_archiveitem_archiveitemchunk_documentarchive_and_more.py +2 -1
- django_cfg/apps/knowbase/migrations/0003_alter_documentarchive_archive_type.py +29 -0
- django_cfg/apps/knowbase/mixins/__init__.py +4 -4
- django_cfg/apps/knowbase/mixins/config/__init__.py +1 -1
- django_cfg/apps/knowbase/mixins/config/meta_config.py +1 -1
- django_cfg/apps/knowbase/mixins/config.py +19 -18
- django_cfg/apps/knowbase/mixins/creator.py +7 -7
- django_cfg/apps/knowbase/mixins/examples/vehicle_model_example.py +29 -28
- django_cfg/apps/knowbase/mixins/external_data_mixin.py +6 -5
- django_cfg/apps/knowbase/mixins/generators/__init__.py +1 -1
- django_cfg/apps/knowbase/mixins/generators/content_generator.py +2 -2
- django_cfg/apps/knowbase/mixins/service.py +47 -45
- django_cfg/apps/knowbase/models/__init__.py +7 -7
- django_cfg/apps/knowbase/models/archive.py +72 -72
- django_cfg/apps/knowbase/models/base.py +12 -13
- django_cfg/apps/knowbase/models/chat.py +20 -19
- django_cfg/apps/knowbase/models/document.py +37 -35
- django_cfg/apps/knowbase/models/external_data.py +41 -42
- django_cfg/apps/knowbase/serializers/__init__.py +7 -7
- django_cfg/apps/knowbase/serializers/archive_serializers.py +50 -42
- django_cfg/apps/knowbase/serializers/chat_serializers.py +16 -15
- django_cfg/apps/knowbase/serializers/document_serializers.py +13 -12
- django_cfg/apps/knowbase/serializers/external_data_serializers.py +31 -31
- django_cfg/apps/knowbase/serializers/public_serializers.py +10 -9
- django_cfg/apps/knowbase/services/__init__.py +7 -7
- django_cfg/apps/knowbase/services/archive/__init__.py +7 -7
- django_cfg/apps/knowbase/services/archive/analyzers/__init__.py +1 -1
- django_cfg/apps/knowbase/services/archive/analyzers/tag_generator.py +1 -1
- django_cfg/apps/knowbase/services/archive/archive_service.py +109 -112
- django_cfg/apps/knowbase/services/archive/chunking/__init__.py +3 -3
- django_cfg/apps/knowbase/services/archive/chunking/base.py +1 -0
- django_cfg/apps/knowbase/services/archive/chunking/json_chunker.py +4 -3
- django_cfg/apps/knowbase/services/archive/chunking/markdown_chunker.py +5 -4
- django_cfg/apps/knowbase/services/archive/chunking/python_chunker.py +6 -5
- django_cfg/apps/knowbase/services/archive/chunking/text_chunker.py +4 -3
- django_cfg/apps/knowbase/services/archive/chunking_service.py +3 -7
- django_cfg/apps/knowbase/services/archive/context/__init__.py +1 -1
- django_cfg/apps/knowbase/services/archive/context/builders.py +2 -1
- django_cfg/apps/knowbase/services/archive/context/models.py +2 -1
- django_cfg/apps/knowbase/services/archive/exceptions.py +5 -5
- django_cfg/apps/knowbase/services/archive/extraction_service.py +111 -110
- django_cfg/apps/knowbase/services/archive/vectorization_service.py +80 -77
- django_cfg/apps/knowbase/services/base.py +11 -9
- django_cfg/apps/knowbase/services/chat_service.py +40 -39
- django_cfg/apps/knowbase/services/document_service.py +28 -27
- django_cfg/apps/knowbase/services/embedding/__init__.py +9 -9
- django_cfg/apps/knowbase/services/embedding/async_processor.py +38 -40
- django_cfg/apps/knowbase/services/embedding/batch_processor.py +45 -42
- django_cfg/apps/knowbase/services/embedding/batch_result.py +7 -6
- django_cfg/apps/knowbase/services/embedding/models.py +52 -51
- django_cfg/apps/knowbase/services/embedding/processors.py +24 -23
- django_cfg/apps/knowbase/services/embedding/utils.py +17 -17
- django_cfg/apps/knowbase/services/prompt_builder.py +24 -23
- django_cfg/apps/knowbase/services/search_service.py +52 -49
- django_cfg/apps/knowbase/signals/__init__.py +2 -5
- django_cfg/apps/knowbase/signals/archive_signals.py +35 -34
- django_cfg/apps/knowbase/signals/chat_signals.py +6 -5
- django_cfg/apps/knowbase/signals/document_signals.py +22 -22
- django_cfg/apps/knowbase/signals/external_data_signals.py +22 -22
- django_cfg/apps/knowbase/tasks/__init__.py +6 -7
- django_cfg/apps/knowbase/tasks/archive_tasks.py +41 -41
- django_cfg/apps/knowbase/tasks/document_processing.py +49 -44
- django_cfg/apps/knowbase/tasks/external_data_tasks.py +46 -44
- django_cfg/apps/knowbase/tasks/maintenance.py +26 -24
- django_cfg/apps/knowbase/urls.py +3 -2
- django_cfg/apps/knowbase/urls_admin.py +6 -3
- django_cfg/apps/knowbase/urls_system.py +4 -5
- django_cfg/apps/knowbase/utils/chunk_settings.py +22 -20
- django_cfg/apps/knowbase/utils/text_processing.py +76 -75
- django_cfg/apps/knowbase/utils/validation.py +9 -9
- django_cfg/apps/knowbase/views/__init__.py +5 -5
- django_cfg/apps/knowbase/views/archive_views.py +90 -87
- django_cfg/apps/knowbase/views/base.py +9 -12
- django_cfg/apps/knowbase/views/chat_views.py +35 -32
- django_cfg/apps/knowbase/views/document_views.py +27 -28
- django_cfg/apps/knowbase/views/public_views.py +19 -19
- django_cfg/apps/leads/admin/leads_admin.py +41 -45
- django_cfg/apps/leads/admin/resources.py +14 -14
- django_cfg/apps/leads/admin.py +7 -9
- django_cfg/apps/leads/apps.py +1 -1
- django_cfg/apps/leads/models.py +17 -17
- django_cfg/apps/leads/serializers.py +5 -4
- django_cfg/apps/leads/signals.py +7 -7
- django_cfg/apps/leads/tests.py +47 -47
- django_cfg/apps/leads/urls.py +2 -2
- django_cfg/apps/leads/views.py +11 -11
- django_cfg/apps/maintenance/__init__.py +3 -3
- django_cfg/apps/maintenance/admin/__init__.py +1 -1
- django_cfg/apps/maintenance/admin/api_key_admin.py +36 -36
- django_cfg/apps/maintenance/admin/log_admin.py +35 -37
- django_cfg/apps/maintenance/admin/scheduled_admin.py +47 -51
- django_cfg/apps/maintenance/admin/site_admin.py +49 -52
- django_cfg/apps/maintenance/apps.py +2 -2
- django_cfg/apps/maintenance/management/commands/maintenance.py +53 -52
- django_cfg/apps/maintenance/management/commands/process_scheduled_maintenance.py +44 -44
- django_cfg/apps/maintenance/management/commands/sync_cloudflare.py +32 -32
- django_cfg/apps/maintenance/managers/__init__.py +1 -1
- django_cfg/apps/maintenance/managers/cloudflare_site_manager.py +39 -38
- django_cfg/apps/maintenance/managers/maintenance_log_manager.py +32 -31
- django_cfg/apps/maintenance/migrations/0001_initial.py +1 -0
- django_cfg/apps/maintenance/models/__init__.py +2 -2
- django_cfg/apps/maintenance/models/cloudflare_api_key.py +15 -15
- django_cfg/apps/maintenance/models/cloudflare_site.py +24 -22
- django_cfg/apps/maintenance/models/maintenance_log.py +15 -14
- django_cfg/apps/maintenance/models/scheduled_maintenance.py +53 -52
- django_cfg/apps/maintenance/services/__init__.py +3 -3
- django_cfg/apps/maintenance/services/bulk_operations_service.py +68 -68
- django_cfg/apps/maintenance/services/maintenance_service.py +59 -58
- django_cfg/apps/maintenance/services/scheduled_maintenance_service.py +52 -52
- django_cfg/apps/maintenance/services/site_sync_service.py +64 -65
- django_cfg/apps/maintenance/utils/__init__.py +1 -1
- django_cfg/apps/maintenance/utils/retry_utils.py +17 -17
- django_cfg/apps/newsletter/admin/__init__.py +12 -16
- django_cfg/apps/newsletter/admin/newsletter_admin.py +90 -87
- django_cfg/apps/newsletter/admin/resources.py +29 -29
- django_cfg/apps/newsletter/admin.py +39 -32
- django_cfg/apps/newsletter/management/commands/test_newsletter.py +3 -3
- django_cfg/apps/newsletter/managers/__init__.py +1 -1
- django_cfg/apps/newsletter/migrations/0001_initial.py +2 -1
- django_cfg/apps/newsletter/models.py +34 -33
- django_cfg/apps/newsletter/serializers.py +13 -13
- django_cfg/apps/newsletter/services/email_service.py +42 -40
- django_cfg/apps/newsletter/signals.py +4 -3
- django_cfg/apps/newsletter/urls.py +7 -7
- django_cfg/apps/newsletter/views/__init__.py +14 -19
- django_cfg/apps/newsletter/views/campaigns.py +19 -19
- django_cfg/apps/newsletter/views/emails.py +20 -20
- django_cfg/apps/newsletter/views/newsletters.py +5 -5
- django_cfg/apps/newsletter/views/subscriptions.py +24 -24
- django_cfg/apps/newsletter/views/tracking.py +6 -5
- django_cfg/apps/payments/admin/__init__.py +6 -5
- django_cfg/apps/payments/admin/api_keys_admin.py +43 -45
- django_cfg/apps/payments/admin/balance_admin.py +41 -47
- django_cfg/apps/payments/admin/currencies_admin.py +60 -62
- django_cfg/apps/payments/admin/endpoint_groups_admin.py +14 -28
- django_cfg/apps/payments/admin/filters.py +59 -59
- django_cfg/apps/payments/admin/networks_admin.py +36 -50
- django_cfg/apps/payments/admin/payments_admin.py +47 -49
- django_cfg/apps/payments/admin/subscriptions_admin.py +30 -32
- django_cfg/apps/payments/admin/tariffs_admin.py +37 -42
- django_cfg/apps/payments/admin_interface/serializers/__init__.py +12 -13
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +28 -27
- django_cfg/apps/payments/admin_interface/serializers/webhook_serializers.py +4 -5
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +407 -3
- django_cfg/apps/payments/admin_interface/templates/payments/components/ngrok_status.html +13 -13
- django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +5 -1
- django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +105 -49
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +4 -1
- django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +16 -8
- django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +16 -8
- django_cfg/apps/payments/admin_interface/views/__init__.py +8 -9
- django_cfg/apps/payments/admin_interface/views/api/__init__.py +3 -3
- django_cfg/apps/payments/admin_interface/views/api/payments.py +52 -54
- django_cfg/apps/payments/admin_interface/views/api/stats.py +33 -30
- django_cfg/apps/payments/admin_interface/views/api/users.py +10 -11
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +46 -51
- django_cfg/apps/payments/admin_interface/views/api/webhook_public.py +9 -9
- django_cfg/apps/payments/admin_interface/views/base.py +17 -19
- django_cfg/apps/payments/admin_interface/views/dashboard.py +10 -10
- django_cfg/apps/payments/admin_interface/views/forms.py +21 -20
- django_cfg/apps/payments/apps.py +7 -6
- django_cfg/apps/payments/config/__init__.py +4 -4
- django_cfg/apps/payments/config/django_cfg_integration.py +22 -21
- django_cfg/apps/payments/config/helpers.py +14 -12
- django_cfg/apps/payments/management/commands/cleanup_expired_data.py +85 -86
- django_cfg/apps/payments/management/commands/currency_stats.py +84 -87
- django_cfg/apps/payments/management/commands/manage_currencies.py +59 -58
- django_cfg/apps/payments/management/commands/manage_providers.py +103 -105
- django_cfg/apps/payments/management/commands/process_pending_payments.py +67 -70
- django_cfg/apps/payments/management/commands/test_providers.py +83 -84
- django_cfg/apps/payments/middleware/__init__.py +1 -1
- django_cfg/apps/payments/middleware/api_access.py +77 -78
- django_cfg/apps/payments/middleware/rate_limiting.py +72 -72
- django_cfg/apps/payments/middleware/usage_tracking.py +66 -64
- django_cfg/apps/payments/migrations/0001_initial.py +2 -1
- django_cfg/apps/payments/models/__init__.py +11 -12
- django_cfg/apps/payments/models/api_keys.py +29 -27
- django_cfg/apps/payments/models/balance.py +38 -38
- django_cfg/apps/payments/models/base.py +12 -11
- django_cfg/apps/payments/models/currencies.py +53 -52
- django_cfg/apps/payments/models/managers/__init__.py +13 -14
- django_cfg/apps/payments/models/managers/api_key_managers.py +55 -53
- django_cfg/apps/payments/models/managers/balance_managers.py +98 -97
- django_cfg/apps/payments/models/managers/currency_managers.py +70 -69
- django_cfg/apps/payments/models/managers/payment_managers.py +113 -111
- django_cfg/apps/payments/models/managers/subscription_managers.py +99 -97
- django_cfg/apps/payments/models/payments.py +167 -73
- django_cfg/apps/payments/models/subscriptions.py +56 -54
- django_cfg/apps/payments/models/tariffs.py +35 -34
- django_cfg/apps/payments/services/__init__.py +33 -36
- django_cfg/apps/payments/services/cache/__init__.py +7 -1
- django_cfg/apps/payments/services/cache_service/__init__.py +22 -20
- django_cfg/apps/payments/services/cache_service/api_key_cache.py +6 -5
- django_cfg/apps/payments/services/cache_service/interfaces.py +5 -5
- django_cfg/apps/payments/services/cache_service/keys.py +8 -8
- django_cfg/apps/payments/services/cache_service/rate_limit_cache.py +8 -7
- django_cfg/apps/payments/services/cache_service/simple_cache.py +17 -14
- django_cfg/apps/payments/services/core/__init__.py +3 -3
- django_cfg/apps/payments/services/core/balance_service.py +69 -65
- django_cfg/apps/payments/services/core/base.py +25 -22
- django_cfg/apps/payments/services/core/currency/__init__.py +1 -1
- django_cfg/apps/payments/services/core/currency/currency_converter.py +2 -0
- django_cfg/apps/payments/services/core/currency_service.py +68 -66
- django_cfg/apps/payments/services/core/operations/__init__.py +1 -1
- django_cfg/apps/payments/services/core/operations/payment_canceller.py +2 -1
- django_cfg/apps/payments/services/core/operations/payment_creator.py +2 -1
- django_cfg/apps/payments/services/core/operations/status_checker.py +2 -1
- django_cfg/apps/payments/services/core/payment_service.py +10 -7
- django_cfg/apps/payments/services/core/providers/provider_client.py +2 -2
- django_cfg/apps/payments/services/core/subscription_service.py +77 -74
- django_cfg/apps/payments/services/core/utils/data_converter.py +1 -0
- django_cfg/apps/payments/services/core/utils/statistics_calculator.py +1 -0
- django_cfg/apps/payments/services/core/webhook_service.py +67 -63
- django_cfg/apps/payments/services/integrations/__init__.py +3 -3
- django_cfg/apps/payments/services/integrations/ngrok_service.py +1 -0
- django_cfg/apps/payments/services/integrations/providers_config.py +3 -2
- django_cfg/apps/payments/services/providers/base.py +59 -57
- django_cfg/apps/payments/services/providers/models/__init__.py +7 -14
- django_cfg/apps/payments/services/providers/models/base.py +15 -15
- django_cfg/apps/payments/services/providers/models/providers.py +13 -12
- django_cfg/apps/payments/services/providers/models/universal.py +6 -5
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +4 -4
- django_cfg/apps/payments/services/providers/nowpayments/config.py +9 -8
- django_cfg/apps/payments/services/providers/nowpayments/models.py +15 -15
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/__init__.py +2 -2
- django_cfg/apps/payments/services/providers/nowpayments/parsers/data/patterns.py +26 -26
- django_cfg/apps/payments/services/providers/nowpayments/parsers/parser.py +3 -2
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +95 -99
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +41 -40
- django_cfg/apps/payments/services/providers/registry.py +65 -63
- django_cfg/apps/payments/services/providers/sync_service.py +50 -50
- django_cfg/apps/payments/services/types/__init__.py +21 -22
- django_cfg/apps/payments/services/types/data.py +14 -13
- django_cfg/apps/payments/services/types/requests.py +21 -22
- django_cfg/apps/payments/services/types/responses.py +16 -15
- django_cfg/apps/payments/services/types/webhooks.py +30 -30
- django_cfg/apps/payments/signals/__init__.py +4 -6
- django_cfg/apps/payments/signals/api_key_signals.py +36 -35
- django_cfg/apps/payments/signals/balance_signals.py +28 -26
- django_cfg/apps/payments/signals/payment_signals.py +29 -28
- django_cfg/apps/payments/signals/subscription_signals.py +39 -38
- django_cfg/apps/payments/static/payments/js/ngrok-status.js +12 -8
- django_cfg/apps/payments/static/payments/js/payment-detail.js +1 -1
- django_cfg/apps/payments/static/payments/js/payment-form.js +3 -3
- django_cfg/apps/payments/static/payments/js/payment-list.js +13 -6
- django_cfg/apps/payments/static/payments/js/webhook-dashboard-mjs.js +241 -0
- django_cfg/apps/payments/tasks/__init__.py +11 -12
- django_cfg/apps/payments/tasks/types.py +10 -9
- django_cfg/apps/payments/tasks/usage_tracking.py +44 -46
- django_cfg/apps/payments/templatetags/payment_tags.py +27 -27
- django_cfg/apps/payments/urls.py +31 -14
- django_cfg/apps/payments/urls_admin.py +10 -10
- django_cfg/apps/payments/views/api/__init__.py +32 -33
- django_cfg/apps/payments/views/api/api_keys.py +62 -62
- django_cfg/apps/payments/views/api/balances.py +63 -64
- django_cfg/apps/payments/views/api/base.py +52 -52
- django_cfg/apps/payments/views/api/currencies.py +75 -63
- django_cfg/apps/payments/views/api/payments.py +73 -74
- django_cfg/apps/payments/views/api/subscriptions.py +71 -72
- django_cfg/apps/payments/views/api/webhooks.py +85 -84
- django_cfg/apps/payments/views/overview/__init__.py +7 -7
- django_cfg/apps/payments/views/overview/serializers.py +13 -14
- django_cfg/apps/payments/views/overview/services.py +66 -67
- django_cfg/apps/payments/views/overview/urls.py +2 -1
- django_cfg/apps/payments/views/overview/views.py +31 -31
- django_cfg/apps/payments/views/serializers/__init__.py +35 -36
- django_cfg/apps/payments/views/serializers/api_keys.py +59 -57
- django_cfg/apps/payments/views/serializers/balances.py +34 -33
- django_cfg/apps/payments/views/serializers/currencies.py +36 -34
- django_cfg/apps/payments/views/serializers/payments.py +48 -47
- django_cfg/apps/payments/views/serializers/subscriptions.py +50 -45
- django_cfg/apps/payments/views/serializers/webhooks.py +17 -16
- django_cfg/apps/support/admin/__init__.py +3 -3
- django_cfg/apps/support/admin/resources.py +26 -26
- django_cfg/apps/support/admin/support_admin.py +44 -48
- django_cfg/apps/support/admin.py +16 -15
- django_cfg/apps/support/apps.py +1 -1
- django_cfg/apps/support/managers/message_manager.py +4 -4
- django_cfg/apps/support/managers/ticket_manager.py +13 -12
- django_cfg/apps/support/migrations/0001_initial.py +2 -1
- django_cfg/apps/support/models.py +3 -1
- django_cfg/apps/support/serializers.py +4 -2
- django_cfg/apps/support/signals.py +12 -10
- django_cfg/apps/support/urls.py +4 -3
- django_cfg/apps/support/utils/support_email_service.py +11 -9
- django_cfg/apps/support/views/__init__.py +3 -3
- django_cfg/apps/support/views/admin.py +9 -9
- django_cfg/apps/support/views/api.py +12 -13
- django_cfg/apps/support/views/chat.py +14 -14
- django_cfg/apps/tasks/admin/tasks_admin.py +65 -74
- django_cfg/apps/tasks/apps.py +2 -2
- django_cfg/apps/tasks/serializers.py +6 -6
- django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +44 -20
- django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +7 -5
- django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +5 -3
- django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +5 -3
- django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +5 -3
- django_cfg/apps/tasks/tasks/demo_tasks.py +12 -11
- django_cfg/apps/tasks/templates/tasks/components/tasks_mjs_integration.html +269 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard-improved.html +168 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +21 -2
- django_cfg/apps/tasks/urls.py +3 -2
- django_cfg/apps/tasks/urls_admin.py +1 -0
- django_cfg/apps/tasks/utils/simulator.py +49 -52
- django_cfg/apps/tasks/views/api.py +75 -73
- django_cfg/apps/tasks/views/dashboard.py +5 -4
- django_cfg/apps/urls.py +20 -11
- django_cfg/apps.py +6 -5
- django_cfg/cli/commands/create_project.py +7 -6
- django_cfg/cli/commands/info.py +25 -25
- django_cfg/cli/utils.py +27 -27
- django_cfg/config.py +1 -1
- django_cfg/core/__init__.py +8 -8
- django_cfg/core/base/config_model.py +13 -12
- django_cfg/core/builders/apps_builder.py +2 -2
- django_cfg/core/builders/middleware_builder.py +1 -1
- django_cfg/core/builders/security_builder.py +1 -1
- django_cfg/core/config.py +2 -2
- django_cfg/core/environment/detector.py +27 -28
- django_cfg/core/exceptions.py +1 -1
- django_cfg/core/generation/core_generators/settings.py +1 -1
- django_cfg/core/generation/core_generators/static.py +11 -5
- django_cfg/core/generation/core_generators/templates.py +1 -1
- django_cfg/core/generation/data_generators/__init__.py +1 -1
- django_cfg/core/generation/data_generators/cache.py +1 -1
- django_cfg/core/generation/data_generators/database.py +1 -1
- django_cfg/core/generation/generation.py +1 -3
- django_cfg/core/generation/integration_generators/__init__.py +2 -2
- django_cfg/core/generation/integration_generators/api.py +12 -2
- django_cfg/core/generation/integration_generators/sessions.py +1 -1
- django_cfg/core/generation/integration_generators/tailwind.py +1 -1
- django_cfg/core/generation/integration_generators/tasks.py +1 -1
- django_cfg/core/generation/integration_generators/third_party.py +1 -1
- django_cfg/core/generation/orchestrator.py +1 -1
- django_cfg/core/generation/protocols.py +1 -1
- django_cfg/core/generation/utility_generators/__init__.py +1 -1
- django_cfg/core/generation/utility_generators/email.py +1 -1
- django_cfg/core/generation/utility_generators/i18n.py +1 -1
- django_cfg/core/generation/utility_generators/limits.py +1 -1
- django_cfg/core/generation/utility_generators/logging.py +1 -1
- django_cfg/core/generation/utility_generators/security.py +1 -1
- django_cfg/core/generation/utils/helpers.py +1 -1
- django_cfg/core/integration/__init__.py +5 -5
- django_cfg/core/integration/commands_collector.py +38 -39
- django_cfg/core/integration/display/__init__.py +2 -2
- django_cfg/core/integration/display/base.py +30 -30
- django_cfg/core/integration/display/ngrok.py +35 -36
- django_cfg/core/integration/display/startup.py +149 -139
- django_cfg/core/integration/url_integration.py +10 -10
- django_cfg/core/integration/version_checker.py +20 -19
- django_cfg/core/services/config_service.py +4 -4
- django_cfg/core/state/__init__.py +1 -1
- django_cfg/core/state/registry.py +1 -1
- django_cfg/core/types/__init__.py +8 -1
- django_cfg/core/validation.py +36 -39
- django_cfg/management/commands/check_endpoints.py +3 -1
- django_cfg/management/commands/check_settings.py +3 -1
- django_cfg/management/commands/clear_constance.py +3 -1
- django_cfg/management/commands/create_token.py +3 -1
- django_cfg/management/commands/generate_clients.py +3 -1
- django_cfg/management/commands/migrate_all.py +3 -1
- django_cfg/management/commands/rundramatiq.py +3 -1
- django_cfg/management/commands/rundramatiq_simulator.py +3 -1
- django_cfg/management/commands/runserver_ngrok.py +3 -1
- django_cfg/management/commands/show_config.py +3 -1
- django_cfg/management/commands/superuser.py +3 -1
- django_cfg/management/commands/task_clear.py +3 -1
- django_cfg/management/commands/task_status.py +3 -1
- django_cfg/management/commands/test_email.py +3 -1
- django_cfg/management/commands/test_telegram.py +3 -1
- django_cfg/management/commands/test_twilio.py +3 -1
- django_cfg/management/commands/validate_openapi.py +3 -1
- django_cfg/middleware/pagination.py +8 -8
- django_cfg/middleware/public_endpoints.py +24 -23
- django_cfg/middleware/user_activity.py +27 -25
- django_cfg/models/__init__.py +19 -20
- django_cfg/models/api/__init__.py +4 -4
- django_cfg/models/api/config.py +23 -21
- django_cfg/models/api/cors.py +17 -16
- django_cfg/models/api/drf/__init__.py +1 -1
- django_cfg/models/api/drf/config.py +2 -1
- django_cfg/models/api/drf/redoc.py +2 -1
- django_cfg/models/api/drf/spectacular.py +4 -2
- django_cfg/models/api/drf/swagger.py +2 -1
- django_cfg/models/api/jwt.py +37 -36
- django_cfg/models/api/keys.py +13 -12
- django_cfg/models/api/limits.py +31 -30
- django_cfg/models/base/config.py +40 -41
- django_cfg/models/base/module.py +8 -8
- django_cfg/models/django/__init__.py +1 -1
- django_cfg/models/django/constance.py +8 -7
- django_cfg/models/django/environment.py +5 -3
- django_cfg/models/django/openapi.py +6 -16
- django_cfg/models/django/revolution_legacy.py +17 -16
- django_cfg/models/infrastructure/__init__.py +1 -1
- django_cfg/models/infrastructure/cache.py +46 -45
- django_cfg/models/infrastructure/database/config.py +4 -6
- django_cfg/models/infrastructure/database/converters.py +1 -1
- django_cfg/models/infrastructure/database/parsers.py +1 -1
- django_cfg/models/infrastructure/database/validators.py +1 -1
- django_cfg/models/infrastructure/logging.py +59 -57
- django_cfg/models/infrastructure/security.py +26 -24
- django_cfg/models/ngrok/auth.py +2 -1
- django_cfg/models/ngrok/config.py +3 -2
- django_cfg/models/ngrok/tunnel.py +2 -1
- django_cfg/models/payments/__init__.py +1 -1
- django_cfg/models/payments/api_keys.py +3 -1
- django_cfg/models/payments/config.py +4 -1
- django_cfg/models/payments/providers/base.py +2 -1
- django_cfg/models/payments/providers/nowpayments.py +3 -1
- django_cfg/models/services/__init__.py +1 -1
- django_cfg/models/services/base.py +2 -1
- django_cfg/models/services/email.py +28 -26
- django_cfg/models/services/telegram.py +2 -1
- django_cfg/models/tasks/__init__.py +2 -2
- django_cfg/models/tasks/backends.py +4 -3
- django_cfg/models/tasks/config.py +6 -4
- django_cfg/models/tasks/utils.py +3 -3
- django_cfg/modules/base.py +18 -17
- django_cfg/modules/django_admin/__init__.py +14 -15
- django_cfg/modules/django_admin/decorators/__init__.py +1 -1
- django_cfg/modules/django_admin/decorators/actions.py +8 -7
- django_cfg/modules/django_admin/decorators/display.py +9 -7
- django_cfg/modules/django_admin/icons/__init__.py +1 -1
- django_cfg/modules/django_admin/icons/constants.py +27 -27
- django_cfg/modules/django_admin/icons/generate_icons.py +54 -54
- django_cfg/modules/django_admin/management/commands/check_endpoints.py +5 -3
- django_cfg/modules/django_admin/management/commands/check_settings.py +40 -44
- django_cfg/modules/django_admin/management/commands/clear_constance.py +29 -30
- django_cfg/modules/django_admin/management/commands/create_token.py +42 -42
- django_cfg/modules/django_admin/management/commands/list_urls.py +37 -38
- django_cfg/modules/django_admin/management/commands/migrate_all.py +13 -15
- django_cfg/modules/django_admin/management/commands/migrator.py +17 -17
- django_cfg/modules/django_admin/management/commands/script.py +58 -60
- django_cfg/modules/django_admin/management/commands/show_config.py +32 -30
- django_cfg/modules/django_admin/management/commands/show_urls.py +46 -44
- django_cfg/modules/django_admin/management/commands/superuser.py +47 -48
- django_cfg/modules/django_admin/management/commands/tree.py +50 -54
- django_cfg/modules/django_admin/mixins/display_mixin.py +16 -15
- django_cfg/modules/django_admin/mixins/optimization_mixin.py +9 -8
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +25 -24
- django_cfg/modules/django_admin/models/__init__.py +4 -4
- django_cfg/modules/django_admin/models/action_models.py +3 -1
- django_cfg/modules/django_admin/models/badge_models.py +4 -2
- django_cfg/modules/django_admin/models/base.py +3 -3
- django_cfg/modules/django_admin/models/display_models.py +1 -0
- django_cfg/modules/django_admin/utils/badges.py +27 -26
- django_cfg/modules/django_admin/utils/displays.py +49 -49
- django_cfg/modules/django_client/apps.py +21 -3
- django_cfg/modules/django_client/core/__init__.py +9 -10
- django_cfg/modules/django_client/core/archive/manager.py +2 -2
- django_cfg/modules/django_client/core/cli/main.py +1 -3
- django_cfg/modules/django_client/core/config/config.py +3 -1
- django_cfg/modules/django_client/core/config/group.py +1 -0
- django_cfg/modules/django_client/core/config/service.py +2 -1
- django_cfg/modules/django_client/core/generator/__init__.py +1 -1
- django_cfg/modules/django_client/core/generator/base.py +2 -2
- django_cfg/modules/django_client/core/generator/python/async_client_gen.py +1 -1
- django_cfg/modules/django_client/core/generator/python/files_generator.py +1 -1
- django_cfg/modules/django_client/core/generator/python/generator.py +4 -4
- django_cfg/modules/django_client/core/generator/python/models_generator.py +1 -1
- django_cfg/modules/django_client/core/generator/python/operations_generator.py +2 -2
- django_cfg/modules/django_client/core/generator/python/sync_client_gen.py +1 -1
- django_cfg/modules/django_client/core/generator/typescript/client_generator.py +3 -1
- django_cfg/modules/django_client/core/generator/typescript/fetchers_generator.py +14 -13
- django_cfg/modules/django_client/core/generator/typescript/files_generator.py +1 -0
- django_cfg/modules/django_client/core/generator/typescript/generator.py +6 -6
- django_cfg/modules/django_client/core/generator/typescript/hooks_generator.py +12 -10
- django_cfg/modules/django_client/core/generator/typescript/models_generator.py +2 -1
- django_cfg/modules/django_client/core/generator/typescript/naming.py +2 -3
- django_cfg/modules/django_client/core/generator/typescript/operations_generator.py +12 -10
- django_cfg/modules/django_client/core/generator/typescript/schemas_generator.py +3 -2
- django_cfg/modules/django_client/core/generator/typescript/templates/client/client.ts.jinja +14 -6
- django_cfg/modules/django_client/core/generator/typescript/templates/main_index.ts.jinja +4 -10
- django_cfg/modules/django_client/core/groups/__init__.py +1 -1
- django_cfg/modules/django_client/core/groups/detector.py +2 -1
- django_cfg/modules/django_client/core/groups/manager.py +2 -1
- django_cfg/modules/django_client/core/ir/schema.py +1 -1
- django_cfg/modules/django_client/core/parser/base.py +0 -2
- django_cfg/modules/django_client/core/parser/models/schema.py +1 -1
- django_cfg/modules/django_client/core/validation/__init__.py +1 -1
- django_cfg/modules/django_client/core/validation/fixer.py +1 -2
- django_cfg/modules/django_client/core/validation/reporter.py +2 -2
- django_cfg/modules/django_client/core/validation/safety.py +1 -1
- django_cfg/modules/django_client/management/commands/generate_client.py +14 -11
- django_cfg/modules/django_client/management/commands/validate_openapi.py +4 -6
- django_cfg/modules/django_client/spectacular/__init__.py +1 -1
- django_cfg/modules/django_client/spectacular/async_detection.py +3 -2
- django_cfg/modules/django_client/spectacular/enum_naming.py +1 -1
- django_cfg/modules/django_client/spectacular/schema.py +5 -5
- django_cfg/modules/django_client/system/__init__.py +24 -0
- django_cfg/modules/django_client/system/base_generator.py +123 -0
- django_cfg/modules/django_client/system/generate_mjs_clients.py +174 -0
- django_cfg/modules/django_client/system/mjs_generator.py +219 -0
- django_cfg/modules/django_client/system/schema_parser.py +195 -0
- django_cfg/modules/django_client/system/templates/api_client.js.j2 +87 -0
- django_cfg/modules/django_client/system/templates/app_index.js.j2 +13 -0
- django_cfg/modules/django_client/system/templates/base_client.js.j2 +166 -0
- django_cfg/modules/django_client/system/templates/main_index.js.j2 +80 -0
- django_cfg/modules/django_client/system/templates/types.js.j2 +24 -0
- django_cfg/modules/django_client/urls.py +3 -2
- django_cfg/modules/django_currency/__init__.py +17 -18
- django_cfg/modules/django_currency/clients/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/coinpaprika_client.py +48 -48
- django_cfg/modules/django_currency/clients/hybrid_client.py +76 -75
- django_cfg/modules/django_currency/core/__init__.py +7 -13
- django_cfg/modules/django_currency/core/converter.py +25 -24
- django_cfg/modules/django_currency/core/models.py +9 -8
- django_cfg/modules/django_currency/database/__init__.py +4 -4
- django_cfg/modules/django_currency/database/database_loader.py +65 -66
- django_cfg/modules/django_currency/examples/example_database_usage.py +29 -28
- django_cfg/modules/django_currency/utils/cache.py +10 -11
- django_cfg/modules/django_dashboard/__init__.py +4 -5
- django_cfg/modules/django_dashboard/components.py +11 -7
- django_cfg/modules/django_dashboard/debug.py +1 -3
- django_cfg/modules/django_dashboard/management/commands/debug_dashboard.py +3 -3
- django_cfg/modules/django_dashboard/sections/base.py +2 -1
- django_cfg/modules/django_dashboard/sections/commands.py +3 -2
- django_cfg/modules/django_dashboard/sections/documentation.py +8 -6
- django_cfg/modules/django_dashboard/sections/overview.py +13 -9
- django_cfg/modules/django_dashboard/sections/stats.py +2 -2
- django_cfg/modules/django_dashboard/sections/system.py +2 -1
- django_cfg/modules/django_drf_theme/templatetags/tailwind_tags.py +12 -4
- django_cfg/modules/django_email/management/commands/test_email.py +8 -7
- django_cfg/modules/django_email/service.py +5 -4
- django_cfg/modules/django_health/service.py +46 -44
- django_cfg/modules/django_import_export/__init__.py +7 -3
- django_cfg/modules/django_llm/__init__.py +3 -2
- django_cfg/modules/django_llm/example.py +58 -56
- django_cfg/modules/django_llm/llm/__init__.py +1 -1
- django_cfg/modules/django_llm/llm/cache.py +21 -20
- django_cfg/modules/django_llm/llm/client.py +9 -9
- django_cfg/modules/django_llm/llm/costs.py +14 -14
- django_cfg/modules/django_llm/llm/embeddings/__init__.py +1 -1
- django_cfg/modules/django_llm/llm/embeddings/mock_embedder.py +1 -2
- django_cfg/modules/django_llm/llm/embeddings/openai_embedder.py +1 -2
- django_cfg/modules/django_llm/llm/extractor.py +8 -8
- django_cfg/modules/django_llm/llm/models.py +5 -5
- django_cfg/modules/django_llm/llm/models_api/models_query.py +2 -2
- django_cfg/modules/django_llm/llm/models_cache.py +91 -92
- django_cfg/modules/django_llm/llm/providers/config_builder.py +1 -1
- django_cfg/modules/django_llm/llm/providers/provider_manager.py +2 -1
- django_cfg/modules/django_llm/llm/requests/cache_manager.py +1 -1
- django_cfg/modules/django_llm/llm/requests/chat_handler.py +2 -2
- django_cfg/modules/django_llm/llm/requests/embedding_handler.py +1 -1
- django_cfg/modules/django_llm/llm/responses/response_builder.py +2 -2
- django_cfg/modules/django_llm/llm/stats/stats_manager.py +1 -1
- django_cfg/modules/django_llm/llm/tokenizer.py +10 -9
- django_cfg/modules/django_llm/translator/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/cache.py +36 -35
- django_cfg/modules/django_llm/translator/detectors/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/detectors/script_detector.py +0 -1
- django_cfg/modules/django_llm/translator/stats/stats_tracker.py +1 -1
- django_cfg/modules/django_llm/translator/translator.py +5 -4
- django_cfg/modules/django_llm/translator/translators/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/translators/json_translator.py +1 -1
- django_cfg/modules/django_llm/translator/utils/__init__.py +1 -1
- django_cfg/modules/django_llm/translator/utils/prompt_builder.py +0 -1
- django_cfg/modules/django_logging/__init__.py +1 -1
- django_cfg/modules/django_logging/django_logger.py +33 -34
- django_cfg/modules/django_logging/logger.py +3 -7
- django_cfg/modules/django_ngrok/__init__.py +7 -7
- django_cfg/modules/django_ngrok/management/commands/runserver_ngrok.py +33 -30
- django_cfg/modules/django_ngrok/service.py +33 -32
- django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +4 -36
- django_cfg/modules/django_tailwind/templates/django_tailwind/components/navbar.html +1 -1
- django_cfg/modules/django_tasks/__init__.py +5 -5
- django_cfg/modules/django_tasks/dramatiq_setup.py +1 -1
- django_cfg/modules/django_tasks/factory.py +1 -1
- django_cfg/modules/django_tasks/management/commands/rundramatiq.py +39 -40
- django_cfg/modules/django_tasks/management/commands/rundramatiq_simulator.py +79 -80
- django_cfg/modules/django_tasks/management/commands/task_clear.py +34 -34
- django_cfg/modules/django_tasks/management/commands/task_status.py +34 -34
- django_cfg/modules/django_tasks/service.py +4 -3
- django_cfg/modules/django_tasks/settings.py +1 -1
- django_cfg/modules/django_telegram/__init__.py +4 -4
- django_cfg/modules/django_telegram/management/commands/test_telegram.py +4 -5
- django_cfg/modules/django_telegram/service.py +4 -3
- django_cfg/modules/django_telegram/utils.py +1 -1
- django_cfg/modules/django_twilio/__init__.py +15 -16
- django_cfg/modules/django_twilio/_imports.py +1 -1
- django_cfg/modules/django_twilio/base.py +9 -5
- django_cfg/modules/django_twilio/email_otp.py +4 -3
- django_cfg/modules/django_twilio/exceptions.py +36 -36
- django_cfg/modules/django_twilio/management/commands/test_twilio.py +6 -7
- django_cfg/modules/django_twilio/models.py +54 -53
- django_cfg/modules/django_twilio/sendgrid_service.py +70 -72
- django_cfg/modules/django_twilio/simple_service.py +42 -41
- django_cfg/modules/django_twilio/sms.py +1 -0
- django_cfg/modules/django_twilio/twilio_service.py +79 -83
- django_cfg/modules/django_twilio/unified.py +6 -5
- django_cfg/modules/django_twilio/utils.py +2 -3
- django_cfg/modules/django_twilio/whatsapp.py +3 -2
- django_cfg/modules/django_unfold/__init__.py +7 -6
- django_cfg/modules/django_unfold/callbacks/actions.py +6 -5
- django_cfg/modules/django_unfold/callbacks/apizones.py +122 -0
- django_cfg/modules/django_unfold/callbacks/base.py +9 -8
- django_cfg/modules/django_unfold/callbacks/charts.py +36 -37
- django_cfg/modules/django_unfold/callbacks/commands.py +2 -2
- django_cfg/modules/django_unfold/callbacks/main.py +27 -27
- django_cfg/modules/django_unfold/callbacks/statistics.py +12 -12
- django_cfg/modules/django_unfold/callbacks/system.py +5 -5
- django_cfg/modules/django_unfold/callbacks/users.py +4 -4
- django_cfg/modules/django_unfold/dashboard.py +29 -29
- django_cfg/modules/django_unfold/models/__init__.py +23 -8
- django_cfg/modules/django_unfold/models/config.py +84 -81
- django_cfg/modules/django_unfold/models/dashboard.py +20 -19
- django_cfg/modules/django_unfold/models/dropdown.py +6 -4
- django_cfg/modules/django_unfold/models/navigation.py +6 -4
- django_cfg/modules/django_unfold/models/tabs.py +4 -3
- django_cfg/modules/django_unfold/models.py +2 -3
- django_cfg/modules/django_unfold/system_monitor.py +27 -25
- django_cfg/modules/django_unfold/tailwind.py +12 -14
- django_cfg/modules/django_unfold/utils.py +7 -6
- django_cfg/pyproject.toml +1 -1
- django_cfg/registry/__init__.py +3 -3
- django_cfg/registry/core.py +8 -8
- django_cfg/registry/modules.py +2 -2
- django_cfg/registry/services.py +2 -2
- django_cfg/registry/third_party.py +3 -3
- django_cfg/routing/__init__.py +3 -3
- django_cfg/routing/callbacks.py +27 -26
- django_cfg/routing/routers.py +2 -2
- django_cfg/static/js/api/accounts/client.mjs +69 -0
- django_cfg/static/js/api/accounts/index.mjs +13 -0
- django_cfg/static/js/api/base.mjs +166 -0
- django_cfg/static/js/api/index.mjs +100 -0
- django_cfg/static/js/api/ipc/client.mjs +74 -0
- django_cfg/static/js/api/ipc/index.mjs +13 -0
- django_cfg/static/js/api/leads/client.mjs +71 -0
- django_cfg/static/js/api/leads/index.mjs +13 -0
- django_cfg/static/js/api/newsletter/client.mjs +109 -0
- django_cfg/static/js/api/newsletter/index.mjs +13 -0
- django_cfg/static/js/api/payments/client.mjs +1264 -0
- django_cfg/static/js/api/payments/index.mjs +13 -0
- django_cfg/static/js/api/support/client.mjs +84 -0
- django_cfg/static/js/api/support/index.mjs +13 -0
- django_cfg/static/js/api/tasks/client.mjs +74 -0
- django_cfg/static/js/api/tasks/index.mjs +13 -0
- django_cfg/static/js/api/types.mjs +729 -0
- django_cfg/static/js/api-loader.mjs +169 -0
- django_cfg/templates/admin/snippets/zones/zones_table.html +4 -3
- django_cfg/templatetags/django_cfg.py +4 -4
- django_cfg/utils/path_resolution.py +49 -50
- django_cfg/utils/smart_defaults.py +27 -29
- django_cfg/utils/version_check.py +14 -14
- {django_cfg-1.4.20.dist-info → django_cfg-1.4.23.dist-info}/METADATA +1 -1
- django_cfg-1.4.23.dist-info/RECORD +1137 -0
- django_cfg/apps/payments/static/payments/js/api-client.js +0 -408
- django_cfg/modules/django_ipc_client/dashboard/README.md +0 -517
- django_cfg/modules/django_ipc_client/dashboard/UNFOLD_INTEGRATION.md +0 -439
- django_cfg/modules/django_ipc_client/dashboard/__init__.py +0 -11
- django_cfg/modules/django_ipc_client/dashboard/apps.py +0 -22
- django_cfg/modules/django_ipc_client/dashboard/templates/django_ipc_dashboard/dashboard.html +0 -200
- django_cfg/modules/django_ipc_client/dashboard/urls.py +0 -22
- django_cfg/modules/django_ipc_client/dashboard/urls_admin.py +0 -9
- django_cfg/modules/django_ipc_client/dashboard/views.py +0 -251
- django_cfg/modules/django_rpc_old/POETRY.md +0 -344
- django_cfg/modules/django_rpc_old/README.md +0 -397
- django_cfg/modules/django_rpc_old/TESTING.md +0 -358
- django_cfg/modules/django_rpc_old/__init__.py +0 -39
- django_cfg/modules/django_rpc_old/client.py +0 -531
- django_cfg/modules/django_rpc_old/config.py +0 -279
- django_cfg/modules/django_rpc_old/exceptions.py +0 -172
- django_cfg/modules/django_unfold/callbacks/revolution.py +0 -81
- django_cfg-1.4.20.dist-info/RECORD +0 -1110
- /django_cfg/{modules/django_ipc_client → apps/ipc}/README.md +0 -0
- /django_cfg/{modules/django_ipc_client → apps/ipc/services/client}/config.py +0 -0
- {django_cfg-1.4.20.dist-info → django_cfg-1.4.23.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.20.dist-info → django_cfg-1.4.23.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.20.dist-info → django_cfg-1.4.23.dist-info}/licenses/LICENSE +0 -0
django_cfg/apps/leads/tests.py
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
Lead Tests - Test cases for Lead model and API.
|
3
3
|
"""
|
4
4
|
|
5
|
+
|
6
|
+
from django.contrib.auth import get_user_model
|
5
7
|
from django.test import TestCase
|
6
8
|
from django.urls import reverse
|
7
|
-
from rest_framework.test import APITestCase
|
8
9
|
from rest_framework import status
|
9
|
-
from
|
10
|
-
from django.contrib.auth import get_user_model
|
10
|
+
from rest_framework.test import APITestCase
|
11
11
|
|
12
12
|
from .models import Lead
|
13
13
|
|
@@ -16,7 +16,7 @@ User = get_user_model()
|
|
16
16
|
|
17
17
|
class LeadModelTest(TestCase):
|
18
18
|
"""Test cases for Lead model."""
|
19
|
-
|
19
|
+
|
20
20
|
def setUp(self):
|
21
21
|
"""Set up test data."""
|
22
22
|
self.user = User.objects.create_user(
|
@@ -24,7 +24,7 @@ class LeadModelTest(TestCase):
|
|
24
24
|
email='test@example.com',
|
25
25
|
password='testpass123'
|
26
26
|
)
|
27
|
-
|
27
|
+
|
28
28
|
self.lead_data = {
|
29
29
|
'name': 'John Doe',
|
30
30
|
'email': 'john@example.com',
|
@@ -41,11 +41,11 @@ class LeadModelTest(TestCase):
|
|
41
41
|
'status': Lead.StatusChoices.NEW,
|
42
42
|
'user': self.user
|
43
43
|
}
|
44
|
-
|
44
|
+
|
45
45
|
def test_create_lead(self):
|
46
46
|
"""Test creating a lead."""
|
47
47
|
lead = Lead.objects.create(**self.lead_data)
|
48
|
-
|
48
|
+
|
49
49
|
self.assertEqual(lead.name, 'John Doe')
|
50
50
|
self.assertEqual(lead.email, 'john@example.com')
|
51
51
|
self.assertEqual(lead.company, 'Test Company')
|
@@ -54,13 +54,13 @@ class LeadModelTest(TestCase):
|
|
54
54
|
self.assertEqual(lead.user, self.user)
|
55
55
|
self.assertIsNotNone(lead.created_at)
|
56
56
|
self.assertIsNotNone(lead.updated_at)
|
57
|
-
|
57
|
+
|
58
58
|
def test_lead_str_representation(self):
|
59
59
|
"""Test string representation of lead."""
|
60
60
|
lead = Lead.objects.create(**self.lead_data)
|
61
|
-
expected_str =
|
61
|
+
expected_str = "John Doe - https://example.com/contact (new)"
|
62
62
|
self.assertEqual(str(lead), expected_str)
|
63
|
-
|
63
|
+
|
64
64
|
def test_lead_choices(self):
|
65
65
|
"""Test lead choices."""
|
66
66
|
# Test status choices
|
@@ -70,7 +70,7 @@ class LeadModelTest(TestCase):
|
|
70
70
|
self.assertIn('qualified', status_choices)
|
71
71
|
self.assertIn('converted', status_choices)
|
72
72
|
self.assertIn('rejected', status_choices)
|
73
|
-
|
73
|
+
|
74
74
|
# Test contact type choices
|
75
75
|
contact_choices = [choice[0] for choice in Lead.ContactTypeChoices.choices]
|
76
76
|
self.assertIn('email', contact_choices)
|
@@ -78,15 +78,15 @@ class LeadModelTest(TestCase):
|
|
78
78
|
self.assertIn('telegram', contact_choices)
|
79
79
|
self.assertIn('phone', contact_choices)
|
80
80
|
self.assertIn('other', contact_choices)
|
81
|
-
|
81
|
+
|
82
82
|
def test_lead_without_user(self):
|
83
83
|
"""Test creating lead without user."""
|
84
84
|
lead_data = self.lead_data.copy()
|
85
85
|
del lead_data['user']
|
86
|
-
|
86
|
+
|
87
87
|
lead = Lead.objects.create(**lead_data)
|
88
88
|
self.assertIsNone(lead.user)
|
89
|
-
|
89
|
+
|
90
90
|
def test_lead_optional_fields(self):
|
91
91
|
"""Test creating lead with optional fields."""
|
92
92
|
lead_data = {
|
@@ -96,7 +96,7 @@ class LeadModelTest(TestCase):
|
|
96
96
|
'site_url': 'https://example.com/contact',
|
97
97
|
'status': Lead.StatusChoices.NEW
|
98
98
|
}
|
99
|
-
|
99
|
+
|
100
100
|
lead = Lead.objects.create(**lead_data)
|
101
101
|
self.assertEqual(lead.name, 'Jane Doe')
|
102
102
|
self.assertIsNone(lead.company)
|
@@ -109,7 +109,7 @@ class LeadModelTest(TestCase):
|
|
109
109
|
|
110
110
|
class LeadAPITest(APITestCase):
|
111
111
|
"""Test cases for Lead API."""
|
112
|
-
|
112
|
+
|
113
113
|
def setUp(self):
|
114
114
|
"""Set up test data."""
|
115
115
|
self.url = reverse('cfg_leads:lead-submit')
|
@@ -125,16 +125,16 @@ class LeadAPITest(APITestCase):
|
|
125
125
|
'extra': {'source': 'contact_form'},
|
126
126
|
'site_url': 'https://example.com/contact'
|
127
127
|
}
|
128
|
-
|
128
|
+
|
129
129
|
def test_submit_lead_success(self):
|
130
130
|
"""Test successful lead submission."""
|
131
131
|
response = self.client.post(self.url, self.valid_data, format='json')
|
132
|
-
|
132
|
+
|
133
133
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
134
134
|
self.assertTrue(response.data['success'])
|
135
135
|
self.assertEqual(response.data['message'], 'Lead submitted successfully')
|
136
136
|
self.assertIn('lead_id', response.data)
|
137
|
-
|
137
|
+
|
138
138
|
# Check if lead was created
|
139
139
|
lead = Lead.objects.get(id=response.data['lead_id'])
|
140
140
|
self.assertEqual(lead.name, 'John Doe')
|
@@ -142,46 +142,46 @@ class LeadAPITest(APITestCase):
|
|
142
142
|
self.assertEqual(lead.status, Lead.StatusChoices.NEW)
|
143
143
|
self.assertIsNotNone(lead.ip_address)
|
144
144
|
self.assertIsNotNone(lead.user_agent)
|
145
|
-
|
145
|
+
|
146
146
|
def test_submit_lead_missing_required_fields(self):
|
147
147
|
"""Test lead submission with missing required fields."""
|
148
148
|
# Test missing name
|
149
149
|
data = self.valid_data.copy()
|
150
150
|
del data['name']
|
151
151
|
response = self.client.post(self.url, data, format='json')
|
152
|
-
|
152
|
+
|
153
153
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
154
154
|
self.assertFalse(response.data['success'])
|
155
155
|
self.assertIn('name', response.data['details'])
|
156
|
-
|
156
|
+
|
157
157
|
# Test missing email
|
158
158
|
data = self.valid_data.copy()
|
159
159
|
del data['email']
|
160
160
|
response = self.client.post(self.url, data, format='json')
|
161
|
-
|
161
|
+
|
162
162
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
163
163
|
self.assertFalse(response.data['success'])
|
164
164
|
self.assertIn('email', response.data['details'])
|
165
|
-
|
165
|
+
|
166
166
|
# Test missing message
|
167
167
|
data = self.valid_data.copy()
|
168
168
|
del data['message']
|
169
169
|
response = self.client.post(self.url, data, format='json')
|
170
|
-
|
170
|
+
|
171
171
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
172
172
|
self.assertFalse(response.data['success'])
|
173
173
|
self.assertIn('message', response.data['details'])
|
174
|
-
|
174
|
+
|
175
175
|
def test_submit_lead_invalid_email(self):
|
176
176
|
"""Test lead submission with invalid email."""
|
177
177
|
data = self.valid_data.copy()
|
178
178
|
data['email'] = 'invalid-email'
|
179
179
|
response = self.client.post(self.url, data, format='json')
|
180
|
-
|
180
|
+
|
181
181
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
182
182
|
self.assertFalse(response.data['success'])
|
183
183
|
self.assertIn('email', response.data['details'])
|
184
|
-
|
184
|
+
|
185
185
|
def test_submit_lead_minimal_data(self):
|
186
186
|
"""Test lead submission with minimal required data."""
|
187
187
|
minimal_data = {
|
@@ -190,12 +190,12 @@ class LeadAPITest(APITestCase):
|
|
190
190
|
'message': 'Test message',
|
191
191
|
'site_url': 'https://example.com/contact'
|
192
192
|
}
|
193
|
-
|
193
|
+
|
194
194
|
response = self.client.post(self.url, minimal_data, format='json')
|
195
|
-
|
195
|
+
|
196
196
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
197
197
|
self.assertTrue(response.data['success'])
|
198
|
-
|
198
|
+
|
199
199
|
# Check if lead was created with defaults
|
200
200
|
lead = Lead.objects.get(id=response.data['lead_id'])
|
201
201
|
self.assertEqual(lead.name, 'Jane Doe')
|
@@ -205,24 +205,24 @@ class LeadAPITest(APITestCase):
|
|
205
205
|
self.assertIsNone(lead.company_site)
|
206
206
|
self.assertIsNone(lead.subject)
|
207
207
|
self.assertIsNone(lead.extra)
|
208
|
-
|
208
|
+
|
209
209
|
def test_submit_lead_different_contact_types(self):
|
210
210
|
"""Test lead submission with different contact types."""
|
211
211
|
contact_types = ['email', 'whatsapp', 'telegram', 'phone', 'other']
|
212
|
-
|
212
|
+
|
213
213
|
for contact_type in contact_types:
|
214
214
|
data = self.valid_data.copy()
|
215
215
|
data['contact_type'] = contact_type
|
216
216
|
data['contact_value'] = f'test_{contact_type}@example.com'
|
217
|
-
|
217
|
+
|
218
218
|
response = self.client.post(self.url, data, format='json')
|
219
|
-
|
219
|
+
|
220
220
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
221
221
|
self.assertTrue(response.data['success'])
|
222
|
-
|
222
|
+
|
223
223
|
lead = Lead.objects.get(id=response.data['lead_id'])
|
224
224
|
self.assertEqual(lead.contact_type, contact_type)
|
225
|
-
|
225
|
+
|
226
226
|
def test_submit_lead_with_extra_data(self):
|
227
227
|
"""Test lead submission with extra JSON data."""
|
228
228
|
data = self.valid_data.copy()
|
@@ -236,14 +236,14 @@ class LeadAPITest(APITestCase):
|
|
236
236
|
'version': '91.0'
|
237
237
|
}
|
238
238
|
}
|
239
|
-
|
239
|
+
|
240
240
|
response = self.client.post(self.url, data, format='json')
|
241
|
-
|
241
|
+
|
242
242
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
243
|
-
|
243
|
+
|
244
244
|
lead = Lead.objects.get(id=response.data['lead_id'])
|
245
245
|
self.assertEqual(lead.extra, data['extra'])
|
246
|
-
|
246
|
+
|
247
247
|
def test_submit_lead_ip_and_user_agent(self):
|
248
248
|
"""Test that IP address and user agent are captured."""
|
249
249
|
# Set custom headers
|
@@ -251,21 +251,21 @@ class LeadAPITest(APITestCase):
|
|
251
251
|
'HTTP_X_FORWARDED_FOR': '192.168.1.100',
|
252
252
|
'HTTP_USER_AGENT': 'Test Browser/1.0'
|
253
253
|
}
|
254
|
-
|
254
|
+
|
255
255
|
response = self.client.post(self.url, self.valid_data, format='json', **headers)
|
256
|
-
|
256
|
+
|
257
257
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
258
|
-
|
258
|
+
|
259
259
|
lead = Lead.objects.get(id=response.data['lead_id'])
|
260
260
|
self.assertEqual(lead.ip_address, '192.168.1.100')
|
261
261
|
self.assertEqual(lead.user_agent, 'Test Browser/1.0')
|
262
|
-
|
262
|
+
|
263
263
|
def test_submit_lead_without_forwarded_ip(self):
|
264
264
|
"""Test IP capture when X-Forwarded-For is not present."""
|
265
265
|
response = self.client.post(self.url, self.valid_data, format='json')
|
266
|
-
|
266
|
+
|
267
267
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
268
|
-
|
268
|
+
|
269
269
|
lead = Lead.objects.get(id=response.data['lead_id'])
|
270
270
|
# Should capture some IP (could be 127.0.0.1 in tests)
|
271
271
|
self.assertIsNotNone(lead.ip_address)
|
django_cfg/apps/leads/urls.py
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
Lead URLs - API routing for the leads application.
|
3
3
|
"""
|
4
4
|
|
5
|
-
from django.urls import
|
5
|
+
from django.urls import include, path
|
6
6
|
from rest_framework.routers import DefaultRouter
|
7
7
|
|
8
8
|
from .views import LeadViewSet
|
@@ -16,4 +16,4 @@ app_name = "cfg_leads"
|
|
16
16
|
|
17
17
|
urlpatterns = [
|
18
18
|
path("", include(router.urls)),
|
19
|
-
]
|
19
|
+
]
|
django_cfg/apps/leads/views.py
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
Lead Views - API views for Lead model.
|
3
3
|
"""
|
4
4
|
|
5
|
-
from
|
5
|
+
from drf_spectacular.utils import OpenApiExample, extend_schema
|
6
|
+
from rest_framework import status, viewsets
|
6
7
|
from rest_framework.decorators import action
|
7
|
-
from rest_framework.response import Response
|
8
8
|
from rest_framework.permissions import AllowAny
|
9
|
-
from
|
9
|
+
from rest_framework.response import Response
|
10
10
|
|
11
11
|
from .models import Lead
|
12
12
|
from .serializers import (
|
13
|
-
|
14
|
-
LeadSubmissionResponseSerializer,
|
15
|
-
|
13
|
+
LeadSubmissionErrorSerializer,
|
14
|
+
LeadSubmissionResponseSerializer,
|
15
|
+
LeadSubmissionSerializer,
|
16
16
|
)
|
17
17
|
|
18
18
|
|
@@ -65,9 +65,9 @@ class LeadViewSet(viewsets.ModelViewSet):
|
|
65
65
|
ip_address = x_forwarded_for.split(',')[0]
|
66
66
|
else:
|
67
67
|
ip_address = request.META.get('REMOTE_ADDR')
|
68
|
-
|
68
|
+
|
69
69
|
user_agent = request.META.get('HTTP_USER_AGENT', '')
|
70
|
-
|
70
|
+
|
71
71
|
# Create lead with metadata
|
72
72
|
lead_data = serializer.validated_data
|
73
73
|
lead_data.update({
|
@@ -75,15 +75,15 @@ class LeadViewSet(viewsets.ModelViewSet):
|
|
75
75
|
'user_agent': user_agent,
|
76
76
|
'status': Lead.StatusChoices.NEW
|
77
77
|
})
|
78
|
-
|
78
|
+
|
79
79
|
lead = Lead.objects.create(**lead_data)
|
80
|
-
|
80
|
+
|
81
81
|
return Response({
|
82
82
|
'success': True,
|
83
83
|
'message': 'Lead submitted successfully',
|
84
84
|
'lead_id': lead.id
|
85
85
|
}, status=status.HTTP_201_CREATED)
|
86
|
-
|
86
|
+
|
87
87
|
return Response({
|
88
88
|
'success': False,
|
89
89
|
'error': 'Invalid data',
|
@@ -21,7 +21,7 @@ _LAZY_IMPORTS = {
|
|
21
21
|
'CloudflareSite': ('django_cfg.apps.maintenance.models', 'CloudflareSite'),
|
22
22
|
'MaintenanceLog': ('django_cfg.apps.maintenance.models', 'MaintenanceLog'),
|
23
23
|
'ScheduledMaintenance': ('django_cfg.apps.maintenance.models', 'ScheduledMaintenance'),
|
24
|
-
|
24
|
+
|
25
25
|
# Services
|
26
26
|
'MaintenanceService': ('django_cfg.apps.maintenance.services', 'MaintenanceService'),
|
27
27
|
'SiteSyncService': ('django_cfg.apps.maintenance.services', 'SiteSyncService'),
|
@@ -45,11 +45,11 @@ def __getattr__(name: str):
|
|
45
45
|
"""Lazy import mechanism to avoid Django initialization issues."""
|
46
46
|
if name in _LAZY_IMPORTS:
|
47
47
|
module_path, attr_name = _LAZY_IMPORTS[name]
|
48
|
-
|
48
|
+
|
49
49
|
import importlib
|
50
50
|
module = importlib.import_module(module_path)
|
51
51
|
return getattr(module, attr_name)
|
52
|
-
|
52
|
+
|
53
53
|
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
54
54
|
|
55
55
|
|
@@ -5,9 +5,9 @@ Refactored admin interfaces with Material Icons and optimized queries.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
from .api_key_admin import CloudflareApiKeyAdmin
|
8
|
-
from .site_admin import CloudflareSiteAdmin
|
9
8
|
from .log_admin import MaintenanceLogAdmin
|
10
9
|
from .scheduled_admin import ScheduledMaintenanceAdmin
|
10
|
+
from .site_admin import CloudflareSiteAdmin
|
11
11
|
|
12
12
|
__all__ = [
|
13
13
|
'CloudflareApiKeyAdmin',
|
@@ -4,22 +4,22 @@ CloudflareApiKey admin using Django Admin Utilities.
|
|
4
4
|
Enhanced API key management with Material Icons and optimized queries.
|
5
5
|
"""
|
6
6
|
|
7
|
+
|
7
8
|
from django.contrib import admin, messages
|
8
|
-
from django.http import HttpRequest
|
9
9
|
from django.db import models
|
10
10
|
from django.db.models import Count
|
11
|
-
from
|
11
|
+
from django.http import HttpRequest
|
12
12
|
from unfold.admin import ModelAdmin
|
13
13
|
|
14
14
|
from django_cfg.modules.django_admin import (
|
15
|
-
|
16
|
-
DisplayMixin,
|
17
|
-
StatusBadgeConfig,
|
15
|
+
ActionVariant,
|
18
16
|
DateTimeDisplayConfig,
|
17
|
+
DisplayMixin,
|
19
18
|
Icons,
|
20
|
-
|
19
|
+
OptimizedModelAdmin,
|
20
|
+
StatusBadgeConfig,
|
21
|
+
action,
|
21
22
|
display,
|
22
|
-
action
|
23
23
|
)
|
24
24
|
from django_cfg.modules.django_admin.utils.badges import StatusBadge
|
25
25
|
|
@@ -29,7 +29,7 @@ from ..models import CloudflareApiKey
|
|
29
29
|
@admin.register(CloudflareApiKey)
|
30
30
|
class CloudflareApiKeyAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
|
31
31
|
"""Admin interface for CloudflareApiKey model using Django Admin Utilities."""
|
32
|
-
|
32
|
+
|
33
33
|
list_display = [
|
34
34
|
'status_display',
|
35
35
|
'name_display',
|
@@ -55,7 +55,7 @@ class CloudflareApiKeyAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
|
|
55
55
|
'last_used_at',
|
56
56
|
'sites_using_key'
|
57
57
|
]
|
58
|
-
|
58
|
+
|
59
59
|
fieldsets = [
|
60
60
|
('🔑 Basic Information', {
|
61
61
|
'fields': ['name', 'description'],
|
@@ -78,13 +78,13 @@ class CloudflareApiKeyAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
|
|
78
78
|
'classes': ('tab', 'collapse')
|
79
79
|
})
|
80
80
|
]
|
81
|
-
|
81
|
+
|
82
82
|
actions = [
|
83
83
|
'make_default_action',
|
84
84
|
'activate_keys_action',
|
85
85
|
'deactivate_keys_action'
|
86
86
|
]
|
87
|
-
|
87
|
+
|
88
88
|
@display(description="Status")
|
89
89
|
def status_display(self, obj: CloudflareApiKey) -> str:
|
90
90
|
"""Display status with badge."""
|
@@ -110,7 +110,7 @@ class CloudflareApiKeyAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
|
|
110
110
|
variant="danger",
|
111
111
|
config=config
|
112
112
|
)
|
113
|
-
|
113
|
+
|
114
114
|
@display(description="Name", ordering="name")
|
115
115
|
def name_display(self, obj: CloudflareApiKey) -> str:
|
116
116
|
"""Display API key name."""
|
@@ -120,19 +120,19 @@ class CloudflareApiKeyAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
|
|
120
120
|
variant="primary",
|
121
121
|
config=config
|
122
122
|
)
|
123
|
-
|
123
|
+
|
124
124
|
@display(description="Description")
|
125
125
|
def description_preview(self, obj: CloudflareApiKey) -> str:
|
126
126
|
"""Show description preview."""
|
127
127
|
if not obj.description:
|
128
128
|
return "—"
|
129
|
-
|
129
|
+
|
130
130
|
preview = obj.description[:50]
|
131
131
|
if len(obj.description) > 50:
|
132
132
|
preview += "..."
|
133
|
-
|
133
|
+
|
134
134
|
return preview
|
135
|
-
|
135
|
+
|
136
136
|
@display(description="Active")
|
137
137
|
def active_display(self, obj: CloudflareApiKey) -> str:
|
138
138
|
"""Display active status badge."""
|
@@ -142,7 +142,7 @@ class CloudflareApiKeyAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
|
|
142
142
|
else:
|
143
143
|
config = StatusBadgeConfig(show_icons=True, icon=Icons.CANCEL)
|
144
144
|
return StatusBadge.create(text="Inactive", variant="secondary", config=config)
|
145
|
-
|
145
|
+
|
146
146
|
@display(description="Default")
|
147
147
|
def default_display(self, obj: CloudflareApiKey) -> str:
|
148
148
|
"""Display default status badge."""
|
@@ -151,7 +151,7 @@ class CloudflareApiKeyAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
|
|
151
151
|
return StatusBadge.create(text="Default", variant="primary", config=config)
|
152
152
|
else:
|
153
153
|
return "—"
|
154
|
-
|
154
|
+
|
155
155
|
@display(description="Sites")
|
156
156
|
def sites_count(self, obj: CloudflareApiKey) -> str:
|
157
157
|
"""Display count of sites using this key."""
|
@@ -159,7 +159,7 @@ class CloudflareApiKeyAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
|
|
159
159
|
if count > 0:
|
160
160
|
return f"{count} sites"
|
161
161
|
return "No sites"
|
162
|
-
|
162
|
+
|
163
163
|
@display(description="Last Used")
|
164
164
|
def last_used_display(self, obj: CloudflareApiKey) -> str:
|
165
165
|
"""Display last used time."""
|
@@ -167,81 +167,81 @@ class CloudflareApiKeyAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin):
|
|
167
167
|
return "Never"
|
168
168
|
config = DateTimeDisplayConfig(show_relative=True)
|
169
169
|
return self.display_datetime_relative(obj, 'last_used_at', config)
|
170
|
-
|
170
|
+
|
171
171
|
@display(description="Created")
|
172
172
|
def created_at_display(self, obj: CloudflareApiKey) -> str:
|
173
173
|
"""Created time with relative display."""
|
174
174
|
config = DateTimeDisplayConfig(show_relative=True)
|
175
175
|
return self.display_datetime_relative(obj, 'created_at', config)
|
176
|
-
|
176
|
+
|
177
177
|
def sites_using_key(self, obj: CloudflareApiKey) -> str:
|
178
178
|
"""Show sites using this API key."""
|
179
179
|
sites = obj.cloudflaresite_set.all()[:10]
|
180
|
-
|
180
|
+
|
181
181
|
if not sites:
|
182
182
|
return "No sites using this key"
|
183
|
-
|
183
|
+
|
184
184
|
site_list = []
|
185
185
|
for site in sites:
|
186
186
|
status_emoji = "🔧" if site.maintenance_active else "🟢"
|
187
187
|
site_list.append(f"{status_emoji} {site.name} ({site.domain})")
|
188
|
-
|
188
|
+
|
189
189
|
result = "\n".join(site_list)
|
190
|
-
|
190
|
+
|
191
191
|
total_count = obj.cloudflaresite_set.count()
|
192
192
|
if total_count > 10:
|
193
193
|
result += f"\n... and {total_count - 10} more sites"
|
194
|
-
|
194
|
+
|
195
195
|
return result
|
196
|
-
|
196
|
+
|
197
197
|
@action(description="Make default API key", variant=ActionVariant.PRIMARY)
|
198
198
|
def make_default_action(self, request: HttpRequest, queryset) -> None:
|
199
199
|
"""Make selected key the default."""
|
200
200
|
if queryset.count() > 1:
|
201
201
|
messages.error(request, "Please select only one API key to make default.")
|
202
202
|
return
|
203
|
-
|
203
|
+
|
204
204
|
key = queryset.first()
|
205
205
|
if key:
|
206
206
|
key.is_default = True
|
207
207
|
key.save()
|
208
208
|
messages.success(request, f"'{key.name}' is now the default API key.")
|
209
|
-
|
209
|
+
|
210
210
|
@action(description="Activate API keys", variant=ActionVariant.SUCCESS)
|
211
211
|
def activate_keys_action(self, request: HttpRequest, queryset) -> None:
|
212
212
|
"""Activate selected API keys."""
|
213
213
|
count = queryset.update(is_active=True)
|
214
214
|
messages.success(request, f"Successfully activated {count} API keys.")
|
215
|
-
|
215
|
+
|
216
216
|
@action(description="Deactivate API keys", variant=ActionVariant.DANGER)
|
217
217
|
def deactivate_keys_action(self, request: HttpRequest, queryset) -> None:
|
218
218
|
"""Deactivate selected API keys."""
|
219
219
|
default_keys = queryset.filter(is_default=True)
|
220
220
|
if default_keys.exists():
|
221
221
|
messages.error(
|
222
|
-
request,
|
222
|
+
request,
|
223
223
|
"Cannot deactivate default API key. Please set another key as default first."
|
224
224
|
)
|
225
225
|
return
|
226
|
-
|
226
|
+
|
227
227
|
count = queryset.update(is_active=False)
|
228
228
|
messages.warning(request, f"Successfully deactivated {count} API keys.")
|
229
|
-
|
229
|
+
|
230
230
|
def changelist_view(self, request, extra_context=None):
|
231
231
|
"""Add API key statistics to changelist."""
|
232
232
|
extra_context = extra_context or {}
|
233
|
-
|
233
|
+
|
234
234
|
queryset = self.get_queryset(request)
|
235
235
|
stats = queryset.aggregate(
|
236
236
|
total_keys=Count('id'),
|
237
237
|
active_keys=Count('id', filter=models.Q(is_active=True)),
|
238
238
|
default_keys=Count('id', filter=models.Q(is_default=True))
|
239
239
|
)
|
240
|
-
|
240
|
+
|
241
241
|
extra_context['api_key_stats'] = {
|
242
242
|
'total_keys': stats['total_keys'] or 0,
|
243
243
|
'active_keys': stats['active_keys'] or 0,
|
244
244
|
'default_keys': stats['default_keys'] or 0
|
245
245
|
}
|
246
|
-
|
246
|
+
|
247
247
|
return super().changelist_view(request, extra_context)
|