diff --git a/db.sqlite3-shm b/db.sqlite3-shm deleted file mode 100644 index 87689361..00000000 Binary files a/db.sqlite3-shm and /dev/null differ diff --git a/db.sqlite3-wal b/db.sqlite3-wal deleted file mode 100644 index e69de29b..00000000 diff --git a/db.sqlite3.backup b/db.sqlite3.backup new file mode 100644 index 00000000..3c7db0c6 Binary files /dev/null and b/db.sqlite3.backup differ diff --git a/haikalbot/migrations/0001_initial.py b/haikalbot/migrations/0001_initial.py index b85002cb..9359116f 100644 --- a/haikalbot/migrations/0001_initial.py +++ b/haikalbot/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.1.4 on 2025-01-12 17:20 +# Generated by Django 4.2.17 on 2025-01-21 13:59 from django.db import migrations, models diff --git a/haikalbot/migrations/0002_initial.py b/haikalbot/migrations/0002_initial.py index 46ca49a3..42e4199a 100644 --- a/haikalbot/migrations/0002_initial.py +++ b/haikalbot/migrations/0002_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.1.4 on 2025-01-12 17:20 +# Generated by Django 4.2.17 on 2025-01-21 13:59 from django.db import migrations, models import django.db.models.deletion @@ -9,8 +9,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('inventory', '0001_initial'), ('haikalbot', '0001_initial'), + ('inventory', '0001_initial'), ] operations = [ diff --git a/inventory/migrations/0001_initial.py b/inventory/migrations/0001_initial.py index 94b54d6e..db2f426b 100644 --- a/inventory/migrations/0001_initial.py +++ b/inventory/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.1.4 on 2025-01-12 17:20 +# Generated by Django 4.2.17 on 2025-01-21 13:59 from decimal import Decimal from django.conf import settings @@ -15,6 +15,7 @@ class Migration(migrations.Migration): dependencies = [ ('contenttypes', '0002_remove_content_type_name'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('django_ledger', '0017_alter_accountmodel_unique_together_and_more'), ] @@ -42,7 +43,7 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('vin', models.CharField(max_length=17, unique=True, verbose_name='VIN')), ('year', models.IntegerField(verbose_name='Year')), - ('status', models.CharField(choices=[('available', 'Available'), ('sold', 'Sold'), ('hold', 'Hold'), ('damaged', 'Damaged'), ('reserved', 'Reserved')], default='available', max_length=10, verbose_name='Status')), + ('status', models.CharField(choices=[('available', 'Available'), ('sold', 'Sold'), ('hold', 'Hold'), ('damaged', 'Damaged'), ('reserved', 'Reserved'), ('transfer', 'Transfer')], default='available', max_length=10, verbose_name='Status')), ('stock_type', models.CharField(choices=[('new', 'New'), ('used', 'Used')], default='new', max_length=10, verbose_name='Stock Type')), ('remarks', models.TextField(blank=True, null=True, verbose_name='Remarks')), ('mileage', models.IntegerField(blank=True, null=True, verbose_name='Mileage')), @@ -74,138 +75,13 @@ class Migration(migrations.Migration): ('arabic_name', models.CharField(blank=True, max_length=255, null=True)), ('logo', models.ImageField(blank=True, null=True, upload_to='car_make', verbose_name='logo')), ('is_sa_import', models.BooleanField(default=False)), - ('car_type', models.SmallIntegerField(choices=[(1, 'Car'), (2, 'Light Commercial'), (3, 'Heavy-Duty Tractors'), (4, 'Trailers'), (5, 'Medium Trucks'), (6, 'Buses'), (20, 'Motorcycles'), (21, 'Buggy'), (22, 'Moto ATV'), (23, 'Scooters'), (24, 'Karting'), (25, 'ATV'), (26, 'Snowmobiles')])), + ('car_type', models.SmallIntegerField(blank=True, choices=[(1, 'Car'), (2, 'Light Commercial'), (3, 'Heavy-Duty Tractors'), (4, 'Trailers'), (5, 'Medium Trucks'), (6, 'Buses'), (20, 'Motorcycles'), (21, 'Buggy'), (22, 'Moto ATV'), (23, 'Scooters'), (24, 'Karting'), (25, 'ATV'), (26, 'Snowmobiles')], null=True)), ], options={ 'verbose_name': 'Make', }, bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), - migrations.CreateModel( - name='ExteriorColors', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, verbose_name='Name')), - ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), - ('rgb', models.CharField(blank=True, max_length=24, null=True, verbose_name='RGB')), - ], - options={ - 'verbose_name': 'Exterior Colors', - 'verbose_name_plural': 'Exterior Colors', - }, - bases=(models.Model, inventory.mixins.LocalizedNameMixin), - ), - migrations.CreateModel( - name='InteriorColors', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, verbose_name='Name')), - ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), - ('rgb', models.CharField(blank=True, max_length=24, null=True, verbose_name='RGB')), - ], - options={ - 'verbose_name': 'Interior Colors', - 'verbose_name_plural': 'Interior Colors', - }, - bases=(models.Model, inventory.mixins.LocalizedNameMixin), - ), - migrations.CreateModel( - name='Payment', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('amount', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='amount')), - ('payment_method', models.CharField(choices=[('cash', 'cash'), ('credit', 'credit'), ('transfer', 'transfer'), ('debit', 'debit'), ('SADAD', 'SADAD')], max_length=50, verbose_name='method')), - ('reference_number', models.CharField(blank=True, max_length=100, null=True, verbose_name='reference number')), - ('payment_date', models.DateField(auto_now_add=True, verbose_name='date')), - ], - options={ - 'verbose_name': 'payment', - 'verbose_name_plural': 'payments', - }, - ), - migrations.CreateModel( - name='SubscriptionPlan', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(help_text='Name of the subscription plan', max_length=100, unique=True)), - ('description', models.TextField()), - ('price', models.DecimalField(decimal_places=2, max_digits=10)), - ('max_users', models.PositiveIntegerField(default=1, help_text='Maximum number of users allowed')), - ('max_inventory_size', models.PositiveIntegerField(default=50, help_text='Maximum number of cars in inventory')), - ('support_level', models.CharField(choices=[('basic', 'Basic Support'), ('priority', 'Priority Support'), ('dedicated', 'Dedicated Support')], default='basic', help_text='Level of support provided', max_length=50)), - ('custom_features', models.JSONField(blank=True, help_text='Additional features specific to this plan', null=True)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ], - options={ - 'verbose_name': 'Subscription Plan', - 'verbose_name_plural': 'Subscription Plans', - }, - ), - migrations.CreateModel( - name='VatRate', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('rate', models.DecimalField(decimal_places=2, default=Decimal('0.15'), max_digits=5)), - ('is_active', models.BooleanField(default=True)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ], - ), - migrations.CreateModel( - name='Activity', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('object_id', models.PositiveIntegerField()), - ('activity_type', models.CharField(choices=[('call', 'Call'), ('sms', 'SMS'), ('email', 'Email'), ('whatsapp', 'WhatsApp'), ('visit', 'Visit'), ('add_car', 'Add Car'), ('reserve_car', 'Reserve Car'), ('remove_car', 'Remove Car'), ('create_quotation', 'Create Quotation'), ('cancel_quotation', 'Cancel Quotation'), ('create_order', 'Create Order'), ('cancel_order', 'Cancel Order'), ('create_invoice', 'Create Invoice'), ('cancel_invoice', 'Cancel Invoice')], max_length=50, verbose_name='Activity Type')), - ('notes', models.TextField(blank=True, null=True, verbose_name='Notes')), - ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), - ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), - ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), - ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='activities_created', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'Activity', - 'verbose_name_plural': 'Activities', - }, - ), - migrations.CreateModel( - name='AdditionalServices', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, verbose_name='Name')), - ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), - ('description', models.TextField(verbose_name='Description')), - ('price', models.DecimalField(decimal_places=2, max_digits=14, verbose_name='Price')), - ('taxable', models.BooleanField(default=False, verbose_name='taxable')), - ('uom', models.CharField(choices=[('EA', 'Each'), ('PR', 'Pair'), ('SET', 'Set'), ('GAL', 'Gallon'), ('L', 'Liter'), ('M', 'Meter'), ('KG', 'Kilogram'), ('HR', 'Hour'), ('BX', 'Box'), ('RL', 'Roll'), ('PKG', 'Package'), ('DZ', 'Dozen'), ('SQ_M', 'Square Meter'), ('PC', 'Piece'), ('BDL', 'Bundle')], max_length=10, verbose_name='Unit of Measurement')), - ('item', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='django_ledger.itemmodel', verbose_name='Item')), - ], - options={ - 'verbose_name': 'Additional Services', - 'verbose_name_plural': 'Additional Services', - }, - bases=(models.Model, inventory.mixins.LocalizedNameMixin), - ), - migrations.CreateModel( - name='CarFinance', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('cost_price', models.DecimalField(decimal_places=2, max_digits=14, verbose_name='Cost Price')), - ('selling_price', models.DecimalField(decimal_places=2, max_digits=14, verbose_name='Selling Price')), - ('discount_amount', models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=14, verbose_name='Discount Amount')), - ('additional_services', models.ManyToManyField(blank=True, related_name='additional_finances', to='inventory.additionalservices')), - ('car', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='finances', to='inventory.car')), - ], - options={ - 'verbose_name': 'Car Financial Details', - 'verbose_name_plural': 'Car Financial Details', - }, - ), - migrations.AddField( - model_name='car', - name='id_car_make', - field=models.ForeignKey(blank=True, db_column='id_car_make', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmake', verbose_name='Make'), - ), migrations.CreateModel( name='CarModel', fields=[ @@ -274,7 +150,6 @@ class Migration(migrations.Migration): ('email', models.EmailField(max_length=254, unique=True, verbose_name='Email')), ('national_id', models.CharField(max_length=10, unique=True, verbose_name='National ID')), ('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', unique=True, verbose_name='Phone Number')), - ('city', models.CharField(blank=True, max_length=255, verbose_name='City')), ('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Address')), ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), @@ -310,51 +185,46 @@ class Migration(migrations.Migration): ], ), migrations.CreateModel( - name='CarLocation', + name='ExteriorColors', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('description', models.TextField(blank=True, help_text='Optional description about the showroom placement.', null=True, verbose_name='Description')), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), - ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Last Updated')), - ('car', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='location', to='inventory.car', verbose_name='Car')), - ('owner', models.ForeignKey(help_text='Dealer who owns the car.', on_delete=django.db.models.deletion.CASCADE, related_name='owned_cars', to='inventory.dealer', verbose_name='Owner')), - ('showroom', models.ForeignKey(help_text='Dealer where the car is displayed (can be the owner).', on_delete=django.db.models.deletion.CASCADE, related_name='showroom_cars', to='inventory.dealer', verbose_name='Showroom')), + ('name', models.CharField(max_length=255, verbose_name='Name')), + ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), + ('rgb', models.CharField(blank=True, max_length=24, null=True, verbose_name='RGB')), ], options={ - 'verbose_name': 'Car Location', - 'verbose_name_plural': 'Car Locations', + 'verbose_name': 'Exterior Colors', + 'verbose_name_plural': 'Exterior Colors', }, + bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), - migrations.AddField( - model_name='car', - name='dealer', - field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='cars', to='inventory.dealer', verbose_name='Dealer'), - ), - migrations.AddField( - model_name='additionalservices', - name='dealer', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.dealer', verbose_name='Dealer'), + migrations.CreateModel( + name='InteriorColors', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='Name')), + ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), + ('rgb', models.CharField(blank=True, max_length=24, null=True, verbose_name='RGB')), + ], + options={ + 'verbose_name': 'Interior Colors', + 'verbose_name_plural': 'Interior Colors', + }, + bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), migrations.CreateModel( name='Lead', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(choices=[('mr', 'Mr'), ('mrs', 'Mrs'), ('ms', 'Ms'), ('miss', 'Miss'), ('dr', 'Dr'), ('prof', 'Prof'), ('prince', 'Prince'), ('princess', 'Princess'), ('company', 'Company'), ('na', 'N/A')], max_length=20, verbose_name='Title')), - ('first_name', models.CharField(max_length=50, verbose_name='First Name')), - ('last_name', models.CharField(max_length=50, verbose_name='Last Name')), - ('email', models.EmailField(db_index=True, max_length=254, unique=True, verbose_name='Email')), - ('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')), - ('salary', models.PositiveIntegerField(blank=True, null=True, verbose_name='Salary')), - ('obligations', models.PositiveIntegerField(blank=True, null=True, verbose_name='Obligations')), ('year', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='Year')), ('source', models.CharField(choices=[('referrals', 'Referrals'), ('whatsapp', 'WhatsApp'), ('showroom', 'Showroom'), ('tiktok', 'TikTok'), ('instagram', 'Instagram'), ('x', 'X'), ('facebook', 'Facebook'), ('motory', 'Motory'), ('influencers', 'Influencers'), ('youtube', 'Youtube'), ('campaign', 'Campaign')], max_length=50, verbose_name='Source')), ('channel', models.CharField(choices=[('walk_in', 'Walk In'), ('toll_free', 'Toll Free'), ('website', 'Website'), ('email', 'Email'), ('form', 'Form')], max_length=50, verbose_name='Channel')), - ('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Address')), ('city', models.CharField(max_length=50, verbose_name='City')), ('priority', models.CharField(choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High')], default='medium', max_length=10, verbose_name='Priority')), ('status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('canceled', 'Canceled')], db_index=True, default='new', max_length=50, verbose_name='Status')), ('created', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Created')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), + ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='leads', to='inventory.customer')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='leads', to='inventory.dealer')), ('id_car_make', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmake', verbose_name='Make')), ('id_car_model', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmodel', verbose_name='Model')), @@ -364,62 +234,6 @@ class Migration(migrations.Migration): 'verbose_name_plural': 'Leads', }, ), - migrations.CreateModel( - name='Customer', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(choices=[('mr', 'Mr'), ('mrs', 'Mrs'), ('ms', 'Ms'), ('miss', 'Miss'), ('dr', 'Dr'), ('prof', 'Prof'), ('prince', 'Prince'), ('princess', 'Princess'), ('company', 'Company'), ('na', 'N/A')], default='na', max_length=10, verbose_name='Title')), - ('first_name', models.CharField(max_length=50, verbose_name='First Name')), - ('middle_name', models.CharField(blank=True, max_length=50, null=True, verbose_name='Middle Name')), - ('last_name', models.CharField(max_length=50, verbose_name='Last Name')), - ('gender', models.CharField(choices=[('m', 'Male'), ('f', 'Female')], max_length=1, verbose_name='Gender')), - ('dob', models.DateField(verbose_name='Date of Birth')), - ('email', models.EmailField(max_length=254, unique=True, verbose_name='Email')), - ('national_id', models.CharField(max_length=10, unique=True, verbose_name='National ID')), - ('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', unique=True, verbose_name='Phone Number')), - ('city', models.CharField(blank=True, max_length=255, verbose_name='City')), - ('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Address')), - ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), - ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), - ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='customers', to='inventory.dealer')), - ('lead', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='converted', to='inventory.lead', verbose_name='Lead')), - ], - options={ - 'verbose_name': 'Customer', - 'verbose_name_plural': 'Customers', - }, - ), - migrations.CreateModel( - name='Notes', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('object_id', models.PositiveIntegerField()), - ('note', models.TextField(verbose_name='Note')), - ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), - ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), - ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), - ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='notes_created', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'Note', - 'verbose_name_plural': 'Notes', - }, - ), - migrations.CreateModel( - name='Notification', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('message', models.CharField(max_length=255, verbose_name='Message')), - ('is_read', models.BooleanField(default=False, verbose_name='Is Read')), - ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notifications', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'Notification', - 'verbose_name_plural': 'Notifications', - 'ordering': ['-created'], - }, - ), migrations.CreateModel( name='Organization', fields=[ @@ -431,7 +245,8 @@ class Migration(migrations.Migration): ('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')), ('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Address')), ('logo', models.ImageField(blank=True, null=True, upload_to='logos', verbose_name='Logo')), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), + ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='organizations', to='inventory.dealer')), ], options={ @@ -478,98 +293,6 @@ class Migration(migrations.Migration): ('dealer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sales', to='inventory.dealer')), ], ), - migrations.AddField( - model_name='payment', - name='quotation', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='payments', to='inventory.salequotation'), - ), - migrations.CreateModel( - name='SaleQuotationCar', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('quantity', models.PositiveIntegerField(default=1, verbose_name='Quantity')), - ('car', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.car', verbose_name='Car')), - ('quotation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='quotation_cars', to='inventory.salequotation', verbose_name='Quotation')), - ], - ), - migrations.CreateModel( - name='SalesOrder', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), - ('total_amount', models.DecimalField(decimal_places=2, max_digits=14, verbose_name='Total Amount')), - ('quotation', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='sales_order', to='inventory.salequotation', verbose_name='Quotation')), - ], - ), - migrations.CreateModel( - name='Staff', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, verbose_name='Name')), - ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), - ('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')), - ('staff_type', models.CharField(choices=[('manager', 'Manager'), ('inventory', 'Inventory'), ('accountant', 'Accountant'), ('sales', 'Sales'), ('coordinator', 'Coordinator'), ('receptionist', 'Receptionist'), ('agent', 'Agent')], max_length=255, verbose_name='Staff Type')), - ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), - ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), - ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='staff', to='inventory.dealer')), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='staff', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'Staff', - 'verbose_name_plural': 'Staff', - 'permissions': [], - }, - bases=(models.Model, inventory.mixins.LocalizedNameMixin), - managers=[ - ('objects', inventory.models.StaffUserManager()), - ], - ), - migrations.CreateModel( - name='Opportunity', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('stage', models.CharField(choices=[('prospect', 'Prospect'), ('proposal', 'Proposal'), ('negotiation', 'Negotiation'), ('closed_won', 'Closed Won'), ('closed_lost', 'Closed Lost')], max_length=20, verbose_name='Stage')), - ('status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('canceled', 'Canceled')], default='new', max_length=20, verbose_name='Status')), - ('probability', models.PositiveIntegerField(validators=[inventory.models.validate_probability])), - ('closing_date', models.DateField(verbose_name='Closing Date')), - ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), - ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), - ('closed', models.BooleanField(default=False, verbose_name='Closed')), - ('car', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='inventory.car', verbose_name='Car')), - ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='inventory.customer')), - ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='inventory.dealer')), - ('staff', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='owner', to='inventory.staff', verbose_name='Owner')), - ], - options={ - 'verbose_name': 'Opportunity', - 'verbose_name_plural': 'Opportunities', - }, - ), - migrations.CreateModel( - name='LeadStatusHistory', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('old_status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('canceled', 'Canceled')], max_length=50, verbose_name='Old Status')), - ('new_status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('canceled', 'Canceled')], max_length=50, verbose_name='New Status')), - ('changed_at', models.DateTimeField(auto_now_add=True, verbose_name='Changed At')), - ('lead', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='status_history', to='inventory.lead')), - ('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='status_changes', to='inventory.staff')), - ], - options={ - 'verbose_name': 'Lead Status History', - 'verbose_name_plural': 'Lead Status Histories', - }, - ), - migrations.AddField( - model_name='lead', - name='assigned', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned', to='inventory.staff', verbose_name='Assigned'), - ), - migrations.AddField( - model_name='customer', - name='staff', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='customer_staff', to='inventory.staff', verbose_name='Staff'), - ), migrations.CreateModel( name='Subscription', fields=[ @@ -719,7 +442,7 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=255, verbose_name='Name')), ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), - ('id_number', models.CharField(max_length=10, verbose_name='ID Number')), + ('id_number', models.CharField(max_length=10, unique=True, verbose_name='ID Number')), ('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')), ('email', models.EmailField(max_length=255, verbose_name='Email Address')), ('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Address')), @@ -820,39 +543,14 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name='lead', - name='assigned', + name='staff', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned', to='inventory.staff', verbose_name='Assigned'), ), - migrations.AddField( - model_name='lead', - name='dealer', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='leads', to='inventory.dealer'), - ), - migrations.AddField( - model_name='lead', - name='id_car_make', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmake', verbose_name='Make'), - ), - migrations.AddField( - model_name='lead', - name='id_car_model', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmodel', verbose_name='Model'), - ), migrations.AddField( model_name='customer', name='dealer', field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='customers', to='inventory.dealer'), ), - migrations.AddField( - model_name='customer', - name='lead', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='converted', to='inventory.lead', verbose_name='Lead'), - ), - migrations.AddField( - model_name='customer', - name='staff', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='customer_staff', to='inventory.staff', verbose_name='Staff'), - ), migrations.CreateModel( name='CustomCard', fields=[ @@ -881,6 +579,27 @@ class Migration(migrations.Migration): }, bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), + migrations.CreateModel( + name='CarTransfer', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('transfer_date', models.DateTimeField(auto_now_add=True, verbose_name='Transfer Date')), + ('quantity', models.IntegerField(default=1, verbose_name='Quantity')), + ('remarks', models.TextField(blank=True, null=True, verbose_name='Remarks')), + ('status', models.CharField(default='draft', max_length=10, verbose_name=[('draft', 'Draft'), ('approved', 'Approved'), ('pending', 'Pending'), ('accepted', 'Accepted'), ('success', 'Success'), ('reject', 'Reject')])), + ('is_approved', models.BooleanField(default=False)), + ('active', models.BooleanField(default=True)), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')), + ('car', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transfer_logs', to='inventory.car', verbose_name='Car')), + ('from_dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transfers_out', to='inventory.dealer', verbose_name='From Dealer')), + ('to_dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transfers_in', to='inventory.dealer', verbose_name='To Dealer')), + ], + options={ + 'verbose_name': 'Car Transfer Log', + 'verbose_name_plural': 'Car Transfer Logs', + }, + ), migrations.CreateModel( name='CarSpecificationValue', fields=[ diff --git a/inventory/migrations/0002_alter_carmake_car_type.py b/inventory/migrations/0002_alter_carmake_car_type.py deleted file mode 100644 index 06e7827a..00000000 --- a/inventory/migrations/0002_alter_carmake_car_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-13 10:20 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='carmake', - name='car_type', - field=models.SmallIntegerField(blank=True, choices=[], null=True), - ), - ] diff --git a/inventory/migrations/0003_alter_carmake_car_type.py b/inventory/migrations/0003_alter_carmake_car_type.py deleted file mode 100644 index c701974c..00000000 --- a/inventory/migrations/0003_alter_carmake_car_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-14 12:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0002_alter_carmake_car_type'), - ] - - operations = [ - migrations.AlterField( - model_name='carmake', - name='car_type', - field=models.SmallIntegerField(blank=True, choices=[(1, 'Car'), (2, 'Light Commercial'), (3, 'Heavy-Duty Tractors'), (4, 'Trailers'), (5, 'Medium Trucks'), (6, 'Buses'), (20, 'Motorcycles'), (21, 'Buggy'), (22, 'Moto ATV'), (23, 'Scooters'), (24, 'Karting'), (25, 'ATV'), (26, 'Snowmobiles')], null=True), - ), - ] diff --git a/inventory/migrations/0004_rename_assigned_lead_staff_remove_customer_city_and_more.py b/inventory/migrations/0004_rename_assigned_lead_staff_remove_customer_city_and_more.py deleted file mode 100644 index 74725067..00000000 --- a/inventory/migrations/0004_rename_assigned_lead_staff_remove_customer_city_and_more.py +++ /dev/null @@ -1,90 +0,0 @@ -# Generated by Django 5.1.4 on 2025-01-17 00:20 - -import django.db.models.deletion -import django.utils.timezone -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0003_alter_carmake_car_type'), - ] - - operations = [ - migrations.RenameField( - model_name='lead', - old_name='assigned', - new_name='staff', - ), - migrations.RemoveField( - model_name='customer', - name='city', - ), - migrations.RemoveField( - model_name='customer', - name='lead', - ), - migrations.RemoveField( - model_name='customer', - name='staff', - ), - migrations.RemoveField( - model_name='lead', - name='address', - ), - migrations.RemoveField( - model_name='lead', - name='email', - ), - migrations.RemoveField( - model_name='lead', - name='first_name', - ), - migrations.RemoveField( - model_name='lead', - name='last_name', - ), - migrations.RemoveField( - model_name='lead', - name='obligations', - ), - migrations.RemoveField( - model_name='lead', - name='phone_number', - ), - migrations.RemoveField( - model_name='lead', - name='salary', - ), - migrations.RemoveField( - model_name='lead', - name='title', - ), - migrations.RemoveField( - model_name='organization', - name='created_at', - ), - migrations.AddField( - model_name='lead', - name='customer', - field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='leads', to='inventory.customer'), - preserve_default=False, - ), - migrations.AddField( - model_name='organization', - name='created', - field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now, verbose_name='Created'), - preserve_default=False, - ), - migrations.AddField( - model_name='organization', - name='updated', - field=models.DateTimeField(auto_now=True, verbose_name='Updated'), - ), - migrations.AlterField( - model_name='representative', - name='id_number', - field=models.CharField(max_length=10, unique=True, verbose_name='ID Number'), - ), - ] diff --git a/inventory/migrations/0005_merge_20250119_1555.py b/inventory/migrations/0005_merge_20250119_1555.py deleted file mode 100644 index 35d879d8..00000000 --- a/inventory/migrations/0005_merge_20250119_1555.py +++ /dev/null @@ -1,13 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-19 12:55 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0004_rename_assigned_lead_staff_remove_customer_city_and_more'), - ] - - operations = [ - ] diff --git a/inventory/migrations/0006_cartransferlog_delete_invoicemodelbase.py b/inventory/migrations/0006_cartransferlog_delete_invoicemodelbase.py deleted file mode 100644 index 32cf79f2..00000000 --- a/inventory/migrations/0006_cartransferlog_delete_invoicemodelbase.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-19 14:01 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0005_merge_20250119_1555'), - ] - - operations = [ - migrations.CreateModel( - name='CarTransferLog', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('transfer_date', models.DateTimeField(auto_now_add=True, verbose_name='Transfer Date')), - ('remarks', models.TextField(blank=True, null=True, verbose_name='Remarks')), - ('cars', models.ManyToManyField(related_name='transfer_logs', to='inventory.car', verbose_name='Cars')), - ('from_dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transfers_out', to='inventory.dealer', verbose_name='From Dealer')), - ('to_dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transfers_in', to='inventory.dealer', verbose_name='To Dealer')), - ], - options={ - 'verbose_name': 'Car Transfer Log', - 'verbose_name_plural': 'Car Transfer Logs', - }, - ), - ] diff --git a/inventory/migrations/0007_remove_cartransferlog_cars_cartransferlog_car.py b/inventory/migrations/0007_remove_cartransferlog_cars_cartransferlog_car.py deleted file mode 100644 index 5c5ddb0e..00000000 --- a/inventory/migrations/0007_remove_cartransferlog_cars_cartransferlog_car.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-19 14:15 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0006_cartransferlog_delete_invoicemodelbase'), - ] - - operations = [ - migrations.RemoveField( - model_name='cartransferlog', - name='cars', - ), - migrations.AddField( - model_name='cartransferlog', - name='car', - field=models.ForeignKey(default=4, on_delete=django.db.models.deletion.CASCADE, related_name='transfer_logs', to='inventory.car', verbose_name='Car'), - preserve_default=False, - ), - ] diff --git a/inventory/migrations/0008_cartransferlog_created_at_cartransferlog_is_approved_and_more.py b/inventory/migrations/0008_cartransferlog_created_at_cartransferlog_is_approved_and_more.py deleted file mode 100644 index 6f16a3ea..00000000 --- a/inventory/migrations/0008_cartransferlog_created_at_cartransferlog_is_approved_and_more.py +++ /dev/null @@ -1,35 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-19 14:29 - -import datetime -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0007_remove_cartransferlog_cars_cartransferlog_car'), - ] - - operations = [ - migrations.AddField( - model_name='cartransferlog', - name='created_at', - field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2025, 1, 19, 14, 29, 29, 771881, tzinfo=datetime.timezone.utc), verbose_name='Created At'), - preserve_default=False, - ), - migrations.AddField( - model_name='cartransferlog', - name='is_approved', - field=models.BooleanField(default=False), - ), - migrations.AddField( - model_name='cartransferlog', - name='status', - field=models.CharField(default='pending', max_length=10, verbose_name=[('draft', 'Draft'), ('approved', 'Approved'), ('pending', 'Pending'), ('success', 'Success'), ('failure', 'Failure')]), - ), - migrations.AddField( - model_name='cartransferlog', - name='updated_at', - field=models.DateTimeField(auto_now=True, verbose_name='Updated At'), - ), - ] diff --git a/inventory/migrations/0009_cartransfer_delete_cartransferlog.py b/inventory/migrations/0009_cartransfer_delete_cartransferlog.py deleted file mode 100644 index 17a1981a..00000000 --- a/inventory/migrations/0009_cartransfer_delete_cartransferlog.py +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-19 14:31 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0008_cartransferlog_created_at_cartransferlog_is_approved_and_more'), - ] - - operations = [ - migrations.CreateModel( - name='CarTransfer', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('transfer_date', models.DateTimeField(auto_now_add=True, verbose_name='Transfer Date')), - ('remarks', models.TextField(blank=True, null=True, verbose_name='Remarks')), - ('status', models.CharField(default='draft', max_length=10, verbose_name=[('draft', 'Draft'), ('approved', 'Approved'), ('pending', 'Pending'), ('success', 'Success'), ('failure', 'Failure')])), - ('is_approved', models.BooleanField(default=False)), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), - ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')), - ('car', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transfer_logs', to='inventory.car', verbose_name='Car')), - ('from_dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transfers_out', to='inventory.dealer', verbose_name='From Dealer')), - ('to_dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transfers_in', to='inventory.dealer', verbose_name='To Dealer')), - ], - options={ - 'verbose_name': 'Car Transfer Log', - 'verbose_name_plural': 'Car Transfer Logs', - }, - ), - migrations.DeleteModel( - name='CarTransferLog', - ), - ] diff --git a/inventory/migrations/0010_cartransfer_active_alter_car_status.py b/inventory/migrations/0010_cartransfer_active_alter_car_status.py deleted file mode 100644 index ca3eff35..00000000 --- a/inventory/migrations/0010_cartransfer_active_alter_car_status.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-19 15:20 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0009_cartransfer_delete_cartransferlog'), - ] - - operations = [ - migrations.AddField( - model_name='cartransfer', - name='active', - field=models.BooleanField(default=True), - ), - migrations.AlterField( - model_name='car', - name='status', - field=models.CharField(choices=[('available', 'Available'), ('sold', 'Sold'), ('hold', 'Hold'), ('damaged', 'Damaged'), ('reserved', 'Reserved'), ('transfer', 'Transfer')], default='available', max_length=10, verbose_name='Status'), - ), - ] diff --git a/inventory/migrations/0011_alter_cartransfer_status.py b/inventory/migrations/0011_alter_cartransfer_status.py deleted file mode 100644 index 46056559..00000000 --- a/inventory/migrations/0011_alter_cartransfer_status.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-20 08:11 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0010_cartransfer_active_alter_car_status'), - ] - - operations = [ - migrations.AlterField( - model_name='cartransfer', - name='status', - field=models.CharField(default='draft', max_length=10, verbose_name=[('draft', 'Draft'), ('approved', 'Approved'), ('pending', 'Pending'), ('accept', 'Accept'), ('success', 'Success'), ('failure', 'Failure')]), - ), - ] diff --git a/inventory/migrations/0012_cartransfer_quantity.py b/inventory/migrations/0012_cartransfer_quantity.py deleted file mode 100644 index a459a94a..00000000 --- a/inventory/migrations/0012_cartransfer_quantity.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-20 08:21 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0011_alter_cartransfer_status'), - ] - - operations = [ - migrations.AddField( - model_name='cartransfer', - name='quantity', - field=models.IntegerField(default=1, verbose_name='Quantity'), - ), - ] diff --git a/inventory/migrations/0013_alter_cartransfer_status.py b/inventory/migrations/0013_alter_cartransfer_status.py deleted file mode 100644 index c48106a3..00000000 --- a/inventory/migrations/0013_alter_cartransfer_status.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-20 09:17 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0012_cartransfer_quantity'), - ] - - operations = [ - migrations.AlterField( - model_name='cartransfer', - name='status', - field=models.CharField(default='draft', max_length=10, verbose_name=[('draft', 'Draft'), ('approved', 'Approved'), ('pending', 'Pending'), ('accept', 'Accept'), ('success', 'Success'), ('reject', 'Reject')]), - ), - ] diff --git a/inventory/migrations/0014_alter_cartransfer_status.py b/inventory/migrations/0014_alter_cartransfer_status.py deleted file mode 100644 index 7ec687ed..00000000 --- a/inventory/migrations/0014_alter_cartransfer_status.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.17 on 2025-01-21 08:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0013_alter_cartransfer_status'), - ] - - operations = [ - migrations.AlterField( - model_name='cartransfer', - name='status', - field=models.CharField(default='draft', max_length=10, verbose_name=[('draft', 'Draft'), ('approved', 'Approved'), ('pending', 'Pending'), ('accepted', 'Accepted'), ('success', 'Success'), ('reject', 'Reject')]), - ), - ] diff --git a/inventory/urls.py b/inventory/urls.py index 1a4bc9d6..0f35f4d7 100644 --- a/inventory/urls.py +++ b/inventory/urls.py @@ -447,7 +447,7 @@ urlpatterns = [ views.PaymentCreateView, name="payment_create", ), - path("sales/payments/create/", views.PaymentCreateView, name="payment_create"), + # path("sales/payments/create/", views.PaymentCreateView, name="payment_create"), path( "sales/payments//payment_details/", views.PaymentDetailView, diff --git a/inventory/views.py b/inventory/views.py index 131fe372..aa6c2e9d 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -829,6 +829,10 @@ def car_transfer_accept_reject(request, car_pk,transfer_pk): transfer.status = "reject" transfer.active = False messages.success(request, _("Car transfer rejected successfully.")) + models.Notification.objects.create( + user=transfer.from_dealer.user, + message=f"Car transfer request from {transfer.to_dealer} is rejected.", + ) transfer.save() elif status == "accepted": transfer.status = "accept" @@ -836,6 +840,10 @@ def car_transfer_accept_reject(request, car_pk,transfer_pk): success = transfer_car(car,transfer) if success: messages.success(request, _("Car Transfer Completed successfully.")) + models.Notification.objects.create( + user=transfer.from_dealer.user, + message=f"Car transfer request from {transfer.to_dealer} is completed.", + ) return redirect("inventory_stats") def CarTransferPreviewView(request, car_pk,transfer_pk): @@ -2549,11 +2557,11 @@ class InvoicePreviewView(LoginRequiredMixin, DetailView): # payments -def PaymentCreateView(request, pk=None): +def PaymentCreateView(request, pk): + print(pk) invoice = InvoiceModel.objects.filter(pk=pk).first() bill = BillModel.objects.filter(pk=pk).first() model = invoice if invoice else bill - redirect_url = 'invoice_detail' if invoice else 'bill_detail' dealer = get_user_type(request) entity = dealer.entity form = forms.PaymentForm() @@ -2564,7 +2572,9 @@ def PaymentCreateView(request, pk=None): invoice = form.cleaned_data.get("invoice") bill = form.cleaned_data.get("bill") payment_method = form.cleaned_data.get("payment_method") + redirect_url = 'invoice_detail' if invoice else 'bill_detail' model = invoice if invoice else bill + if not model.is_approved(): model.mark_as_approved(user_model=entity.admin) try: @@ -2572,6 +2582,7 @@ def PaymentCreateView(request, pk=None): set_invoice_payment(dealer,entity,invoice,amount,payment_method) elif bill: set_bill_payment(dealer,entity,bill,amount,payment_method) + messages.success(request, "Payment created successfully!") return redirect(redirect_url, pk=model.pk) except Exception as e: messages.error(request, f"Error creating payment: {str(e)}") @@ -2579,8 +2590,8 @@ def PaymentCreateView(request, pk=None): messages.error(request, f"Invalid form data: {str(form.errors)}") # return redirect(redirect_url, pk=model.pk) form = forms.PaymentForm() - form.initial["amount"] = model.amount_due - model.amount_paid if model: + form.initial["amount"] = model.amount_due - model.amount_paid if isinstance(model, InvoiceModel): form.initial["invoice"] = model form.fields['bill'].widget = HiddenInput() @@ -2630,7 +2641,12 @@ def payment_mark_as_paid(request, pk): invoice.ledger.post() invoice.ledger.save() - messages.success(request, "Payment created successfully!") + messages.success(request, "Payment created successfully!") + else: + messages.error( + request, + "Invoice is not fully paid. Payment cannot be marked as paid.", + ) except Exception as e: messages.error(request, f"Error: {str(e)}") return redirect("invoice_detail", pk=invoice.pk) @@ -2849,15 +2865,16 @@ def fetch_notifications(request): notifications = models.Notification.objects.filter( user=request.user, is_read=False ).order_by("-created") - notifications_data = [ - { - "id": notification.id, - "message": notification.message, - "created": notification.created.strftime("%Y-%m-%d %H:%M:%S"), - } - for notification in notifications - ] - return JsonResponse({"notifications": notifications_data}) + # notifications_data = [ + # { + # "id": notification.id, + # "message": notification.message, + # "created": notification.created.strftime("%Y-%m-%d %H:%M:%S"), + # } + # for notification in notifications + # ] + # return JsonResponse({"notifications": notifications_data}) + return render(request,'notifications.html',{'notifications_':notifications}) class ItemServiceCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView): @@ -3106,8 +3123,8 @@ def bill_create(request): terms = data.get("terms") vendor = entity.get_vendors().filter(pk=vendor_id).first() - items = data.get("item[]", []) - quantities = data.get("quantity[]", []) + items = data.get("item", []) + quantities = data.get("quantity", []) if not all([items, quantities]): return JsonResponse( diff --git a/templates/auth_base.html b/templates/auth_base.html index 9c63dab3..1567ab39 100644 --- a/templates/auth_base.html +++ b/templates/auth_base.html @@ -79,7 +79,7 @@ - {% block extra_js %}{% endblock extra_js %} + {% block customJS %}{% endblock customJS %} + + -{% endblock extra_js %} \ No newline at end of file +{% endblock customJS %} \ No newline at end of file diff --git a/templates/notifications.html b/templates/notifications.html new file mode 100644 index 00000000..d3ee5cbf --- /dev/null +++ b/templates/notifications.html @@ -0,0 +1,50 @@ + + \ No newline at end of file diff --git a/templates/sales/estimates/estimate_detail.html b/templates/sales/estimates/estimate_detail.html index 58d2f8f7..77c55607 100644 --- a/templates/sales/estimates/estimate_detail.html +++ b/templates/sales/estimates/estimate_detail.html @@ -174,7 +174,7 @@ {% endblock %} -{% block extra_js %} +{% block customJS %} -{% endblock extra_js %} \ No newline at end of file +{% endblock customJS %} \ No newline at end of file diff --git a/templates/sales/invoices/invoice_detail.html b/templates/sales/invoices/invoice_detail.html index 3f1f6ac7..7bb2b3e3 100644 --- a/templates/sales/invoices/invoice_detail.html +++ b/templates/sales/invoices/invoice_detail.html @@ -262,7 +262,7 @@ {% endblock %} -{% block extra_js %} +{% block customJS %}