diff --git a/api/__pycache__/settings.cpython-313.pyc b/api/__pycache__/settings.cpython-313.pyc index 823adfb3..888080bb 100644 Binary files a/api/__pycache__/settings.cpython-313.pyc and b/api/__pycache__/settings.cpython-313.pyc differ diff --git a/api/__pycache__/urls.cpython-313.pyc b/api/__pycache__/urls.cpython-313.pyc index cfdfbd89..c4a84014 100644 Binary files a/api/__pycache__/urls.cpython-313.pyc and b/api/__pycache__/urls.cpython-313.pyc differ diff --git a/api/urls.py b/api/urls.py index fa8f261b..fd5be2eb 100644 --- a/api/urls.py +++ b/api/urls.py @@ -14,7 +14,7 @@ Including another URLconf 2. Add a URL to urlpatterns: re_path('blog/', include('blog.urls')) """ from django.urls import re_path -from app import views, cob, cleardata, email, backup, server, importdata +from app import views, cob, email, backup, server, importdata urlpatterns = [ @@ -40,7 +40,7 @@ urlpatterns = [ re_path('password/(?P.+)/$', views.get_password), re_path('exportcsv/(?P.+)/$', views.export_csv), re_path('close-of-business/$', cob.close_of_business), - re_path('data-deletion/', cleardata.data_deletion), + re_path('send-email/$', email.send_email), re_path('backup-database/', backup.backup_database), re_path('set-token-expiry/', views.set_token_expiry), diff --git a/app/__pycache__/models.cpython-313.pyc b/app/__pycache__/models.cpython-313.pyc index be2482fe..5a5b8db8 100644 Binary files a/app/__pycache__/models.cpython-313.pyc and b/app/__pycache__/models.cpython-313.pyc differ diff --git a/app/__pycache__/views.cpython-313.pyc b/app/__pycache__/views.cpython-313.pyc index ae8c1564..839097cb 100644 Binary files a/app/__pycache__/views.cpython-313.pyc and b/app/__pycache__/views.cpython-313.pyc differ diff --git a/app/migrations/0001_initial.py b/app/migrations/0001_initial.py index 0543a763..c12da6a7 100644 --- a/app/migrations/0001_initial.py +++ b/app/migrations/0001_initial.py @@ -1,6 +1,7 @@ -# Generated by Django 5.1.7 on 2026-03-19 04:48 +# Generated by Django 5.1.7 on 2026-03-24 03:54 import django.db.models.deletion +import uuid from django.db import migrations, models @@ -187,6 +188,21 @@ class Migration(migrations.Migration): 'db_table': 'company_type', }, ), + migrations.CreateModel( + name='Contract_Status', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('en', models.CharField(max_length=100, null=True)), + ('index', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'contract_status', + }, + ), migrations.CreateModel( name='Country', fields=[ @@ -268,6 +284,42 @@ class Migration(migrations.Migration): 'db_table': 'data_type', }, ), + migrations.CreateModel( + name='Dealer', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=20, null=True, unique=True)), + ('name', models.CharField(max_length=100)), + ('phone', models.CharField(db_index=True, max_length=20, null=True)), + ('email', models.CharField(max_length=50, null=True)), + ('address', models.CharField(max_length=255, null=True)), + ('sale_amount', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('pay_sale', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('commission_amount', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('pay_commission', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('commission_remain', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('batch_date', models.DateTimeField(null=True)), + ('count_sale', models.IntegerField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'dealer', + }, + ), + migrations.CreateModel( + name='Direction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'direction', + }, + ), migrations.CreateModel( name='Discount_Method', fields=[ @@ -339,6 +391,20 @@ class Migration(migrations.Migration): 'db_table': 'document_type', }, ), + migrations.CreateModel( + name='Duration', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('detail', models.TextField()), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'duration', + }, + ), migrations.CreateModel( name='Email_List', fields=[ @@ -463,6 +529,21 @@ class Migration(migrations.Migration): 'db_table': 'filter_type', }, ), + migrations.CreateModel( + name='Gift', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('detail', models.TextField(null=True)), + ('index', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'gift', + }, + ), migrations.CreateModel( name='Import_Setting', fields=[ @@ -481,21 +562,6 @@ class Migration(migrations.Migration): 'db_table': 'import_setting', }, ), - migrations.CreateModel( - name='Instance_Status', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(max_length=30, unique=True)), - ('name', models.CharField(max_length=100)), - ('en', models.CharField(max_length=100, null=True)), - ('color', models.CharField(max_length=20, null=True)), - ('index', models.IntegerField(default=1, null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ], - options={ - 'db_table': 'instance_status', - }, - ), migrations.CreateModel( name='Interest_Base', fields=[ @@ -512,6 +578,26 @@ class Migration(migrations.Migration): 'db_table': 'interest_base', }, ), + migrations.CreateModel( + name='Investor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('tax_code', models.CharField(max_length=20)), + ('address', models.TextField()), + ('phone', models.CharField(max_length=15, null=True)), + ('email', models.CharField(max_length=50, null=True)), + ('bank_account', models.CharField(max_length=20, null=True)), + ('bank_name', models.CharField(max_length=100, null=True)), + ('representative', models.CharField(max_length=100, null=True)), + ('website', models.URLField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'investor', + }, + ), migrations.CreateModel( name='Issued_Place', fields=[ @@ -525,6 +611,19 @@ class Migration(migrations.Migration): 'db_table': 'issued_place', }, ), + migrations.CreateModel( + name='Land_Type', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'land_type', + }, + ), migrations.CreateModel( name='Lang_Choice', fields=[ @@ -626,6 +725,19 @@ class Migration(migrations.Migration): 'db_table': 'notification_status', }, ), + migrations.CreateModel( + name='Ownership_Type', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'ownership_type', + }, + ), migrations.CreateModel( name='Payment_Method', fields=[ @@ -641,6 +753,34 @@ class Migration(migrations.Migration): 'db_table': 'payment_method', }, ), + migrations.CreateModel( + name='Payment_Schedule', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, null=True, unique=True)), + ('from_date', models.DateField()), + ('to_date', models.DateField()), + ('amount', models.DecimalField(decimal_places=2, max_digits=35)), + ('paid_amount', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('amount_remain', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('remain_amount', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('cycle', models.IntegerField()), + ('cycle_days', models.IntegerField()), + ('entry', models.JSONField(null=True)), + ('detail', models.JSONField(null=True)), + ('batch_date', models.DateField(null=True)), + ('ovd_days', models.IntegerField(null=True)), + ('penalty_amount', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('penalty_paid', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('penalty_remain', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('penalty_reduce', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'payment_schedule', + }, + ), migrations.CreateModel( name='Payment_Status', fields=[ @@ -684,38 +824,44 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='Pricing_Tier', + name='Product_Status', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(max_length=30, unique=True)), ('name', models.CharField(max_length=100)), - ('months', models.IntegerField()), - ('discount_percent', models.DecimalField(decimal_places=2, default=0, max_digits=5)), + ('color', models.CharField(max_length=20, null=True)), ('index', models.IntegerField(default=1, null=True)), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), ('update_time', models.DateTimeField(auto_now=True, null=True)), ], options={ - 'db_table': 'pricing_tier', + 'db_table': 'product_status', }, ), migrations.CreateModel( - name='Provider', + name='Product_Type', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(max_length=30, unique=True)), ('name', models.CharField(max_length=100)), - ('website', models.URLField(null=True)), - ('api_endpoint', models.CharField(max_length=200, null=True)), - ('partner_id', models.CharField(max_length=100, null=True)), - ('contact_email', models.CharField(max_length=100, null=True)), - ('note', models.TextField(null=True)), - ('active', models.BooleanField(default=True)), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), ('update_time', models.DateTimeField(auto_now=True, null=True)), ], options={ - 'db_table': 'provider', + 'db_table': 'product_type', + }, + ), + migrations.CreateModel( + name='Project_Status', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'project_status', }, ), migrations.CreateModel( @@ -745,6 +891,21 @@ class Migration(migrations.Migration): 'db_table': 'relation', }, ), + migrations.CreateModel( + name='Sale_Status', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('color', models.CharField(max_length=20, null=True)), + ('index', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'sale_status', + }, + ), migrations.CreateModel( name='Schedule_Type', fields=[ @@ -783,22 +944,6 @@ class Migration(migrations.Migration): 'db_table': 'send_status', }, ), - migrations.CreateModel( - name='Service_Category', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(max_length=30, unique=True)), - ('name', models.CharField(max_length=100)), - ('en', models.CharField(max_length=100, null=True)), - ('icon', models.CharField(max_length=100, null=True)), - ('index', models.IntegerField(default=1, null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('update_time', models.DateTimeField(auto_now=True, null=True)), - ], - options={ - 'db_table': 'service_category', - }, - ), migrations.CreateModel( name='Setting_Choice', fields=[ @@ -935,7 +1080,7 @@ class Migration(migrations.Migration): ('description', models.TextField(blank=True)), ('order', models.PositiveIntegerField(default=0)), ('trigger_event', models.CharField(choices=[('create', 'Create'), ('update', 'Update'), ('approve', 'Approve'), ('advance', 'Advance'), ('confirm', 'Confirm'), ('custom', 'Custom')], max_length=50)), - ('target_model', models.CharField(blank=True, max_length=100)), + ('target_model', models.CharField(blank=True, help_text="Model chính, e.g., 'app.Transaction'", max_length=100)), ('actions', models.JSONField(blank=True, default=list)), ('config', models.JSONField(blank=True, default=dict)), ('is_active', models.BooleanField(default=True)), @@ -943,25 +1088,12 @@ class Migration(migrations.Migration): ('update_time', models.DateTimeField(auto_now=True)), ], options={ + 'verbose_name': 'Step/Action', + 'verbose_name_plural': 'Steps/Actions', 'db_table': 'step_action', 'ordering': ['order'], }, ), - migrations.CreateModel( - name='Subscription_Status', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(max_length=30, unique=True)), - ('name', models.CharField(max_length=100)), - ('en', models.CharField(max_length=100, null=True)), - ('color', models.CharField(max_length=20, null=True)), - ('index', models.IntegerField(default=1, null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ], - options={ - 'db_table': 'subscription_status', - }, - ), migrations.CreateModel( name='Table_Setting', fields=[ @@ -1043,33 +1175,45 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='Ticket_Priority', + name='Transaction_Phase', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(max_length=30, unique=True)), + ('code', models.CharField(max_length=30, null=True, unique=True)), ('name', models.CharField(max_length=100)), - ('en', models.CharField(max_length=100, null=True)), - ('color', models.CharField(max_length=20, null=True)), + ('color', models.IntegerField(null=True)), ('index', models.IntegerField(default=1, null=True)), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), ], options={ - 'db_table': 'ticket_priority', + 'db_table': 'transaction_phase', }, ), migrations.CreateModel( - name='Ticket_Status', + name='Transaction_Status', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(max_length=30, unique=True)), ('name', models.CharField(max_length=100)), - ('en', models.CharField(max_length=100, null=True)), - ('color', models.CharField(max_length=20, null=True)), - ('index', models.IntegerField(default=1, null=True)), + ('detail', models.TextField()), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), ], options={ - 'db_table': 'ticket_status', + 'db_table': 'transaction_status', + }, + ), + migrations.CreateModel( + name='Transaction_Type', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('detail', models.TextField()), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'transaction_type', }, ), migrations.CreateModel( @@ -1096,12 +1240,14 @@ class Migration(migrations.Migration): ('utility_type', models.CharField(choices=[('email', 'Email API'), ('crud', 'Data CRUD'), ('payment', 'Payment API'), ('document', 'Document Gen'), ('notification', 'Notification'), ('custom', 'Custom')], max_length=50)), ('api_config', models.JSONField(blank=True, default=dict)), ('params_template', models.JSONField(blank=True, default=dict)), - ('integration_module', models.CharField(blank=True, max_length=100)), + ('integration_module', models.CharField(blank=True, help_text="e.g., 'app.email.send_email'", max_length=100)), ('is_active', models.BooleanField(default=True)), ('create_time', models.DateTimeField(auto_now_add=True)), ('update_time', models.DateTimeField(auto_now=True)), ], options={ + 'verbose_name': 'Utility', + 'verbose_name_plural': 'Utilities', 'db_table': 'utility', }, ), @@ -1121,17 +1267,16 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='Wallet_Transaction_Type', + name='Zone_Type', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(max_length=30, unique=True)), ('name', models.CharField(max_length=100)), - ('en', models.CharField(max_length=100, null=True)), - ('index', models.IntegerField(default=1, null=True)), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), ], options={ - 'db_table': 'wallet_transaction_type', + 'db_table': 'zone_type', }, ), migrations.CreateModel( @@ -1260,8 +1405,8 @@ class Migration(migrations.Migration): ('create_time', models.DateTimeField(auto_now_add=True, null=True)), ('update_time', models.DateTimeField(auto_now=True, null=True)), ('country', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.country')), - ('segment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.customer_segment')), ('type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.customer_type')), + ('dealer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.dealer')), ('issued_place', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.issued_place')), ('legal_type', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.legal_type')), ], @@ -1270,90 +1415,18 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='Customer_Wallet', + name='Cart', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('billing_mode', models.CharField(choices=[('PREPAID', 'Prepaid — Nạp trước'), ('POSTPAID', 'Postpaid — Trả sau cuối tháng')], default='PREPAID', max_length=20)), - ('balance', models.DecimalField(decimal_places=2, default=0, max_digits=20)), - ('low_balance_threshold', models.DecimalField(decimal_places=2, max_digits=20, null=True)), - ('credit_limit', models.DecimalField(decimal_places=2, max_digits=20, null=True)), - ('billing_day', models.IntegerField(default=1, null=True)), + ('code', models.CharField(max_length=20, null=True, unique=True)), + ('name', models.CharField(max_length=255)), + ('index', models.IntegerField(default=1, null=True)), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), - ('customer', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='wallet', to='app.customer')), + ('dealer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.dealer')), ], options={ - 'db_table': 'customer_wallet', - }, - ), - migrations.CreateModel( - name='Datacenter', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(max_length=30, unique=True)), - ('name', models.CharField(max_length=100)), - ('region', models.CharField(max_length=100, null=True)), - ('provider_location_id', models.CharField(max_length=50, null=True)), - ('active', models.BooleanField(default=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('country', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.country')), - ('provider', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='datacenters', to='app.provider')), - ], - options={ - 'db_table': 'datacenter', - }, - ), - migrations.CreateModel( - name='Cloud_Instance', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), - ('provider_instance_id', models.CharField(db_index=True, max_length=100, null=True)), - ('provider_instance_name', models.CharField(max_length=200, null=True)), - ('ip_address', models.GenericIPAddressField(null=True)), - ('ipv6_address', models.CharField(max_length=50, null=True)), - ('hostname', models.CharField(max_length=200, null=True)), - ('cpu', models.IntegerField(null=True)), - ('ram_gb', models.IntegerField(null=True)), - ('disk_gb', models.IntegerField(null=True)), - ('provisioned_at', models.DateTimeField(null=True)), - ('terminated_at', models.DateTimeField(null=True)), - ('root_password', models.CharField(max_length=300, null=True)), - ('ssh_key', models.TextField(null=True)), - ('note', models.TextField(null=True)), - ('extra_info', models.JSONField(null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('datacenter', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.datacenter')), - ('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.instance_status')), - ('provider', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.provider')), - ], - options={ - 'db_table': 'cloud_instance', - }, - ), - migrations.CreateModel( - name='Dealer_Setting', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('category', models.CharField(max_length=100)), - ('classify', models.CharField(max_length=100)), - ('code', models.CharField(max_length=100)), - ('vi', models.TextField()), - ('en', models.TextField(null=True)), - ('image', models.TextField(null=True)), - ('icon', models.TextField(null=True)), - ('link', models.TextField(null=True)), - ('detail', models.JSONField(null=True)), - ('detail_en', models.JSONField(null=True)), - ('index', models.IntegerField(default=0, null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ], - options={ - 'db_table': 'dealer_setting', - 'unique_together': {('category', 'classify', 'code')}, + 'db_table': 'cart', }, ), migrations.CreateModel( @@ -1377,7 +1450,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=200)), - ('model_name', models.CharField(help_text='e.g., app.Subscription', max_length=100)), + ('model_name', models.CharField(help_text='e.g., app.Transaction_Detail', max_length=100)), ('trigger_on_create', models.BooleanField(default=False)), ('trigger_on_update', models.BooleanField(default=False)), ('active', models.BooleanField(default=True)), @@ -1389,25 +1462,6 @@ class Migration(migrations.Migration): 'db_table': 'email_job', }, ), - migrations.CreateModel( - name='File', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(max_length=20, null=True, unique=True)), - ('name', models.CharField(max_length=200)), - ('file', models.CharField(max_length=200)), - ('hashtag', models.CharField(max_length=200, null=True)), - ('size', models.IntegerField()), - ('caption', models.CharField(max_length=200, null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('update_time', models.DateTimeField(null=True)), - ('doc_type', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.document_type')), - ('type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.file_type')), - ], - options={ - 'db_table': 'file', - }, - ), migrations.CreateModel( name='Info_Setting', fields=[ @@ -1447,29 +1501,6 @@ class Migration(migrations.Migration): 'unique_together': {('branch', 'type', 'currency')}, }, ), - migrations.CreateModel( - name='Invoice', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('link', models.CharField(max_length=100, null=True)), - ('ref_code', models.CharField(max_length=30)), - ('amount', models.DecimalField(decimal_places=2, max_digits=35)), - ('note', models.CharField(max_length=100, null=True)), - ('issue_date', models.DateField(null=True)), - ('due_date', models.DateField(null=True)), - ('paid_amount', models.DecimalField(decimal_places=2, default=0, max_digits=20, null=True)), - ('remain_amount', models.DecimalField(decimal_places=2, max_digits=20, null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('currency', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), - ('customer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='invoices', to='app.customer')), - ('payment_method', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_method')), - ('status', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_status')), - ], - options={ - 'db_table': 'invoice', - }, - ), migrations.CreateModel( name='Message', fields=[ @@ -1507,6 +1538,30 @@ class Migration(migrations.Migration): 'db_table': 'organization', }, ), + migrations.CreateModel( + name='Invoice', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('link', models.CharField(max_length=100, null=True)), + ('ref_code', models.CharField(max_length=30)), + ('amount', models.DecimalField(decimal_places=2, max_digits=35)), + ('note', models.CharField(max_length=100, null=True)), + ('payment', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='invoice', to='app.payment_schedule')), + ], + options={ + 'db_table': 'invoice', + }, + ), + migrations.AddField( + model_name='payment_schedule', + name='status', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_status'), + ), + migrations.AddField( + model_name='payment_schedule', + name='type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_type'), + ), migrations.CreateModel( name='People', fields=[ @@ -1546,54 +1601,18 @@ class Migration(migrations.Migration): field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.people'), ), migrations.CreateModel( - name='Provider_Credential', + name='Project', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('label', models.CharField(max_length=100)), - ('api_key', models.CharField(max_length=500)), - ('api_secret', models.CharField(max_length=500, null=True)), - ('active', models.BooleanField(default=True)), - ('note', models.TextField(null=True)), + ('code', models.CharField(max_length=20, unique=True)), + ('name', models.CharField(max_length=255)), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('provider', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='credentials', to='app.provider')), + ('investor', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.investor')), + ('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.project_status')), ], options={ - 'db_table': 'provider_credential', - }, - ), - migrations.CreateModel( - name='Provider_Invoice', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(max_length=20, null=True, unique=True)), - ('period_from', models.DateField()), - ('period_to', models.DateField()), - ('total_amount', models.DecimalField(decimal_places=2, max_digits=20)), - ('note', models.TextField(null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), - ('document', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.file')), - ('provider', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='provider_invoices', to='app.provider')), - ('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_status')), - ], - options={ - 'db_table': 'provider_invoice', - }, - ), - migrations.CreateModel( - name='Provider_Invoice_Line', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('description', models.CharField(max_length=300)), - ('amount', models.DecimalField(decimal_places=2, max_digits=20)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('instance', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.cloud_instance')), - ('provider_invoice', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='lines', to='app.provider_invoice')), - ], - options={ - 'db_table': 'provider_invoice_line', + 'db_table': 'project', }, ), migrations.CreateModel( @@ -1609,6 +1628,65 @@ class Migration(migrations.Migration): 'db_table': 'legal_rep', }, ), + migrations.CreateModel( + name='Sale_Policy', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('deposit', models.DecimalField(decimal_places=2, max_digits=35)), + ('enable', models.BooleanField(default=True)), + ('contract_allocation_percentage', models.IntegerField(blank=True, default=100, null=True)), + ('index', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('method', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_method')), + ], + options={ + 'db_table': 'sale_policy', + }, + ), + migrations.CreateModel( + name='Product', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=20, null=True, unique=True)), + ('land_lot_code', models.CharField(max_length=255)), + ('zone_code', models.CharField(max_length=255)), + ('trade_code', models.CharField(max_length=20, null=True)), + ('lot_area', models.DecimalField(decimal_places=2, max_digits=35)), + ('building_area', models.DecimalField(decimal_places=2, max_digits=35)), + ('total_built_area', models.DecimalField(decimal_places=2, max_digits=35)), + ('number_of_floors', models.IntegerField()), + ('land_lot_size', models.CharField(max_length=255)), + ('villa_model', models.CharField(max_length=255, null=True)), + ('note', models.TextField(null=True)), + ('origin_price', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('price_excluding_vat', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('product_type', models.CharField(max_length=255, null=True)), + ('template_name', models.CharField(max_length=255, null=True)), + ('link', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('locked_until', models.DateTimeField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('cart', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='prdcart', to='app.cart')), + ('dealer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.dealer')), + ('direction', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.direction')), + ('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.product_status')), + ('type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.product_type')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.project')), + ('policy', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.sale_policy')), + ('zone_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.zone_type')), + ], + options={ + 'db_table': 'product', + }, + ), + migrations.AddField( + model_name='product_status', + name='sale_status', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.sale_status'), + ), migrations.CreateModel( name='Email_Sent', fields=[ @@ -1624,37 +1702,6 @@ class Migration(migrations.Migration): 'db_table': 'email_sent', }, ), - migrations.CreateModel( - name='Service_Plan', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(max_length=30, unique=True)), - ('name', models.CharField(max_length=200)), - ('billing_type', models.CharField(choices=[('SUBSCRIPTION', 'Subscription'), ('PAYG', 'Pay-as-you-go'), ('BOTH', 'Cả hai')], default='SUBSCRIPTION', max_length=20)), - ('cpu', models.IntegerField(null=True)), - ('ram_gb', models.IntegerField(null=True)), - ('disk_gb', models.IntegerField(null=True)), - ('bandwidth_tb', models.DecimalField(decimal_places=2, max_digits=8, null=True)), - ('storage_gb', models.IntegerField(null=True)), - ('extra_specs', models.JSONField(null=True)), - ('provider_price', models.DecimalField(decimal_places=4, max_digits=20)), - ('provider_plan_id', models.CharField(max_length=100, null=True)), - ('sell_price', models.DecimalField(decimal_places=2, max_digits=20)), - ('sell_price_hourly', models.DecimalField(decimal_places=6, max_digits=20, null=True)), - ('active', models.BooleanField(default=True)), - ('index', models.IntegerField(default=1, null=True)), - ('note', models.TextField(null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('category', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='plans', to='app.service_category')), - ('provider', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='plans', to='app.provider')), - ('provider_currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), - ('sell_currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), - ], - options={ - 'db_table': 'service_plan', - }, - ), migrations.CreateModel( name='Individual', fields=[ @@ -1672,95 +1719,6 @@ class Migration(migrations.Migration): 'db_table': 'individual', }, ), - migrations.CreateModel( - name='Staff', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(db_index=True, max_length=20, unique=True)), - ('fullname', models.CharField(db_index=True, max_length=50)), - ('phone', models.CharField(db_index=True, max_length=20, unique=True)), - ('email', models.CharField(max_length=50, null=True, unique=True)), - ('dob', models.DateField(null=True)), - ('legal_code', models.CharField(max_length=20, null=True, unique=True)), - ('issued_place', models.CharField(max_length=200, null=True)), - ('issued_date', models.DateField(null=True)), - ('province', models.CharField(max_length=200, null=True)), - ('district', models.CharField(max_length=200, null=True)), - ('address', models.CharField(max_length=200, null=True)), - ('note', models.TextField(null=True)), - ('zalo', models.CharField(max_length=20, null=True)), - ('facebook', models.CharField(max_length=100, null=True)), - ('deleted', models.BooleanField(db_index=True, default=False)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('branch', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.branch')), - ('country', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.country')), - ('legal_type', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.legal_type')), - ('sex', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.sex')), - ('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.staff_status')), - ], - options={ - 'db_table': 'staff', - }, - ), - migrations.AddField( - model_name='customer', - name='sale_staff', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.staff'), - ), - migrations.CreateModel( - name='Subscription', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), - ('billing_type', models.CharField(choices=[('SUBSCRIPTION', 'Subscription'), ('PAYG', 'Pay-as-you-go')], default='SUBSCRIPTION', max_length=20)), - ('unit_price', models.DecimalField(decimal_places=2, max_digits=20, null=True)), - ('unit_price_hourly', models.DecimalField(decimal_places=6, max_digits=20, null=True)), - ('discount_amount', models.DecimalField(decimal_places=2, default=0, max_digits=20, null=True)), - ('final_price', models.DecimalField(decimal_places=2, max_digits=20, null=True)), - ('start_date', models.DateField()), - ('end_date', models.DateField(null=True)), - ('next_billing_date', models.DateField(null=True)), - ('auto_renew', models.BooleanField(default=True)), - ('note', models.TextField(null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), - ('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='subscriptions', to='app.customer')), - ('datacenter', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.datacenter')), - ('payment_method', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_method')), - ('plan', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='subscriptions', to='app.service_plan')), - ('pricing_tier', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.pricing_tier')), - ('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.subscription_status')), - ], - options={ - 'db_table': 'subscription', - }, - ), - migrations.CreateModel( - name='Invoice_Line', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('description', models.CharField(max_length=300)), - ('period_from', models.DateField()), - ('period_to', models.DateField()), - ('unit_price', models.DecimalField(decimal_places=2, max_digits=20)), - ('quantity', models.DecimalField(decimal_places=2, default=1, max_digits=10)), - ('discount_amount', models.DecimalField(decimal_places=2, default=0, max_digits=20, null=True)), - ('line_total', models.DecimalField(decimal_places=2, max_digits=20)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('invoice', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='lines', to='app.invoice')), - ('subscription', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='invoice_lines', to='app.subscription')), - ], - options={ - 'db_table': 'invoice_line', - }, - ), - migrations.AddField( - model_name='cloud_instance', - name='subscription', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='instances', to='app.subscription'), - ), migrations.CreateModel( name='System_Setting', fields=[ @@ -1838,24 +1796,85 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='Support_Ticket', + name='Transaction', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), - ('title', models.CharField(max_length=300)), - ('description', models.TextField()), - ('resolved_at', models.DateTimeField(null=True)), + ('code', models.CharField(max_length=30, null=True, unique=True)), + ('date', models.DateField()), + ('origin_price', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('discount_amount', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('sale_price', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('deposit_amount', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('deposit_received', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('deposit_remaining', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('amount_received', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('amount_remain', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('penalty_amount', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('early_discount_amount', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('payment_plan', models.JSONField(null=True)), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('assignee', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.staff')), - ('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='tickets', to='app.customer')), - ('instance', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='tickets', to='app.cloud_instance')), - ('subscription', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='tickets', to='app.subscription')), - ('priority', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.ticket_priority')), - ('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.ticket_status')), + ('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='txncust', to='app.customer')), + ('policy', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='txnplc', to='app.sale_policy')), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='txnprd', to='app.product')), + ('phase', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.transaction_phase')), ], options={ - 'db_table': 'support_ticket', + 'db_table': 'transaction', + }, + ), + migrations.CreateModel( + name='Transaction_Detail', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, null=True, unique=True)), + ('date', models.DateField()), + ('amount', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('amount_remaining', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('amount_received', models.DecimalField(decimal_places=2, max_digits=35, null=True)), + ('due_date', models.DateField(null=True)), + ('approve_time', models.DateTimeField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('customer_new', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.customer')), + ('customer_old', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.customer')), + ('transaction', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='resvtxn', to='app.transaction')), + ('phase', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.transaction_phase')), + ('status', models.ForeignKey(default=1, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.transaction_status')), + ], + options={ + 'db_table': 'transaction_detail', + }, + ), + migrations.AddField( + model_name='payment_schedule', + name='txn_detail', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='psh', to='app.transaction_detail'), + ), + migrations.CreateModel( + name='Transaction_Gift', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('gift', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.gift')), + ('transaction', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='txngift', to='app.transaction')), + ], + options={ + 'db_table': 'transaction_gift', + }, + ), + migrations.CreateModel( + name='Phase_Doctype', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('doctype', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.document_type')), + ('phase', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='phasedoc', to='app.transaction_phase')), + ], + options={ + 'db_table': 'phase_doctype', }, ), migrations.CreateModel( @@ -1885,6 +1904,16 @@ class Migration(migrations.Migration): 'db_table': 'user', }, ), + migrations.AddField( + model_name='transaction_detail', + name='approver', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), + ), + migrations.AddField( + model_name='transaction_detail', + name='creator', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), + ), migrations.CreateModel( name='Token', fields=[ @@ -1913,22 +1942,41 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='Ticket_Reply', + name='Staff', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('content', models.TextField()), - ('is_internal', models.BooleanField(default=False)), - ('files', models.JSONField(null=True)), + ('code', models.CharField(db_index=True, max_length=20, unique=True)), + ('fullname', models.CharField(db_index=True, max_length=50)), + ('phone', models.CharField(db_index=True, max_length=20, unique=True)), + ('email', models.CharField(max_length=50, null=True, unique=True)), + ('dob', models.DateField(null=True)), + ('legal_code', models.CharField(max_length=20, null=True, unique=True)), + ('issued_place', models.CharField(max_length=200, null=True)), + ('issued_date', models.DateField(null=True)), + ('province', models.CharField(max_length=200, null=True)), + ('district', models.CharField(max_length=200, null=True)), + ('address', models.CharField(max_length=200, null=True)), + ('note', models.TextField(null=True)), + ('zalo', models.CharField(max_length=20, null=True)), + ('facebook', models.CharField(max_length=100, null=True)), + ('deleted', models.BooleanField(db_index=True, default=False)), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='replies', to='app.support_ticket')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('branch', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.branch')), + ('country', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.country')), + ('legal_type', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.legal_type')), + ('sex', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.sex')), + ('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.staff_status')), + ('creator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), + ('updater', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), ], options={ - 'db_table': 'ticket_reply', + 'db_table': 'staff', }, ), migrations.CreateModel( - name='Subscription_Note', + name='Product_Note', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('detail', models.TextField()), @@ -1936,38 +1984,13 @@ class Migration(migrations.Migration): ('deleted', models.BooleanField(default=False, null=True)), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('ref', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='subnote', to='app.subscription')), + ('ref', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='prdnote', to='app.product')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), ], options={ - 'db_table': 'subscription_note', + 'db_table': 'product_note', }, ), - migrations.AddField( - model_name='subscription', - name='creator', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), - ), - migrations.AddField( - model_name='subscription', - name='updater', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), - ), - migrations.AddField( - model_name='staff', - name='creator', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), - ), - migrations.AddField( - model_name='staff', - name='updater', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), - ), - migrations.AddField( - model_name='staff', - name='user', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), - ), migrations.AddField( model_name='people', name='creator', @@ -1978,29 +2001,10 @@ class Migration(migrations.Migration): name='updater', field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), ), - migrations.CreateModel( - name='Payment_Receipt', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), - ('amount', models.DecimalField(decimal_places=2, max_digits=20)), - ('payment_date', models.DateField()), - ('ref_code', models.CharField(max_length=100, null=True)), - ('note', models.TextField(null=True)), - ('approve_time', models.DateTimeField(null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), - ('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='receipts', to='app.customer')), - ('invoice', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='receipts', to='app.invoice')), - ('payment_method', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_method')), - ('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_status')), - ('approver', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), - ('creator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), - ], - options={ - 'db_table': 'payment_receipt', - }, + migrations.AddField( + model_name='payment_schedule', + name='updater', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), ), migrations.CreateModel( name='News', @@ -2041,11 +2045,6 @@ class Migration(migrations.Migration): 'db_table': 'layer_setting', }, ), - migrations.AddField( - model_name='invoice', - name='creator', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), - ), migrations.CreateModel( name='Internal_Entry', fields=[ @@ -2066,9 +2065,7 @@ class Migration(migrations.Migration): ('category', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='entrycate', to='app.entry_category')), ('customer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='entrycus', to='app.customer')), ('type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.entry_type')), - ('invoice', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.invoice')), - ('provider_invoice', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.provider_invoice')), - ('subscription', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.subscription')), + ('product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.product')), ('approver', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), ('inputer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), ], @@ -2076,21 +2073,6 @@ class Migration(migrations.Migration): 'db_table': 'internal_entry', }, ), - migrations.CreateModel( - name='Instance_Log', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('action', models.CharField(max_length=50)), - ('status', models.CharField(max_length=30)), - ('detail', models.JSONField(null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('instance', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='logs', to='app.cloud_instance')), - ('performed_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), - ], - options={ - 'db_table': 'instance_log', - }, - ), migrations.CreateModel( name='Group', fields=[ @@ -2106,10 +2088,30 @@ class Migration(migrations.Migration): 'unique_together': {('creator', 'name')}, }, ), + migrations.CreateModel( + name='File', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=20, null=True, unique=True)), + ('name', models.CharField(max_length=200)), + ('file', models.CharField(max_length=200)), + ('hashtag', models.CharField(max_length=200, null=True)), + ('size', models.IntegerField()), + ('caption', models.CharField(max_length=200, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(null=True)), + ('doc_type', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.document_type')), + ('type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.file_type')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), + ], + options={ + 'db_table': 'file', + }, + ), migrations.AddField( - model_name='file', + model_name='dealer', name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), + field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='dealer_profile', to='app.user'), ), migrations.CreateModel( name='Customer_Sms', @@ -2148,10 +2150,22 @@ class Migration(migrations.Migration): name='updater', field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), ), - migrations.AddField( - model_name='customer', - name='user', - field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='customer_profile', to='app.user'), + migrations.CreateModel( + name='Contract', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('link', models.UUIDField(default=uuid.uuid4, editable=False, null=True)), + ('document', models.JSONField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('status', models.ForeignKey(default=1, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.contract_status')), + ('signature', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.file')), + ('transaction', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.transaction')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), + ], + options={ + 'db_table': 'contract', + }, ), migrations.AddField( model_name='company', @@ -2245,17 +2259,18 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='Subscription_Discount', + name='Transaction_Discount', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('value', models.DecimalField(decimal_places=2, max_digits=20, null=True)), + ('value', models.DecimalField(decimal_places=2, max_digits=35, null=True)), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), ('discount', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.discount_type')), - ('subscription', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='discounts', to='app.subscription')), + ('transaction', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='txndiscount', to='app.transaction')), ('type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.value_type')), ], options={ - 'db_table': 'subscription_discount', + 'db_table': 'transaction_discount', }, ), migrations.CreateModel( @@ -2275,27 +2290,6 @@ class Migration(migrations.Migration): 'db_table': 'fee_type', }, ), - migrations.CreateModel( - name='Wallet_Transaction', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), - ('amount', models.DecimalField(decimal_places=2, max_digits=20)), - ('balance_before', models.DecimalField(decimal_places=2, max_digits=20)), - ('balance_after', models.DecimalField(decimal_places=2, max_digits=20)), - ('description', models.CharField(max_length=300)), - ('ref_code', models.CharField(max_length=100, null=True)), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('invoice', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='wallet_txns', to='app.invoice')), - ('performed_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), - ('subscription', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='wallet_txns', to='app.subscription')), - ('wallet', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transactions', to='app.customer_wallet')), - ('type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.wallet_transaction_type')), - ], - options={ - 'db_table': 'wallet_transaction', - }, - ), migrations.CreateModel( name='Workflow', fields=[ @@ -2309,6 +2303,8 @@ class Migration(migrations.Migration): ('initial_step', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='initial_workflows', to='app.stepaction')), ], options={ + 'verbose_name': 'Workflow', + 'verbose_name_plural': 'Workflows', 'db_table': 'workflow', }, ), @@ -2380,24 +2376,29 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='Postpaid_Billing_Cycle', + name='Product_File', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), - ('period_from', models.DateField()), - ('period_to', models.DateField()), - ('total_usage_amount', models.DecimalField(decimal_places=2, max_digits=20, null=True)), - ('status', models.CharField(choices=[('OPEN', 'Đang tích lũy usage'), ('INVOICED', 'Đã xuất Invoice'), ('PAID', 'Đã thanh toán')], default='OPEN', max_length=20)), - ('closed_at', models.DateTimeField(null=True)), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('update_time', models.DateTimeField(auto_now=True, null=True)), - ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), - ('customer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='billing_cycles', to='app.customer')), - ('invoice', models.OneToOneField(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='billing_cycle', to='app.invoice')), + ('file', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.file')), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='prdfile', to='app.product')), ], options={ - 'db_table': 'postpaid_billing_cycle', - 'unique_together': {('customer', 'period_from')}, + 'db_table': 'product_file', + 'unique_together': {('product', 'file')}, + }, + ), + migrations.CreateModel( + name='Project_File', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('file', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.file')), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='prjfile', to='app.project')), + ], + options={ + 'db_table': 'project_file', + 'unique_together': {('project', 'file')}, }, ), migrations.CreateModel( @@ -2415,19 +2416,6 @@ class Migration(migrations.Migration): 'unique_together': {('customer', 'people')}, }, ), - migrations.CreateModel( - name='Plan_Datacenter', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('datacenter', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.datacenter')), - ('plan', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='plan_dcs', to='app.service_plan')), - ], - options={ - 'db_table': 'plan_datacenter', - 'unique_together': {('plan', 'datacenter')}, - }, - ), migrations.CreateModel( name='Staff_File', fields=[ @@ -2442,16 +2430,59 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='Subscription_File', + name='Product_Booked', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('file', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.file')), - ('ref', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='subfile', to='app.subscription')), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('product', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='prdbk', to='app.product')), + ('transaction', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transbk', to='app.transaction')), ], options={ - 'db_table': 'subscription_file', - 'unique_together': {('ref', 'file')}, + 'db_table': 'product_booked', + 'unique_together': {('product', 'transaction')}, + }, + ), + migrations.CreateModel( + name='Co_Ownership', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('people', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.people')), + ('transaction', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='co_op', to='app.transaction')), + ], + options={ + 'db_table': 'co_ownership', + 'unique_together': {('transaction', 'people')}, + }, + ), + migrations.CreateModel( + name='Transaction_Current', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('transaction', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='txncurrent', to='app.transaction')), + ('detail', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.transaction_detail')), + ], + options={ + 'db_table': 'transaction_current', + 'unique_together': {('transaction', 'detail')}, + }, + ), + migrations.CreateModel( + name='Transaction_File', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('file', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.file')), + ('txn_detail', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='txnfile', to='app.transaction_detail')), + ], + options={ + 'db_table': 'transaction_file', + 'unique_together': {('txn_detail', 'file')}, }, ), migrations.CreateModel( @@ -2470,19 +2501,6 @@ class Migration(migrations.Migration): 'unique_together': {('message', 'user')}, }, ), - migrations.CreateModel( - name='Dealer_Rights', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('setting', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.dealer_setting')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), - ], - options={ - 'db_table': 'dealer_rights', - 'unique_together': {('setting', 'user')}, - }, - ), migrations.CreateModel( name='Biz_Rights', fields=[ @@ -2555,30 +2573,29 @@ class Migration(migrations.Migration): ('utility', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rules', to='app.utility')), ], options={ + 'verbose_name': 'Rule', + 'verbose_name_plural': 'Rules', 'db_table': 'rule', 'unique_together': {('step_action', 'rule_code')}, }, ), migrations.CreateModel( - name='Usage_Record', + name='Payment_Plan', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('period_from', models.DateTimeField()), - ('period_to', models.DateTimeField()), - ('hours', models.DecimalField(decimal_places=4, max_digits=10)), - ('unit_price_hourly', models.DecimalField(decimal_places=6, max_digits=20)), - ('amount', models.DecimalField(decimal_places=4, max_digits=20)), - ('charged', models.BooleanField(default=False)), + ('cycle', models.IntegerField()), + ('value', models.IntegerField()), + ('days', models.IntegerField()), + ('payment_note', models.TextField()), + ('due_note', models.TextField()), ('create_time', models.DateTimeField(auto_now_add=True, null=True)), - ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), - ('instance', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='usage_records', to='app.cloud_instance')), - ('postpaid_invoice', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='usage_records', to='app.invoice')), - ('subscription', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='usage_records', to='app.subscription')), - ('wallet_transaction', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='usage_records', to='app.wallet_transaction')), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('policy', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.sale_policy')), + ('type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.value_type')), ], options={ - 'db_table': 'usage_record', - 'indexes': [models.Index(fields=['subscription', 'period_from'], name='usage_recor_subscri_b0fb0c_idx')], + 'db_table': 'payment_plan', + 'unique_together': {('policy', 'cycle')}, }, ), migrations.AlterUniqueTogether( diff --git a/app/migrations/0002_alter_dealer_rights_unique_together_and_more.py b/app/migrations/0002_alter_dealer_rights_unique_together_and_more.py deleted file mode 100644 index 86e1c0ad..00000000 --- a/app/migrations/0002_alter_dealer_rights_unique_together_and_more.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 5.1.7 on 2026-03-19 04:54 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('app', '0001_initial'), - ] - - operations = [ - migrations.AlterUniqueTogether( - name='dealer_rights', - unique_together=None, - ), - migrations.RemoveField( - model_name='dealer_rights', - name='setting', - ), - migrations.RemoveField( - model_name='dealer_rights', - name='user', - ), - migrations.DeleteModel( - name='Dealer_Setting', - ), - migrations.DeleteModel( - name='Dealer_Rights', - ), - ] diff --git a/app/migrations/0002_cloud_instance_customer_wallet_datacenter_and_more.py b/app/migrations/0002_cloud_instance_customer_wallet_datacenter_and_more.py new file mode 100644 index 00000000..3e0c6bc7 --- /dev/null +++ b/app/migrations/0002_cloud_instance_customer_wallet_datacenter_and_more.py @@ -0,0 +1,1257 @@ +# Generated by Django 5.1.7 on 2026-03-24 03:55 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('app', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Cloud_Instance', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), + ('provider_instance_id', models.CharField(db_index=True, max_length=100, null=True)), + ('provider_instance_name', models.CharField(max_length=200, null=True)), + ('ip_address', models.GenericIPAddressField(null=True)), + ('ipv6_address', models.CharField(max_length=50, null=True)), + ('hostname', models.CharField(max_length=200, null=True)), + ('cpu', models.IntegerField(null=True)), + ('ram_gb', models.IntegerField(null=True)), + ('disk_gb', models.IntegerField(null=True)), + ('provisioned_at', models.DateTimeField(null=True)), + ('terminated_at', models.DateTimeField(null=True)), + ('root_password', models.CharField(max_length=300, null=True)), + ('ssh_key', models.TextField(null=True)), + ('note', models.TextField(null=True)), + ('extra_info', models.JSONField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'cloud_instance', + }, + ), + migrations.CreateModel( + name='Customer_Wallet', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('billing_mode', models.CharField(choices=[('PREPAID', 'Prepaid — Nạp trước'), ('POSTPAID', 'Postpaid — Trả sau cuối tháng')], default='PREPAID', max_length=20)), + ('balance', models.DecimalField(decimal_places=2, default=0, max_digits=20)), + ('low_balance_threshold', models.DecimalField(decimal_places=2, max_digits=20, null=True)), + ('credit_limit', models.DecimalField(decimal_places=2, max_digits=20, null=True)), + ('billing_day', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), + ], + options={ + 'db_table': 'customer_wallet', + }, + ), + migrations.CreateModel( + name='Datacenter', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('region', models.CharField(max_length=100, null=True)), + ('provider_location_id', models.CharField(max_length=50, null=True)), + ('active', models.BooleanField(default=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('country', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.country')), + ], + options={ + 'db_table': 'datacenter', + }, + ), + migrations.CreateModel( + name='Instance_Log', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('action', models.CharField(max_length=50)), + ('status', models.CharField(max_length=30)), + ('detail', models.JSONField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ], + options={ + 'db_table': 'instance_log', + }, + ), + migrations.CreateModel( + name='Instance_Status', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('en', models.CharField(max_length=100, null=True)), + ('color', models.CharField(max_length=20, null=True)), + ('index', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ], + options={ + 'db_table': 'instance_status', + }, + ), + migrations.CreateModel( + name='Invoice_Line', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('description', models.CharField(max_length=300)), + ('period_from', models.DateField()), + ('period_to', models.DateField()), + ('unit_price', models.DecimalField(decimal_places=2, max_digits=20)), + ('quantity', models.DecimalField(decimal_places=2, default=1, max_digits=10)), + ('discount_amount', models.DecimalField(decimal_places=2, default=0, max_digits=20, null=True)), + ('line_total', models.DecimalField(decimal_places=2, max_digits=20)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ], + options={ + 'db_table': 'invoice_line', + }, + ), + migrations.CreateModel( + name='Payment_Receipt', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), + ('amount', models.DecimalField(decimal_places=2, max_digits=20)), + ('payment_date', models.DateField()), + ('ref_code', models.CharField(max_length=100, null=True)), + ('note', models.TextField(null=True)), + ('approve_time', models.DateTimeField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('approver', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), + ('creator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), + ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), + ], + options={ + 'db_table': 'payment_receipt', + }, + ), + migrations.CreateModel( + name='Plan_Datacenter', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('datacenter', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.datacenter')), + ], + options={ + 'db_table': 'plan_datacenter', + }, + ), + migrations.CreateModel( + name='Postpaid_Billing_Cycle', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), + ('period_from', models.DateField()), + ('period_to', models.DateField()), + ('total_usage_amount', models.DecimalField(decimal_places=2, max_digits=20, null=True)), + ('status', models.CharField(choices=[('OPEN', 'Đang tích lũy usage'), ('INVOICED', 'Đã xuất Invoice'), ('PAID', 'Đã thanh toán')], default='OPEN', max_length=20)), + ('closed_at', models.DateTimeField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), + ], + options={ + 'db_table': 'postpaid_billing_cycle', + }, + ), + migrations.CreateModel( + name='Pricing_Tier', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('months', models.IntegerField()), + ('discount_percent', models.DecimalField(decimal_places=2, default=0, max_digits=5)), + ('index', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'pricing_tier', + }, + ), + migrations.CreateModel( + name='Provider', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('website', models.URLField(null=True)), + ('api_endpoint', models.CharField(max_length=200, null=True)), + ('partner_id', models.CharField(max_length=100, null=True)), + ('contact_email', models.CharField(max_length=100, null=True)), + ('note', models.TextField(null=True)), + ('active', models.BooleanField(default=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'provider', + }, + ), + migrations.CreateModel( + name='Provider_Credential', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.CharField(max_length=100)), + ('api_key', models.CharField(max_length=500)), + ('api_secret', models.CharField(max_length=500, null=True)), + ('active', models.BooleanField(default=True)), + ('note', models.TextField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('provider', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='credentials', to='app.provider')), + ], + options={ + 'db_table': 'provider_credential', + }, + ), + migrations.CreateModel( + name='Provider_Invoice', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=20, null=True, unique=True)), + ('period_from', models.DateField()), + ('period_to', models.DateField()), + ('total_amount', models.DecimalField(decimal_places=2, max_digits=20)), + ('note', models.TextField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), + ('document', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.file')), + ('provider', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='provider_invoices', to='app.provider')), + ('status', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_status')), + ], + options={ + 'db_table': 'provider_invoice', + }, + ), + migrations.CreateModel( + name='Provider_Invoice_Line', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('description', models.CharField(max_length=300)), + ('amount', models.DecimalField(decimal_places=2, max_digits=20)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ], + options={ + 'db_table': 'provider_invoice_line', + }, + ), + migrations.CreateModel( + name='Service_Category', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('en', models.CharField(max_length=100, null=True)), + ('icon', models.CharField(max_length=100, null=True)), + ('index', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'service_category', + }, + ), + migrations.CreateModel( + name='Service_Plan', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=200)), + ('billing_type', models.CharField(choices=[('SUBSCRIPTION', 'Subscription'), ('PAYG', 'Pay-as-you-go'), ('BOTH', 'Cả hai')], default='SUBSCRIPTION', max_length=20)), + ('cpu', models.IntegerField(null=True)), + ('ram_gb', models.IntegerField(null=True)), + ('disk_gb', models.IntegerField(null=True)), + ('bandwidth_tb', models.DecimalField(decimal_places=2, max_digits=8, null=True)), + ('storage_gb', models.IntegerField(null=True)), + ('extra_specs', models.JSONField(null=True)), + ('provider_price', models.DecimalField(decimal_places=4, max_digits=20)), + ('provider_plan_id', models.CharField(max_length=100, null=True)), + ('sell_price', models.DecimalField(decimal_places=2, max_digits=20)), + ('sell_price_hourly', models.DecimalField(decimal_places=6, max_digits=20, null=True)), + ('active', models.BooleanField(default=True)), + ('index', models.IntegerField(default=1, null=True)), + ('note', models.TextField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('category', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='plans', to='app.service_category')), + ('provider', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='plans', to='app.provider')), + ('provider_currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), + ('sell_currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), + ], + options={ + 'db_table': 'service_plan', + }, + ), + migrations.CreateModel( + name='Subscription', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), + ('billing_type', models.CharField(choices=[('SUBSCRIPTION', 'Subscription'), ('PAYG', 'Pay-as-you-go')], default='SUBSCRIPTION', max_length=20)), + ('unit_price', models.DecimalField(decimal_places=2, max_digits=20, null=True)), + ('unit_price_hourly', models.DecimalField(decimal_places=6, max_digits=20, null=True)), + ('discount_amount', models.DecimalField(decimal_places=2, default=0, max_digits=20, null=True)), + ('final_price', models.DecimalField(decimal_places=2, max_digits=20, null=True)), + ('start_date', models.DateField()), + ('end_date', models.DateField(null=True)), + ('next_billing_date', models.DateField(null=True)), + ('auto_renew', models.BooleanField(default=True)), + ('note', models.TextField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('creator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user')), + ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), + ], + options={ + 'db_table': 'subscription', + }, + ), + migrations.CreateModel( + name='Subscription_Discount', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('value', models.DecimalField(decimal_places=2, max_digits=20, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('discount', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.discount_type')), + ], + options={ + 'db_table': 'subscription_discount', + }, + ), + migrations.CreateModel( + name='Subscription_File', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('file', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.file')), + ], + options={ + 'db_table': 'subscription_file', + }, + ), + migrations.CreateModel( + name='Subscription_Note', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('detail', models.TextField()), + ('files', models.JSONField(null=True)), + ('deleted', models.BooleanField(default=False, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'db_table': 'subscription_note', + }, + ), + migrations.CreateModel( + name='Subscription_Status', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('en', models.CharField(max_length=100, null=True)), + ('color', models.CharField(max_length=20, null=True)), + ('index', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ], + options={ + 'db_table': 'subscription_status', + }, + ), + migrations.CreateModel( + name='Support_Ticket', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), + ('title', models.CharField(max_length=300)), + ('description', models.TextField()), + ('resolved_at', models.DateTimeField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('update_time', models.DateTimeField(auto_now=True, null=True)), + ('assignee', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.staff')), + ], + options={ + 'db_table': 'support_ticket', + }, + ), + migrations.CreateModel( + name='Ticket_Priority', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('en', models.CharField(max_length=100, null=True)), + ('color', models.CharField(max_length=20, null=True)), + ('index', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ], + options={ + 'db_table': 'ticket_priority', + }, + ), + migrations.CreateModel( + name='Ticket_Reply', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField()), + ('is_internal', models.BooleanField(default=False)), + ('files', models.JSONField(null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ], + options={ + 'db_table': 'ticket_reply', + }, + ), + migrations.CreateModel( + name='Ticket_Status', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('en', models.CharField(max_length=100, null=True)), + ('color', models.CharField(max_length=20, null=True)), + ('index', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ], + options={ + 'db_table': 'ticket_status', + }, + ), + migrations.CreateModel( + name='Usage_Record', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('period_from', models.DateTimeField()), + ('period_to', models.DateTimeField()), + ('hours', models.DecimalField(decimal_places=4, max_digits=10)), + ('unit_price_hourly', models.DecimalField(decimal_places=6, max_digits=20)), + ('amount', models.DecimalField(decimal_places=4, max_digits=20)), + ('charged', models.BooleanField(default=False)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ('currency', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency')), + ], + options={ + 'db_table': 'usage_record', + }, + ), + migrations.CreateModel( + name='Wallet_Transaction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(db_index=True, max_length=20, null=True, unique=True)), + ('amount', models.DecimalField(decimal_places=2, max_digits=20)), + ('balance_before', models.DecimalField(decimal_places=2, max_digits=20)), + ('balance_after', models.DecimalField(decimal_places=2, max_digits=20)), + ('description', models.CharField(max_length=300)), + ('ref_code', models.CharField(max_length=100, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ], + options={ + 'db_table': 'wallet_transaction', + }, + ), + migrations.CreateModel( + name='Wallet_Transaction_Type', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=30, unique=True)), + ('name', models.CharField(max_length=100)), + ('en', models.CharField(max_length=100, null=True)), + ('index', models.IntegerField(default=1, null=True)), + ('create_time', models.DateTimeField(auto_now_add=True, null=True)), + ], + options={ + 'db_table': 'wallet_transaction_type', + }, + ), + migrations.RemoveField( + model_name='cart', + name='dealer', + ), + migrations.RemoveField( + model_name='product', + name='cart', + ), + migrations.AlterUniqueTogether( + name='co_ownership', + unique_together=None, + ), + migrations.RemoveField( + model_name='co_ownership', + name='people', + ), + migrations.RemoveField( + model_name='co_ownership', + name='transaction', + ), + migrations.RemoveField( + model_name='contract', + name='signature', + ), + migrations.RemoveField( + model_name='contract', + name='status', + ), + migrations.RemoveField( + model_name='contract', + name='transaction', + ), + migrations.RemoveField( + model_name='contract', + name='user', + ), + migrations.RemoveField( + model_name='dealer', + name='user', + ), + migrations.RemoveField( + model_name='product', + name='dealer', + ), + migrations.RemoveField( + model_name='customer', + name='dealer', + ), + migrations.RemoveField( + model_name='product', + name='direction', + ), + migrations.DeleteModel( + name='Duration', + ), + migrations.RemoveField( + model_name='transaction_gift', + name='gift', + ), + migrations.RemoveField( + model_name='project', + name='investor', + ), + migrations.DeleteModel( + name='Land_Type', + ), + migrations.DeleteModel( + name='Ownership_Type', + ), + migrations.AlterUniqueTogether( + name='payment_plan', + unique_together=None, + ), + migrations.RemoveField( + model_name='payment_plan', + name='policy', + ), + migrations.RemoveField( + model_name='payment_plan', + name='type', + ), + migrations.RemoveField( + model_name='payment_schedule', + name='status', + ), + migrations.RemoveField( + model_name='payment_schedule', + name='txn_detail', + ), + migrations.RemoveField( + model_name='payment_schedule', + name='type', + ), + migrations.RemoveField( + model_name='payment_schedule', + name='updater', + ), + migrations.RemoveField( + model_name='invoice', + name='payment', + ), + migrations.RemoveField( + model_name='phase_doctype', + name='doctype', + ), + migrations.RemoveField( + model_name='phase_doctype', + name='phase', + ), + migrations.RemoveField( + model_name='product', + name='policy', + ), + migrations.RemoveField( + model_name='product', + name='project', + ), + migrations.RemoveField( + model_name='product', + name='status', + ), + migrations.RemoveField( + model_name='product', + name='type', + ), + migrations.RemoveField( + model_name='product', + name='zone_type', + ), + migrations.RemoveField( + model_name='internal_entry', + name='product', + ), + migrations.RemoveField( + model_name='transaction', + name='product', + ), + migrations.RemoveField( + model_name='product_note', + name='ref', + ), + migrations.AlterUniqueTogether( + name='product_booked', + unique_together=None, + ), + migrations.RemoveField( + model_name='product_booked', + name='product', + ), + migrations.AlterUniqueTogether( + name='product_file', + unique_together=None, + ), + migrations.RemoveField( + model_name='product_file', + name='product', + ), + migrations.RemoveField( + model_name='product_booked', + name='transaction', + ), + migrations.RemoveField( + model_name='product_file', + name='file', + ), + migrations.RemoveField( + model_name='product_note', + name='user', + ), + migrations.RemoveField( + model_name='product_status', + name='sale_status', + ), + migrations.RemoveField( + model_name='project', + name='status', + ), + migrations.AlterUniqueTogether( + name='project_file', + unique_together=None, + ), + migrations.RemoveField( + model_name='project_file', + name='project', + ), + migrations.RemoveField( + model_name='project_file', + name='file', + ), + migrations.SeparateDatabaseAndState( + state_operations=[ + migrations.AlterUniqueTogether( + name='rule', + unique_together=None, + ), + migrations.RemoveField( + model_name='rule', + name='step_action', + ), + migrations.RemoveField( + model_name='rule', + name='utility', + ), + ], + database_operations=[], + ), + migrations.RemoveField( + model_name='sale_policy', + name='method', + ), + migrations.RemoveField( + model_name='transaction', + name='policy', + ), + migrations.SeparateDatabaseAndState( + state_operations=[ + migrations.AlterUniqueTogether( + name='stepaction', + unique_together=None, + ), + migrations.RemoveField( + model_name='stepaction', + name='workflow', + ), + migrations.RemoveField( + model_name='workflow', + name='initial_step', + ), + ], + database_operations=[], + ), + migrations.RemoveField( + model_name='transaction', + name='customer', + ), + migrations.RemoveField( + model_name='transaction', + name='phase', + ), + migrations.AlterUniqueTogether( + name='transaction_current', + unique_together=None, + ), + migrations.RemoveField( + model_name='transaction_current', + name='transaction', + ), + migrations.RemoveField( + model_name='transaction_discount', + name='transaction', + ), + migrations.RemoveField( + model_name='transaction_detail', + name='transaction', + ), + migrations.RemoveField( + model_name='transaction_gift', + name='transaction', + ), + migrations.RemoveField( + model_name='transaction_current', + name='detail', + ), + migrations.RemoveField( + model_name='transaction_detail', + name='approver', + ), + migrations.RemoveField( + model_name='transaction_detail', + name='creator', + ), + migrations.RemoveField( + model_name='transaction_detail', + name='customer_new', + ), + migrations.RemoveField( + model_name='transaction_detail', + name='customer_old', + ), + migrations.RemoveField( + model_name='transaction_detail', + name='phase', + ), + migrations.RemoveField( + model_name='transaction_detail', + name='status', + ), + migrations.AlterUniqueTogether( + name='transaction_file', + unique_together=None, + ), + migrations.RemoveField( + model_name='transaction_file', + name='txn_detail', + ), + migrations.RemoveField( + model_name='transaction_discount', + name='discount', + ), + migrations.RemoveField( + model_name='transaction_discount', + name='type', + ), + migrations.RemoveField( + model_name='transaction_file', + name='file', + ), + migrations.DeleteModel( + name='Transaction_Type', + ), + migrations.AddField( + model_name='customer', + name='sale_staff', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.staff'), + ), + migrations.AddField( + model_name='customer', + name='segment', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.customer_segment'), + ), + migrations.AddField( + model_name='customer', + name='user', + field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='customer_profile', to='app.user'), + ), + migrations.AddField( + model_name='internal_entry', + name='invoice', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.invoice'), + ), + migrations.AddField( + model_name='invoice', + name='create_time', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='invoice', + name='creator', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), + ), + migrations.AddField( + model_name='invoice', + name='currency', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.currency'), + ), + migrations.AddField( + model_name='invoice', + name='customer', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='invoices', to='app.customer'), + ), + migrations.AddField( + model_name='invoice', + name='due_date', + field=models.DateField(null=True), + ), + migrations.AddField( + model_name='invoice', + name='issue_date', + field=models.DateField(null=True), + ), + migrations.AddField( + model_name='invoice', + name='paid_amount', + field=models.DecimalField(decimal_places=2, default=0, max_digits=20, null=True), + ), + migrations.AddField( + model_name='invoice', + name='payment_method', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_method'), + ), + migrations.AddField( + model_name='invoice', + name='remain_amount', + field=models.DecimalField(decimal_places=2, max_digits=20, null=True), + ), + migrations.AddField( + model_name='invoice', + name='status', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_status'), + ), + migrations.AddField( + model_name='invoice', + name='update_time', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='email_job', + name='model_name', + field=models.CharField(help_text='e.g., app.Subscription', max_length=100), + ), + migrations.AddField( + model_name='customer_wallet', + name='customer', + field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='wallet', to='app.customer'), + ), + migrations.AddField( + model_name='cloud_instance', + name='datacenter', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.datacenter'), + ), + migrations.AddField( + model_name='instance_log', + name='instance', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='logs', to='app.cloud_instance'), + ), + migrations.AddField( + model_name='instance_log', + name='performed_by', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), + ), + migrations.AddField( + model_name='cloud_instance', + name='status', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.instance_status'), + ), + migrations.AddField( + model_name='invoice_line', + name='invoice', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='lines', to='app.invoice'), + ), + migrations.AddField( + model_name='payment_receipt', + name='customer', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='receipts', to='app.customer'), + ), + migrations.AddField( + model_name='payment_receipt', + name='invoice', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='receipts', to='app.invoice'), + ), + migrations.AddField( + model_name='payment_receipt', + name='payment_method', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_method'), + ), + migrations.AddField( + model_name='payment_receipt', + name='status', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_status'), + ), + migrations.AddField( + model_name='postpaid_billing_cycle', + name='customer', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='billing_cycles', to='app.customer'), + ), + migrations.AddField( + model_name='postpaid_billing_cycle', + name='invoice', + field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='billing_cycle', to='app.invoice'), + ), + migrations.AddField( + model_name='datacenter', + name='provider', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='datacenters', to='app.provider'), + ), + migrations.AddField( + model_name='cloud_instance', + name='provider', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.provider'), + ), + migrations.AddField( + model_name='internal_entry', + name='provider_invoice', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.provider_invoice'), + ), + migrations.AddField( + model_name='provider_invoice_line', + name='instance', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.cloud_instance'), + ), + migrations.AddField( + model_name='provider_invoice_line', + name='provider_invoice', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='lines', to='app.provider_invoice'), + ), + migrations.AddField( + model_name='plan_datacenter', + name='plan', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='plan_dcs', to='app.service_plan'), + ), + migrations.AddField( + model_name='subscription', + name='customer', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='subscriptions', to='app.customer'), + ), + migrations.AddField( + model_name='subscription', + name='datacenter', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.datacenter'), + ), + migrations.AddField( + model_name='subscription', + name='payment_method', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.payment_method'), + ), + migrations.AddField( + model_name='subscription', + name='plan', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='subscriptions', to='app.service_plan'), + ), + migrations.AddField( + model_name='subscription', + name='pricing_tier', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.pricing_tier'), + ), + migrations.AddField( + model_name='subscription', + name='updater', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), + ), + migrations.AddField( + model_name='invoice_line', + name='subscription', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='invoice_lines', to='app.subscription'), + ), + migrations.AddField( + model_name='cloud_instance', + name='subscription', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='instances', to='app.subscription'), + ), + migrations.AddField( + model_name='internal_entry', + name='subscription', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.subscription'), + ), + migrations.AddField( + model_name='subscription_discount', + name='subscription', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='discounts', to='app.subscription'), + ), + migrations.AddField( + model_name='subscription_discount', + name='type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.value_type'), + ), + migrations.AddField( + model_name='subscription_file', + name='ref', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='subfile', to='app.subscription'), + ), + migrations.AddField( + model_name='subscription_note', + name='ref', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='subnote', to='app.subscription'), + ), + migrations.AddField( + model_name='subscription_note', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), + ), + migrations.AddField( + model_name='subscription', + name='status', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.subscription_status'), + ), + migrations.AddField( + model_name='support_ticket', + name='customer', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='tickets', to='app.customer'), + ), + migrations.AddField( + model_name='support_ticket', + name='instance', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='tickets', to='app.cloud_instance'), + ), + migrations.AddField( + model_name='support_ticket', + name='subscription', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='tickets', to='app.subscription'), + ), + migrations.AddField( + model_name='support_ticket', + name='priority', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.ticket_priority'), + ), + migrations.AddField( + model_name='ticket_reply', + name='ticket', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='replies', to='app.support_ticket'), + ), + migrations.AddField( + model_name='ticket_reply', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), + ), + migrations.AddField( + model_name='support_ticket', + name='status', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.ticket_status'), + ), + migrations.AddField( + model_name='usage_record', + name='instance', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='usage_records', to='app.cloud_instance'), + ), + migrations.AddField( + model_name='usage_record', + name='postpaid_invoice', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='usage_records', to='app.invoice'), + ), + migrations.AddField( + model_name='usage_record', + name='subscription', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='usage_records', to='app.subscription'), + ), + migrations.AddField( + model_name='wallet_transaction', + name='invoice', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='wallet_txns', to='app.invoice'), + ), + migrations.AddField( + model_name='wallet_transaction', + name='performed_by', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.user'), + ), + migrations.AddField( + model_name='wallet_transaction', + name='subscription', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='wallet_txns', to='app.subscription'), + ), + migrations.AddField( + model_name='wallet_transaction', + name='wallet', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transactions', to='app.customer_wallet'), + ), + migrations.AddField( + model_name='usage_record', + name='wallet_transaction', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='usage_records', to='app.wallet_transaction'), + ), + migrations.AddField( + model_name='wallet_transaction', + name='type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='app.wallet_transaction_type'), + ), + migrations.DeleteModel( + name='Cart', + ), + migrations.DeleteModel( + name='Co_Ownership', + ), + migrations.DeleteModel( + name='Contract_Status', + ), + migrations.DeleteModel( + name='Contract', + ), + migrations.DeleteModel( + name='Dealer', + ), + migrations.DeleteModel( + name='Direction', + ), + migrations.DeleteModel( + name='Gift', + ), + migrations.DeleteModel( + name='Investor', + ), + migrations.DeleteModel( + name='Payment_Plan', + ), + migrations.DeleteModel( + name='Payment_Schedule', + ), + migrations.DeleteModel( + name='Phase_Doctype', + ), + migrations.DeleteModel( + name='Product_Type', + ), + migrations.DeleteModel( + name='Zone_Type', + ), + migrations.DeleteModel( + name='Product', + ), + migrations.DeleteModel( + name='Product_Booked', + ), + migrations.DeleteModel( + name='Product_File', + ), + migrations.DeleteModel( + name='Product_Note', + ), + migrations.DeleteModel( + name='Product_Status', + ), + migrations.DeleteModel( + name='Sale_Status', + ), + migrations.DeleteModel( + name='Project_Status', + ), + migrations.DeleteModel( + name='Project', + ), + migrations.DeleteModel( + name='Project_File', + ), + migrations.SeparateDatabaseAndState( + state_operations=[ + migrations.DeleteModel( + name='Rule', + ), + ], + database_operations=[], + ), + migrations.SeparateDatabaseAndState( + state_operations=[ + migrations.DeleteModel( + name='Utility', + ), + ], + database_operations=[], + ), + migrations.DeleteModel( + name='Sale_Policy', + ), + migrations.SeparateDatabaseAndState( + state_operations=[ + migrations.DeleteModel( + name='StepAction', + ), + ], + database_operations=[], + ), + migrations.SeparateDatabaseAndState( + state_operations=[ + migrations.DeleteModel( + name='Workflow', + ), + ], + database_operations=[], + ), + migrations.DeleteModel( + name='Transaction', + ), + migrations.DeleteModel( + name='Transaction_Gift', + ), + migrations.DeleteModel( + name='Transaction_Current', + ), + migrations.DeleteModel( + name='Transaction_Phase', + ), + migrations.DeleteModel( + name='Transaction_Status', + ), + migrations.DeleteModel( + name='Transaction_Detail', + ), + migrations.DeleteModel( + name='Transaction_Discount', + ), + migrations.DeleteModel( + name='Transaction_File', + ), + migrations.AlterUniqueTogether( + name='postpaid_billing_cycle', + unique_together={('customer', 'period_from')}, + ), + migrations.AlterUniqueTogether( + name='plan_datacenter', + unique_together={('plan', 'datacenter')}, + ), + migrations.AlterUniqueTogether( + name='subscription_file', + unique_together={('ref', 'file')}, + ), + migrations.AddIndex( + model_name='usage_record', + index=models.Index(fields=['subscription', 'period_from'], name='usage_recor_subscri_b0fb0c_idx'), + ), + ] \ No newline at end of file diff --git a/app/migrations/0003_alter_stepaction_unique_together_and_more.py b/app/migrations/0003_alter_stepaction_unique_together_and_more.py deleted file mode 100644 index 506e4290..00000000 --- a/app/migrations/0003_alter_stepaction_unique_together_and_more.py +++ /dev/null @@ -1,37 +0,0 @@ -# Generated by Django 5.1.7 on 2026-03-19 05:05 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('app', '0002_alter_dealer_rights_unique_together_and_more'), - ] - - operations = [ - migrations.AlterUniqueTogether( - name='stepaction', - unique_together=None, - ), - migrations.RemoveField( - model_name='stepaction', - name='workflow', - ), - migrations.RemoveField( - model_name='workflow', - name='initial_step', - ), - migrations.DeleteModel( - name='Rule', - ), - migrations.DeleteModel( - name='Utility', - ), - migrations.DeleteModel( - name='StepAction', - ), - migrations.DeleteModel( - name='Workflow', - ), - ] diff --git a/app/migrations/__pycache__/0001_initial.cpython-313.pyc b/app/migrations/__pycache__/0001_initial.cpython-313.pyc index 0013114c..2dd0ad4a 100644 Binary files a/app/migrations/__pycache__/0001_initial.cpython-313.pyc and b/app/migrations/__pycache__/0001_initial.cpython-313.pyc differ diff --git a/envdev.py b/envdev.py index a23b54f3..70fde1e7 100755 --- a/envdev.py +++ b/envdev.py @@ -10,8 +10,8 @@ def search_text(file, text, new_text): f.write(content) file = './api/settings.py' -text1 = "'PORT': '6433'" -newtext1 = "'PORT': '6432'" +text1 = "'PORT': '5423'" +newtext1 = "'PORT': '5423'" search_text(file, text1, newtext1) text1 = "MODE = 'prod'" diff --git a/migration.sh b/migration.sh index ab863021..b5ffc93c 100755 --- a/migration.sh +++ b/migration.sh @@ -1,4 +1,3 @@ -python3 envdev.py python3 manage.py makemigrations python3 manage.py migrate sh genmodel.sh