django-cfg 1.2.29__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.
Files changed (126) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/payments/admin/__init__.py +3 -2
  3. django_cfg/apps/payments/admin/balance_admin.py +18 -18
  4. django_cfg/apps/payments/admin/currencies_admin.py +319 -131
  5. django_cfg/apps/payments/admin/payments_admin.py +15 -4
  6. django_cfg/apps/payments/config/module.py +2 -2
  7. django_cfg/apps/payments/config/utils.py +2 -2
  8. django_cfg/apps/payments/decorators.py +2 -2
  9. django_cfg/apps/payments/management/commands/README.md +95 -127
  10. django_cfg/apps/payments/management/commands/currency_stats.py +5 -24
  11. django_cfg/apps/payments/management/commands/manage_currencies.py +229 -0
  12. django_cfg/apps/payments/management/commands/manage_providers.py +235 -0
  13. django_cfg/apps/payments/managers/__init__.py +3 -2
  14. django_cfg/apps/payments/managers/balance_manager.py +2 -2
  15. django_cfg/apps/payments/managers/currency_manager.py +272 -49
  16. django_cfg/apps/payments/managers/payment_manager.py +161 -13
  17. django_cfg/apps/payments/middleware/api_access.py +2 -2
  18. django_cfg/apps/payments/middleware/rate_limiting.py +8 -18
  19. django_cfg/apps/payments/middleware/usage_tracking.py +20 -17
  20. django_cfg/apps/payments/migrations/0002_network_providercurrency_and_more.py +241 -0
  21. django_cfg/apps/payments/migrations/0003_add_usd_rate_cache.py +30 -0
  22. django_cfg/apps/payments/models/__init__.py +3 -2
  23. django_cfg/apps/payments/models/currencies.py +187 -71
  24. django_cfg/apps/payments/models/payments.py +3 -2
  25. django_cfg/apps/payments/serializers/__init__.py +3 -2
  26. django_cfg/apps/payments/serializers/currencies.py +20 -12
  27. django_cfg/apps/payments/services/cache/simple_cache.py +2 -2
  28. django_cfg/apps/payments/services/core/balance_service.py +2 -2
  29. django_cfg/apps/payments/services/core/fallback_service.py +2 -2
  30. django_cfg/apps/payments/services/core/payment_service.py +3 -6
  31. django_cfg/apps/payments/services/core/subscription_service.py +4 -7
  32. django_cfg/apps/payments/services/internal_types.py +171 -7
  33. django_cfg/apps/payments/services/monitoring/api_schemas.py +58 -204
  34. django_cfg/apps/payments/services/monitoring/provider_health.py +2 -2
  35. django_cfg/apps/payments/services/providers/base.py +144 -43
  36. django_cfg/apps/payments/services/providers/cryptapi/__init__.py +4 -0
  37. django_cfg/apps/payments/services/providers/cryptapi/config.py +8 -0
  38. django_cfg/apps/payments/services/providers/cryptapi/models.py +192 -0
  39. django_cfg/apps/payments/services/providers/cryptapi/provider.py +439 -0
  40. django_cfg/apps/payments/services/providers/cryptomus/__init__.py +4 -0
  41. django_cfg/apps/payments/services/providers/cryptomus/models.py +176 -0
  42. django_cfg/apps/payments/services/providers/cryptomus/provider.py +429 -0
  43. django_cfg/apps/payments/services/providers/cryptomus/provider_v2.py +564 -0
  44. django_cfg/apps/payments/services/providers/models/__init__.py +34 -0
  45. django_cfg/apps/payments/services/providers/models/currencies.py +190 -0
  46. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +4 -0
  47. django_cfg/apps/payments/services/providers/nowpayments/models.py +196 -0
  48. django_cfg/apps/payments/services/providers/nowpayments/provider.py +380 -0
  49. django_cfg/apps/payments/services/providers/registry.py +294 -11
  50. django_cfg/apps/payments/services/providers/stripe/__init__.py +4 -0
  51. django_cfg/apps/payments/services/providers/stripe/models.py +184 -0
  52. django_cfg/apps/payments/services/providers/stripe/provider.py +109 -0
  53. django_cfg/apps/payments/services/security/error_handler.py +6 -8
  54. django_cfg/apps/payments/services/security/payment_notifications.py +2 -2
  55. django_cfg/apps/payments/services/security/webhook_validator.py +3 -4
  56. django_cfg/apps/payments/signals/api_key_signals.py +2 -2
  57. django_cfg/apps/payments/signals/payment_signals.py +11 -5
  58. django_cfg/apps/payments/signals/subscription_signals.py +2 -2
  59. django_cfg/apps/payments/tasks/webhook_processing.py +2 -2
  60. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +50 -0
  61. django_cfg/apps/payments/templates/payments/base.html +4 -4
  62. django_cfg/apps/payments/templates/payments/components/payment_card.html +6 -6
  63. django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +4 -4
  64. django_cfg/apps/payments/templates/payments/components/progress_bar.html +14 -7
  65. django_cfg/apps/payments/templates/payments/components/provider_stats.html +2 -2
  66. django_cfg/apps/payments/templates/payments/components/status_badge.html +8 -1
  67. django_cfg/apps/payments/templates/payments/components/status_overview.html +34 -30
  68. django_cfg/apps/payments/templates/payments/dashboard.html +202 -290
  69. django_cfg/apps/payments/templates/payments/dashboard_simple_test.html +35 -0
  70. django_cfg/apps/payments/templates/payments/payment_create.html +579 -0
  71. django_cfg/apps/payments/templates/payments/payment_detail.html +373 -0
  72. django_cfg/apps/payments/templates/payments/payment_list.html +354 -0
  73. django_cfg/apps/payments/templates/payments/stats.html +261 -0
  74. django_cfg/apps/payments/templates/payments/test.html +213 -0
  75. django_cfg/apps/payments/urls.py +3 -1
  76. django_cfg/apps/payments/{urls_templates.py → urls_admin.py} +6 -0
  77. django_cfg/apps/payments/utils/__init__.py +1 -3
  78. django_cfg/apps/payments/utils/billing_utils.py +2 -2
  79. django_cfg/apps/payments/utils/config_utils.py +2 -8
  80. django_cfg/apps/payments/utils/validation_utils.py +2 -2
  81. django_cfg/apps/payments/views/__init__.py +3 -2
  82. django_cfg/apps/payments/views/currency_views.py +31 -20
  83. django_cfg/apps/payments/views/payment_views.py +2 -2
  84. django_cfg/apps/payments/views/templates/ajax.py +141 -2
  85. django_cfg/apps/payments/views/templates/base.py +21 -13
  86. django_cfg/apps/payments/views/templates/payment_detail.py +1 -1
  87. django_cfg/apps/payments/views/templates/payment_management.py +34 -40
  88. django_cfg/apps/payments/views/templates/stats.py +8 -4
  89. django_cfg/apps/payments/views/webhook_views.py +2 -2
  90. django_cfg/apps/payments/viewsets.py +3 -2
  91. django_cfg/apps/tasks/urls.py +0 -2
  92. django_cfg/apps/tasks/urls_admin.py +14 -0
  93. django_cfg/apps/urls.py +4 -4
  94. django_cfg/core/config.py +35 -0
  95. django_cfg/models/payments.py +2 -8
  96. django_cfg/modules/django_currency/__init__.py +16 -11
  97. django_cfg/modules/django_currency/clients/__init__.py +4 -4
  98. django_cfg/modules/django_currency/clients/coinpaprika_client.py +289 -0
  99. django_cfg/modules/django_currency/clients/yahoo_client.py +157 -0
  100. django_cfg/modules/django_currency/core/__init__.py +1 -7
  101. django_cfg/modules/django_currency/core/converter.py +18 -23
  102. django_cfg/modules/django_currency/core/models.py +122 -11
  103. django_cfg/modules/django_currency/database/__init__.py +4 -4
  104. django_cfg/modules/django_currency/database/database_loader.py +190 -309
  105. django_cfg/modules/django_unfold/dashboard.py +7 -2
  106. django_cfg/template_archive/django_sample.zip +0 -0
  107. django_cfg/templates/admin/components/action_grid.html +9 -9
  108. django_cfg/templates/admin/components/metric_card.html +5 -5
  109. django_cfg/templates/admin/components/status_badge.html +2 -2
  110. django_cfg/templates/admin/layouts/dashboard_with_tabs.html +152 -24
  111. django_cfg/templates/admin/snippets/components/quick_actions.html +3 -3
  112. django_cfg/templates/admin/snippets/components/system_health.html +1 -1
  113. django_cfg/templates/admin/snippets/tabs/overview_tab.html +49 -52
  114. {django_cfg-1.2.29.dist-info → django_cfg-1.2.31.dist-info}/METADATA +2 -4
  115. {django_cfg-1.2.29.dist-info → django_cfg-1.2.31.dist-info}/RECORD +118 -96
  116. django_cfg/apps/payments/management/commands/populate_currencies.py +0 -246
  117. django_cfg/apps/payments/management/commands/update_currencies.py +0 -336
  118. django_cfg/apps/payments/services/providers/cryptapi.py +0 -273
  119. django_cfg/apps/payments/services/providers/cryptomus.py +0 -311
  120. django_cfg/apps/payments/services/providers/nowpayments.py +0 -293
  121. django_cfg/apps/payments/services/validators/__init__.py +0 -8
  122. django_cfg/modules/django_currency/clients/coingecko_client.py +0 -257
  123. django_cfg/modules/django_currency/clients/yfinance_client.py +0 -246
  124. {django_cfg-1.2.29.dist-info → django_cfg-1.2.31.dist-info}/WHEEL +0 -0
  125. {django_cfg-1.2.29.dist-info → django_cfg-1.2.31.dist-info}/entry_points.txt +0 -0
  126. {django_cfg-1.2.29.dist-info → django_cfg-1.2.31.dist-info}/licenses/LICENSE +0 -0
