django-cfg 1.2.27__py3-none-any.whl → 1.2.31__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/payments/admin/__init__.py +3 -2
- django_cfg/apps/payments/admin/balance_admin.py +18 -18
- django_cfg/apps/payments/admin/currencies_admin.py +319 -131
- django_cfg/apps/payments/admin/payments_admin.py +15 -4
- django_cfg/apps/payments/config/module.py +2 -2
- django_cfg/apps/payments/config/utils.py +2 -2
- django_cfg/apps/payments/decorators.py +2 -2
- django_cfg/apps/payments/management/commands/README.md +95 -127
- django_cfg/apps/payments/management/commands/currency_stats.py +5 -24
- django_cfg/apps/payments/management/commands/manage_currencies.py +229 -0
- django_cfg/apps/payments/management/commands/manage_providers.py +235 -0
- django_cfg/apps/payments/managers/__init__.py +3 -2
- django_cfg/apps/payments/managers/balance_manager.py +2 -2
- django_cfg/apps/payments/managers/currency_manager.py +272 -49
- django_cfg/apps/payments/managers/payment_manager.py +161 -13
- django_cfg/apps/payments/middleware/api_access.py +2 -2
- django_cfg/apps/payments/middleware/rate_limiting.py +8 -18
- django_cfg/apps/payments/middleware/usage_tracking.py +20 -17
- django_cfg/apps/payments/migrations/0002_network_providercurrency_and_more.py +241 -0
- django_cfg/apps/payments/migrations/0003_add_usd_rate_cache.py +30 -0
- django_cfg/apps/payments/models/__init__.py +3 -2
- django_cfg/apps/payments/models/currencies.py +187 -71
- django_cfg/apps/payments/models/payments.py +3 -2
- django_cfg/apps/payments/serializers/__init__.py +3 -2
- django_cfg/apps/payments/serializers/currencies.py +20 -12
- django_cfg/apps/payments/services/cache/simple_cache.py +2 -2
- django_cfg/apps/payments/services/core/balance_service.py +2 -2
- django_cfg/apps/payments/services/core/fallback_service.py +2 -2
- django_cfg/apps/payments/services/core/payment_service.py +3 -6
- django_cfg/apps/payments/services/core/subscription_service.py +4 -7
- django_cfg/apps/payments/services/internal_types.py +171 -7
- django_cfg/apps/payments/services/monitoring/api_schemas.py +58 -204
- django_cfg/apps/payments/services/monitoring/provider_health.py +2 -2
- django_cfg/apps/payments/services/providers/base.py +144 -43
- django_cfg/apps/payments/services/providers/cryptapi/__init__.py +4 -0
- django_cfg/apps/payments/services/providers/cryptapi/config.py +8 -0
- django_cfg/apps/payments/services/providers/cryptapi/models.py +192 -0
- django_cfg/apps/payments/services/providers/cryptapi/provider.py +439 -0
- django_cfg/apps/payments/services/providers/cryptomus/__init__.py +4 -0
- django_cfg/apps/payments/services/providers/cryptomus/models.py +176 -0
- django_cfg/apps/payments/services/providers/cryptomus/provider.py +429 -0
- django_cfg/apps/payments/services/providers/cryptomus/provider_v2.py +564 -0
- django_cfg/apps/payments/services/providers/models/__init__.py +34 -0
- django_cfg/apps/payments/services/providers/models/currencies.py +190 -0
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +4 -0
- django_cfg/apps/payments/services/providers/nowpayments/models.py +196 -0
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +380 -0
- django_cfg/apps/payments/services/providers/registry.py +294 -11
- django_cfg/apps/payments/services/providers/stripe/__init__.py +4 -0
- django_cfg/apps/payments/services/providers/stripe/models.py +184 -0
- django_cfg/apps/payments/services/providers/stripe/provider.py +109 -0
- django_cfg/apps/payments/services/security/error_handler.py +6 -8
- django_cfg/apps/payments/services/security/payment_notifications.py +2 -2
- django_cfg/apps/payments/services/security/webhook_validator.py +3 -4
- django_cfg/apps/payments/signals/api_key_signals.py +2 -2
- django_cfg/apps/payments/signals/payment_signals.py +11 -5
- django_cfg/apps/payments/signals/subscription_signals.py +2 -2
- django_cfg/apps/payments/static/payments/css/payments.css +340 -0
- django_cfg/apps/payments/static/payments/js/notifications.js +202 -0
- django_cfg/apps/payments/static/payments/js/payment-utils.js +318 -0
- django_cfg/apps/payments/static/payments/js/theme.js +86 -0
- django_cfg/apps/payments/tasks/webhook_processing.py +2 -2
- django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +50 -0
- django_cfg/apps/payments/templates/payments/base.html +182 -0
- django_cfg/apps/payments/templates/payments/components/payment_card.html +201 -0
- django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +109 -0
- django_cfg/apps/payments/templates/payments/components/progress_bar.html +43 -0
- django_cfg/apps/payments/templates/payments/components/provider_stats.html +40 -0
- django_cfg/apps/payments/templates/payments/components/status_badge.html +34 -0
- django_cfg/apps/payments/templates/payments/components/status_overview.html +148 -0
- django_cfg/apps/payments/templates/payments/dashboard.html +258 -0
- django_cfg/apps/payments/templates/payments/dashboard_simple_test.html +35 -0
- django_cfg/apps/payments/templates/payments/payment_create.html +579 -0
- django_cfg/apps/payments/templates/payments/payment_detail.html +373 -0
- django_cfg/apps/payments/templates/payments/payment_list.html +354 -0
- django_cfg/apps/payments/templates/payments/stats.html +261 -0
- django_cfg/apps/payments/templates/payments/test.html +213 -0
- django_cfg/apps/payments/templatetags/__init__.py +1 -0
- django_cfg/apps/payments/templatetags/payments_tags.py +315 -0
- django_cfg/apps/payments/urls.py +3 -1
- django_cfg/apps/payments/urls_admin.py +58 -0
- django_cfg/apps/payments/utils/__init__.py +1 -3
- django_cfg/apps/payments/utils/billing_utils.py +2 -2
- django_cfg/apps/payments/utils/config_utils.py +2 -8
- django_cfg/apps/payments/utils/validation_utils.py +2 -2
- django_cfg/apps/payments/views/__init__.py +3 -2
- django_cfg/apps/payments/views/currency_views.py +31 -20
- django_cfg/apps/payments/views/payment_views.py +2 -2
- django_cfg/apps/payments/views/templates/__init__.py +25 -0
- django_cfg/apps/payments/views/templates/ajax.py +451 -0
- django_cfg/apps/payments/views/templates/base.py +212 -0
- django_cfg/apps/payments/views/templates/dashboard.py +60 -0
- django_cfg/apps/payments/views/templates/payment_detail.py +102 -0
- django_cfg/apps/payments/views/templates/payment_management.py +158 -0
- django_cfg/apps/payments/views/templates/qr_code.py +174 -0
- django_cfg/apps/payments/views/templates/stats.py +244 -0
- django_cfg/apps/payments/views/templates/utils.py +181 -0
- django_cfg/apps/payments/views/webhook_views.py +2 -2
- django_cfg/apps/payments/viewsets.py +3 -2
- django_cfg/apps/tasks/urls.py +0 -2
- django_cfg/apps/tasks/urls_admin.py +14 -0
- django_cfg/apps/urls.py +6 -3
- django_cfg/core/config.py +35 -0
- django_cfg/models/payments.py +2 -8
- django_cfg/modules/django_currency/__init__.py +16 -11
- django_cfg/modules/django_currency/clients/__init__.py +4 -4
- django_cfg/modules/django_currency/clients/coinpaprika_client.py +289 -0
- django_cfg/modules/django_currency/clients/yahoo_client.py +157 -0
- django_cfg/modules/django_currency/core/__init__.py +1 -7
- django_cfg/modules/django_currency/core/converter.py +18 -23
- django_cfg/modules/django_currency/core/models.py +122 -11
- django_cfg/modules/django_currency/database/__init__.py +4 -4
- django_cfg/modules/django_currency/database/database_loader.py +190 -309
- django_cfg/modules/django_unfold/dashboard.py +7 -2
- django_cfg/registry/core.py +1 -0
- django_cfg/template_archive/.gitignore +1 -0
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/templates/admin/components/action_grid.html +9 -9
- django_cfg/templates/admin/components/metric_card.html +5 -5
- django_cfg/templates/admin/components/status_badge.html +2 -2
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +152 -24
- django_cfg/templates/admin/snippets/components/quick_actions.html +3 -3
- django_cfg/templates/admin/snippets/components/system_health.html +1 -1
- django_cfg/templates/admin/snippets/tabs/overview_tab.html +49 -52
- {django_cfg-1.2.27.dist-info → django_cfg-1.2.31.dist-info}/METADATA +13 -18
- {django_cfg-1.2.27.dist-info → django_cfg-1.2.31.dist-info}/RECORD +130 -83
- django_cfg/apps/payments/management/commands/populate_currencies.py +0 -246
- django_cfg/apps/payments/management/commands/update_currencies.py +0 -336
- django_cfg/apps/payments/services/providers/cryptapi.py +0 -273
- django_cfg/apps/payments/services/providers/cryptomus.py +0 -310
- django_cfg/apps/payments/services/providers/nowpayments.py +0 -293
- django_cfg/apps/payments/services/validators/__init__.py +0 -8
- django_cfg/modules/django_currency/clients/coingecko_client.py +0 -257
- django_cfg/modules/django_currency/clients/yfinance_client.py +0 -246
- {django_cfg-1.2.27.dist-info → django_cfg-1.2.31.dist-info}/WHEEL +0 -0
- {django_cfg-1.2.27.dist-info → django_cfg-1.2.31.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.2.27.dist-info → django_cfg-1.2.31.dist-info}/licenses/LICENSE +0 -0
@@ -10,6 +10,9 @@ from unfold.decorators import display
|
|
10
10
|
|
11
11
|
from ..models import UniversalPayment
|
12
12
|
from .filters import PaymentStatusFilter, PaymentAmountFilter, UserEmailFilter, RecentActivityFilter
|
13
|
+
from django_cfg.modules.django_logger import get_logger
|
14
|
+
|
15
|
+
logger = get_logger("payments_admin")
|
13
16
|
|
14
17
|
|
15
18
|
@admin.register(UniversalPayment)
|
@@ -35,6 +38,10 @@ class UniversalPaymentAdmin(ModelAdmin):
|
|
35
38
|
'user__last_name'
|
36
39
|
]
|
37
40
|
|
41
|
+
def get_queryset(self, request):
|
42
|
+
"""Optimize queryset to prevent N+1 queries."""
|
43
|
+
return super().get_queryset(request).optimized()
|
44
|
+
|
38
45
|
list_filter = [
|
39
46
|
PaymentStatusFilter,
|
40
47
|
PaymentAmountFilter,
|
@@ -59,12 +66,16 @@ class UniversalPaymentAdmin(ModelAdmin):
|
|
59
66
|
('Payment Details', {
|
60
67
|
'fields': ['internal_payment_id', 'provider_payment_id', 'provider', 'status']
|
61
68
|
}),
|
69
|
+
('Crypto Details', {
|
70
|
+
'fields': ['pay_address', 'pay_amount', 'network', 'security_nonce', 'transaction_hash', 'sender_address', 'receiver_address', 'crypto_amount', 'confirmations_count'],
|
71
|
+
'classes': ['collapse']
|
72
|
+
}),
|
62
73
|
('Provider Data', {
|
63
|
-
'fields': ['
|
74
|
+
'fields': ['metadata', 'webhook_data'],
|
64
75
|
'classes': ['collapse']
|
65
76
|
}),
|
66
77
|
('Timestamps', {
|
67
|
-
'fields': ['created_at', 'updated_at'],
|
78
|
+
'fields': ['created_at', 'updated_at', 'expires_at', 'completed_at', 'processed_at'],
|
68
79
|
'classes': ['collapse']
|
69
80
|
})
|
70
81
|
]
|
@@ -91,8 +102,8 @@ class UniversalPaymentAdmin(ModelAdmin):
|
|
91
102
|
def amount_display(self, obj):
|
92
103
|
"""Display amount with currency."""
|
93
104
|
return format_html(
|
94
|
-
'<span style="font-weight: bold; font-size: 14px;">${
|
95
|
-
obj.amount_usd,
|
105
|
+
'<span style="font-weight: bold; font-size: 14px;">${}</span><br><small>{}</small>',
|
106
|
+
f"{float(obj.amount_usd):.2f}",
|
96
107
|
obj.currency_code
|
97
108
|
)
|
98
109
|
|
@@ -5,12 +5,12 @@ Handles loading and managing payment configurations from project settings.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
from typing import Optional
|
8
|
-
import
|
8
|
+
from django_cfg.modules.django_logger import get_logger
|
9
9
|
|
10
10
|
from django_cfg.modules.base import BaseCfgModule
|
11
11
|
from .settings import PaymentsSettings
|
12
12
|
|
13
|
-
logger =
|
13
|
+
logger = get_logger("config_module")
|
14
14
|
|
15
15
|
|
16
16
|
class PaymentsCfgModule(BaseCfgModule):
|
@@ -5,13 +5,13 @@ Helper functions for working with payment configurations.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
from typing import Optional
|
8
|
-
import
|
8
|
+
from django_cfg.modules.django_logger import get_logger
|
9
9
|
|
10
10
|
from .module import PaymentsCfgModule
|
11
11
|
from .settings import PaymentsSettings
|
12
12
|
from django_cfg.models.payments import PaymentProviderConfig
|
13
13
|
|
14
|
-
logger =
|
14
|
+
logger = get_logger("config_utils")
|
15
15
|
|
16
16
|
# Global payments configuration instance
|
17
17
|
_payments_config = PaymentsCfgModule()
|
@@ -3,14 +3,14 @@ Decorators for API access control and endpoint registration.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import functools
|
6
|
-
import
|
6
|
+
from django_cfg.modules.django_logger import get_logger
|
7
7
|
from typing import Optional, List, Callable, Any
|
8
8
|
from django.http import JsonResponse
|
9
9
|
from django.conf import settings
|
10
10
|
from django.utils import timezone
|
11
11
|
from .models import EndpointGroup, Subscription
|
12
12
|
|
13
|
-
logger =
|
13
|
+
logger = get_logger("decorators")
|
14
14
|
|
15
15
|
|
16
16
|
def require_api_key(func: Callable) -> Callable:
|
@@ -1,178 +1,146 @@
|
|
1
|
-
#
|
1
|
+
# Payment Management Commands
|
2
2
|
|
3
|
-
|
3
|
+
Optimized management commands for Django CFG payments system.
|
4
4
|
|
5
|
-
##
|
5
|
+
## Available Commands
|
6
6
|
|
7
|
-
###
|
7
|
+
### 1. `manage_currencies` - Currency and Rate Management
|
8
8
|
|
9
|
-
|
9
|
+
Universal command for all currency-related operations.
|
10
10
|
|
11
|
-
|
12
|
-
# Быстрое заполнение (50 криптовалют + 20 фиатных)
|
13
|
-
python manage.py populate_currencies --quick
|
14
|
-
|
15
|
-
# Стандартное заполнение (200 криптовалют + 30 фиатных)
|
16
|
-
python manage.py populate_currencies
|
17
|
-
|
18
|
-
# Только криптовалюты
|
19
|
-
python manage.py populate_currencies --crypto-only
|
20
|
-
|
21
|
-
# Только фиатные валюты
|
22
|
-
python manage.py populate_currencies --fiat-only
|
23
|
-
|
24
|
-
# Пропустить существующие валюты
|
25
|
-
python manage.py populate_currencies --skip-existing
|
26
|
-
```
|
27
|
-
|
28
|
-
### 🔄 `update_currencies` - Обновление курсов
|
29
|
-
|
30
|
-
Обновляет курсы валют с внешних API.
|
11
|
+
#### Usage Examples:
|
31
12
|
|
32
13
|
```bash
|
33
|
-
#
|
34
|
-
python manage.py
|
14
|
+
# Update USD exchange rates only
|
15
|
+
python manage.py manage_currencies --rates-only
|
35
16
|
|
36
|
-
#
|
37
|
-
python manage.py
|
17
|
+
# Update specific currency rate
|
18
|
+
python manage.py manage_currencies --rates-only --currency ETH
|
38
19
|
|
39
|
-
#
|
40
|
-
python manage.py
|
20
|
+
# Initial population (empty database)
|
21
|
+
python manage.py manage_currencies --populate
|
41
22
|
|
42
|
-
#
|
43
|
-
python manage.py
|
23
|
+
# Full update with fresh rates
|
24
|
+
python manage.py manage_currencies --force
|
44
25
|
|
45
|
-
#
|
46
|
-
python manage.py
|
26
|
+
# Dry run to see what would be updated
|
27
|
+
python manage.py manage_currencies --dry-run
|
47
28
|
|
48
|
-
#
|
49
|
-
python manage.py
|
29
|
+
# Limit number of currencies processed
|
30
|
+
python manage.py manage_currencies --populate --max-crypto 100 --max-fiat 20
|
50
31
|
```
|
51
32
|
|
52
|
-
|
33
|
+
#### Options:
|
34
|
+
- `--populate` - Initial population mode for empty database
|
35
|
+
- `--rates-only` - Only update USD exchange rates
|
36
|
+
- `--currency CODE` - Update specific currency (e.g., BTC, ETH)
|
37
|
+
- `--force` - Force refresh all data even if fresh
|
38
|
+
- `--dry-run` - Show what would be done without changes
|
39
|
+
- `--max-crypto N` - Limit crypto currencies (default: 200)
|
40
|
+
- `--max-fiat N` - Limit fiat currencies (default: 50)
|
53
41
|
|
54
|
-
|
42
|
+
---
|
55
43
|
|
56
|
-
|
57
|
-
# Базовая статистика
|
58
|
-
python manage.py currency_stats
|
44
|
+
### 2. `manage_providers` - Payment Provider Management
|
59
45
|
|
60
|
-
|
61
|
-
python manage.py currency_stats --detailed
|
46
|
+
Universal command for all provider-related operations.
|
62
47
|
|
63
|
-
|
64
|
-
python manage.py currency_stats --top 10
|
48
|
+
#### Usage Examples:
|
65
49
|
|
66
|
-
|
67
|
-
|
50
|
+
```bash
|
51
|
+
# Sync all active providers
|
52
|
+
python manage.py manage_providers
|
68
53
|
|
69
|
-
#
|
70
|
-
python manage.py
|
71
|
-
```
|
54
|
+
# Sync specific provider
|
55
|
+
python manage.py manage_providers --provider nowpayments
|
72
56
|
|
73
|
-
|
57
|
+
# Sync multiple providers
|
58
|
+
python manage.py manage_providers --provider nowpayments,cryptomus
|
74
59
|
|
75
|
-
|
60
|
+
# Sync providers + update USD rates
|
61
|
+
python manage.py manage_providers --with-rates
|
76
62
|
|
77
|
-
|
78
|
-
|
79
|
-
0 */6 * * * cd /path/to/project && poetry run python manage.py update_currencies
|
63
|
+
# Show provider statistics
|
64
|
+
python manage.py manage_providers --stats
|
80
65
|
|
81
|
-
#
|
82
|
-
|
66
|
+
# Dry run to see what would be synced
|
67
|
+
python manage.py manage_providers --dry-run --verbose
|
83
68
|
```
|
84
69
|
|
85
|
-
|
70
|
+
#### Options:
|
71
|
+
- `--provider NAME` - Specific provider(s) to sync (comma-separated)
|
72
|
+
- `--all` - Sync all available providers
|
73
|
+
- `--with-rates` - Also update USD exchange rates after sync
|
74
|
+
- `--stats` - Show provider statistics
|
75
|
+
- `--dry-run` - Show what would be synced without changes
|
76
|
+
- `--verbose` - Show detailed progress information
|
86
77
|
|
87
|
-
|
88
|
-
# В Docker контейнере
|
89
|
-
docker exec -it container_name poetry run python manage.py populate_currencies --quick
|
90
|
-
docker exec -it container_name poetry run python manage.py update_currencies
|
91
|
-
```
|
78
|
+
---
|
92
79
|
|
93
|
-
|
80
|
+
### 3. `currency_stats` - Statistics and Reports
|
94
81
|
|
95
|
-
|
82
|
+
Display currency database statistics and health information.
|
96
83
|
|
97
|
-
|
98
|
-
# 1. Заполнить базу данных валютами
|
99
|
-
python manage.py populate_currencies --quick
|
84
|
+
#### Usage Examples:
|
100
85
|
|
101
|
-
|
86
|
+
```bash
|
87
|
+
# Basic statistics
|
102
88
|
python manage.py currency_stats
|
103
|
-
```
|
104
89
|
|
105
|
-
|
90
|
+
# Detailed breakdown
|
91
|
+
python manage.py currency_stats --detailed
|
106
92
|
|
107
|
-
|
108
|
-
|
109
|
-
python manage.py update_currencies --verbose
|
93
|
+
# Top currencies by value
|
94
|
+
python manage.py currency_stats --top 10
|
110
95
|
|
111
|
-
#
|
96
|
+
# Check rate freshness
|
112
97
|
python manage.py currency_stats --check-rates
|
113
|
-
|
114
|
-
# 3. При необходимости - принудительное обновление
|
115
|
-
python manage.py update_currencies --force-update
|
116
98
|
```
|
117
99
|
|
118
|
-
|
100
|
+
---
|
119
101
|
|
120
|
-
|
121
|
-
# Обновление с минимальными API запросами
|
122
|
-
python manage.py update_currencies --max-crypto 50 --max-fiat 20
|
102
|
+
## Migration from Old Commands
|
123
103
|
|
124
|
-
|
125
|
-
|
126
|
-
|
104
|
+
| Old Command | New Command |
|
105
|
+
|-------------|-------------|
|
106
|
+
| `populate_currencies` | `manage_currencies --populate` |
|
107
|
+
| `update_currencies` | `manage_currencies` |
|
108
|
+
| `update_currency_rates` | `manage_currencies --rates-only` |
|
109
|
+
| `sync_providers` | `manage_providers` |
|
110
|
+
| `currency_stats` | `currency_stats` (unchanged) |
|
127
111
|
|
128
|
-
##
|
112
|
+
## Automation Examples
|
129
113
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
- ✅ Rate limiting для защиты от API throttling
|
135
|
-
- ✅ Кэширования для оптимизации производительности
|
136
|
-
- ✅ Pydantic валидации для типобезопасности
|
137
|
-
|
138
|
-
## Конфигурация
|
139
|
-
|
140
|
-
Настройки в `DatabaseLoaderConfig`:
|
114
|
+
### Daily Rate Updates (Crontab)
|
115
|
+
```bash
|
116
|
+
# Update rates every 6 hours
|
117
|
+
0 */6 * * * cd /path/to/project && python manage.py manage_currencies --rates-only
|
141
118
|
|
142
|
-
|
143
|
-
|
144
|
-
max_cryptocurrencies=500, # Максимум криптовалют
|
145
|
-
max_fiat_currencies=50, # Максимум фиатных валют
|
146
|
-
min_market_cap_usd=1_000_000, # Минимальная капитализация
|
147
|
-
coingecko_delay=1.5, # Задержка между запросами
|
148
|
-
yfinance_delay=0.5, # Задержка для YFinance
|
149
|
-
exclude_stablecoins=False, # Исключить стейблкоины
|
150
|
-
cache_ttl_hours=24 # TTL кэша в часах
|
151
|
-
)
|
119
|
+
# Sync providers once daily
|
120
|
+
0 2 * * * cd /path/to/project && python manage.py manage_providers --with-rates
|
152
121
|
```
|
153
122
|
|
154
|
-
|
155
|
-
|
156
|
-
|
123
|
+
### Initial Setup
|
124
|
+
```bash
|
125
|
+
# 1. Populate base currencies
|
126
|
+
python manage.py manage_currencies --populate
|
157
127
|
|
158
|
-
|
128
|
+
# 2. Sync payment providers
|
129
|
+
python manage.py manage_providers
|
159
130
|
|
160
|
-
|
161
|
-
|
162
|
-
|
131
|
+
# 3. Check statistics
|
132
|
+
python manage.py manage_providers --stats
|
133
|
+
python manage.py currency_stats
|
163
134
|
```
|
164
135
|
|
165
|
-
|
166
|
-
|
167
|
-
- Количество созданных/обновленных валют
|
168
|
-
- Время выполнения API запросов
|
169
|
-
- Ошибки валидации и API
|
170
|
-
- Статистика курсов валют
|
136
|
+
---
|
171
137
|
|
172
|
-
##
|
138
|
+
## Features
|
173
139
|
|
174
|
-
-
|
175
|
-
-
|
176
|
-
-
|
177
|
-
-
|
178
|
-
-
|
140
|
+
- **🚀 Fast**: Optimized database queries and caching
|
141
|
+
- **📊 Progress**: Real-time progress reporting and statistics
|
142
|
+
- **🔄 Atomic**: Transaction safety with rollback on errors
|
143
|
+
- **🎯 Flexible**: Multiple operation modes and options
|
144
|
+
- **📈 Pydantic**: Full type safety with Pydantic models
|
145
|
+
- **🛡️ Safe**: Dry-run mode for testing changes
|
146
|
+
- **📝 Verbose**: Detailed logging and error reporting
|
@@ -76,7 +76,7 @@ class Command(BaseCommand):
|
|
76
76
|
|
77
77
|
# Basic counts
|
78
78
|
total = Currency.objects.count()
|
79
|
-
active = Currency.objects.
|
79
|
+
active = Currency.objects.count()
|
80
80
|
inactive = total - active
|
81
81
|
|
82
82
|
fiat_count = Currency.objects.filter(currency_type=Currency.CurrencyType.FIAT).count()
|
@@ -84,11 +84,9 @@ class Command(BaseCommand):
|
|
84
84
|
|
85
85
|
active_fiat = Currency.objects.filter(
|
86
86
|
currency_type=Currency.CurrencyType.FIAT,
|
87
|
-
is_active=True
|
88
87
|
).count()
|
89
88
|
active_crypto = Currency.objects.filter(
|
90
89
|
currency_type=Currency.CurrencyType.CRYPTO,
|
91
|
-
is_active=True
|
92
90
|
).count()
|
93
91
|
|
94
92
|
self.stdout.write(f"\n📈 Overview:")
|
@@ -119,7 +117,6 @@ class Command(BaseCommand):
|
|
119
117
|
# Top cryptocurrencies by USD value
|
120
118
|
top_crypto = Currency.objects.filter(
|
121
119
|
currency_type=Currency.CurrencyType.CRYPTO,
|
122
|
-
is_active=True
|
123
120
|
).order_by('-usd_rate')[:options['top']]
|
124
121
|
|
125
122
|
if top_crypto:
|
@@ -134,7 +131,6 @@ class Command(BaseCommand):
|
|
134
131
|
major_fiat = Currency.objects.filter(
|
135
132
|
currency_type=Currency.CurrencyType.FIAT,
|
136
133
|
code__in=['USD', 'EUR', 'GBP', 'JPY', 'CNY'],
|
137
|
-
is_active=True
|
138
134
|
).order_by('code')
|
139
135
|
|
140
136
|
if major_fiat:
|
@@ -162,12 +158,10 @@ class Command(BaseCommand):
|
|
162
158
|
# Average rates by type
|
163
159
|
crypto_avg = Currency.objects.filter(
|
164
160
|
currency_type=Currency.CurrencyType.CRYPTO,
|
165
|
-
is_active=True
|
166
161
|
).aggregate(avg_rate=Avg('usd_rate'))['avg_rate']
|
167
162
|
|
168
163
|
fiat_avg = Currency.objects.filter(
|
169
164
|
currency_type=Currency.CurrencyType.FIAT,
|
170
|
-
is_active=True
|
171
165
|
).aggregate(avg_rate=Avg('usd_rate'))['avg_rate']
|
172
166
|
|
173
167
|
self.stdout.write(f"\n📊 Average USD Rates:")
|
@@ -177,13 +171,8 @@ class Command(BaseCommand):
|
|
177
171
|
self.stdout.write(f" Fiat currencies: ${fiat_avg:.6f}")
|
178
172
|
|
179
173
|
# Min payment amounts
|
180
|
-
|
181
|
-
|
182
|
-
).order_by('min_payment_amount')[:5]
|
183
|
-
|
184
|
-
self.stdout.write(f"\n💰 Top Min Payment Amounts:")
|
185
|
-
for stat in min_payment_stats:
|
186
|
-
self.stdout.write(f" ${stat['min_payment_amount']}: {stat['count']} currencies")
|
174
|
+
# Note: min_payment_amount field was removed - now handled at provider level
|
175
|
+
self.stdout.write(f"\n💰 Payment amounts now managed at provider level (ProviderCurrency)")
|
187
176
|
|
188
177
|
# Rate freshness distribution
|
189
178
|
now = timezone.now()
|
@@ -219,7 +208,6 @@ class Command(BaseCommand):
|
|
219
208
|
very_old_threshold = now - timedelta(days=30)
|
220
209
|
very_old = Currency.objects.filter(
|
221
210
|
Q(rate_updated_at__lt=very_old_threshold) | Q(rate_updated_at__isnull=True),
|
222
|
-
is_active=True
|
223
211
|
)
|
224
212
|
|
225
213
|
if very_old.exists():
|
@@ -237,7 +225,6 @@ class Command(BaseCommand):
|
|
237
225
|
old_currencies = Currency.objects.filter(
|
238
226
|
rate_updated_at__lt=old_threshold,
|
239
227
|
rate_updated_at__gte=very_old_threshold,
|
240
|
-
is_active=True
|
241
228
|
)
|
242
229
|
|
243
230
|
if old_currencies.exists():
|
@@ -249,7 +236,6 @@ class Command(BaseCommand):
|
|
249
236
|
fresh_threshold = now - timedelta(hours=24)
|
250
237
|
fresh = Currency.objects.filter(
|
251
238
|
rate_updated_at__gte=fresh_threshold,
|
252
|
-
is_active=True
|
253
239
|
).count()
|
254
240
|
|
255
241
|
if fresh > 0:
|
@@ -258,7 +244,7 @@ class Command(BaseCommand):
|
|
258
244
|
)
|
259
245
|
|
260
246
|
# Recommendations
|
261
|
-
total_active = Currency.objects.
|
247
|
+
total_active = Currency.objects.count()
|
262
248
|
if very_old.count() > 0:
|
263
249
|
self.stdout.write(f"\n💡 Recommendations:")
|
264
250
|
self.stdout.write(f" • Run: python manage.py update_currencies --force-update")
|
@@ -294,8 +280,7 @@ class Command(BaseCommand):
|
|
294
280
|
|
295
281
|
# Header
|
296
282
|
writer.writerow([
|
297
|
-
'code', 'name', '
|
298
|
-
'usd_rate', 'min_payment_amount', 'is_active', 'rate_updated_at'
|
283
|
+
'code', 'name', 'currency_type', 'usd_rate', 'rate_updated_at'
|
299
284
|
])
|
300
285
|
|
301
286
|
# Data
|
@@ -304,12 +289,8 @@ class Command(BaseCommand):
|
|
304
289
|
writer.writerow([
|
305
290
|
currency.code,
|
306
291
|
currency.name,
|
307
|
-
currency.symbol,
|
308
292
|
currency.currency_type,
|
309
|
-
currency.decimal_places,
|
310
293
|
currency.usd_rate,
|
311
|
-
currency.min_payment_amount,
|
312
|
-
currency.is_active,
|
313
294
|
currency.rate_updated_at.isoformat() if currency.rate_updated_at else None
|
314
295
|
])
|
315
296
|
|