django-cfg 1.4.21__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/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 +32 -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 +33 -32
- 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 +10 -9
- 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.21.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.21.dist-info/RECORD +0 -1111
- /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.21.dist-info → django_cfg-1.4.23.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.21.dist-info → django_cfg-1.4.23.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.21.dist-info → django_cfg-1.4.23.dist-info}/licenses/LICENSE +0 -0
@@ -5,48 +5,44 @@ Enhanced support ticket management with Material Icons and optimized queries.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
from django.contrib import admin, messages
|
8
|
-
from django.
|
9
|
-
from django.shortcuts import redirect
|
8
|
+
from django.db.models import Count, Q
|
10
9
|
from django.http import HttpRequest
|
11
|
-
from django.
|
12
|
-
from django.utils.timesince import timesince
|
10
|
+
from django.urls import reverse
|
13
11
|
from django.utils.html import format_html
|
14
|
-
from django.db import models
|
15
|
-
from django.db.models import Count, Q
|
16
12
|
from unfold.admin import ModelAdmin, TabularInline
|
17
|
-
from django_cfg import ExportMixin, ExportForm
|
18
13
|
|
14
|
+
from django_cfg import ExportForm, ExportMixin
|
19
15
|
from django_cfg.modules.django_admin import (
|
20
|
-
|
21
|
-
DisplayMixin,
|
22
|
-
StatusBadgeConfig,
|
16
|
+
ActionVariant,
|
23
17
|
DateTimeDisplayConfig,
|
18
|
+
DisplayMixin,
|
24
19
|
Icons,
|
25
|
-
|
20
|
+
OptimizedModelAdmin,
|
21
|
+
StatusBadgeConfig,
|
22
|
+
action,
|
26
23
|
display,
|
27
|
-
action
|
28
24
|
)
|
29
25
|
from django_cfg.modules.django_admin.utils.badges import StatusBadge
|
30
26
|
|
31
|
-
from ..models import
|
32
|
-
from .filters import TicketUserEmailFilter, TicketUserNameFilter
|
33
|
-
from .resources import
|
27
|
+
from ..models import Message, Ticket
|
28
|
+
from .filters import MessageSenderEmailFilter, TicketUserEmailFilter, TicketUserNameFilter
|
29
|
+
from .resources import MessageResource, TicketResource
|
34
30
|
|
35
31
|
|
36
32
|
class MessageInline(TabularInline):
|
37
33
|
"""Read-only inline for viewing messages. Use Chat interface for replies."""
|
38
|
-
|
34
|
+
|
39
35
|
model = Message
|
40
36
|
extra = 0
|
41
37
|
fields = ["sender_display", "created_at", "text_preview"]
|
42
38
|
readonly_fields = ["sender_display", "created_at", "text_preview"]
|
43
39
|
show_change_link = False
|
44
40
|
classes = ('collapse',)
|
45
|
-
|
41
|
+
|
46
42
|
def has_add_permission(self, request, obj=None):
|
47
43
|
"""Disable adding messages through admin - use chat interface instead."""
|
48
44
|
return False
|
49
|
-
|
45
|
+
|
50
46
|
def has_delete_permission(self, request, obj=None):
|
51
47
|
"""Disable deleting messages through admin."""
|
52
48
|
return False
|
@@ -56,7 +52,7 @@ class MessageInline(TabularInline):
|
|
56
52
|
"""Display sender with badge."""
|
57
53
|
if not obj.sender:
|
58
54
|
return "—"
|
59
|
-
|
55
|
+
|
60
56
|
# Determine sender type and variant
|
61
57
|
if obj.sender.is_superuser:
|
62
58
|
variant = "danger"
|
@@ -67,40 +63,40 @@ class MessageInline(TabularInline):
|
|
67
63
|
else:
|
68
64
|
variant = "info"
|
69
65
|
icon = Icons.PERSON
|
70
|
-
|
66
|
+
|
71
67
|
config = StatusBadgeConfig(show_icons=True, icon=icon)
|
72
68
|
return StatusBadge.create(
|
73
69
|
text=obj.sender.get_full_name() or obj.sender.username,
|
74
70
|
variant=variant,
|
75
71
|
config=config
|
76
72
|
)
|
77
|
-
|
73
|
+
|
78
74
|
@display(description="Message")
|
79
75
|
def text_preview(self, obj):
|
80
76
|
"""Display message preview."""
|
81
77
|
if not obj.text:
|
82
78
|
return "—"
|
83
|
-
|
79
|
+
|
84
80
|
preview = obj.text[:100]
|
85
81
|
if len(obj.text) > 100:
|
86
82
|
preview += "..."
|
87
|
-
|
83
|
+
|
88
84
|
return preview
|
89
85
|
|
90
86
|
|
91
87
|
@admin.register(Ticket)
|
92
88
|
class TicketAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
93
89
|
"""Admin interface for Ticket using Django Admin Utilities."""
|
94
|
-
|
90
|
+
|
95
91
|
# Performance optimization
|
96
92
|
select_related_fields = ['user']
|
97
|
-
|
93
|
+
|
98
94
|
# Export-only configuration
|
99
95
|
resource_class = TicketResource
|
100
96
|
export_form_class = ExportForm
|
101
|
-
|
97
|
+
|
102
98
|
list_display = [
|
103
|
-
"user_display", "uuid_display", "subject_display", "status_display",
|
99
|
+
"user_display", "uuid_display", "subject_display", "status_display",
|
104
100
|
"last_message_display", "last_message_ago_display", "chat_link_display", "created_at_display"
|
105
101
|
]
|
106
102
|
list_display_links = ["subject_display"]
|
@@ -109,16 +105,16 @@ class TicketAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
|
109
105
|
list_filter = ["status", "created_at", TicketUserEmailFilter, TicketUserNameFilter]
|
110
106
|
inlines = [MessageInline]
|
111
107
|
autocomplete_fields = ["user"]
|
112
|
-
|
108
|
+
|
113
109
|
actions = ["mark_as_open", "mark_as_waiting_for_user", "mark_as_waiting_for_admin", "mark_as_resolved", "mark_as_closed"]
|
114
|
-
|
110
|
+
|
115
111
|
def get_readonly_fields(self, request, obj=None):
|
116
112
|
"""Different readonly fields for add/change forms."""
|
117
113
|
if obj is None: # Adding new ticket
|
118
114
|
return ("uuid", "created_at")
|
119
115
|
else: # Editing existing ticket
|
120
116
|
return ("uuid", "user", "created_at")
|
121
|
-
|
117
|
+
|
122
118
|
def get_fieldsets(self, request, obj=None):
|
123
119
|
"""Different fieldsets for add/change forms."""
|
124
120
|
if obj is None: # Adding new ticket
|
@@ -265,7 +261,7 @@ class TicketAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
|
265
261
|
def changelist_view(self, request, extra_context=None):
|
266
262
|
"""Add ticket statistics to changelist."""
|
267
263
|
extra_context = extra_context or {}
|
268
|
-
|
264
|
+
|
269
265
|
queryset = self.get_queryset(request)
|
270
266
|
stats = queryset.aggregate(
|
271
267
|
total_tickets=Count('uuid'),
|
@@ -275,7 +271,7 @@ class TicketAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
|
275
271
|
resolved_tickets=Count('uuid', filter=Q(status='resolved')),
|
276
272
|
closed_tickets=Count('uuid', filter=Q(status='closed'))
|
277
273
|
)
|
278
|
-
|
274
|
+
|
279
275
|
extra_context['ticket_stats'] = {
|
280
276
|
'total_tickets': stats['total_tickets'] or 0,
|
281
277
|
'open_tickets': stats['open_tickets'] or 0,
|
@@ -284,21 +280,21 @@ class TicketAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
|
284
280
|
'resolved_tickets': stats['resolved_tickets'] or 0,
|
285
281
|
'closed_tickets': stats['closed_tickets'] or 0
|
286
282
|
}
|
287
|
-
|
283
|
+
|
288
284
|
return super().changelist_view(request, extra_context)
|
289
285
|
|
290
286
|
|
291
287
|
@admin.register(Message)
|
292
288
|
class MessageAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
293
289
|
"""Admin interface for Message using Django Admin Utilities."""
|
294
|
-
|
290
|
+
|
295
291
|
# Performance optimization
|
296
292
|
select_related_fields = ['ticket', 'sender']
|
297
|
-
|
293
|
+
|
298
294
|
# Export-only configuration
|
299
295
|
resource_class = MessageResource
|
300
296
|
export_form_class = ExportForm
|
301
|
-
|
297
|
+
|
302
298
|
list_display = [
|
303
299
|
"ticket_display", "sender_display", "text_preview", "created_at_display"
|
304
300
|
]
|
@@ -307,7 +303,7 @@ class MessageAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
|
307
303
|
search_fields = ["ticket__uuid", "ticket__subject", "sender__username", "sender__email", "text"]
|
308
304
|
list_filter = ["created_at", "ticket__status", MessageSenderEmailFilter]
|
309
305
|
readonly_fields = ["ticket", "sender", "created_at"]
|
310
|
-
|
306
|
+
|
311
307
|
fieldsets = [
|
312
308
|
('💬 Message Information', {
|
313
309
|
'fields': ['ticket', 'sender', 'text'],
|
@@ -318,11 +314,11 @@ class MessageAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
|
318
314
|
'classes': ('tab', 'collapse')
|
319
315
|
})
|
320
316
|
]
|
321
|
-
|
317
|
+
|
322
318
|
def has_add_permission(self, request):
|
323
319
|
"""Disable adding messages through admin - use chat interface instead."""
|
324
320
|
return False
|
325
|
-
|
321
|
+
|
326
322
|
def has_change_permission(self, request, obj=None):
|
327
323
|
"""Disable editing messages through admin."""
|
328
324
|
return False
|
@@ -332,7 +328,7 @@ class MessageAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
|
332
328
|
"""Display ticket information."""
|
333
329
|
if not obj.ticket:
|
334
330
|
return "—"
|
335
|
-
|
331
|
+
|
336
332
|
config = StatusBadgeConfig(show_icons=True, icon=Icons.CONFIRMATION_NUMBER)
|
337
333
|
return StatusBadge.create(
|
338
334
|
text=f"{obj.ticket.subject} ({str(obj.ticket.uuid)[:8]}...)",
|
@@ -345,7 +341,7 @@ class MessageAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
|
345
341
|
"""Display sender with role indication."""
|
346
342
|
if not obj.sender:
|
347
343
|
return "—"
|
348
|
-
|
344
|
+
|
349
345
|
# Determine sender type and variant
|
350
346
|
if obj.sender.is_superuser:
|
351
347
|
variant = "danger"
|
@@ -356,7 +352,7 @@ class MessageAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
|
356
352
|
else:
|
357
353
|
variant = "info"
|
358
354
|
icon = Icons.PERSON
|
359
|
-
|
355
|
+
|
360
356
|
config = StatusBadgeConfig(show_icons=True, icon=icon)
|
361
357
|
return StatusBadge.create(
|
362
358
|
text=obj.sender.get_full_name() or obj.sender.username,
|
@@ -369,11 +365,11 @@ class MessageAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
|
369
365
|
"""Display message text preview."""
|
370
366
|
if not obj.text:
|
371
367
|
return "—"
|
372
|
-
|
368
|
+
|
373
369
|
preview = obj.text[:100]
|
374
370
|
if len(obj.text) > 100:
|
375
371
|
preview += "..."
|
376
|
-
|
372
|
+
|
377
373
|
return preview
|
378
374
|
|
379
375
|
@display(description="Created")
|
@@ -385,26 +381,26 @@ class MessageAdmin(OptimizedModelAdmin, DisplayMixin, ModelAdmin, ExportMixin):
|
|
385
381
|
def changelist_view(self, request, extra_context=None):
|
386
382
|
"""Add message statistics to changelist."""
|
387
383
|
extra_context = extra_context or {}
|
388
|
-
|
384
|
+
|
389
385
|
queryset = self.get_queryset(request)
|
390
386
|
stats = queryset.aggregate(
|
391
387
|
total_messages=Count('uuid'),
|
392
388
|
staff_messages=Count('uuid', filter=Q(sender__is_staff=True)),
|
393
389
|
user_messages=Count('uuid', filter=Q(sender__is_staff=False))
|
394
390
|
)
|
395
|
-
|
391
|
+
|
396
392
|
# Messages by ticket status
|
397
393
|
ticket_status_counts = dict(
|
398
394
|
queryset.values_list('ticket__status').annotate(
|
399
395
|
count=Count('uuid')
|
400
396
|
)
|
401
397
|
)
|
402
|
-
|
398
|
+
|
403
399
|
extra_context['message_stats'] = {
|
404
400
|
'total_messages': stats['total_messages'] or 0,
|
405
401
|
'staff_messages': stats['staff_messages'] or 0,
|
406
402
|
'user_messages': stats['user_messages'] or 0,
|
407
403
|
'ticket_status_counts': ticket_status_counts
|
408
404
|
}
|
409
|
-
|
405
|
+
|
410
406
|
return super().changelist_view(request, extra_context)
|
django_cfg/apps/support/admin.py
CHANGED
@@ -1,30 +1,31 @@
|
|
1
1
|
from django.contrib import admin
|
2
|
-
from unfold.admin import ModelAdmin, TabularInline
|
3
|
-
from unfold.decorators import action
|
4
|
-
from django.utils.timesince import timesince
|
5
|
-
from django.utils.html import format_html
|
6
|
-
from django.urls import reverse
|
7
|
-
from django.shortcuts import redirect
|
8
2
|
from django.http import HttpRequest
|
3
|
+
from django.shortcuts import redirect
|
4
|
+
from django.urls import reverse
|
5
|
+
from django.utils.html import format_html
|
6
|
+
from django.utils.timesince import timesince
|
9
7
|
from django.utils.translation import gettext_lazy as _
|
10
|
-
from .
|
11
|
-
from .
|
12
|
-
|
8
|
+
from unfold.admin import ModelAdmin, TabularInline
|
9
|
+
from unfold.decorators import action
|
10
|
+
|
11
|
+
from .admin_filters import MessageSenderEmailFilter, TicketUserEmailFilter, TicketUserNameFilter
|
12
|
+
from .models import Message, Ticket
|
13
|
+
|
13
14
|
|
14
15
|
class MessageInline(TabularInline):
|
15
16
|
"""Read-only inline for viewing messages. Use Chat interface for replies."""
|
16
|
-
|
17
|
+
|
17
18
|
model = Message
|
18
19
|
extra = 0
|
19
20
|
fields = ("sender_avatar", "created_at", "text")
|
20
21
|
readonly_fields = ("sender_avatar", "created_at", "text")
|
21
22
|
show_change_link = False
|
22
23
|
classes = ('collapse',)
|
23
|
-
|
24
|
+
|
24
25
|
def has_add_permission(self, request, obj=None):
|
25
26
|
"""Disable adding messages through admin - use chat interface instead."""
|
26
27
|
return False
|
27
|
-
|
28
|
+
|
28
29
|
def has_delete_permission(self, request, obj=None):
|
29
30
|
"""Disable deleting messages through admin."""
|
30
31
|
return False
|
@@ -39,7 +40,7 @@ class MessageInline(TabularInline):
|
|
39
40
|
else:
|
40
41
|
initials = obj.sender.__class__.objects.get_initials(obj.sender)
|
41
42
|
bg_color = '#0d6efd' if obj.sender.is_staff else '#6f42c1' if obj.sender.is_superuser else '#198754'
|
42
|
-
|
43
|
+
|
43
44
|
return format_html(
|
44
45
|
'<div style="width: 24px; height: 24px; border-radius: 50%; background: {}; '
|
45
46
|
'color: white; display: flex; align-items: center; justify-content: center; '
|
@@ -97,7 +98,7 @@ class TicketAdmin(ModelAdmin):
|
|
97
98
|
else:
|
98
99
|
initials = obj.user.__class__.objects.get_initials(obj.user)
|
99
100
|
bg_color = '#0d6efd' if obj.user.is_staff else '#6f42c1' if obj.user.is_superuser else '#198754'
|
100
|
-
|
101
|
+
|
101
102
|
return format_html(
|
102
103
|
'<div style="width: 32px; height: 32px; border-radius: 50%; background: {}; '
|
103
104
|
'color: white; display: flex; align-items: center; justify-content: center; '
|
@@ -181,7 +182,7 @@ class MessageAdmin(ModelAdmin):
|
|
181
182
|
else:
|
182
183
|
initials = obj.sender.__class__.objects.get_initials(obj.sender)
|
183
184
|
bg_color = '#0d6efd' if obj.sender.is_staff else '#6f42c1' if obj.sender.is_superuser else '#198754'
|
184
|
-
|
185
|
+
|
185
186
|
return format_html(
|
186
187
|
'<div style="width: 32px; height: 32px; border-radius: 50%; background: {}; '
|
187
188
|
'color: white; display: flex; align-items: center; justify-content: center; '
|
django_cfg/apps/support/apps.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
from django.db import models
|
2
1
|
import threading
|
3
|
-
|
4
2
|
from typing import TYPE_CHECKING
|
5
3
|
|
4
|
+
from django.db import models
|
5
|
+
|
6
6
|
if TYPE_CHECKING:
|
7
7
|
# Only for type checking
|
8
8
|
from django_cfg.apps.support.models import Message
|
@@ -12,10 +12,10 @@ class MessageManager(models.Manager):
|
|
12
12
|
def send_support_reply_email(self, message: "Message"):
|
13
13
|
"""Send email notification when support replies to a ticket."""
|
14
14
|
from ..utils.support_email_service import SupportEmailService
|
15
|
-
|
15
|
+
|
16
16
|
ticket = message.ticket
|
17
17
|
user = ticket.user
|
18
|
-
|
18
|
+
|
19
19
|
# Don't send email to yourself
|
20
20
|
if message.sender == ticket.user:
|
21
21
|
return
|
@@ -1,10 +1,11 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
1
3
|
from django.db import models
|
2
4
|
from django.db.models import QuerySet
|
3
|
-
from typing import TYPE_CHECKING
|
4
5
|
|
5
6
|
if TYPE_CHECKING:
|
6
7
|
# Only for type checking
|
7
|
-
|
8
|
+
pass
|
8
9
|
|
9
10
|
class TicketManager(models.Manager):
|
10
11
|
def _count_unanswered_messages_for_user_in_tickets(self, user, tickets) -> int:
|
@@ -16,30 +17,30 @@ class TicketManager(models.Manager):
|
|
16
17
|
2. Check if there's an admin message after the last user message
|
17
18
|
"""
|
18
19
|
from django_cfg.apps.support.models import Message
|
19
|
-
|
20
|
+
|
20
21
|
unanswered_count = 0
|
21
|
-
|
22
|
+
|
22
23
|
for ticket in tickets:
|
23
24
|
messages: QuerySet[Message] = ticket.messages.order_by('created_at')
|
24
|
-
|
25
|
+
|
25
26
|
# Find the last user message in this ticket
|
26
27
|
last_user_message = messages.filter(sender=user).order_by('-created_at').first()
|
27
|
-
|
28
|
+
|
28
29
|
print(f"DEBUG: Ticket {ticket.uuid}")
|
29
30
|
print(f"DEBUG: Last user message: {last_user_message}")
|
30
|
-
|
31
|
+
|
31
32
|
if last_user_message:
|
32
33
|
# Check if there's an admin message after the last user message
|
33
34
|
admin_message_after = messages.filter(
|
34
35
|
sender__is_staff=True, # Admin messages
|
35
36
|
created_at__gt=last_user_message.created_at
|
36
37
|
).order_by('-created_at').first()
|
37
|
-
|
38
|
+
|
38
39
|
if admin_message_after:
|
39
40
|
print(f"DEBUG: Latest admin message after user: {admin_message_after.sender.username}: {admin_message_after.text[:50]}... ({admin_message_after.created_at})")
|
40
41
|
unanswered_count += 1
|
41
42
|
else:
|
42
|
-
print(
|
43
|
+
print("DEBUG: No admin messages after user message")
|
43
44
|
else:
|
44
45
|
# If user never sent a message, check if there are any admin messages
|
45
46
|
admin_messages_count = messages.filter(sender__is_staff=True).count()
|
@@ -47,8 +48,8 @@ class TicketManager(models.Manager):
|
|
47
48
|
print(f"DEBUG: User never sent message, but there are {admin_messages_count} admin messages")
|
48
49
|
unanswered_count += 1
|
49
50
|
else:
|
50
|
-
print(
|
51
|
-
|
51
|
+
print("DEBUG: User never sent message, no admin messages")
|
52
|
+
|
52
53
|
print(f"DEBUG: Total unanswered count: {unanswered_count}")
|
53
54
|
return unanswered_count
|
54
55
|
|
@@ -64,4 +65,4 @@ class TicketManager(models.Manager):
|
|
64
65
|
"""
|
65
66
|
Count unanswered messages for a specific ticket.
|
66
67
|
"""
|
67
|
-
return self._count_unanswered_messages_for_user_in_tickets(ticket.user, [ticket])
|
68
|
+
return self._count_unanswered_messages_for_user_in_tickets(ticket.user, [ticket])
|
@@ -1,7 +1,9 @@
|
|
1
1
|
from typing import Optional
|
2
|
-
|
2
|
+
|
3
3
|
from django.contrib.auth import get_user_model
|
4
|
-
from
|
4
|
+
from rest_framework import serializers
|
5
|
+
|
6
|
+
from .models import Message, Ticket
|
5
7
|
|
6
8
|
User = get_user_model()
|
7
9
|
|
@@ -1,13 +1,15 @@
|
|
1
|
-
from django.db.models.signals import post_save
|
2
|
-
from django.dispatch import receiver
|
3
|
-
import traceback
|
4
1
|
import logging
|
5
2
|
import socket
|
3
|
+
import traceback
|
6
4
|
from smtplib import SMTPException
|
7
5
|
|
6
|
+
from django.db.models.signals import post_save
|
7
|
+
from django.dispatch import receiver
|
8
|
+
|
9
|
+
from django_cfg.modules.django_telegram import DjangoTelegram
|
10
|
+
|
8
11
|
from .models import Message, Ticket
|
9
12
|
from .utils.support_email_service import SupportEmailService
|
10
|
-
from django_cfg.modules.django_telegram import DjangoTelegram
|
11
13
|
|
12
14
|
logger = logging.getLogger(__name__)
|
13
15
|
|
@@ -15,14 +17,14 @@ logger = logging.getLogger(__name__)
|
|
15
17
|
def notify_on_message(sender, instance: Message, created: bool, **kwargs):
|
16
18
|
"""Send notifications when a new message is created."""
|
17
19
|
logger.info(f"🔔 Signal triggered: Message {instance.uuid} created={created}")
|
18
|
-
|
20
|
+
|
19
21
|
if not created:
|
20
22
|
logger.info(" ⏭️ Not a new message, skipping")
|
21
23
|
return
|
22
24
|
|
23
25
|
ticket = instance.ticket
|
24
26
|
user = ticket.user
|
25
|
-
|
27
|
+
|
26
28
|
logger.info(f" 📝 Message from: {instance.sender.username} (is_staff: {instance.sender.is_staff})")
|
27
29
|
logger.info(f" 🎫 Ticket author: {user.username}")
|
28
30
|
logger.info(f" 📧 Is from author: {instance.is_from_author}")
|
@@ -33,10 +35,10 @@ def notify_on_message(sender, instance: Message, created: bool, **kwargs):
|
|
33
35
|
try:
|
34
36
|
email_service = SupportEmailService(user)
|
35
37
|
email_service.send_support_reply_email(instance)
|
36
|
-
logger.info(
|
38
|
+
logger.info(" 📬 Email sent successfully!")
|
37
39
|
except (socket.timeout, TimeoutError, SMTPException) as e:
|
38
40
|
logger.warning(f" ⚠️ Email service timeout/error: {e}")
|
39
|
-
logger.info(
|
41
|
+
logger.info(" 📝 Message processed successfully, email notification failed")
|
40
42
|
# Do not re-raise to prevent blocking the main process
|
41
43
|
except Exception as e:
|
42
44
|
logger.error(f" ❌ Failed to send email notification: {e}")
|
@@ -75,10 +77,10 @@ def notify_on_ticket_created(sender, instance: Ticket, created: bool, **kwargs):
|
|
75
77
|
try:
|
76
78
|
email_service = SupportEmailService(instance.user)
|
77
79
|
email_service.send_ticket_created_email(instance)
|
78
|
-
logger.info(
|
80
|
+
logger.info(" 📬 Ticket creation email sent successfully!")
|
79
81
|
except (socket.timeout, TimeoutError, SMTPException) as e:
|
80
82
|
logger.warning(f" ⚠️ Email service timeout/error for ticket creation: {e}")
|
81
|
-
logger.info(
|
83
|
+
logger.info(" 📝 Ticket created successfully, email notification failed")
|
82
84
|
except Exception as e:
|
83
85
|
logger.error(f" ❌ Failed to send ticket creation email: {e}")
|
84
86
|
logger.debug(f" 🔍 Exception details: {traceback.format_exc()}")
|
django_cfg/apps/support/urls.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
from django.urls import path
|
2
2
|
from rest_framework_nested import routers
|
3
|
-
|
4
|
-
from .views
|
3
|
+
|
4
|
+
from .views import MessageViewSet, TicketViewSet
|
5
5
|
from .views.admin import ticket_admin_chat_view
|
6
|
+
from .views.chat import send_message_ajax, ticket_chat_view
|
6
7
|
|
7
8
|
app_name = 'cfg_support'
|
8
9
|
|
@@ -20,4 +21,4 @@ chat_urlpatterns = [
|
|
20
21
|
path('admin/chat/<uuid:ticket_uuid>/', ticket_admin_chat_view, name='ticket-admin-chat'),
|
21
22
|
]
|
22
23
|
|
23
|
-
urlpatterns = router.urls + tickets_router.urls + chat_urlpatterns
|
24
|
+
urlpatterns = router.urls + tickets_router.urls + chat_urlpatterns
|
@@ -3,7 +3,9 @@ Support Email Service - Email notifications for support operations
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import logging
|
6
|
+
|
6
7
|
from django.contrib.auth import get_user_model
|
8
|
+
|
7
9
|
from django_cfg.modules.django_email import DjangoEmailService
|
8
10
|
|
9
11
|
User = get_user_model()
|
@@ -15,7 +17,7 @@ class SupportEmailService:
|
|
15
17
|
|
16
18
|
def __init__(self, user: User):
|
17
19
|
self.user = user
|
18
|
-
|
20
|
+
|
19
21
|
def _get_ticket_url(self, ticket_uuid: str) -> str:
|
20
22
|
"""Get ticket URL from configuration."""
|
21
23
|
try:
|
@@ -42,7 +44,7 @@ class SupportEmailService:
|
|
42
44
|
):
|
43
45
|
"""Private method for sending templated emails."""
|
44
46
|
email_service = DjangoEmailService()
|
45
|
-
|
47
|
+
|
46
48
|
# Prepare context for template
|
47
49
|
context = {
|
48
50
|
"user": self.user,
|
@@ -54,7 +56,7 @@ class SupportEmailService:
|
|
54
56
|
"button_text": button_text,
|
55
57
|
"button_url": button_url,
|
56
58
|
}
|
57
|
-
|
59
|
+
|
58
60
|
email_service.send_template(
|
59
61
|
subject=subject,
|
60
62
|
template_name=template_name,
|
@@ -76,11 +78,11 @@ class SupportEmailService:
|
|
76
78
|
def send_support_reply_email(self, message):
|
77
79
|
"""Send email notification when support replies to a ticket."""
|
78
80
|
ticket = message.ticket
|
79
|
-
|
81
|
+
|
80
82
|
# Don't send email to yourself
|
81
83
|
if message.sender == ticket.user:
|
82
84
|
return
|
83
|
-
|
85
|
+
|
84
86
|
self._send_email(
|
85
87
|
subject=f"Support Reply: {ticket.subject}",
|
86
88
|
main_text="You have received a reply from our support team.",
|
@@ -94,13 +96,13 @@ class SupportEmailService:
|
|
94
96
|
"""Send email notification when ticket status changes."""
|
95
97
|
status_colors = {
|
96
98
|
'open': '#28a745',
|
97
|
-
'in_progress': '#ffc107',
|
99
|
+
'in_progress': '#ffc107',
|
98
100
|
'resolved': '#17a2b8',
|
99
101
|
'closed': '#6c757d',
|
100
102
|
}
|
101
|
-
|
103
|
+
|
102
104
|
color = status_colors.get(new_status, '#6c757d')
|
103
|
-
|
105
|
+
|
104
106
|
self._send_email(
|
105
107
|
subject=f"Ticket Status Updated: {ticket.subject}",
|
106
108
|
main_text=f"Your ticket status has been updated from '{old_status}' to '{new_status}'.",
|
@@ -115,7 +117,7 @@ class SupportEmailService:
|
|
115
117
|
self._send_email(
|
116
118
|
subject=f"Ticket Resolved: {ticket.subject}",
|
117
119
|
main_text="Great news! Your support ticket has been resolved.",
|
118
|
-
main_html_content=
|
120
|
+
main_html_content='<div style="background: #e8f5e8; padding: 15px; border-left: 4px solid #28a745; margin: 15px 0;"><strong>✅ Ticket Resolved</strong><br>Your issue has been successfully resolved by our support team.</div>',
|
119
121
|
secondary_text="If you're satisfied with the resolution, no further action is needed. If you need additional help, feel free to reply to reopen the ticket.",
|
120
122
|
button_text="View Resolution",
|
121
123
|
button_url=self._get_ticket_url(ticket.uuid),
|
@@ -7,13 +7,13 @@ Decomposed views for better organization:
|
|
7
7
|
- admin.py: Admin-specific views
|
8
8
|
"""
|
9
9
|
|
10
|
-
from .api import TicketViewSet, MessageViewSet
|
11
|
-
from .chat import ticket_chat_view, send_message_ajax
|
12
10
|
from .admin import ticket_admin_chat_view
|
11
|
+
from .api import MessageViewSet, TicketViewSet
|
12
|
+
from .chat import send_message_ajax, ticket_chat_view
|
13
13
|
|
14
14
|
__all__ = [
|
15
15
|
'TicketViewSet',
|
16
|
-
'MessageViewSet',
|
16
|
+
'MessageViewSet',
|
17
17
|
'ticket_chat_view',
|
18
18
|
'send_message_ajax',
|
19
19
|
'ticket_admin_chat_view',
|