@@ -1,138 +1,254 @@
1
1
  """
2
- Currency models for the universal payments system.
2
+ Currency models for the universal payments system - KISS version.
3
3
  """
4
4
 
5
5
  from django.db import models
6
6
  from .base import TimestampedModel
7
7
 
8
+ # Currency converter import moved inside methods to avoid circular imports
8
9
 
9
10
  class Currency(TimestampedModel):
10
- """Supported currencies for payments."""
11
+ """Base currencies - clean, no provider-specific codes."""
11
12
 
12
13
  class CurrencyType(models.TextChoices):
13
14
  FIAT = "fiat", "Fiat Currency"
14
15
  CRYPTO = "crypto", "Cryptocurrency"
15
16
 
17
+ # Core fields - only essentials
16
18
  code = models.CharField(
17
19
  max_length=10,
18
20
  unique=True,
19
- help_text="Currency code (e.g., USD, BTC, ETH)"
21
+ help_text="Clean currency code: BTC, USDT, ETH, USD (NO network suffixes)"
20
22
  )
21
23
  name = models.CharField(
22
24
  max_length=100,
23
- help_text="Full currency name"
24
- )
25
- symbol = models.CharField(
26
- max_length=10,
27
- help_text="Currency symbol (e.g., $, ₿, Ξ)"
25
+ help_text="Currency name: Bitcoin, Tether USD, Ethereum"
28
26
  )
