django-cfg 1.2.31__py3-none-any.whl → 1.3.1__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/api/health/views.py +4 -2
- django_cfg/apps/knowbase/config/settings.py +16 -15
- django_cfg/apps/payments/README.md +326 -0
- django_cfg/apps/payments/admin/__init__.py +20 -10
- django_cfg/apps/payments/admin/api_keys_admin.py +521 -237
- django_cfg/apps/payments/admin/balance_admin.py +592 -297
- django_cfg/apps/payments/admin/currencies_admin.py +526 -222
- django_cfg/apps/payments/admin/filters.py +306 -199
- django_cfg/apps/payments/admin/payments_admin.py +465 -70
- django_cfg/apps/payments/admin/subscriptions_admin.py +578 -128
- django_cfg/apps/payments/admin_interface/__init__.py +18 -0
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +162 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/dev_tool_card.html +38 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/loading_spinner.html +16 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/notification.html +27 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/provider_card.html +86 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_card.html +39 -0
- django_cfg/apps/payments/admin_interface/templates/payments/currency_converter.html +382 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +300 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +303 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +382 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_status.html +500 -0
- django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +594 -0
- django_cfg/apps/payments/admin_interface/views/__init__.py +23 -0
- django_cfg/apps/payments/admin_interface/views/payment_views.py +259 -0
- django_cfg/apps/payments/admin_interface/views/webhook_dashboard.py +37 -0
- django_cfg/apps/payments/apps.py +34 -9
- django_cfg/apps/payments/config/__init__.py +28 -51
- django_cfg/apps/payments/config/constance/__init__.py +22 -0
- django_cfg/apps/payments/config/constance/config_service.py +123 -0
- django_cfg/apps/payments/config/constance/fields.py +69 -0
- django_cfg/apps/payments/config/constance/settings.py +160 -0
- django_cfg/apps/payments/config/django_cfg_integration.py +202 -0
- django_cfg/apps/payments/config/helpers.py +130 -0
- django_cfg/apps/payments/management/__init__.py +1 -3
- django_cfg/apps/payments/management/commands/__init__.py +1 -3
- django_cfg/apps/payments/management/commands/manage_currencies.py +303 -151
- django_cfg/apps/payments/management/commands/manage_providers.py +333 -160
- django_cfg/apps/payments/middleware/__init__.py +3 -1
- django_cfg/apps/payments/middleware/api_access.py +329 -222
- django_cfg/apps/payments/middleware/rate_limiting.py +342 -152
- django_cfg/apps/payments/middleware/usage_tracking.py +249 -240
- django_cfg/apps/payments/migrations/0001_initial.py +708 -536
- django_cfg/apps/payments/models/__init__.py +13 -18
- django_cfg/apps/payments/models/api_keys.py +121 -43
- django_cfg/apps/payments/models/balance.py +150 -115
- django_cfg/apps/payments/models/base.py +68 -15
- django_cfg/apps/payments/models/currencies.py +172 -148
- django_cfg/apps/payments/models/managers/__init__.py +44 -0
- django_cfg/apps/payments/models/managers/api_key_managers.py +329 -0
- django_cfg/apps/payments/models/managers/balance_managers.py +599 -0
- django_cfg/apps/payments/models/managers/currency_managers.py +385 -0
- django_cfg/apps/payments/models/managers/payment_managers.py +511 -0
- django_cfg/apps/payments/models/managers/subscription_managers.py +641 -0
- django_cfg/apps/payments/models/payments.py +235 -285
- django_cfg/apps/payments/models/subscriptions.py +257 -177
- django_cfg/apps/payments/models/tariffs.py +147 -40
- django_cfg/apps/payments/services/__init__.py +209 -56
- django_cfg/apps/payments/services/cache/__init__.py +6 -6
- django_cfg/apps/payments/services/cache/{simple_cache.py → cache_service.py} +112 -12
- django_cfg/apps/payments/services/core/__init__.py +10 -6
- django_cfg/apps/payments/services/core/balance_service.py +435 -360
- django_cfg/apps/payments/services/core/base.py +166 -0
- django_cfg/apps/payments/services/core/currency_service.py +478 -0
- django_cfg/apps/payments/services/core/payment_service.py +346 -467
- django_cfg/apps/payments/services/core/subscription_service.py +425 -481
- django_cfg/apps/payments/services/core/webhook_service.py +410 -0
- django_cfg/apps/payments/services/integrations/__init__.py +29 -0
- django_cfg/apps/payments/services/integrations/ngrok_service.py +47 -0
- django_cfg/apps/payments/services/integrations/providers_config.py +107 -0
- django_cfg/apps/payments/services/providers/__init__.py +9 -14
- django_cfg/apps/payments/services/providers/base.py +234 -174
- django_cfg/apps/payments/services/providers/nowpayments.py +478 -0
- django_cfg/apps/payments/services/providers/registry.py +367 -301
- django_cfg/apps/payments/services/types/__init__.py +78 -0
- django_cfg/apps/payments/services/types/data.py +177 -0
- django_cfg/apps/payments/services/types/requests.py +150 -0
- django_cfg/apps/payments/services/types/responses.py +156 -0
- django_cfg/apps/payments/services/types/webhooks.py +232 -0
- django_cfg/apps/payments/signals/__init__.py +33 -8
- django_cfg/apps/payments/signals/api_key_signals.py +210 -129
- django_cfg/apps/payments/signals/balance_signals.py +174 -0
- django_cfg/apps/payments/signals/payment_signals.py +128 -103
- django_cfg/apps/payments/signals/subscription_signals.py +194 -142
- django_cfg/apps/payments/static/payments/css/components.css +380 -0
- django_cfg/apps/payments/static/payments/css/dashboard.css +188 -0
- django_cfg/apps/payments/static/payments/js/components.js +545 -0
- django_cfg/apps/payments/static/payments/js/utils.js +412 -0
- django_cfg/apps/payments/templatetags/__init__.py +1 -1
- django_cfg/apps/payments/templatetags/payment_tags.py +466 -0
- django_cfg/apps/payments/urls.py +45 -48
- django_cfg/apps/payments/urls_admin.py +33 -42
- django_cfg/apps/payments/views/api/__init__.py +101 -0
- django_cfg/apps/payments/views/api/api_keys.py +387 -0
- django_cfg/apps/payments/views/api/balances.py +381 -0
- django_cfg/apps/payments/views/api/base.py +298 -0
- django_cfg/apps/payments/views/api/currencies.py +402 -0
- django_cfg/apps/payments/views/api/payments.py +415 -0
- django_cfg/apps/payments/views/api/subscriptions.py +475 -0
- django_cfg/apps/payments/views/api/webhooks.py +476 -0
- django_cfg/apps/payments/views/serializers/__init__.py +99 -0
- django_cfg/apps/payments/views/serializers/api_keys.py +424 -0
- django_cfg/apps/payments/views/serializers/balances.py +300 -0
- django_cfg/apps/payments/views/serializers/currencies.py +335 -0
- django_cfg/apps/payments/views/serializers/payments.py +387 -0
- django_cfg/apps/payments/views/serializers/subscriptions.py +429 -0
- django_cfg/apps/payments/views/serializers/webhooks.py +137 -0
- django_cfg/config.py +1 -1
- django_cfg/core/config.py +40 -4
- django_cfg/core/generation.py +25 -4
- django_cfg/core/integration/README.md +363 -0
- django_cfg/core/integration/__init__.py +47 -0
- django_cfg/core/integration/commands_collector.py +239 -0
- django_cfg/core/integration/display/__init__.py +15 -0
- django_cfg/core/integration/display/base.py +157 -0
- django_cfg/core/integration/display/ngrok.py +164 -0
- django_cfg/core/integration/display/startup.py +815 -0
- django_cfg/core/integration/url_integration.py +123 -0
- django_cfg/core/integration/version_checker.py +160 -0
- django_cfg/management/commands/auto_generate.py +4 -0
- django_cfg/management/commands/check_settings.py +6 -0
- django_cfg/management/commands/clear_constance.py +5 -2
- django_cfg/management/commands/create_token.py +6 -0
- django_cfg/management/commands/list_urls.py +6 -0
- django_cfg/management/commands/migrate_all.py +6 -0
- django_cfg/management/commands/migrator.py +3 -0
- django_cfg/management/commands/rundramatiq.py +6 -0
- django_cfg/management/commands/runserver_ngrok.py +51 -29
- django_cfg/management/commands/script.py +6 -0
- django_cfg/management/commands/show_config.py +12 -2
- django_cfg/management/commands/show_urls.py +4 -0
- django_cfg/management/commands/superuser.py +6 -0
- django_cfg/management/commands/task_clear.py +4 -1
- django_cfg/management/commands/task_status.py +3 -1
- django_cfg/management/commands/test_email.py +3 -0
- django_cfg/management/commands/test_telegram.py +6 -0
- django_cfg/management/commands/test_twilio.py +6 -0
- django_cfg/management/commands/tree.py +6 -0
- django_cfg/management/commands/validate_config.py +155 -149
- django_cfg/models/constance.py +31 -11
- django_cfg/models/payments.py +175 -492
- django_cfg/modules/django_logger.py +160 -146
- django_cfg/modules/django_unfold/dashboard.py +64 -16
- django_cfg/registry/core.py +1 -0
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/utils/smart_defaults.py +222 -571
- django_cfg/utils/toolkit.py +51 -11
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/METADATA +4 -1
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/RECORD +153 -185
- django_cfg/apps/payments/__init__.py +0 -8
- django_cfg/apps/payments/admin/tariffs_admin.py +0 -199
- django_cfg/apps/payments/config/module.py +0 -70
- django_cfg/apps/payments/config/providers.py +0 -105
- django_cfg/apps/payments/config/settings.py +0 -96
- django_cfg/apps/payments/config/utils.py +0 -52
- django_cfg/apps/payments/decorators.py +0 -291
- django_cfg/apps/payments/management/commands/README.md +0 -146
- django_cfg/apps/payments/management/commands/currency_stats.py +0 -304
- django_cfg/apps/payments/managers/__init__.py +0 -23
- django_cfg/apps/payments/managers/api_key_manager.py +0 -35
- django_cfg/apps/payments/managers/balance_manager.py +0 -361
- django_cfg/apps/payments/managers/currency_manager.py +0 -306
- django_cfg/apps/payments/managers/payment_manager.py +0 -192
- django_cfg/apps/payments/managers/subscription_manager.py +0 -37
- django_cfg/apps/payments/managers/tariff_manager.py +0 -29
- django_cfg/apps/payments/migrations/0002_network_providercurrency_and_more.py +0 -241
- django_cfg/apps/payments/migrations/0003_add_usd_rate_cache.py +0 -30
- django_cfg/apps/payments/models/events.py +0 -73
- django_cfg/apps/payments/serializers/__init__.py +0 -57
- django_cfg/apps/payments/serializers/api_keys.py +0 -51
- django_cfg/apps/payments/serializers/balance.py +0 -59
- django_cfg/apps/payments/serializers/currencies.py +0 -63
- django_cfg/apps/payments/serializers/payments.py +0 -62
- django_cfg/apps/payments/serializers/subscriptions.py +0 -71
- django_cfg/apps/payments/serializers/tariffs.py +0 -56
- django_cfg/apps/payments/services/billing/__init__.py +0 -8
- django_cfg/apps/payments/services/cache/base.py +0 -30
- django_cfg/apps/payments/services/core/fallback_service.py +0 -432
- django_cfg/apps/payments/services/internal_types.py +0 -461
- django_cfg/apps/payments/services/middleware/__init__.py +0 -8
- django_cfg/apps/payments/services/monitoring/__init__.py +0 -22
- django_cfg/apps/payments/services/monitoring/api_schemas.py +0 -76
- django_cfg/apps/payments/services/monitoring/provider_health.py +0 -372
- django_cfg/apps/payments/services/providers/cryptapi/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/cryptapi/config.py +0 -8
- django_cfg/apps/payments/services/providers/cryptapi/models.py +0 -192
- django_cfg/apps/payments/services/providers/cryptapi/provider.py +0 -439
- django_cfg/apps/payments/services/providers/cryptomus/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/cryptomus/models.py +0 -176
- django_cfg/apps/payments/services/providers/cryptomus/provider.py +0 -429
- django_cfg/apps/payments/services/providers/cryptomus/provider_v2.py +0 -564
- django_cfg/apps/payments/services/providers/models/__init__.py +0 -34
- django_cfg/apps/payments/services/providers/models/currencies.py +0 -190
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/nowpayments/models.py +0 -196
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +0 -380
- django_cfg/apps/payments/services/providers/stripe/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/stripe/models.py +0 -184
- django_cfg/apps/payments/services/providers/stripe/provider.py +0 -109
- django_cfg/apps/payments/services/security/__init__.py +0 -34
- django_cfg/apps/payments/services/security/error_handler.py +0 -635
- django_cfg/apps/payments/services/security/payment_notifications.py +0 -342
- django_cfg/apps/payments/services/security/webhook_validator.py +0 -474
- django_cfg/apps/payments/static/payments/css/payments.css +0 -340
- django_cfg/apps/payments/static/payments/js/notifications.js +0 -202
- django_cfg/apps/payments/static/payments/js/payment-utils.js +0 -318
- django_cfg/apps/payments/static/payments/js/theme.js +0 -86
- django_cfg/apps/payments/tasks/__init__.py +0 -12
- django_cfg/apps/payments/tasks/webhook_processing.py +0 -177
- django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +0 -50
- django_cfg/apps/payments/templates/payments/base.html +0 -182
- django_cfg/apps/payments/templates/payments/components/payment_card.html +0 -201
- django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +0 -109
- django_cfg/apps/payments/templates/payments/components/progress_bar.html +0 -43
- django_cfg/apps/payments/templates/payments/components/provider_stats.html +0 -40
- django_cfg/apps/payments/templates/payments/components/status_badge.html +0 -34
- django_cfg/apps/payments/templates/payments/components/status_overview.html +0 -148
- django_cfg/apps/payments/templates/payments/dashboard.html +0 -258
- django_cfg/apps/payments/templates/payments/dashboard_simple_test.html +0 -35
- django_cfg/apps/payments/templates/payments/payment_create.html +0 -579
- django_cfg/apps/payments/templates/payments/payment_detail.html +0 -373
- django_cfg/apps/payments/templates/payments/payment_list.html +0 -354
- django_cfg/apps/payments/templates/payments/stats.html +0 -261
- django_cfg/apps/payments/templates/payments/test.html +0 -213
- django_cfg/apps/payments/templatetags/payments_tags.py +0 -315
- django_cfg/apps/payments/utils/__init__.py +0 -43
- django_cfg/apps/payments/utils/billing_utils.py +0 -342
- django_cfg/apps/payments/utils/config_utils.py +0 -239
- django_cfg/apps/payments/utils/middleware_utils.py +0 -228
- django_cfg/apps/payments/utils/validation_utils.py +0 -94
- django_cfg/apps/payments/views/__init__.py +0 -63
- django_cfg/apps/payments/views/api_key_views.py +0 -164
- django_cfg/apps/payments/views/balance_views.py +0 -75
- django_cfg/apps/payments/views/currency_views.py +0 -122
- django_cfg/apps/payments/views/payment_views.py +0 -149
- django_cfg/apps/payments/views/subscription_views.py +0 -135
- django_cfg/apps/payments/views/tariff_views.py +0 -131
- django_cfg/apps/payments/views/templates/__init__.py +0 -25
- django_cfg/apps/payments/views/templates/ajax.py +0 -451
- django_cfg/apps/payments/views/templates/base.py +0 -212
- django_cfg/apps/payments/views/templates/dashboard.py +0 -60
- django_cfg/apps/payments/views/templates/payment_detail.py +0 -102
- django_cfg/apps/payments/views/templates/payment_management.py +0 -158
- django_cfg/apps/payments/views/templates/qr_code.py +0 -174
- django_cfg/apps/payments/views/templates/stats.py +0 -244
- django_cfg/apps/payments/views/templates/utils.py +0 -181
- django_cfg/apps/payments/views/webhook_views.py +0 -266
- django_cfg/apps/payments/viewsets.py +0 -66
- django_cfg/core/integration.py +0 -160
- django_cfg/template_archive/.gitignore +0 -1
- django_cfg/template_archive/__init__.py +0 -0
- django_cfg/urls.py +0 -33
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/WHEEL +0 -0
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,385 @@
|
|
1
|
+
"""
|
2
|
+
Currency managers for the Universal Payment System v2.0.
|
3
|
+
|
4
|
+
Optimized querysets and managers for currency operations with django_currency integration.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from django.db import models
|
8
|
+
from django_cfg.modules.django_logger import get_logger
|
9
|
+
|
10
|
+
logger = get_logger("currency_managers")
|
11
|
+
|
12
|
+
|
13
|
+
class CurrencyQuerySet(models.QuerySet):
|
14
|
+
"""
|
15
|
+
Optimized queryset for currency operations.
|
16
|
+
|
17
|
+
Provides efficient queries for currency management and conversion.
|
18
|
+
"""
|
19
|
+
|
20
|
+
def active(self):
|
21
|
+
"""Get active currencies."""
|
22
|
+
return self.filter(is_active=True)
|
23
|
+
|
24
|
+
def inactive(self):
|
25
|
+
"""Get inactive currencies."""
|
26
|
+
return self.filter(is_active=False)
|
27
|
+
|
28
|
+
def by_type(self, currency_type):
|
29
|
+
"""Filter by currency type (fiat/crypto)."""
|
30
|
+
return self.filter(currency_type=currency_type)
|
31
|
+
|
32
|
+
def crypto(self):
|
33
|
+
"""Get cryptocurrency currencies."""
|
34
|
+
return self.filter(currency_type='crypto')
|
35
|
+
|
36
|
+
def fiat(self):
|
37
|
+
"""Get fiat currencies."""
|
38
|
+
return self.filter(currency_type='fiat')
|
39
|
+
|
40
|
+
def by_code(self, code):
|
41
|
+
"""Filter by currency code."""
|
42
|
+
return self.filter(code=code.upper())
|
43
|
+
|
44
|
+
def supported_by_provider(self, provider):
|
45
|
+
"""
|
46
|
+
Get currencies supported by specific provider.
|
47
|
+
|
48
|
+
Args:
|
49
|
+
provider: Provider name (e.g., 'nowpayments')
|
50
|
+
"""
|
51
|
+
return self.filter(
|
52
|
+
provider_configs__provider=provider,
|
53
|
+
provider_configs__is_enabled=True,
|
54
|
+
is_active=True
|
55
|
+
).distinct()
|
56
|
+
|
57
|
+
def with_networks(self):
|
58
|
+
"""Get currencies that have associated networks (crypto only)."""
|
59
|
+
return self.crypto().filter(provider_configs__network__isnull=False).distinct()
|
60
|
+
|
61
|
+
def without_networks(self):
|
62
|
+
"""Get currencies without networks (typically fiat)."""
|
63
|
+
return self.filter(provider_configs__network__isnull=True).distinct()
|
64
|
+
|
65
|
+
def popular(self):
|
66
|
+
"""
|
67
|
+
Get popular currencies based on usage.
|
68
|
+
|
69
|
+
This would typically be based on payment volume or frequency.
|
70
|
+
For now, returns major currencies.
|
71
|
+
"""
|
72
|
+
popular_codes = ['USD', 'EUR', 'BTC', 'ETH', 'USDT', 'USDC']
|
73
|
+
return self.filter(code__in=popular_codes, is_active=True)
|
74
|
+
|
75
|
+
def search(self, query):
|
76
|
+
"""
|
77
|
+
Search currencies by code or name.
|
78
|
+
|
79
|
+
Args:
|
80
|
+
query: Search query string
|
81
|
+
"""
|
82
|
+
return self.filter(
|
83
|
+
models.Q(code__icontains=query) |
|
84
|
+
models.Q(name__icontains=query)
|
85
|
+
)
|
86
|
+
|
87
|
+
|
88
|
+
class CurrencyManager(models.Manager):
|
89
|
+
"""
|
90
|
+
Manager for currency operations with django_currency integration.
|
91
|
+
|
92
|
+
Provides high-level methods for currency management and conversion.
|
93
|
+
"""
|
94
|
+
|
95
|
+
def get_queryset(self):
|
96
|
+
"""Return custom queryset."""
|
97
|
+
return CurrencyQuerySet(self.model, using=self._db)
|
98
|
+
|
99
|
+
def active(self):
|
100
|
+
"""Get active currencies."""
|
101
|
+
return self.get_queryset().active()
|
102
|
+
|
103
|
+
def crypto(self):
|
104
|
+
"""Get active cryptocurrencies."""
|
105
|
+
return self.get_queryset().crypto().active()
|
106
|
+
|
107
|
+
def fiat(self):
|
108
|
+
"""Get active fiat currencies."""
|
109
|
+
return self.get_queryset().fiat().active()
|
110
|
+
|
111
|
+
def by_code(self, code):
|
112
|
+
"""Get currency by code."""
|
113
|
+
try:
|
114
|
+
return self.get_queryset().by_code(code).get()
|
115
|
+
except self.model.DoesNotExist:
|
116
|
+
return None
|
117
|
+
|
118
|
+
def supported_by_provider(self, provider):
|
119
|
+
"""Get currencies supported by provider."""
|
120
|
+
return self.get_queryset().supported_by_provider(provider)
|
121
|
+
|
122
|
+
def popular(self):
|
123
|
+
"""Get popular currencies."""
|
124
|
+
return self.get_queryset().popular()
|
125
|
+
|
126
|
+
def get_or_create_currency(self, code, name=None, currency_type=None, **kwargs):
|
127
|
+
"""
|
128
|
+
Get existing currency or create new one.
|
129
|
+
|
130
|
+
Args:
|
131
|
+
code: Currency code (e.g., 'BTC')
|
132
|
+
name: Currency name (e.g., 'Bitcoin')
|
133
|
+
currency_type: 'crypto' or 'fiat'
|
134
|
+
**kwargs: Additional currency fields
|
135
|
+
|
136
|
+
Returns:
|
137
|
+
tuple: (Currency, created)
|
138
|
+
"""
|
139
|
+
code = code.upper()
|
140
|
+
|
141
|
+
# Try to get existing currency
|
142
|
+
try:
|
143
|
+
currency = self.get(code=code)
|
144
|
+
return currency, False
|
145
|
+
except self.model.DoesNotExist:
|
146
|
+
pass
|
147
|
+
|
148
|
+
# Auto-detect currency type if not provided
|
149
|
+
if not currency_type:
|
150
|
+
# Simple heuristic: common fiat currencies
|
151
|
+
fiat_codes = ['USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD', 'CHF', 'CNY', 'RUB']
|
152
|
+
currency_type = 'fiat' if code in fiat_codes else 'crypto'
|
153
|
+
|
154
|
+
# Auto-generate name if not provided
|
155
|
+
if not name:
|
156
|
+
name = self._generate_currency_name(code, currency_type)
|
157
|
+
|
158
|
+
# Set defaults based on currency type
|
159
|
+
defaults = {
|
160
|
+
'name': name,
|
161
|
+
'currency_type': currency_type,
|
162
|
+
'decimal_places': 2 if currency_type == 'fiat' else 8,
|
163
|
+
'is_active': True,
|
164
|
+
**kwargs
|
165
|
+
}
|
166
|
+
|
167
|
+
currency = self.create(code=code, **defaults)
|
168
|
+
|
169
|
+
logger.info(f"Created new currency", extra={
|
170
|
+
'code': code,
|
171
|
+
'name': name,
|
172
|
+
'currency_type': currency_type
|
173
|
+
})
|
174
|
+
|
175
|
+
return currency, True
|
176
|
+
|
177
|
+
def _generate_currency_name(self, code, currency_type):
|
178
|
+
"""Generate currency name from code."""
|
179
|
+
# Common currency names
|
180
|
+
names = {
|
181
|
+
# Fiat
|
182
|
+
'USD': 'US Dollar',
|
183
|
+
'EUR': 'Euro',
|
184
|
+
'GBP': 'British Pound',
|
185
|
+
'JPY': 'Japanese Yen',
|
186
|
+
'CAD': 'Canadian Dollar',
|
187
|
+
'AUD': 'Australian Dollar',
|
188
|
+
'CHF': 'Swiss Franc',
|
189
|
+
'CNY': 'Chinese Yuan',
|
190
|
+
'RUB': 'Russian Ruble',
|
191
|
+
|
192
|
+
# Crypto
|
193
|
+
'BTC': 'Bitcoin',
|
194
|
+
'ETH': 'Ethereum',
|
195
|
+
'LTC': 'Litecoin',
|
196
|
+
'XMR': 'Monero',
|
197
|
+
'USDT': 'Tether',
|
198
|
+
'USDC': 'USD Coin',
|
199
|
+
'ADA': 'Cardano',
|
200
|
+
'DOT': 'Polkadot',
|
201
|
+
'MATIC': 'Polygon',
|
202
|
+
'BNB': 'Binance Coin',
|
203
|
+
}
|
204
|
+
|
205
|
+
return names.get(code, f"{code} {'Cryptocurrency' if currency_type == 'crypto' else 'Currency'}")
|
206
|
+
|
207
|
+
def sync_with_django_currency(self):
|
208
|
+
"""
|
209
|
+
Sync currencies with django_currency module.
|
210
|
+
|
211
|
+
This method would integrate with the django_currency module
|
212
|
+
to ensure our currency list is up-to-date.
|
213
|
+
"""
|
214
|
+
try:
|
215
|
+
from django_cfg.modules.django_currency import get_supported_currencies
|
216
|
+
|
217
|
+
# Get supported currencies from django_currency
|
218
|
+
supported = get_supported_currencies()
|
219
|
+
|
220
|
+
created_count = 0
|
221
|
+
updated_count = 0
|
222
|
+
|
223
|
+
for currency_info in supported:
|
224
|
+
currency, created = self.get_or_create_currency(
|
225
|
+
code=currency_info['code'],
|
226
|
+
name=currency_info.get('name'),
|
227
|
+
currency_type=currency_info.get('type', 'crypto')
|
228
|
+
)
|
229
|
+
|
230
|
+
if created:
|
231
|
+
created_count += 1
|
232
|
+
else:
|
233
|
+
# Update exchange rate source if available
|
234
|
+
if currency_info.get('source') and not currency.exchange_rate_source:
|
235
|
+
currency.exchange_rate_source = currency_info['source']
|
236
|
+
currency.save(update_fields=['exchange_rate_source'])
|
237
|
+
updated_count += 1
|
238
|
+
|
239
|
+
logger.info(f"Synced currencies with django_currency", extra={
|
240
|
+
'created': created_count,
|
241
|
+
'updated': updated_count,
|
242
|
+
'total': len(supported)
|
243
|
+
})
|
244
|
+
|
245
|
+
return {
|
246
|
+
'created': created_count,
|
247
|
+
'updated': updated_count,
|
248
|
+
'total': len(supported)
|
249
|
+
}
|
250
|
+
|
251
|
+
except ImportError:
|
252
|
+
logger.warning("django_currency module not available for sync")
|
253
|
+
return {'error': 'django_currency module not available'}
|
254
|
+
except Exception as e:
|
255
|
+
logger.error(f"Failed to sync with django_currency: {e}")
|
256
|
+
return {'error': str(e)}
|
257
|
+
|
258
|
+
def get_conversion_rate(self, from_code, to_code):
|
259
|
+
"""
|
260
|
+
Get conversion rate between currencies using django_currency.
|
261
|
+
|
262
|
+
Args:
|
263
|
+
from_code: Source currency code
|
264
|
+
to_code: Target currency code
|
265
|
+
|
266
|
+
Returns:
|
267
|
+
float: Conversion rate or None if unavailable
|
268
|
+
"""
|
269
|
+
try:
|
270
|
+
from django_cfg.modules.django_currency import get_exchange_rate
|
271
|
+
|
272
|
+
rate = get_exchange_rate(from_code.upper(), to_code.upper())
|
273
|
+
|
274
|
+
logger.debug(f"Retrieved conversion rate", extra={
|
275
|
+
'from_currency': from_code,
|
276
|
+
'to_currency': to_code,
|
277
|
+
'rate': rate
|
278
|
+
})
|
279
|
+
|
280
|
+
return rate
|
281
|
+
|
282
|
+
except Exception as e:
|
283
|
+
logger.error(f"Failed to get conversion rate: {e}", extra={
|
284
|
+
'from_currency': from_code,
|
285
|
+
'to_currency': to_code
|
286
|
+
})
|
287
|
+
return None
|
288
|
+
|
289
|
+
def convert_amount(self, amount, from_code, to_code):
|
290
|
+
"""
|
291
|
+
Convert amount between currencies using django_currency.
|
292
|
+
|
293
|
+
Args:
|
294
|
+
amount: Amount to convert
|
295
|
+
from_code: Source currency code
|
296
|
+
to_code: Target currency code
|
297
|
+
|
298
|
+
Returns:
|
299
|
+
float: Converted amount or None if conversion failed
|
300
|
+
"""
|
301
|
+
try:
|
302
|
+
from django_cfg.modules.django_currency import convert_currency
|
303
|
+
|
304
|
+
converted = convert_currency(amount, from_code.upper(), to_code.upper())
|
305
|
+
|
306
|
+
logger.debug(f"Converted currency amount", extra={
|
307
|
+
'amount': amount,
|
308
|
+
'from_currency': from_code,
|
309
|
+
'to_currency': to_code,
|
310
|
+
'converted_amount': converted
|
311
|
+
})
|
312
|
+
|
313
|
+
return converted
|
314
|
+
|
315
|
+
except Exception as e:
|
316
|
+
logger.error(f"Failed to convert currency: {e}", extra={
|
317
|
+
'amount': amount,
|
318
|
+
'from_currency': from_code,
|
319
|
+
'to_currency': to_code
|
320
|
+
})
|
321
|
+
return None
|
322
|
+
|
323
|
+
def get_supported_currencies_for_provider(self, provider):
|
324
|
+
"""
|
325
|
+
Get list of currencies supported by a specific provider.
|
326
|
+
|
327
|
+
Args:
|
328
|
+
provider: Provider name
|
329
|
+
|
330
|
+
Returns:
|
331
|
+
list: List of currency dictionaries
|
332
|
+
"""
|
333
|
+
currencies = self.supported_by_provider(provider).select_related().prefetch_related(
|
334
|
+
'provider_configs'
|
335
|
+
)
|
336
|
+
|
337
|
+
result = []
|
338
|
+
for currency in currencies:
|
339
|
+
provider_config = currency.provider_configs.filter(
|
340
|
+
provider=provider,
|
341
|
+
is_enabled=True
|
342
|
+
).first()
|
343
|
+
|
344
|
+
if provider_config:
|
345
|
+
result.append({
|
346
|
+
'code': currency.code,
|
347
|
+
'name': currency.name,
|
348
|
+
'type': currency.currency_type,
|
349
|
+
'symbol': currency.symbol,
|
350
|
+
'decimal_places': currency.decimal_places,
|
351
|
+
'min_amount': float(provider_config.min_amount) if provider_config.min_amount else None,
|
352
|
+
'max_amount': float(provider_config.max_amount) if provider_config.max_amount else None,
|
353
|
+
'network': provider_config.network.code if provider_config.network else None,
|
354
|
+
'fee_percentage': float(provider_config.fee_percentage),
|
355
|
+
'fixed_fee': float(provider_config.fixed_fee),
|
356
|
+
})
|
357
|
+
|
358
|
+
return result
|
359
|
+
|
360
|
+
def get_currency_stats(self):
|
361
|
+
"""
|
362
|
+
Get currency statistics.
|
363
|
+
|
364
|
+
Returns:
|
365
|
+
dict: Currency statistics
|
366
|
+
"""
|
367
|
+
queryset = self.get_queryset()
|
368
|
+
|
369
|
+
stats = {
|
370
|
+
'total_currencies': queryset.count(),
|
371
|
+
'active_currencies': queryset.active().count(),
|
372
|
+
'crypto_currencies': queryset.crypto().count(),
|
373
|
+
'fiat_currencies': queryset.fiat().count(),
|
374
|
+
'with_provider_support': queryset.filter(provider_configs__isnull=False).distinct().count(),
|
375
|
+
'popular_currencies': queryset.popular().count(),
|
376
|
+
}
|
377
|
+
|
378
|
+
# Add provider breakdown
|
379
|
+
stats['by_provider'] = {}
|
380
|
+
providers = queryset.values_list('provider_configs__provider', flat=True).distinct()
|
381
|
+
for provider in providers:
|
382
|
+
if provider: # Skip None values
|
383
|
+
stats['by_provider'][provider] = queryset.supported_by_provider(provider).count()
|
384
|
+
|
385
|
+
return stats
|