django-cfg 1.2.31__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 -10
- 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 +526 -222
- django_cfg/apps/payments/admin/filters.py +306 -199
- django_cfg/apps/payments/admin/payments_admin.py +465 -70
- 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 +303 -151
- django_cfg/apps/payments/management/commands/manage_providers.py +333 -160
- 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 +342 -152
- django_cfg/apps/payments/middleware/usage_tracking.py +249 -240
- django_cfg/apps/payments/migrations/0001_initial.py +708 -536
- django_cfg/apps/payments/models/__init__.py +13 -18
- 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 +172 -148
- 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 -285
- 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 +346 -467
- django_cfg/apps/payments/services/core/subscription_service.py +425 -481
- 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 +234 -174
- django_cfg/apps/payments/services/providers/nowpayments.py +478 -0
- django_cfg/apps/payments/services/providers/registry.py +367 -301
- 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 +210 -129
- django_cfg/apps/payments/signals/balance_signals.py +174 -0
- django_cfg/apps/payments/signals/payment_signals.py +128 -103
- django_cfg/apps/payments/signals/subscription_signals.py +194 -142
- 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 +45 -48
- django_cfg/apps/payments/urls_admin.py +33 -42
- 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/config.py +1 -1
- django_cfg/core/config.py +40 -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 -492
- django_cfg/modules/django_logger.py +160 -146
- django_cfg/modules/django_unfold/dashboard.py +64 -16
- django_cfg/registry/core.py +1 -0
- django_cfg/template_archive/django_sample.zip +0 -0
- django_cfg/utils/smart_defaults.py +222 -571
- django_cfg/utils/toolkit.py +51 -11
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/METADATA +4 -1
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/RECORD +153 -185
- 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 -146
- django_cfg/apps/payments/management/commands/currency_stats.py +0 -304
- django_cfg/apps/payments/managers/__init__.py +0 -23
- 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 -306
- django_cfg/apps/payments/managers/payment_manager.py +0 -192
- django_cfg/apps/payments/managers/subscription_manager.py +0 -37
- django_cfg/apps/payments/managers/tariff_manager.py +0 -29
- django_cfg/apps/payments/migrations/0002_network_providercurrency_and_more.py +0 -241
- django_cfg/apps/payments/migrations/0003_add_usd_rate_cache.py +0 -30
- django_cfg/apps/payments/models/events.py +0 -73
- django_cfg/apps/payments/serializers/__init__.py +0 -57
- 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 -63
- 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 -461
- 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 -76
- django_cfg/apps/payments/services/monitoring/provider_health.py +0 -372
- django_cfg/apps/payments/services/providers/cryptapi/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/cryptapi/config.py +0 -8
- django_cfg/apps/payments/services/providers/cryptapi/models.py +0 -192
- django_cfg/apps/payments/services/providers/cryptapi/provider.py +0 -439
- django_cfg/apps/payments/services/providers/cryptomus/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/cryptomus/models.py +0 -176
- django_cfg/apps/payments/services/providers/cryptomus/provider.py +0 -429
- django_cfg/apps/payments/services/providers/cryptomus/provider_v2.py +0 -564
- django_cfg/apps/payments/services/providers/models/__init__.py +0 -34
- django_cfg/apps/payments/services/providers/models/currencies.py +0 -190
- django_cfg/apps/payments/services/providers/nowpayments/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/nowpayments/models.py +0 -196
- django_cfg/apps/payments/services/providers/nowpayments/provider.py +0 -380
- django_cfg/apps/payments/services/providers/stripe/__init__.py +0 -4
- django_cfg/apps/payments/services/providers/stripe/models.py +0 -184
- django_cfg/apps/payments/services/providers/stripe/provider.py +0 -109
- django_cfg/apps/payments/services/security/__init__.py +0 -34
- django_cfg/apps/payments/services/security/error_handler.py +0 -635
- django_cfg/apps/payments/services/security/payment_notifications.py +0 -342
- django_cfg/apps/payments/services/security/webhook_validator.py +0 -474
- 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/admin/payments/currency/change_list.html +0 -50
- 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 -43
- django_cfg/apps/payments/templates/payments/components/provider_stats.html +0 -40
- django_cfg/apps/payments/templates/payments/components/status_badge.html +0 -34
- django_cfg/apps/payments/templates/payments/components/status_overview.html +0 -148
- django_cfg/apps/payments/templates/payments/dashboard.html +0 -258
- django_cfg/apps/payments/templates/payments/dashboard_simple_test.html +0 -35
- django_cfg/apps/payments/templates/payments/payment_create.html +0 -579
- django_cfg/apps/payments/templates/payments/payment_detail.html +0 -373
- django_cfg/apps/payments/templates/payments/payment_list.html +0 -354
- django_cfg/apps/payments/templates/payments/stats.html +0 -261
- django_cfg/apps/payments/templates/payments/test.html +0 -213
- django_cfg/apps/payments/templatetags/payments_tags.py +0 -315
- django_cfg/apps/payments/utils/__init__.py +0 -43
- django_cfg/apps/payments/utils/billing_utils.py +0 -342
- django_cfg/apps/payments/utils/config_utils.py +0 -239
- 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 -63
- 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 -122
- 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 -451
- django_cfg/apps/payments/views/templates/base.py +0 -212
- 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 -158
- django_cfg/apps/payments/views/templates/qr_code.py +0 -174
- django_cfg/apps/payments/views/templates/stats.py +0 -244
- 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 -66
- django_cfg/core/integration.py +0 -160
- 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.31.dist-info → django_cfg-1.3.1.dist-info}/WHEEL +0 -0
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.2.31.dist-info → django_cfg-1.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,7 +1,8 @@
|
|
1
|
-
# Generated by Django 5.2.6 on 2025-09-
|
1
|
+
# Generated by Django 5.2.6 on 2025-09-26 05:27
|
2
2
|
|
3
3
|
import django.core.validators
|
4
4
|
import django.db.models.deletion
|
5
|
+
import django.utils.timezone
|
5
6
|
import uuid
|
6
7
|
from django.conf import settings
|
7
8
|
from django.db import migrations, models
|
@@ -16,7 +17,7 @@ class Migration(migrations.Migration):
|
|
16
17
|
|
17
18
|
operations = [
|
18
19
|
migrations.CreateModel(
|
19
|
-
name="
|
20
|
+
name="EndpointGroup",
|
20
21
|
fields=[
|
21
22
|
(
|
22
23
|
"id",
|
@@ -24,18 +25,94 @@ class Migration(migrations.Migration):
|
|
24
25
|
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
25
26
|
),
|
26
27
|
),
|
27
|
-
(
|
28
|
+
(
|
29
|
+
"name",
|
30
|
+
models.CharField(
|
31
|
+
help_text="Endpoint group name (e.g., 'Payment API', 'Balance API')",
|
32
|
+
max_length=100,
|
33
|
+
unique=True,
|
34
|
+
),
|
35
|
+
),
|
36
|
+
(
|
37
|
+
"code",
|
38
|
+
models.CharField(
|
39
|
+
help_text="Endpoint group code (e.g., 'payments', 'balance')",
|
40
|
+
max_length=50,
|
41
|
+
unique=True,
|
42
|
+
),
|
43
|
+
),
|
44
|
+
(
|
45
|
+
"description",
|
46
|
+
models.TextField(
|
47
|
+
blank=True, help_text="Description of what this endpoint group provides"
|
48
|
+
),
|
49
|
+
),
|
50
|
+
(
|
51
|
+
"is_enabled",
|
52
|
+
models.BooleanField(
|
53
|
+
default=True, help_text="Whether this endpoint group is available"
|
54
|
+
),
|
55
|
+
),
|
56
|
+
(
|
57
|
+
"requires_subscription",
|
58
|
+
models.BooleanField(
|
59
|
+
default=True, help_text="Whether access requires an active subscription"
|
60
|
+
),
|
61
|
+
),
|
62
|
+
(
|
63
|
+
"default_rate_limit",
|
64
|
+
models.PositiveIntegerField(
|
65
|
+
default=1000, help_text="Default requests per hour for this endpoint group"
|
66
|
+
),
|
67
|
+
),
|
68
|
+
("created_at", models.DateTimeField(auto_now_add=True)),
|
28
69
|
("updated_at", models.DateTimeField(auto_now=True)),
|
70
|
+
],
|
71
|
+
options={
|
72
|
+
"verbose_name": "Endpoint Group",
|
73
|
+
"verbose_name_plural": "Endpoint Groups",
|
74
|
+
"db_table": "payments_endpoint_groups",
|
75
|
+
"ordering": ["name"],
|
76
|
+
},
|
77
|
+
),
|
78
|
+
migrations.CreateModel(
|
79
|
+
name="Currency",
|
80
|
+
fields=[
|
81
|
+
(
|
82
|
+
"id",
|
83
|
+
models.BigAutoField(
|
84
|
+
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
85
|
+
),
|
86
|
+
),
|
87
|
+
(
|
88
|
+
"created_at",
|
89
|
+
models.DateTimeField(
|
90
|
+
auto_now_add=True, db_index=True, help_text="When this record was created"
|
91
|
+
),
|
92
|
+
),
|
93
|
+
(
|
94
|
+
"updated_at",
|
95
|
+
models.DateTimeField(
|
96
|
+
auto_now=True, help_text="When this record was last updated"
|
97
|
+
),
|
98
|
+
),
|
29
99
|
(
|
30
100
|
"code",
|
31
101
|
models.CharField(
|
32
|
-
help_text="Currency code (e.g.,
|
102
|
+
help_text="Currency code (e.g., BTC, USD, ETH)",
|
103
|
+
max_length=10,
|
104
|
+
unique=True,
|
105
|
+
validators=[
|
106
|
+
django.core.validators.MinLengthValidator(3),
|
107
|
+
django.core.validators.MaxLengthValidator(10),
|
108
|
+
],
|
33
109
|
),
|
34
110
|
),
|
35
|
-
("name", models.CharField(help_text="Full currency name", max_length=100)),
|
36
111
|
(
|
37
|
-
"
|
38
|
-
models.CharField(
|
112
|
+
"name",
|
113
|
+
models.CharField(
|
114
|
+
help_text="Full currency name (e.g., Bitcoin, US Dollar)", max_length=100
|
115
|
+
),
|
39
116
|
),
|
40
117
|
(
|
41
118
|
"currency_type",
|
@@ -45,52 +122,48 @@ class Migration(migrations.Migration):
|
|
45
122
|
max_length=10,
|
46
123
|
),
|
47
124
|
),
|
125
|
+
(
|
126
|
+
"symbol",
|
127
|
+
models.CharField(
|
128
|
+
blank=True, help_text="Currency symbol (e.g., $, ₿, Ξ)", max_length=10
|
129
|
+
),
|
130
|
+
),
|
48
131
|
(
|
49
132
|
"decimal_places",
|
50
133
|
models.PositiveSmallIntegerField(
|
51
|
-
default=
|
134
|
+
default=8, help_text="Number of decimal places for this currency"
|
52
135
|
),
|
53
136
|
),
|
54
137
|
(
|
55
138
|
"is_active",
|
56
139
|
models.BooleanField(
|
57
|
-
default=True, help_text="Whether this currency is
|
58
|
-
),
|
59
|
-
),
|
60
|
-
(
|
61
|
-
"min_payment_amount",
|
62
|
-
models.FloatField(
|
63
|
-
default=1.0, help_text="Minimum payment amount for this currency"
|
64
|
-
),
|
65
|
-
),
|
66
|
-
(
|
67
|
-
"usd_rate",
|
68
|
-
models.FloatField(
|
69
|
-
default=1.0,
|
70
|
-
help_text="Exchange rate to USD (1 unit of this currency = X USD)",
|
140
|
+
default=True, help_text="Whether this currency is available for payments"
|
71
141
|
),
|
72
142
|
),
|
73
143
|
(
|
74
|
-
"
|
75
|
-
models.
|
76
|
-
blank=True,
|
144
|
+
"exchange_rate_source",
|
145
|
+
models.CharField(
|
146
|
+
blank=True,
|
147
|
+
help_text="Source for exchange rates (auto-detected by django_currency)",
|
148
|
+
max_length=50,
|
77
149
|
),
|
78
150
|
),
|
79
151
|
],
|
80
152
|
options={
|
81
153
|
"verbose_name": "Currency",
|
82
154
|
"verbose_name_plural": "Currencies",
|
83
|
-
"db_table": "
|
84
|
-
"ordering": ["code"],
|
155
|
+
"db_table": "payments_currencies",
|
156
|
+
"ordering": ["currency_type", "code"],
|
85
157
|
"indexes": [
|
86
|
-
models.Index(
|
87
|
-
|
88
|
-
|
158
|
+
models.Index(
|
159
|
+
fields=["currency_type", "is_active"], name="payments_cu_currenc_c67daf_idx"
|
160
|
+
),
|
161
|
+
models.Index(fields=["code"], name="payments_cu_code_2e1e62_idx"),
|
89
162
|
],
|
90
163
|
},
|
91
164
|
),
|
92
165
|
migrations.CreateModel(
|
93
|
-
name="
|
166
|
+
name="Network",
|
94
167
|
fields=[
|
95
168
|
(
|
96
169
|
"id",
|
@@ -98,158 +171,176 @@ class Migration(migrations.Migration):
|
|
98
171
|
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
99
172
|
),
|
100
173
|
),
|
101
|
-
("created_at", models.DateTimeField(auto_now_add=True, db_index=True)),
|
102
|
-
("updated_at", models.DateTimeField(auto_now=True)),
|
103
174
|
(
|
104
|
-
"
|
105
|
-
models.
|
175
|
+
"created_at",
|
176
|
+
models.DateTimeField(
|
177
|
+
auto_now_add=True, db_index=True, help_text="When this record was created"
|
178
|
+
),
|
106
179
|
),
|
107
|
-
("display_name", models.CharField(help_text="Human-readable name", max_length=200)),
|
108
|
-
("description", models.TextField(blank=True, help_text="Group description")),
|
109
180
|
(
|
110
|
-
"
|
111
|
-
models.
|
112
|
-
|
113
|
-
help_text="Basic tier monthly price",
|
114
|
-
validators=[django.core.validators.MinValueValidator(0.0)],
|
181
|
+
"updated_at",
|
182
|
+
models.DateTimeField(
|
183
|
+
auto_now=True, help_text="When this record was last updated"
|
115
184
|
),
|
116
185
|
),
|
117
186
|
(
|
118
|
-
"
|
119
|
-
models.
|
120
|
-
|
121
|
-
|
122
|
-
|
187
|
+
"name",
|
188
|
+
models.CharField(
|
189
|
+
help_text="Network name (e.g., Ethereum, Bitcoin, Polygon)",
|
190
|
+
max_length=50,
|
191
|
+
unique=True,
|
123
192
|
),
|
124
193
|
),
|
125
194
|
(
|
126
|
-
"
|
127
|
-
models.
|
128
|
-
|
129
|
-
help_text="Enterprise tier monthly price",
|
130
|
-
validators=[django.core.validators.MinValueValidator(0.0)],
|
195
|
+
"code",
|
196
|
+
models.CharField(
|
197
|
+
help_text="Network code (e.g., ETH, BTC, MATIC)", max_length=20, unique=True
|
131
198
|
),
|
132
199
|
),
|
133
200
|
(
|
134
|
-
"
|
135
|
-
models.
|
136
|
-
|
201
|
+
"block_explorer_url",
|
202
|
+
models.URLField(
|
203
|
+
blank=True,
|
204
|
+
help_text="Block explorer URL template (use {tx} for transaction hash)",
|
137
205
|
),
|
138
206
|
),
|
139
207
|
(
|
140
|
-
"
|
141
|
-
models.
|
142
|
-
default=
|
208
|
+
"is_active",
|
209
|
+
models.BooleanField(
|
210
|
+
default=True, help_text="Whether this network is available for payments"
|
143
211
|
),
|
144
212
|
),
|
145
213
|
(
|
146
|
-
"
|
214
|
+
"confirmation_blocks",
|
147
215
|
models.PositiveIntegerField(
|
148
|
-
default=
|
216
|
+
default=1, help_text="Number of confirmations required for this network"
|
149
217
|
),
|
150
218
|
),
|
151
219
|
(
|
152
|
-
"
|
153
|
-
models.
|
220
|
+
"average_block_time",
|
221
|
+
models.PositiveIntegerField(
|
222
|
+
default=600, help_text="Average block time in seconds"
|
223
|
+
),
|
154
224
|
),
|
155
225
|
(
|
156
|
-
"
|
157
|
-
models.
|
226
|
+
"native_currency",
|
227
|
+
models.ForeignKey(
|
228
|
+
help_text="Native currency of this network",
|
229
|
+
on_delete=django.db.models.deletion.PROTECT,
|
230
|
+
related_name="native_networks",
|
231
|
+
to="payments.currency",
|
232
|
+
),
|
158
233
|
),
|
159
234
|
],
|
160
235
|
options={
|
161
|
-
"verbose_name": "
|
162
|
-
"verbose_name_plural": "
|
163
|
-
"db_table": "
|
236
|
+
"verbose_name": "Network",
|
237
|
+
"verbose_name_plural": "Networks",
|
238
|
+
"db_table": "payments_networks",
|
164
239
|
"ordering": ["name"],
|
165
|
-
"indexes": [
|
166
|
-
models.Index(fields=["name"], name="endpoint_gr_name_970d2f_idx"),
|
167
|
-
models.Index(fields=["is_active"], name="endpoint_gr_is_acti_a9b5f6_idx"),
|
168
|
-
],
|
169
240
|
},
|
170
241
|
),
|
171
242
|
migrations.CreateModel(
|
172
|
-
name="
|
243
|
+
name="ProviderCurrency",
|
173
244
|
fields=[
|
174
245
|
(
|
175
246
|
"id",
|
176
|
-
models.
|
177
|
-
|
178
|
-
editable=False,
|
179
|
-
help_text="Unique identifier",
|
180
|
-
primary_key=True,
|
181
|
-
serialize=False,
|
247
|
+
models.BigAutoField(
|
248
|
+
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
182
249
|
),
|
183
250
|
),
|
184
|
-
("created_at", models.DateTimeField(auto_now_add=True, db_index=True)),
|
185
|
-
("updated_at", models.DateTimeField(auto_now=True)),
|
186
251
|
(
|
187
|
-
"
|
188
|
-
models.
|
252
|
+
"created_at",
|
253
|
+
models.DateTimeField(
|
254
|
+
auto_now_add=True, db_index=True, help_text="When this record was created"
|
255
|
+
),
|
189
256
|
),
|
190
257
|
(
|
191
|
-
"
|
192
|
-
models.
|
193
|
-
|
194
|
-
("payment_created", "Payment Created"),
|
195
|
-
("webhook_received", "Webhook Received"),
|
196
|
-
("webhook_processed", "Webhook Processed"),
|
197
|
-
("balance_updated", "Balance Updated"),
|
198
|
-
("refund_processed", "Refund Processed"),
|
199
|
-
("status_changed", "Status Changed"),
|
200
|
-
("error_occurred", "Error Occurred"),
|
201
|
-
],
|
202
|
-
db_index=True,
|
203
|
-
help_text="Type of event",
|
204
|
-
max_length=50,
|
258
|
+
"updated_at",
|
259
|
+
models.DateTimeField(
|
260
|
+
auto_now=True, help_text="When this record was last updated"
|
205
261
|
),
|
206
262
|
),
|
207
263
|
(
|
208
|
-
"
|
209
|
-
models.
|
264
|
+
"provider",
|
265
|
+
models.CharField(
|
266
|
+
help_text="Payment provider name (e.g., nowpayments)", max_length=50
|
267
|
+
),
|
210
268
|
),
|
211
|
-
("event_data", models.JSONField(help_text="Event data payload")),
|
212
269
|
(
|
213
|
-
"
|
270
|
+
"provider_currency_code",
|
214
271
|
models.CharField(
|
215
|
-
help_text="
|
272
|
+
help_text="Currency code as used by the provider", max_length=20
|
216
273
|
),
|
217
274
|
),
|
218
275
|
(
|
219
|
-
"
|
220
|
-
models.
|
276
|
+
"min_amount",
|
277
|
+
models.DecimalField(
|
221
278
|
blank=True,
|
222
|
-
|
223
|
-
|
279
|
+
decimal_places=8,
|
280
|
+
help_text="Minimum payment amount for this currency",
|
281
|
+
max_digits=20,
|
224
282
|
null=True,
|
225
283
|
),
|
226
284
|
),
|
227
285
|
(
|
228
|
-
"
|
229
|
-
models.
|
230
|
-
|
231
|
-
|
232
|
-
|
286
|
+
"max_amount",
|
287
|
+
models.DecimalField(
|
288
|
+
blank=True,
|
289
|
+
decimal_places=8,
|
290
|
+
help_text="Maximum payment amount for this currency",
|
291
|
+
max_digits=20,
|
292
|
+
null=True,
|
233
293
|
),
|
234
294
|
),
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
"db_table": "payment_events",
|
240
|
-
"ordering": ["sequence_number"],
|
241
|
-
"indexes": [
|
242
|
-
models.Index(
|
243
|
-
fields=["payment_id", "sequence_number"],
|
244
|
-
name="payment_eve_payment_aaf2d1_idx",
|
295
|
+
(
|
296
|
+
"is_enabled",
|
297
|
+
models.BooleanField(
|
298
|
+
default=True, help_text="Whether this currency is enabled for this provider"
|
245
299
|
),
|
246
|
-
|
247
|
-
|
300
|
+
),
|
301
|
+
(
|
302
|
+
"fee_percentage",
|
303
|
+
models.DecimalField(
|
304
|
+
decimal_places=4,
|
305
|
+
default=0,
|
306
|
+
help_text="Fee percentage (0.0250 = 2.5%)",
|
307
|
+
max_digits=5,
|
248
308
|
),
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
309
|
+
),
|
310
|
+
(
|
311
|
+
"fixed_fee",
|
312
|
+
models.DecimalField(
|
313
|
+
decimal_places=8,
|
314
|
+
default=0,
|
315
|
+
help_text="Fixed fee amount in this currency",
|
316
|
+
max_digits=20,
|
317
|
+
),
|
318
|
+
),
|
319
|
+
(
|
320
|
+
"currency",
|
321
|
+
models.ForeignKey(
|
322
|
+
on_delete=django.db.models.deletion.CASCADE,
|
323
|
+
related_name="provider_configs",
|
324
|
+
to="payments.currency",
|
325
|
+
),
|
326
|
+
),
|
327
|
+
(
|
328
|
+
"network",
|
329
|
+
models.ForeignKey(
|
330
|
+
blank=True,
|
331
|
+
help_text="Network for crypto currencies (null for fiat)",
|
332
|
+
null=True,
|
333
|
+
on_delete=django.db.models.deletion.CASCADE,
|
334
|
+
related_name="provider_configs",
|
335
|
+
to="payments.network",
|
336
|
+
),
|
337
|
+
),
|
338
|
+
],
|
339
|
+
options={
|
340
|
+
"verbose_name": "Provider Currency",
|
341
|
+
"verbose_name_plural": "Provider Currencies",
|
342
|
+
"db_table": "payments_provider_currencies",
|
343
|
+
"ordering": ["provider", "currency__code"],
|
253
344
|
},
|
254
345
|
),
|
255
346
|
migrations.CreateModel(
|
@@ -260,22 +351,33 @@ class Migration(migrations.Migration):
|
|
260
351
|
models.UUIDField(
|
261
352
|
default=uuid.uuid4,
|
262
353
|
editable=False,
|
263
|
-
help_text="Unique identifier",
|
354
|
+
help_text="Unique identifier for this record",
|
264
355
|
primary_key=True,
|
265
356
|
serialize=False,
|
266
357
|
),
|
267
358
|
),
|
268
|
-
(
|
269
|
-
|
359
|
+
(
|
360
|
+
"created_at",
|
361
|
+
models.DateTimeField(
|
362
|
+
auto_now_add=True, db_index=True, help_text="When this record was created"
|
363
|
+
),
|
364
|
+
),
|
365
|
+
(
|
366
|
+
"updated_at",
|
367
|
+
models.DateTimeField(
|
368
|
+
auto_now=True, help_text="When this record was last updated"
|
369
|
+
),
|
370
|
+
),
|
270
371
|
(
|
271
372
|
"tier",
|
272
373
|
models.CharField(
|
273
374
|
choices=[
|
274
|
-
("
|
275
|
-
("
|
276
|
-
("
|
375
|
+
("free", "Free Tier"),
|
376
|
+
("basic", "Basic Tier"),
|
377
|
+
("pro", "Pro Tier"),
|
378
|
+
("enterprise", "Enterprise Tier"),
|
277
379
|
],
|
278
|
-
default="
|
380
|
+
default="free",
|
279
381
|
help_text="Subscription tier",
|
280
382
|
max_length=20,
|
281
383
|
),
|
@@ -286,9 +388,9 @@ class Migration(migrations.Migration):
|
|
286
388
|
choices=[
|
287
389
|
("active", "Active"),
|
288
390
|
("inactive", "Inactive"),
|
289
|
-
("expired", "Expired"),
|
290
|
-
("cancelled", "Cancelled"),
|
291
391
|
("suspended", "Suspended"),
|
392
|
+
("cancelled", "Cancelled"),
|
393
|
+
("expired", "Expired"),
|
292
394
|
],
|
293
395
|
default="active",
|
294
396
|
help_text="Subscription status",
|
@@ -296,59 +398,75 @@ class Migration(migrations.Migration):
|
|
296
398
|
),
|
297
399
|
),
|
298
400
|
(
|
299
|
-
"
|
300
|
-
models.
|
301
|
-
|
302
|
-
|
401
|
+
"requests_per_hour",
|
402
|
+
models.PositiveIntegerField(
|
403
|
+
default=100,
|
404
|
+
help_text="API requests allowed per hour",
|
405
|
+
validators=[
|
406
|
+
django.core.validators.MinValueValidator(1),
|
407
|
+
django.core.validators.MaxValueValidator(100000),
|
408
|
+
],
|
303
409
|
),
|
304
410
|
),
|
305
411
|
(
|
306
|
-
"
|
412
|
+
"requests_per_day",
|
307
413
|
models.PositiveIntegerField(
|
308
|
-
default=1000,
|
414
|
+
default=1000,
|
415
|
+
help_text="API requests allowed per day",
|
416
|
+
validators=[
|
417
|
+
django.core.validators.MinValueValidator(1),
|
418
|
+
django.core.validators.MaxValueValidator(1000000),
|
419
|
+
],
|
309
420
|
),
|
310
421
|
),
|
311
422
|
(
|
312
|
-
"
|
313
|
-
models.
|
423
|
+
"starts_at",
|
424
|
+
models.DateTimeField(
|
425
|
+
default=django.utils.timezone.now, help_text="When this subscription starts"
|
426
|
+
),
|
314
427
|
),
|
428
|
+
("expires_at", models.DateTimeField(help_text="When this subscription expires")),
|
315
429
|
(
|
316
|
-
"
|
317
|
-
models.
|
430
|
+
"monthly_cost_usd",
|
431
|
+
models.FloatField(
|
432
|
+
default=0.0,
|
433
|
+
help_text="Monthly cost in USD",
|
434
|
+
validators=[django.core.validators.MinValueValidator(0.0)],
|
435
|
+
),
|
318
436
|
),
|
319
437
|
(
|
320
|
-
"
|
321
|
-
models.
|
438
|
+
"total_requests",
|
439
|
+
models.PositiveIntegerField(
|
440
|
+
default=0, help_text="Total API requests made with this subscription"
|
441
|
+
),
|
322
442
|
),
|
323
443
|
(
|
324
|
-
"
|
444
|
+
"last_request_at",
|
325
445
|
models.DateTimeField(
|
326
|
-
blank=True, help_text="
|
446
|
+
blank=True, help_text="When the last API request was made", null=True
|
327
447
|
),
|
328
448
|
),
|
329
449
|
(
|
330
|
-
"
|
331
|
-
models.
|
332
|
-
|
333
|
-
|
334
|
-
"metadata",
|
335
|
-
models.JSONField(default=dict, help_text="Additional subscription metadata"),
|
450
|
+
"auto_renew",
|
451
|
+
models.BooleanField(
|
452
|
+
default=False, help_text="Whether to automatically renew this subscription"
|
453
|
+
),
|
336
454
|
),
|
337
455
|
(
|
338
|
-
"
|
339
|
-
models.
|
340
|
-
|
341
|
-
|
456
|
+
"endpoint_groups",
|
457
|
+
models.ManyToManyField(
|
458
|
+
blank=True,
|
459
|
+
help_text="Endpoint groups accessible with this subscription",
|
342
460
|
related_name="subscriptions",
|
343
|
-
to="
|
461
|
+
to="payments.endpointgroup",
|
344
462
|
),
|
345
463
|
),
|
346
464
|
(
|
347
465
|
"user",
|
348
466
|
models.ForeignKey(
|
349
|
-
help_text="
|
467
|
+
help_text="User who owns this subscription",
|
350
468
|
on_delete=django.db.models.deletion.CASCADE,
|
351
|
-
related_name="
|
469
|
+
related_name="payment_subscriptions",
|
352
470
|
to=settings.AUTH_USER_MODEL,
|
353
471
|
),
|
354
472
|
),
|
@@ -356,7 +474,7 @@ class Migration(migrations.Migration):
|
|
356
474
|
options={
|
357
475
|
"verbose_name": "Subscription",
|
358
476
|
"verbose_name_plural": "Subscriptions",
|
359
|
-
"db_table": "
|
477
|
+
"db_table": "payments_subscriptions",
|
360
478
|
"ordering": ["-created_at"],
|
361
479
|
},
|
362
480
|
),
|
@@ -369,38 +487,140 @@ class Migration(migrations.Migration):
|
|
369
487
|
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
370
488
|
),
|
371
489
|
),
|
372
|
-
("created_at", models.DateTimeField(auto_now_add=True, db_index=True)),
|
373
|
-
("updated_at", models.DateTimeField(auto_now=True)),
|
374
|
-
("name", models.CharField(help_text="Tariff name", max_length=100, unique=True)),
|
375
490
|
(
|
376
|
-
"
|
377
|
-
models.
|
491
|
+
"created_at",
|
492
|
+
models.DateTimeField(
|
493
|
+
auto_now_add=True, db_index=True, help_text="When this record was created"
|
494
|
+
),
|
495
|
+
),
|
496
|
+
(
|
497
|
+
"updated_at",
|
498
|
+
models.DateTimeField(
|
499
|
+
auto_now=True, help_text="When this record was last updated"
|
500
|
+
),
|
501
|
+
),
|
502
|
+
(
|
503
|
+
"name",
|
504
|
+
models.CharField(
|
505
|
+
help_text="Tariff name (e.g., 'Free', 'Basic', 'Pro')",
|
506
|
+
max_length=100,
|
507
|
+
unique=True,
|
508
|
+
),
|
509
|
+
),
|
510
|
+
(
|
511
|
+
"code",
|
512
|
+
models.CharField(
|
513
|
+
help_text="Tariff code (e.g., 'free', 'basic', 'pro')",
|
514
|
+
max_length=50,
|
515
|
+
unique=True,
|
516
|
+
),
|
517
|
+
),
|
518
|
+
(
|
519
|
+
"description",
|
520
|
+
models.TextField(
|
521
|
+
blank=True, help_text="Detailed description of what this tariff includes"
|
522
|
+
),
|
378
523
|
),
|
379
|
-
("description", models.TextField(blank=True, help_text="Tariff description")),
|
380
524
|
(
|
381
|
-
"
|
525
|
+
"monthly_price_usd",
|
382
526
|
models.FloatField(
|
383
|
-
default=0.0,
|
384
527
|
help_text="Monthly price in USD",
|
385
528
|
validators=[django.core.validators.MinValueValidator(0.0)],
|
386
529
|
),
|
387
530
|
),
|
388
531
|
(
|
389
|
-
"
|
532
|
+
"yearly_price_usd",
|
533
|
+
models.FloatField(
|
534
|
+
blank=True,
|
535
|
+
help_text="Yearly price in USD (optional discount)",
|
536
|
+
null=True,
|
537
|
+
validators=[django.core.validators.MinValueValidator(0.0)],
|
538
|
+
),
|
539
|
+
),
|
540
|
+
(
|
541
|
+
"requests_per_hour",
|
390
542
|
models.PositiveIntegerField(
|
391
|
-
default=
|
543
|
+
default=100,
|
544
|
+
help_text="API requests allowed per hour",
|
545
|
+
validators=[
|
546
|
+
django.core.validators.MinValueValidator(1),
|
547
|
+
django.core.validators.MaxValueValidator(100000),
|
548
|
+
],
|
549
|
+
),
|
550
|
+
),
|
551
|
+
(
|
552
|
+
"requests_per_day",
|
553
|
+
models.PositiveIntegerField(
|
554
|
+
default=1000,
|
555
|
+
help_text="API requests allowed per day",
|
556
|
+
validators=[
|
557
|
+
django.core.validators.MinValueValidator(1),
|
558
|
+
django.core.validators.MaxValueValidator(1000000),
|
559
|
+
],
|
560
|
+
),
|
561
|
+
),
|
562
|
+
(
|
563
|
+
"requests_per_month",
|
564
|
+
models.PositiveIntegerField(
|
565
|
+
default=30000,
|
566
|
+
help_text="API requests allowed per month",
|
567
|
+
validators=[
|
568
|
+
django.core.validators.MinValueValidator(1),
|
569
|
+
django.core.validators.MaxValueValidator(10000000),
|
570
|
+
],
|
571
|
+
),
|
572
|
+
),
|
573
|
+
(
|
574
|
+
"max_api_keys",
|
575
|
+
models.PositiveIntegerField(
|
576
|
+
default=1,
|
577
|
+
help_text="Maximum number of API keys allowed",
|
578
|
+
validators=[
|
579
|
+
django.core.validators.MinValueValidator(1),
|
580
|
+
django.core.validators.MaxValueValidator(100),
|
581
|
+
],
|
582
|
+
),
|
583
|
+
),
|
584
|
+
(
|
585
|
+
"supports_webhooks",
|
586
|
+
models.BooleanField(default=True, help_text="Whether webhooks are supported"),
|
587
|
+
),
|
588
|
+
(
|
589
|
+
"priority_support",
|
590
|
+
models.BooleanField(
|
591
|
+
default=False, help_text="Whether priority support is included"
|
592
|
+
),
|
593
|
+
),
|
594
|
+
(
|
595
|
+
"is_active",
|
596
|
+
models.BooleanField(
|
597
|
+
default=True,
|
598
|
+
help_text="Whether this tariff is available for new subscriptions",
|
599
|
+
),
|
600
|
+
),
|
601
|
+
(
|
602
|
+
"is_public",
|
603
|
+
models.BooleanField(
|
604
|
+
default=True, help_text="Whether this tariff is publicly visible"
|
605
|
+
),
|
606
|
+
),
|
607
|
+
(
|
608
|
+
"sort_order",
|
609
|
+
models.PositiveIntegerField(
|
610
|
+
default=0, help_text="Sort order for display (lower numbers first)"
|
392
611
|
),
|
393
612
|
),
|
394
|
-
("is_active", models.BooleanField(default=True, help_text="Is this tariff active")),
|
395
613
|
],
|
396
614
|
options={
|
397
615
|
"verbose_name": "Tariff",
|
398
616
|
"verbose_name_plural": "Tariffs",
|
399
|
-
"db_table": "
|
400
|
-
"ordering": ["
|
617
|
+
"db_table": "payments_tariffs",
|
618
|
+
"ordering": ["sort_order", "monthly_price_usd"],
|
401
619
|
"indexes": [
|
402
|
-
models.Index(
|
403
|
-
|
620
|
+
models.Index(
|
621
|
+
fields=["is_active", "is_public"], name="payments_ta_is_acti_716f1f_idx"
|
622
|
+
),
|
623
|
+
models.Index(fields=["sort_order"], name="payments_ta_sort_or_e6ec28_idx"),
|
404
624
|
],
|
405
625
|
},
|
406
626
|
),
|
@@ -413,233 +633,267 @@ class Migration(migrations.Migration):
|
|
413
633
|
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
414
634
|
),
|
415
635
|
),
|
416
|
-
(
|
417
|
-
|
636
|
+
(
|
637
|
+
"created_at",
|
638
|
+
models.DateTimeField(
|
639
|
+
auto_now_add=True, db_index=True, help_text="When this record was created"
|
640
|
+
),
|
641
|
+
),
|
642
|
+
(
|
643
|
+
"updated_at",
|
644
|
+
models.DateTimeField(
|
645
|
+
auto_now=True, help_text="When this record was last updated"
|
646
|
+
),
|
647
|
+
),
|
648
|
+
(
|
649
|
+
"custom_rate_limit",
|
650
|
+
models.PositiveIntegerField(
|
651
|
+
blank=True,
|
652
|
+
help_text="Custom rate limit for this endpoint group (overrides tariff default)",
|
653
|
+
null=True,
|
654
|
+
),
|
655
|
+
),
|
418
656
|
(
|
419
657
|
"is_enabled",
|
420
658
|
models.BooleanField(
|
421
|
-
default=True,
|
659
|
+
default=True,
|
660
|
+
help_text="Whether this endpoint group is enabled for this tariff",
|
422
661
|
),
|
423
662
|
),
|
424
663
|
(
|
425
664
|
"endpoint_group",
|
426
665
|
models.ForeignKey(
|
427
|
-
help_text="Endpoint group",
|
428
666
|
on_delete=django.db.models.deletion.CASCADE,
|
429
667
|
related_name="tariffs",
|
430
|
-
to="
|
668
|
+
to="payments.endpointgroup",
|
431
669
|
),
|
432
670
|
),
|
433
671
|
(
|
434
672
|
"tariff",
|
435
673
|
models.ForeignKey(
|
436
|
-
help_text="Tariff plan",
|
437
674
|
on_delete=django.db.models.deletion.CASCADE,
|
438
675
|
related_name="endpoint_groups",
|
439
|
-
to="
|
676
|
+
to="payments.tariff",
|
440
677
|
),
|
441
678
|
),
|
442
679
|
],
|
443
680
|
options={
|
444
681
|
"verbose_name": "Tariff Endpoint Group",
|
445
682
|
"verbose_name_plural": "Tariff Endpoint Groups",
|
446
|
-
"db_table": "
|
683
|
+
"db_table": "payments_tariff_endpoint_groups",
|
684
|
+
"ordering": ["tariff__sort_order", "endpoint_group__name"],
|
447
685
|
},
|
448
686
|
),
|
449
687
|
migrations.CreateModel(
|
450
|
-
name="
|
688
|
+
name="Transaction",
|
451
689
|
fields=[
|
452
690
|
(
|
453
691
|
"id",
|
454
692
|
models.UUIDField(
|
455
693
|
default=uuid.uuid4,
|
456
694
|
editable=False,
|
457
|
-
help_text="Unique identifier",
|
695
|
+
help_text="Unique identifier for this record",
|
458
696
|
primary_key=True,
|
459
697
|
serialize=False,
|
460
698
|
),
|
461
699
|
),
|
462
|
-
("created_at", models.DateTimeField(auto_now_add=True, db_index=True)),
|
463
|
-
("updated_at", models.DateTimeField(auto_now=True)),
|
464
700
|
(
|
465
|
-
"
|
466
|
-
models.
|
467
|
-
help_text="
|
468
|
-
validators=[django.core.validators.MinValueValidator(1.0)],
|
701
|
+
"created_at",
|
702
|
+
models.DateTimeField(
|
703
|
+
auto_now_add=True, db_index=True, help_text="When this record was created"
|
469
704
|
),
|
470
705
|
),
|
471
706
|
(
|
472
|
-
"
|
473
|
-
models.
|
474
|
-
|
475
|
-
(
|
476
|
-
"actual_amount_usd",
|
477
|
-
models.FloatField(
|
478
|
-
blank=True, help_text="Actual received amount in USD", null=True
|
707
|
+
"updated_at",
|
708
|
+
models.DateTimeField(
|
709
|
+
auto_now=True, help_text="When this record was last updated"
|
479
710
|
),
|
480
711
|
),
|
481
712
|
(
|
482
|
-
"
|
713
|
+
"transaction_type",
|
483
714
|
models.CharField(
|
484
|
-
|
715
|
+
choices=[
|
716
|
+
("deposit", "Deposit"),
|
717
|
+
("withdrawal", "Withdrawal"),
|
718
|
+
("payment", "Payment"),
|
719
|
+
("refund", "Refund"),
|
720
|
+
("fee", "Fee"),
|
721
|
+
("bonus", "Bonus"),
|
722
|
+
("adjustment", "Adjustment"),
|
723
|
+
],
|
724
|
+
help_text="Type of transaction",
|
725
|
+
max_length=20,
|
485
726
|
),
|
486
727
|
),
|
487
728
|
(
|
488
|
-
"
|
729
|
+
"amount_usd",
|
489
730
|
models.FloatField(
|
490
|
-
|
491
|
-
help_text="Fee amount in USD",
|
492
|
-
null=True,
|
493
|
-
validators=[django.core.validators.MinValueValidator(0.0)],
|
731
|
+
help_text="Transaction amount in USD (positive=credit, negative=debit)"
|
494
732
|
),
|
495
733
|
),
|
496
734
|
(
|
497
|
-
"
|
498
|
-
models.
|
499
|
-
|
500
|
-
|
501
|
-
("cryptapi", "CryptAPI"),
|
502
|
-
("cryptomus", "Cryptomus"),
|
503
|
-
("stripe", "Stripe"),
|
504
|
-
("internal", "Internal"),
|
505
|
-
],
|
506
|
-
help_text="Payment provider",
|
507
|
-
max_length=50,
|
735
|
+
"balance_after",
|
736
|
+
models.FloatField(
|
737
|
+
help_text="User balance after this transaction",
|
738
|
+
validators=[django.core.validators.MinValueValidator(0.0)],
|
508
739
|
),
|
509
740
|
),
|
510
741
|
(
|
511
|
-
"
|
742
|
+
"payment_id",
|
512
743
|
models.CharField(
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
("failed", "Failed"),
|
519
|
-
("expired", "Expired"),
|
520
|
-
("cancelled", "Cancelled"),
|
521
|
-
("refunded", "Refunded"),
|
522
|
-
],
|
523
|
-
default="pending",
|
524
|
-
help_text="Payment status",
|
525
|
-
max_length=20,
|
744
|
+
blank=True,
|
745
|
+
db_index=True,
|
746
|
+
help_text="Related payment ID (if applicable)",
|
747
|
+
max_length=100,
|
748
|
+
null=True,
|
526
749
|
),
|
527
750
|
),
|
751
|
+
("description", models.TextField(help_text="Transaction description")),
|
528
752
|
(
|
529
|
-
"
|
530
|
-
models.
|
531
|
-
blank=True,
|
532
|
-
help_text="Provider's payment ID",
|
533
|
-
max_length=255,
|
534
|
-
null=True,
|
535
|
-
unique=True,
|
753
|
+
"metadata",
|
754
|
+
models.JSONField(
|
755
|
+
blank=True, default=dict, help_text="Additional transaction metadata"
|
536
756
|
),
|
537
757
|
),
|
538
758
|
(
|
539
|
-
"
|
540
|
-
models.
|
541
|
-
help_text="
|
759
|
+
"user",
|
760
|
+
models.ForeignKey(
|
761
|
+
help_text="User who owns this transaction",
|
762
|
+
on_delete=django.db.models.deletion.CASCADE,
|
763
|
+
related_name="payment_transactions",
|
764
|
+
to=settings.AUTH_USER_MODEL,
|
542
765
|
),
|
543
766
|
),
|
767
|
+
],
|
768
|
+
options={
|
769
|
+
"verbose_name": "Transaction",
|
770
|
+
"verbose_name_plural": "Transactions",
|
771
|
+
"db_table": "payments_transactions",
|
772
|
+
"ordering": ["-created_at"],
|
773
|
+
},
|
774
|
+
),
|
775
|
+
migrations.CreateModel(
|
776
|
+
name="UniversalPayment",
|
777
|
+
fields=[
|
544
778
|
(
|
545
|
-
"
|
546
|
-
models.
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
779
|
+
"id",
|
780
|
+
models.UUIDField(
|
781
|
+
default=uuid.uuid4,
|
782
|
+
editable=False,
|
783
|
+
help_text="Unique identifier for this record",
|
784
|
+
primary_key=True,
|
785
|
+
serialize=False,
|
551
786
|
),
|
552
787
|
),
|
553
788
|
(
|
554
|
-
"
|
555
|
-
models.
|
556
|
-
|
789
|
+
"created_at",
|
790
|
+
models.DateTimeField(
|
791
|
+
auto_now_add=True, db_index=True, help_text="When this record was created"
|
557
792
|
),
|
558
793
|
),
|
559
794
|
(
|
560
|
-
"
|
561
|
-
models.
|
562
|
-
|
563
|
-
help_text="Blockchain network (mainnet, testnet, etc.)",
|
564
|
-
max_length=50,
|
565
|
-
null=True,
|
795
|
+
"updated_at",
|
796
|
+
models.DateTimeField(
|
797
|
+
auto_now=True, help_text="When this record was last updated"
|
566
798
|
),
|
567
799
|
),
|
568
|
-
("description", models.TextField(blank=True, help_text="Payment description")),
|
569
800
|
(
|
570
|
-
"
|
801
|
+
"internal_payment_id",
|
571
802
|
models.CharField(
|
572
|
-
|
803
|
+
db_index=True,
|
804
|
+
help_text="Internal payment identifier",
|
805
|
+
max_length=100,
|
806
|
+
unique=True,
|
573
807
|
),
|
574
808
|
),
|
575
|
-
("metadata", models.JSONField(default=dict, help_text="Additional metadata")),
|
576
809
|
(
|
577
|
-
"
|
578
|
-
models.
|
579
|
-
|
810
|
+
"amount_usd",
|
811
|
+
models.FloatField(
|
812
|
+
help_text="Payment amount in USD (float for performance)",
|
813
|
+
validators=[
|
814
|
+
django.core.validators.MinValueValidator(1.0),
|
815
|
+
django.core.validators.MaxValueValidator(50000.0),
|
816
|
+
],
|
580
817
|
),
|
581
818
|
),
|
582
819
|
(
|
583
|
-
"
|
584
|
-
models.
|
820
|
+
"pay_amount",
|
821
|
+
models.DecimalField(
|
585
822
|
blank=True,
|
586
|
-
|
587
|
-
help_text="
|
588
|
-
|
823
|
+
decimal_places=8,
|
824
|
+
help_text="Amount to pay in cryptocurrency (Decimal for precision)",
|
825
|
+
max_digits=20,
|
589
826
|
null=True,
|
590
827
|
),
|
591
828
|
),
|
592
829
|
(
|
593
|
-
"
|
594
|
-
models.
|
595
|
-
blank=True,
|
596
|
-
help_text="Full callback URL with security parameters",
|
597
|
-
max_length=512,
|
598
|
-
null=True,
|
830
|
+
"actual_amount_usd",
|
831
|
+
models.FloatField(
|
832
|
+
blank=True, help_text="Actual amount received in USD", null=True
|
599
833
|
),
|
600
834
|
),
|
601
835
|
(
|
602
|
-
"
|
836
|
+
"fee_amount_usd",
|
837
|
+
models.FloatField(blank=True, help_text="Fee amount in USD", null=True),
|
838
|
+
),
|
839
|
+
(
|
840
|
+
"provider",
|
603
841
|
models.CharField(
|
604
|
-
|
605
|
-
|
606
|
-
help_text="
|
607
|
-
max_length=
|
608
|
-
null=True,
|
842
|
+
choices=[("nowpayments", "NowPayments")],
|
843
|
+
default="nowpayments",
|
844
|
+
help_text="Payment provider",
|
845
|
+
max_length=50,
|
609
846
|
),
|
610
847
|
),
|
611
848
|
(
|
612
|
-
"
|
849
|
+
"provider_payment_id",
|
613
850
|
models.CharField(
|
614
851
|
blank=True,
|
615
|
-
|
616
|
-
|
852
|
+
db_index=True,
|
853
|
+
help_text="Provider's payment ID",
|
854
|
+
max_length=255,
|
617
855
|
null=True,
|
618
856
|
),
|
619
857
|
),
|
620
858
|
(
|
621
|
-
"
|
859
|
+
"status",
|
622
860
|
models.CharField(
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
861
|
+
choices=[
|
862
|
+
("pending", "Pending"),
|
863
|
+
("confirming", "Confirming"),
|
864
|
+
("confirmed", "Confirmed"),
|
865
|
+
("completed", "Completed"),
|
866
|
+
("failed", "Failed"),
|
867
|
+
("expired", "Expired"),
|
868
|
+
("cancelled", "Cancelled"),
|
869
|
+
("refunded", "Refunded"),
|
870
|
+
],
|
871
|
+
db_index=True,
|
872
|
+
default="pending",
|
873
|
+
help_text="Current payment status",
|
874
|
+
max_length=20,
|
627
875
|
),
|
628
876
|
),
|
629
877
|
(
|
630
|
-
"
|
878
|
+
"pay_address",
|
631
879
|
models.CharField(
|
632
880
|
blank=True,
|
633
|
-
help_text="
|
634
|
-
max_length=
|
881
|
+
help_text="Cryptocurrency payment address",
|
882
|
+
max_length=255,
|
635
883
|
null=True,
|
636
884
|
),
|
637
885
|
),
|
638
886
|
(
|
639
|
-
"
|
640
|
-
models.
|
887
|
+
"payment_url",
|
888
|
+
models.URLField(blank=True, help_text="Payment page URL", null=True),
|
889
|
+
),
|
890
|
+
(
|
891
|
+
"transaction_hash",
|
892
|
+
models.CharField(
|
641
893
|
blank=True,
|
642
|
-
|
894
|
+
db_index=True,
|
895
|
+
help_text="Blockchain transaction hash",
|
896
|
+
max_length=256,
|
643
897
|
null=True,
|
644
898
|
),
|
645
899
|
),
|
@@ -650,139 +904,84 @@ class Migration(migrations.Migration):
|
|
650
904
|
),
|
651
905
|
),
|
652
906
|
(
|
653
|
-
"
|
654
|
-
models.
|
655
|
-
blank=True,
|
907
|
+
"security_nonce",
|
908
|
+
models.CharField(
|
909
|
+
blank=True,
|
910
|
+
db_index=True,
|
911
|
+
help_text="Security nonce for validation",
|
912
|
+
max_length=64,
|
913
|
+
null=True,
|
656
914
|
),
|
657
915
|
),
|
658
916
|
(
|
659
|
-
"
|
917
|
+
"expires_at",
|
660
918
|
models.DateTimeField(
|
661
|
-
blank=True, help_text="
|
919
|
+
blank=True, help_text="When this payment expires", null=True
|
662
920
|
),
|
663
921
|
),
|
664
922
|
(
|
665
|
-
"
|
923
|
+
"completed_at",
|
666
924
|
models.DateTimeField(
|
667
|
-
blank=True,
|
668
|
-
help_text="When the payment was processed and funds added to balance",
|
669
|
-
null=True,
|
925
|
+
blank=True, help_text="When this payment was completed", null=True
|
670
926
|
),
|
671
927
|
),
|
928
|
+
("description", models.TextField(blank=True, help_text="Payment description")),
|
672
929
|
(
|
673
|
-
"
|
674
|
-
models.
|
675
|
-
help_text="User who initiated this payment",
|
676
|
-
on_delete=django.db.models.deletion.CASCADE,
|
677
|
-
related_name="universal_payments",
|
678
|
-
to=settings.AUTH_USER_MODEL,
|
679
|
-
),
|
930
|
+
"callback_url",
|
931
|
+
models.URLField(blank=True, help_text="Success callback URL", null=True),
|
680
932
|
),
|
681
|
-
],
|
682
|
-
options={
|
683
|
-
"verbose_name": "Universal Payment",
|
684
|
-
"verbose_name_plural": "Universal Payments",
|
685
|
-
"db_table": "universal_payments",
|
686
|
-
"ordering": ["-created_at"],
|
687
|
-
},
|
688
|
-
),
|
689
|
-
migrations.CreateModel(
|
690
|
-
name="Transaction",
|
691
|
-
fields=[
|
692
933
|
(
|
693
|
-
"
|
694
|
-
models.
|
695
|
-
default=uuid.uuid4,
|
696
|
-
editable=False,
|
697
|
-
help_text="Unique identifier",
|
698
|
-
primary_key=True,
|
699
|
-
serialize=False,
|
700
|
-
),
|
934
|
+
"cancel_url",
|
935
|
+
models.URLField(blank=True, help_text="Cancellation URL", null=True),
|
701
936
|
),
|
702
|
-
("created_at", models.DateTimeField(auto_now_add=True, db_index=True)),
|
703
|
-
("updated_at", models.DateTimeField(auto_now=True)),
|
704
937
|
(
|
705
|
-
"
|
706
|
-
models.
|
707
|
-
|
938
|
+
"provider_data",
|
939
|
+
models.JSONField(
|
940
|
+
blank=True,
|
941
|
+
default=dict,
|
942
|
+
help_text="Provider-specific data (validated by Pydantic)",
|
708
943
|
),
|
709
944
|
),
|
710
945
|
(
|
711
|
-
"
|
712
|
-
models.
|
713
|
-
|
714
|
-
("payment", "Payment"),
|
715
|
-
("subscription", "Subscription"),
|
716
|
-
("refund", "Refund"),
|
717
|
-
("credit", "Credit"),
|
718
|
-
("debit", "Debit"),
|
719
|
-
("hold", "Hold"),
|
720
|
-
("release", "Release"),
|
721
|
-
("fee", "Fee"),
|
722
|
-
("adjustment", "Adjustment"),
|
723
|
-
],
|
724
|
-
help_text="Type of transaction",
|
725
|
-
max_length=20,
|
946
|
+
"webhook_data",
|
947
|
+
models.JSONField(
|
948
|
+
blank=True, default=dict, help_text="Webhook data (validated by Pydantic)"
|
726
949
|
),
|
727
950
|
),
|
728
951
|
(
|
729
|
-
"
|
730
|
-
models.
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
),
|
736
|
-
(
|
737
|
-
"balance_after",
|
738
|
-
models.FloatField(help_text="User balance after this transaction"),
|
739
|
-
),
|
740
|
-
(
|
741
|
-
"reference_id",
|
742
|
-
models.CharField(
|
743
|
-
blank=True, help_text="External reference ID", max_length=255, null=True
|
952
|
+
"currency",
|
953
|
+
models.ForeignKey(
|
954
|
+
help_text="Payment currency",
|
955
|
+
on_delete=django.db.models.deletion.PROTECT,
|
956
|
+
related_name="payments",
|
957
|
+
to="payments.currency",
|
744
958
|
),
|
745
959
|
),
|
746
960
|
(
|
747
|
-
"
|
748
|
-
models.JSONField(default=dict, help_text="Additional transaction metadata"),
|
749
|
-
),
|
750
|
-
(
|
751
|
-
"subscription",
|
961
|
+
"network",
|
752
962
|
models.ForeignKey(
|
753
963
|
blank=True,
|
754
|
-
help_text="
|
964
|
+
help_text="Blockchain network (for crypto payments)",
|
755
965
|
null=True,
|
756
|
-
on_delete=django.db.models.deletion.
|
757
|
-
related_name="
|
758
|
-
to="
|
966
|
+
on_delete=django.db.models.deletion.PROTECT,
|
967
|
+
related_name="payments",
|
968
|
+
to="payments.network",
|
759
969
|
),
|
760
970
|
),
|
761
971
|
(
|
762
972
|
"user",
|
763
973
|
models.ForeignKey(
|
764
|
-
help_text="User who
|
974
|
+
help_text="User who created this payment",
|
765
975
|
on_delete=django.db.models.deletion.CASCADE,
|
766
|
-
related_name="
|
976
|
+
related_name="payments",
|
767
977
|
to=settings.AUTH_USER_MODEL,
|
768
978
|
),
|
769
979
|
),
|
770
|
-
(
|
771
|
-
"payment",
|
772
|
-
models.ForeignKey(
|
773
|
-
blank=True,
|
774
|
-
help_text="Related payment (if applicable)",
|
775
|
-
null=True,
|
776
|
-
on_delete=django.db.models.deletion.SET_NULL,
|
777
|
-
related_name="transactions",
|
778
|
-
to="django_cfg_payments.universalpayment",
|
779
|
-
),
|
780
|
-
),
|
781
980
|
],
|
782
981
|
options={
|
783
|
-
"verbose_name": "
|
784
|
-
"verbose_name_plural": "
|
785
|
-
"db_table": "
|
982
|
+
"verbose_name": "Universal Payment",
|
983
|
+
"verbose_name_plural": "Universal Payments",
|
984
|
+
"db_table": "payments_universal",
|
786
985
|
"ordering": ["-created_at"],
|
787
986
|
},
|
788
987
|
),
|
@@ -795,29 +994,19 @@ class Migration(migrations.Migration):
|
|
795
994
|
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
796
995
|
),
|
797
996
|
),
|
798
|
-
("created_at", models.DateTimeField(auto_now_add=True, db_index=True)),
|
799
|
-
("updated_at", models.DateTimeField(auto_now=True)),
|
800
|
-
(
|
801
|
-
"amount_usd",
|
802
|
-
models.FloatField(
|
803
|
-
default=0.0,
|
804
|
-
help_text="Current balance in USD",
|
805
|
-
validators=[django.core.validators.MinValueValidator(0.0)],
|
806
|
-
),
|
807
|
-
),
|
808
997
|
(
|
809
|
-
"
|
998
|
+
"balance_usd",
|
810
999
|
models.FloatField(
|
811
1000
|
default=0.0,
|
812
|
-
help_text="
|
1001
|
+
help_text="Current balance in USD (float for performance)",
|
813
1002
|
validators=[django.core.validators.MinValueValidator(0.0)],
|
814
1003
|
),
|
815
1004
|
),
|
816
1005
|
(
|
817
|
-
"
|
1006
|
+
"total_deposited",
|
818
1007
|
models.FloatField(
|
819
1008
|
default=0.0,
|
820
|
-
help_text="Total amount
|
1009
|
+
help_text="Total amount deposited (lifetime)",
|
821
1010
|
validators=[django.core.validators.MinValueValidator(0.0)],
|
822
1011
|
),
|
823
1012
|
),
|
@@ -835,12 +1024,14 @@ class Migration(migrations.Migration):
|
|
835
1024
|
blank=True, help_text="When the last transaction occurred", null=True
|
836
1025
|
),
|
837
1026
|
),
|
1027
|
+
("created_at", models.DateTimeField(auto_now_add=True)),
|
1028
|
+
("updated_at", models.DateTimeField(auto_now=True)),
|
838
1029
|
(
|
839
1030
|
"user",
|
840
1031
|
models.OneToOneField(
|
841
1032
|
help_text="User who owns this balance",
|
842
1033
|
on_delete=django.db.models.deletion.CASCADE,
|
843
|
-
related_name="
|
1034
|
+
related_name="payment_balance",
|
844
1035
|
to=settings.AUTH_USER_MODEL,
|
845
1036
|
),
|
846
1037
|
),
|
@@ -848,7 +1039,7 @@ class Migration(migrations.Migration):
|
|
848
1039
|
options={
|
849
1040
|
"verbose_name": "User Balance",
|
850
1041
|
"verbose_name_plural": "User Balances",
|
851
|
-
"db_table": "
|
1042
|
+
"db_table": "payments_user_balances",
|
852
1043
|
},
|
853
1044
|
),
|
854
1045
|
migrations.CreateModel(
|
@@ -859,238 +1050,219 @@ class Migration(migrations.Migration):
|
|
859
1050
|
models.UUIDField(
|
860
1051
|
default=uuid.uuid4,
|
861
1052
|
editable=False,
|
862
|
-
help_text="Unique identifier",
|
1053
|
+
help_text="Unique identifier for this record",
|
863
1054
|
primary_key=True,
|
864
1055
|
serialize=False,
|
865
1056
|
),
|
866
1057
|
),
|
867
|
-
("created_at", models.DateTimeField(auto_now_add=True, db_index=True)),
|
868
|
-
("updated_at", models.DateTimeField(auto_now=True)),
|
869
|
-
("name", models.CharField(help_text="Human-readable key name", max_length=100)),
|
870
1058
|
(
|
871
|
-
"
|
872
|
-
models.
|
873
|
-
help_text="
|
1059
|
+
"created_at",
|
1060
|
+
models.DateTimeField(
|
1061
|
+
auto_now_add=True, db_index=True, help_text="When this record was created"
|
874
1062
|
),
|
875
1063
|
),
|
876
1064
|
(
|
877
|
-
"
|
878
|
-
models.
|
1065
|
+
"updated_at",
|
1066
|
+
models.DateTimeField(
|
1067
|
+
auto_now=True, help_text="When this record was last updated"
|
1068
|
+
),
|
879
1069
|
),
|
880
|
-
("is_active", models.BooleanField(default=True, help_text="Is key active")),
|
881
1070
|
(
|
882
|
-
"
|
883
|
-
models.
|
1071
|
+
"name",
|
1072
|
+
models.CharField(
|
1073
|
+
help_text="Human-readable name for this API key", max_length=100
|
1074
|
+
),
|
884
1075
|
),
|
885
1076
|
(
|
886
|
-
"
|
887
|
-
models.
|
1077
|
+
"key",
|
1078
|
+
models.CharField(
|
1079
|
+
help_text="The actual API key (auto-generated)",
|
1080
|
+
max_length=64,
|
1081
|
+
unique=True,
|
1082
|
+
validators=[django.core.validators.MinLengthValidator(32)],
|
1083
|
+
),
|
888
1084
|
),
|
889
1085
|
(
|
890
|
-
"
|
891
|
-
models.
|
1086
|
+
"is_active",
|
1087
|
+
models.BooleanField(default=True, help_text="Whether this API key is active"),
|
892
1088
|
),
|
893
1089
|
(
|
894
|
-
"
|
895
|
-
models.
|
896
|
-
help_text="
|
897
|
-
on_delete=django.db.models.deletion.CASCADE,
|
898
|
-
related_name="api_keys",
|
899
|
-
to=settings.AUTH_USER_MODEL,
|
1090
|
+
"total_requests",
|
1091
|
+
models.PositiveIntegerField(
|
1092
|
+
default=0, help_text="Total number of requests made with this key"
|
900
1093
|
),
|
901
1094
|
),
|
902
|
-
],
|
903
|
-
options={
|
904
|
-
"verbose_name": "API Key",
|
905
|
-
"verbose_name_plural": "API Keys",
|
906
|
-
"db_table": "api_keys",
|
907
|
-
"ordering": ["-created_at"],
|
908
|
-
"indexes": [
|
909
|
-
models.Index(fields=["user", "is_active"], name="api_keys_user_id_6e7352_idx"),
|
910
|
-
models.Index(fields=["key_value"], name="api_keys_key_val_a809c4_idx"),
|
911
|
-
models.Index(fields=["key_prefix"], name="api_keys_key_pre_9c2634_idx"),
|
912
|
-
models.Index(fields=["last_used"], name="api_keys_last_us_f1be76_idx"),
|
913
|
-
models.Index(fields=["expires_at"], name="api_keys_expires_f68b1a_idx"),
|
914
|
-
],
|
915
|
-
},
|
916
|
-
),
|
917
|
-
migrations.CreateModel(
|
918
|
-
name="CurrencyNetwork",
|
919
|
-
fields=[
|
920
1095
|
(
|
921
|
-
"
|
922
|
-
models.
|
923
|
-
|
1096
|
+
"last_used_at",
|
1097
|
+
models.DateTimeField(
|
1098
|
+
blank=True, help_text="When this API key was last used", null=True
|
924
1099
|
),
|
925
1100
|
),
|
926
|
-
("created_at", models.DateTimeField(auto_now_add=True, db_index=True)),
|
927
|
-
("updated_at", models.DateTimeField(auto_now=True)),
|
928
1101
|
(
|
929
|
-
"
|
930
|
-
models.
|
931
|
-
|
1102
|
+
"expires_at",
|
1103
|
+
models.DateTimeField(
|
1104
|
+
blank=True,
|
1105
|
+
help_text="When this API key expires (null = never expires)",
|
1106
|
+
null=True,
|
932
1107
|
),
|
933
1108
|
),
|
934
1109
|
(
|
935
|
-
"
|
936
|
-
models.
|
937
|
-
|
938
|
-
|
939
|
-
"is_active",
|
940
|
-
models.BooleanField(default=True, help_text="Whether this network is active"),
|
941
|
-
),
|
942
|
-
(
|
943
|
-
"confirmation_blocks",
|
944
|
-
models.PositiveIntegerField(
|
945
|
-
default=1, help_text="Number of confirmations required"
|
1110
|
+
"allowed_ips",
|
1111
|
+
models.TextField(
|
1112
|
+
blank=True,
|
1113
|
+
help_text="Comma-separated list of allowed IP addresses (empty = any IP)",
|
946
1114
|
),
|
947
1115
|
),
|
948
1116
|
(
|
949
|
-
"
|
1117
|
+
"user",
|
950
1118
|
models.ForeignKey(
|
951
|
-
help_text="
|
1119
|
+
help_text="User who owns this API key",
|
952
1120
|
on_delete=django.db.models.deletion.CASCADE,
|
953
|
-
related_name="
|
954
|
-
to=
|
1121
|
+
related_name="api_keys",
|
1122
|
+
to=settings.AUTH_USER_MODEL,
|
955
1123
|
),
|
956
1124
|
),
|
957
1125
|
],
|
958
1126
|
options={
|
959
|
-
"verbose_name": "
|
960
|
-
"verbose_name_plural": "
|
961
|
-
"db_table": "
|
1127
|
+
"verbose_name": "API Key",
|
1128
|
+
"verbose_name_plural": "API Keys",
|
1129
|
+
"db_table": "payments_api_keys",
|
1130
|
+
"ordering": ["-created_at"],
|
962
1131
|
"indexes": [
|
1132
|
+
models.Index(fields=["key"], name="payments_ap_key_9290c6_idx"),
|
963
1133
|
models.Index(
|
964
|
-
fields=["
|
1134
|
+
fields=["user", "is_active"], name="payments_ap_user_id_784de9_idx"
|
965
1135
|
),
|
966
|
-
models.Index(fields=["
|
1136
|
+
models.Index(fields=["expires_at"], name="payments_ap_expires_dff82d_idx"),
|
967
1137
|
],
|
968
|
-
"unique_together": {("currency", "network_code")},
|
969
1138
|
},
|
970
1139
|
),
|
971
1140
|
migrations.AddIndex(
|
972
|
-
model_name="
|
973
|
-
index=models.Index(fields=["
|
1141
|
+
model_name="network",
|
1142
|
+
index=models.Index(fields=["is_active"], name="payments_ne_is_acti_915889_idx"),
|
974
1143
|
),
|
975
1144
|
migrations.AddIndex(
|
976
|
-
model_name="
|
1145
|
+
model_name="network",
|
1146
|
+
index=models.Index(fields=["code"], name="payments_ne_code_28d2a9_idx"),
|
1147
|
+
),
|
1148
|
+
migrations.AddIndex(
|
1149
|
+
model_name="providercurrency",
|
977
1150
|
index=models.Index(
|
978
|
-
fields=["
|
1151
|
+
fields=["provider", "is_enabled"], name="payments_pr_provide_585c03_idx"
|
979
1152
|
),
|
980
1153
|
),
|
981
1154
|
migrations.AddIndex(
|
982
|
-
model_name="
|
1155
|
+
model_name="providercurrency",
|
983
1156
|
index=models.Index(
|
984
|
-
fields=["
|
1157
|
+
fields=["currency", "is_enabled"], name="payments_pr_currenc_a88055_idx"
|
985
1158
|
),
|
986
1159
|
),
|
1160
|
+
migrations.AlterUniqueTogether(
|
1161
|
+
name="providercurrency",
|
1162
|
+
unique_together={("provider", "currency", "network")},
|
1163
|
+
),
|
1164
|
+
migrations.AddIndex(
|
1165
|
+
model_name="subscription",
|
1166
|
+
index=models.Index(fields=["user", "status"], name="payments_su_user_id_3279a3_idx"),
|
1167
|
+
),
|
987
1168
|
migrations.AddIndex(
|
988
1169
|
model_name="subscription",
|
989
|
-
index=models.Index(
|
1170
|
+
index=models.Index(
|
1171
|
+
fields=["status", "expires_at"], name="payments_su_status_1a9788_idx"
|
1172
|
+
),
|
990
1173
|
),
|
991
1174
|
migrations.AddIndex(
|
992
1175
|
model_name="subscription",
|
993
|
-
index=models.Index(fields=["
|
1176
|
+
index=models.Index(fields=["tier", "status"], name="payments_su_tier_2ba72c_idx"),
|
994
1177
|
),
|
995
|
-
migrations.
|
996
|
-
|
997
|
-
|
1178
|
+
migrations.AddConstraint(
|
1179
|
+
model_name="subscription",
|
1180
|
+
constraint=models.UniqueConstraint(
|
1181
|
+
condition=models.Q(("status", "active")),
|
1182
|
+
fields=("user",),
|
1183
|
+
name="one_active_subscription_per_user",
|
1184
|
+
),
|
998
1185
|
),
|
999
1186
|
migrations.AlterUniqueTogether(
|
1000
1187
|
name="tariffendpointgroup",
|
1001
1188
|
unique_together={("tariff", "endpoint_group")},
|
1002
1189
|
),
|
1003
1190
|
migrations.AddIndex(
|
1004
|
-
model_name="
|
1005
|
-
index=models.Index(fields=["user", "status"], name="universal_p_user_id_7bdba2_idx"),
|
1006
|
-
),
|
1007
|
-
migrations.AddIndex(
|
1008
|
-
model_name="universalpayment",
|
1191
|
+
model_name="transaction",
|
1009
1192
|
index=models.Index(
|
1010
|
-
fields=["
|
1193
|
+
fields=["user", "created_at"], name="payments_tr_user_id_c1c1f7_idx"
|
1011
1194
|
),
|
1012
1195
|
),
|
1013
1196
|
migrations.AddIndex(
|
1014
|
-
model_name="
|
1197
|
+
model_name="transaction",
|
1015
1198
|
index=models.Index(
|
1016
|
-
fields=["
|
1199
|
+
fields=["transaction_type", "created_at"], name="payments_tr_transac_4c7d58_idx"
|
1017
1200
|
),
|
1018
1201
|
),
|
1019
1202
|
migrations.AddIndex(
|
1020
|
-
model_name="
|
1021
|
-
index=models.Index(fields=["
|
1022
|
-
),
|
1023
|
-
migrations.AddIndex(
|
1024
|
-
model_name="universalpayment",
|
1025
|
-
index=models.Index(fields=["provider"], name="universal_p_provide_9820af_idx"),
|
1026
|
-
),
|
1027
|
-
migrations.AddIndex(
|
1028
|
-
model_name="universalpayment",
|
1029
|
-
index=models.Index(fields=["currency_code"], name="universal_p_currenc_56f1fc_idx"),
|
1030
|
-
),
|
1031
|
-
migrations.AddIndex(
|
1032
|
-
model_name="universalpayment",
|
1033
|
-
index=models.Index(fields=["created_at"], name="universal_p_created_978509_idx"),
|
1034
|
-
),
|
1035
|
-
migrations.AddIndex(
|
1036
|
-
model_name="universalpayment",
|
1037
|
-
index=models.Index(fields=["processed_at"], name="universal_p_process_1c8a1f_idx"),
|
1203
|
+
model_name="transaction",
|
1204
|
+
index=models.Index(fields=["payment_id"], name="payments_tr_payment_96b00a_idx"),
|
1038
1205
|
),
|
1039
1206
|
migrations.AddIndex(
|
1040
|
-
model_name="
|
1041
|
-
index=models.Index(fields=["
|
1207
|
+
model_name="transaction",
|
1208
|
+
index=models.Index(fields=["amount_usd"], name="payments_tr_amount__c7f348_idx"),
|
1042
1209
|
),
|
1043
1210
|
migrations.AddIndex(
|
1044
1211
|
model_name="universalpayment",
|
1045
|
-
index=models.Index(fields=["
|
1212
|
+
index=models.Index(fields=["user", "status"], name="payments_un_user_id_8ce187_idx"),
|
1046
1213
|
),
|
1047
1214
|
migrations.AddIndex(
|
1048
1215
|
model_name="universalpayment",
|
1049
1216
|
index=models.Index(
|
1050
|
-
fields=["
|
1217
|
+
fields=["provider", "status"], name="payments_un_provide_904e1a_idx"
|
1051
1218
|
),
|
1052
1219
|
),
|
1053
1220
|
migrations.AddIndex(
|
1054
1221
|
model_name="universalpayment",
|
1055
1222
|
index=models.Index(
|
1056
|
-
fields=["
|
1057
|
-
name="universal_p_provide_3c8a34_idx",
|
1223
|
+
fields=["status", "created_at"], name="payments_un_status_fd808c_idx"
|
1058
1224
|
),
|
1059
1225
|
),
|
1060
1226
|
migrations.AddIndex(
|
1061
|
-
model_name="
|
1227
|
+
model_name="universalpayment",
|
1062
1228
|
index=models.Index(
|
1063
|
-
fields=["
|
1229
|
+
fields=["provider_payment_id"], name="payments_un_provide_553809_idx"
|
1064
1230
|
),
|
1065
1231
|
),
|
1066
1232
|
migrations.AddIndex(
|
1067
|
-
model_name="
|
1068
|
-
index=models.Index(fields=["
|
1233
|
+
model_name="universalpayment",
|
1234
|
+
index=models.Index(fields=["transaction_hash"], name="payments_un_transac_5a0fe3_idx"),
|
1069
1235
|
),
|
1070
1236
|
migrations.AddIndex(
|
1071
|
-
model_name="
|
1072
|
-
index=models.Index(fields=["
|
1237
|
+
model_name="universalpayment",
|
1238
|
+
index=models.Index(fields=["expires_at"], name="payments_un_expires_3b92ad_idx"),
|
1073
1239
|
),
|
1074
|
-
migrations.
|
1075
|
-
model_name="
|
1076
|
-
|
1240
|
+
migrations.AddConstraint(
|
1241
|
+
model_name="universalpayment",
|
1242
|
+
constraint=models.CheckConstraint(
|
1243
|
+
condition=models.Q(("amount_usd__gte", 1.0)), name="payments_min_amount_check"
|
1244
|
+
),
|
1077
1245
|
),
|
1078
|
-
migrations.
|
1079
|
-
model_name="
|
1080
|
-
|
1246
|
+
migrations.AddConstraint(
|
1247
|
+
model_name="universalpayment",
|
1248
|
+
constraint=models.CheckConstraint(
|
1249
|
+
condition=models.Q(("amount_usd__lte", 50000.0)), name="payments_max_amount_check"
|
1250
|
+
),
|
1081
1251
|
),
|
1082
1252
|
migrations.AddIndex(
|
1083
1253
|
model_name="userbalance",
|
1084
|
-
index=models.Index(fields=["
|
1254
|
+
index=models.Index(fields=["balance_usd"], name="payments_us_balance_32e5aa_idx"),
|
1085
1255
|
),
|
1086
1256
|
migrations.AddIndex(
|
1087
1257
|
model_name="userbalance",
|
1088
|
-
index=models.Index(
|
1258
|
+
index=models.Index(
|
1259
|
+
fields=["last_transaction_at"], name="payments_us_last_tr_935db2_idx"
|
1260
|
+
),
|
1089
1261
|
),
|
1090
|
-
migrations.
|
1262
|
+
migrations.AddConstraint(
|
1091
1263
|
model_name="userbalance",
|
1092
|
-
|
1093
|
-
|
1264
|
+
constraint=models.CheckConstraint(
|
1265
|
+
condition=models.Q(("balance_usd__gte", 0.0)), name="balance_non_negative_check"
|
1094
1266
|
),
|
1095
1267
|
),
|
1096
1268
|
]
|