From 3f89935d1ba833d2a1411a7e85e948fdff1f489b Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 20 Mar 2025 20:37:39 +0300 Subject: [PATCH] update --- haikalbot/migrations/0001_initial.py | 2 +- haikalbot/migrations/0002_initial.py | 6 +- inventory/apps.py | 10 +- inventory/migrations/0001_initial.py | 868 +++++++++--------- .../0002_alter_saleorder_payment_method.py | 18 - inventory/models.py | 2 - inventory/signals.py | 27 +- inventory/views.py | 31 +- requirements.txt | 2 - scripts/generate.py | 11 +- 10 files changed, 484 insertions(+), 493 deletions(-) delete mode 100644 inventory/migrations/0002_alter_saleorder_payment_method.py diff --git a/haikalbot/migrations/0001_initial.py b/haikalbot/migrations/0001_initial.py index 40c4a0ce..9c202e5c 100644 --- a/haikalbot/migrations/0001_initial.py +++ b/haikalbot/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.1.6 on 2025-03-06 01:43 +# Generated by Django 4.2.20 on 2025-03-20 17:15 from django.db import migrations, models diff --git a/haikalbot/migrations/0002_initial.py b/haikalbot/migrations/0002_initial.py index 2ef50ed1..62877afe 100644 --- a/haikalbot/migrations/0002_initial.py +++ b/haikalbot/migrations/0002_initial.py @@ -1,7 +1,7 @@ -# Generated by Django 5.1.6 on 2025-03-06 01:43 +# Generated by Django 4.2.20 on 2025-03-20 17:15 -import django.db.models.deletion from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): @@ -9,8 +9,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('haikalbot', '0001_initial'), ('inventory', '0001_initial'), + ('haikalbot', '0001_initial'), ] operations = [ diff --git a/inventory/apps.py b/inventory/apps.py index 9a82aef1..6e8c8729 100644 --- a/inventory/apps.py +++ b/inventory/apps.py @@ -5,8 +5,8 @@ class InventoryConfig(AppConfig): name = 'inventory' def ready(self): - import inventory.signals - # from decimal import Decimal - # from inventory.models import VatRate - # VatRate.objects.get_or_create(rate=Decimal('0.15'), is_active=True) - + import inventory.signals + from decimal import Decimal + from inventory.models import VatRate + VatRate.objects.get_or_create(rate=Decimal('0.15'), is_active=True) + diff --git a/inventory/migrations/0001_initial.py b/inventory/migrations/0001_initial.py index e76d84e3..1c658e0f 100644 --- a/inventory/migrations/0001_initial.py +++ b/inventory/migrations/0001_initial.py @@ -1,13 +1,13 @@ -# Generated by Django 5.1.6 on 2025-03-06 01:43 +# Generated by Django 4.2.20 on 2025-03-20 17:15 import datetime +from decimal import Decimal +from django.conf import settings +from django.db import migrations, models import django.db.models.deletion import inventory.mixins import inventory.models import phonenumber_field.modelfields -from decimal import Decimal -from django.conf import settings -from django.db import migrations, models class Migration(migrations.Migration): @@ -15,20 +15,55 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('appointment', '__first__'), - ('auth', '0012_alter_user_first_name_max_length'), + migrations.swappable_dependency(settings.DJANGO_LEDGER_INVOICE_MODEL), ('contenttypes', '0002_remove_content_type_name'), + migrations.swappable_dependency(settings.DJANGO_LEDGER_CUSTOMER_MODEL), + migrations.swappable_dependency(settings.DJANGO_LEDGER_ESTIMATE_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.DJANGO_LEDGER_ACCOUNT_MODEL), - migrations.swappable_dependency(settings.DJANGO_LEDGER_CUSTOMER_MODEL), migrations.swappable_dependency(settings.DJANGO_LEDGER_ENTITY_MODEL), - migrations.swappable_dependency(settings.DJANGO_LEDGER_ESTIMATE_MODEL), - migrations.swappable_dependency(settings.DJANGO_LEDGER_INVOICE_MODEL), - migrations.swappable_dependency(settings.DJANGO_LEDGER_ITEM_MODEL), migrations.swappable_dependency(settings.DJANGO_LEDGER_VENDOR_MODEL), + migrations.swappable_dependency(settings.DJANGO_LEDGER_ITEM_MODEL), + ('auth', '0012_alter_user_first_name_max_length'), + ('appointment', '__first__'), ] operations = [ + 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')), + ], + options={ + 'verbose_name': 'Additional Services', + 'verbose_name_plural': 'Additional Services', + }, + bases=(models.Model, inventory.mixins.LocalizedNameMixin), + ), + migrations.CreateModel( + name='Car', + fields=[ + ('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'), ('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')), + ('receiving_date', models.DateTimeField(verbose_name='Receiving Date')), + ('hash', models.CharField(blank=True, max_length=64, null=True, verbose_name='Hash')), + ], + options={ + 'verbose_name': 'Car', + 'verbose_name_plural': 'Cars', + }, + ), migrations.CreateModel( name='CarEquipment', fields=[ @@ -57,110 +92,6 @@ class Migration(migrations.Migration): }, 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='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='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=settings.DJANGO_LEDGER_ITEM_MODEL, verbose_name='Item')), - ], - options={ - 'verbose_name': 'Additional Services', - 'verbose_name_plural': 'Additional Services', - }, - bases=(models.Model, inventory.mixins.LocalizedNameMixin), - ), - migrations.CreateModel( - name='Car', - fields=[ - ('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'), ('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')), - ('receiving_date', models.DateTimeField(verbose_name='Receiving Date')), - ('hash', models.CharField(blank=True, max_length=64, null=True, verbose_name='Hash')), - ('vendor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='cars', to=settings.DJANGO_LEDGER_VENDOR_MODEL, verbose_name='Vendor')), - ('id_car_make', 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')), - ], - options={ - 'verbose_name': 'Car', - 'verbose_name_plural': 'Cars', - }, - ), - 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.CreateModel( name='CarModel', fields=[ @@ -174,11 +105,6 @@ class Migration(migrations.Migration): }, bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), - migrations.AddField( - model_name='car', - name='id_car_model', - field=models.ForeignKey(blank=True, db_column='id_car_model', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmodel', verbose_name='Model'), - ), migrations.CreateModel( name='CarOption', fields=[ @@ -192,36 +118,6 @@ class Migration(migrations.Migration): }, bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), - migrations.CreateModel( - name='CarOptionValue', - fields=[ - ('id_car_option_value', models.AutoField(primary_key=True, serialize=False)), - ('value', models.CharField(max_length=500)), - ('unit', models.CharField(blank=True, max_length=255, null=True)), - ('is_base', models.IntegerField()), - ('id_car_equipment', models.ForeignKey(db_column='id_car_equipment', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carequipment')), - ('id_car_option', models.ForeignKey(db_column='id_car_option', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.caroption')), - ], - options={ - 'verbose_name': 'Option Value', - }, - ), - migrations.CreateModel( - name='CarRegistration', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('plate_number', models.IntegerField(verbose_name='Plate Number')), - ('text1', models.CharField(max_length=1, verbose_name='Text 1')), - ('text2', models.CharField(blank=True, max_length=1, null=True, verbose_name='Text 2')), - ('text3', models.CharField(blank=True, max_length=1, null=True, verbose_name='Text 3')), - ('registration_date', models.DateTimeField(verbose_name='Registration Date')), - ('car', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='registrations', to='inventory.car', verbose_name='Car')), - ], - options={ - 'verbose_name': 'Registration', - 'verbose_name_plural': 'Registrations', - }, - ), migrations.CreateModel( name='CarSerie', fields=[ @@ -238,11 +134,6 @@ class Migration(migrations.Migration): }, bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), - migrations.AddField( - model_name='car', - name='id_car_serie', - field=models.ForeignKey(blank=True, db_column='id_car_serie', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carserie', verbose_name='Series'), - ), migrations.CreateModel( name='CarSpecification', fields=[ @@ -256,57 +147,6 @@ class Migration(migrations.Migration): }, bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), - migrations.CreateModel( - name='CarTrim', - fields=[ - ('id_car_trim', models.AutoField(primary_key=True, serialize=False)), - ('name', models.CharField(blank=True, max_length=255, null=True)), - ('arabic_name', models.CharField(blank=True, max_length=255, null=True)), - ('start_production_year', models.IntegerField(blank=True, null=True)), - ('end_production_year', models.IntegerField(blank=True, null=True)), - ('id_car_serie', models.ForeignKey(db_column='id_car_serie', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carserie')), - ], - options={ - 'verbose_name': 'Trim', - }, - bases=(models.Model, inventory.mixins.LocalizedNameMixin), - ), - migrations.CreateModel( - name='CarSpecificationValue', - fields=[ - ('id_car_specification_value', models.AutoField(primary_key=True, serialize=False)), - ('value', models.CharField(max_length=500)), - ('unit', models.CharField(blank=True, max_length=255, null=True)), - ('id_car_specification', models.ForeignKey(db_column='id_car_specification', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carspecification')), - ('id_car_trim', models.ForeignKey(db_column='id_car_trim', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.cartrim')), - ], - options={ - 'verbose_name': 'Specification Value', - }, - ), - migrations.AddField( - model_name='carequipment', - name='id_car_trim', - field=models.ForeignKey(db_column='id_car_trim', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.cartrim'), - ), - migrations.AddField( - model_name='car', - name='id_car_trim', - field=models.ForeignKey(blank=True, db_column='id_car_trim', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.cartrim', verbose_name='Trim'), - ), - migrations.CreateModel( - name='CustomCard', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('custom_number', models.CharField(max_length=255, verbose_name='Custom Number')), - ('custom_date', models.DateField(verbose_name='Custom Date')), - ('car', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='custom_cards', to='inventory.car', verbose_name='Car')), - ], - options={ - 'verbose_name': 'Custom Card', - 'verbose_name_plural': 'Custom Cards', - }, - ), migrations.CreateModel( name='Dealer', fields=[ @@ -333,136 +173,32 @@ class Migration(migrations.Migration): ], ), migrations.CreateModel( - name='CustomGroup', + name='ExteriorColors', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), - ('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='auth.group', verbose_name='')), - ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='groups', to='inventory.dealer')), - ], - ), - 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')), - ('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')), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='customer_profile', to=settings.AUTH_USER_MODEL)), - ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='customers', to='inventory.dealer')), + ('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': 'Customer', - 'verbose_name_plural': 'Customers', + 'verbose_name': 'Exterior Colors', + 'verbose_name_plural': 'Exterior Colors', }, + bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), migrations.CreateModel( - name='CarTransfer', + name='InteriorColors', 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'), ('cancelled', 'Cancelled')])), - ('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')), + ('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 Transfer Log', - 'verbose_name_plural': 'Car Transfer Logs', - }, - ), - migrations.CreateModel( - name='CarLocation', - 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')), - ], - options={ - 'verbose_name': 'Car Location', - 'verbose_name_plural': 'Car Locations', - }, - ), - 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='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'), ('sale_car', 'Sale Car'), ('reserve_car', 'Reserve Car'), ('transfer_car', 'Transfer 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.DO_NOTHING, to='contenttypes.contenttype')), - ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='activities_created_by', to=settings.AUTH_USER_MODEL)), - ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='inventory.dealer')), - ], - options={ - 'verbose_name': 'Activity', - 'verbose_name_plural': 'Activities', - }, - ), - migrations.CreateModel( - name='DealerSettings', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('additional_info', models.JSONField(blank=True, default=dict, null=True)), - ('bill_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_cash', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), - ('bill_prepaid_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_prepaid', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), - ('bill_unearned_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_unearned', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), - ('dealer', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='settings', to='inventory.dealer')), - ('invoice_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_cash', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), - ('invoice_prepaid_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_prepaid', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), - ('invoice_unearned_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_unearned', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), - ], - ), - migrations.CreateModel( - name='Email', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('object_id', models.PositiveIntegerField()), - ('from_email', models.TextField(blank=True, null=True, verbose_name='From Email')), - ('to_email', models.TextField(blank=True, null=True, verbose_name='To Email')), - ('subject', models.TextField(blank=True, null=True, verbose_name='Subject')), - ('message', models.TextField(blank=True, null=True, verbose_name='Message')), - ('status', models.CharField(choices=[('SENT', 'Sent'), ('FAILED', 'Failed'), ('DELIVERED', 'Delivered'), ('OPEN', 'Open'), ('DRAFT', 'Draft')], default='OPEN', max_length=20, verbose_name='Status')), - ('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='emails_created', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'Email', - 'verbose_name_plural': 'Emails', + 'verbose_name': 'Interior Colors', + 'verbose_name_plural': 'Interior Colors', }, + bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), migrations.CreateModel( name='Lead', @@ -493,37 +229,6 @@ class Migration(migrations.Migration): 'verbose_name_plural': 'Leads', }, ), - 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=[ @@ -546,71 +251,62 @@ class Migration(migrations.Migration): bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), migrations.CreateModel( - name='Refund', + 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')), - ('reason', models.TextField(blank=True, verbose_name='reason')), - ('refund_date', models.DateField(auto_now_add=True, verbose_name='refund date')), - ('payment', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='refund', to='inventory.payment')), + ('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': 'refund', - 'verbose_name_plural': 'refunds', + 'verbose_name': 'payment', + 'verbose_name_plural': 'payments', }, ), migrations.CreateModel( - name='Representative', + name='VatRate', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, verbose_name='Name')), + ('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='Vendor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('crn', models.CharField(max_length=10, unique=True, verbose_name='Commercial Registration Number')), + ('vrn', models.CharField(max_length=15, unique=True, verbose_name='VAT Registration Number')), ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), - ('id_number', models.CharField(max_length=10, unique=True, verbose_name='ID Number')), + ('name', models.CharField(max_length=255, verbose_name='English Name')), + ('contact_person', models.CharField(max_length=100, verbose_name='Contact Person')), ('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')), - ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='representatives', to='inventory.dealer')), - ('organization', models.ManyToManyField(related_name='representatives', to='inventory.organization')), + ('logo', models.ImageField(blank=True, null=True, upload_to='logos/vendors', verbose_name='Logo')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), + ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='vendors', to='inventory.dealer')), ], options={ - 'verbose_name': 'Representative', - 'verbose_name_plural': 'Representatives', + 'verbose_name': 'Vendor', + 'verbose_name_plural': 'Vendors', }, bases=(models.Model, inventory.mixins.LocalizedNameMixin), ), migrations.CreateModel( - name='SaleOrder', + name='UserActivityLog', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('payment_method', models.CharField(choices=[('cash', 'Cash'), ('finance', 'Finance'), ('lease', 'Lease')], max_length=20)), - ('comments', models.TextField(blank=True, null=True)), - ('formatted_order_id', models.CharField(editable=False, max_length=10, unique=True)), - ('created', models.DateTimeField(auto_now_add=True)), - ('estimate', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sale_orders', to=settings.DJANGO_LEDGER_ESTIMATE_MODEL, verbose_name='Estimate')), - ('invoice', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sale_orders', to=settings.DJANGO_LEDGER_INVOICE_MODEL, verbose_name='Invoice')), + ('action', models.TextField()), + ('timestamp', models.DateTimeField(auto_now_add=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ - 'ordering': ['-created'], - }, - ), - migrations.CreateModel( - name='Schedule', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('purpose', models.CharField(choices=[('Product Demo', 'Product Demo'), ('Follow-Up Call', 'Follow-Up Call'), ('Contract Discussion', 'Contract Discussion'), ('Sales Meeting', 'Sales Meeting'), ('Support Call', 'Support Call'), ('Other', 'Other')], max_length=200)), - ('scheduled_at', models.DateTimeField()), - ('scheduled_type', models.CharField(choices=[('Call', 'Call'), ('Meeting', 'Meeting'), ('Email', 'Email')], default='Call', max_length=200)), - ('duration', models.DurationField(default=datetime.timedelta(seconds=300))), - ('notes', models.TextField(blank=True, null=True)), - ('status', models.CharField(choices=[('Scheduled', 'Scheduled'), ('Completed', 'Completed'), ('Canceled', 'Canceled')], default='Scheduled', max_length=200)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('customer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL)), - ('lead', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='inventory.lead')), - ('scheduled_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'ordering': ['-scheduled_at'], + 'verbose_name': 'User Activity Log', + 'verbose_name_plural': 'User Activity Logs', + 'ordering': ['-timestamp'], }, ), migrations.CreateModel( @@ -636,6 +332,74 @@ class Migration(migrations.Migration): ('objects', inventory.models.StaffUserManager()), ], ), + migrations.CreateModel( + name='Schedule', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('purpose', models.CharField(choices=[('Product Demo', 'Product Demo'), ('Follow-Up Call', 'Follow-Up Call'), ('Contract Discussion', 'Contract Discussion'), ('Sales Meeting', 'Sales Meeting'), ('Support Call', 'Support Call'), ('Other', 'Other')], max_length=200)), + ('scheduled_at', models.DateTimeField()), + ('scheduled_type', models.CharField(choices=[('Call', 'Call'), ('Meeting', 'Meeting'), ('Email', 'Email')], default='Call', max_length=200)), + ('duration', models.DurationField(default=datetime.timedelta(seconds=300))), + ('notes', models.TextField(blank=True, null=True)), + ('status', models.CharField(choices=[('Scheduled', 'Scheduled'), ('Completed', 'Completed'), ('Canceled', 'Canceled')], default='Scheduled', max_length=200)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('customer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL)), + ('lead', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='inventory.lead')), + ('scheduled_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ['-scheduled_at'], + }, + ), + migrations.CreateModel( + name='SaleOrder', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('payment_method', models.CharField(choices=[('cash', 'Cash'), ('finance', 'Finance'), ('lease', 'Lease'), ('credit_card', 'Credit Card'), ('bank_transfer', 'Bank Transfer'), ('SADAD', 'SADAD')], max_length=20)), + ('comments', models.TextField(blank=True, null=True)), + ('formatted_order_id', models.CharField(editable=False, max_length=10, unique=True)), + ('created', models.DateTimeField(auto_now_add=True)), + ('estimate', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sale_orders', to=settings.DJANGO_LEDGER_ESTIMATE_MODEL, verbose_name='Estimate')), + ('invoice', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sale_orders', to=settings.DJANGO_LEDGER_INVOICE_MODEL, verbose_name='Invoice')), + ], + options={ + 'ordering': ['-created'], + }, + ), + migrations.CreateModel( + name='Representative', + 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')), + ('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')), + ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='representatives', to='inventory.dealer')), + ('organization', models.ManyToManyField(related_name='representatives', to='inventory.organization')), + ], + options={ + 'verbose_name': 'Representative', + 'verbose_name_plural': 'Representatives', + }, + bases=(models.Model, inventory.mixins.LocalizedNameMixin), + ), + migrations.CreateModel( + name='Refund', + 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')), + ('reason', models.TextField(blank=True, verbose_name='reason')), + ('refund_date', models.DateField(auto_now_add=True, verbose_name='refund date')), + ('payment', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='refund', to='inventory.payment')), + ], + options={ + 'verbose_name': 'refund', + 'verbose_name_plural': 'refunds', + }, + ), migrations.CreateModel( name='Opportunity', fields=[ @@ -659,6 +423,37 @@ class Migration(migrations.Migration): 'verbose_name_plural': 'Opportunities', }, ), + 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='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='LeadStatusHistory', fields=[ @@ -666,8 +461,8 @@ class Migration(migrations.Migration): ('old_status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('canceled', 'Canceled')], max_length=50, verbose_name='Old Status')), ('new_status', models.CharField(choices=[('new', 'New'), ('pending', 'Pending'), ('in_progress', 'In Progress'), ('qualified', 'Qualified'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('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')), + ('lead', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='status_history', to='inventory.lead')), ], options={ 'verbose_name': 'Lead Status History', @@ -680,41 +475,270 @@ class Migration(migrations.Migration): 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.CreateModel( - name='UserActivityLog', + name='Email', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('action', models.TextField()), - ('timestamp', models.DateTimeField(auto_now_add=True)), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('object_id', models.PositiveIntegerField()), + ('from_email', models.TextField(blank=True, null=True, verbose_name='From Email')), + ('to_email', models.TextField(blank=True, null=True, verbose_name='To Email')), + ('subject', models.TextField(blank=True, null=True, verbose_name='Subject')), + ('message', models.TextField(blank=True, null=True, verbose_name='Message')), + ('status', models.CharField(choices=[('SENT', 'Sent'), ('FAILED', 'Failed'), ('DELIVERED', 'Delivered'), ('OPEN', 'Open'), ('DRAFT', 'Draft')], default='OPEN', max_length=20, verbose_name='Status')), + ('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='emails_created', to=settings.AUTH_USER_MODEL)), ], options={ - 'verbose_name': 'User Activity Log', - 'verbose_name_plural': 'User Activity Logs', - 'ordering': ['-timestamp'], + 'verbose_name': 'Email', + 'verbose_name_plural': 'Emails', }, ), migrations.CreateModel( - name='Vendor', + name='DealerSettings', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('crn', models.CharField(max_length=10, unique=True, verbose_name='Commercial Registration Number')), - ('vrn', models.CharField(max_length=15, unique=True, verbose_name='VAT Registration Number')), - ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), - ('name', models.CharField(max_length=255, verbose_name='English Name')), - ('contact_person', models.CharField(max_length=100, verbose_name='Contact Person')), - ('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')), + ('additional_info', models.JSONField(blank=True, default=dict, null=True)), + ('bill_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_cash', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), + ('bill_prepaid_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_prepaid', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), + ('bill_unearned_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_unearned', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), + ('dealer', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='settings', to='inventory.dealer')), + ('invoice_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_cash', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), + ('invoice_prepaid_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_prepaid', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), + ('invoice_unearned_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_unearned', to=settings.DJANGO_LEDGER_ACCOUNT_MODEL)), + ], + ), + migrations.CreateModel( + name='CustomGroup', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='groups', to='inventory.dealer')), + ('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='auth.group', verbose_name='')), + ], + ), + 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')), ('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Address')), - ('logo', models.ImageField(blank=True, null=True, upload_to='logos/vendors', verbose_name='Logo')), - ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created At')), - ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='vendors', to='inventory.dealer')), + ('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')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='customer_profile', to=settings.AUTH_USER_MODEL)), ], options={ - 'verbose_name': 'Vendor', - 'verbose_name_plural': 'Vendors', + 'verbose_name': 'Customer', + 'verbose_name_plural': 'Customers', + }, + ), + migrations.CreateModel( + name='CustomCard', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('custom_number', models.CharField(max_length=255, verbose_name='Custom Number')), + ('custom_date', models.DateField(verbose_name='Custom Date')), + ('car', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='custom_cards', to='inventory.car', verbose_name='Car')), + ], + options={ + 'verbose_name': 'Custom Card', + 'verbose_name_plural': 'Custom Cards', + }, + ), + migrations.CreateModel( + name='CarTrim', + fields=[ + ('id_car_trim', models.AutoField(primary_key=True, serialize=False)), + ('name', models.CharField(blank=True, max_length=255, null=True)), + ('arabic_name', models.CharField(blank=True, max_length=255, null=True)), + ('start_production_year', models.IntegerField(blank=True, null=True)), + ('end_production_year', models.IntegerField(blank=True, null=True)), + ('id_car_serie', models.ForeignKey(db_column='id_car_serie', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carserie')), + ], + options={ + 'verbose_name': 'Trim', }, 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'), ('cancelled', 'Cancelled')])), + ('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=[ + ('id_car_specification_value', models.AutoField(primary_key=True, serialize=False)), + ('value', models.CharField(max_length=500)), + ('unit', models.CharField(blank=True, max_length=255, null=True)), + ('id_car_specification', models.ForeignKey(db_column='id_car_specification', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carspecification')), + ('id_car_trim', models.ForeignKey(db_column='id_car_trim', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.cartrim')), + ], + options={ + 'verbose_name': 'Specification Value', + }, + ), + migrations.CreateModel( + name='CarRegistration', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('plate_number', models.IntegerField(verbose_name='Plate Number')), + ('text1', models.CharField(max_length=1, verbose_name='Text 1')), + ('text2', models.CharField(blank=True, max_length=1, null=True, verbose_name='Text 2')), + ('text3', models.CharField(blank=True, max_length=1, null=True, verbose_name='Text 3')), + ('registration_date', models.DateTimeField(verbose_name='Registration Date')), + ('car', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='registrations', to='inventory.car', verbose_name='Car')), + ], + options={ + 'verbose_name': 'Registration', + 'verbose_name_plural': 'Registrations', + }, + ), + migrations.CreateModel( + name='CarOptionValue', + fields=[ + ('id_car_option_value', models.AutoField(primary_key=True, serialize=False)), + ('value', models.CharField(max_length=500)), + ('unit', models.CharField(blank=True, max_length=255, null=True)), + ('is_base', models.IntegerField()), + ('id_car_equipment', models.ForeignKey(db_column='id_car_equipment', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carequipment')), + ('id_car_option', models.ForeignKey(db_column='id_car_option', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.caroption')), + ], + options={ + 'verbose_name': 'Option Value', + }, + ), + migrations.CreateModel( + name='CarLocation', + 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')), + ], + options={ + 'verbose_name': 'Car Location', + 'verbose_name_plural': 'Car Locations', + }, + ), + 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='carequipment', + name='id_car_trim', + field=models.ForeignKey(db_column='id_car_trim', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.cartrim'), + ), + 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='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.AddField( + model_name='car', + name='id_car_model', + field=models.ForeignKey(blank=True, db_column='id_car_model', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmodel', verbose_name='Model'), + ), + migrations.AddField( + model_name='car', + name='id_car_serie', + field=models.ForeignKey(blank=True, db_column='id_car_serie', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carserie', verbose_name='Series'), + ), + migrations.AddField( + model_name='car', + name='id_car_trim', + field=models.ForeignKey(blank=True, db_column='id_car_trim', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.cartrim', verbose_name='Trim'), + ), + migrations.AddField( + model_name='car', + name='vendor', + field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='cars', to=settings.DJANGO_LEDGER_VENDOR_MODEL, verbose_name='Vendor'), + ), + migrations.AddField( + model_name='additionalservices', + name='dealer', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.dealer', verbose_name='Dealer'), + ), + migrations.AddField( + model_name='additionalservices', + name='item', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.DJANGO_LEDGER_ITEM_MODEL, verbose_name='Item'), + ), + 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'), ('sale_car', 'Sale Car'), ('reserve_car', 'Reserve Car'), ('transfer_car', 'Transfer 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.DO_NOTHING, to='contenttypes.contenttype')), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='activities_created_by', to=settings.AUTH_USER_MODEL)), + ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='inventory.dealer')), + ], + options={ + 'verbose_name': 'Activity', + 'verbose_name_plural': 'Activities', + }, + ), + migrations.CreateModel( + name='DealersMake', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('added_at', models.DateTimeField(auto_now_add=True)), + ('car_make', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='car_dealers', to='inventory.carmake')), + ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='dealer_makes', to='inventory.dealer')), + ], + options={ + 'unique_together': {('dealer', 'car_make')}, + }, + ), migrations.CreateModel( name='CarReservation', fields=[ @@ -731,18 +755,6 @@ class Migration(migrations.Migration): 'unique_together': {('car', 'reserved_until')}, }, ), - migrations.CreateModel( - name='DealersMake', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('added_at', models.DateTimeField(auto_now_add=True)), - ('car_make', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='car_dealers', to='inventory.carmake')), - ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='dealer_makes', to='inventory.dealer')), - ], - options={ - 'unique_together': {('dealer', 'car_make')}, - }, - ), migrations.CreateModel( name='CarColors', fields=[ diff --git a/inventory/migrations/0002_alter_saleorder_payment_method.py b/inventory/migrations/0002_alter_saleorder_payment_method.py deleted file mode 100644 index dc6c31ca..00000000 --- a/inventory/migrations/0002_alter_saleorder_payment_method.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.1.7 on 2025-03-16 19:09 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('inventory', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='saleorder', - name='payment_method', - field=models.CharField(choices=[('cash', 'Cash'), ('finance', 'Finance'), ('lease', 'Lease'), ('credit_card', 'Credit Card'), ('bank_transfer', 'Bank Transfer'), ('SADAD', 'SADAD')], max_length=20), - ), - ] diff --git a/inventory/models.py b/inventory/models.py index 55d06bb1..45d873bd 100644 --- a/inventory/models.py +++ b/inventory/models.py @@ -358,8 +358,6 @@ class Car(models.Model): vendor = models.ForeignKey( VendorModel, models.DO_NOTHING, - null=True, - blank=True, related_name="cars", verbose_name=_("Vendor"), ) diff --git a/inventory/signals.py b/inventory/signals.py index 33a902f7..ac99e298 100644 --- a/inventory/signals.py +++ b/inventory/signals.py @@ -623,7 +623,7 @@ def create_ledger_entity(sender, instance, created, **kwargs): entity.create_account(coa_model=coa, code="6302", role=roles.EXPENSE_OTHER, name=_("Taxes"), balance_type="debit", active=True) entity.create_account(coa_model=coa, code="6303", role=roles.EXPENSE_OTHER, name=_("Foreign Currency Translation"), balance_type="debit", active=True) entity.create_account(coa_model=coa, code="6304", role=roles.EXPENSE_OTHER, name=_("Interest Expenses"), balance_type="debit", active=True) - + @receiver(post_save, sender=models.Dealer) def create_dealer_groups(sender, instance, created, **kwargs): @@ -658,7 +658,7 @@ def create_ledger_vendor(sender, instance, created, **kwargs): }, } ) - + coa = entity.get_default_coa() last_account = entity.get_all_accounts().filter(role=roles.LIABILITY_CL_ACC_PAYABLE).order_by('-created').first() # code = f"{int(last_account.code)}{1:03d}" @@ -674,7 +674,7 @@ def create_ledger_vendor(sender, instance, created, **kwargs): coa_model=coa, balance_type="credit", active=True - ) + ) print(f"VendorModel created for Vendor: {instance.name}") @@ -898,11 +898,6 @@ def create_dealer_settings(sender, instance, created, **kwargs): bill_prepaid_account=instance.entity.get_all_accounts().filter(role=roles.ASSET_CA_PREPAID).first(), bill_unearned_account=instance.entity.get_all_accounts().filter(role=roles.LIABILITY_CL_ACC_PAYABLE).first() ) - -@receiver(post_save, sender=models.Dealer) -def check_if_vat_exists(sender, instance, created, **kwargs): - if created: - models.VatRate.objects.get_create(is_active=True) # @receiver(post_save, sender=EstimateModel) # def update_estimate_status(sender, instance,created, **kwargs): @@ -951,7 +946,7 @@ def create_make_ledger_accounts(sender, instance, created, **kwargs): # coa_model=entity.get_default_coa(), # balance_type="credit", # active=True -# ) +# ) @receiver(post_save, sender=models.CarFinance) def update_finance_cost(sender, instance, created, **kwargs): @@ -969,17 +964,17 @@ def update_finance_cost(sender, instance, created, **kwargs): ) ledger.additional_info["je_number"] = journal.je_number ledger.save() - + inventory_account = entity.get_default_coa_accounts().filter(role=roles.ASSET_CA_INVENTORY).first() vendor_account = entity.get_default_coa_accounts().get(name=vendor.vendor_name) - # Debit Inventory Account + # Debit Inventory Account TransactionModel.objects.create( journal_entry=journal, account=inventory_account, amount=instance.total + instance.total_additionals, tx_type='debit' - ) + ) # Credit Vendor Account TransactionModel.objects.create( @@ -1003,13 +998,13 @@ def update_finance_cost(sender, instance, created, **kwargs): inventory_account = entity.get_default_coa_accounts().filter(role=roles.ASSET_CA_INVENTORY).first() vendor_account = entity.get_default_coa_accounts().get(name=vendor.vendor_name, active=True) - # Debit Inventory Account + # Debit Inventory Account TransactionModel.objects.create( journal_entry=journal, account=inventory_account, amount=instance.cost_price, tx_type='debit' - ) + ) # Credit Vendor Account TransactionModel.objects.create( @@ -1023,9 +1018,9 @@ def update_finance_cost(sender, instance, created, **kwargs): journal = JournalEntryModel.objects.filter(je_number=ledger.additional_info.get("je_number")).first() debit = journal.get_transaction_queryset().filter(tx_type='debit').first() credit = journal.get_transaction_queryset().filter(tx_type='credit').first() - + debit.amount = instance.cost_price credit.amount = instance.cost_price - + debit.save() credit.save() \ No newline at end of file diff --git a/inventory/views.py b/inventory/views.py index 63162e9d..b200852a 100644 --- a/inventory/views.py +++ b/inventory/views.py @@ -4070,8 +4070,9 @@ class LedgerModelListView(LoginRequiredMixin, ListView,ArchiveIndexView): show_all = False show_current = False show_visible = False + allow_empty = True + - def get_queryset(self): qs = super().get_queryset() dealer = get_user_type(self.request) @@ -4091,51 +4092,51 @@ class LedgerModelDetailView(LoginRequiredMixin, DetailView): model = LedgerModel context_object_name = "ledger" template_name = "ledger/ledger/ledger_detail.html" - + # class LedgerModelCreateView(LoginRequiredMixin,SuccessMessageMixin, CreateView): # model = LedgerModel # template_name = "ledger/ledger/ledger_form.html" # form_class = forms.LedgerModelCreateForm # success_message = "Ledger created" - + # def get_form(self, form_class=None): # dealer = get_user_type(self.request) # form = forms.LedgerModelCreateForm(entity_slug=dealer.entity.slug,user_model=dealer.entity.admin,**self.get_form_kwargs()) # return form # def get_success_url(self): # return reverse('ledger_list') - + # def form_valid(self, form): # instance = form.save(commit=False) # dealer = get_user_type(self.request) # instance.entity = dealer.entity -# instance.save() +# instance.save() # return super().form_valid(form) class JournalEntryListView(LoginRequiredMixin, ListView): model = JournalEntryModel context_object_name = "journal_entries" template_name = "ledger/journal_entry/journal_entry_list.html" - + def get_queryset(self): qs = super().get_queryset() ledger = LedgerModel.objects.filter(pk=self.kwargs['pk']).first() qs = qs.filter(ledger=ledger) return qs - + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['ledger'] = LedgerModel.objects.filter(pk=self.kwargs['pk']).first() return context - + class JournalEntryCreateView(LoginRequiredMixin,SuccessMessageMixin, CreateView): model = JournalEntryModel template_name = "ledger/journal_entry/journal_entry_form.html" form_class = forms.JournalEntryModelCreateForm ledger_model = None success_message = "Journal Entry created" - + def get_form(self, form_class=None): dealer = get_user_type(self.request) ledger = LedgerModel.objects.filter(pk=self.kwargs['pk']).first() @@ -4150,11 +4151,11 @@ class JournalEntryCreateView(LoginRequiredMixin,SuccessMessageMixin, CreateView) context = super().get_context_data(**kwargs) context["ledger"] = LedgerModel.objects.filter(pk=self.kwargs['pk']).first() return context - + def get_success_url(self): ledger = LedgerModel.objects.filter(pk=self.kwargs['pk']).first() return reverse("journalentry_list", kwargs={"pk": ledger.pk}) - + def JournalEntryDeleteView(request,pk): journal_entry = get_object_or_404(JournalEntryModel, pk=pk) @@ -4182,7 +4183,7 @@ def JournalEntryTransactionsView(request, pk): class JournalEntryModelTXSDetailView(JournalEntryModelTXSDetailViewBase): template_name = 'ledger/journal_entry/journal_entry_txs.html' - + def ledger_lock_all_journals(request,entity_slug,pk): ledger = LedgerModel.objects.filter(pk=pk).first() @@ -4199,7 +4200,7 @@ def ledger_unlock_all_journals(request,entity_slug,pk): if not ledger.is_locked(): messages.error(request, "Ledger is already Unlocked.") return redirect("journalentry_list", pk=ledger.pk) - + ledger.unlock() ledger.save() qs = ledger.journal_entries.locked() @@ -4224,10 +4225,10 @@ def ledger_unpost_all_journals(request,entity_slug,pk): messages.error(request, "Ledger is already Unposted.") return redirect("journalentry_list", pk=ledger.pk) qs = ledger.journal_entries.posted() - for je in qs: + for je in qs: je.mark_as_unposted() je.save() - + ledger.unpost() ledger.save() return redirect("journalentry_list", pk=ledger.pk) diff --git a/requirements.txt b/requirements.txt index 6a0fd620..6f10ed53 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,8 +29,6 @@ commonmark contourpy crispy-bootstrap5 cryptography -cssselect2 -ctranslate2 cycler Cython decorator diff --git a/scripts/generate.py b/scripts/generate.py index d235fb3e..864598a1 100644 --- a/scripts/generate.py +++ b/scripts/generate.py @@ -1,4 +1,5 @@ from inventory.models import * +from django_ledger.models import VendorModel from rich import print import random import datetime @@ -8,6 +9,9 @@ from inventory.services import decodevin def run(): # car = Car.objects.filter(vin='2C3HD46R4WH170267') + dealer = Dealer.objects.first() + vendors = [VendorModel.objects.create(vendor_name=f'vendor{i}',entity_model=dealer.entity) for i in range(1, 5)] + vin_list = [ "1B3ES56C13D120225", "1GB4KYC86FF131536", @@ -24,8 +28,8 @@ def run(): ] for vin in vin_list: try: - for _ in range(15): - dealer = Dealer.objects.get(user__email="ismail.mosa.ibrahim@gmail.com") + for _ in range(5): + vin = f"{vin[:-4]}{random.randint(0, 9)}{random.randint(0, 9)}{random.randint(0, 9)}{random.randint(0, 9)}" result = decodevin(vin) make = CarMake.objects.get(name=result["maker"]) @@ -35,13 +39,14 @@ def run(): year = result["modelYear"] serie = random.choice(model.carserie_set.all()) trim = random.choice(serie.cartrim_set.all()) - + vendor = random.choice(vendors) car = Car.objects.create( vin=vin, id_car_make=make, id_car_model=model, id_car_serie=serie, id_car_trim=trim, + vendor=vendor, year=(int(year) or 2025), receiving_date=datetime.datetime.now(), dealer=dealer,