29
27
  currency_type = models.CharField(
30
28
  max_length=10,
31
29
  choices=CurrencyType.choices,
32
- help_text="Type of currency"
33
- )
34
- decimal_places = models.PositiveSmallIntegerField(
35
- default=2,
36
- help_text="Number of decimal places for this currency"
37
- )
38
- is_active = models.BooleanField(
39
- default=True,
40
- help_text="Whether this currency is active for payments"
41
- )
42
- min_payment_amount = models.FloatField(
43
- default=1.0,
44
- help_text="Minimum payment amount for this currency"
30
+ help_text="fiat or crypto"
45
31
  )
46
32
 
47
- # Exchange rate to USD (base currency)
48
- usd_rate = models.FloatField(
49
- default=1.0,
50
- help_text="Exchange rate to USD (1 unit of this currency = X USD)"
33
+ # USD rate caching - updated once per day
34
+ usd_rate = models.DecimalField(
35
+ max_digits=20,
36
+ decimal_places=8,
37
+ null=True,
38
+ blank=True,
39
+ help_text="Cached USD exchange rate (1 CURRENCY = X USD)"
51
40
  )
41
+
52
42
  rate_updated_at = models.DateTimeField(
53
43
  null=True,
54
44
  blank=True,
55
- help_text="When the exchange rate was last updated"
45
+ help_text="When the USD rate was last updated"
56
46
  )
57
47
 
58
- # Import and assign manager
59
- from ..managers import CurrencyManager
48
+ # Import manager
49
+ from ..managers.currency_manager import CurrencyManager
60
50
  objects = CurrencyManager()
61
51
 
62
52
  class Meta:
63
53
  db_table = 'payment_currencies'
64
54
  verbose_name = "Currency"
65
55
  verbose_name_plural = "Currencies"
66
- indexes = [
67
- models.Index(fields=['code']),
68
- models.Index(fields=['currency_type']),
69
- models.Index(fields=['is_active']),
70
- ]
71
- ordering = ['code']
56
+ ordering = ['currency_type', 'code']
72
57
 
73
58
  def __str__(self):
74
59
  return f"{self.code} - {self.name}"
75
60
 
76
61
  @property
77
62
  def is_fiat(self) -> bool:
78
- """Check if this is a fiat currency."""
79
63
  return self.currency_type == self.CurrencyType.FIAT
80
64
 
81
65
  @property
82
66
  def is_crypto(self) -> bool:
83
- """Check if this is a cryptocurrency."""
84
67
  return self.currency_type == self.CurrencyType.CRYPTO
68
+
69
+
70
+ class Network(TimestampedModel):
71
+ """Blockchain networks - code and name only."""
85
72
 
86
- def to_usd(self, amount: float) -> float:
87
- """Convert amount of this currency to USD."""
88
- return amount * self.usd_rate
73
+ code = models.CharField(
74
+ max_length=20,
75
+ unique=True,
76
+ help_text="Network code: ethereum, bitcoin, tron, bsc"
77
+ )
78
+ name = models.CharField(
79
+ max_length=100,
80
+ help_text="Network name: Ethereum, Bitcoin, TRON, BSC"
81
+ )
89
82
 
90
- def from_usd(self, usd_amount: float) -> float:
91
- """Convert USD amount to this currency."""
92
- if self.usd_rate == 0:
93
- return 0
94
- return usd_amount / self.usd_rate
83
+ # Import manager
84
+ from ..managers.currency_manager import NetworkManager
85
+ objects = NetworkManager()
86
+
87
+ class Meta:
88
+ db_table = 'payment_networks'
89
+ verbose_name = "Network"
90
+ verbose_name_plural = "Networks"
91
+ ordering = ['name']
92
+
93
+ def __str__(self):
94
+ return f"{self.name} ({self.code})"
95
95
 
96
96
 
97
- class CurrencyNetwork(TimestampedModel):
98
- """Networks/blockchains for cryptocurrencies."""
97
+ class ProviderCurrency(TimestampedModel):
98
+ """Provider-currency-network mapping - minimal."""
99
99
 
100
- currency = models.ForeignKey(
100
+ # Identification
101
+ provider_name = models.CharField(
102
+ max_length=50,
103
+ help_text="Provider: nowpayments, stripe, cryptomus"
104
+ )
105
+ provider_currency_code = models.CharField(
106
+ max_length=20,
107
+ help_text="Provider code: USDTERC20, USDTBSC, usd"
108
+ )
109
+
110
+ # Links to clean models
111
+ base_currency = models.ForeignKey(
101
112
  Currency,
102
113
  on_delete=models.CASCADE,
103
- related_name='networks',
104
- help_text="Currency this network supports"
114
+ related_name='provider_mappings',
115
+ help_text="Base currency: BTC, USDT, ETH"
105
116
  )
106
- network_name = models.CharField(
107
- max_length=50,
108
- help_text="Network name (e.g., mainnet, polygon, bsc)"
117
+ network = models.ForeignKey(
118
+ Network,
119
+ on_delete=models.CASCADE,
120
+ null=True,
121
+ blank=True,
122
+ related_name='provider_currencies',
123
+ help_text="Network for crypto (null for fiat)"
109
124
  )
110
- network_code = models.CharField(
111
- max_length=20,
112
- help_text="Network code for API integration"
125
+
126
+ # Universal provider fields - common across providers
127
+ min_amount = models.DecimalField(
128
+ max_digits=20,
129
+ decimal_places=8,
130
+ null=True,
131
+ blank=True,
132
+ help_text="Minimum payment amount"
113
133
  )
114
- is_active = models.BooleanField(
134
+ max_amount = models.DecimalField(
135
+ max_digits=20,
136
+ decimal_places=8,
137
+ null=True,
138
+ blank=True,
139
+ help_text="Maximum payment amount (null = no limit)"
140
+ )
141
+
142
+ # Status and availability
143
+ is_enabled = models.BooleanField(
115
144
  default=True,
116
- help_text="Whether this network is active"
145
+ help_text="Enabled by provider"
117
146
  )
118
- confirmation_blocks = models.PositiveIntegerField(
119
- default=1,
120
- help_text="Number of confirmations required"
147
+ available_for_payment = models.BooleanField(
148
+ default=True,
149
+ help_text="Can receive payments"
150
+ )
151
+ available_for_payout = models.BooleanField(
152
+ default=True,
153
+ help_text="Can send payouts"
121
154
  )
122
155
 
123
- # Import and assign manager
124
- from ..managers import CurrencyNetworkManager
125
- objects = CurrencyNetworkManager()
156
+ # Classification for UI
157
+ is_popular = models.BooleanField(
158
+ default=False,
159
+ help_text="Popular/recommended by provider"
160
+ )
161
+ is_stable = models.BooleanField(
162
+ default=False,
163
+ help_text="Stable coin (USDT, USDC, etc.)"
164
+ )
165
+ priority = models.IntegerField(
166
+ default=0,
167
+ help_text="Display priority (higher = shown first)"
168
+ )
169
+ logo_url = models.URLField(
170
+ blank=True,
171
+ help_text="Currency logo/icon URL from provider"
172
+ )
173
+
174
+ # Raw provider data - everything else goes here
175
+ metadata = models.JSONField(
176
+ default=dict,
177
+ blank=True,
178
+ help_text="All provider-specific data: logo_url, smart_contract, wallet_regex, commission_percent, etc."
179
+ )
180
+
181
+ # Import manager
182
+ from ..managers.currency_manager import ProviderCurrencyManager
183
+ objects = ProviderCurrencyManager()
126
184
 
127
185
  class Meta:
128
- db_table = 'payment_currency_networks'
129
- verbose_name = "Currency Network"
130
- verbose_name_plural = "Currency Networks"
131
- unique_together = [['currency', 'network_code']]
132
- indexes = [
133
- models.Index(fields=['currency', 'is_active']),
134
- models.Index(fields=['network_code']),
186
+ db_table = 'payment_provider_currencies'
187
+ verbose_name = "Provider Currency"
188
+ verbose_name_plural = "Provider Currencies"
189
+ unique_together = [
190
+ ('provider_name', 'provider_currency_code'),
191
+ ('provider_name', 'base_currency', 'network')
135
192
  ]
193
+ ordering = ['-priority', 'provider_name', 'base_currency__code']
136
194
 
137
195
  def __str__(self):
138
- return f"{self.currency.code} - {self.network_name}"
196
+ network_part = f" ({self.network.code})" if self.network else ""
197
+ return f"{self.provider_name}: {self.base_currency.code}{network_part}"
198
+
199
+ @property
200
+ def display_name(self) -> str:
201
+ """Human-readable name."""
202
+ if self.network:
203
+ return f"{self.base_currency.name} ({self.network.name})"
204
+ return self.base_currency.name
205
+
206
+ # Metadata helper properties
207
+
208
+ def is_amount_valid(self, amount) -> bool:
209
+ """Check if amount is within provider limits."""
210
+ if not amount:
211
+ return False
212
+
213
+ if self.min_amount and amount < self.min_amount:
214
+ return False
215
+
216
+ if self.max_amount and amount > self.max_amount:
217
+ return False
218
+
219
+ return True
220
+
221
+ def get_validation_errors(self, amount) -> list:
222
+ """Get validation errors for amount."""
223
+ errors = []
224
+
225
+ if not amount:
226
+ errors.append("Amount is required")
227
+ return errors
228
+
229
+ if self.min_amount and amount < self.min_amount:
230
+ errors.append(f"Amount must be at least {self.min_amount}")
231
+
232
+ if self.max_amount and amount > self.max_amount:
233
+ errors.append(f"Amount must not exceed {self.max_amount}")
234
+
235
+ return errors
236
+
237
+ @property
238
+ def usd_rate(self) -> float:
239
+ """Get USD rate for base currency (1 CURRENCY = X USD)."""
240
+ return Currency.objects.get_usd_rate(self.base_currency.code)
241
+
242
+ @property
243
+ def tokens_per_usd(self) -> float:
244
+ """Get how many tokens you can buy for 1 USD."""
245
+ return Currency.objects.get_tokens_per_usd(self.base_currency.code)
246
+
247
+ def convert_to_usd(self, amount: float) -> float:
248
+ """Convert amount of this currency to USD."""
249
+ return Currency.objects.convert_to_usd(amount, self.base_currency.code)
250
+
251
+ def convert_from_usd(self, usd_amount: float) -> float:
252
+ """Convert USD amount to this currency."""
253
+ return Currency.objects.convert_from_usd(usd_amount, self.base_currency.code)
254
+
@@ -13,6 +13,7 @@ User = get_user_model()
13
13
 
14
14
 
15
15
 
16
+
16
17
  class UniversalPayment(UUIDTimestampedModel):
17
18
  """Universal payment model for all providers."""
18
19
 
@@ -208,8 +209,8 @@ class UniversalPayment(UUIDTimestampedModel):
208
209
  help_text="When the payment was processed and funds added to balance"
209
210
  )
210
211
 
211
- # Import and assign manager
212
- from ..managers import UniversalPaymentManager
212
+ # Custom managers for optimized queries
213
+ from ..managers.payment_manager import UniversalPaymentManager
213
214
  objects = UniversalPaymentManager()
214
215
 
215
216
  class Meta:
@@ -16,7 +16,7 @@ from .api_keys import (
16
16
  APIKeySerializer, APIKeyCreateSerializer, APIKeyListSerializer
17
17
  )
18
18
  from .currencies import (
19
- CurrencySerializer, CurrencyNetworkSerializer, CurrencyListSerializer
19
+ CurrencySerializer, NetworkSerializer, ProviderCurrencySerializer, CurrencyListSerializer
20
20
  )
21
21
  from .tariffs import (
22
22
  TariffSerializer, TariffEndpointGroupSerializer, TariffListSerializer
@@ -46,7 +46,8 @@ __all__ = [
46
46
 
47
47
  # Currencies
48
48
  'CurrencySerializer',
49
- 'CurrencyNetworkSerializer',
49
+ 'NetworkSerializer',
50
+ 'ProviderCurrencySerializer',
50
51
  'CurrencyListSerializer',
51
52
 
52
53
  # Tariffs
@@ -3,7 +3,7 @@ Currency serializers.
3
3
  """
4
4
 
5
5
  from rest_framework import serializers
6
- from ..models import Currency, CurrencyNetwork
6
+ from ..models import Currency, Network, ProviderCurrency
7
7
 
8
8
 
9
9
  class CurrencySerializer(serializers.ModelSerializer):
@@ -16,9 +16,8 @@ class CurrencySerializer(serializers.ModelSerializer):
16
16
  class Meta:
17
17
  model = Currency
18
18
  fields = [
19
- 'id', 'code', 'name', 'symbol', 'currency_type', 'currency_type_display',
20
- 'is_crypto', 'is_fiat', 'decimal_places', 'usd_rate', 'rate_updated_at',
21
- 'is_active', 'min_payment_amount'
19
+ 'id', 'code', 'name', 'currency_type', 'currency_type_display',
20
+ 'is_crypto', 'is_fiat', 'usd_rate', 'rate_updated_at'
22
21
  ]
23
22
  read_only_fields = ['rate_updated_at']
24
23
 
@@ -31,17 +30,26 @@ class CurrencySerializer(serializers.ModelSerializer):
31
30
  return obj.is_fiat
32
31
 
33
32
 
34
- class CurrencyNetworkSerializer(serializers.ModelSerializer):
35
- """Currency network with status."""
33
+ class NetworkSerializer(serializers.ModelSerializer):
34
+ """Network information."""
36
35
 
37
- currency_code = serializers.CharField(source='currency.code', read_only=True)
38
- currency_name = serializers.CharField(source='currency.name', read_only=True)
36
+ class Meta:
37
+ model = Network
38
+ fields = ['id', 'code', 'name']
39
+
40
+
41
+ class ProviderCurrencySerializer(serializers.ModelSerializer):
42
+ """Provider currency with base currency and network info."""
43
+
44
+ base_currency = CurrencySerializer(read_only=True)
45
+ network = NetworkSerializer(read_only=True)
39
46
 
40
47
  class Meta:
41
- model = CurrencyNetwork
48
+ model = ProviderCurrency
42
49
  fields = [
43
- 'id', 'currency', 'currency_code', 'currency_name', 'network_code',
44
- 'network_name', 'is_active', 'confirmation_blocks'
50
+ 'id', 'provider_name', 'provider_currency_code', 'base_currency', 'network',
51
+ 'is_enabled', 'available_for_payment', 'available_for_payout',
52
+ 'is_popular', 'is_stable', 'min_amount', 'max_amount', 'logo_url'
45
53
  ]
46
54
 
47
55
 
@@ -52,4 +60,4 @@ class CurrencyListSerializer(serializers.ModelSerializer):
52
60
 
53
61
  class Meta:
54
62
  model = Currency
55
- fields = ['id', 'code', 'name', 'currency_type', 'currency_type_display', 'is_active']
63
+ fields = ['id', 'code', 'name', 'currency_type', 'currency_type_display']
@@ -3,14 +3,14 @@ Simple cache implementation for API keys and rate limiting.
3
3
  ONLY for API access control - NOT payment data!
4
4
  """
5
5
 
6
- import logging
6
+ from django_cfg.modules.django_logger import get_logger
7
7
  from typing import Optional, Any
8
8
  from django.core.cache import cache
9
9
 
10
10
  from .base import CacheInterface
11
11
  from ...utils.config_utils import CacheConfigHelper
12
12
 
13
- logger = logging.getLogger(__name__)
13
+ logger = get_logger("simple_cache")
14
14
 
15
15
 
16
16
  class SimpleCache(CacheInterface):
@@ -5,8 +5,8 @@ This service handles user balance operations, transaction recording,
5
5
  and balance validation with atomic operations.
6
6
  """
7
7
 
8
- import logging
9
8
  from typing import Dict, Any, Optional, List
9
+ from django_cfg.modules.django_logger import get_logger
10
10
  from decimal import Decimal
11
11
  from datetime import timezone
12
12
 
@@ -18,7 +18,7 @@ from ...models import UserBalance, Transaction
18
18
  from ..internal_types import ServiceOperationResult, BalanceUpdateRequest, UserBalanceResult, TransactionInfo
19
19
 
20
20
  User = get_user_model()
21
- logger = logging.getLogger(__name__)
21
+ logger = get_logger("balance_service")
22
22
 
23
23
 
24
24
  class BalanceOperation(BaseModel):
@@ -5,7 +5,7 @@ Handles automatic provider switching when providers become unavailable,
5
5
  ensuring payment system resilience and high availability.
6
6
  """
7
7
 
8
- import logging
8
+ from django_cfg.modules.django_logger import get_logger
9
9
  from typing import Optional, List, Dict, Any
10
10
  from dataclasses import dataclass
11
11
  from enum import Enum
@@ -18,7 +18,7 @@ from ..monitoring.provider_health import get_health_monitor, HealthStatus
18
18
  from ..providers.registry import ProviderRegistry
19
19
  from ...models.events import PaymentEvent
20
20
 
21
- logger = logging.getLogger(__name__)
21
+ logger = get_logger("fallback_service")
22
22
 
23
23
 
24
24
  class FallbackStrategy(Enum):
@@ -5,7 +5,6 @@ This service handles universal payment operations, provider orchestration,
5
5
  and payment lifecycle management.
6
6
  """
7
7
 
8
- import logging
9
8
  from typing import Optional, List
10
9
  from decimal import Decimal
11
10
  from django.db import transaction
@@ -18,6 +17,7 @@ from .fallback_service import get_fallback_service
18
17
  from ...models import UniversalPayment, UserBalance, Transaction
19
18
  from ...utils.config_utils import get_payments_config
20
19
  from ..providers.registry import ProviderRegistry
20
+ from django_cfg.modules.django_logger import get_logger
21
21
  from ..monitoring.provider_health import get_health_monitor
22
22
  from ..internal_types import (
23
23
  ProviderResponse, WebhookData, ServiceOperationResult,
@@ -28,9 +28,10 @@ from ..internal_types import (
28
28
 
29
29
  # Import django_currency module for currency conversion
30
30
  from django_cfg.modules.django_currency import convert_currency, CurrencyError
31
+ from ...models.events import PaymentEvent
31
32
 
32
33
  User = get_user_model()
33
- logger = logging.getLogger(__name__)
34
+ logger = get_logger("payment_service")
34
35
 
35
36
 
36
37
  class PaymentRequest(BaseModel):
@@ -501,8 +502,6 @@ class PaymentService:
501
502
  data: Event data
502
503
  """
503
504
  try:
504
- from ...models.events import PaymentEvent
505
-
506
505
  # Get next sequence number
507
506
  last_event = PaymentEvent.objects.filter(
508
507
  payment_id=str(payment.id)
@@ -534,8 +533,6 @@ class PaymentService:
534
533
  List of payment events
535
534
  """
536
535
  try:
537
- from ...models.events import PaymentEvent
538
-
539
536
  events = PaymentEvent.objects.filter(
540
537
  payment_id=payment_id
541
538
  ).order_by('sequence_number')
@@ -5,21 +5,21 @@ This service handles subscription creation, renewal, access validation,
5
5
  and usage tracking with Redis caching.
6
6
  """
7
7
 
8
- import logging
9
8
  from typing import Dict, Any, Optional, List
9
+ from django_cfg.modules.django_logger import get_logger
10
10
  from datetime import datetime, timedelta, timezone as dt_timezone
11
11
 
12
12
  from django.db import transaction
13
13
  from django.contrib.auth import get_user_model
14
14
  from django.utils import timezone
15
15
  from pydantic import BaseModel, Field, ValidationError
16
-
16
+ from decimal import Decimal
17
17
 
18
18
  from ...models import Subscription, EndpointGroup, Tariff
19
- from ..internal_types import ServiceOperationResult
19
+ from ..internal_types import ServiceOperationResult, SubscriptionInfo, EndpointGroupInfo
20
20
 
21
21
  User = get_user_model()
22
- logger = logging.getLogger(__name__)
22
+ logger = get_logger("subscription_service")
23
23
 
24
24
 
25
25
  class SubscriptionRequest(BaseModel):
@@ -276,9 +276,6 @@ class SubscriptionService:
276
276
  'endpoint_group'
277
277
  ).order_by('-created_at')
278
278
 
279
- from ..internal_types import SubscriptionInfo, EndpointGroupInfo
280
- from decimal import Decimal
281
-
282
279
  result = [
283
280
  SubscriptionInfo(
284
281
  id=str(sub.id),