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,12 +4,14 @@ Subscription models for the Universal Payment System v2.0.
|
|
4
4
|
Handles user subscriptions and API access control.
|
5
5
|
"""
|
6
6
|
|
7
|
-
from
|
7
|
+
from datetime import timedelta
|
8
|
+
|
8
9
|
from django.contrib.auth import get_user_model
|
9
|
-
from django.core.validators import MinValueValidator, MaxValueValidator
|
10
10
|
from django.core.exceptions import ValidationError
|
11
|
+
from django.core.validators import MaxValueValidator, MinValueValidator
|
12
|
+
from django.db import models
|
11
13
|
from django.utils import timezone
|
12
|
-
|
14
|
+
|
13
15
|
from .base import UUIDTimestampedModel
|
14
16
|
|
15
17
|
User = get_user_model()
|
@@ -21,54 +23,54 @@ class EndpointGroup(models.Model):
|
|
21
23
|
|
22
24
|
Groups related API endpoints for subscription-based access control.
|
23
25
|
"""
|
24
|
-
|
26
|
+
|
25
27
|
name = models.CharField(
|
26
28
|
max_length=100,
|
27
29
|
unique=True,
|
28
30
|
help_text="Endpoint group name (e.g., 'Payment API', 'Balance API')"
|
29
31
|
)
|
30
|
-
|
32
|
+
|
31
33
|
code = models.CharField(
|
32
34
|
max_length=50,
|
33
35
|
unique=True,
|
34
36
|
help_text="Endpoint group code (e.g., 'payments', 'balance')"
|
35
37
|
)
|
36
|
-
|
38
|
+
|
37
39
|
description = models.TextField(
|
38
40
|
blank=True,
|
39
41
|
help_text="Description of what this endpoint group provides"
|
40
42
|
)
|
41
|
-
|
43
|
+
|
42
44
|
# Access control
|
43
45
|
is_enabled = models.BooleanField(
|
44
46
|
default=True,
|
45
47
|
help_text="Whether this endpoint group is available"
|
46
48
|
)
|
47
|
-
|
49
|
+
|
48
50
|
requires_subscription = models.BooleanField(
|
49
51
|
default=True,
|
50
52
|
help_text="Whether access requires an active subscription"
|
51
53
|
)
|
52
|
-
|
54
|
+
|
53
55
|
# Rate limiting defaults
|
54
56
|
default_rate_limit = models.PositiveIntegerField(
|
55
57
|
default=1000,
|
56
58
|
help_text="Default requests per hour for this endpoint group"
|
57
59
|
)
|
58
|
-
|
60
|
+
|
59
61
|
# Timestamps
|
60
62
|
created_at = models.DateTimeField(auto_now_add=True)
|
61
63
|
updated_at = models.DateTimeField(auto_now=True)
|
62
|
-
|
64
|
+
|
63
65
|
class Meta:
|
64
66
|
db_table = 'payments_endpoint_groups'
|
65
67
|
verbose_name = 'Endpoint Group'
|
66
68
|
verbose_name_plural = 'Endpoint Groups'
|
67
69
|
ordering = ['name']
|
68
|
-
|
70
|
+
|
69
71
|
def __str__(self):
|
70
72
|
return f"{self.name} ({self.code})"
|
71
|
-
|
73
|
+
|
72
74
|
def clean(self):
|
73
75
|
"""Validate endpoint group data."""
|
74
76
|
if self.code:
|
@@ -77,26 +79,26 @@ class EndpointGroup(models.Model):
|
|
77
79
|
|
78
80
|
class SubscriptionQuerySet(models.QuerySet):
|
79
81
|
"""Optimized queryset for subscription operations."""
|
80
|
-
|
82
|
+
|
81
83
|
def optimized(self):
|
82
84
|
"""Prevent N+1 queries."""
|
83
85
|
return self.select_related('user').prefetch_related('endpoint_groups')
|
84
|
-
|
86
|
+
|
85
87
|
def active(self):
|
86
88
|
"""Get active subscriptions."""
|
87
89
|
return self.filter(
|
88
90
|
status=Subscription.SubscriptionStatus.ACTIVE,
|
89
91
|
expires_at__gt=timezone.now()
|
90
92
|
)
|
91
|
-
|
93
|
+
|
92
94
|
def expired(self):
|
93
95
|
"""Get expired subscriptions."""
|
94
96
|
return self.filter(expires_at__lte=timezone.now())
|
95
|
-
|
97
|
+
|
96
98
|
def by_tier(self, tier):
|
97
99
|
"""Filter by subscription tier."""
|
98
100
|
return self.filter(tier=tier)
|
99
|
-
|
101
|
+
|
100
102
|
def by_user(self, user):
|
101
103
|
"""Filter by user."""
|
102
104
|
return self.filter(user=user)
|
@@ -108,41 +110,41 @@ class Subscription(UUIDTimestampedModel):
|
|
108
110
|
|
109
111
|
Manages user subscriptions with different tiers and access levels.
|
110
112
|
"""
|
111
|
-
|
113
|
+
|
112
114
|
class SubscriptionStatus(models.TextChoices):
|
113
115
|
ACTIVE = "active", "Active"
|
114
116
|
INACTIVE = "inactive", "Inactive"
|
115
117
|
SUSPENDED = "suspended", "Suspended"
|
116
118
|
CANCELLED = "cancelled", "Cancelled"
|
117
119
|
EXPIRED = "expired", "Expired"
|
118
|
-
|
120
|
+
|
119
121
|
class SubscriptionTier(models.TextChoices):
|
120
122
|
FREE = "free", "Free Tier"
|
121
123
|
BASIC = "basic", "Basic Tier"
|
122
124
|
PRO = "pro", "Pro Tier"
|
123
125
|
ENTERPRISE = "enterprise", "Enterprise Tier"
|
124
|
-
|
126
|
+
|
125
127
|
user = models.ForeignKey(
|
126
128
|
User,
|
127
129
|
on_delete=models.CASCADE,
|
128
130
|
related_name='payment_subscriptions',
|
129
131
|
help_text="User who owns this subscription"
|
130
132
|
)
|
131
|
-
|
133
|
+
|
132
134
|
tier = models.CharField(
|
133
135
|
max_length=20,
|
134
136
|
choices=SubscriptionTier.choices,
|
135
137
|
default=SubscriptionTier.FREE,
|
136
138
|
help_text="Subscription tier"
|
137
139
|
)
|
138
|
-
|
140
|
+
|
139
141
|
status = models.CharField(
|
140
142
|
max_length=20,
|
141
143
|
choices=SubscriptionStatus.choices,
|
142
144
|
default=SubscriptionStatus.ACTIVE,
|
143
145
|
help_text="Subscription status"
|
144
146
|
)
|
145
|
-
|
147
|
+
|
146
148
|
# Access control
|
147
149
|
endpoint_groups = models.ManyToManyField(
|
148
150
|
EndpointGroup,
|
@@ -150,59 +152,59 @@ class Subscription(UUIDTimestampedModel):
|
|
150
152
|
blank=True,
|
151
153
|
help_text="Endpoint groups accessible with this subscription"
|
152
154
|
)
|
153
|
-
|
155
|
+
|
154
156
|
# Rate limiting
|
155
157
|
requests_per_hour = models.PositiveIntegerField(
|
156
158
|
default=100,
|
157
159
|
validators=[MinValueValidator(1), MaxValueValidator(100000)],
|
158
160
|
help_text="API requests allowed per hour"
|
159
161
|
)
|
160
|
-
|
162
|
+
|
161
163
|
requests_per_day = models.PositiveIntegerField(
|
162
164
|
default=1000,
|
163
165
|
validators=[MinValueValidator(1), MaxValueValidator(1000000)],
|
164
166
|
help_text="API requests allowed per day"
|
165
167
|
)
|
166
|
-
|
168
|
+
|
167
169
|
# Subscription period
|
168
170
|
starts_at = models.DateTimeField(
|
169
171
|
default=timezone.now,
|
170
172
|
help_text="When this subscription starts"
|
171
173
|
)
|
172
|
-
|
174
|
+
|
173
175
|
expires_at = models.DateTimeField(
|
174
176
|
help_text="When this subscription expires"
|
175
177
|
)
|
176
|
-
|
178
|
+
|
177
179
|
# Billing information
|
178
180
|
monthly_cost_usd = models.FloatField(
|
179
181
|
default=0.0,
|
180
182
|
validators=[MinValueValidator(0.0)],
|
181
183
|
help_text="Monthly cost in USD"
|
182
184
|
)
|
183
|
-
|
185
|
+
|
184
186
|
# Usage tracking
|
185
187
|
total_requests = models.PositiveIntegerField(
|
186
188
|
default=0,
|
187
189
|
help_text="Total API requests made with this subscription"
|
188
190
|
)
|
189
|
-
|
191
|
+
|
190
192
|
last_request_at = models.DateTimeField(
|
191
193
|
null=True,
|
192
194
|
blank=True,
|
193
195
|
help_text="When the last API request was made"
|
194
196
|
)
|
195
|
-
|
197
|
+
|
196
198
|
# Auto-renewal
|
197
199
|
auto_renew = models.BooleanField(
|
198
200
|
default=False,
|
199
201
|
help_text="Whether to automatically renew this subscription"
|
200
202
|
)
|
201
|
-
|
203
|
+
|
202
204
|
# Manager
|
203
205
|
from .managers.subscription_managers import SubscriptionManager
|
204
206
|
objects = SubscriptionManager()
|
205
|
-
|
207
|
+
|
206
208
|
class Meta:
|
207
209
|
db_table = 'payments_subscriptions'
|
208
210
|
verbose_name = 'Subscription'
|
@@ -220,26 +222,26 @@ class Subscription(UUIDTimestampedModel):
|
|
220
222
|
name='one_active_subscription_per_user'
|
221
223
|
),
|
222
224
|
]
|
223
|
-
|
225
|
+
|
224
226
|
def __str__(self):
|
225
227
|
return f"{self.user.username} - {self.tier} ({self.status})"
|
226
|
-
|
228
|
+
|
227
229
|
def save(self, *args, **kwargs):
|
228
230
|
"""Override save to set default expiration."""
|
229
231
|
if not self.expires_at:
|
230
232
|
# Default to 30 days from start
|
231
233
|
self.expires_at = self.starts_at + timedelta(days=30)
|
232
|
-
|
234
|
+
|
233
235
|
super().save(*args, **kwargs)
|
234
|
-
|
236
|
+
|
235
237
|
def clean(self):
|
236
238
|
"""Validate subscription data."""
|
237
239
|
if self.expires_at and self.starts_at and self.expires_at <= self.starts_at:
|
238
240
|
raise ValidationError("Expiration date must be after start date")
|
239
|
-
|
241
|
+
|
240
242
|
if self.requests_per_day < self.requests_per_hour:
|
241
243
|
raise ValidationError("Daily limit cannot be less than hourly limit")
|
242
|
-
|
244
|
+
|
243
245
|
@property
|
244
246
|
def is_active(self) -> bool:
|
245
247
|
"""Check if subscription is active and not expired."""
|
@@ -247,12 +249,12 @@ class Subscription(UUIDTimestampedModel):
|
|
247
249
|
self.status == self.SubscriptionStatus.ACTIVE and
|
248
250
|
self.expires_at > timezone.now()
|
249
251
|
)
|
250
|
-
|
252
|
+
|
251
253
|
@property
|
252
254
|
def is_expired(self) -> bool:
|
253
255
|
"""Check if subscription is expired."""
|
254
256
|
return timezone.now() > self.expires_at
|
255
|
-
|
257
|
+
|
256
258
|
@property
|
257
259
|
def days_remaining(self) -> int:
|
258
260
|
"""Get days remaining until expiration."""
|
@@ -260,19 +262,19 @@ class Subscription(UUIDTimestampedModel):
|
|
260
262
|
return 0
|
261
263
|
delta = self.expires_at - timezone.now()
|
262
264
|
return max(0, delta.days)
|
263
|
-
|
265
|
+
|
264
266
|
@property
|
265
267
|
def usage_percentage(self) -> float:
|
266
268
|
"""Get usage percentage for current period."""
|
267
269
|
# This would need to be calculated based on actual usage tracking
|
268
270
|
# For now, return 0.0 as placeholder
|
269
271
|
return 0.0
|
270
|
-
|
272
|
+
|
271
273
|
@property
|
272
274
|
def tier_display(self) -> str:
|
273
275
|
"""Get display name for tier."""
|
274
276
|
return self.get_tier_display()
|
275
|
-
|
277
|
+
|
276
278
|
@property
|
277
279
|
def status_color(self) -> str:
|
278
280
|
"""Get color for status display."""
|
@@ -284,42 +286,42 @@ class Subscription(UUIDTimestampedModel):
|
|
284
286
|
self.SubscriptionStatus.EXPIRED: 'danger',
|
285
287
|
}
|
286
288
|
return colors.get(self.status, 'secondary')
|
287
|
-
|
289
|
+
|
288
290
|
def activate(self):
|
289
291
|
"""Activate subscription (delegates to manager)."""
|
290
292
|
return self.__class__.objects.activate_subscription(self)
|
291
|
-
|
293
|
+
|
292
294
|
def suspend(self, reason=None):
|
293
295
|
"""Suspend subscription (delegates to manager)."""
|
294
296
|
return self.__class__.objects.suspend_subscription(self, reason)
|
295
|
-
|
297
|
+
|
296
298
|
def cancel(self, reason=None):
|
297
299
|
"""Cancel subscription (delegates to manager)."""
|
298
300
|
return self.__class__.objects.cancel_subscription(self, reason)
|
299
|
-
|
301
|
+
|
300
302
|
def renew(self, duration_days: int = 30):
|
301
303
|
"""Renew subscription (delegates to manager)."""
|
302
304
|
return self.__class__.objects.renew_subscription(self, duration_days)
|
303
|
-
|
305
|
+
|
304
306
|
def has_access_to_endpoint_group(self, endpoint_group_code: str) -> bool:
|
305
307
|
"""Check if subscription has access to specific endpoint group."""
|
306
308
|
if not self.is_active:
|
307
309
|
return False
|
308
|
-
|
310
|
+
|
309
311
|
return self.endpoint_groups.filter(
|
310
312
|
code=endpoint_group_code,
|
311
313
|
is_enabled=True
|
312
314
|
).exists()
|
313
|
-
|
315
|
+
|
314
316
|
def increment_usage(self):
|
315
317
|
"""Increment usage counter (delegates to manager)."""
|
316
318
|
return self.__class__.objects.increment_subscription_usage(self)
|
317
|
-
|
319
|
+
|
318
320
|
@classmethod
|
319
321
|
def get_active_for_user(cls, user: User) -> 'Subscription':
|
320
322
|
"""Get active subscription for user (delegates to manager)."""
|
321
323
|
return cls.objects.get_active_for_user(user)
|
322
|
-
|
324
|
+
|
323
325
|
@classmethod
|
324
326
|
def create_free_subscription(cls, user: User) -> 'Subscription':
|
325
327
|
"""Create free tier subscription for user (delegates to manager)."""
|
@@ -4,9 +4,10 @@ Tariff models for the Universal Payment System v2.0.
|
|
4
4
|
Handles pricing tiers and endpoint group associations.
|
5
5
|
"""
|
6
6
|
|
7
|
-
from django.db import models
|
8
|
-
from django.core.validators import MinValueValidator, MaxValueValidator
|
9
7
|
from django.core.exceptions import ValidationError
|
8
|
+
from django.core.validators import MaxValueValidator, MinValueValidator
|
9
|
+
from django.db import models
|
10
|
+
|
10
11
|
from .base import TimestampedModel
|
11
12
|
from .subscriptions import EndpointGroup
|
12
13
|
|
@@ -17,90 +18,90 @@ class Tariff(TimestampedModel):
|
|
17
18
|
|
18
19
|
Defines pricing and limits for different subscription levels.
|
19
20
|
"""
|
20
|
-
|
21
|
+
|
21
22
|
name = models.CharField(
|
22
23
|
max_length=100,
|
23
24
|
unique=True,
|
24
25
|
help_text="Tariff name (e.g., 'Free', 'Basic', 'Pro')"
|
25
26
|
)
|
26
|
-
|
27
|
+
|
27
28
|
code = models.CharField(
|
28
29
|
max_length=50,
|
29
30
|
unique=True,
|
30
31
|
help_text="Tariff code (e.g., 'free', 'basic', 'pro')"
|
31
32
|
)
|
32
|
-
|
33
|
+
|
33
34
|
description = models.TextField(
|
34
35
|
blank=True,
|
35
36
|
help_text="Detailed description of what this tariff includes"
|
36
37
|
)
|
37
|
-
|
38
|
+
|
38
39
|
# Pricing
|
39
40
|
monthly_price_usd = models.FloatField(
|
40
41
|
validators=[MinValueValidator(0.0)],
|
41
42
|
help_text="Monthly price in USD"
|
42
43
|
)
|
43
|
-
|
44
|
+
|
44
45
|
yearly_price_usd = models.FloatField(
|
45
46
|
null=True,
|
46
47
|
blank=True,
|
47
48
|
validators=[MinValueValidator(0.0)],
|
48
49
|
help_text="Yearly price in USD (optional discount)"
|
49
50
|
)
|
50
|
-
|
51
|
+
|
51
52
|
# Rate limits
|
52
53
|
requests_per_hour = models.PositiveIntegerField(
|
53
54
|
default=100,
|
54
55
|
validators=[MinValueValidator(1), MaxValueValidator(100000)],
|
55
56
|
help_text="API requests allowed per hour"
|
56
57
|
)
|
57
|
-
|
58
|
+
|
58
59
|
requests_per_day = models.PositiveIntegerField(
|
59
60
|
default=1000,
|
60
61
|
validators=[MinValueValidator(1), MaxValueValidator(1000000)],
|
61
62
|
help_text="API requests allowed per day"
|
62
63
|
)
|
63
|
-
|
64
|
+
|
64
65
|
requests_per_month = models.PositiveIntegerField(
|
65
66
|
default=30000,
|
66
67
|
validators=[MinValueValidator(1), MaxValueValidator(10000000)],
|
67
68
|
help_text="API requests allowed per month"
|
68
69
|
)
|
69
|
-
|
70
|
+
|
70
71
|
# Features
|
71
72
|
max_api_keys = models.PositiveIntegerField(
|
72
73
|
default=1,
|
73
74
|
validators=[MinValueValidator(1), MaxValueValidator(100)],
|
74
75
|
help_text="Maximum number of API keys allowed"
|
75
76
|
)
|
76
|
-
|
77
|
+
|
77
78
|
supports_webhooks = models.BooleanField(
|
78
79
|
default=True,
|
79
80
|
help_text="Whether webhooks are supported"
|
80
81
|
)
|
81
|
-
|
82
|
+
|
82
83
|
priority_support = models.BooleanField(
|
83
84
|
default=False,
|
84
85
|
help_text="Whether priority support is included"
|
85
86
|
)
|
86
|
-
|
87
|
+
|
87
88
|
# Availability
|
88
89
|
is_active = models.BooleanField(
|
89
90
|
default=True,
|
90
91
|
help_text="Whether this tariff is available for new subscriptions"
|
91
92
|
)
|
92
|
-
|
93
|
+
|
93
94
|
is_public = models.BooleanField(
|
94
95
|
default=True,
|
95
96
|
help_text="Whether this tariff is publicly visible"
|
96
97
|
)
|
97
|
-
|
98
|
+
|
98
99
|
# Ordering
|
99
100
|
sort_order = models.PositiveIntegerField(
|
100
101
|
default=0,
|
101
102
|
help_text="Sort order for display (lower numbers first)"
|
102
103
|
)
|
103
|
-
|
104
|
+
|
104
105
|
class Meta:
|
105
106
|
db_table = 'payments_tariffs'
|
106
107
|
verbose_name = 'Tariff'
|
@@ -110,48 +111,48 @@ class Tariff(TimestampedModel):
|
|
110
111
|
models.Index(fields=['is_active', 'is_public']),
|
111
112
|
models.Index(fields=['sort_order']),
|
112
113
|
]
|
113
|
-
|
114
|
+
|
114
115
|
def __str__(self):
|
115
116
|
return f"{self.name} - ${self.monthly_price_usd:.2f}/month"
|
116
|
-
|
117
|
+
|
117
118
|
def clean(self):
|
118
119
|
"""Validate tariff data."""
|
119
120
|
if self.code:
|
120
121
|
self.code = self.code.lower().replace(' ', '_')
|
121
|
-
|
122
|
+
|
122
123
|
# Validate rate limits hierarchy
|
123
124
|
if self.requests_per_day < self.requests_per_hour:
|
124
125
|
raise ValidationError("Daily limit cannot be less than hourly limit")
|
125
|
-
|
126
|
+
|
126
127
|
if self.requests_per_month < self.requests_per_day:
|
127
128
|
raise ValidationError("Monthly limit cannot be less than daily limit")
|
128
|
-
|
129
|
+
|
129
130
|
# Validate yearly pricing
|
130
131
|
if self.yearly_price_usd and self.yearly_price_usd >= (self.monthly_price_usd * 12):
|
131
132
|
raise ValidationError("Yearly price should be less than 12x monthly price")
|
132
|
-
|
133
|
+
|
133
134
|
@property
|
134
135
|
def is_free(self) -> bool:
|
135
136
|
"""Check if this is a free tariff."""
|
136
137
|
return self.monthly_price_usd == 0.0
|
137
|
-
|
138
|
+
|
138
139
|
@property
|
139
140
|
def yearly_discount_percentage(self) -> float:
|
140
141
|
"""Calculate yearly discount percentage."""
|
141
142
|
if not self.yearly_price_usd or self.monthly_price_usd == 0:
|
142
143
|
return 0.0
|
143
|
-
|
144
|
+
|
144
145
|
yearly_equivalent = self.monthly_price_usd * 12
|
145
146
|
discount = yearly_equivalent - self.yearly_price_usd
|
146
147
|
return (discount / yearly_equivalent) * 100
|
147
|
-
|
148
|
+
|
148
149
|
@property
|
149
150
|
def price_display(self) -> str:
|
150
151
|
"""Formatted price display."""
|
151
152
|
if self.is_free:
|
152
153
|
return "Free"
|
153
154
|
return f"${self.monthly_price_usd:.2f}/month"
|
154
|
-
|
155
|
+
|
155
156
|
@property
|
156
157
|
def yearly_price_display(self) -> str:
|
157
158
|
"""Formatted yearly price display."""
|
@@ -168,41 +169,41 @@ class TariffEndpointGroup(TimestampedModel):
|
|
168
169
|
|
169
170
|
Defines which API endpoints are available for each tariff.
|
170
171
|
"""
|
171
|
-
|
172
|
+
|
172
173
|
tariff = models.ForeignKey(
|
173
174
|
Tariff,
|
174
175
|
on_delete=models.CASCADE,
|
175
176
|
related_name='endpoint_groups'
|
176
177
|
)
|
177
|
-
|
178
|
+
|
178
179
|
endpoint_group = models.ForeignKey(
|
179
180
|
EndpointGroup,
|
180
181
|
on_delete=models.CASCADE,
|
181
182
|
related_name='tariffs'
|
182
183
|
)
|
183
|
-
|
184
|
+
|
184
185
|
# Override default rate limits for this specific combination
|
185
186
|
custom_rate_limit = models.PositiveIntegerField(
|
186
187
|
null=True,
|
187
188
|
blank=True,
|
188
189
|
help_text="Custom rate limit for this endpoint group (overrides tariff default)"
|
189
190
|
)
|
190
|
-
|
191
|
+
|
191
192
|
is_enabled = models.BooleanField(
|
192
193
|
default=True,
|
193
194
|
help_text="Whether this endpoint group is enabled for this tariff"
|
194
195
|
)
|
195
|
-
|
196
|
+
|
196
197
|
class Meta:
|
197
198
|
db_table = 'payments_tariff_endpoint_groups'
|
198
199
|
verbose_name = 'Tariff Endpoint Group'
|
199
200
|
verbose_name_plural = 'Tariff Endpoint Groups'
|
200
201
|
unique_together = [['tariff', 'endpoint_group']]
|
201
202
|
ordering = ['tariff__sort_order', 'endpoint_group__name']
|
202
|
-
|
203
|
+
|
203
204
|
def __str__(self):
|
204
205
|
return f"{self.tariff.name} - {self.endpoint_group.name}"
|
205
|
-
|
206
|
+
|
206
207
|
@property
|
207
208
|
def effective_rate_limit(self) -> int:
|
208
209
|
"""Get effective rate limit (custom or tariff default)."""
|