django-cfg 1.3.1__py3-none-any.whl → 1.3.3__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 (25) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/payments/management/commands/cleanup_expired_data.py +419 -0
  3. django_cfg/apps/payments/management/commands/currency_stats.py +376 -0
  4. django_cfg/apps/payments/management/commands/process_pending_payments.py +357 -0
  5. django_cfg/apps/payments/management/commands/test_providers.py +434 -0
  6. django_cfg/apps/payments/models/balance.py +5 -2
  7. django_cfg/apps/payments/models/managers/api_key_managers.py +2 -2
  8. django_cfg/apps/payments/models/managers/balance_managers.py +3 -3
  9. django_cfg/apps/payments/models/managers/subscription_managers.py +3 -3
  10. django_cfg/apps/payments/services/cache_service/__init__.py +143 -0
  11. django_cfg/apps/payments/services/cache_service/api_key_cache.py +37 -0
  12. django_cfg/apps/payments/services/cache_service/interfaces.py +32 -0
  13. django_cfg/apps/payments/services/cache_service/keys.py +49 -0
  14. django_cfg/apps/payments/services/cache_service/rate_limit_cache.py +47 -0
  15. django_cfg/apps/payments/services/cache_service/simple_cache.py +101 -0
  16. django_cfg/apps/payments/services/core/payment_service.py +49 -22
  17. django_cfg/apps/payments/signals/api_key_signals.py +2 -2
  18. django_cfg/apps/payments/signals/balance_signals.py +1 -1
  19. django_cfg/utils/smart_defaults.py +10 -4
  20. {django_cfg-1.3.1.dist-info → django_cfg-1.3.3.dist-info}/METADATA +1 -1
  21. {django_cfg-1.3.1.dist-info → django_cfg-1.3.3.dist-info}/RECORD +24 -15
  22. django_cfg/apps/payments/services/cache/cache_service.py +0 -235
  23. {django_cfg-1.3.1.dist-info → django_cfg-1.3.3.dist-info}/WHEEL +0 -0
  24. {django_cfg-1.3.1.dist-info → django_cfg-1.3.3.dist-info}/entry_points.txt +0 -0
  25. {django_cfg-1.3.1.dist-info → django_cfg-1.3.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,37 @@
1
+ """
2
+ API Key cache implementation for the Universal Payment System v2.0.
3
+
4
+ Specialized caching for API key operations and validation.
5
+ """
6
+
7
+ from typing import Optional
8
+ from .simple_cache import SimpleCache
9
+
10
+
11
+ class ApiKeyCache:
12
+ """Specialized cache for API key operations."""
13
+
14
+ def __init__(self):
15
+ self.cache = SimpleCache("api_keys")
16
+ self.default_timeout = self._get_cache_timeout('api_key')
17
+
18
+ def _get_cache_timeout(self, cache_type: str) -> int:
19
+ """Get cache timeout from PaymentsConfig."""
20
+ try:
21
+ from django_cfg.models.payments import PaymentsConfig
22
+ config = PaymentsConfig.get_current_config()
23
+ return config.cache_timeouts.get(cache_type, 300)
24
+ except Exception:
25
+ return 300 # 5 minutes default
26
+
27
+ def get_api_key_data(self, api_key: str) -> Optional[dict]:
28
+ """Get cached API key data."""
29
+ return self.cache.get(f"key:{api_key}")
30
+
31
+ def cache_api_key_data(self, api_key: str, data: dict) -> bool:
32
+ """Cache API key data."""
33
+ return self.cache.set(f"key:{api_key}", data, self.default_timeout)
34
+
35
+ def invalidate_api_key(self, api_key: str) -> bool:
36
+ """Invalidate cached API key."""
37
+ return self.cache.delete(f"key:{api_key}")
@@ -0,0 +1,32 @@
1
+ """
2
+ Cache interfaces for the Universal Payment System v2.0.
3
+
4
+ Abstract interfaces for cache implementations.
5
+ """
6
+
7
+ from abc import ABC, abstractmethod
8
+ from typing import Optional, Any
9
+
10
+
11
+ class CacheInterface(ABC):
12
+ """Abstract cache interface."""
13
+
14
+ @abstractmethod
15
+ def get(self, key: str) -> Optional[Any]:
16
+ """Get value from cache."""
17
+ pass
18
+
19
+ @abstractmethod
20
+ def set(self, key: str, value: Any, timeout: Optional[int] = None) -> bool:
21
+ """Set value in cache."""
22
+ pass
23
+
24
+ @abstractmethod
25
+ def delete(self, key: str) -> bool:
26
+ """Delete value from cache."""
27
+ pass
28
+
29
+ @abstractmethod
30
+ def exists(self, key: str) -> bool:
31
+ """Check if key exists in cache."""
32
+ pass
@@ -0,0 +1,49 @@
1
+ """
2
+ Cache key generation utilities for the Universal Payment System v2.0.
3
+
4
+ Centralized cache key generation for consistency and testing.
5
+ """
6
+
7
+
8
+ class CacheKeys:
9
+ """Cache key generation utilities."""
10
+
11
+ @staticmethod
12
+ def user_balance(user_id: int) -> str:
13
+ """Generate cache key for user balance."""
14
+ return f"payments:user_balance:{user_id}"
15
+
16
+ @staticmethod
17
+ def payment(payment_id: str) -> str:
18
+ """Generate cache key for payment data."""
19
+ return f"payments:payment:{payment_id}"
20
+
21
+ @staticmethod
22
+ def payment_status(payment_id: str) -> str:
23
+ """Generate cache key for payment status."""
24
+ return f"payments:payment_status:{payment_id}"
25
+
26
+ @staticmethod
27
+ def currency_rates(from_currency: str, to_currency: str) -> str:
28
+ """Generate cache key for currency exchange rates."""
29
+ return f"payments:currency_rates:{from_currency}:{to_currency}"
30
+
31
+ @staticmethod
32
+ def provider_currencies(provider: str) -> str:
33
+ """Generate cache key for provider supported currencies."""
34
+ return f"payments:provider_currencies:{provider}"
35
+
36
+ @staticmethod
37
+ def api_key_validation(api_key: str) -> str:
38
+ """Generate cache key for API key validation data."""
39
+ return f"payments:api_key_validation:{api_key}"
40
+
41
+ @staticmethod
42
+ def user_subscription(user_id: int) -> str:
43
+ """Generate cache key for user subscription data."""
44
+ return f"payments:user_subscription:{user_id}"
45
+
46
+ @staticmethod
47
+ def rate_limit(user_id: int, action: str) -> str:
48
+ """Generate cache key for rate limiting."""
49
+ return f"payments:rate_limit:{user_id}:{action}"
@@ -0,0 +1,47 @@
1
+ """
2
+ Rate limiting cache implementation for the Universal Payment System v2.0.
3
+
4
+ Specialized caching for API rate limiting and usage tracking.
5
+ """
6
+
7
+ from typing import Optional
8
+ from .simple_cache import SimpleCache
9
+
10
+
11
+ class RateLimitCache:
12
+ """Specialized cache for rate limiting."""
13
+
14
+ def __init__(self):
15
+ self.cache = SimpleCache("rate_limit")
16
+
17
+ def get_usage_count(self, user_id: int, endpoint_group: str, window: str = "hour") -> int:
18
+ """Get current usage count for rate limiting."""
19
+ key = f"usage:{user_id}:{endpoint_group}:{window}"
20
+ count = self.cache.get(key)
21
+ return count if count is not None else 0
22
+
23
+ def increment_usage(self, user_id: int, endpoint_group: str, window: str = "hour", ttl: Optional[int] = None) -> int:
24
+ """Increment usage count and return new count."""
25
+ key = f"usage:{user_id}:{endpoint_group}:{window}"
26
+
27
+ # Get current count
28
+ current = self.get_usage_count(user_id, endpoint_group, window)
29
+ new_count = current + 1
30
+
31
+ # Get TTL from config or use defaults
32
+ if ttl is None:
33
+ try:
34
+ from django_cfg.models.payments import PaymentsConfig
35
+ config = PaymentsConfig.get_current_config()
36
+ ttl = config.cache_timeouts.get('rate_limit', 3600)
37
+ except Exception:
38
+ ttl = 3600 if window == "hour" else 86400 # 1 hour or 1 day
39
+
40
+ # Set new count with TTL
41
+ self.cache.set(key, new_count, ttl)
42
+ return new_count
43
+
44
+ def reset_usage(self, user_id: int, endpoint_group: str, window: str = "hour") -> bool:
45
+ """Reset usage count."""
46
+ key = f"usage:{user_id}:{endpoint_group}:{window}"
47
+ return self.cache.delete(key)
@@ -0,0 +1,101 @@
1
+ """
2
+ Simple cache implementation for the Universal Payment System v2.0.
3
+
4
+ Basic cache functionality with graceful fallback.
5
+ """
6
+
7
+ from typing import Optional, Any
8
+ from django.core.cache import cache
9
+ from django_cfg.modules.django_logger import get_logger
10
+
11
+ from .interfaces import CacheInterface
12
+
13
+ logger = get_logger(__name__)
14
+
15
+
16
+ class SimpleCache(CacheInterface):
17
+ """
18
+ Simple cache implementation using Django's cache framework.
19
+
20
+ Falls back gracefully when cache is unavailable.
21
+ Based on proven solution from payments_old.
22
+ """
23
+
24
+ def __init__(self, prefix: str = "payments"):
25
+ self.prefix = prefix
26
+ self.enabled = self._is_cache_enabled()
27
+
28
+ def _is_cache_enabled(self) -> bool:
29
+ """Check if cache is enabled via PaymentsConfig."""
30
+ from django.conf import settings
31
+ import sys
32
+
33
+ # For tests, always enable cache (detect test environment)
34
+ if 'test' in sys.argv or hasattr(settings, 'TESTING'):
35
+ return True
36
+
37
+ # For development, enable by default
38
+ if settings.DEBUG:
39
+ return True
40
+
41
+ try:
42
+ from django_cfg.models.payments import PaymentsConfig
43
+ config = PaymentsConfig.get_current_config()
44
+ return config.enabled # Cache enabled if payments enabled
45
+ except Exception as e:
46
+ logger.debug(f"PaymentsConfig not available, enabling cache by default: {e}")
47
+ return True # Default to enabled with graceful fallback
48
+
49
+ def _make_key(self, key: str) -> str:
50
+ """Create prefixed cache key."""
51
+ return f"{self.prefix}:{key}"
52
+
53
+ def get(self, key: str) -> Optional[Any]:
54
+ """Get value from cache."""
55
+ if not self.enabled:
56
+ return None
57
+
58
+ try:
59
+ cache_key = self._make_key(key)
60
+ return cache.get(cache_key)
61
+ except Exception as e:
62
+ logger.warning(f"Cache get failed for key {key}: {e}")
63
+ return None
64
+
65
+ def set(self, key: str, value: Any, timeout: Optional[int] = None) -> bool:
66
+ """Set value in cache."""
67
+ if not self.enabled:
68
+ return False
69
+
70
+ try:
71
+ cache_key = self._make_key(key)
72
+ cache.set(cache_key, value, timeout)
73
+ return True
74
+ except Exception as e:
75
+ logger.warning(f"Cache set failed for key {key}: {e}")
76
+ return False
77
+
78
+ def delete(self, key: str) -> bool:
79
+ """Delete value from cache."""
80
+ if not self.enabled:
81
+ return False
82
+
83
+ try:
84
+ cache_key = self._make_key(key)
85
+ cache.delete(cache_key)
86
+ return True
87
+ except Exception as e:
88
+ logger.warning(f"Cache delete failed for key {key}: {e}")
89
+ return False
90
+
91
+ def exists(self, key: str) -> bool:
92
+ """Check if key exists in cache."""
93
+ if not self.enabled:
94
+ return False
95
+
96
+ try:
97
+ cache_key = self._make_key(key)
98
+ return cache.get(cache_key) is not None
99
+ except Exception as e:
100
+ logger.warning(f"Cache exists check failed for key {key}: {e}")
101
+ return False
@@ -6,19 +6,20 @@ Handles payment creation, status checking, and lifecycle management.
6
6
 
7
7
  from typing import Optional, Dict, Any
8
8
  from decimal import Decimal
9
- from django.contrib.auth.models import User
9
+ from django.contrib.auth import get_user_model
10
+ from django.db import models
10
11
  from django.utils import timezone
11
12
 
13
+ from django_cfg.modules.django_currency import convert_currency, get_exchange_rate
12
14
  from .base import BaseService
13
15
  from ..types import (
14
16
  PaymentCreateRequest, PaymentStatusRequest, PaymentResult,
15
17
  PaymentData, ServiceOperationResult
16
18
  )
17
19
  from ...models import UniversalPayment, Currency, ProviderCurrency
18
- from django_cfg.modules.django_currency import convert_currency, get_exchange_rate
19
- # ConfigService removed - using direct Constance access
20
20
  from ..providers import ProviderRegistry, get_provider_registry
21
21
 
22
+ User = get_user_model()
22
23
 
23
24
  class PaymentService(BaseService):
24
25
  """
@@ -85,16 +86,17 @@ class PaymentService(BaseService):
85
86
 
86
87
  # Create payment in database first
87
88
  def create_payment_transaction():
89
+ currency = currency_result.data['currency']
88
90
  payment = UniversalPayment.objects.create(
89
91
  user=user,
90
92
  amount_usd=request.amount_usd,
91
- currency_code=request.currency_code,
93
+ currency=currency,
94
+ network=currency.native_networks.first(), # Use first native network
92
95
  provider=request.provider,
93
96
  status=UniversalPayment.PaymentStatus.PENDING,
94
97
  callback_url=request.callback_url,
95
98
  cancel_url=request.cancel_url,
96
99
  description=request.description,
97
- metadata=request.metadata,
98
100
  expires_at=timezone.now() + timezone.timedelta(hours=1) # 1 hour expiry
99
101
  )
100
102
  return payment
@@ -137,8 +139,8 @@ class PaymentService(BaseService):
137
139
  error_code="provider_creation_failed"
138
140
  )
139
141
 
140
- # Convert to PaymentData for response
141
- payment_data = PaymentData.model_validate(payment)
142
+ # Convert to PaymentData using our helper method
143
+ payment_data = self._convert_payment_to_data(payment)
142
144
 
143
145
  self._log_operation(
144
146
  "create_payment",
@@ -154,8 +156,9 @@ class PaymentService(BaseService):
154
156
  payment_id=str(payment.id),
155
157
  status=payment.status,
156
158
  amount_usd=payment.amount_usd,
157
- crypto_amount=payment.crypto_amount,
158
- currency_code=payment.currency_code,
159
+ crypto_amount=payment.pay_amount,
160
+ currency_code=payment.currency.code,
161
+ payment_url=payment.payment_url,
159
162
  expires_at=payment.expires_at,
160
163
  data={'payment': payment_data.model_dump()}
161
164
  )
@@ -211,8 +214,8 @@ class PaymentService(BaseService):
211
214
  # Reload payment if status was updated
212
215
  payment.refresh_from_db()
213
216
 
214
- # Convert to PaymentData
215
- payment_data = PaymentData.model_validate(payment)
217
+ # Convert to PaymentData using from_attributes
218
+ payment_data = self._convert_payment_to_data(payment)
216
219
 
217
220
  return PaymentResult(
218
221
  success=True,
@@ -220,12 +223,12 @@ class PaymentService(BaseService):
220
223
  payment_id=str(payment.id),
221
224
  status=payment.status,
222
225
  amount_usd=payment.amount_usd,
223
- crypto_amount=payment.crypto_amount,
224
- currency_code=payment.currency_code,
226
+ crypto_amount=payment.pay_amount,
227
+ currency_code=payment.currency.code,
225
228
  provider_payment_id=payment.provider_payment_id,
226
229
  payment_url=payment.payment_url,
227
- qr_code_url=payment.qr_code_url,
228
- wallet_address=payment.wallet_address,
230
+ qr_code_url=getattr(payment, 'qr_code_url', None),
231
+ wallet_address=payment.pay_address,
229
232
  expires_at=payment.expires_at,
230
233
  data={'payment': payment_data.model_dump()}
231
234
  )
@@ -279,7 +282,7 @@ class PaymentService(BaseService):
279
282
 
280
283
  if success:
281
284
  payment.refresh_from_db()
282
- payment_data = PaymentData.model_validate(payment)
285
+ payment_data = self._convert_payment_to_data(payment)
283
286
 
284
287
  self._log_operation(
285
288
  "cancel_payment",
@@ -311,7 +314,7 @@ class PaymentService(BaseService):
311
314
  def _validate_currency(self, currency_code: str) -> ServiceOperationResult:
312
315
  """Validate currency is supported."""
313
316
  try:
314
- currency = Currency.objects.get(code=currency_code, is_enabled=True)
317
+ currency = Currency.objects.get(code=currency_code, is_active=True)
315
318
 
316
319
  # Check if currency is supported by any provider
317
320
  provider_currency = ProviderCurrency.objects.filter(
@@ -327,7 +330,7 @@ class PaymentService(BaseService):
327
330
 
328
331
  return self._create_success_result(
329
332
  "Currency is valid",
330
- {'currency': currency_code}
333
+ {'currency': currency} # Wrap in dict for Pydantic
331
334
  )
332
335
 
333
336
  except Currency.DoesNotExist:
@@ -391,10 +394,10 @@ class PaymentService(BaseService):
391
394
  total_count = queryset.count()
392
395
  payments = queryset.order_by('-created_at')[offset:offset + limit]
393
396
 
394
- payment_data = [
395
- PaymentData.model_validate(payment).model_dump()
396
- for payment in payments
397
- ]
397
+ payment_data = []
398
+ for payment in payments:
399
+ payment_obj = self._convert_payment_to_data(payment)
400
+ payment_data.append(payment_obj.model_dump())
398
401
 
399
402
  return self._create_success_result(
400
403
  f"Retrieved {len(payment_data)} payments",
@@ -413,6 +416,30 @@ class PaymentService(BaseService):
413
416
  user_id=user_id
414
417
  )
415
418
 
419
+ def _convert_payment_to_data(self, payment: UniversalPayment) -> PaymentData:
420
+ """Convert Django UniversalPayment to PaymentData."""
421
+ return PaymentData(
422
+ id=str(payment.id),
423
+ user_id=payment.user_id,
424
+ amount_usd=float(payment.amount_usd),
425
+ crypto_amount=payment.pay_amount,
426
+ currency_code=payment.currency.code,
427
+ provider=payment.provider,
428
+ status=payment.status,
429
+ provider_payment_id=payment.provider_payment_id,
430
+ payment_url=payment.payment_url,
431
+ qr_code_url=getattr(payment, 'qr_code_url', None),
432
+ wallet_address=payment.pay_address,
433
+ callback_url=payment.callback_url,
434
+ cancel_url=payment.cancel_url,
435
+ description=payment.description,
436
+ metadata={},
437
+ created_at=payment.created_at,
438
+ updated_at=payment.updated_at,
439
+ expires_at=payment.expires_at,
440
+ completed_at=getattr(payment, 'completed_at', None)
441
+ )
442
+
416
443
  def get_payment_stats(self, days: int = 30) -> ServiceOperationResult:
417
444
  """Get payment statistics."""
418
445
  try:
@@ -43,7 +43,7 @@ def handle_api_key_changes(sender, instance: APIKey, created: bool, **kwargs):
43
43
  logger.info(f"New API key created", extra={
44
44
  'api_key_id': str(instance.id),
45
45
  'user_id': instance.user.id,
46
- 'name': instance.name,
46
+ 'key_name': instance.name,
47
47
  'expires_at': instance.expires_at.isoformat() if instance.expires_at else None
48
48
  })
49
49
 
@@ -52,7 +52,7 @@ def handle_api_key_changes(sender, instance: APIKey, created: bool, **kwargs):
52
52
  f"api_key_created:{instance.user.id}:{instance.id}",
53
53
  {
54
54
  'api_key_id': str(instance.id),
55
- 'name': instance.name,
55
+ 'key_name': instance.name,
56
56
  'timestamp': timezone.now().isoformat()
57
57
  },
58
58
  timeout=86400 # 24 hours
@@ -81,7 +81,7 @@ def handle_transaction_creation(sender, instance: Transaction, created: bool, **
81
81
  'transaction_id': str(instance.id),
82
82
  'user_id': instance.user.id,
83
83
  'transaction_type': instance.transaction_type,
84
- 'amount': instance.amount,
84
+ 'amount': instance.amount_usd,
85
85
  'payment_id': str(instance.payment_id) if instance.payment_id else None
86
86
  })
87
87
 
@@ -50,15 +50,21 @@ class SmartDefaults:
50
50
  @staticmethod
51
51
  def get_database_defaults(environment: str = "development", debug: bool = False, engine: str = "sqlite3") -> Dict[str, Any]:
52
52
  """Get database configuration defaults."""
53
- return {
53
+ defaults = {
54
54
  'ENGINE': 'django.db.backends.sqlite3',
55
55
  'NAME': Path('db') / 'db.sqlite3',
56
56
  'ATOMIC_REQUESTS': True,
57
57
  'CONN_MAX_AGE': 60,
58
- 'OPTIONS': {
59
- 'timeout': 20,
60
- }
58
+ 'OPTIONS': {}
61
59
  }
60
+
61
+ # Add engine-specific options
62
+ if engine == "django.db.backends.postgresql":
63
+ defaults['OPTIONS']['connect_timeout'] = 20
64
+ elif engine == "django.db.backends.sqlite3":
65
+ defaults['OPTIONS']['timeout'] = 20 # SQLite uses 'timeout'
66
+
67
+ return defaults
62
68
 
63
69
  @staticmethod
64
70
  def get_cache_defaults() -> Dict[str, Any]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cfg
3
- Version: 1.3.1
3
+ Version: 1.3.3
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
@@ -1,5 +1,5 @@
1
1
  django_cfg/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- django_cfg/__init__.py,sha256=Kh_1ZiiR3P_VYqAdl9_rNfN0CYQh9ue3pRtboDq2UWU,1630
2
+ django_cfg/__init__.py,sha256=tA-lxGDQpDFg-AcpBhuyA2sNdleuJjI4TbNJwxuQTWk,1630
3
3
  django_cfg/apps.py,sha256=k84brkeXJI7EgKZLEpTkM9YFZofKI4PzhFOn1cl9Msc,1656
4
4
  django_cfg/config.py,sha256=cbrtZxfXbI5p-qfdK5eR86OGxIbm4827zYdGIr6LmNg,1399
5
5
  django_cfg/apps/__init__.py,sha256=JtDmEYt1OcleWM2ZaeX0LKDnRQzPOavfaXBWG4ECB5Q,26
@@ -297,8 +297,12 @@ django_cfg/apps/payments/config/constance/fields.py,sha256=v45-3ulrrxUesj9r3WEuX
297
297
  django_cfg/apps/payments/config/constance/settings.py,sha256=PTzAPwbTV9FX8LwYY0OYkuvbWcIVU47XEeDqTbbbwv0,6854
298
298
  django_cfg/apps/payments/management/__init__.py,sha256=1qi5wv2KVLIKoGVzItrB78D8xrbf3ruwO3_kGZ7bLh4,30
299
299
  django_cfg/apps/payments/management/commands/__init__.py,sha256=1pri3qN5PLFIRSwxLkZJ7Bc4W4UyiKBZCcJjqy1IUr0,22
300
+ django_cfg/apps/payments/management/commands/cleanup_expired_data.py,sha256=fKvpSlCwaCiJorlN2vhnid-iUHAwsM3fHJfVB9uKKag,15168
301
+ django_cfg/apps/payments/management/commands/currency_stats.py,sha256=yftYm7edz1oxbP1xYR6CO0lR61YUSliOpJlw7tGMi7g,14974
300
302
  django_cfg/apps/payments/management/commands/manage_currencies.py,sha256=yQjOl25wT3UUmA8uLKI-p4PE0adpxMAhy81TVid7ZDs,15339
301
303
  django_cfg/apps/payments/management/commands/manage_providers.py,sha256=ojSvGOtjSLnZ8M0-WziC6qNd-sDrXnIzgm7YId7OnuU,15745
304
+ django_cfg/apps/payments/management/commands/process_pending_payments.py,sha256=yfmO9sRulGfZQi-tIdf2qWniCU1HhqtGxBY-j_N4UkM,13308
305
+ django_cfg/apps/payments/management/commands/test_providers.py,sha256=qpXTiKoErZBIXz2KtiWqa4IwWbK8c5WuABE2tDR_eGY,18475
302
306
  django_cfg/apps/payments/middleware/__init__.py,sha256=eL5TmlCKmpW53Ift5rtwS8ss1wUqp4j2gzjGhcAQUQY,380
303
307
  django_cfg/apps/payments/middleware/api_access.py,sha256=0UEHUNKjNKsewBNDMMNtOdywrj0w84fh0wbw-jjrvn4,15312
304
308
  django_cfg/apps/payments/middleware/rate_limiting.py,sha256=U6mEyonU3JAK0LZjZqp-q4KgHnXdWpUJT4LJ1jCeQRQ,14813
@@ -307,26 +311,31 @@ django_cfg/apps/payments/migrations/0001_initial.py,sha256=DYi5gAC-4U7Mijrj_wKGu
307
311
  django_cfg/apps/payments/migrations/__init__.py,sha256=OHlzxEGDJYKZz82orZXnh77xy-Okv6FcG3EKMfg9LzU,21
308
312
  django_cfg/apps/payments/models/__init__.py,sha256=7x38zrZjYxH3tV079SthGZeIjuyNB5hbqirT03-ZxuE,1443
309
313
  django_cfg/apps/payments/models/api_keys.py,sha256=dAS9XSOwAOBK40qnjrElz04Up9sqNGNg_0k13pnUjbs,5344
310
- django_cfg/apps/payments/models/balance.py,sha256=utryquLyGrxYnKrBlXRtFWXrJafvwZCK3fiiLgNCpMo,7857
314
+ django_cfg/apps/payments/models/balance.py,sha256=esjkt-VIdWBu09eqxTwP5WmcGdI4aCbXSfjoTHwYZec,8084
311
315
  django_cfg/apps/payments/models/base.py,sha256=XXMxqHe7OYmzVBW7g8nXgE41wJMigkRtgkPYGTx53oA,2212
312
316
  django_cfg/apps/payments/models/currencies.py,sha256=6ONWpBoZUOFVIHGzj_j1LZsI0yRRhk1x9sNn6kINAA8,8458
313
317
  django_cfg/apps/payments/models/payments.py,sha256=qvSBAl5YSqttZCAgaYCIyP23KiCJafzt0HZEJoAkNpg,11321
314
318
  django_cfg/apps/payments/models/subscriptions.py,sha256=w2zUrybgsKGfQ2QO0QbWHPp5ZZshVrf013CyfKoxdVA,11037
315
319
  django_cfg/apps/payments/models/tariffs.py,sha256=b2iDC7hBdZR8TX8aEskM5nTEa5_f0H6-j6wZdcbHdyk,6471
316
320
  django_cfg/apps/payments/models/managers/__init__.py,sha256=56kdXtRJOLHhtnY4arYi15fEAmWWrWJP0F8kn8okpzU,1090
317
- django_cfg/apps/payments/models/managers/api_key_managers.py,sha256=zL3NPUPDuNepypu02UxoQD-e5RgXGC0HNEpL0IMWGNA,10420
318
- django_cfg/apps/payments/models/managers/balance_managers.py,sha256=1uMINGsCk6qzgx3vi8OLRtVbKuIU3Y5VpmF9JPjukc0,20299
321
+ django_cfg/apps/payments/models/managers/api_key_managers.py,sha256=LuSugGdivQ_3Cb_6feJKa2AHTKdH-vFD68mWKM3Kgb8,10428
322
+ django_cfg/apps/payments/models/managers/balance_managers.py,sha256=84iV5cfSWiETyfLXoSK_s6A1lRv_dsOxu_n6V57gbEY,20298
319
323
  django_cfg/apps/payments/models/managers/currency_managers.py,sha256=ybLPx24rdnXo8jhCybq_3p5_si9BAhOSwIYib3tey-g,13061
320
324
  django_cfg/apps/payments/models/managers/payment_managers.py,sha256=Hrkpk6N2bm8uxqNKFy7MTXg8W6-GVw5KMVNj4WYJ-9k,17547
321
- django_cfg/apps/payments/models/managers/subscription_managers.py,sha256=52t5JfOXq_fTLGbEB1daFZLnRx5X5lkqLO7obkCoH68,21686
325
+ django_cfg/apps/payments/models/managers/subscription_managers.py,sha256=_hDmneMMTtvo2htNDDZOxuoYyxNKP46JC0MrXLwv5f8,21688
322
326
  django_cfg/apps/payments/services/__init__.py,sha256=QUFVfTwliUvQWtaw0JqDss_LDamgNZwaej8fzL6Qzco,6147
323
327
  django_cfg/apps/payments/services/cache/__init__.py,sha256=xIeDSSelNoS2eiWlIn-qsK9tYDizPJtVmBH1Ghc7wxk,353
324
- django_cfg/apps/payments/services/cache/cache_service.py,sha256=oPbRnjDmSf6nPpP5jbA4QfWC5G1yVeVC0rdOByDPpUw,7705
328
+ django_cfg/apps/payments/services/cache_service/__init__.py,sha256=Lp29sQUzuW7tKfrT6JBQYZgQ_ko4hqm2XozQ0XkC5Gc,4291
329
+ django_cfg/apps/payments/services/cache_service/api_key_cache.py,sha256=kVLUC5WbRpxXNGiKfcgnR7j4kBH861KpMTuGZJo8ADY,1292
330
+ django_cfg/apps/payments/services/cache_service/interfaces.py,sha256=7sqTRBSX4BPZ_Oxw6RJTyoLLHTLB5__adyNFZeAzjBI,758
331
+ django_cfg/apps/payments/services/cache_service/keys.py,sha256=U37Dwkboxn0E_B5MpfcY0RobIzhC5SQklE-jfkBMcOg,1700
332
+ django_cfg/apps/payments/services/cache_service/rate_limit_cache.py,sha256=MjFn5q23WjupNI2wZ9KpUJZR5TxX1zkYp6Cu1okZIfQ,1785
333
+ django_cfg/apps/payments/services/cache_service/simple_cache.py,sha256=aoAVHLfDUpAF0DP7UQYywGKjg8KzPjzu5xxMqRmN8zU,3258
325
334
  django_cfg/apps/payments/services/core/__init__.py,sha256=CY2M4ID3rqcdpbokQSdO_fxtdCfHjsGgBsTznyGPw3k,526
326
335
  django_cfg/apps/payments/services/core/balance_service.py,sha256=vNYJfRS_nsAzxq8aGmwp96Tj5UUgXBoNlMRwP45n9Jc,18212
327
336
  django_cfg/apps/payments/services/core/base.py,sha256=BBOUWPx3dS7u7Ix7KaAyuacCTfXM9jympUuaRSGP4-M,5448
328
337
  django_cfg/apps/payments/services/core/currency_service.py,sha256=1E6uX9rhJyycfktxunkHPD3nhCLWLchXZoVXiwjGiOM,18174
329
- django_cfg/apps/payments/services/core/payment_service.py,sha256=KoSSk_t68h645Cz4mG0lG4DN6GSIrJ1_tt6MkPtylvg,17424
338
+ django_cfg/apps/payments/services/core/payment_service.py,sha256=X8-yXpBFnvfSVEidMrj42RRvQRZFSKu0cTTrRTtCU0s,18727
330
339
  django_cfg/apps/payments/services/core/subscription_service.py,sha256=1kfxaW-BybIwQkbEpizxNJG_Egz6aF1qCVF2mX4v7Q4,21125
331
340
  django_cfg/apps/payments/services/core/webhook_service.py,sha256=5Ly44QDUQJYm7V5xkOoKaPzobwf5MkLjFI6uamrpTY0,16222
332
341
  django_cfg/apps/payments/services/integrations/__init__.py,sha256=sD48dDem1rqR8jALgrShBfm0-VMhvbK32q4_ufGElq8,663
@@ -342,8 +351,8 @@ django_cfg/apps/payments/services/types/requests.py,sha256=0s-5kPdtInnXJE_0lVUlI
342
351
  django_cfg/apps/payments/services/types/responses.py,sha256=3FdyNOGQEoI8uZNjBPhhw1XtXqs-2lo02qZ5TQg-CqY,7947
343
352
  django_cfg/apps/payments/services/types/webhooks.py,sha256=y7R1CoAZBRn71y9Mc8k6VVj5rjpbQ1ZHJkNHD1ZyK3M,10095
344
353
  django_cfg/apps/payments/signals/__init__.py,sha256=rSso5kyUszEtlbYiw6A72XU2mK1gmB7O9n2lQb2GPWQ,933
345
- django_cfg/apps/payments/signals/api_key_signals.py,sha256=u_YhN-V8dTBSrLCsc4RwqbIYVMybMPylG61umK9TInA,8579
346
- django_cfg/apps/payments/signals/balance_signals.py,sha256=hrnjs7f4-KZQYN9-y258rFuH8RW610ddDsYQW3-R8nA,5998
354
+ django_cfg/apps/payments/signals/api_key_signals.py,sha256=fR61t2mOAORD-ugWl4u6ZSP5nuykahnyIqh1uWjRnbY,8587
355
+ django_cfg/apps/payments/signals/balance_signals.py,sha256=ByPFzeMpNwo1vGmkeTg0bzLyAhaRPqVdgEvGayUN43Q,6002
347
356
  django_cfg/apps/payments/signals/payment_signals.py,sha256=uV5v1HlHKxP4A_bpIC1TkTHkj28nEsP3gbRJx3ca0iI,5449
348
357
  django_cfg/apps/payments/signals/subscription_signals.py,sha256=erzd3UczXGKamUecq2r2DeLm-0ycpFANy0nO948qmwg,9061
349
358
  django_cfg/apps/payments/static/payments/css/components.css,sha256=CE9HL-pqlq1gvmluNIXh5-GvRvHLSYHRm-MVxURZO-I,8395
@@ -619,11 +628,11 @@ django_cfg/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
619
628
  django_cfg/templatetags/django_cfg.py,sha256=11_3YX0jAVuOd_fVcDixAxyDMG4V7A98SPqv8Lbfpxc,1308
620
629
  django_cfg/utils/__init__.py,sha256=64wwXJuXytvwt8Ze_erSR2HmV07nGWJ6DV5wloRBvYE,435
621
630
  django_cfg/utils/path_resolution.py,sha256=C9As6p4Q9l3VeoVkFDRPQWGrzAWf8O8UxLVkaI3ToVM,13899
622
- django_cfg/utils/smart_defaults.py,sha256=Wola023crqB0zMzqMCN2Ne3Q5KcQ7x0-AgpaGhZ0m84,8938
631
+ django_cfg/utils/smart_defaults.py,sha256=Otmho1DGvuC8eaYgY3X6VA0okf8srYRyW6OQBonpEjE,9214
623
632
  django_cfg/utils/toolkit.py,sha256=MfnjfGl2_VZo2o5aWIJaOYz2w45HQfOjO6X6nm5BJ8k,25312
624
633
  django_cfg/utils/version_check.py,sha256=jI4v3YMdQriUEeb_TvRl511sDghy6I75iKRDUaNpucs,4800
625
- django_cfg-1.3.1.dist-info/METADATA,sha256=oy1GCbPlrwEsSyAvAZtbfgXYJ-NYPckUwVYGlMKF4ms,38740
626
- django_cfg-1.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
627
- django_cfg-1.3.1.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
628
- django_cfg-1.3.1.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
629
- django_cfg-1.3.1.dist-info/RECORD,,
634
+ django_cfg-1.3.3.dist-info/METADATA,sha256=ItziNnmUhaCQo35YUTrSoZ9nSJDk6MN9ZsehpFqbhNs,38740
635
+ django_cfg-1.3.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
636
+ django_cfg-1.3.3.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
637
+ django_cfg-1.3.3.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
638
+ django_cfg-1.3.3.dist-info/RECORD,,