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
@@ -4,9 +4,11 @@ Subscription managers for the Universal Payment System v2.0.
|
|
4
4
|
Optimized querysets and managers for subscription and endpoint group operations.
|
5
5
|
"""
|
6
6
|
|
7
|
+
from datetime import timedelta
|
8
|
+
|
7
9
|
from django.db import models
|
8
10
|
from django.utils import timezone
|
9
|
-
|
11
|
+
|
10
12
|
from django_cfg.modules.django_logging import get_logger
|
11
13
|
|
12
14
|
logger = get_logger("subscription_managers")
|
@@ -18,23 +20,23 @@ class SubscriptionQuerySet(models.QuerySet):
|
|
18
20
|
|
19
21
|
Provides efficient queries for subscription management and access control.
|
20
22
|
"""
|
21
|
-
|
23
|
+
|
22
24
|
def optimized(self):
|
23
25
|
"""Prevent N+1 queries with select_related and prefetch_related."""
|
24
26
|
return self.select_related('user').prefetch_related('endpoint_groups')
|
25
|
-
|
27
|
+
|
26
28
|
def by_user(self, user):
|
27
29
|
"""Filter subscriptions by user."""
|
28
30
|
return self.filter(user=user)
|
29
|
-
|
31
|
+
|
30
32
|
def by_tier(self, tier):
|
31
33
|
"""Filter by subscription tier."""
|
32
34
|
return self.filter(tier=tier)
|
33
|
-
|
35
|
+
|
34
36
|
def by_status(self, status):
|
35
37
|
"""Filter by subscription status."""
|
36
38
|
return self.filter(status=status)
|
37
|
-
|
39
|
+
|
38
40
|
# Status-based filters
|
39
41
|
def active(self):
|
40
42
|
"""
|
@@ -46,19 +48,19 @@ class SubscriptionQuerySet(models.QuerySet):
|
|
46
48
|
status='active',
|
47
49
|
expires_at__gt=timezone.now()
|
48
50
|
)
|
49
|
-
|
51
|
+
|
50
52
|
def inactive(self):
|
51
53
|
"""Get inactive subscriptions."""
|
52
54
|
return self.filter(status='inactive')
|
53
|
-
|
55
|
+
|
54
56
|
def suspended(self):
|
55
57
|
"""Get suspended subscriptions."""
|
56
58
|
return self.filter(status='suspended')
|
57
|
-
|
59
|
+
|
58
60
|
def cancelled(self):
|
59
61
|
"""Get cancelled subscriptions."""
|
60
62
|
return self.filter(status='cancelled')
|
61
|
-
|
63
|
+
|
62
64
|
def expired(self):
|
63
65
|
"""
|
64
66
|
Get expired subscriptions.
|
@@ -66,7 +68,7 @@ class SubscriptionQuerySet(models.QuerySet):
|
|
66
68
|
Returns subscriptions where expires_at <= now, regardless of status.
|
67
69
|
"""
|
68
70
|
return self.filter(expires_at__lte=timezone.now())
|
69
|
-
|
71
|
+
|
70
72
|
def expiring_soon(self, days=7):
|
71
73
|
"""
|
72
74
|
Get subscriptions expiring in the next N days.
|
@@ -80,28 +82,28 @@ class SubscriptionQuerySet(models.QuerySet):
|
|
80
82
|
expires_at__gt=timezone.now(),
|
81
83
|
status='active'
|
82
84
|
)
|
83
|
-
|
85
|
+
|
84
86
|
# Tier-based filters
|
85
87
|
def free_tier(self):
|
86
88
|
"""Get free tier subscriptions."""
|
87
89
|
return self.filter(tier='free')
|
88
|
-
|
90
|
+
|
89
91
|
def basic_tier(self):
|
90
92
|
"""Get basic tier subscriptions."""
|
91
93
|
return self.filter(tier='basic')
|
92
|
-
|
94
|
+
|
93
95
|
def pro_tier(self):
|
94
96
|
"""Get pro tier subscriptions."""
|
95
97
|
return self.filter(tier='pro')
|
96
|
-
|
98
|
+
|
97
99
|
def enterprise_tier(self):
|
98
100
|
"""Get enterprise tier subscriptions."""
|
99
101
|
return self.filter(tier='enterprise')
|
100
|
-
|
102
|
+
|
101
103
|
def paid_tiers(self):
|
102
104
|
"""Get paid tier subscriptions (non-free)."""
|
103
105
|
return self.exclude(tier='free')
|
104
|
-
|
106
|
+
|
105
107
|
# Time-based filters
|
106
108
|
def created_recently(self, days=30):
|
107
109
|
"""
|
@@ -112,7 +114,7 @@ class SubscriptionQuerySet(models.QuerySet):
|
|
112
114
|
"""
|
113
115
|
since = timezone.now() - timedelta(days=days)
|
114
116
|
return self.filter(created_at__gte=since)
|
115
|
-
|
117
|
+
|
116
118
|
def renewed_recently(self, days=30):
|
117
119
|
"""
|
118
120
|
Get subscriptions renewed in the last N days.
|
@@ -122,16 +124,16 @@ class SubscriptionQuerySet(models.QuerySet):
|
|
122
124
|
"""
|
123
125
|
since = timezone.now() - timedelta(days=days)
|
124
126
|
return self.filter(updated_at__gte=since, status='active')
|
125
|
-
|
127
|
+
|
126
128
|
# Usage-based filters
|
127
129
|
def with_usage(self):
|
128
130
|
"""Get subscriptions that have been used (total_requests > 0)."""
|
129
131
|
return self.filter(total_requests__gt=0)
|
130
|
-
|
132
|
+
|
131
133
|
def without_usage(self):
|
132
134
|
"""Get subscriptions that have never been used."""
|
133
135
|
return self.filter(total_requests=0)
|
134
|
-
|
136
|
+
|
135
137
|
def high_usage(self, threshold=1000):
|
136
138
|
"""
|
137
139
|
Get subscriptions with high usage.
|
@@ -140,7 +142,7 @@ class SubscriptionQuerySet(models.QuerySet):
|
|
140
142
|
threshold: Request count threshold (default: 1000)
|
141
143
|
"""
|
142
144
|
return self.filter(total_requests__gte=threshold)
|
143
|
-
|
145
|
+
|
144
146
|
def recent_usage(self, hours=24):
|
145
147
|
"""
|
146
148
|
Get subscriptions used in the last N hours.
|
@@ -150,16 +152,16 @@ class SubscriptionQuerySet(models.QuerySet):
|
|
150
152
|
"""
|
151
153
|
since = timezone.now() - timedelta(hours=hours)
|
152
154
|
return self.filter(last_request_at__gte=since)
|
153
|
-
|
155
|
+
|
154
156
|
# Auto-renewal filters
|
155
157
|
def auto_renewing(self):
|
156
158
|
"""Get subscriptions with auto-renewal enabled."""
|
157
159
|
return self.filter(auto_renew=True)
|
158
|
-
|
160
|
+
|
159
161
|
def manual_renewal(self):
|
160
162
|
"""Get subscriptions with manual renewal."""
|
161
163
|
return self.filter(auto_renew=False)
|
162
|
-
|
164
|
+
|
163
165
|
# Endpoint access filters
|
164
166
|
def with_endpoint_access(self, endpoint_group_code):
|
165
167
|
"""
|
@@ -172,26 +174,26 @@ class SubscriptionQuerySet(models.QuerySet):
|
|
172
174
|
endpoint_groups__code=endpoint_group_code,
|
173
175
|
endpoint_groups__is_enabled=True
|
174
176
|
)
|
175
|
-
|
177
|
+
|
176
178
|
# Aggregation methods
|
177
179
|
def total_revenue(self):
|
178
180
|
"""Get total monthly revenue from active subscriptions."""
|
179
181
|
result = self.active().aggregate(total=models.Sum('monthly_cost_usd'))
|
180
182
|
return result['total'] or 0.0
|
181
|
-
|
183
|
+
|
182
184
|
def average_cost(self):
|
183
185
|
"""Get average monthly cost."""
|
184
186
|
result = self.aggregate(avg=models.Avg('monthly_cost_usd'))
|
185
187
|
return result['avg'] or 0.0
|
186
|
-
|
188
|
+
|
187
189
|
def count_by_tier(self):
|
188
190
|
"""Get count of subscriptions grouped by tier."""
|
189
191
|
return self.values('tier').annotate(count=models.Count('id')).order_by('tier')
|
190
|
-
|
192
|
+
|
191
193
|
def count_by_status(self):
|
192
194
|
"""Get count of subscriptions grouped by status."""
|
193
195
|
return self.values('status').annotate(count=models.Count('id')).order_by('status')
|
194
|
-
|
196
|
+
|
195
197
|
def usage_stats(self):
|
196
198
|
"""Get usage statistics."""
|
197
199
|
return self.aggregate(
|
@@ -207,41 +209,41 @@ class SubscriptionManager(models.Manager):
|
|
207
209
|
|
208
210
|
Provides high-level methods for subscription management and access control.
|
209
211
|
"""
|
210
|
-
|
212
|
+
|
211
213
|
def get_queryset(self):
|
212
214
|
"""Return optimized queryset by default."""
|
213
215
|
return SubscriptionQuerySet(self.model, using=self._db)
|
214
|
-
|
216
|
+
|
215
217
|
def optimized(self):
|
216
218
|
"""Get optimized queryset."""
|
217
219
|
return self.get_queryset().optimized()
|
218
|
-
|
220
|
+
|
219
221
|
# Status-based methods
|
220
222
|
def active(self):
|
221
223
|
"""Get active subscriptions."""
|
222
224
|
return self.get_queryset().active()
|
223
|
-
|
225
|
+
|
224
226
|
def expired(self):
|
225
227
|
"""Get expired subscriptions."""
|
226
228
|
return self.get_queryset().expired()
|
227
|
-
|
229
|
+
|
228
230
|
def expiring_soon(self, days=7):
|
229
231
|
"""Get subscriptions expiring soon."""
|
230
232
|
return self.get_queryset().expiring_soon(days)
|
231
|
-
|
233
|
+
|
232
234
|
# Tier-based methods
|
233
235
|
def by_tier(self, tier):
|
234
236
|
"""Get subscriptions by tier."""
|
235
237
|
return self.get_queryset().by_tier(tier)
|
236
|
-
|
238
|
+
|
237
239
|
def free_tier(self):
|
238
240
|
"""Get free tier subscriptions."""
|
239
241
|
return self.get_queryset().free_tier()
|
240
|
-
|
242
|
+
|
241
243
|
def paid_tiers(self):
|
242
244
|
"""Get paid tier subscriptions."""
|
243
245
|
return self.get_queryset().paid_tiers()
|
244
|
-
|
246
|
+
|
245
247
|
# User methods
|
246
248
|
def get_active_for_user(self, user):
|
247
249
|
"""
|
@@ -257,7 +259,7 @@ class SubscriptionManager(models.Manager):
|
|
257
259
|
return self.active().get(user=user)
|
258
260
|
except self.model.DoesNotExist:
|
259
261
|
return None
|
260
|
-
|
262
|
+
|
261
263
|
def has_active_subscription(self, user):
|
262
264
|
"""
|
263
265
|
Check if user has an active subscription.
|
@@ -269,7 +271,7 @@ class SubscriptionManager(models.Manager):
|
|
269
271
|
bool: True if user has active subscription
|
270
272
|
"""
|
271
273
|
return self.active().filter(user=user).exists()
|
272
|
-
|
274
|
+
|
273
275
|
def get_or_create_free_subscription(self, user):
|
274
276
|
"""
|
275
277
|
Get existing subscription or create free tier subscription for user.
|
@@ -284,17 +286,17 @@ class SubscriptionManager(models.Manager):
|
|
284
286
|
existing = self.get_active_for_user(user)
|
285
287
|
if existing:
|
286
288
|
return existing, False
|
287
|
-
|
289
|
+
|
288
290
|
# Create free subscription
|
289
291
|
subscription = self.model.create_free_subscription(user)
|
290
|
-
|
291
|
-
logger.info(
|
292
|
+
|
293
|
+
logger.info("Created free subscription for user", extra={
|
292
294
|
'user_id': user.id,
|
293
295
|
'subscription_id': str(subscription.id)
|
294
296
|
})
|
295
|
-
|
297
|
+
|
296
298
|
return subscription, True
|
297
|
-
|
299
|
+
|
298
300
|
# Access control methods
|
299
301
|
def check_endpoint_access(self, user, endpoint_group_code):
|
300
302
|
"""
|
@@ -310,9 +312,9 @@ class SubscriptionManager(models.Manager):
|
|
310
312
|
subscription = self.get_active_for_user(user)
|
311
313
|
if not subscription:
|
312
314
|
return False
|
313
|
-
|
315
|
+
|
314
316
|
return subscription.has_access_to_endpoint_group(endpoint_group_code)
|
315
|
-
|
317
|
+
|
316
318
|
def get_user_rate_limits(self, user):
|
317
319
|
"""
|
318
320
|
Get rate limits for user based on their subscription.
|
@@ -330,7 +332,7 @@ class SubscriptionManager(models.Manager):
|
|
330
332
|
'requests_per_day': 0,
|
331
333
|
'has_access': False
|
332
334
|
}
|
333
|
-
|
335
|
+
|
334
336
|
return {
|
335
337
|
'requests_per_hour': subscription.requests_per_hour,
|
336
338
|
'requests_per_day': subscription.requests_per_day,
|
@@ -338,7 +340,7 @@ class SubscriptionManager(models.Manager):
|
|
338
340
|
'tier': subscription.tier,
|
339
341
|
'expires_at': subscription.expires_at
|
340
342
|
}
|
341
|
-
|
343
|
+
|
342
344
|
# Maintenance methods
|
343
345
|
def cleanup_expired(self, dry_run=True):
|
344
346
|
"""
|
@@ -355,13 +357,13 @@ class SubscriptionManager(models.Manager):
|
|
355
357
|
status__in=['active', 'suspended']
|
356
358
|
)
|
357
359
|
count = expired_subscriptions.count()
|
358
|
-
|
360
|
+
|
359
361
|
if not dry_run and count > 0:
|
360
362
|
expired_subscriptions.update(status='expired')
|
361
363
|
logger.info(f"Marked {count} subscriptions as expired")
|
362
|
-
|
364
|
+
|
363
365
|
return count
|
364
|
-
|
366
|
+
|
365
367
|
def process_auto_renewals(self, dry_run=True):
|
366
368
|
"""
|
367
369
|
Process auto-renewal for subscriptions expiring soon.
|
@@ -379,14 +381,14 @@ class SubscriptionManager(models.Manager):
|
|
379
381
|
auto_renew=True,
|
380
382
|
status='active'
|
381
383
|
)
|
382
|
-
|
384
|
+
|
383
385
|
count = expiring_subscriptions.count()
|
384
|
-
|
386
|
+
|
385
387
|
if not dry_run and count > 0:
|
386
388
|
for subscription in expiring_subscriptions:
|
387
389
|
try:
|
388
390
|
subscription.renew(duration_days=30)
|
389
|
-
logger.info(
|
391
|
+
logger.info("Auto-renewed subscription", extra={
|
390
392
|
'subscription_id': str(subscription.id),
|
391
393
|
'user_id': subscription.user.id
|
392
394
|
})
|
@@ -395,9 +397,9 @@ class SubscriptionManager(models.Manager):
|
|
395
397
|
'subscription_id': str(subscription.id),
|
396
398
|
'user_id': subscription.user.id
|
397
399
|
})
|
398
|
-
|
400
|
+
|
399
401
|
return count
|
400
|
-
|
402
|
+
|
401
403
|
# Statistics methods
|
402
404
|
def get_subscription_stats(self, days=30):
|
403
405
|
"""
|
@@ -411,7 +413,7 @@ class SubscriptionManager(models.Manager):
|
|
411
413
|
"""
|
412
414
|
queryset = self.get_queryset()
|
413
415
|
recent_queryset = queryset.created_recently(days)
|
414
|
-
|
416
|
+
|
415
417
|
stats = {
|
416
418
|
'total_subscriptions': queryset.count(),
|
417
419
|
'active_subscriptions': queryset.active().count(),
|
@@ -425,15 +427,15 @@ class SubscriptionManager(models.Manager):
|
|
425
427
|
'auto_renewing': queryset.auto_renewing().count(),
|
426
428
|
'expiring_soon': queryset.expiring_soon(7).count(),
|
427
429
|
}
|
428
|
-
|
430
|
+
|
429
431
|
logger.info(f"Generated subscription stats for {days} days", extra={
|
430
432
|
'days': days,
|
431
433
|
'total_subscriptions': stats['total_subscriptions'],
|
432
434
|
'active_subscriptions': stats['active_subscriptions']
|
433
435
|
})
|
434
|
-
|
436
|
+
|
435
437
|
return stats
|
436
|
-
|
438
|
+
|
437
439
|
def get_tier_analytics(self):
|
438
440
|
"""
|
439
441
|
Get detailed analytics by subscription tier.
|
@@ -442,10 +444,10 @@ class SubscriptionManager(models.Manager):
|
|
442
444
|
dict: Tier-based analytics
|
443
445
|
"""
|
444
446
|
analytics = {}
|
445
|
-
|
447
|
+
|
446
448
|
for tier_code, tier_name in self.model.SubscriptionTier.choices:
|
447
449
|
tier_subscriptions = self.by_tier(tier_code)
|
448
|
-
|
450
|
+
|
449
451
|
analytics[tier_code] = {
|
450
452
|
'name': tier_name,
|
451
453
|
'total_count': tier_subscriptions.count(),
|
@@ -456,9 +458,9 @@ class SubscriptionManager(models.Manager):
|
|
456
458
|
)['avg'] or 0,
|
457
459
|
'conversion_rate': 0.0 # Would need additional logic for conversion tracking
|
458
460
|
}
|
459
|
-
|
461
|
+
|
460
462
|
return analytics
|
461
|
-
|
463
|
+
|
462
464
|
# Business logic methods
|
463
465
|
def activate_subscription(self, subscription_id):
|
464
466
|
"""
|
@@ -475,23 +477,23 @@ class SubscriptionManager(models.Manager):
|
|
475
477
|
subscription = self.get(id=subscription_id)
|
476
478
|
else:
|
477
479
|
subscription = subscription_id
|
478
|
-
|
480
|
+
|
479
481
|
subscription.status = subscription.model.SubscriptionStatus.ACTIVE
|
480
482
|
subscription.save(update_fields=['status', 'updated_at'])
|
481
|
-
|
482
|
-
logger.info(
|
483
|
+
|
484
|
+
logger.info("Subscription activated", extra={
|
483
485
|
'subscription_id': str(subscription.id),
|
484
486
|
'user_id': subscription.user.id
|
485
487
|
})
|
486
|
-
|
488
|
+
|
487
489
|
return True
|
488
|
-
|
490
|
+
|
489
491
|
except Exception as e:
|
490
492
|
logger.error(f"Failed to activate subscription: {e}", extra={
|
491
493
|
'subscription_id': str(subscription_id) if hasattr(subscription_id, 'id') else subscription_id
|
492
494
|
})
|
493
495
|
return False
|
494
|
-
|
496
|
+
|
495
497
|
def suspend_subscription(self, subscription_id, reason=None):
|
496
498
|
"""
|
497
499
|
Suspend subscription (business logic in manager).
|
@@ -508,24 +510,24 @@ class SubscriptionManager(models.Manager):
|
|
508
510
|
subscription = self.get(id=subscription_id)
|
509
511
|
else:
|
510
512
|
subscription = subscription_id
|
511
|
-
|
513
|
+
|
512
514
|
subscription.status = subscription.model.SubscriptionStatus.SUSPENDED
|
513
515
|
subscription.save(update_fields=['status', 'updated_at'])
|
514
|
-
|
515
|
-
logger.warning(
|
516
|
+
|
517
|
+
logger.warning("Subscription suspended", extra={
|
516
518
|
'subscription_id': str(subscription.id),
|
517
519
|
'user_id': subscription.user.id,
|
518
520
|
'reason': reason
|
519
521
|
})
|
520
|
-
|
522
|
+
|
521
523
|
return True
|
522
|
-
|
524
|
+
|
523
525
|
except Exception as e:
|
524
526
|
logger.error(f"Failed to suspend subscription: {e}", extra={
|
525
527
|
'subscription_id': str(subscription_id) if hasattr(subscription_id, 'id') else subscription_id
|
526
528
|
})
|
527
529
|
return False
|
528
|
-
|
530
|
+
|
529
531
|
def cancel_subscription(self, subscription_id, reason=None):
|
530
532
|
"""
|
531
533
|
Cancel subscription (business logic in manager).
|
@@ -542,24 +544,24 @@ class SubscriptionManager(models.Manager):
|
|
542
544
|
subscription = self.get(id=subscription_id)
|
543
545
|
else:
|
544
546
|
subscription = subscription_id
|
545
|
-
|
547
|
+
|
546
548
|
subscription.status = self.model.SubscriptionStatus.CANCELLED
|
547
549
|
subscription.save(update_fields=['status', 'updated_at'])
|
548
|
-
|
549
|
-
logger.info(
|
550
|
+
|
551
|
+
logger.info("Subscription cancelled", extra={
|
550
552
|
'subscription_id': str(subscription.id),
|
551
553
|
'user_id': subscription.user.id,
|
552
554
|
'reason': reason
|
553
555
|
})
|
554
|
-
|
556
|
+
|
555
557
|
return True
|
556
|
-
|
558
|
+
|
557
559
|
except Exception as e:
|
558
560
|
logger.error(f"Failed to cancel subscription: {e}", extra={
|
559
561
|
'subscription_id': str(subscription_id) if hasattr(subscription_id, 'id') else subscription_id
|
560
562
|
})
|
561
563
|
return False
|
562
|
-
|
564
|
+
|
563
565
|
def renew_subscription(self, subscription_id, duration_days=30):
|
564
566
|
"""
|
565
567
|
Renew subscription (business logic in manager).
|
@@ -576,9 +578,9 @@ class SubscriptionManager(models.Manager):
|
|
576
578
|
subscription = self.get(id=subscription_id)
|
577
579
|
else:
|
578
580
|
subscription = subscription_id
|
579
|
-
|
581
|
+
|
580
582
|
from datetime import timedelta
|
581
|
-
|
583
|
+
|
582
584
|
if subscription.expires_at <= timezone.now():
|
583
585
|
# If expired, start from now
|
584
586
|
subscription.starts_at = timezone.now()
|
@@ -586,25 +588,25 @@ class SubscriptionManager(models.Manager):
|
|
586
588
|
else:
|
587
589
|
# If not expired, extend from current expiration
|
588
590
|
subscription.expires_at += timedelta(days=duration_days)
|
589
|
-
|
591
|
+
|
590
592
|
subscription.status = self.model.SubscriptionStatus.ACTIVE
|
591
593
|
subscription.save(update_fields=['starts_at', 'expires_at', 'status', 'updated_at'])
|
592
|
-
|
593
|
-
logger.info(
|
594
|
+
|
595
|
+
logger.info("Subscription renewed", extra={
|
594
596
|
'subscription_id': str(subscription.id),
|
595
597
|
'user_id': subscription.user.id,
|
596
598
|
'duration_days': duration_days,
|
597
599
|
'new_expires_at': subscription.expires_at.isoformat()
|
598
600
|
})
|
599
|
-
|
601
|
+
|
600
602
|
return True
|
601
|
-
|
603
|
+
|
602
604
|
except Exception as e:
|
603
605
|
logger.error(f"Failed to renew subscription: {e}", extra={
|
604
606
|
'subscription_id': str(subscription_id) if hasattr(subscription_id, 'id') else subscription_id
|
605
607
|
})
|
606
608
|
return False
|
607
|
-
|
609
|
+
|
608
610
|
def increment_subscription_usage(self, subscription_id):
|
609
611
|
"""
|
610
612
|
Increment usage counter for subscription (business logic in manager).
|
@@ -620,19 +622,19 @@ class SubscriptionManager(models.Manager):
|
|
620
622
|
subscription = self.get(id=subscription_id)
|
621
623
|
else:
|
622
624
|
subscription = subscription_id
|
623
|
-
|
625
|
+
|
624
626
|
subscription.total_requests += 1
|
625
627
|
subscription.last_request_at = timezone.now()
|
626
628
|
subscription.save(update_fields=['total_requests', 'last_request_at', 'updated_at'])
|
627
|
-
|
628
|
-
logger.debug(
|
629
|
+
|
630
|
+
logger.debug("Incremented subscription usage", extra={
|
629
631
|
'subscription_id': str(subscription.id),
|
630
632
|
'user_id': subscription.user.id,
|
631
633
|
'total_requests': subscription.total_requests
|
632
634
|
})
|
633
|
-
|
635
|
+
|
634
636
|
return True
|
635
|
-
|
637
|
+
|
636
638
|
except Exception as e:
|
637
639
|
logger.error(f"Failed to increment subscription usage: {e}", extra={
|
638
640
|
'subscription_id': str(subscription_id) if hasattr(subscription_id, 'id') else subscription_id
|