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,25 +4,24 @@ Balance ViewSets for the Universal Payment System v2.0.
|
|
4
4
|
DRF ViewSets for balance and transaction management with service integration.
|
5
5
|
"""
|
6
6
|
|
7
|
-
from rest_framework import viewsets, permissions, status
|
8
|
-
from rest_framework.decorators import action
|
9
|
-
from rest_framework.response import Response
|
10
|
-
from django_filters.rest_framework import DjangoFilterBackend
|
11
7
|
from django.contrib.auth import get_user_model
|
12
8
|
from django.db import models
|
13
9
|
from django.utils import timezone
|
10
|
+
from rest_framework import permissions, status
|
11
|
+
from rest_framework.decorators import action
|
12
|
+
from rest_framework.response import Response
|
14
13
|
|
15
|
-
from .
|
16
|
-
|
17
|
-
from ...
|
14
|
+
from django_cfg.modules.django_logging import get_logger
|
15
|
+
|
16
|
+
from ...models import Transaction, UserBalance
|
18
17
|
from ..serializers.balances import (
|
19
|
-
|
20
|
-
TransactionSerializer,
|
18
|
+
BalanceStatsSerializer,
|
21
19
|
BalanceUpdateSerializer,
|
22
20
|
FundsTransferSerializer,
|
23
|
-
|
21
|
+
TransactionSerializer,
|
22
|
+
UserBalanceSerializer,
|
24
23
|
)
|
25
|
-
from
|
24
|
+
from .base import NestedPaymentViewSet, ReadOnlyPaymentViewSet
|
26
25
|
|
27
26
|
User = get_user_model()
|
28
27
|
logger = get_logger("balance_viewsets")
|
@@ -34,24 +33,24 @@ class UserBalanceViewSet(ReadOnlyPaymentViewSet):
|
|
34
33
|
|
35
34
|
Read-only access to user balances with statistics.
|
36
35
|
"""
|
37
|
-
|
36
|
+
|
38
37
|
queryset = UserBalance.objects.all()
|
39
38
|
serializer_class = UserBalanceSerializer
|
40
39
|
permission_classes = [permissions.IsAuthenticated]
|
41
40
|
filterset_fields = ['user']
|
42
41
|
search_fields = ['user__username', 'user__email']
|
43
42
|
ordering_fields = ['balance_usd', 'created_at', 'updated_at']
|
44
|
-
|
43
|
+
|
45
44
|
def get_queryset(self):
|
46
45
|
"""Filter by user permissions and optimize queryset."""
|
47
46
|
queryset = super().get_queryset().select_related('user')
|
48
|
-
|
47
|
+
|
49
48
|
# Non-staff users can only see their own balance
|
50
49
|
if not self.request.user.is_staff:
|
51
50
|
queryset = queryset.filter(user=self.request.user)
|
52
|
-
|
51
|
+
|
53
52
|
return queryset
|
54
|
-
|
53
|
+
|
55
54
|
@action(detail=True, methods=['post'])
|
56
55
|
def add_funds(self, request, pk=None):
|
57
56
|
"""
|
@@ -60,14 +59,14 @@ class UserBalanceViewSet(ReadOnlyPaymentViewSet):
|
|
60
59
|
POST /api/balances/{id}/add_funds/
|
61
60
|
"""
|
62
61
|
balance = self.get_object()
|
63
|
-
|
62
|
+
|
64
63
|
# Permission check: users can only add funds to their own balance
|
65
64
|
if not request.user.is_staff and balance.user != request.user:
|
66
65
|
return Response(
|
67
66
|
{'error': 'You can only add funds to your own balance'},
|
68
67
|
status=status.HTTP_403_FORBIDDEN
|
69
68
|
)
|
70
|
-
|
69
|
+
|
71
70
|
serializer = BalanceUpdateSerializer(
|
72
71
|
data=request.data,
|
73
72
|
context={
|
@@ -75,13 +74,13 @@ class UserBalanceViewSet(ReadOnlyPaymentViewSet):
|
|
75
74
|
'user_pk': balance.user.id
|
76
75
|
}
|
77
76
|
)
|
78
|
-
|
77
|
+
|
79
78
|
if serializer.is_valid():
|
80
79
|
result = serializer.save()
|
81
80
|
return Response(result)
|
82
|
-
|
81
|
+
|
83
82
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
84
|
-
|
83
|
+
|
85
84
|
@action(detail=True, methods=['post'])
|
86
85
|
def withdraw_funds(self, request, pk=None):
|
87
86
|
"""
|
@@ -90,19 +89,19 @@ class UserBalanceViewSet(ReadOnlyPaymentViewSet):
|
|
90
89
|
POST /api/balances/{id}/withdraw_funds/
|
91
90
|
"""
|
92
91
|
balance = self.get_object()
|
93
|
-
|
92
|
+
|
94
93
|
# Permission check
|
95
94
|
if not request.user.is_staff and balance.user != request.user:
|
96
95
|
return Response(
|
97
96
|
{'error': 'You can only withdraw from your own balance'},
|
98
97
|
status=status.HTTP_403_FORBIDDEN
|
99
98
|
)
|
100
|
-
|
99
|
+
|
101
100
|
# Convert to negative amount for withdrawal
|
102
101
|
data = request.data.copy()
|
103
102
|
if 'amount' in data and data['amount'] > 0:
|
104
103
|
data['amount'] = -abs(data['amount'])
|
105
|
-
|
104
|
+
|
106
105
|
serializer = BalanceUpdateSerializer(
|
107
106
|
data=data,
|
108
107
|
context={
|
@@ -110,13 +109,13 @@ class UserBalanceViewSet(ReadOnlyPaymentViewSet):
|
|
110
109
|
'user_pk': balance.user.id
|
111
110
|
}
|
112
111
|
)
|
113
|
-
|
112
|
+
|
114
113
|
if serializer.is_valid():
|
115
114
|
result = serializer.save()
|
116
115
|
return Response(result)
|
117
|
-
|
116
|
+
|
118
117
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
119
|
-
|
118
|
+
|
120
119
|
@action(detail=True, methods=['post'])
|
121
120
|
def transfer_funds(self, request, pk=None):
|
122
121
|
"""
|
@@ -125,25 +124,25 @@ class UserBalanceViewSet(ReadOnlyPaymentViewSet):
|
|
125
124
|
POST /api/balances/{id}/transfer_funds/
|
126
125
|
"""
|
127
126
|
balance = self.get_object()
|
128
|
-
|
127
|
+
|
129
128
|
# Permission check
|
130
129
|
if not request.user.is_staff and balance.user != request.user:
|
131
130
|
return Response(
|
132
131
|
{'error': 'You can only transfer from your own balance'},
|
133
132
|
status=status.HTTP_403_FORBIDDEN
|
134
133
|
)
|
135
|
-
|
134
|
+
|
136
135
|
serializer = FundsTransferSerializer(
|
137
136
|
data=request.data,
|
138
137
|
context=self.get_serializer_context()
|
139
138
|
)
|
140
|
-
|
139
|
+
|
141
140
|
if serializer.is_valid():
|
142
141
|
result = serializer.save()
|
143
142
|
return Response(result)
|
144
|
-
|
143
|
+
|
145
144
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
146
|
-
|
145
|
+
|
147
146
|
@action(detail=False, methods=['get'])
|
148
147
|
def analytics(self, request):
|
149
148
|
"""
|
@@ -152,13 +151,13 @@ class UserBalanceViewSet(ReadOnlyPaymentViewSet):
|
|
152
151
|
GET /api/balances/analytics/?days=30
|
153
152
|
"""
|
154
153
|
serializer = BalanceStatsSerializer(data=request.query_params)
|
155
|
-
|
154
|
+
|
156
155
|
if serializer.is_valid():
|
157
156
|
result = serializer.save()
|
158
157
|
return Response(result)
|
159
|
-
|
158
|
+
|
160
159
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
161
|
-
|
160
|
+
|
162
161
|
@action(detail=False, methods=['get'])
|
163
162
|
def summary(self, request):
|
164
163
|
"""
|
@@ -168,7 +167,7 @@ class UserBalanceViewSet(ReadOnlyPaymentViewSet):
|
|
168
167
|
"""
|
169
168
|
try:
|
170
169
|
queryset = self.filter_queryset(self.get_queryset())
|
171
|
-
|
170
|
+
|
172
171
|
summary = queryset.aggregate(
|
173
172
|
total_users=models.Count('id'),
|
174
173
|
total_balance=models.Sum('balance_usd'),
|
@@ -182,7 +181,7 @@ class UserBalanceViewSet(ReadOnlyPaymentViewSet):
|
|
182
181
|
filter=models.Q(balance_usd=0)
|
183
182
|
),
|
184
183
|
)
|
185
|
-
|
184
|
+
|
186
185
|
return Response({
|
187
186
|
'summary': {
|
188
187
|
**summary,
|
@@ -191,7 +190,7 @@ class UserBalanceViewSet(ReadOnlyPaymentViewSet):
|
|
191
190
|
},
|
192
191
|
'generated_at': timezone.now().isoformat()
|
193
192
|
})
|
194
|
-
|
193
|
+
|
195
194
|
except Exception as e:
|
196
195
|
logger.error(f"Balance summary failed: {e}")
|
197
196
|
return Response(
|
@@ -206,24 +205,24 @@ class TransactionViewSet(ReadOnlyPaymentViewSet):
|
|
206
205
|
|
207
206
|
Read-only access to transaction history with filtering.
|
208
207
|
"""
|
209
|
-
|
208
|
+
|
210
209
|
queryset = Transaction.objects.all()
|
211
210
|
serializer_class = TransactionSerializer
|
212
211
|
permission_classes = [permissions.IsAuthenticated]
|
213
212
|
filterset_fields = ['user', 'transaction_type', 'payment_id']
|
214
213
|
search_fields = ['description', 'payment_id']
|
215
214
|
ordering_fields = ['created_at', 'amount']
|
216
|
-
|
215
|
+
|
217
216
|
def get_queryset(self):
|
218
217
|
"""Filter by user permissions and optimize queryset."""
|
219
218
|
queryset = super().get_queryset().select_related('user')
|
220
|
-
|
219
|
+
|
221
220
|
# Non-staff users can only see their own transactions
|
222
221
|
if not self.request.user.is_staff:
|
223
222
|
queryset = queryset.filter(user=self.request.user)
|
224
|
-
|
223
|
+
|
225
224
|
return queryset
|
226
|
-
|
225
|
+
|
227
226
|
@action(detail=False, methods=['get'])
|
228
227
|
def by_type(self, request):
|
229
228
|
"""
|
@@ -233,14 +232,14 @@ class TransactionViewSet(ReadOnlyPaymentViewSet):
|
|
233
232
|
"""
|
234
233
|
try:
|
235
234
|
queryset = self.filter_queryset(self.get_queryset())
|
236
|
-
|
235
|
+
|
237
236
|
type_stats = {}
|
238
237
|
for type_choice in Transaction.TransactionType.choices:
|
239
238
|
type_code = type_choice[0]
|
240
239
|
type_name = type_choice[1]
|
241
|
-
|
240
|
+
|
242
241
|
type_transactions = queryset.filter(transaction_type=type_code)
|
243
|
-
|
242
|
+
|
244
243
|
type_stats[type_code] = {
|
245
244
|
'name': type_name,
|
246
245
|
'total_transactions': type_transactions.count(),
|
@@ -255,19 +254,19 @@ class TransactionViewSet(ReadOnlyPaymentViewSet):
|
|
255
254
|
)['avg'] or 0
|
256
255
|
),
|
257
256
|
}
|
258
|
-
|
257
|
+
|
259
258
|
return Response({
|
260
259
|
'type_stats': type_stats,
|
261
260
|
'generated_at': timezone.now().isoformat()
|
262
261
|
})
|
263
|
-
|
262
|
+
|
264
263
|
except Exception as e:
|
265
264
|
logger.error(f"Transaction type stats failed: {e}")
|
266
265
|
return Response(
|
267
266
|
{'error': f'Type stats failed: {e}'},
|
268
267
|
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
269
268
|
)
|
270
|
-
|
269
|
+
|
271
270
|
@action(detail=False, methods=['get'])
|
272
271
|
def recent(self, request):
|
273
272
|
"""
|
@@ -278,19 +277,19 @@ class TransactionViewSet(ReadOnlyPaymentViewSet):
|
|
278
277
|
try:
|
279
278
|
limit = int(request.query_params.get('limit', 10))
|
280
279
|
limit = min(limit, 100) # Cap at 100
|
281
|
-
|
280
|
+
|
282
281
|
queryset = self.filter_queryset(self.get_queryset())
|
283
282
|
recent_transactions = queryset.order_by('-created_at')[:limit]
|
284
|
-
|
283
|
+
|
285
284
|
serializer = self.get_serializer(recent_transactions, many=True)
|
286
|
-
|
285
|
+
|
287
286
|
return Response({
|
288
287
|
'transactions': serializer.data,
|
289
288
|
'count': len(serializer.data),
|
290
289
|
'limit': limit,
|
291
290
|
'generated_at': timezone.now().isoformat()
|
292
291
|
})
|
293
|
-
|
292
|
+
|
294
293
|
except Exception as e:
|
295
294
|
logger.error(f"Recent transactions failed: {e}")
|
296
295
|
return Response(
|
@@ -305,33 +304,33 @@ class UserTransactionViewSet(NestedPaymentViewSet):
|
|
305
304
|
|
306
305
|
User-scoped access to transaction history.
|
307
306
|
"""
|
308
|
-
|
307
|
+
|
309
308
|
queryset = Transaction.objects.all()
|
310
309
|
serializer_class = TransactionSerializer
|
311
310
|
permission_classes = [permissions.IsAuthenticated]
|
312
311
|
filterset_fields = ['transaction_type', 'payment_id']
|
313
312
|
search_fields = ['description', 'payment_id']
|
314
313
|
ordering_fields = ['created_at', 'amount']
|
315
|
-
|
314
|
+
|
316
315
|
# Nested ViewSet configuration
|
317
316
|
parent_lookup_field = 'user_pk'
|
318
317
|
parent_model_field = 'user'
|
319
|
-
|
318
|
+
|
320
319
|
# Read-only operations only
|
321
320
|
http_method_names = ['get', 'head', 'options']
|
322
|
-
|
321
|
+
|
323
322
|
def get_queryset(self):
|
324
323
|
"""Filter by user and optimize queryset."""
|
325
324
|
queryset = super().get_queryset()
|
326
|
-
|
325
|
+
|
327
326
|
# Additional permission check: users can only see their own transactions
|
328
327
|
if not self.request.user.is_staff:
|
329
328
|
user_id = self.kwargs.get('user_pk')
|
330
329
|
if str(self.request.user.id) != str(user_id):
|
331
330
|
return queryset.none()
|
332
|
-
|
331
|
+
|
333
332
|
return queryset
|
334
|
-
|
333
|
+
|
335
334
|
@action(detail=False, methods=['get'])
|
336
335
|
def summary(self, request, user_pk=None):
|
337
336
|
"""
|
@@ -341,7 +340,7 @@ class UserTransactionViewSet(NestedPaymentViewSet):
|
|
341
340
|
"""
|
342
341
|
try:
|
343
342
|
queryset = self.filter_queryset(self.get_queryset())
|
344
|
-
|
343
|
+
|
345
344
|
summary = queryset.aggregate(
|
346
345
|
total_transactions=models.Count('id'),
|
347
346
|
total_credits=models.Sum(
|
@@ -354,14 +353,14 @@ class UserTransactionViewSet(NestedPaymentViewSet):
|
|
354
353
|
),
|
355
354
|
net_amount=models.Sum('amount_usd'),
|
356
355
|
)
|
357
|
-
|
356
|
+
|
358
357
|
# Get type breakdown
|
359
358
|
type_breakdown = dict(
|
360
359
|
queryset.values('transaction_type')
|
361
360
|
.annotate(count=models.Count('id'))
|
362
361
|
.values_list('transaction_type', 'count')
|
363
362
|
)
|
364
|
-
|
363
|
+
|
365
364
|
return Response({
|
366
365
|
'user_id': user_pk,
|
367
366
|
'summary': {
|
@@ -373,7 +372,7 @@ class UserTransactionViewSet(NestedPaymentViewSet):
|
|
373
372
|
},
|
374
373
|
'generated_at': timezone.now().isoformat()
|
375
374
|
})
|
376
|
-
|
375
|
+
|
377
376
|
except Exception as e:
|
378
377
|
logger.error(f"User transaction summary failed: {e}")
|
379
378
|
return Response(
|
@@ -4,17 +4,17 @@ Base ViewSet classes for the Universal Payment System v2.0.
|
|
4
4
|
Common functionality for all payment system ViewSets.
|
5
5
|
"""
|
6
6
|
|
7
|
-
from
|
8
|
-
from
|
9
|
-
from rest_framework.response import Response
|
10
|
-
from django_filters.rest_framework import DjangoFilterBackend
|
11
|
-
from rest_framework.filters import SearchFilter, OrderingFilter
|
12
|
-
from rest_framework.exceptions import NotFound
|
7
|
+
from datetime import timedelta
|
8
|
+
from typing import Any, Dict
|
13
9
|
|
14
|
-
from django.db.models import Count, Sum
|
10
|
+
from django.db.models import Avg, Count, Sum
|
15
11
|
from django.utils import timezone
|
16
|
-
from
|
17
|
-
from
|
12
|
+
from django_filters.rest_framework import DjangoFilterBackend
|
13
|
+
from rest_framework import permissions, status, viewsets
|
14
|
+
from rest_framework.decorators import action
|
15
|
+
from rest_framework.exceptions import NotFound
|
16
|
+
from rest_framework.filters import OrderingFilter, SearchFilter
|
17
|
+
from rest_framework.response import Response
|
18
18
|
|
19
19
|
from django_cfg.modules.django_logging import get_logger
|
20
20
|
|
@@ -28,15 +28,15 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
28
28
|
Provides standard CRUD operations plus common actions like stats,
|
29
29
|
health checks, and optimized querysets.
|
30
30
|
"""
|
31
|
-
|
31
|
+
|
32
32
|
permission_classes = [permissions.IsAuthenticated]
|
33
33
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
34
34
|
ordering = ['-created_at']
|
35
35
|
versioning_class = None # Disable versioning for payments API
|
36
|
-
|
36
|
+
|
37
37
|
# Serializer classes mapping for different actions
|
38
38
|
serializer_classes = {}
|
39
|
-
|
39
|
+
|
40
40
|
def get_queryset(self):
|
41
41
|
"""
|
42
42
|
Optimized queryset with select_related and prefetch_related.
|
@@ -44,13 +44,13 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
44
44
|
Override in subclasses to add specific optimizations.
|
45
45
|
"""
|
46
46
|
queryset = super().get_queryset()
|
47
|
-
|
47
|
+
|
48
48
|
# Add common optimizations
|
49
49
|
if hasattr(self.queryset.model, 'user'):
|
50
50
|
queryset = queryset.select_related('user')
|
51
|
-
|
51
|
+
|
52
52
|
return queryset
|
53
|
-
|
53
|
+
|
54
54
|
def get_serializer_class(self):
|
55
55
|
"""
|
56
56
|
Dynamic serializer selection based on action.
|
@@ -59,7 +59,7 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
59
59
|
"""
|
60
60
|
serializer_classes = getattr(self, 'serializer_classes', {})
|
61
61
|
return serializer_classes.get(self.action, self.serializer_class)
|
62
|
-
|
62
|
+
|
63
63
|
def get_serializer_context(self):
|
64
64
|
"""
|
65
65
|
Enhanced serializer context with additional data.
|
@@ -69,18 +69,18 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
69
69
|
'action': self.action,
|
70
70
|
'user': self.request.user,
|
71
71
|
})
|
72
|
-
|
72
|
+
|
73
73
|
# Add object ID for detail actions
|
74
74
|
if self.action in ['retrieve', 'update', 'partial_update', 'destroy']:
|
75
75
|
context['object_id'] = self.kwargs.get('pk')
|
76
|
-
|
76
|
+
|
77
77
|
# Add parent object ID for nested routes
|
78
78
|
for key, value in self.kwargs.items():
|
79
79
|
if key.endswith('_pk'):
|
80
80
|
context[key] = value
|
81
|
-
|
81
|
+
|
82
82
|
return context
|
83
|
-
|
83
|
+
|
84
84
|
@action(detail=False, methods=['get'])
|
85
85
|
def stats(self, request, **kwargs):
|
86
86
|
"""
|
@@ -90,35 +90,35 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
90
90
|
"""
|
91
91
|
try:
|
92
92
|
queryset = self.filter_queryset(self.get_queryset())
|
93
|
-
|
93
|
+
|
94
94
|
# Basic counts
|
95
95
|
total_count = queryset.count()
|
96
|
-
|
96
|
+
|
97
97
|
stats = {
|
98
98
|
'total_count': total_count,
|
99
99
|
'generated_at': timezone.now().isoformat(),
|
100
100
|
}
|
101
|
-
|
101
|
+
|
102
102
|
# Add status breakdown if model has status field
|
103
103
|
if hasattr(queryset.model, 'status'):
|
104
104
|
stats['status_breakdown'] = self._get_status_breakdown(queryset)
|
105
|
-
|
105
|
+
|
106
106
|
# Add amount summary if model has amount fields
|
107
107
|
if hasattr(queryset.model, 'amount_usd'):
|
108
108
|
stats['amount_summary'] = self._get_amount_summary(queryset)
|
109
|
-
|
109
|
+
|
110
110
|
# Add time-based breakdown
|
111
111
|
stats['time_breakdown'] = self._get_time_breakdown(queryset)
|
112
|
-
|
112
|
+
|
113
113
|
return Response(stats)
|
114
|
-
|
114
|
+
|
115
115
|
except Exception as e:
|
116
116
|
logger.error(f"Stats generation failed: {e}")
|
117
117
|
return Response(
|
118
118
|
{'error': f'Stats generation failed: {e}'},
|
119
119
|
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
120
120
|
)
|
121
|
-
|
121
|
+
|
122
122
|
@action(detail=False, methods=['get'])
|
123
123
|
def health(self, request, **kwargs):
|
124
124
|
"""
|
@@ -128,7 +128,7 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
128
128
|
"""
|
129
129
|
try:
|
130
130
|
queryset = self.get_queryset()
|
131
|
-
|
131
|
+
|
132
132
|
# Basic health metrics
|
133
133
|
health_data = {
|
134
134
|
'service': self.__class__.__name__,
|
@@ -137,16 +137,16 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
137
137
|
'model': queryset.model.__name__,
|
138
138
|
'timestamp': timezone.now().isoformat(),
|
139
139
|
}
|
140
|
-
|
140
|
+
|
141
141
|
# Check recent activity (last 24 hours)
|
142
142
|
if hasattr(queryset.model, 'created_at'):
|
143
143
|
recent_count = queryset.filter(
|
144
144
|
created_at__gte=timezone.now() - timedelta(hours=24)
|
145
145
|
).count()
|
146
146
|
health_data['recent_activity'] = recent_count
|
147
|
-
|
147
|
+
|
148
148
|
return Response(health_data)
|
149
|
-
|
149
|
+
|
150
150
|
except Exception as e:
|
151
151
|
logger.error(f"Health check failed: {e}")
|
152
152
|
return Response(
|
@@ -158,7 +158,7 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
158
158
|
},
|
159
159
|
status=status.HTTP_503_SERVICE_UNAVAILABLE
|
160
160
|
)
|
161
|
-
|
161
|
+
|
162
162
|
def _get_status_breakdown(self, queryset) -> Dict[str, int]:
|
163
163
|
"""Get status breakdown for statistics."""
|
164
164
|
return dict(
|
@@ -166,7 +166,7 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
166
166
|
.annotate(count=Count('id'))
|
167
167
|
.values_list('status', 'count')
|
168
168
|
)
|
169
|
-
|
169
|
+
|
170
170
|
def _get_amount_summary(self, queryset) -> Dict[str, Any]:
|
171
171
|
"""Get amount summary for statistics."""
|
172
172
|
aggregates = queryset.aggregate(
|
@@ -174,20 +174,20 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
174
174
|
average_amount=Avg('amount_usd'),
|
175
175
|
count=Count('id')
|
176
176
|
)
|
177
|
-
|
177
|
+
|
178
178
|
return {
|
179
179
|
'total_amount_usd': float(aggregates['total_amount'] or 0),
|
180
180
|
'average_amount_usd': float(aggregates['average_amount'] or 0),
|
181
181
|
'transaction_count': aggregates['count'],
|
182
182
|
}
|
183
|
-
|
183
|
+
|
184
184
|
def _get_time_breakdown(self, queryset) -> Dict[str, int]:
|
185
185
|
"""Get time-based breakdown for statistics."""
|
186
186
|
if not hasattr(queryset.model, 'created_at'):
|
187
187
|
return {}
|
188
|
-
|
188
|
+
|
189
189
|
now = timezone.now()
|
190
|
-
|
190
|
+
|
191
191
|
return {
|
192
192
|
'last_24h': queryset.filter(
|
193
193
|
created_at__gte=now - timedelta(hours=24)
|
@@ -199,7 +199,7 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
199
199
|
created_at__gte=now - timedelta(days=30)
|
200
200
|
).count(),
|
201
201
|
}
|
202
|
-
|
202
|
+
|
203
203
|
def handle_exception(self, exc):
|
204
204
|
"""
|
205
205
|
Enhanced exception handling with logging.
|
@@ -209,7 +209,7 @@ class PaymentBaseViewSet(viewsets.ModelViewSet):
|
|
209
209
|
'user_id': getattr(self.request.user, 'id', None) if hasattr(self, 'request') else None,
|
210
210
|
'exception_type': type(exc).__name__,
|
211
211
|
})
|
212
|
-
|
212
|
+
|
213
213
|
return super().handle_exception(exc)
|
214
214
|
|
215
215
|
|
@@ -219,30 +219,30 @@ class ReadOnlyPaymentViewSet(PaymentBaseViewSet):
|
|
219
219
|
|
220
220
|
Provides list, retrieve, and stats actions only.
|
221
221
|
"""
|
222
|
-
|
222
|
+
|
223
223
|
http_method_names = ['get', 'head', 'options']
|
224
|
-
|
224
|
+
|
225
225
|
def create(self, request, *args, **kwargs):
|
226
226
|
"""Disable create action."""
|
227
227
|
return Response(
|
228
228
|
{'error': 'Create operation not allowed'},
|
229
229
|
status=status.HTTP_405_METHOD_NOT_ALLOWED
|
230
230
|
)
|
231
|
-
|
231
|
+
|
232
232
|
def update(self, request, *args, **kwargs):
|
233
233
|
"""Disable update action."""
|
234
234
|
return Response(
|
235
235
|
{'error': 'Update operation not allowed'},
|
236
236
|
status=status.HTTP_405_METHOD_NOT_ALLOWED
|
237
237
|
)
|
238
|
-
|
238
|
+
|
239
239
|
def partial_update(self, request, *args, **kwargs):
|
240
240
|
"""Disable partial update action."""
|
241
241
|
return Response(
|
242
242
|
{'error': 'Update operation not allowed'},
|
243
243
|
status=status.HTTP_405_METHOD_NOT_ALLOWED
|
244
244
|
)
|
245
|
-
|
245
|
+
|
246
246
|
def destroy(self, request, *args, **kwargs):
|
247
247
|
"""Disable destroy action."""
|
248
248
|
return Response(
|
@@ -257,10 +257,10 @@ class NestedPaymentViewSet(PaymentBaseViewSet):
|
|
257
257
|
|
258
258
|
Automatically filters queryset by parent object and sets parent on creation.
|
259
259
|
"""
|
260
|
-
|
260
|
+
|
261
261
|
parent_lookup_field = 'user_pk' # Override in subclasses
|
262
262
|
parent_model_field = 'user' # Override in subclasses
|
263
|
-
|
263
|
+
|
264
264
|
def get_queryset(self):
|
265
265
|
"""Filter queryset by parent object from URL."""
|
266
266
|
queryset = super().get_queryset()
|
@@ -275,7 +275,7 @@ class NestedPaymentViewSet(PaymentBaseViewSet):
|
|
275
275
|
queryset = queryset.filter(**filter_kwargs)
|
276
276
|
|
277
277
|
return queryset
|
278
|
-
|
278
|
+
|
279
279
|
def perform_create(self, serializer):
|
280
280
|
"""Set parent object when creating nested resource."""
|
281
281
|
parent_id = self.kwargs.get(self.parent_lookup_field)
|
@@ -283,7 +283,7 @@ class NestedPaymentViewSet(PaymentBaseViewSet):
|
|
283
283
|
# Get parent model class
|
284
284
|
parent_field = getattr(self.queryset.model, self.parent_model_field)
|
285
285
|
parent_model = parent_field.field.related_model
|
286
|
-
|
286
|
+
|
287
287
|
try:
|
288
288
|
parent_obj = parent_model.objects.get(id=parent_id)
|
289
289
|
serializer.save(**{self.parent_model_field: parent_obj})
|
@@ -291,13 +291,13 @@ class NestedPaymentViewSet(PaymentBaseViewSet):
|
|
291
291
|
raise NotFound(f"Parent object not found: {parent_id}")
|
292
292
|
else:
|
293
293
|
serializer.save()
|
294
|
-
|
294
|
+
|
295
295
|
def get_serializer_context(self):
|
296
296
|
"""Add parent object ID to serializer context."""
|
297
297
|
context = super().get_serializer_context()
|
298
|
-
|
298
|
+
|
299
299
|
parent_id = self.kwargs.get(self.parent_lookup_field)
|
300
300
|
if parent_id:
|
301
301
|
context[self.parent_lookup_field] = parent_id
|
302
|
-
|
302
|
+
|
303
303
|
return context
|