django-cfg 1.2.31__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 (264) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/api/health/views.py +4 -2
  3. django_cfg/apps/knowbase/config/settings.py +16 -15
  4. django_cfg/apps/payments/README.md +326 -0
  5. django_cfg/apps/payments/admin/__init__.py +20 -10
  6. django_cfg/apps/payments/admin/api_keys_admin.py +521 -237
  7. django_cfg/apps/payments/admin/balance_admin.py +592 -297
  8. django_cfg/apps/payments/admin/currencies_admin.py +526 -222
  9. django_cfg/apps/payments/admin/filters.py +306 -199
  10. django_cfg/apps/payments/admin/payments_admin.py +465 -70
  11. django_cfg/apps/payments/admin/subscriptions_admin.py +578 -128
  12. django_cfg/apps/payments/admin_interface/__init__.py +18 -0
  13. django_cfg/apps/payments/admin_interface/templates/payments/base.html +162 -0
  14. django_cfg/apps/payments/admin_interface/templates/payments/components/dev_tool_card.html +38 -0
  15. django_cfg/apps/payments/admin_interface/templates/payments/components/loading_spinner.html +16 -0
  16. django_cfg/apps/payments/admin_interface/templates/payments/components/notification.html +27 -0
  17. django_cfg/apps/payments/admin_interface/templates/payments/components/provider_card.html +86 -0
  18. django_cfg/apps/payments/admin_interface/templates/payments/components/status_card.html +39 -0
  19. django_cfg/apps/payments/admin_interface/templates/payments/currency_converter.html +382 -0
  20. django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +300 -0
  21. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +303 -0
  22. django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +382 -0
  23. django_cfg/apps/payments/admin_interface/templates/payments/payment_status.html +500 -0
  24. django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +594 -0
  25. django_cfg/apps/payments/admin_interface/views/__init__.py +23 -0
  26. django_cfg/apps/payments/admin_interface/views/payment_views.py +259 -0
  27. django_cfg/apps/payments/admin_interface/views/webhook_dashboard.py +37 -0
  28. django_cfg/apps/payments/apps.py +34 -9
  29. django_cfg/apps/payments/config/__init__.py +28 -51
  30. django_cfg/apps/payments/config/constance/__init__.py +22 -0
  31. django_cfg/apps/payments/config/constance/config_service.py +123 -0
  32. django_cfg/apps/payments/config/constance/fields.py +69 -0
  33. django_cfg/apps/payments/config/constance/settings.py +160 -0
  34. django_cfg/apps/payments/config/django_cfg_integration.py +202 -0
  35. django_cfg/apps/payments/config/helpers.py +130 -0
  36. django_cfg/apps/payments/management/__init__.py +1 -3
  37. django_cfg/apps/payments/management/commands/__init__.py +1 -3
  38. django_cfg/apps/payments/management/commands/cleanup_expired_data.py +419 -0
  39. django_cfg/apps/payments/management/commands/currency_stats.py +297 -225
  40. django_cfg/apps/payments/management/commands/manage_currencies.py +303 -151
  41. django_cfg/apps/payments/management/commands/manage_providers.py +333 -160
  42. django_cfg/apps/payments/management/commands/process_pending_payments.py +357 -0
  43. django_cfg/apps/payments/management/commands/test_providers.py +434 -0
  44. django_cfg/apps/payments/middleware/__init__.py +3 -1
  45. django_cfg/apps/payments/middleware/api_access.py +329 -222
  46. django_cfg/apps/payments/middleware/rate_limiting.py +342 -152
  47. django_cfg/apps/payments/middleware/usage_tracking.py +249 -240
  48. django_cfg/apps/payments/migrations/0001_initial.py +708 -536
  49. django_cfg/apps/payments/models/__init__.py +13 -18
  50. django_cfg/apps/payments/models/api_keys.py +121 -43
  51. django_cfg/apps/payments/models/balance.py +153 -115
  52. django_cfg/apps/payments/models/base.py +68 -15
  53. django_cfg/apps/payments/models/currencies.py +172 -148
  54. django_cfg/apps/payments/models/managers/__init__.py +44 -0
  55. django_cfg/apps/payments/models/managers/api_key_managers.py +329 -0
  56. django_cfg/apps/payments/models/managers/balance_managers.py +599 -0
  57. django_cfg/apps/payments/models/managers/currency_managers.py +385 -0
  58. django_cfg/apps/payments/models/managers/payment_managers.py +511 -0
  59. django_cfg/apps/payments/models/managers/subscription_managers.py +641 -0
  60. django_cfg/apps/payments/models/payments.py +235 -285
  61. django_cfg/apps/payments/models/subscriptions.py +257 -177
  62. django_cfg/apps/payments/models/tariffs.py +147 -40
  63. django_cfg/apps/payments/services/__init__.py +209 -56
  64. django_cfg/apps/payments/services/cache/__init__.py +6 -6
  65. django_cfg/apps/payments/services/cache_service/__init__.py +143 -0
  66. django_cfg/apps/payments/services/cache_service/api_key_cache.py +37 -0
  67. django_cfg/apps/payments/services/{cache/base.py → cache_service/interfaces.py} +3 -1
  68. django_cfg/apps/payments/services/cache_service/keys.py +49 -0
  69. django_cfg/apps/payments/services/cache_service/rate_limit_cache.py +47 -0
  70. django_cfg/apps/payments/services/cache_service/simple_cache.py +101 -0
  71. django_cfg/apps/payments/services/core/__init__.py +10 -6
  72. django_cfg/apps/payments/services/core/balance_service.py +435 -360
  73. django_cfg/apps/payments/services/core/base.py +166 -0
  74. django_cfg/apps/payments/services/core/currency_service.py +478 -0
  75. django_cfg/apps/payments/services/core/payment_service.py +371 -465
  76. django_cfg/apps/payments/services/core/subscription_service.py +425 -481
  77. django_cfg/apps/payments/services/core/webhook_service.py +410 -0
  78. django_cfg/apps/payments/services/integrations/__init__.py +29 -0
  79. django_cfg/apps/payments/services/integrations/ngrok_service.py +47 -0
  80. django_cfg/apps/payments/services/integrations/providers_config.py +107 -0
  81. django_cfg/apps/payments/services/providers/__init__.py +9 -14
  82. django_cfg/apps/payments/services/providers/base.py +234 -174
  83. django_cfg/apps/payments/services/providers/nowpayments.py +478 -0
  84. django_cfg/apps/payments/services/providers/registry.py +367 -301
  85. django_cfg/apps/payments/services/types/__init__.py +78 -0
  86. django_cfg/apps/payments/services/types/data.py +177 -0
  87. django_cfg/apps/payments/services/types/requests.py +150 -0
  88. django_cfg/apps/payments/services/types/responses.py +156 -0
  89. django_cfg/apps/payments/services/types/webhooks.py +232 -0
  90. django_cfg/apps/payments/signals/__init__.py +33 -8
  91. django_cfg/apps/payments/signals/api_key_signals.py +210 -129
  92. django_cfg/apps/payments/signals/balance_signals.py +174 -0
  93. django_cfg/apps/payments/signals/payment_signals.py +128 -103
  94. django_cfg/apps/payments/signals/subscription_signals.py +194 -142
  95. django_cfg/apps/payments/static/payments/css/components.css +380 -0
  96. django_cfg/apps/payments/static/payments/css/dashboard.css +188 -0
  97. django_cfg/apps/payments/static/payments/js/components.js +545 -0
  98. django_cfg/apps/payments/static/payments/js/utils.js +412 -0
  99. django_cfg/apps/payments/templatetags/__init__.py +1 -1
  100. django_cfg/apps/payments/templatetags/payment_tags.py +466 -0
  101. django_cfg/apps/payments/urls.py +45 -48
  102. django_cfg/apps/payments/urls_admin.py +33 -42
  103. django_cfg/apps/payments/views/api/__init__.py +101 -0
  104. django_cfg/apps/payments/views/api/api_keys.py +387 -0
  105. django_cfg/apps/payments/views/api/balances.py +381 -0
  106. django_cfg/apps/payments/views/api/base.py +298 -0
  107. django_cfg/apps/payments/views/api/currencies.py +402 -0
  108. django_cfg/apps/payments/views/api/payments.py +415 -0
  109. django_cfg/apps/payments/views/api/subscriptions.py +475 -0
  110. django_cfg/apps/payments/views/api/webhooks.py +476 -0
  111. django_cfg/apps/payments/views/serializers/__init__.py +99 -0
  112. django_cfg/apps/payments/views/serializers/api_keys.py +424 -0
  113. django_cfg/apps/payments/views/serializers/balances.py +300 -0
  114. django_cfg/apps/payments/views/serializers/currencies.py +335 -0
  115. django_cfg/apps/payments/views/serializers/payments.py +387 -0
  116. django_cfg/apps/payments/views/serializers/subscriptions.py +429 -0
  117. django_cfg/apps/payments/views/serializers/webhooks.py +137 -0
  118. django_cfg/config.py +1 -1
  119. django_cfg/core/config.py +40 -4
  120. django_cfg/core/generation.py +25 -4
  121. django_cfg/core/integration/README.md +363 -0
  122. django_cfg/core/integration/__init__.py +47 -0
  123. django_cfg/core/integration/commands_collector.py +239 -0
  124. django_cfg/core/integration/display/__init__.py +15 -0
  125. django_cfg/core/integration/display/base.py +157 -0
  126. django_cfg/core/integration/display/ngrok.py +164 -0
  127. django_cfg/core/integration/display/startup.py +815 -0
  128. django_cfg/core/integration/url_integration.py +123 -0
  129. django_cfg/core/integration/version_checker.py +160 -0
  130. django_cfg/management/commands/auto_generate.py +4 -0
  131. django_cfg/management/commands/check_settings.py +6 -0
  132. django_cfg/management/commands/clear_constance.py +5 -2
  133. django_cfg/management/commands/create_token.py +6 -0
  134. django_cfg/management/commands/list_urls.py +6 -0
  135. django_cfg/management/commands/migrate_all.py +6 -0
  136. django_cfg/management/commands/migrator.py +3 -0
  137. django_cfg/management/commands/rundramatiq.py +6 -0
  138. django_cfg/management/commands/runserver_ngrok.py +51 -29
  139. django_cfg/management/commands/script.py +6 -0
  140. django_cfg/management/commands/show_config.py +12 -2
  141. django_cfg/management/commands/show_urls.py +4 -0
  142. django_cfg/management/commands/superuser.py +6 -0
  143. django_cfg/management/commands/task_clear.py +4 -1
  144. django_cfg/management/commands/task_status.py +3 -1
  145. django_cfg/management/commands/test_email.py +3 -0
  146. django_cfg/management/commands/test_telegram.py +6 -0
  147. django_cfg/management/commands/test_twilio.py +6 -0
  148. django_cfg/management/commands/tree.py +6 -0
  149. django_cfg/management/commands/validate_config.py +155 -149
  150. django_cfg/models/constance.py +31 -11
  151. django_cfg/models/payments.py +175 -492
  152. django_cfg/modules/django_logger.py +160 -146
  153. django_cfg/modules/django_unfold/dashboard.py +64 -16
  154. django_cfg/registry/core.py +1 -0
  155. django_cfg/template_archive/django_sample.zip +0 -0
  156. django_cfg/utils/smart_defaults.py +227 -570
  157. django_cfg/utils/toolkit.py +51 -11
  158. {django_cfg-1.2.31.dist-info → django_cfg-1.3.3.dist-info}/METADATA +4 -1
  159. {django_cfg-1.2.31.dist-info → django_cfg-1.3.3.dist-info}/RECORD +162 -185
  160. django_cfg/apps/payments/__init__.py +0 -8
  161. django_cfg/apps/payments/admin/tariffs_admin.py +0 -199
  162. django_cfg/apps/payments/config/module.py +0 -70
  163. django_cfg/apps/payments/config/providers.py +0 -105
  164. django_cfg/apps/payments/config/settings.py +0 -96
  165. django_cfg/apps/payments/config/utils.py +0 -52
  166. django_cfg/apps/payments/decorators.py +0 -291
  167. django_cfg/apps/payments/management/commands/README.md +0 -146
  168. django_cfg/apps/payments/managers/__init__.py +0 -23
  169. django_cfg/apps/payments/managers/api_key_manager.py +0 -35
  170. django_cfg/apps/payments/managers/balance_manager.py +0 -361
  171. django_cfg/apps/payments/managers/currency_manager.py +0 -306
  172. django_cfg/apps/payments/managers/payment_manager.py +0 -192
  173. django_cfg/apps/payments/managers/subscription_manager.py +0 -37
  174. django_cfg/apps/payments/managers/tariff_manager.py +0 -29
  175. django_cfg/apps/payments/migrations/0002_network_providercurrency_and_more.py +0 -241
  176. django_cfg/apps/payments/migrations/0003_add_usd_rate_cache.py +0 -30
  177. django_cfg/apps/payments/models/events.py +0 -73
  178. django_cfg/apps/payments/serializers/__init__.py +0 -57
  179. django_cfg/apps/payments/serializers/api_keys.py +0 -51
  180. django_cfg/apps/payments/serializers/balance.py +0 -59
  181. django_cfg/apps/payments/serializers/currencies.py +0 -63
  182. django_cfg/apps/payments/serializers/payments.py +0 -62
  183. django_cfg/apps/payments/serializers/subscriptions.py +0 -71
  184. django_cfg/apps/payments/serializers/tariffs.py +0 -56
  185. django_cfg/apps/payments/services/billing/__init__.py +0 -8
  186. django_cfg/apps/payments/services/cache/simple_cache.py +0 -135
  187. django_cfg/apps/payments/services/core/fallback_service.py +0 -432
  188. django_cfg/apps/payments/services/internal_types.py +0 -461
  189. django_cfg/apps/payments/services/middleware/__init__.py +0 -8
  190. django_cfg/apps/payments/services/monitoring/__init__.py +0 -22
  191. django_cfg/apps/payments/services/monitoring/api_schemas.py +0 -76
  192. django_cfg/apps/payments/services/monitoring/provider_health.py +0 -372
  193. django_cfg/apps/payments/services/providers/cryptapi/__init__.py +0 -4
  194. django_cfg/apps/payments/services/providers/cryptapi/config.py +0 -8
  195. django_cfg/apps/payments/services/providers/cryptapi/models.py +0 -192
  196. django_cfg/apps/payments/services/providers/cryptapi/provider.py +0 -439
  197. django_cfg/apps/payments/services/providers/cryptomus/__init__.py +0 -4
  198. django_cfg/apps/payments/services/providers/cryptomus/models.py +0 -176
  199. django_cfg/apps/payments/services/providers/cryptomus/provider.py +0 -429
  200. django_cfg/apps/payments/services/providers/cryptomus/provider_v2.py +0 -564
  201. django_cfg/apps/payments/services/providers/models/__init__.py +0 -34
  202. django_cfg/apps/payments/services/providers/models/currencies.py +0 -190
  203. django_cfg/apps/payments/services/providers/nowpayments/__init__.py +0 -4
  204. django_cfg/apps/payments/services/providers/nowpayments/models.py +0 -196
  205. django_cfg/apps/payments/services/providers/nowpayments/provider.py +0 -380
  206. django_cfg/apps/payments/services/providers/stripe/__init__.py +0 -4
  207. django_cfg/apps/payments/services/providers/stripe/models.py +0 -184
  208. django_cfg/apps/payments/services/providers/stripe/provider.py +0 -109
  209. django_cfg/apps/payments/services/security/__init__.py +0 -34
  210. django_cfg/apps/payments/services/security/error_handler.py +0 -635
  211. django_cfg/apps/payments/services/security/payment_notifications.py +0 -342
  212. django_cfg/apps/payments/services/security/webhook_validator.py +0 -474
  213. django_cfg/apps/payments/static/payments/css/payments.css +0 -340
  214. django_cfg/apps/payments/static/payments/js/notifications.js +0 -202
  215. django_cfg/apps/payments/static/payments/js/payment-utils.js +0 -318
  216. django_cfg/apps/payments/static/payments/js/theme.js +0 -86
  217. django_cfg/apps/payments/tasks/__init__.py +0 -12
  218. django_cfg/apps/payments/tasks/webhook_processing.py +0 -177
  219. django_cfg/apps/payments/templates/admin/payments/currency/change_list.html +0 -50
  220. django_cfg/apps/payments/templates/payments/base.html +0 -182
  221. django_cfg/apps/payments/templates/payments/components/payment_card.html +0 -201
  222. django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +0 -109
  223. django_cfg/apps/payments/templates/payments/components/progress_bar.html +0 -43
  224. django_cfg/apps/payments/templates/payments/components/provider_stats.html +0 -40
  225. django_cfg/apps/payments/templates/payments/components/status_badge.html +0 -34
  226. django_cfg/apps/payments/templates/payments/components/status_overview.html +0 -148
  227. django_cfg/apps/payments/templates/payments/dashboard.html +0 -258
  228. django_cfg/apps/payments/templates/payments/dashboard_simple_test.html +0 -35
  229. django_cfg/apps/payments/templates/payments/payment_create.html +0 -579
  230. django_cfg/apps/payments/templates/payments/payment_detail.html +0 -373
  231. django_cfg/apps/payments/templates/payments/payment_list.html +0 -354
  232. django_cfg/apps/payments/templates/payments/stats.html +0 -261
  233. django_cfg/apps/payments/templates/payments/test.html +0 -213
  234. django_cfg/apps/payments/templatetags/payments_tags.py +0 -315
  235. django_cfg/apps/payments/utils/__init__.py +0 -43
  236. django_cfg/apps/payments/utils/billing_utils.py +0 -342
  237. django_cfg/apps/payments/utils/config_utils.py +0 -239
  238. django_cfg/apps/payments/utils/middleware_utils.py +0 -228
  239. django_cfg/apps/payments/utils/validation_utils.py +0 -94
  240. django_cfg/apps/payments/views/__init__.py +0 -63
  241. django_cfg/apps/payments/views/api_key_views.py +0 -164
  242. django_cfg/apps/payments/views/balance_views.py +0 -75
  243. django_cfg/apps/payments/views/currency_views.py +0 -122
  244. django_cfg/apps/payments/views/payment_views.py +0 -149
  245. django_cfg/apps/payments/views/subscription_views.py +0 -135
  246. django_cfg/apps/payments/views/tariff_views.py +0 -131
  247. django_cfg/apps/payments/views/templates/__init__.py +0 -25
  248. django_cfg/apps/payments/views/templates/ajax.py +0 -451
  249. django_cfg/apps/payments/views/templates/base.py +0 -212
  250. django_cfg/apps/payments/views/templates/dashboard.py +0 -60
  251. django_cfg/apps/payments/views/templates/payment_detail.py +0 -102
  252. django_cfg/apps/payments/views/templates/payment_management.py +0 -158
  253. django_cfg/apps/payments/views/templates/qr_code.py +0 -174
  254. django_cfg/apps/payments/views/templates/stats.py +0 -244
  255. django_cfg/apps/payments/views/templates/utils.py +0 -181
  256. django_cfg/apps/payments/views/webhook_views.py +0 -266
  257. django_cfg/apps/payments/viewsets.py +0 -66
  258. django_cfg/core/integration.py +0 -160
  259. django_cfg/template_archive/.gitignore +0 -1
  260. django_cfg/template_archive/__init__.py +0 -0
  261. django_cfg/urls.py +0 -33
  262. {django_cfg-1.2.31.dist-info → django_cfg-1.3.3.dist-info}/WHEEL +0 -0
  263. {django_cfg-1.2.31.dist-info → django_cfg-1.3.3.dist-info}/entry_points.txt +0 -0
  264. {django_cfg-1.2.31.dist-info → django_cfg-1.3.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,102 +1,209 @@
1
1
  """
2
- Tariff models for the universal payments system.
2
+ Tariff models for the Universal Payment System v2.0.
3
+
4
+ Handles pricing tiers and endpoint group associations.
3
5
  """
4
6
 
5
7
  from django.db import models
6
- from django.core.validators import MinValueValidator
8
+ from django.core.validators import MinValueValidator, MaxValueValidator
9
+ from django.core.exceptions import ValidationError
7
10
  from .base import TimestampedModel
11
+ from .subscriptions import EndpointGroup
8
12
 
9
13
 
10
14
  class Tariff(TimestampedModel):
11
- """Simple tariff plans for API access."""
15
+ """
16
+ Tariff model for subscription pricing tiers.
17
+
18
+ Defines pricing and limits for different subscription levels.
19
+ """
12
20
 
13
21
  name = models.CharField(
14
22
  max_length=100,
15
23
  unique=True,
16
- help_text="Tariff name"
24
+ help_text="Tariff name (e.g., 'Free', 'Basic', 'Pro')"
17
25
  )
18
- display_name = models.CharField(
19
- max_length=200,
20
- help_text="Human-readable tariff name"
26
+
27
+ code = models.CharField(
28
+ max_length=50,
29
+ unique=True,
30
+ help_text="Tariff code (e.g., 'free', 'basic', 'pro')"
21
31
  )
32
+
22
33
  description = models.TextField(
23
34
  blank=True,
24
- help_text="Tariff description"
35
+ help_text="Detailed description of what this tariff includes"
25
36
  )
26
37
 
27
38
  # Pricing
28
- monthly_price = models.FloatField(
29
- default=0.0,
39
+ monthly_price_usd = models.FloatField(
30
40
  validators=[MinValueValidator(0.0)],
31
41
  help_text="Monthly price in USD"
32
42
  )
33
43
 
34
- # Limits
35
- request_limit = models.PositiveIntegerField(
44
+ yearly_price_usd = models.FloatField(
45
+ null=True,
46
+ blank=True,
47
+ validators=[MinValueValidator(0.0)],
48
+ help_text="Yearly price in USD (optional discount)"
49
+ )
50
+
51
+ # Rate limits
52
+ requests_per_hour = models.PositiveIntegerField(
53
+ default=100,
54
+ validators=[MinValueValidator(1), MaxValueValidator(100000)],
55
+ help_text="API requests allowed per hour"
56
+ )
57
+
58
+ requests_per_day = models.PositiveIntegerField(
36
59
  default=1000,
37
- help_text="Monthly request limit (0 = unlimited)"
60
+ validators=[MinValueValidator(1), MaxValueValidator(1000000)],
61
+ help_text="API requests allowed per day"
62
+ )
63
+
64
+ requests_per_month = models.PositiveIntegerField(
65
+ default=30000,
66
+ validators=[MinValueValidator(1), MaxValueValidator(10000000)],
67
+ help_text="API requests allowed per month"
68
+ )
69
+
70
+ # Features
71
+ max_api_keys = models.PositiveIntegerField(
72
+ default=1,
73
+ validators=[MinValueValidator(1), MaxValueValidator(100)],
74
+ help_text="Maximum number of API keys allowed"
75
+ )
76
+
77
+ supports_webhooks = models.BooleanField(
78
+ default=True,
79
+ help_text="Whether webhooks are supported"
80
+ )
81
+
82
+ priority_support = models.BooleanField(
83
+ default=False,
84
+ help_text="Whether priority support is included"
38
85
  )
39
86
 
40
- # Settings
87
+ # Availability
41
88
  is_active = models.BooleanField(
42
89
  default=True,
43
- help_text="Is this tariff active"
90
+ help_text="Whether this tariff is available for new subscriptions"
44
91
  )
45
92
 
46
- # Import and assign manager
47
- from ..managers import TariffManager
48
- objects = TariffManager()
93
+ is_public = models.BooleanField(
94
+ default=True,
95
+ help_text="Whether this tariff is publicly visible"
96
+ )
97
+
98
+ # Ordering
99
+ sort_order = models.PositiveIntegerField(
100
+ default=0,
101
+ help_text="Sort order for display (lower numbers first)"
102
+ )
49
103
 
50
104
  class Meta:
51
- db_table = 'tariffs'
52
- verbose_name = "Tariff"
53
- verbose_name_plural = "Tariffs"
105
+ db_table = 'payments_tariffs'
106
+ verbose_name = 'Tariff'
107
+ verbose_name_plural = 'Tariffs'
108
+ ordering = ['sort_order', 'monthly_price_usd']
54
109
  indexes = [
55
- models.Index(fields=['is_active']),
56
- models.Index(fields=['monthly_price']),
110
+ models.Index(fields=['is_active', 'is_public']),
111
+ models.Index(fields=['sort_order']),
57
112
  ]
58
- ordering = ['monthly_price']
59
113
 
60
114
  def __str__(self):
61
- return f"{self.display_name} (${self.monthly_price}/month)"
115
+ return f"{self.name} - ${self.monthly_price_usd:.2f}/month"
116
+
117
+ def clean(self):
118
+ """Validate tariff data."""
119
+ if self.code:
120
+ self.code = self.code.lower().replace(' ', '_')
121
+
122
+ # Validate rate limits hierarchy
123
+ if self.requests_per_day < self.requests_per_hour:
124
+ raise ValidationError("Daily limit cannot be less than hourly limit")
125
+
126
+ if self.requests_per_month < self.requests_per_day:
127
+ raise ValidationError("Monthly limit cannot be less than daily limit")
128
+
129
+ # Validate yearly pricing
130
+ if self.yearly_price_usd and self.yearly_price_usd >= (self.monthly_price_usd * 12):
131
+ raise ValidationError("Yearly price should be less than 12x monthly price")
62
132
 
63
133
  @property
64
134
  def is_free(self) -> bool:
65
135
  """Check if this is a free tariff."""
66
- return self.monthly_price == 0
136
+ return self.monthly_price_usd == 0.0
137
+
138
+ @property
139
+ def yearly_discount_percentage(self) -> float:
140
+ """Calculate yearly discount percentage."""
141
+ if not self.yearly_price_usd or self.monthly_price_usd == 0:
142
+ return 0.0
143
+
144
+ yearly_equivalent = self.monthly_price_usd * 12
145
+ discount = yearly_equivalent - self.yearly_price_usd
146
+ return (discount / yearly_equivalent) * 100
147
+
148
+ @property
149
+ def price_display(self) -> str:
150
+ """Formatted price display."""
151
+ if self.is_free:
152
+ return "Free"
153
+ return f"${self.monthly_price_usd:.2f}/month"
154
+
155
+ @property
156
+ def yearly_price_display(self) -> str:
157
+ """Formatted yearly price display."""
158
+ if not self.yearly_price_usd:
159
+ return "N/A"
160
+ if self.yearly_price_usd == 0:
161
+ return "Free"
162
+ return f"${self.yearly_price_usd:.2f}/year"
67
163
 
68
164
 
69
165
  class TariffEndpointGroup(TimestampedModel):
70
- """Simple association between tariffs and endpoint groups."""
166
+ """
167
+ Association between tariffs and endpoint groups.
168
+
169
+ Defines which API endpoints are available for each tariff.
170
+ """
71
171
 
72
172
  tariff = models.ForeignKey(
73
173
  Tariff,
74
174
  on_delete=models.CASCADE,
75
- related_name='endpoint_groups',
76
- help_text="Tariff plan"
175
+ related_name='endpoint_groups'
77
176
  )
78
- from .subscriptions import EndpointGroup
177
+
79
178
  endpoint_group = models.ForeignKey(
80
179
  EndpointGroup,
81
180
  on_delete=models.CASCADE,
82
- related_name='tariffs',
83
- help_text="Endpoint group"
181
+ related_name='tariffs'
182
+ )
183
+
184
+ # Override default rate limits for this specific combination
185
+ custom_rate_limit = models.PositiveIntegerField(
186
+ null=True,
187
+ blank=True,
188
+ help_text="Custom rate limit for this endpoint group (overrides tariff default)"
84
189
  )
85
190
 
86
191
  is_enabled = models.BooleanField(
87
192
  default=True,
88
- help_text="Is this endpoint group enabled for this tariff"
193
+ help_text="Whether this endpoint group is enabled for this tariff"
89
194
  )
90
195
 
91
- # Import and assign manager
92
- from ..managers import TariffEndpointGroupManager
93
- objects = TariffEndpointGroupManager()
94
-
95
196
  class Meta:
96
- db_table = 'tariff_endpoint_groups'
97
- verbose_name = "Tariff Endpoint Group"
98
- verbose_name_plural = "Tariff Endpoint Groups"
197
+ db_table = 'payments_tariff_endpoint_groups'
198
+ verbose_name = 'Tariff Endpoint Group'
199
+ verbose_name_plural = 'Tariff Endpoint Groups'
99
200
  unique_together = [['tariff', 'endpoint_group']]
201
+ ordering = ['tariff__sort_order', 'endpoint_group__name']
100
202
 
101
203
  def __str__(self):
102
204
  return f"{self.tariff.name} - {self.endpoint_group.name}"
205
+
206
+ @property
207
+ def effective_rate_limit(self) -> int:
208
+ """Get effective rate limit (custom or tariff default)."""
209
+ return self.custom_rate_limit or self.tariff.requests_per_hour
@@ -1,71 +1,224 @@
1
1
  """
2
- Universal Payment Services.
2
+ Services package for the Universal Payment System v2.0.
3
3
 
4
- Modular architecture with minimal Pydantic typing for inter-service communication.
5
- Uses Django ORM for data persistence and DRF for API responses.
4
+ Business logic services with Pydantic validation and type safety.
6
5
  """
7
6
 
8
7
  # Core services
9
- from .core.payment_service import PaymentService
10
- from .core.balance_service import BalanceService
11
- from .core.subscription_service import SubscriptionService
12
-
13
- # Provider services
14
- from .providers.registry import ProviderRegistry
15
- from .providers.nowpayments import NowPaymentsProvider
16
- from .providers.cryptapi import CryptAPIProvider
17
-
18
- # Cache services
19
- from .cache import SimpleCache, ApiKeyCache, RateLimitCache
20
-
21
- # Internal types for inter-service communication
22
- from .internal_types import (
23
- ProviderResponse, WebhookData, ServiceOperationResult,
24
- BalanceUpdateRequest, AccessCheckRequest, AccessCheckResult,
25
- # Service response models
26
- PaymentCreationResult, WebhookProcessingResult, PaymentStatusResult,
27
- UserBalanceResult, TransferResult, TransactionInfo,
28
- EndpointGroupInfo, SubscriptionInfo, SubscriptionAnalytics,
29
- # Additional response models
30
- PaymentHistoryItem, ProviderInfo
8
+ from .core import (
9
+ BaseService,
10
+ PaymentService,
11
+ BalanceService,
12
+ SubscriptionService,
13
+ WebhookService,
14
+ CurrencyService,
15
+ )
16
+
17
+ # Service types
18
+ from .types import (
19
+ # Request types
20
+ PaymentCreateRequest,
21
+ PaymentStatusRequest,
22
+ BalanceUpdateRequest,
23
+ SubscriptionCreateRequest,
24
+ SubscriptionUpdateRequest,
25
+ CurrencyConversionRequest,
26
+
27
+ # Response types
28
+ PaymentResult,
29
+ BalanceResult,
30
+ SubscriptionResult,
31
+ CurrencyConversionResult,
32
+ ServiceOperationResult,
33
+
34
+ # Data types
35
+ PaymentData,
36
+ BalanceData,
37
+ SubscriptionData,
38
+ TransactionData,
39
+ CurrencyData,
40
+
41
+ # Webhook types
42
+ WebhookData,
43
+ NowPaymentsWebhook,
44
+ WebhookProcessingResult,
31
45
  )
32
46
 
33
47
  __all__ = [
34
48
  # Core services
49
+ 'BaseService',
35
50
  'PaymentService',
36
- 'BalanceService',
51
+ 'BalanceService',
37
52
  'SubscriptionService',
53
+ 'WebhookService',
54
+ 'CurrencyService',
38
55
 
39
- # Provider services
40
- 'ProviderRegistry',
41
- 'NowPaymentsProvider',
42
- 'CryptAPIProvider',
43
-
44
- # Cache services
45
- 'SimpleCache',
46
- 'ApiKeyCache',
47
- 'RateLimitCache',
56
+ # Request types
57
+ 'PaymentCreateRequest',
58
+ 'PaymentStatusRequest',
59
+ 'BalanceUpdateRequest',
60
+ 'SubscriptionCreateRequest',
61
+ 'SubscriptionUpdateRequest',
62
+ 'CurrencyConversionRequest',
48
63
 
49
- # Internal types
50
- 'ProviderResponse',
51
- 'WebhookData',
64
+ # Response types
65
+ 'PaymentResult',
66
+ 'BalanceResult',
67
+ 'SubscriptionResult',
68
+ 'CurrencyConversionResult',
52
69
  'ServiceOperationResult',
53
- 'BalanceUpdateRequest',
54
- 'AccessCheckRequest',
55
- 'AccessCheckResult',
56
-
57
- # Service response models
58
- 'PaymentCreationResult',
59
- 'WebhookProcessingResult',
60
- 'PaymentStatusResult',
61
- 'UserBalanceResult',
62
- 'TransferResult',
63
- 'TransactionInfo',
64
- 'EndpointGroupInfo',
65
- 'SubscriptionInfo',
66
- 'SubscriptionAnalytics',
67
-
68
- # Additional response models
69
- 'PaymentHistoryItem',
70
- 'ProviderInfo',
70
+
71
+ # Data types
72
+ 'PaymentData',
73
+ 'BalanceData',
74
+ 'SubscriptionData',
75
+ 'TransactionData',
76
+ 'CurrencyData',
77
+
78
+ # Webhook types
79
+ 'WebhookData',
80
+ 'NowPaymentsWebhook',
81
+ 'WebhookProcessingResult',
71
82
  ]
83
+
84
+
85
+ # Service registry for dependency injection and health checks
86
+ class ServiceRegistry:
87
+ """
88
+ Service registry for managing service instances.
89
+
90
+ Provides singleton access to services and health monitoring.
91
+ """
92
+
93
+ _instances = {}
94
+
95
+ @classmethod
96
+ def get_payment_service(cls) -> PaymentService:
97
+ """Get PaymentService instance."""
98
+ if 'payment' not in cls._instances:
99
+ cls._instances['payment'] = PaymentService()
100
+ return cls._instances['payment']
101
+
102
+ @classmethod
103
+ def get_balance_service(cls) -> BalanceService:
104
+ """Get BalanceService instance."""
105
+ if 'balance' not in cls._instances:
106
+ cls._instances['balance'] = BalanceService()
107
+ return cls._instances['balance']
108
+
109
+ @classmethod
110
+ def get_subscription_service(cls) -> SubscriptionService:
111
+ """Get SubscriptionService instance."""
112
+ if 'subscription' not in cls._instances:
113
+ cls._instances['subscription'] = SubscriptionService()
114
+ return cls._instances['subscription']
115
+
116
+ @classmethod
117
+ def get_webhook_service(cls) -> WebhookService:
118
+ """Get WebhookService instance."""
119
+ if 'webhook' not in cls._instances:
120
+ cls._instances['webhook'] = WebhookService()
121
+ return cls._instances['webhook']
122
+
123
+ @classmethod
124
+ def get_currency_service(cls) -> CurrencyService:
125
+ """Get CurrencyService instance."""
126
+ if 'currency' not in cls._instances:
127
+ cls._instances['currency'] = CurrencyService()
128
+ return cls._instances['currency']
129
+
130
+ @classmethod
131
+ def get_all_services(cls) -> dict:
132
+ """Get all service instances."""
133
+ return {
134
+ 'payment': cls.get_payment_service(),
135
+ 'balance': cls.get_balance_service(),
136
+ 'subscription': cls.get_subscription_service(),
137
+ 'webhook': cls.get_webhook_service(),
138
+ 'currency': cls.get_currency_service(),
139
+ }
140
+
141
+ @classmethod
142
+ def health_check_all(cls) -> dict:
143
+ """Perform health check on all services."""
144
+ services = cls.get_all_services()
145
+ results = {}
146
+
147
+ for name, service in services.items():
148
+ try:
149
+ health_result = service.health_check()
150
+ results[name] = {
151
+ 'healthy': health_result.success,
152
+ 'message': health_result.message,
153
+ 'data': health_result.data
154
+ }
155
+ except Exception as e:
156
+ results[name] = {
157
+ 'healthy': False,
158
+ 'message': f"Health check failed: {e}",
159
+ 'data': {}
160
+ }
161
+
162
+ return results
163
+
164
+ @classmethod
165
+ def clear_cache_all(cls):
166
+ """Clear cache for all services."""
167
+ for service in cls._instances.values():
168
+ if hasattr(service, '_cache_clear'):
169
+ service._cache_clear()
170
+
171
+ @classmethod
172
+ def get_stats_all(cls) -> dict:
173
+ """Get statistics from all services."""
174
+ services = cls.get_all_services()
175
+ stats = {}
176
+
177
+ for name, service in services.items():
178
+ try:
179
+ service_stats = service.get_service_stats()
180
+ stats[name] = service_stats
181
+ except Exception as e:
182
+ stats[name] = {
183
+ 'error': str(e),
184
+ 'service_name': service.__class__.__name__
185
+ }
186
+
187
+ return stats
188
+
189
+
190
+ # Convenience functions for direct service access
191
+ def get_payment_service() -> PaymentService:
192
+ """Get PaymentService instance."""
193
+ return ServiceRegistry.get_payment_service()
194
+
195
+
196
+ def get_balance_service() -> BalanceService:
197
+ """Get BalanceService instance."""
198
+ return ServiceRegistry.get_balance_service()
199
+
200
+
201
+ def get_subscription_service() -> SubscriptionService:
202
+ """Get SubscriptionService instance."""
203
+ return ServiceRegistry.get_subscription_service()
204
+
205
+
206
+ def get_webhook_service() -> WebhookService:
207
+ """Get WebhookService instance."""
208
+ return ServiceRegistry.get_webhook_service()
209
+
210
+
211
+ def get_currency_service() -> CurrencyService:
212
+ """Get CurrencyService instance."""
213
+ return ServiceRegistry.get_currency_service()
214
+
215
+
216
+ # Add convenience functions to __all__
217
+ __all__.extend([
218
+ 'ServiceRegistry',
219
+ 'get_payment_service',
220
+ 'get_balance_service',
221
+ 'get_subscription_service',
222
+ 'get_webhook_service',
223
+ 'get_currency_service',
224
+ ])
@@ -1,15 +1,15 @@
1
1
  """
2
- Simple caching for API key access control and rate limiting.
2
+ Cache services for the Universal Payment System v2.0.
3
3
 
4
- ONLY for API key caching - NOT for payment data!
4
+ Redis-backed caching with type safety and automatic key management.
5
5
  """
6
6
 
7
- from .base import CacheInterface
8
- from .simple_cache import SimpleCache, ApiKeyCache, RateLimitCache
7
+ from .cache_service import CacheService, get_cache_service, SimpleCache, ApiKeyCache, RateLimitCache
9
8
 
10
9
  __all__ = [
11
- 'CacheInterface',
12
- 'SimpleCache',
10
+ 'CacheService',
11
+ 'get_cache_service',
13
12
  'ApiKeyCache',
14
13
  'RateLimitCache',
14
+ 'SimpleCache',
15
15
  ]