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
@@ -1,235 +0,0 @@
1
- """
2
- Cache services for the Universal Payment System v2.0.
3
-
4
- Based on proven solutions from payments_old with improvements.
5
- ONLY for API access control - NOT payment data!
6
- """
7
-
8
- from abc import ABC, abstractmethod
9
- from typing import Optional, Any, Dict
10
- from django.core.cache import cache
11
- from django_cfg.modules.django_logger import get_logger
12
-
13
- logger = get_logger(__name__)
14
-
15
-
16
- class CacheInterface(ABC):
17
- """Abstract cache interface."""
18
-
19
- @abstractmethod
20
- def get(self, key: str) -> Optional[Any]:
21
- """Get value from cache."""
22
- pass
23
-
24
- @abstractmethod
25
- def set(self, key: str, value: Any, timeout: Optional[int] = None) -> bool:
26
- """Set value in cache."""
27
- pass
28
-
29
- @abstractmethod
30
- def delete(self, key: str) -> bool:
31
- """Delete value from cache."""
32
- pass
33
-
34
- @abstractmethod
35
- def exists(self, key: str) -> bool:
36
- """Check if key exists in cache."""
37
- pass
38
-
39
-
40
- class SimpleCache(CacheInterface):
41
- """
42
- Simple cache implementation using Django's cache framework.
43
-
44
- Falls back gracefully when cache is unavailable.
45
- Based on proven solution from payments_old.
46
- """
47
-
48
- def __init__(self, prefix: str = "payments"):
49
- self.prefix = prefix
50
- self.enabled = self._is_cache_enabled()
51
-
52
- def _is_cache_enabled(self) -> bool:
53
- """Check if cache is enabled via PaymentsConfig."""
54
- try:
55
- from django_cfg.models.payments import PaymentsConfig
56
- config = PaymentsConfig.get_current_config()
57
- return config.enabled # Cache enabled if payments enabled
58
- except Exception:
59
- return True # Default to enabled with graceful fallback
60
-
61
- def _make_key(self, key: str) -> str:
62
- """Create prefixed cache key."""
63
- return f"{self.prefix}:{key}"
64
-
65
- def get(self, key: str) -> Optional[Any]:
66
- """Get value from cache."""
67
- if not self.enabled:
68
- return None
69
-
70
- try:
71
- cache_key = self._make_key(key)
72
- return cache.get(cache_key)
73
- except Exception as e:
74
- logger.warning(f"Cache get failed for key {key}: {e}")
75
- return None
76
-
77
- def set(self, key: str, value: Any, timeout: Optional[int] = None) -> bool:
78
- """Set value in cache."""
79
- if not self.enabled:
80
- return False
81
-
82
- try:
83
- cache_key = self._make_key(key)
84
- cache.set(cache_key, value, timeout)
85
- return True
86
- except Exception as e:
87
- logger.warning(f"Cache set failed for key {key}: {e}")
88
- return False
89
-
90
- def delete(self, key: str) -> bool:
91
- """Delete value from cache."""
92
- if not self.enabled:
93
- return False
94
-
95
- try:
96
- cache_key = self._make_key(key)
97
- cache.delete(cache_key)
98
- return True
99
- except Exception as e:
100
- logger.warning(f"Cache delete failed for key {key}: {e}")
101
- return False
102
-
103
- def exists(self, key: str) -> bool:
104
- """Check if key exists in cache."""
105
- if not self.enabled:
106
- return False
107
-
108
- try:
109
- cache_key = self._make_key(key)
110
- return cache.get(cache_key) is not None
111
- except Exception as e:
112
- logger.warning(f"Cache exists check failed for key {key}: {e}")
113
- return False
114
-
115
-
116
- class ApiKeyCache:
117
- """Specialized cache for API key operations."""
118
-
119
- def __init__(self):
120
- self.cache = SimpleCache("api_keys")
121
- self.default_timeout = self._get_cache_timeout('api_key')
122
-
123
- def _get_cache_timeout(self, cache_type: str) -> int:
124
- """Get cache timeout from PaymentsConfig."""
125
- try:
126
- from django_cfg.models.payments import PaymentsConfig
127
- config = PaymentsConfig.get_current_config()
128
- return config.cache_timeouts.get(cache_type, 300)
129
- except Exception:
130
- return 300 # 5 minutes default
131
-
132
- def get_api_key_data(self, api_key: str) -> Optional[dict]:
133
- """Get cached API key data."""
134
- return self.cache.get(f"key:{api_key}")
135
-
136
- def cache_api_key_data(self, api_key: str, data: dict) -> bool:
137
- """Cache API key data."""
138
- return self.cache.set(f"key:{api_key}", data, self.default_timeout)
139
-
140
- def invalidate_api_key(self, api_key: str) -> bool:
141
- """Invalidate cached API key."""
142
- return self.cache.delete(f"key:{api_key}")
143
-
144
-
145
- class RateLimitCache:
146
- """Specialized cache for rate limiting."""
147
-
148
- def __init__(self):
149
- self.cache = SimpleCache("rate_limit")
150
-
151
- def get_usage_count(self, user_id: int, endpoint_group: str, window: str = "hour") -> int:
152
- """Get current usage count for rate limiting."""
153
- key = f"usage:{user_id}:{endpoint_group}:{window}"
154
- count = self.cache.get(key)
155
- return count if count is not None else 0
156
-
157
- def increment_usage(self, user_id: int, endpoint_group: str, window: str = "hour", ttl: Optional[int] = None) -> int:
158
- """Increment usage count and return new count."""
159
- key = f"usage:{user_id}:{endpoint_group}:{window}"
160
-
161
- # Get current count
162
- current = self.get_usage_count(user_id, endpoint_group, window)
163
- new_count = current + 1
164
-
165
- # Get TTL from config or use defaults
166
- if ttl is None:
167
- try:
168
- from django_cfg.models.payments import PaymentsConfig
169
- config = PaymentsConfig.get_current_config()
170
- ttl = config.cache_timeouts.get('rate_limit', 3600)
171
- except Exception:
172
- ttl = 3600 if window == "hour" else 86400 # 1 hour or 1 day
173
-
174
- # Set new count with TTL
175
- self.cache.set(key, new_count, ttl)
176
- return new_count
177
-
178
- def reset_usage(self, user_id: int, endpoint_group: str, window: str = "hour") -> bool:
179
- """Reset usage count."""
180
- key = f"usage:{user_id}:{endpoint_group}:{window}"
181
- return self.cache.delete(key)
182
-
183
-
184
- class CacheService:
185
- """
186
- Main cache service providing access to specialized caches.
187
-
188
- Provides centralized access to different cache types.
189
- """
190
-
191
- def __init__(self):
192
- """Initialize cache service with specialized caches."""
193
- self.simple_cache = SimpleCache()
194
- self.api_key_cache = ApiKeyCache()
195
- self.rate_limit_cache = RateLimitCache()
196
-
197
- def health_check(self) -> Dict[str, Any]:
198
- """Check cache health."""
199
- try:
200
- test_key = "health_check"
201
- test_value = "ok"
202
-
203
- # Test set/get/delete
204
- self.simple_cache.set(test_key, test_value, 10)
205
- retrieved = self.simple_cache.get(test_key)
206
- self.simple_cache.delete(test_key)
207
-
208
- is_healthy = retrieved == test_value
209
-
210
- return {
211
- 'healthy': is_healthy,
212
- 'backend': cache.__class__.__name__,
213
- 'simple_cache': True,
214
- 'api_key_cache': True,
215
- 'rate_limit_cache': True
216
- }
217
- except Exception as e:
218
- logger.error(f"Cache health check failed: {e}")
219
- return {
220
- 'healthy': False,
221
- 'error': str(e),
222
- 'backend': cache.__class__.__name__
223
- }
224
-
225
-
226
- # Global cache service instance
227
- _cache_service = None
228
-
229
-
230
- def get_cache_service() -> CacheService:
231
- """Get global cache service instance."""
232
- global _cache_service
233
- if _cache_service is None:
234
- _cache_service = CacheService()
235
- return _cache_service