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
@@ -2,10 +2,10 @@
|
|
2
2
|
DRF Serializers for newsletter application.
|
3
3
|
"""
|
4
4
|
|
5
|
-
from rest_framework import serializers
|
6
5
|
from django.contrib.auth import get_user_model
|
6
|
+
from rest_framework import serializers
|
7
7
|
|
8
|
-
from .models import
|
8
|
+
from .models import EmailLog, Newsletter, NewsletterCampaign, NewsletterSubscription
|
9
9
|
|
10
10
|
User = get_user_model()
|
11
11
|
|
@@ -14,7 +14,7 @@ class NewsletterSerializer(serializers.ModelSerializer):
|
|
14
14
|
"""Serializer for Newsletter model."""
|
15
15
|
|
16
16
|
subscribers_count = serializers.IntegerField(read_only=True)
|
17
|
-
|
17
|
+
|
18
18
|
class Meta:
|
19
19
|
model = Newsletter
|
20
20
|
fields = [
|
@@ -26,10 +26,10 @@ class NewsletterSerializer(serializers.ModelSerializer):
|
|
26
26
|
|
27
27
|
class NewsletterSubscriptionSerializer(serializers.ModelSerializer):
|
28
28
|
"""Serializer for NewsletterSubscription model."""
|
29
|
-
|
29
|
+
|
30
30
|
newsletter_title = serializers.CharField(source='newsletter.title', read_only=True)
|
31
31
|
user_email = serializers.CharField(source='user.email', read_only=True)
|
32
|
-
|
32
|
+
|
33
33
|
class Meta:
|
34
34
|
model = NewsletterSubscription
|
35
35
|
fields = [
|
@@ -43,20 +43,20 @@ class NewsletterSubscriptionSerializer(serializers.ModelSerializer):
|
|
43
43
|
|
44
44
|
class SubscribeSerializer(serializers.Serializer):
|
45
45
|
"""Simple serializer for newsletter subscription."""
|
46
|
-
|
46
|
+
|
47
47
|
newsletter_id = serializers.IntegerField()
|
48
48
|
email = serializers.EmailField()
|
49
49
|
|
50
50
|
|
51
51
|
class UnsubscribeSerializer(serializers.Serializer):
|
52
52
|
"""Simple serializer for unsubscribe."""
|
53
|
-
|
53
|
+
|
54
54
|
subscription_id = serializers.IntegerField()
|
55
55
|
|
56
56
|
|
57
57
|
class TestEmailSerializer(serializers.Serializer):
|
58
58
|
"""Simple serializer for test email."""
|
59
|
-
|
59
|
+
|
60
60
|
email = serializers.EmailField()
|
61
61
|
subject = serializers.CharField(max_length=255, default="Django CFG Newsletter Test")
|
62
62
|
message = serializers.CharField(default="This is a test email from Django CFG Newsletter.")
|
@@ -64,9 +64,9 @@ class TestEmailSerializer(serializers.Serializer):
|
|
64
64
|
|
65
65
|
class NewsletterCampaignSerializer(serializers.ModelSerializer):
|
66
66
|
"""Serializer for NewsletterCampaign model."""
|
67
|
-
|
67
|
+
|
68
68
|
newsletter_title = serializers.CharField(source='newsletter.title', read_only=True)
|
69
|
-
|
69
|
+
|
70
70
|
class Meta:
|
71
71
|
model = NewsletterCampaign
|
72
72
|
fields = [
|
@@ -81,16 +81,16 @@ class NewsletterCampaignSerializer(serializers.ModelSerializer):
|
|
81
81
|
|
82
82
|
class SendCampaignSerializer(serializers.Serializer):
|
83
83
|
"""Simple serializer for sending campaign."""
|
84
|
-
|
84
|
+
|
85
85
|
campaign_id = serializers.IntegerField()
|
86
86
|
|
87
87
|
|
88
88
|
class EmailLogSerializer(serializers.ModelSerializer):
|
89
89
|
"""Serializer for EmailLog model."""
|
90
|
-
|
90
|
+
|
91
91
|
user_email = serializers.CharField(source='user.email', read_only=True)
|
92
92
|
newsletter_title = serializers.CharField(source='newsletter.title', read_only=True)
|
93
|
-
|
93
|
+
|
94
94
|
class Meta:
|
95
95
|
model = EmailLog
|
96
96
|
fields = [
|
@@ -5,12 +5,14 @@ Uses the built-in DjangoEmailService for sending emails with proper logging.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import logging
|
8
|
-
from typing import
|
8
|
+
from typing import Any, Dict, List, Optional
|
9
|
+
|
9
10
|
from django.contrib.auth import get_user_model
|
10
11
|
from django.utils import timezone
|
11
12
|
|
12
13
|
from django_cfg.modules.django_email import DjangoEmailService
|
13
|
-
|
14
|
+
|
15
|
+
from ..models import EmailLog, Newsletter, NewsletterSubscription
|
14
16
|
|
15
17
|
User = get_user_model()
|
16
18
|
logger = logging.getLogger(__name__)
|
@@ -18,16 +20,16 @@ logger = logging.getLogger(__name__)
|
|
18
20
|
|
19
21
|
class NewsletterEmailService:
|
20
22
|
"""Email service for newsletter application using DjangoEmailService."""
|
21
|
-
|
23
|
+
|
22
24
|
def __init__(self):
|
23
25
|
"""Initialize the email service."""
|
24
26
|
self.email_service = DjangoEmailService()
|
25
|
-
|
27
|
+
|
26
28
|
def _create_email_log(
|
27
|
-
self,
|
28
|
-
recipient: str,
|
29
|
-
subject: str,
|
30
|
-
status: str,
|
29
|
+
self,
|
30
|
+
recipient: str,
|
31
|
+
subject: str,
|
32
|
+
status: str,
|
31
33
|
newsletter: Optional[Newsletter] = None,
|
32
34
|
campaign = None
|
33
35
|
) -> EmailLog:
|
@@ -46,14 +48,14 @@ class NewsletterEmailService:
|
|
46
48
|
"""
|
47
49
|
try:
|
48
50
|
from django.utils import timezone
|
49
|
-
|
51
|
+
|
50
52
|
# Try to find user by email
|
51
53
|
user = None
|
52
54
|
try:
|
53
55
|
user = User.objects.get(email=recipient)
|
54
56
|
except User.DoesNotExist:
|
55
57
|
pass
|
56
|
-
|
58
|
+
|
57
59
|
log_data = {
|
58
60
|
'user': user,
|
59
61
|
'newsletter': newsletter,
|
@@ -61,18 +63,18 @@ class NewsletterEmailService:
|
|
61
63
|
'recipient': recipient,
|
62
64
|
'subject': subject,
|
63
65
|
'status': status,
|
64
|
-
'body':
|
66
|
+
'body': "Newsletter email sent via campaign"
|
65
67
|
}
|
66
|
-
|
68
|
+
|
67
69
|
# Add sent_at for successful emails
|
68
70
|
if status == EmailLog.EmailLogStatus.SENT:
|
69
71
|
log_data['sent_at'] = timezone.now()
|
70
|
-
|
72
|
+
|
71
73
|
return EmailLog.objects.create(**log_data)
|
72
74
|
except Exception as e:
|
73
75
|
logger.error(f"Failed to create email log: {e}")
|
74
76
|
raise
|
75
|
-
|
77
|
+
|
76
78
|
def send_newsletter_email(
|
77
79
|
self,
|
78
80
|
newsletter: Newsletter,
|
@@ -133,7 +135,7 @@ class NewsletterEmailService:
|
|
133
135
|
'sent_count': 0,
|
134
136
|
'failed_count': 0
|
135
137
|
}
|
136
|
-
|
138
|
+
|
137
139
|
if not emails:
|
138
140
|
return {
|
139
141
|
'success': False,
|
@@ -141,7 +143,7 @@ class NewsletterEmailService:
|
|
141
143
|
'sent_count': 0,
|
142
144
|
'failed_count': 0
|
143
145
|
}
|
144
|
-
|
146
|
+
|
145
147
|
# Use the optimized send_bulk_email method with tracking
|
146
148
|
result = self.send_bulk_email(
|
147
149
|
recipients=emails,
|
@@ -157,17 +159,17 @@ class NewsletterEmailService:
|
|
157
159
|
newsletter=newsletter,
|
158
160
|
campaign=campaign
|
159
161
|
)
|
160
|
-
|
162
|
+
|
161
163
|
# Add newsletter-specific context to the result
|
162
164
|
result.update({
|
163
165
|
'newsletter_id': newsletter.id,
|
164
166
|
'newsletter_title': newsletter.title
|
165
167
|
})
|
166
|
-
|
168
|
+
|
167
169
|
logger.info(f"Newsletter '{newsletter.title}' sent to {len(emails)} recipients, {result['sent_count']} successful")
|
168
|
-
|
170
|
+
|
169
171
|
return result
|
170
|
-
|
172
|
+
|
171
173
|
except Exception as e:
|
172
174
|
logger.error(f"Failed to send newsletter emails: {e}")
|
173
175
|
return {
|
@@ -176,7 +178,7 @@ class NewsletterEmailService:
|
|
176
178
|
'sent_count': 0,
|
177
179
|
'failed_count': 0
|
178
180
|
}
|
179
|
-
|
181
|
+
|
180
182
|
def send_subscription_welcome_email(self, subscription: NewsletterSubscription) -> bool:
|
181
183
|
"""
|
182
184
|
Send welcome email to new newsletter subscriber.
|
@@ -190,7 +192,7 @@ class NewsletterEmailService:
|
|
190
192
|
try:
|
191
193
|
context = {
|
192
194
|
'email_title': f"Welcome to {subscription.newsletter.title}",
|
193
|
-
'greeting':
|
195
|
+
'greeting': "Hello",
|
194
196
|
'main_text': f"Thank you for subscribing to our newsletter <strong>{subscription.newsletter.title}</strong>!",
|
195
197
|
'main_html_content': f"""
|
196
198
|
<p>You'll receive updates and news directly to your inbox at <strong>{subscription.email}</strong>.</p>
|
@@ -199,7 +201,7 @@ class NewsletterEmailService:
|
|
199
201
|
""",
|
200
202
|
'secondary_text': f'If you no longer wish to receive these emails, you can <a href="/mailer/unsubscribe/{subscription.id}/">unsubscribe here</a>.'
|
201
203
|
}
|
202
|
-
|
204
|
+
|
203
205
|
self.email_service.send_template(
|
204
206
|
subject=f"Welcome to {subscription.newsletter.title}",
|
205
207
|
template_name="emails/base_email",
|
@@ -207,14 +209,14 @@ class NewsletterEmailService:
|
|
207
209
|
recipient_list=[subscription.email],
|
208
210
|
fail_silently=False
|
209
211
|
)
|
210
|
-
|
212
|
+
|
211
213
|
logger.info(f"Welcome email sent to {subscription.email}")
|
212
214
|
return True
|
213
|
-
|
215
|
+
|
214
216
|
except Exception as e:
|
215
217
|
logger.error(f"Failed to send welcome email to {subscription.email}: {e}")
|
216
218
|
return False
|
217
|
-
|
219
|
+
|
218
220
|
def send_unsubscribe_confirmation_email(self, subscription: NewsletterSubscription) -> bool:
|
219
221
|
"""
|
220
222
|
Send unsubscribe confirmation email.
|
@@ -228,7 +230,7 @@ class NewsletterEmailService:
|
|
228
230
|
try:
|
229
231
|
context = {
|
230
232
|
'email_title': "Unsubscribe Confirmation",
|
231
|
-
'greeting':
|
233
|
+
'greeting': "Hello",
|
232
234
|
'main_text': f"You have been successfully unsubscribed from <strong>{subscription.newsletter.title}</strong>.",
|
233
235
|
'main_html_content': f"""
|
234
236
|
<p>Your email address <strong>{subscription.email}</strong> will no longer receive emails from this newsletter.</p>
|
@@ -236,7 +238,7 @@ class NewsletterEmailService:
|
|
236
238
|
<p>We're sorry to see you go!</p>
|
237
239
|
"""
|
238
240
|
}
|
239
|
-
|
241
|
+
|
240
242
|
self.email_service.send_template(
|
241
243
|
subject=f"Unsubscribed from {subscription.newsletter.title}",
|
242
244
|
template_name="emails/base_email",
|
@@ -244,14 +246,14 @@ class NewsletterEmailService:
|
|
244
246
|
recipient_list=[subscription.email],
|
245
247
|
fail_silently=False
|
246
248
|
)
|
247
|
-
|
249
|
+
|
248
250
|
logger.info(f"Unsubscribe confirmation sent to {subscription.email}")
|
249
251
|
return True
|
250
|
-
|
252
|
+
|
251
253
|
except Exception as e:
|
252
254
|
logger.error(f"Failed to send unsubscribe confirmation to {subscription.email}: {e}")
|
253
255
|
return False
|
254
|
-
|
256
|
+
|
255
257
|
def send_bulk_email(
|
256
258
|
self,
|
257
259
|
recipients: List[str],
|
@@ -289,7 +291,7 @@ class NewsletterEmailService:
|
|
289
291
|
"""
|
290
292
|
sent_count = 0
|
291
293
|
failed_count = 0
|
292
|
-
|
294
|
+
|
293
295
|
try:
|
294
296
|
for recipient in recipients:
|
295
297
|
try:
|
@@ -303,7 +305,7 @@ class NewsletterEmailService:
|
|
303
305
|
newsletter=newsletter,
|
304
306
|
campaign=campaign
|
305
307
|
)
|
306
|
-
|
308
|
+
|
307
309
|
context = {
|
308
310
|
'email_title': email_title,
|
309
311
|
'greeting': "Hello",
|
@@ -313,7 +315,7 @@ class NewsletterEmailService:
|
|
313
315
|
'button_url': button_url,
|
314
316
|
'secondary_text': secondary_text
|
315
317
|
}
|
316
|
-
|
318
|
+
|
317
319
|
# Send email with tracking if enabled
|
318
320
|
if enable_tracking and email_log:
|
319
321
|
success = self.email_service.send_template_with_tracking(
|
@@ -344,7 +346,7 @@ class NewsletterEmailService:
|
|
344
346
|
recipient_list=[recipient],
|
345
347
|
fail_silently=False
|
346
348
|
) > 0
|
347
|
-
|
349
|
+
|
348
350
|
# Update email log status
|
349
351
|
if enable_tracking and email_log:
|
350
352
|
if success:
|
@@ -360,26 +362,26 @@ class NewsletterEmailService:
|
|
360
362
|
sent_count += 1
|
361
363
|
else:
|
362
364
|
failed_count += 1
|
363
|
-
|
365
|
+
|
364
366
|
except Exception as e:
|
365
367
|
logger.error(f"Failed to send email to {recipient}: {e}")
|
366
368
|
failed_count += 1
|
367
|
-
|
369
|
+
|
368
370
|
# Update email log if exists
|
369
371
|
if enable_tracking and email_log:
|
370
372
|
email_log.status = EmailLog.EmailLogStatus.FAILED
|
371
373
|
email_log.error_message = str(e)
|
372
374
|
email_log.save()
|
373
|
-
|
375
|
+
|
374
376
|
logger.info(f"Bulk email sent to {len(recipients)} recipients, {sent_count} successful")
|
375
|
-
|
377
|
+
|
376
378
|
return {
|
377
379
|
'success': sent_count > 0,
|
378
380
|
'sent_count': sent_count,
|
379
381
|
'failed_count': failed_count,
|
380
382
|
'total_recipients': len(recipients)
|
381
383
|
}
|
382
|
-
|
384
|
+
|
383
385
|
except Exception as e:
|
384
386
|
logger.error(f"Failed to send bulk emails: {e}")
|
385
387
|
return {
|
@@ -5,9 +5,10 @@ Handles automatic email notifications and newsletter management.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import logging
|
8
|
+
|
9
|
+
from django.contrib.auth import get_user_model
|
8
10
|
from django.db.models.signals import post_save, pre_delete
|
9
11
|
from django.dispatch import receiver
|
10
|
-
from django.contrib.auth import get_user_model
|
11
12
|
|
12
13
|
from .models import Newsletter, NewsletterSubscription
|
13
14
|
|
@@ -59,7 +60,7 @@ def auto_subscribe_new_users(sender, instance, created, **kwargs):
|
|
59
60
|
try:
|
60
61
|
# Find newsletters with auto_subscribe enabled
|
61
62
|
auto_newsletters = Newsletter.objects.filter(auto_subscribe=True, is_active=True)
|
62
|
-
|
63
|
+
|
63
64
|
for newsletter in auto_newsletters:
|
64
65
|
NewsletterSubscription.objects.get_or_create(
|
65
66
|
newsletter=newsletter,
|
@@ -70,6 +71,6 @@ def auto_subscribe_new_users(sender, instance, created, **kwargs):
|
|
70
71
|
}
|
71
72
|
)
|
72
73
|
logger.info(f"Auto-subscribed {instance.email} to {newsletter.title}")
|
73
|
-
|
74
|
+
|
74
75
|
except Exception as e:
|
75
76
|
logger.error(f"Failed to auto-subscribe user {instance.email}: {e}")
|
@@ -2,8 +2,8 @@
|
|
2
2
|
DRF URLs for newsletter application.
|
3
3
|
"""
|
4
4
|
|
5
|
-
from django.urls import
|
6
|
-
|
5
|
+
from django.urls import include, path
|
6
|
+
|
7
7
|
from . import views
|
8
8
|
|
9
9
|
app_name = 'cfg_newsletter'
|
@@ -13,28 +13,28 @@ api_urlpatterns = [
|
|
13
13
|
# Newsletters
|
14
14
|
path('newsletters/', views.NewsletterListView.as_view(), name='newsletter-list'),
|
15
15
|
path('newsletters/<int:pk>/', views.NewsletterDetailView.as_view(), name='newsletter-detail'),
|
16
|
-
|
16
|
+
|
17
17
|
# Subscriptions
|
18
18
|
path('subscribe/', views.SubscribeView.as_view(), name='subscribe'),
|
19
19
|
path('unsubscribe/', views.UnsubscribeView.as_view(), name='unsubscribe'),
|
20
20
|
path('subscriptions/', views.SubscriptionListView.as_view(), name='subscription-list'),
|
21
|
-
|
21
|
+
|
22
22
|
# Campaigns
|
23
23
|
path('campaigns/', views.NewsletterCampaignListView.as_view(), name='campaign-list'),
|
24
24
|
path('campaigns/<int:pk>/', views.NewsletterCampaignDetailView.as_view(), name='campaign-detail'),
|
25
25
|
path('campaigns/send/', views.SendCampaignView.as_view(), name='send-campaign'),
|
26
|
-
|
26
|
+
|
27
27
|
# Email operations
|
28
28
|
path('test/', views.TestEmailView.as_view(), name='test-email'),
|
29
29
|
path('bulk/', views.BulkEmailView.as_view(), name='bulk-email'),
|
30
|
-
|
30
|
+
|
31
31
|
# Logs
|
32
32
|
path('logs/', views.EmailLogListView.as_view(), name='email-logs'),
|
33
33
|
]
|
34
34
|
|
35
35
|
urlpatterns = [
|
36
36
|
path('', include(api_urlpatterns)),
|
37
|
-
|
37
|
+
|
38
38
|
# Tracking endpoints (no auth required) - accept any string to handle invalid UUIDs gracefully
|
39
39
|
path('track/open/<str:email_log_id>/', views.TrackEmailOpenView.as_view(), name='track-open'),
|
40
40
|
path('track/click/<str:email_log_id>/', views.TrackEmailClickView.as_view(), name='track-click'),
|
@@ -3,44 +3,39 @@ Newsletter views package.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
# Newsletter views
|
6
|
-
from .newsletters import NewsletterListView, NewsletterDetailView
|
7
|
-
|
8
|
-
# Subscription views
|
9
|
-
from .subscriptions import SubscribeView, UnsubscribeView, SubscriptionListView
|
10
|
-
|
11
6
|
# Campaign views
|
12
|
-
from .campaigns import
|
13
|
-
NewsletterCampaignListView,
|
14
|
-
NewsletterCampaignDetailView,
|
15
|
-
SendCampaignView
|
16
|
-
)
|
7
|
+
from .campaigns import NewsletterCampaignDetailView, NewsletterCampaignListView, SendCampaignView
|
17
8
|
|
18
9
|
# Email views
|
19
|
-
from .emails import
|
10
|
+
from .emails import BulkEmailView, EmailLogListView, TestEmailView
|
11
|
+
from .newsletters import NewsletterDetailView, NewsletterListView
|
12
|
+
|
13
|
+
# Subscription views
|
14
|
+
from .subscriptions import SubscribeView, SubscriptionListView, UnsubscribeView
|
20
15
|
|
21
16
|
# Tracking views
|
22
|
-
from .tracking import
|
17
|
+
from .tracking import TrackEmailClickView, TrackEmailOpenView
|
23
18
|
|
24
19
|
__all__ = [
|
25
20
|
# Newsletters
|
26
21
|
'NewsletterListView',
|
27
22
|
'NewsletterDetailView',
|
28
|
-
|
23
|
+
|
29
24
|
# Subscriptions
|
30
|
-
'SubscribeView',
|
25
|
+
'SubscribeView',
|
31
26
|
'UnsubscribeView',
|
32
27
|
'SubscriptionListView',
|
33
|
-
|
28
|
+
|
34
29
|
# Campaigns
|
35
30
|
'NewsletterCampaignListView',
|
36
|
-
'NewsletterCampaignDetailView',
|
31
|
+
'NewsletterCampaignDetailView',
|
37
32
|
'SendCampaignView',
|
38
|
-
|
33
|
+
|
39
34
|
# Emails
|
40
35
|
'TestEmailView',
|
41
|
-
'BulkEmailView',
|
36
|
+
'BulkEmailView',
|
42
37
|
'EmailLogListView',
|
43
|
-
|
38
|
+
|
44
39
|
# Tracking
|
45
40
|
'TrackEmailOpenView',
|
46
41
|
'TrackEmailClickView',
|
@@ -2,27 +2,27 @@
|
|
2
2
|
Campaign views.
|
3
3
|
"""
|
4
4
|
|
5
|
+
from drf_spectacular.utils import extend_schema
|
5
6
|
from rest_framework import generics, status
|
6
|
-
from rest_framework.response import Response
|
7
7
|
from rest_framework.permissions import IsAuthenticated
|
8
|
-
from
|
8
|
+
from rest_framework.response import Response
|
9
9
|
|
10
10
|
from ..models import NewsletterCampaign
|
11
11
|
from ..serializers import (
|
12
|
+
ErrorResponseSerializer,
|
12
13
|
NewsletterCampaignSerializer,
|
13
|
-
SendCampaignSerializer,
|
14
14
|
SendCampaignResponseSerializer,
|
15
|
-
|
15
|
+
SendCampaignSerializer,
|
16
16
|
)
|
17
17
|
|
18
18
|
|
19
19
|
class NewsletterCampaignListView(generics.ListCreateAPIView):
|
20
20
|
"""List and create newsletter campaigns."""
|
21
|
-
|
21
|
+
|
22
22
|
queryset = NewsletterCampaign.objects.all()
|
23
23
|
serializer_class = NewsletterCampaignSerializer
|
24
24
|
permission_classes = [IsAuthenticated]
|
25
|
-
|
25
|
+
|
26
26
|
@extend_schema(
|
27
27
|
summary="List Newsletter Campaigns",
|
28
28
|
description="Get a list of all newsletter campaigns.",
|
@@ -31,7 +31,7 @@ class NewsletterCampaignListView(generics.ListCreateAPIView):
|
|
31
31
|
)
|
32
32
|
def get(self, request, *args, **kwargs):
|
33
33
|
return super().get(request, *args, **kwargs)
|
34
|
-
|
34
|
+
|
35
35
|
@extend_schema(
|
36
36
|
summary="Create Newsletter Campaign",
|
37
37
|
description="Create a new newsletter campaign.",
|
@@ -45,11 +45,11 @@ class NewsletterCampaignListView(generics.ListCreateAPIView):
|
|
45
45
|
|
46
46
|
class NewsletterCampaignDetailView(generics.RetrieveUpdateDestroyAPIView):
|
47
47
|
"""Retrieve, update, or delete a newsletter campaign."""
|
48
|
-
|
48
|
+
|
49
49
|
queryset = NewsletterCampaign.objects.all()
|
50
50
|
serializer_class = NewsletterCampaignSerializer
|
51
51
|
permission_classes = [IsAuthenticated]
|
52
|
-
|
52
|
+
|
53
53
|
@extend_schema(
|
54
54
|
summary="Get Campaign Details",
|
55
55
|
description="Retrieve details of a specific newsletter campaign.",
|
@@ -58,7 +58,7 @@ class NewsletterCampaignDetailView(generics.RetrieveUpdateDestroyAPIView):
|
|
58
58
|
)
|
59
59
|
def get(self, request, *args, **kwargs):
|
60
60
|
return super().get(request, *args, **kwargs)
|
61
|
-
|
61
|
+
|
62
62
|
@extend_schema(
|
63
63
|
summary="Update Campaign",
|
64
64
|
description="Update a newsletter campaign.",
|
@@ -68,7 +68,7 @@ class NewsletterCampaignDetailView(generics.RetrieveUpdateDestroyAPIView):
|
|
68
68
|
)
|
69
69
|
def put(self, request, *args, **kwargs):
|
70
70
|
return super().put(request, *args, **kwargs)
|
71
|
-
|
71
|
+
|
72
72
|
@extend_schema(
|
73
73
|
summary="Delete Campaign",
|
74
74
|
description="Delete a newsletter campaign.",
|
@@ -81,10 +81,10 @@ class NewsletterCampaignDetailView(generics.RetrieveUpdateDestroyAPIView):
|
|
81
81
|
|
82
82
|
class SendCampaignView(generics.CreateAPIView):
|
83
83
|
"""Send a newsletter campaign."""
|
84
|
-
|
84
|
+
|
85
85
|
serializer_class = SendCampaignSerializer
|
86
86
|
permission_classes = [IsAuthenticated]
|
87
|
-
|
87
|
+
|
88
88
|
@extend_schema(
|
89
89
|
summary="Send Newsletter Campaign",
|
90
90
|
description="Send a newsletter campaign to all subscribers.",
|
@@ -99,20 +99,20 @@ class SendCampaignView(generics.CreateAPIView):
|
|
99
99
|
def post(self, request, *args, **kwargs):
|
100
100
|
serializer = self.get_serializer(data=request.data)
|
101
101
|
serializer.is_valid(raise_exception=True)
|
102
|
-
|
102
|
+
|
103
103
|
campaign_id = serializer.validated_data['campaign_id']
|
104
|
-
|
104
|
+
|
105
105
|
try:
|
106
106
|
campaign = NewsletterCampaign.objects.get(id=campaign_id)
|
107
|
-
|
107
|
+
|
108
108
|
if campaign.status != NewsletterCampaign.CampaignStatus.DRAFT:
|
109
109
|
return Response(
|
110
110
|
{'success': False, 'error': 'Campaign is not in draft status'},
|
111
111
|
status=status.HTTP_400_BAD_REQUEST
|
112
112
|
)
|
113
|
-
|
113
|
+
|
114
114
|
success = campaign.send_campaign()
|
115
|
-
|
115
|
+
|
116
116
|
if success:
|
117
117
|
# Get updated campaign data
|
118
118
|
campaign.refresh_from_db()
|
@@ -130,7 +130,7 @@ class SendCampaignView(generics.CreateAPIView):
|
|
130
130
|
{'success': False, 'error': 'Failed to send campaign'},
|
131
131
|
status=status.HTTP_400_BAD_REQUEST
|
132
132
|
)
|
133
|
-
|
133
|
+
|
134
134
|
except NewsletterCampaign.DoesNotExist:
|
135
135
|
return Response(
|
136
136
|
{'success': False, 'error': 'Campaign not found'},
|