django-cfg 1.2.29__py3-none-any.whl → 1.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/api/health/views.py +4 -2
- django_cfg/apps/knowbase/config/settings.py +16 -15
- django_cfg/apps/payments/README.md +326 -0
- django_cfg/apps/payments/admin/__init__.py +20 -9
- django_cfg/apps/payments/admin/api_keys_admin.py +521 -237
- django_cfg/apps/payments/admin/balance_admin.py +592 -297
- django_cfg/apps/payments/admin/currencies_admin.py +600 -108
- django_cfg/apps/payments/admin/filters.py +306 -199
- django_cfg/apps/payments/admin/payments_admin.py +470 -64
- django_cfg/apps/payments/admin/subscriptions_admin.py +578 -128
- django_cfg/apps/payments/admin_interface/__init__.py +18 -0
- django_cfg/apps/payments/admin_interface/templates/payments/base.html +162 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/dev_tool_card.html +38 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/loading_spinner.html +16 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/notification.html +27 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/provider_card.html +86 -0
- django_cfg/apps/payments/admin_interface/templates/payments/components/status_card.html +39 -0
- django_cfg/apps/payments/admin_interface/templates/payments/currency_converter.html +382 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_dashboard.html +300 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +303 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_list.html +382 -0
- django_cfg/apps/payments/admin_interface/templates/payments/payment_status.html +500 -0
- django_cfg/apps/payments/admin_interface/templates/payments/webhook_dashboard.html +594 -0
- django_cfg/apps/payments/admin_interface/views/__init__.py +23 -0
- django_cfg/apps/payments/admin_interface/views/payment_views.py +259 -0
- django_cfg/apps/payments/admin_interface/views/webhook_dashboard.py +37 -0
- django_cfg/apps/payments/apps.py +34 -9
- django_cfg/apps/payments/config/__init__.py +28 -51
- django_cfg/apps/payments/config/constance/__init__.py +22 -0
- django_cfg/apps/payments/config/constance/config_service.py +123 -0
- django_cfg/apps/payments/config/constance/fields.py +69 -0
- django_cfg/apps/payments/config/constance/settings.py +160 -0
- django_cfg/apps/payments/config/django_cfg_integration.py +202 -0
- django_cfg/apps/payments/config/helpers.py +130 -0
- django_cfg/apps/payments/management/__init__.py +1 -3
- django_cfg/apps/payments/management/commands/__init__.py +1 -3
- django_cfg/apps/payments/management/commands/manage_currencies.py +381 -0
- django_cfg/apps/payments/management/commands/manage_providers.py +408 -0
- django_cfg/apps/payments/middleware/__init__.py +3 -1
- django_cfg/apps/payments/middleware/api_access.py +329 -222
- django_cfg/apps/payments/middleware/rate_limiting.py +343 -163
- django_cfg/apps/payments/middleware/usage_tracking.py +250 -238
- django_cfg/apps/payments/migrations/0001_initial.py +708 -536
- django_cfg/apps/payments/models/__init__.py +16 -20
- django_cfg/apps/payments/models/api_keys.py +121 -43
- django_cfg/apps/payments/models/balance.py +150 -115
- django_cfg/apps/payments/models/base.py +68 -15
- django_cfg/apps/payments/models/currencies.py +207 -67
- django_cfg/apps/payments/models/managers/__init__.py +44 -0
- django_cfg/apps/payments/models/managers/api_key_managers.py +329 -0
- django_cfg/apps/payments/models/managers/balance_managers.py +599 -0
- django_cfg/apps/payments/models/managers/currency_managers.py +385 -0
- django_cfg/apps/payments/models/managers/payment_managers.py +511 -0
- django_cfg/apps/payments/models/managers/subscription_managers.py +641 -0
- django_cfg/apps/payments/models/payments.py +235 -284
- django_cfg/apps/payments/models/subscriptions.py +257 -177
- django_cfg/apps/payments/models/tariffs.py +147 -40
- django_cfg/apps/payments/services/__init__.py +209 -56
- django_cfg/apps/payments/services/cache/__init__.py +6 -6
- django_cfg/apps/payments/services/cache/{simple_cache.py → cache_service.py} +112 -12
- django_cfg/apps/payments/services/core/__init__.py +10 -6
- django_cfg/apps/payments/services/core/balance_service.py +435 -360
- django_cfg/apps/payments/services/core/base.py +166 -0
- django_cfg/apps/payments/services/core/currency_service.py +478 -0
- django_cfg/apps/payments/services/core/payment_service.py +344 -468
- django_cfg/apps/payments/services/core/subscription_service.py +425 -484
- django_cfg/apps/payments/services/core/webhook_service.py +410 -0
- django_cfg/apps/payments/services/integrations/__init__.py +29 -0
- django_cfg/apps/payments/services/integrations/ngrok_service.py +47 -0
- django_cfg/apps/payments/services/integrations/providers_config.py +107 -0
- django_cfg/apps/payments/services/providers/__init__.py +9 -14
- django_cfg/apps/payments/services/providers/base.py +232 -71
- django_cfg/apps/payments/services/providers/nowpayments.py +404 -219
- django_cfg/apps/payments/services/providers/registry.py +429 -80
- django_cfg/apps/payments/services/types/__init__.py +78 -0
- django_cfg/apps/payments/services/types/data.py +177 -0
- django_cfg/apps/payments/services/types/requests.py +150 -0
- django_cfg/apps/payments/services/types/responses.py +156 -0
- django_cfg/apps/payments/services/types/webhooks.py +232 -0
- django_cfg/apps/payments/signals/__init__.py +33 -8
- django_cfg/apps/payments/signals/api_key_signals.py +211 -130
- django_cfg/apps/payments/signals/balance_signals.py +174 -0
- django_cfg/apps/payments/signals/payment_signals.py +129 -98
- django_cfg/apps/payments/signals/subscription_signals.py +195 -143
- django_cfg/apps/payments/static/payments/css/components.css +380 -0
- django_cfg/apps/payments/static/payments/css/dashboard.css +188 -0
- django_cfg/apps/payments/static/payments/js/components.js +545 -0
- django_cfg/apps/payments/static/payments/js/utils.js +412 -0
- django_cfg/apps/payments/templatetags/__init__.py +1 -1
- django_cfg/apps/payments/templatetags/payment_tags.py +466 -0
- django_cfg/apps/payments/urls.py +46 -47
- django_cfg/apps/payments/urls_admin.py +49 -0
- django_cfg/apps/payments/views/api/__init__.py +101 -0
- django_cfg/apps/payments/views/api/api_keys.py +387 -0
- django_cfg/apps/payments/views/api/balances.py +381 -0
- django_cfg/apps/payments/views/api/base.py +298 -0
- django_cfg/apps/payments/views/api/currencies.py +402 -0
- django_cfg/apps/payments/views/api/payments.py +415 -0
- django_cfg/apps/payments/views/api/subscriptions.py +475 -0
- django_cfg/apps/payments/views/api/webhooks.py +476 -0
- django_cfg/apps/payments/views/serializers/__init__.py +99 -0
- django_cfg/apps/payments/views/serializers/api_keys.py +424 -0
- django_cfg/apps/payments/views/serializers/balances.py +300 -0
- django_cfg/apps/payments/views/serializers/currencies.py +335 -0
- django_cfg/apps/payments/views/serializers/payments.py +387 -0
- django_cfg/apps/payments/views/serializers/subscriptions.py +429 -0
- django_cfg/apps/payments/views/serializers/webhooks.py +137 -0
- django_cfg/apps/tasks/urls.py +0 -2
- django_cfg/apps/tasks/urls_admin.py +14 -0
- django_cfg/apps/urls.py +4 -4
- django_cfg/config.py +1 -1
- django_cfg/core/config.py +75 -4
- django_cfg/core/generation.py +25 -4
- django_cfg/core/integration/README.md +363 -0
- django_cfg/core/integration/__init__.py +47 -0
- django_cfg/core/integration/commands_collector.py +239 -0
- django_cfg/core/integration/display/__init__.py +15 -0
- django_cfg/core/integration/display/base.py +157 -0
- django_cfg/core/integration/display/ngrok.py +164 -0
- django_cfg/core/integration/display/startup.py +815 -0
- django_cfg/core/integration/url_integration.py +123 -0
- django_cfg/core/integration/version_checker.py +160 -0
- django_cfg/management/commands/auto_generate.py +4 -0
- django_cfg/management/commands/check_settings.py +6 -0
- django_cfg/management/commands/clear_constance.py +5 -2
- django_cfg/management/commands/create_token.py +6 -0
- django_cfg/management/commands/list_urls.py +6 -0
- django_cfg/management/commands/migrate_all.py +6 -0
- django_cfg/management/commands/migrator.py +3 -0
- django_cfg/management/commands/rundramatiq.py +6 -0
- django_cfg/management/commands/runserver_ngrok.py +51 -29
- django_cfg/management/commands/script.py +6 -0
- django_cfg/management/commands/show_config.py +12 -2
- django_cfg/management/commands/show_urls.py +4 -0
- django_cfg/management/commands/superuser.py +6 -0
- django_cfg/management/commands/task_clear.py +4 -1
- django_cfg/management/commands/task_status.py +3 -1
- django_cfg/management/commands/test_email.py +3 -0
- django_cfg/management/commands/test_telegram.py +6 -0
- django_cfg/management/commands/test_twilio.py +6 -0
- django_cfg/management/commands/tree.py +6 -0
- django_cfg/management/commands/validate_config.py +155 -149
- django_cfg/models/constance.py +31 -11
- django_cfg/models/payments.py +175 -498
- django_cfg/modules/django_currency/__init__.py +16 -11
- django_cfg/modules/django_currency/clients/__init__.py +4 -4
- django_cfg/modules/django_currency/clients/coinpaprika_client.py +289 -0
- django_cfg/modules/django_currency/clients/yahoo_client.py +157 -0
- django_cfg/modules/django_currency/core/__init__.py +1 -7
- django_cfg/modules/django_currency/core/converter.py +18 -23
- django_cfg/modules/django_currency/core/models.py +122 -11
- django_cfg/modules/django_currency/database/__init__.py +4 -4
- django_cfg/modules/django_currency/database/database_loader.py +190 -309
- django_cfg/modules/django_logger.py +160 -146
- django_cfg/modules/django_unfold/dashboard.py +65 -12
- django_cfg/registry/core.py +1 -0
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/templates/admin/components/action_grid.html +9 -9
- django_cfg/templates/admin/components/metric_card.html +5 -5
- django_cfg/templates/admin/components/status_badge.html +2 -2
- django_cfg/templates/admin/layouts/dashboard_with_tabs.html +152 -24
- django_cfg/templates/admin/snippets/components/quick_actions.html +3 -3
- django_cfg/templates/admin/snippets/components/system_health.html +1 -1
- django_cfg/templates/admin/snippets/tabs/overview_tab.html +49 -52
- django_cfg/utils/smart_defaults.py +222 -571
- django_cfg/utils/toolkit.py +51 -11
- {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/METADATA +5 -4
- {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/RECORD +172 -182
- django_cfg/apps/payments/__init__.py +0 -8
- django_cfg/apps/payments/admin/tariffs_admin.py +0 -199
- django_cfg/apps/payments/config/module.py +0 -70
- django_cfg/apps/payments/config/providers.py +0 -105
- django_cfg/apps/payments/config/settings.py +0 -96
- django_cfg/apps/payments/config/utils.py +0 -52
- django_cfg/apps/payments/decorators.py +0 -291
- django_cfg/apps/payments/management/commands/README.md +0 -178
- django_cfg/apps/payments/management/commands/currency_stats.py +0 -323
- django_cfg/apps/payments/management/commands/populate_currencies.py +0 -246
- django_cfg/apps/payments/management/commands/update_currencies.py +0 -336
- django_cfg/apps/payments/managers/__init__.py +0 -22
- django_cfg/apps/payments/managers/api_key_manager.py +0 -35
- django_cfg/apps/payments/managers/balance_manager.py +0 -361
- django_cfg/apps/payments/managers/currency_manager.py +0 -83
- django_cfg/apps/payments/managers/payment_manager.py +0 -44
- django_cfg/apps/payments/managers/subscription_manager.py +0 -37
- django_cfg/apps/payments/managers/tariff_manager.py +0 -29
- django_cfg/apps/payments/models/events.py +0 -73
- django_cfg/apps/payments/serializers/__init__.py +0 -56
- django_cfg/apps/payments/serializers/api_keys.py +0 -51
- django_cfg/apps/payments/serializers/balance.py +0 -59
- django_cfg/apps/payments/serializers/currencies.py +0 -55
- django_cfg/apps/payments/serializers/payments.py +0 -62
- django_cfg/apps/payments/serializers/subscriptions.py +0 -71
- django_cfg/apps/payments/serializers/tariffs.py +0 -56
- django_cfg/apps/payments/services/billing/__init__.py +0 -8
- django_cfg/apps/payments/services/cache/base.py +0 -30
- django_cfg/apps/payments/services/core/fallback_service.py +0 -432
- django_cfg/apps/payments/services/internal_types.py +0 -297
- django_cfg/apps/payments/services/middleware/__init__.py +0 -8
- django_cfg/apps/payments/services/monitoring/__init__.py +0 -22
- django_cfg/apps/payments/services/monitoring/api_schemas.py +0 -222
- django_cfg/apps/payments/services/monitoring/provider_health.py +0 -372
- django_cfg/apps/payments/services/providers/cryptapi.py +0 -273
- django_cfg/apps/payments/services/providers/cryptomus.py +0 -311
- django_cfg/apps/payments/services/security/__init__.py +0 -34
- django_cfg/apps/payments/services/security/error_handler.py +0 -637
- django_cfg/apps/payments/services/security/payment_notifications.py +0 -342
- django_cfg/apps/payments/services/security/webhook_validator.py +0 -475
- django_cfg/apps/payments/services/validators/__init__.py +0 -8
- django_cfg/apps/payments/static/payments/css/payments.css +0 -340
- django_cfg/apps/payments/static/payments/js/notifications.js +0 -202
- django_cfg/apps/payments/static/payments/js/payment-utils.js +0 -318
- django_cfg/apps/payments/static/payments/js/theme.js +0 -86
- django_cfg/apps/payments/tasks/__init__.py +0 -12
- django_cfg/apps/payments/tasks/webhook_processing.py +0 -177
- django_cfg/apps/payments/templates/payments/base.html +0 -182
- django_cfg/apps/payments/templates/payments/components/payment_card.html +0 -201
- django_cfg/apps/payments/templates/payments/components/payment_qr_code.html +0 -109
- django_cfg/apps/payments/templates/payments/components/progress_bar.html +0 -36
- django_cfg/apps/payments/templates/payments/components/provider_stats.html +0 -40
- django_cfg/apps/payments/templates/payments/components/status_badge.html +0 -27
- django_cfg/apps/payments/templates/payments/components/status_overview.html +0 -144
- django_cfg/apps/payments/templates/payments/dashboard.html +0 -346
- django_cfg/apps/payments/templatetags/payments_tags.py +0 -315
- django_cfg/apps/payments/urls_templates.py +0 -52
- django_cfg/apps/payments/utils/__init__.py +0 -45
- django_cfg/apps/payments/utils/billing_utils.py +0 -342
- django_cfg/apps/payments/utils/config_utils.py +0 -245
- django_cfg/apps/payments/utils/middleware_utils.py +0 -228
- django_cfg/apps/payments/utils/validation_utils.py +0 -94
- django_cfg/apps/payments/views/__init__.py +0 -62
- django_cfg/apps/payments/views/api_key_views.py +0 -164
- django_cfg/apps/payments/views/balance_views.py +0 -75
- django_cfg/apps/payments/views/currency_views.py +0 -111
- django_cfg/apps/payments/views/payment_views.py +0 -149
- django_cfg/apps/payments/views/subscription_views.py +0 -135
- django_cfg/apps/payments/views/tariff_views.py +0 -131
- django_cfg/apps/payments/views/templates/__init__.py +0 -25
- django_cfg/apps/payments/views/templates/ajax.py +0 -312
- django_cfg/apps/payments/views/templates/base.py +0 -204
- django_cfg/apps/payments/views/templates/dashboard.py +0 -60
- django_cfg/apps/payments/views/templates/payment_detail.py +0 -102
- django_cfg/apps/payments/views/templates/payment_management.py +0 -164
- django_cfg/apps/payments/views/templates/qr_code.py +0 -174
- django_cfg/apps/payments/views/templates/stats.py +0 -240
- django_cfg/apps/payments/views/templates/utils.py +0 -181
- django_cfg/apps/payments/views/webhook_views.py +0 -266
- django_cfg/apps/payments/viewsets.py +0 -65
- django_cfg/core/integration.py +0 -160
- django_cfg/modules/django_currency/clients/coingecko_client.py +0 -257
- django_cfg/modules/django_currency/clients/yfinance_client.py +0 -246
- django_cfg/template_archive/.gitignore +0 -1
- django_cfg/template_archive/__init__.py +0 -0
- django_cfg/urls.py +0 -33
- {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/WHEEL +0 -0
- {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.2.29.dist-info → django_cfg-1.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,30 +1,83 @@
|
|
1
1
|
"""
|
2
|
-
Base
|
2
|
+
Base models for the Universal Payment System v2.0.
|
3
|
+
|
4
|
+
Provides common functionality for all payment-related models.
|
3
5
|
"""
|
4
6
|
|
5
7
|
import uuid
|
6
8
|
from django.db import models
|
7
|
-
|
8
|
-
|
9
|
-
class TimestampedModel(models.Model):
|
10
|
-
"""Base model with automatic timestamps."""
|
11
|
-
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
|
12
|
-
updated_at = models.DateTimeField(auto_now=True)
|
13
|
-
|
14
|
-
class Meta:
|
15
|
-
abstract = True
|
9
|
+
from django.utils import timezone
|
16
10
|
|
17
11
|
|
18
12
|
class UUIDTimestampedModel(models.Model):
|
19
|
-
"""
|
13
|
+
"""
|
14
|
+
Abstract base model with UUID primary key and timestamps.
|
15
|
+
|
16
|
+
Provides:
|
17
|
+
- UUID primary key for security and scalability
|
18
|
+
- Created/updated timestamps with timezone awareness
|
19
|
+
- Common functionality for all payment models
|
20
|
+
"""
|
21
|
+
|
20
22
|
id = models.UUIDField(
|
21
23
|
primary_key=True,
|
22
24
|
default=uuid.uuid4,
|
23
25
|
editable=False,
|
24
|
-
help_text="Unique identifier"
|
26
|
+
help_text="Unique identifier for this record"
|
27
|
+
)
|
28
|
+
|
29
|
+
created_at = models.DateTimeField(
|
30
|
+
auto_now_add=True,
|
31
|
+
db_index=True,
|
32
|
+
help_text="When this record was created"
|
33
|
+
)
|
34
|
+
|
35
|
+
updated_at = models.DateTimeField(
|
36
|
+
auto_now=True,
|
37
|
+
help_text="When this record was last updated"
|
25
38
|
)
|
26
|
-
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
|
27
|
-
updated_at = models.DateTimeField(auto_now=True)
|
28
39
|
|
29
40
|
class Meta:
|
30
|
-
abstract = True
|
41
|
+
abstract = True
|
42
|
+
ordering = ['-created_at']
|
43
|
+
|
44
|
+
def __str__(self):
|
45
|
+
"""String representation showing ID and creation time."""
|
46
|
+
return f"{self.__class__.__name__}({str(self.id)[:8]}...)"
|
47
|
+
|
48
|
+
def __repr__(self):
|
49
|
+
"""Developer-friendly representation."""
|
50
|
+
return f"<{self.__class__.__name__}: {str(self.id)}>"
|
51
|
+
|
52
|
+
@property
|
53
|
+
def age_in_seconds(self) -> int:
|
54
|
+
"""Get age of this record in seconds."""
|
55
|
+
return int((timezone.now() - self.created_at).total_seconds())
|
56
|
+
|
57
|
+
@property
|
58
|
+
def is_recent(self) -> bool:
|
59
|
+
"""Check if record was created in the last hour."""
|
60
|
+
return self.age_in_seconds < 3600
|
61
|
+
|
62
|
+
|
63
|
+
class TimestampedModel(models.Model):
|
64
|
+
"""
|
65
|
+
Abstract base model with auto-incrementing ID and timestamps.
|
66
|
+
|
67
|
+
Use this for models that don't need UUID (like configuration models).
|
68
|
+
"""
|
69
|
+
|
70
|
+
created_at = models.DateTimeField(
|
71
|
+
auto_now_add=True,
|
72
|
+
db_index=True,
|
73
|
+
help_text="When this record was created"
|
74
|
+
)
|
75
|
+
|
76
|
+
updated_at = models.DateTimeField(
|
77
|
+
auto_now=True,
|
78
|
+
help_text="When this record was last updated"
|
79
|
+
)
|
80
|
+
|
81
|
+
class Meta:
|
82
|
+
abstract = True
|
83
|
+
ordering = ['-created_at']
|
@@ -1,13 +1,21 @@
|
|
1
1
|
"""
|
2
|
-
Currency models for the
|
2
|
+
Currency models for the Universal Payment System v2.0.
|
3
|
+
|
4
|
+
Handles multi-provider currency support with integration to django_currency module.
|
3
5
|
"""
|
4
6
|
|
5
7
|
from django.db import models
|
8
|
+
from django.core.validators import MinLengthValidator, MaxLengthValidator
|
9
|
+
from django.core.exceptions import ValidationError
|
6
10
|
from .base import TimestampedModel
|
7
11
|
|
8
12
|
|
9
13
|
class Currency(TimestampedModel):
|
10
|
-
"""
|
14
|
+
"""
|
15
|
+
Universal currency model supporting both fiat and crypto.
|
16
|
+
|
17
|
+
Integrates with django_currency module for rate conversion.
|
18
|
+
"""
|
11
19
|
|
12
20
|
class CurrencyType(models.TextChoices):
|
13
21
|
FIAT = "fiat", "Fiat Currency"
|
@@ -16,123 +24,255 @@ class Currency(TimestampedModel):
|
|
16
24
|
code = models.CharField(
|
17
25
|
max_length=10,
|
18
26
|
unique=True,
|
19
|
-
|
27
|
+
validators=[MinLengthValidator(3), MaxLengthValidator(10)],
|
28
|
+
help_text="Currency code (e.g., BTC, USD, ETH)"
|
20
29
|
)
|
30
|
+
|
21
31
|
name = models.CharField(
|
22
32
|
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., $, ₿, Ξ)"
|
33
|
+
help_text="Full currency name (e.g., Bitcoin, US Dollar)"
|
28
34
|
)
|
35
|
+
|
29
36
|
currency_type = models.CharField(
|
30
37
|
max_length=10,
|
31
38
|
choices=CurrencyType.choices,
|
32
39
|
help_text="Type of currency"
|
33
40
|
)
|
41
|
+
|
42
|
+
symbol = models.CharField(
|
43
|
+
max_length=10,
|
44
|
+
blank=True,
|
45
|
+
help_text="Currency symbol (e.g., $, ₿, Ξ)"
|
46
|
+
)
|
47
|
+
|
34
48
|
decimal_places = models.PositiveSmallIntegerField(
|
35
|
-
default=
|
49
|
+
default=8,
|
36
50
|
help_text="Number of decimal places for this currency"
|
37
51
|
)
|
52
|
+
|
38
53
|
is_active = models.BooleanField(
|
39
54
|
default=True,
|
40
|
-
help_text="Whether this currency is
|
41
|
-
)
|
42
|
-
min_payment_amount = models.FloatField(
|
43
|
-
default=1.0,
|
44
|
-
help_text="Minimum payment amount for this currency"
|
55
|
+
help_text="Whether this currency is available for payments"
|
45
56
|
)
|
46
57
|
|
47
|
-
#
|
48
|
-
|
49
|
-
|
50
|
-
help_text="Exchange rate to USD (1 unit of this currency = X USD)"
|
51
|
-
)
|
52
|
-
rate_updated_at = models.DateTimeField(
|
53
|
-
null=True,
|
58
|
+
# Integration with django_currency
|
59
|
+
exchange_rate_source = models.CharField(
|
60
|
+
max_length=50,
|
54
61
|
blank=True,
|
55
|
-
help_text="
|
62
|
+
help_text="Source for exchange rates (auto-detected by django_currency)"
|
56
63
|
)
|
57
64
|
|
58
|
-
#
|
59
|
-
from
|
65
|
+
# Manager
|
66
|
+
from .managers.currency_managers import CurrencyManager
|
60
67
|
objects = CurrencyManager()
|
61
68
|
|
62
69
|
class Meta:
|
63
|
-
db_table = '
|
64
|
-
verbose_name =
|
65
|
-
verbose_name_plural =
|
70
|
+
db_table = 'payments_currencies'
|
71
|
+
verbose_name = 'Currency'
|
72
|
+
verbose_name_plural = 'Currencies'
|
73
|
+
ordering = ['currency_type', 'code']
|
66
74
|
indexes = [
|
75
|
+
models.Index(fields=['currency_type', 'is_active']),
|
67
76
|
models.Index(fields=['code']),
|
68
|
-
models.Index(fields=['currency_type']),
|
69
|
-
models.Index(fields=['is_active']),
|
70
77
|
]
|
71
|
-
ordering = ['code']
|
72
78
|
|
73
79
|
def __str__(self):
|
74
|
-
return f"{self.code}
|
80
|
+
return f"{self.code} ({self.name})"
|
75
81
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
82
|
+
def clean(self):
|
83
|
+
"""Validate currency data."""
|
84
|
+
if self.code:
|
85
|
+
self.code = self.code.upper()
|
86
|
+
|
87
|
+
# Validate decimal places based on currency type
|
88
|
+
if self.currency_type == self.CurrencyType.FIAT and self.decimal_places > 4:
|
89
|
+
raise ValidationError("Fiat currencies should not have more than 4 decimal places")
|
90
|
+
|
91
|
+
if self.currency_type == self.CurrencyType.CRYPTO and self.decimal_places > 18:
|
92
|
+
raise ValidationError("Crypto currencies should not have more than 18 decimal places")
|
80
93
|
|
81
94
|
@property
|
82
95
|
def is_crypto(self) -> bool:
|
83
96
|
"""Check if this is a cryptocurrency."""
|
84
97
|
return self.currency_type == self.CurrencyType.CRYPTO
|
85
98
|
|
86
|
-
|
87
|
-
|
88
|
-
|
99
|
+
@property
|
100
|
+
def is_fiat(self) -> bool:
|
101
|
+
"""Check if this is a fiat currency."""
|
102
|
+
return self.currency_type == self.CurrencyType.FIAT
|
103
|
+
|
104
|
+
|
105
|
+
class Network(TimestampedModel):
|
106
|
+
"""
|
107
|
+
Blockchain network model for cryptocurrency payments.
|
108
|
+
|
109
|
+
Represents different networks like Ethereum, Bitcoin, Polygon, etc.
|
110
|
+
"""
|
111
|
+
|
112
|
+
name = models.CharField(
|
113
|
+
max_length=50,
|
114
|
+
unique=True,
|
115
|
+
help_text="Network name (e.g., Ethereum, Bitcoin, Polygon)"
|
116
|
+
)
|
117
|
+
|
118
|
+
code = models.CharField(
|
119
|
+
max_length=20,
|
120
|
+
unique=True,
|
121
|
+
help_text="Network code (e.g., ETH, BTC, MATIC)"
|
122
|
+
)
|
123
|
+
|
124
|
+
native_currency = models.ForeignKey(
|
125
|
+
Currency,
|
126
|
+
on_delete=models.PROTECT,
|
127
|
+
related_name='native_networks',
|
128
|
+
help_text="Native currency of this network"
|
129
|
+
)
|
130
|
+
|
131
|
+
block_explorer_url = models.URLField(
|
132
|
+
blank=True,
|
133
|
+
help_text="Block explorer URL template (use {tx} for transaction hash)"
|
134
|
+
)
|
89
135
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
136
|
+
is_active = models.BooleanField(
|
137
|
+
default=True,
|
138
|
+
help_text="Whether this network is available for payments"
|
139
|
+
)
|
140
|
+
|
141
|
+
# Network-specific settings
|
142
|
+
confirmation_blocks = models.PositiveIntegerField(
|
143
|
+
default=1,
|
144
|
+
help_text="Number of confirmations required for this network"
|
145
|
+
)
|
146
|
+
|
147
|
+
average_block_time = models.PositiveIntegerField(
|
148
|
+
default=600, # 10 minutes in seconds
|
149
|
+
help_text="Average block time in seconds"
|
150
|
+
)
|
151
|
+
|
152
|
+
class Meta:
|
153
|
+
db_table = 'payments_networks'
|
154
|
+
verbose_name = 'Network'
|
155
|
+
verbose_name_plural = 'Networks'
|
156
|
+
ordering = ['name']
|
157
|
+
indexes = [
|
158
|
+
models.Index(fields=['is_active']),
|
159
|
+
models.Index(fields=['code']),
|
160
|
+
]
|
161
|
+
|
162
|
+
def __str__(self):
|
163
|
+
return f"{self.name} ({self.code})"
|
164
|
+
|
165
|
+
def clean(self):
|
166
|
+
"""Validate network data."""
|
167
|
+
if self.code:
|
168
|
+
self.code = self.code.upper()
|
169
|
+
|
170
|
+
@property
|
171
|
+
def estimated_confirmation_time(self) -> int:
|
172
|
+
"""Estimated time for confirmations in seconds."""
|
173
|
+
return self.confirmation_blocks * self.average_block_time
|
95
174
|
|
96
175
|
|
97
|
-
class
|
98
|
-
"""
|
176
|
+
class ProviderCurrency(TimestampedModel):
|
177
|
+
"""
|
178
|
+
Provider-specific currency configuration.
|
179
|
+
|
180
|
+
Maps currencies to specific providers and networks.
|
181
|
+
"""
|
182
|
+
|
183
|
+
provider = models.CharField(
|
184
|
+
max_length=50,
|
185
|
+
help_text="Payment provider name (e.g., nowpayments)"
|
186
|
+
)
|
99
187
|
|
100
188
|
currency = models.ForeignKey(
|
101
189
|
Currency,
|
102
190
|
on_delete=models.CASCADE,
|
103
|
-
related_name='
|
104
|
-
help_text="Currency this network supports"
|
191
|
+
related_name='provider_configs'
|
105
192
|
)
|
106
|
-
|
107
|
-
|
108
|
-
|
193
|
+
|
194
|
+
network = models.ForeignKey(
|
195
|
+
Network,
|
196
|
+
on_delete=models.CASCADE,
|
197
|
+
related_name='provider_configs',
|
198
|
+
null=True,
|
199
|
+
blank=True,
|
200
|
+
help_text="Network for crypto currencies (null for fiat)"
|
109
201
|
)
|
110
|
-
|
202
|
+
|
203
|
+
# Provider-specific settings
|
204
|
+
provider_currency_code = models.CharField(
|
111
205
|
max_length=20,
|
112
|
-
help_text="
|
206
|
+
help_text="Currency code as used by the provider"
|
113
207
|
)
|
114
|
-
|
208
|
+
|
209
|
+
min_amount = models.DecimalField(
|
210
|
+
max_digits=20,
|
211
|
+
decimal_places=8,
|
212
|
+
null=True,
|
213
|
+
blank=True,
|
214
|
+
help_text="Minimum payment amount for this currency"
|
215
|
+
)
|
216
|
+
|
217
|
+
max_amount = models.DecimalField(
|
218
|
+
max_digits=20,
|
219
|
+
decimal_places=8,
|
220
|
+
null=True,
|
221
|
+
blank=True,
|
222
|
+
help_text="Maximum payment amount for this currency"
|
223
|
+
)
|
224
|
+
|
225
|
+
is_enabled = models.BooleanField(
|
115
226
|
default=True,
|
116
|
-
help_text="Whether this
|
227
|
+
help_text="Whether this currency is enabled for this provider"
|
117
228
|
)
|
118
|
-
|
119
|
-
|
120
|
-
|
229
|
+
|
230
|
+
# Fee configuration
|
231
|
+
fee_percentage = models.DecimalField(
|
232
|
+
max_digits=5,
|
233
|
+
decimal_places=4,
|
234
|
+
default=0,
|
235
|
+
help_text="Fee percentage (0.0250 = 2.5%)"
|
121
236
|
)
|
122
237
|
|
123
|
-
|
124
|
-
|
125
|
-
|
238
|
+
fixed_fee = models.DecimalField(
|
239
|
+
max_digits=20,
|
240
|
+
decimal_places=8,
|
241
|
+
default=0,
|
242
|
+
help_text="Fixed fee amount in this currency"
|
243
|
+
)
|
126
244
|
|
127
245
|
class Meta:
|
128
|
-
db_table = '
|
129
|
-
verbose_name =
|
130
|
-
verbose_name_plural =
|
131
|
-
unique_together = [['currency', '
|
246
|
+
db_table = 'payments_provider_currencies'
|
247
|
+
verbose_name = 'Provider Currency'
|
248
|
+
verbose_name_plural = 'Provider Currencies'
|
249
|
+
unique_together = [['provider', 'currency', 'network']]
|
250
|
+
ordering = ['provider', 'currency__code']
|
132
251
|
indexes = [
|
133
|
-
models.Index(fields=['
|
134
|
-
models.Index(fields=['
|
252
|
+
models.Index(fields=['provider', 'is_enabled']),
|
253
|
+
models.Index(fields=['currency', 'is_enabled']),
|
135
254
|
]
|
136
255
|
|
137
256
|
def __str__(self):
|
138
|
-
|
257
|
+
network_part = f" ({self.network.code})" if self.network else ""
|
258
|
+
return f"{self.provider}: {self.currency.code}{network_part}"
|
259
|
+
|
260
|
+
def clean(self):
|
261
|
+
"""Validate provider currency configuration."""
|
262
|
+
# Crypto currencies must have a network
|
263
|
+
if self.currency and self.currency.is_crypto and not self.network:
|
264
|
+
raise ValidationError("Crypto currencies must specify a network")
|
265
|
+
|
266
|
+
# Fiat currencies should not have a network
|
267
|
+
if self.currency and self.currency.is_fiat and self.network:
|
268
|
+
raise ValidationError("Fiat currencies should not specify a network")
|
269
|
+
|
270
|
+
# Validate amount limits
|
271
|
+
if self.min_amount and self.max_amount and self.min_amount > self.max_amount:
|
272
|
+
raise ValidationError("Minimum amount cannot be greater than maximum amount")
|
273
|
+
|
274
|
+
@property
|
275
|
+
def display_name(self) -> str:
|
276
|
+
"""Human-readable display name."""
|
277
|
+
network_part = f" on {self.network.name}" if self.network else ""
|
278
|
+
return f"{self.currency.name}{network_part}"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
"""
|
2
|
+
Django ORM Managers for the Universal Payment System v2.0.
|
3
|
+
|
4
|
+
Optimized managers and querysets for all payment-related models.
|
5
|
+
Follows the data typing requirements: Django ORM for database layer.
|
6
|
+
"""
|
7
|
+
|
8
|
+
# Payment managers
|
9
|
+
from .payment_managers import PaymentQuerySet, PaymentManager
|
10
|
+
|
11
|
+
# Balance managers
|
12
|
+
from .balance_managers import UserBalanceManager, TransactionQuerySet, TransactionManager
|
13
|
+
|
14
|
+
# Subscription managers
|
15
|
+
from .subscription_managers import SubscriptionQuerySet, SubscriptionManager
|
16
|
+
|
17
|
+
# Currency managers
|
18
|
+
from .currency_managers import CurrencyQuerySet, CurrencyManager
|
19
|
+
|
20
|
+
# API Key managers
|
21
|
+
from .api_key_managers import APIKeyQuerySet, APIKeyManager
|
22
|
+
|
23
|
+
__all__ = [
|
24
|
+
# Payment managers
|
25
|
+
'PaymentQuerySet',
|
26
|
+
'PaymentManager',
|
27
|
+
|
28
|
+
# Balance managers
|
29
|
+
'UserBalanceManager',
|
30
|
+
'TransactionQuerySet',
|
31
|
+
'TransactionManager',
|
32
|
+
|
33
|
+
# Subscription managers
|
34
|
+
'SubscriptionQuerySet',
|
35
|
+
'SubscriptionManager',
|
36
|
+
|
37
|
+
# Currency managers
|
38
|
+
'CurrencyQuerySet',
|
39
|
+
'CurrencyManager',
|
40
|
+
|
41
|
+
# API Key managers
|
42
|
+
'APIKeyQuerySet',
|
43
|
+
'APIKeyManager',
|
44
|
+
]
|