django-cfg 1.3.7__py3-none-any.whl → 1.3.11__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 +1 -1
- django_cfg/apps/accounts/admin/__init__.py +24 -8
- django_cfg/apps/accounts/admin/activity_admin.py +146 -0
- django_cfg/apps/accounts/admin/filters.py +98 -22
- django_cfg/apps/accounts/admin/group_admin.py +86 -0
- django_cfg/apps/accounts/admin/inlines.py +42 -13
- django_cfg/apps/accounts/admin/otp_admin.py +115 -0
- django_cfg/apps/accounts/admin/registration_admin.py +173 -0
- django_cfg/apps/accounts/admin/resources.py +123 -19
- django_cfg/apps/accounts/admin/twilio_admin.py +327 -0
- django_cfg/apps/accounts/admin/user_admin.py +362 -0
- django_cfg/apps/agents/admin/__init__.py +17 -4
- django_cfg/apps/agents/admin/execution_admin.py +204 -183
- django_cfg/apps/agents/admin/registry_admin.py +230 -255
- django_cfg/apps/agents/admin/toolsets_admin.py +274 -321
- django_cfg/apps/agents/core/__init__.py +1 -1
- django_cfg/apps/agents/core/django_agent.py +221 -0
- django_cfg/apps/agents/core/exceptions.py +14 -0
- django_cfg/apps/agents/core/orchestrator.py +18 -3
- django_cfg/apps/knowbase/admin/__init__.py +1 -1
- django_cfg/apps/knowbase/admin/archive_admin.py +352 -640
- django_cfg/apps/knowbase/admin/chat_admin.py +258 -192
- django_cfg/apps/knowbase/admin/document_admin.py +269 -262
- django_cfg/apps/knowbase/admin/external_data_admin.py +271 -489
- django_cfg/apps/knowbase/config/settings.py +21 -4
- django_cfg/apps/knowbase/views/chat_views.py +3 -0
- django_cfg/apps/leads/admin/__init__.py +3 -1
- django_cfg/apps/leads/admin/leads_admin.py +235 -35
- django_cfg/apps/maintenance/admin/__init__.py +2 -2
- django_cfg/apps/maintenance/admin/api_key_admin.py +125 -63
- django_cfg/apps/maintenance/admin/log_admin.py +143 -61
- django_cfg/apps/maintenance/admin/scheduled_admin.py +212 -301
- django_cfg/apps/maintenance/admin/site_admin.py +213 -352
- django_cfg/apps/newsletter/admin/__init__.py +29 -2
- django_cfg/apps/newsletter/admin/newsletter_admin.py +531 -193
- django_cfg/apps/payments/admin/__init__.py +18 -27
- django_cfg/apps/payments/admin/api_keys_admin.py +179 -546
- django_cfg/apps/payments/admin/balance_admin.py +166 -632
- django_cfg/apps/payments/admin/currencies_admin.py +235 -607
- django_cfg/apps/payments/admin/endpoint_groups_admin.py +127 -0
- django_cfg/apps/payments/admin/filters.py +83 -3
- django_cfg/apps/payments/admin/networks_admin.py +269 -0
- django_cfg/apps/payments/admin/payments_admin.py +183 -460
- django_cfg/apps/payments/admin/subscriptions_admin.py +119 -636
- django_cfg/apps/payments/admin/tariffs_admin.py +248 -0
- django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +153 -34
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +43 -17
- django_cfg/apps/payments/admin_interface/views/__init__.py +2 -0
- django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
- django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +109 -63
- django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
- django_cfg/apps/payments/config/__init__.py +14 -15
- django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
- django_cfg/apps/payments/config/helpers.py +8 -13
- django_cfg/apps/payments/management/commands/manage_currencies.py +236 -274
- django_cfg/apps/payments/management/commands/manage_providers.py +4 -1
- django_cfg/apps/payments/middleware/api_access.py +32 -6
- django_cfg/apps/payments/migrations/0001_initial.py +33 -46
- django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
- django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
- django_cfg/apps/payments/models/balance.py +12 -0
- django_cfg/apps/payments/models/currencies.py +106 -32
- django_cfg/apps/payments/models/managers/currency_managers.py +65 -0
- django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
- django_cfg/apps/payments/models/payments.py +94 -0
- django_cfg/apps/payments/services/core/base.py +4 -4
- django_cfg/apps/payments/services/core/currency_service.py +35 -28
- django_cfg/apps/payments/services/core/payment_service.py +266 -39
- django_cfg/apps/payments/services/providers/__init__.py +3 -0
- django_cfg/apps/payments/services/providers/base.py +303 -41
- django_cfg/apps/payments/services/providers/models/__init__.py +42 -0
- django_cfg/apps/payments/services/providers/models/base.py +145 -0
- django_cfg/apps/payments/services/providers/models/providers.py +87 -0
- django_cfg/apps/payments/services/providers/models/universal.py +48 -0
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +31 -0
- django_cfg/apps/payments/services/providers/nowpayments/config.py +70 -0
- django_cfg/apps/payments/services/providers/nowpayments/models.py +150 -0
- django_cfg/apps/payments/services/providers/nowpayments/parsers.py +879 -0
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +557 -0
- django_cfg/apps/payments/services/providers/nowpayments/sync.py +196 -0
- django_cfg/apps/payments/services/providers/registry.py +9 -37
- django_cfg/apps/payments/services/providers/sync_service.py +277 -0
- django_cfg/apps/payments/services/types/requests.py +19 -7
- django_cfg/apps/payments/signals/payment_signals.py +31 -2
- django_cfg/apps/payments/static/payments/js/api-client.js +29 -6
- django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
- django_cfg/apps/payments/static/payments/js/payment-form.js +98 -32
- django_cfg/apps/payments/tasks/__init__.py +39 -0
- django_cfg/apps/payments/tasks/types.py +73 -0
- django_cfg/apps/payments/tasks/usage_tracking.py +308 -0
- django_cfg/apps/payments/templates/admin/payments/_components/dashboard_header.html +23 -0
- django_cfg/apps/payments/templates/admin/payments/_components/stats_card.html +25 -0
- django_cfg/apps/payments/templates/admin/payments/_components/stats_grid.html +16 -0
- django_cfg/apps/payments/templates/admin/payments/apikey/change_list.html +39 -0
- django_cfg/apps/payments/templates/admin/payments/balance/change_list.html +50 -0
- django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +40 -0
- django_cfg/apps/payments/templates/admin/payments/payment/change_list.html +48 -0
- django_cfg/apps/payments/templates/admin/payments/subscription/change_list.html +48 -0
- django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
- django_cfg/apps/payments/urls.py +3 -2
- django_cfg/apps/payments/urls_admin.py +1 -1
- django_cfg/apps/payments/views/api/currencies.py +8 -5
- django_cfg/apps/payments/views/overview/services.py +2 -2
- django_cfg/apps/payments/views/serializers/currencies.py +22 -8
- django_cfg/apps/support/admin/__init__.py +10 -1
- django_cfg/apps/support/admin/support_admin.py +338 -141
- django_cfg/apps/tasks/admin/__init__.py +11 -0
- django_cfg/apps/tasks/admin/tasks_admin.py +430 -0
- django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
- django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
- django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
- django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
- django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
- django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
- django_cfg/apps/tasks/tasks/__init__.py +10 -0
- django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
- django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
- django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
- django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
- django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
- django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
- django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
- django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
- django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
- django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
- django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
- django_cfg/apps/tasks/urls.py +2 -2
- django_cfg/apps/tasks/urls_admin.py +2 -2
- django_cfg/apps/tasks/utils/__init__.py +1 -0
- django_cfg/apps/tasks/utils/simulator.py +356 -0
- django_cfg/apps/tasks/views/__init__.py +16 -0
- django_cfg/apps/tasks/views/api.py +569 -0
- django_cfg/apps/tasks/views/dashboard.py +58 -0
- django_cfg/config.py +1 -1
- django_cfg/core/config.py +10 -5
- django_cfg/core/generation.py +1 -1
- django_cfg/core/integration/__init__.py +21 -0
- django_cfg/management/commands/__init__.py +13 -1
- django_cfg/management/commands/migrate_all.py +9 -3
- django_cfg/management/commands/migrator.py +11 -6
- django_cfg/management/commands/rundramatiq.py +3 -2
- django_cfg/management/commands/rundramatiq_simulator.py +430 -0
- django_cfg/middleware/__init__.py +0 -2
- django_cfg/models/api_keys.py +115 -0
- django_cfg/models/constance.py +0 -11
- django_cfg/models/payments.py +137 -3
- django_cfg/modules/django_admin/__init__.py +64 -0
- django_cfg/modules/django_admin/decorators/__init__.py +13 -0
- django_cfg/modules/django_admin/decorators/actions.py +106 -0
- django_cfg/modules/django_admin/decorators/display.py +106 -0
- django_cfg/modules/django_admin/mixins/__init__.py +14 -0
- django_cfg/modules/django_admin/mixins/display_mixin.py +81 -0
- django_cfg/modules/django_admin/mixins/optimization_mixin.py +41 -0
- django_cfg/modules/django_admin/mixins/standalone_actions_mixin.py +202 -0
- django_cfg/modules/django_admin/models/__init__.py +20 -0
- django_cfg/modules/django_admin/models/action_models.py +33 -0
- django_cfg/modules/django_admin/models/badge_models.py +20 -0
- django_cfg/modules/django_admin/models/base.py +26 -0
- django_cfg/modules/django_admin/models/display_models.py +31 -0
- django_cfg/modules/django_admin/utils/badges.py +159 -0
- django_cfg/modules/django_admin/utils/displays.py +247 -0
- django_cfg/modules/django_currency/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/__init__.py +2 -2
- django_cfg/modules/django_currency/clients/hybrid_client.py +587 -0
- django_cfg/modules/django_currency/core/converter.py +12 -12
- django_cfg/modules/django_currency/database/__init__.py +2 -2
- django_cfg/modules/django_currency/database/database_loader.py +93 -42
- django_cfg/modules/django_llm/llm/client.py +10 -2
- django_cfg/modules/django_tasks.py +54 -21
- django_cfg/modules/django_unfold/callbacks/actions.py +1 -1
- django_cfg/modules/django_unfold/callbacks/statistics.py +1 -1
- django_cfg/modules/django_unfold/dashboard.py +14 -13
- django_cfg/modules/django_unfold/models/config.py +1 -1
- django_cfg/registry/core.py +7 -9
- django_cfg/registry/third_party.py +2 -2
- django_cfg/template_archive/django_sample.zip +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/METADATA +2 -1
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/RECORD +198 -160
- django_cfg/apps/accounts/admin/activity.py +0 -96
- django_cfg/apps/accounts/admin/group.py +0 -17
- django_cfg/apps/accounts/admin/otp.py +0 -59
- django_cfg/apps/accounts/admin/registration_source.py +0 -97
- django_cfg/apps/accounts/admin/twilio_response.py +0 -227
- django_cfg/apps/accounts/admin/user.py +0 -300
- django_cfg/apps/agents/core/agent.py +0 -281
- django_cfg/apps/payments/admin_interface/old/payments/base.html +0 -175
- django_cfg/apps/payments/admin_interface/old/payments/components/dev_tool_card.html +0 -125
- django_cfg/apps/payments/admin_interface/old/payments/components/loading_spinner.html +0 -16
- django_cfg/apps/payments/admin_interface/old/payments/components/ngrok_status_card.html +0 -113
- django_cfg/apps/payments/admin_interface/old/payments/components/notification.html +0 -27
- django_cfg/apps/payments/admin_interface/old/payments/components/provider_card.html +0 -86
- django_cfg/apps/payments/admin_interface/old/payments/components/status_card.html +0 -35
- django_cfg/apps/payments/admin_interface/old/payments/currency_converter.html +0 -382
- django_cfg/apps/payments/admin_interface/old/payments/payment_dashboard.html +0 -309
- django_cfg/apps/payments/admin_interface/old/payments/payment_form.html +0 -303
- django_cfg/apps/payments/admin_interface/old/payments/payment_list.html +0 -382
- django_cfg/apps/payments/admin_interface/old/payments/payment_status.html +0 -500
- django_cfg/apps/payments/admin_interface/old/payments/webhook_dashboard.html +0 -518
- django_cfg/apps/payments/admin_interface/old/static/payments/css/components.css +0 -619
- django_cfg/apps/payments/admin_interface/old/static/payments/css/dashboard.css +0 -188
- django_cfg/apps/payments/admin_interface/old/static/payments/js/components.js +0 -545
- django_cfg/apps/payments/admin_interface/old/static/payments/js/ngrok-status.js +0 -163
- django_cfg/apps/payments/admin_interface/old/static/payments/js/utils.js +0 -412
- django_cfg/apps/payments/config/constance/__init__.py +0 -22
- django_cfg/apps/payments/config/constance/config_service.py +0 -123
- django_cfg/apps/payments/config/constance/fields.py +0 -69
- django_cfg/apps/payments/config/constance/settings.py +0 -160
- django_cfg/apps/payments/services/providers/nowpayments.py +0 -478
- django_cfg/apps/tasks/admin.py +0 -320
- django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
- django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
- django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
- django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
- django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
- django_cfg/apps/tasks/templates/tasks/base.html +0 -96
- django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
- django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
- django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
- django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
- django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
- django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
- django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
- django_cfg/apps/tasks/views.py +0 -461
- django_cfg/management/commands/auto_generate.py +0 -486
- django_cfg/middleware/static_nocache.py +0 -55
- django_cfg/modules/django_currency/clients/yahoo_client.py +0 -157
- /django_cfg/modules/{django_unfold → django_admin}/icons/README.md +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/__init__.py +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/constants.py +0 -0
- /django_cfg/modules/{django_unfold → django_admin}/icons/generate_icons.py +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/WHEEL +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.3.7.dist-info → django_cfg-1.3.11.dist-info}/licenses/LICENSE +0 -0
@@ -12,7 +12,7 @@ from pydantic import BaseModel, Field, validator
|
|
12
12
|
from cachetools import TTLCache
|
13
13
|
|
14
14
|
# Our new clients
|
15
|
-
from ..clients import
|
15
|
+
from ..clients import HybridCurrencyClient, CoinPaprikaClient
|
16
16
|
|
17
17
|
logger = logging.getLogger(__name__)
|
18
18
|
|
@@ -28,11 +28,12 @@ class CoinPaprikaCoinInfo(BaseModel):
|
|
28
28
|
name: str = Field(description="Full coin name")
|
29
29
|
|
30
30
|
|
31
|
-
class
|
32
|
-
"""Single
|
31
|
+
class HybridCurrencyInfo(BaseModel):
|
32
|
+
"""Single currency information from hybrid client."""
|
33
33
|
code: str = Field(description="Currency code (e.g., USD)")
|
34
34
|
name: str = Field(description="Full currency name")
|
35
35
|
symbol: str = Field(default="", description="Currency symbol (e.g., $)")
|
36
|
+
currency_type: str = Field(description="Currency type (fiat, crypto, metal)")
|
36
37
|
|
37
38
|
|
38
39
|
class CurrencyRateInfo(BaseModel):
|
@@ -93,7 +94,7 @@ class CurrencyDatabaseLoader:
|
|
93
94
|
self.config = config or DatabaseLoaderConfig()
|
94
95
|
|
95
96
|
# Initialize clients
|
96
|
-
self.
|
97
|
+
self.hybrid = HybridCurrencyClient(cache_ttl=self.config.cache_ttl_hours * 3600)
|
97
98
|
self.coinpaprika = CoinPaprikaClient(cache_ttl=self.config.cache_ttl_hours * 3600)
|
98
99
|
|
99
100
|
# Rate limiters
|
@@ -107,36 +108,48 @@ class CurrencyDatabaseLoader:
|
|
107
108
|
|
108
109
|
logger.info(f"Initialized CurrencyDatabaseLoader with config: {self.config}")
|
109
110
|
|
110
|
-
def
|
111
|
+
def get_hybrid_currency_list(self) -> List[HybridCurrencyInfo]:
|
111
112
|
"""
|
112
|
-
Get list of supported
|
113
|
+
Get list of supported currencies from hybrid client.
|
113
114
|
|
114
115
|
Returns:
|
115
|
-
List of
|
116
|
+
List of currency info objects
|
116
117
|
"""
|
117
|
-
cache_key = "
|
118
|
+
cache_key = "hybrid_currencies"
|
118
119
|
|
119
120
|
if cache_key in self.fiat_cache:
|
120
|
-
logger.debug("Retrieved
|
121
|
+
logger.debug("Retrieved hybrid currencies from cache")
|
121
122
|
return self.fiat_cache[cache_key]
|
122
123
|
|
123
|
-
# Get supported currencies from
|
124
|
-
supported_currencies = self.
|
124
|
+
# Get supported currencies from Hybrid client
|
125
|
+
supported_currencies = self.hybrid.get_all_supported_currencies()
|
125
126
|
|
126
|
-
# Convert to our format
|
127
|
-
|
128
|
-
for code, name in
|
129
|
-
|
127
|
+
# Convert to our format
|
128
|
+
hybrid_currencies = []
|
129
|
+
for code, name in supported_currencies.items():
|
130
|
+
# Determine currency type based on code
|
131
|
+
if code in ['BTC', 'ETH', 'BNB', 'XRP', 'ADA', 'SOL', 'DOT', 'MATIC',
|
132
|
+
'LTC', 'BCH', 'LINK', 'UNI', 'ATOM', 'XLM', 'VET', 'FIL',
|
133
|
+
'TRX', 'ETC', 'THETA', 'AAVE', 'MKR', 'COMP', 'SUSHI',
|
134
|
+
'USDT', 'USDC', 'BUSD', 'DAI', 'TUSD', 'USDP']:
|
135
|
+
currency_type = "crypto"
|
136
|
+
elif code in ['XAU', 'XAG', 'XPT', 'XPD']:
|
137
|
+
currency_type = "metal"
|
138
|
+
else:
|
139
|
+
currency_type = "fiat"
|
140
|
+
|
141
|
+
currency_info = HybridCurrencyInfo(
|
130
142
|
code=code,
|
131
143
|
name=name,
|
132
|
-
symbol="" #
|
144
|
+
symbol="$" if code == "USD" else "", # Basic symbol mapping
|
145
|
+
currency_type=currency_type
|
133
146
|
)
|
134
|
-
|
147
|
+
hybrid_currencies.append(currency_info)
|
135
148
|
|
136
|
-
self.fiat_cache[cache_key] =
|
137
|
-
logger.info(f"Loaded {len(
|
149
|
+
self.fiat_cache[cache_key] = hybrid_currencies
|
150
|
+
logger.info(f"Loaded {len(hybrid_currencies)} currencies from hybrid client")
|
138
151
|
|
139
|
-
return
|
152
|
+
return hybrid_currencies
|
140
153
|
|
141
154
|
def get_cryptocurrency_list(self) -> List[CoinPaprikaCoinInfo]:
|
142
155
|
"""
|
@@ -233,7 +246,7 @@ class CurrencyDatabaseLoader:
|
|
233
246
|
self.yahoo_limiter()
|
234
247
|
|
235
248
|
try:
|
236
|
-
rate_obj = self.
|
249
|
+
rate_obj = self.hybrid.fetch_rate(base, quote)
|
237
250
|
return rate_obj.rate
|
238
251
|
except Exception as e:
|
239
252
|
logger.debug(f"Failed to get fiat rate {base}/{quote}: {e}")
|
@@ -241,48 +254,72 @@ class CurrencyDatabaseLoader:
|
|
241
254
|
|
242
255
|
def build_currency_database_data(self) -> List[CurrencyRateInfo]:
|
243
256
|
"""
|
244
|
-
Build complete currency database data
|
257
|
+
Build complete currency database data using hybrid client.
|
245
258
|
|
246
259
|
Returns:
|
247
260
|
List of currency rate info objects
|
248
261
|
"""
|
249
262
|
currencies = []
|
250
263
|
|
251
|
-
# Get
|
252
|
-
logger.info("Loading
|
253
|
-
|
264
|
+
# Get currencies from hybrid client
|
265
|
+
logger.info("Loading currencies from hybrid client...")
|
266
|
+
hybrid_currencies = self.get_hybrid_currency_list()
|
254
267
|
|
255
|
-
for
|
268
|
+
for currency in hybrid_currencies:
|
256
269
|
# Get USD rate
|
257
|
-
if
|
270
|
+
if currency.code == 'USD':
|
258
271
|
usd_rate = 1.0
|
259
272
|
else:
|
260
|
-
usd_rate = self.get_fiat_rate(
|
273
|
+
usd_rate = self.get_fiat_rate(currency.code, 'USD')
|
261
274
|
if usd_rate is None:
|
262
|
-
logger.warning(f"Could not get USD rate for {
|
275
|
+
logger.warning(f"Could not get USD rate for {currency.code}")
|
263
276
|
continue
|
264
277
|
|
278
|
+
# Set decimal places based on currency type and value
|
279
|
+
if currency.currency_type == "fiat":
|
280
|
+
decimal_places = 2
|
281
|
+
min_payment = 1.0
|
282
|
+
elif currency.currency_type == "crypto":
|
283
|
+
if usd_rate >= 1:
|
284
|
+
decimal_places = 2
|
285
|
+
elif usd_rate >= 0.01:
|
286
|
+
decimal_places = 4
|
287
|
+
else:
|
288
|
+
decimal_places = 8
|
289
|
+
min_payment = max(1.0 / usd_rate, 0.000001)
|
290
|
+
else: # metal
|
291
|
+
decimal_places = 4
|
292
|
+
min_payment = 0.001
|
293
|
+
|
265
294
|
currency_info = CurrencyRateInfo(
|
266
|
-
code=
|
267
|
-
name=
|
268
|
-
symbol=
|
269
|
-
currency_type=
|
270
|
-
decimal_places=
|
295
|
+
code=currency.code,
|
296
|
+
name=currency.name,
|
297
|
+
symbol=currency.symbol,
|
298
|
+
currency_type=currency.currency_type,
|
299
|
+
decimal_places=decimal_places,
|
271
300
|
usd_rate=usd_rate,
|
272
|
-
min_payment_amount=
|
301
|
+
min_payment_amount=min_payment
|
273
302
|
)
|
274
303
|
currencies.append(currency_info)
|
275
304
|
|
276
|
-
# Get cryptocurrencies
|
277
|
-
logger.info("Loading cryptocurrencies...")
|
305
|
+
# Get additional cryptocurrencies from CoinPaprika (for extended crypto coverage)
|
306
|
+
logger.info("Loading additional cryptocurrencies from CoinPaprika...")
|
278
307
|
crypto_currencies = self.get_cryptocurrency_list()
|
279
308
|
|
309
|
+
# Filter out cryptos that are already in hybrid client
|
310
|
+
hybrid_crypto_codes = {c.code for c in hybrid_currencies if c.currency_type == "crypto"}
|
311
|
+
|
280
312
|
if crypto_currencies:
|
281
313
|
# Get rates for all cryptos
|
282
|
-
crypto_symbols = [crypto.symbol for crypto in crypto_currencies
|
314
|
+
crypto_symbols = [crypto.symbol for crypto in crypto_currencies
|
315
|
+
if crypto.symbol not in hybrid_crypto_codes]
|
283
316
|
rates = self.get_currency_rates(crypto_symbols, 'usd')
|
284
317
|
|
285
318
|
for crypto in crypto_currencies:
|
319
|
+
# Skip if already covered by hybrid client
|
320
|
+
if crypto.symbol in hybrid_crypto_codes:
|
321
|
+
continue
|
322
|
+
|
286
323
|
if crypto.symbol in rates:
|
287
324
|
usd_rate = rates[crypto.symbol]
|
288
325
|
|
@@ -313,13 +350,27 @@ class CurrencyDatabaseLoader:
|
|
313
350
|
|
314
351
|
def get_statistics(self) -> Dict[str, int]:
|
315
352
|
"""Get loader statistics."""
|
316
|
-
|
317
|
-
|
353
|
+
hybrid_currencies = self.get_hybrid_currency_list()
|
354
|
+
coinpaprika_cryptos = self.get_cryptocurrency_list()
|
355
|
+
|
356
|
+
# Count by type from hybrid client
|
357
|
+
fiat_count = len([c for c in hybrid_currencies if c.currency_type == "fiat"])
|
358
|
+
hybrid_crypto_count = len([c for c in hybrid_currencies if c.currency_type == "crypto"])
|
359
|
+
metal_count = len([c for c in hybrid_currencies if c.currency_type == "metal"])
|
360
|
+
|
361
|
+
# Additional cryptos from CoinPaprika (excluding duplicates)
|
362
|
+
hybrid_crypto_codes = {c.code for c in hybrid_currencies if c.currency_type == "crypto"}
|
363
|
+
additional_crypto_count = len([c for c in coinpaprika_cryptos if c.symbol not in hybrid_crypto_codes])
|
364
|
+
|
365
|
+
total_crypto_count = hybrid_crypto_count + additional_crypto_count
|
318
366
|
|
319
367
|
return {
|
320
368
|
'total_fiat_currencies': fiat_count,
|
321
|
-
'total_cryptocurrencies':
|
322
|
-
'
|
369
|
+
'total_cryptocurrencies': total_crypto_count,
|
370
|
+
'total_metal_currencies': metal_count,
|
371
|
+
'hybrid_crypto_currencies': hybrid_crypto_count,
|
372
|
+
'coinpaprika_crypto_currencies': additional_crypto_count,
|
373
|
+
'total_currencies': fiat_count + total_crypto_count + metal_count,
|
323
374
|
'max_cryptocurrencies': self.config.max_cryptocurrencies,
|
324
375
|
'max_fiat_currencies': self.config.max_fiat_currencies,
|
325
376
|
'min_market_cap_usd': self.config.min_market_cap_usd
|
@@ -76,8 +76,16 @@ class LLMClient(BaseCfgModule):
|
|
76
76
|
django_config = self.get_config()
|
77
77
|
if django_config:
|
78
78
|
if apikey_openai is None:
|
79
|
-
|
80
|
-
|
79
|
+
# Try new api_keys system first, then fallback to old attribute
|
80
|
+
if hasattr(django_config, 'api_keys') and django_config.api_keys:
|
81
|
+
apikey_openai = django_config.api_keys.get_openai_key()
|
82
|
+
else:
|
83
|
+
apikey_openai = getattr(django_config, 'openai_api_key', None)
|
84
|
+
|
85
|
+
if apikey_openrouter is None:
|
86
|
+
# Try new api_keys system first
|
87
|
+
if hasattr(django_config, 'api_keys') and django_config.api_keys:
|
88
|
+
apikey_openrouter = django_config.api_keys.get_openrouter_key()
|
81
89
|
|
82
90
|
# Store API keys and preferred provider
|
83
91
|
self.apikey_openrouter = apikey_openrouter
|
@@ -86,29 +86,49 @@ class DjangoTasks(BaseCfgModule):
|
|
86
86
|
return True
|
87
87
|
|
88
88
|
def get_redis_url(self) -> Optional[str]:
|
89
|
-
"""Get Redis URL
|
89
|
+
"""Get Redis URL using the same logic as Dramatiq settings generation."""
|
90
90
|
if self._redis_url is None:
|
91
|
+
# Use BaseCfgModule to get config (same as generate_dramatiq_settings_from_config)
|
92
|
+
config = self.get_config()
|
93
|
+
|
94
|
+
if not config:
|
95
|
+
raise RuntimeError("No Django-CFG configuration available")
|
96
|
+
|
97
|
+
# Get Redis URL from cache config (same logic as generate_dramatiq_settings_from_config)
|
98
|
+
if hasattr(config, 'cache_default') and config.cache_default:
|
99
|
+
self._redis_url = getattr(config.cache_default, 'redis_url', None)
|
100
|
+
if self._redis_url:
|
101
|
+
logger.debug(f"Got Redis URL from cache config: {self._redis_url}")
|
102
|
+
return self._redis_url
|
103
|
+
|
104
|
+
# If no cache_default, try to get from Django cache settings
|
91
105
|
try:
|
92
|
-
from
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
logger.warning("Could not import config from api.config")
|
101
|
-
|
102
|
-
if django_config and hasattr(django_config, 'cache_default') and django_config.cache_default:
|
103
|
-
cache_config = django_config.cache_default
|
104
|
-
if hasattr(cache_config, 'redis_url') and cache_config.redis_url:
|
105
|
-
self._redis_url = cache_config.redis_url
|
106
|
-
logger.debug(f"Got Redis URL: {self._redis_url}")
|
107
|
-
elif hasattr(cache_config, 'location') and cache_config.location:
|
108
|
-
self._redis_url = cache_config.location
|
109
|
-
logger.debug(f"Got Redis URL from location: {self._redis_url}")
|
106
|
+
from django.conf import settings
|
107
|
+
if hasattr(settings, 'CACHES') and 'default' in settings.CACHES:
|
108
|
+
cache_config = settings.CACHES['default']
|
109
|
+
if cache_config.get('BACKEND') == 'django_redis.cache.RedisCache':
|
110
|
+
self._redis_url = cache_config.get('LOCATION')
|
111
|
+
if self._redis_url:
|
112
|
+
logger.debug(f"Got Redis URL from Django cache settings: {self._redis_url}")
|
113
|
+
return self._redis_url
|
110
114
|
except Exception as e:
|
111
|
-
logger.
|
115
|
+
logger.debug(f"Could not get Redis URL from Django settings: {e}")
|
116
|
+
|
117
|
+
# Try to get from DRAMATIQ_BROKER settings
|
118
|
+
try:
|
119
|
+
from django.conf import settings
|
120
|
+
if hasattr(settings, 'DRAMATIQ_BROKER'):
|
121
|
+
dramatiq_config = settings.DRAMATIQ_BROKER
|
122
|
+
if isinstance(dramatiq_config, dict) and 'OPTIONS' in dramatiq_config:
|
123
|
+
self._redis_url = dramatiq_config['OPTIONS'].get('url')
|
124
|
+
if self._redis_url:
|
125
|
+
logger.debug(f"Got Redis URL from DRAMATIQ_BROKER settings: {self._redis_url}")
|
126
|
+
return self._redis_url
|
127
|
+
except Exception as e:
|
128
|
+
logger.debug(f"Could not get Redis URL from DRAMATIQ_BROKER settings: {e}")
|
129
|
+
|
130
|
+
# If still no Redis URL found, raise error (no fallbacks)
|
131
|
+
raise RuntimeError("No Redis URL found in cache configuration, Django settings, or DRAMATIQ_BROKER")
|
112
132
|
|
113
133
|
return self._redis_url
|
114
134
|
|
@@ -120,10 +140,23 @@ class DjangoTasks(BaseCfgModule):
|
|
120
140
|
|
121
141
|
try:
|
122
142
|
parsed = urlparse(redis_url)
|
143
|
+
|
144
|
+
# Extract database from URL path, fallback to config or default
|
145
|
+
db = 1 # Default
|
146
|
+
if parsed.path and parsed.path != "/":
|
147
|
+
try:
|
148
|
+
db = int(parsed.path.lstrip('/'))
|
149
|
+
except ValueError:
|
150
|
+
pass
|
151
|
+
elif self.config and self.config.dramatiq:
|
152
|
+
db = self.config.dramatiq.redis_db
|
153
|
+
|
154
|
+
logger.debug(f"Using Redis DB: {db} from URL: {redis_url}")
|
155
|
+
|
123
156
|
return redis.Redis(
|
124
157
|
host=parsed.hostname or 'localhost',
|
125
158
|
port=parsed.port or 6379,
|
126
|
-
db=
|
159
|
+
db=db,
|
127
160
|
password=parsed.password,
|
128
161
|
socket_timeout=5
|
129
162
|
)
|
@@ -9,7 +9,7 @@ from typing import List, Dict, Any, Optional
|
|
9
9
|
from django.templatetags.static import static
|
10
10
|
from django.urls import reverse_lazy
|
11
11
|
from ..base import BaseCfgModule
|
12
|
-
from .icons import Icons
|
12
|
+
from django_cfg.modules.django_admin.icons import Icons
|
13
13
|
from .models.navigation import NavigationSection, NavigationItem
|
14
14
|
from .models.dashboard import StatCard, StatsCardsWidget
|
15
15
|
|
@@ -176,29 +176,30 @@ class DashboardManager(BaseCfgModule):
|
|
176
176
|
|
177
177
|
# Always show basic admin models (even if payments functionality is disabled)
|
178
178
|
payments_items.extend([
|
179
|
-
NavigationItem(title="Payments", icon=Icons.ACCOUNT_BALANCE, link="/admin/payments/universalpayment/"),
|
179
|
+
NavigationItem(title="Universal Payments", icon=Icons.ACCOUNT_BALANCE, link="/admin/payments/universalpayment/"),
|
180
180
|
NavigationItem(title="Currencies", icon=Icons.CURRENCY_BITCOIN, link="/admin/payments/currency/"),
|
181
|
-
NavigationItem(title="
|
181
|
+
NavigationItem(title="Networks", icon=Icons.LINK, link="/admin/payments/network/"),
|
182
182
|
NavigationItem(title="Provider Currencies", icon=Icons.ACCOUNT_CIRCLE, link="/admin/payments/providercurrency/"),
|
183
183
|
])
|
184
184
|
|
185
185
|
# Add advanced features only if payments functionality is enabled
|
186
186
|
if config.enabled:
|
187
|
-
payments_items.append(
|
188
|
-
|
189
|
-
)
|
190
|
-
payments_items.append(
|
191
|
-
|
192
|
-
)
|
193
|
-
payments_items.append(
|
194
|
-
|
195
|
-
)
|
187
|
+
# payments_items.append(
|
188
|
+
# NavigationItem(title="Webhook Dashboard", icon=Icons.WEBHOOK, link="/cfg/admin/django_cfg_payments/admin/webhooks/")
|
189
|
+
# )
|
190
|
+
# payments_items.append(
|
191
|
+
# NavigationItem(title="Create Payment", icon=Icons.ADD, link="/cfg/admin/django_cfg_payments/admin/payments/create/")
|
192
|
+
# )
|
193
|
+
# payments_items.append(
|
194
|
+
# NavigationItem(title="Currency Converter", icon=Icons.CURRENCY_EXCHANGE, link="/cfg/admin/django_cfg_payments/admin/tools/converter/")
|
195
|
+
# )
|
196
196
|
|
197
197
|
# Show subscription features only if enabled
|
198
198
|
if config.show_subscription_management():
|
199
199
|
payments_items.extend([
|
200
200
|
NavigationItem(title="Subscriptions", icon=Icons.PERSON_ADD, link="/admin/payments/subscription/"),
|
201
201
|
NavigationItem(title="Tariffs", icon=Icons.PRICE_CHANGE, link="/admin/payments/tariff/"),
|
202
|
+
NavigationItem(title="Tariff Endpoint Groups", icon=Icons.GROUP, link="/admin/payments/tariffendpointgroup/"),
|
202
203
|
])
|
203
204
|
|
204
205
|
# Show API management only if enabled
|
@@ -223,7 +224,7 @@ class DashboardManager(BaseCfgModule):
|
|
223
224
|
# Fallback
|
224
225
|
payments_items = [
|
225
226
|
NavigationItem(title="Payment Dashboard", icon=Icons.DASHBOARD, link="/cfg/admin/django_cfg_payments/admin/"),
|
226
|
-
NavigationItem(title="Payments", icon=Icons.ACCOUNT_BALANCE, link="/admin/payments/universalpayment/"),
|
227
|
+
NavigationItem(title="Universal Payments", icon=Icons.ACCOUNT_BALANCE, link="/admin/payments/universalpayment/"),
|
227
228
|
]
|
228
229
|
|
229
230
|
navigation_sections.append(NavigationSection(
|
@@ -10,7 +10,7 @@ from ...base import BaseCfgModule
|
|
10
10
|
from .navigation import NavigationSection
|
11
11
|
from .dropdown import SiteDropdownItem
|
12
12
|
from .tabs import TabConfiguration
|
13
|
-
from
|
13
|
+
from django_cfg.modules.django_admin.icons import Icons
|
14
14
|
import logging
|
15
15
|
|
16
16
|
logger = logging.getLogger(__name__)
|
django_cfg/registry/core.py
CHANGED
@@ -35,6 +35,9 @@ CORE_REGISTRY = {
|
|
35
35
|
# Limits models
|
36
36
|
"LimitsConfig": ("django_cfg.models.limits", "LimitsConfig"),
|
37
37
|
|
38
|
+
# API Keys models
|
39
|
+
"ApiKeys": ("django_cfg.models.api_keys", "ApiKeys"),
|
40
|
+
|
38
41
|
# JWT models
|
39
42
|
"JWTConfig": ("django_cfg.models.jwt", "JWTConfig"),
|
40
43
|
|
@@ -42,16 +45,11 @@ CORE_REGISTRY = {
|
|
42
45
|
"TaskConfig": ("django_cfg.models.tasks", "TaskConfig"),
|
43
46
|
"DramatiqConfig": ("django_cfg.models.tasks", "DramatiqConfig"),
|
44
47
|
|
45
|
-
# Payment system models
|
48
|
+
# Payment system models (BaseCfgAutoModule)
|
46
49
|
"PaymentsConfig": ("django_cfg.models.payments", "PaymentsConfig"),
|
47
|
-
"
|
48
|
-
"
|
49
|
-
"
|
50
|
-
"StripeConfig": ("django_cfg.models.payments", "StripeConfig"),
|
51
|
-
"create_nowpayments_config": ("django_cfg.models.payments", "create_nowpayments_config"),
|
52
|
-
"create_cryptapi_config": ("django_cfg.models.payments", "create_cryptapi_config"),
|
53
|
-
"create_stripe_config": ("django_cfg.models.payments", "create_stripe_config"),
|
54
|
-
"create_cryptomus_config": ("django_cfg.models.payments", "create_cryptomus_config"),
|
50
|
+
"ProviderAPIKeysConfig": ("django_cfg.models.payments", "ProviderAPIKeysConfig"),
|
51
|
+
"BaseProviderConfig": ("django_cfg.models.payments", "BaseProviderConfig"),
|
52
|
+
"NowPaymentsProviderConfig": ("django_cfg.models.payments", "NowPaymentsProviderConfig"),
|
55
53
|
|
56
54
|
# Pagination classes
|
57
55
|
"DefaultPagination": ("django_cfg.middleware.pagination", "DefaultPagination"),
|
@@ -47,6 +47,6 @@ THIRD_PARTY_REGISTRY = {
|
|
47
47
|
"NgrokTunnelConfig": ("django_cfg.models.ngrok", "NgrokTunnelConfig"),
|
48
48
|
|
49
49
|
# Material Icons
|
50
|
-
"Icons": ("django_cfg.modules.
|
51
|
-
"IconCategories": ("django_cfg.modules.
|
50
|
+
"Icons": ("django_cfg.modules.django_admin.icons", "Icons"),
|
51
|
+
"IconCategories": ("django_cfg.modules.django_admin.icons", "IconCategories"),
|
52
52
|
}
|
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: django-cfg
|
3
|
-
Version: 1.3.
|
3
|
+
Version: 1.3.11
|
4
4
|
Summary: 🚀 Next-gen Django configuration: type-safety, AI features, blazing-fast setup, and automated best practices — all in one.
|
5
5
|
Project-URL: Homepage, https://djangocfg.com
|
6
6
|
Project-URL: Documentation, https://docs.djangocfg.com
|
@@ -60,6 +60,7 @@ Requires-Dist: drf-spectacular<1.0,>=0.28.0
|
|
60
60
|
Requires-Dist: hiredis<4.0,>=2.0.0
|
61
61
|
Requires-Dist: loguru<1.0,>=0.7.0
|
62
62
|
Requires-Dist: lxml<7.0,>=6.0.0
|
63
|
+
Requires-Dist: mypy<2.0.0,>=1.18.2
|
63
64
|
Requires-Dist: ngrok>=1.5.1; python_version >= '3.12'
|
64
65
|
Requires-Dist: openai<2.0,>=1.107.0
|
65
66
|
Requires-Dist: pgvector<1.0,>=0.4.0
|