fe update

This commit is contained in:
Faheedkhan 2025-05-19 14:29:36 +03:00
parent 03c76bec95
commit 9cb371ae9e
54 changed files with 248 additions and 662 deletions

View File

@ -1,17 +1,21 @@
#!/bin/sh #!/bin/sh
echo "Delete Old Migrations" echo "Delete Old Migrations"
find ./inventory -type f -iname "000*.py" -delete find ./inventory -type f -iname "00*.py" -delete
echo "Delete Old Cache" echo "Delete Old Cache"
find ./car_inventory -type d -iname "__pycache__"|xargs rm -rf find ./car_inventory -type d -iname "__pycache__"|xargs rm -rf
find ./inventory -type d -iname "__pycache__"|xargs rm -rf find ./inventory -type d -iname "__pycache__"|xargs rm -rf
echo "Apply Base Migrate" echo "Apply Base Migrate"
python3 manage.py migrate python3 manage.py migrate
echo "Apply Make Migratinos"
python3 manage.py makemigrations python3 manage.py makemigrations
echo "Apply Appointment Migratinos"
python3 manage.py makemigrations appointment
echo "Apply Final Migrate" echo "Apply Final Migrate"
python3 manage.py migrate python3 manage.py migrate

View File

@ -1,4 +1,4 @@
# Generated by Django 5.1.7 on 2025-05-05 16:32 # Generated by Django 5.1.7 on 2025-05-18 11:18
import datetime import datetime
import django.core.validators import django.core.validators
@ -25,6 +25,24 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
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( migrations.CreateModel(
name='CarEquipment', name='CarEquipment',
fields=[ fields=[
@ -122,26 +140,6 @@ class Migration(migrations.Migration):
}, },
bases=(models.Model, inventory.mixins.LocalizedNameMixin), 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(on_delete=django.db.models.deletion.DO_NOTHING, related_name='cars', to='django_ledger.vendormodel', 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( migrations.CreateModel(
name='CarFinance', name='CarFinance',
fields=[ fields=[
@ -157,6 +155,11 @@ class Migration(migrations.Migration):
'verbose_name_plural': '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( migrations.CreateModel(
name='CarModel', name='CarModel',
fields=[ fields=[
@ -343,16 +346,18 @@ class Migration(migrations.Migration):
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('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')), ('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')), ('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')), ('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')), ('gender', models.CharField(choices=[('m', 'Male'), ('f', 'Female')], max_length=1, verbose_name='Gender')),
('dob', models.DateField(verbose_name='Date of Birth')), ('dob', models.DateField(blank=True, null=True, verbose_name='Date of Birth')),
('email', models.EmailField(max_length=254, unique=True, verbose_name='Email')), ('email', models.EmailField(max_length=254, unique=True, verbose_name='Email')),
('national_id', models.CharField(max_length=10, unique=True, verbose_name='National ID')), ('national_id', models.CharField(blank=True, max_length=10, null=True, unique=True, verbose_name='National ID')),
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', unique=True, verbose_name='Phone Number')), ('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')), ('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Address')),
('active', models.BooleanField(default=True, verbose_name='Active')),
('image', models.ImageField(blank=True, null=True, upload_to='customers/', verbose_name='Image')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('customer_model', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='django_ledger.customermodel')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='customer_profile', to=settings.AUTH_USER_MODEL)), ('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')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='customers', to='inventory.dealer')),
], ],
@ -413,7 +418,7 @@ class Migration(migrations.Migration):
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('object_id', models.PositiveIntegerField()), ('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')), ('activity_type', models.CharField(choices=[('call', 'Call'), ('sms', 'SMS'), ('email', 'Email'), ('whatsapp', 'WhatsApp'), ('visit', 'Visit'), ('negotiation', 'Negotiation'), ('follow_up', 'Follow Up'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed'), ('converted', 'Converted'), ('transfer', 'Transfer'), ('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')), ('notes', models.TextField(blank=True, null=True, verbose_name='Notes')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
@ -460,35 +465,6 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'Emails', 'verbose_name_plural': 'Emails',
}, },
), ),
migrations.CreateModel(
name='Lead',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('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(max_length=254, verbose_name='Email')),
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')),
('lead_type', models.CharField(choices=[('customer', 'Customer'), ('organization', 'Organization')], default='customer', max_length=50, verbose_name='Lead Type')),
('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')),
('crn', models.CharField(blank=True, max_length=10, null=True, unique=True, verbose_name='Commercial Registration Number')),
('vrn', models.CharField(blank=True, max_length=15, null=True, unique=True, verbose_name='VAT Registration Number')),
('address', models.CharField(max_length=50, verbose_name='address')),
('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'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('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(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='leads', to='django_ledger.customermodel')),
('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')),
],
options={
'verbose_name': 'Lead',
'verbose_name_plural': 'Leads',
},
),
migrations.CreateModel( migrations.CreateModel(
name='Notes', name='Notes',
fields=[ fields=[
@ -528,12 +504,16 @@ class Migration(migrations.Migration):
('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')), ('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')),
('crn', models.CharField(max_length=15, verbose_name='Commercial Registration Number')), ('crn', models.CharField(max_length=15, verbose_name='Commercial Registration Number')),
('vrn', models.CharField(max_length=15, verbose_name='VAT Registration Number')), ('vrn', models.CharField(max_length=15, verbose_name='VAT Registration Number')),
('email', models.EmailField(max_length=254, verbose_name='Email')),
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')), ('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')), ('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')), ('logo', models.ImageField(blank=True, null=True, upload_to='logos', verbose_name='Logo')),
('active', models.BooleanField(default=True, verbose_name='Active')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('customer_model', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='django_ledger.customermodel')),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='organizations', to='inventory.dealer')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='organizations', to='inventory.dealer')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='organization_profile', to=settings.AUTH_USER_MODEL)),
], ],
options={ options={
'verbose_name': 'Organization', 'verbose_name': 'Organization',
@ -541,6 +521,40 @@ class Migration(migrations.Migration):
}, },
bases=(models.Model, inventory.mixins.LocalizedNameMixin), 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')),
('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(max_length=254, verbose_name='Email')),
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')),
('lead_type', models.CharField(choices=[('customer', 'Customer'), ('organization', 'Organization')], default='customer', max_length=50, verbose_name='Lead Type')),
('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')),
('crn', models.CharField(blank=True, max_length=10, null=True, unique=True, verbose_name='Commercial Registration Number')),
('vrn', models.CharField(blank=True, max_length=15, null=True, unique=True, verbose_name='VAT Registration Number')),
('address', models.CharField(max_length=50, verbose_name='address')),
('priority', models.CharField(choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High')], default='medium', max_length=10, verbose_name='Priority')),
('status', models.CharField(choices=[('new', 'New'), ('follow_up', 'Follow-up'), ('negotiation', 'Negotiation'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed')], db_index=True, default='new', max_length=50, verbose_name='Status')),
('next_action', models.CharField(blank=True, max_length=255, null=True, verbose_name='Next Action')),
('next_action_date', models.DateTimeField(blank=True, null=True, verbose_name='Next Action Date')),
('is_converted', models.BooleanField(default=False)),
('converted_at', models.DateTimeField(blank=True, null=True)),
('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(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='customer_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')),
('organization', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='organization_leads', to='inventory.organization')),
],
options={
'verbose_name': 'Lead',
'verbose_name_plural': 'Leads',
},
),
migrations.CreateModel( migrations.CreateModel(
name='Refund', name='Refund',
fields=[ fields=[
@ -636,15 +650,14 @@ class Migration(migrations.Migration):
name='Opportunity', name='Opportunity',
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('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')), ('stage', models.CharField(choices=[('discovery', 'Discovery'), ('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'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('canceled', 'Canceled')], default='new', max_length=20, verbose_name='Status')),
('probability', models.PositiveIntegerField(validators=[inventory.models.validate_probability])), ('probability', models.PositiveIntegerField(validators=[inventory.models.validate_probability])),
('expected_revenue', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Expected Revenue')),
('closing_date', models.DateField(blank=True, null=True, verbose_name='Closing Date')), ('closing_date', models.DateField(blank=True, null=True, verbose_name='Closing Date')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')), ('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')), ('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='django_ledger.customermodel')), ('customer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='django_ledger.customermodel')),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='inventory.dealer')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='inventory.dealer')),
('estimate', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='opportunity', to='django_ledger.estimatemodel')), ('estimate', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='opportunity', to='django_ledger.estimatemodel')),
('lead', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opportunity', to='inventory.lead')), ('lead', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opportunity', to='inventory.lead')),
@ -659,8 +672,8 @@ class Migration(migrations.Migration):
name='LeadStatusHistory', name='LeadStatusHistory',
fields=[ fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('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'), ('contacted', 'Contacted'), ('converted', 'Converted'), ('canceled', 'Canceled')], max_length=50, verbose_name='Old Status')), ('old_status', models.CharField(choices=[('new', 'New'), ('follow_up', 'Follow-up'), ('negotiation', 'Negotiation'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed')], 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')), ('new_status', models.CharField(choices=[('new', 'New'), ('follow_up', 'Follow-up'), ('negotiation', 'Negotiation'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed')], max_length=50, verbose_name='New Status')),
('changed_at', models.DateTimeField(auto_now_add=True, verbose_name='Changed At')), ('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')), ('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')), ('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='status_changes', to='inventory.staff')),
@ -675,6 +688,27 @@ class Migration(migrations.Migration):
name='staff', 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'), 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='Tasks',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('object_id', models.UUIDField()),
('title', models.CharField(max_length=255, verbose_name='Title')),
('description', models.TextField(blank=True, null=True, verbose_name='Description')),
('due_date', models.DateField(verbose_name='Due Date')),
('completed', models.BooleanField(default=False, verbose_name='Completed')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('assigned_to', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='tasks_assigned', to=settings.AUTH_USER_MODEL)),
('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='tasks_created', to=settings.AUTH_USER_MODEL)),
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tasks', to='inventory.dealer')),
],
options={
'verbose_name': 'Task',
'verbose_name_plural': 'Tasks',
},
),
migrations.CreateModel( migrations.CreateModel(
name='UserActivityLog', name='UserActivityLog',
fields=[ fields=[
@ -704,7 +738,7 @@ class Migration(migrations.Migration):
('logo', models.ImageField(blank=True, null=True, upload_to='logos/vendors', verbose_name='Logo')), ('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')), ('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')), ('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='vendors', to='inventory.dealer')),
('vendor_model', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='django_ledger.vendormodel', verbose_name='Vendor Model')), ('vendor_model', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='django_ledger.vendormodel', verbose_name='Vendor Model')),
], ],
options={ options={
'verbose_name': 'Vendor', 'verbose_name': 'Vendor',
@ -712,6 +746,11 @@ class Migration(migrations.Migration):
}, },
bases=(models.Model, inventory.mixins.LocalizedNameMixin), bases=(models.Model, inventory.mixins.LocalizedNameMixin),
), ),
migrations.AddField(
model_name='car',
name='vendor',
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='cars', to='inventory.vendor', verbose_name='Vendor'),
),
migrations.CreateModel( migrations.CreateModel(
name='CarReservation', name='CarReservation',
fields=[ fields=[

View File

@ -1,20 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-06 12:57
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'),
('inventory', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='vendor',
name='vendor_model',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='django_ledger.vendormodel', verbose_name='Vendor Model'),
),
]

View File

@ -1,19 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-06 14:31
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0002_alter_vendor_vendor_model'),
]
operations = [
migrations.AlterField(
model_name='car',
name='vendor',
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='cars', to='inventory.vendor', verbose_name='Vendor'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-06 14:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0003_alter_car_vendor'),
]
operations = [
migrations.AddField(
model_name='customer',
name='image',
field=models.ImageField(blank=True, null=True, upload_to='customers/', verbose_name='Image'),
),
]

View File

@ -1,20 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-06 14:54
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'),
('inventory', '0004_customer_image'),
]
operations = [
migrations.AddField(
model_name='customer',
name='customer_model',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='django_ledger.customermodel'),
),
]

View File

@ -1,22 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-06 15:38
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0005_customer_customer_model'),
]
operations = [
migrations.RemoveField(
model_name='customer',
name='middle_name',
),
migrations.AddField(
model_name='customer',
name='active',
field=models.BooleanField(default=True, verbose_name='Active'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-06 16:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0006_remove_customer_middle_name_customer_active'),
]
operations = [
migrations.AddField(
model_name='customer',
name='customer_type',
field=models.CharField(blank=True, choices=[('customer', 'Customer'), ('organization', 'Organization')], default='customer', max_length=15, null=True, verbose_name='Customer Type'),
),
]

View File

@ -1,32 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-07 09:33
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'),
('inventory', '0007_customer_customer_type'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RemoveField(
model_name='customer',
name='customer_type',
),
migrations.AddField(
model_name='organization',
name='customer_model',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='django_ledger.customermodel'),
),
migrations.AddField(
model_name='organization',
name='user',
field=models.OneToOneField(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='organization_profile', to=settings.AUTH_USER_MODEL),
preserve_default=False,
),
]

View File

@ -1,19 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-07 09:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0008_remove_customer_customer_type_and_more'),
]
operations = [
migrations.AddField(
model_name='organization',
name='email',
field=models.EmailField(default='t@tenhal.sa', max_length=254, verbose_name='Email'),
preserve_default=False,
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-07 09:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0009_organization_email'),
]
operations = [
migrations.AddField(
model_name='organization',
name='active',
field=models.BooleanField(default=True, verbose_name='Active'),
),
]

View File

@ -1,24 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-07 14:32
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0010_organization_active'),
]
operations = [
migrations.AddField(
model_name='lead',
name='organization',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='organization_leads', to='inventory.organization'),
),
migrations.AlterField(
model_name='lead',
name='customer',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='customer_leads', to='inventory.customer'),
),
]

View File

@ -1,23 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-08 10:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0011_lead_organization_alter_lead_customer'),
]
operations = [
migrations.AlterField(
model_name='customer',
name='dob',
field=models.DateField(blank=True, null=True, verbose_name='Date of Birth'),
),
migrations.AlterField(
model_name='customer',
name='national_id',
field=models.CharField(blank=True, max_length=10, null=True, unique=True, verbose_name='National ID'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-11 14:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0012_alter_customer_dob_alter_customer_national_id'),
]
operations = [
migrations.AddField(
model_name='lead',
name='converted_at',
field=models.DateTimeField(blank=True, null=True),
),
]

View File

@ -1,50 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-11 14:26
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0013_lead_converted_at'),
]
operations = [
migrations.AddField(
model_name='lead',
name='is_converted',
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name='lead',
name='status',
field=models.CharField(choices=[('new', 'New'), ('follow_up', 'Needs Follow-up'), ('negotiation', 'Under Negotiation'), ('won', 'Converted'), ('lost', 'Lost'), ('closed', 'Closed')], db_index=True, default='new', max_length=50, verbose_name='Status'),
),
migrations.AlterField(
model_name='leadstatushistory',
name='new_status',
field=models.CharField(choices=[('new', 'New'), ('follow_up', 'Needs Follow-up'), ('negotiation', 'Under Negotiation'), ('won', 'Converted'), ('lost', 'Lost'), ('closed', 'Closed')], max_length=50, verbose_name='New Status'),
),
migrations.AlterField(
model_name='leadstatushistory',
name='old_status',
field=models.CharField(choices=[('new', 'New'), ('follow_up', 'Needs Follow-up'), ('negotiation', 'Under Negotiation'), ('won', 'Converted'), ('lost', 'Lost'), ('closed', 'Closed')], max_length=50, verbose_name='Old Status'),
),
migrations.AlterField(
model_name='opportunity',
name='status',
field=models.CharField(choices=[('new', 'New'), ('follow_up', 'Needs Follow-up'), ('negotiation', 'Under Negotiation'), ('won', 'Converted'), ('lost', 'Lost'), ('closed', 'Closed')], default='new', max_length=20, verbose_name='Status'),
),
migrations.CreateModel(
name='LeadActivity',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('action', models.CharField(max_length=255)),
('notes', models.TextField(blank=True)),
('timestamp', models.DateTimeField(auto_now_add=True)),
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='inventory.staff')),
('lead', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='activities', to='inventory.lead')),
],
),
]

View File

@ -1,23 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-11 14:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0014_lead_is_converted_alter_lead_status_and_more'),
]
operations = [
migrations.AddField(
model_name='lead',
name='next_action',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Next Action'),
),
migrations.AddField(
model_name='lead',
name='next_action_date',
field=models.DateTimeField(blank=True, null=True, verbose_name='Next Action Date'),
),
]

View File

@ -1,21 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-11 15:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0015_lead_next_action_lead_next_action_date'),
]
operations = [
migrations.AlterField(
model_name='activity',
name='activity_type',
field=models.CharField(choices=[('call', 'Call'), ('sms', 'SMS'), ('email', 'Email'), ('whatsapp', 'WhatsApp'), ('visit', 'Visit'), ('negotiation', 'Negotiation'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed'), ('converted', 'Converted'), ('transfer', 'Transfer'), ('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'),
),
migrations.DeleteModel(
name='LeadActivity',
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-11 15:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0016_alter_activity_activity_type_delete_leadactivity'),
]
operations = [
migrations.AlterField(
model_name='activity',
name='activity_type',
field=models.CharField(choices=[('call', 'Call'), ('sms', 'SMS'), ('email', 'Email'), ('whatsapp', 'WhatsApp'), ('visit', 'Visit'), ('negotiation', 'Negotiation'), ('follow_up', 'Follow Up'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed'), ('converted', 'Converted'), ('transfer', 'Transfer'), ('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'),
),
]

View File

@ -1,44 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-13 15:19
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('inventory', '0017_alter_activity_activity_type'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RemoveField(
model_name='opportunity',
name='closed',
),
migrations.RemoveField(
model_name='opportunity',
name='status',
),
migrations.CreateModel(
name='Tasks',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('object_id', models.UUIDField()),
('title', models.CharField(max_length=255, verbose_name='Title')),
('description', models.TextField(blank=True, null=True, verbose_name='Description')),
('due_date', models.DateField(verbose_name='Due Date')),
('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
('assigned_to', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='tasks_assigned', to=settings.AUTH_USER_MODEL)),
('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='tasks_created', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Task',
'verbose_name_plural': 'Tasks',
},
),
]

View File

@ -1,20 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-13 16:22
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0018_remove_opportunity_closed_remove_opportunity_status_and_more'),
]
operations = [
migrations.AddField(
model_name='tasks',
name='dealer',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='tasks', to='inventory.dealer'),
preserve_default=False,
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-13 16:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0019_tasks_dealer'),
]
operations = [
migrations.AddField(
model_name='tasks',
name='completed',
field=models.BooleanField(default=False, verbose_name='Completed'),
),
]

View File

@ -1,28 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-14 10:29
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0020_tasks_completed'),
]
operations = [
migrations.AlterField(
model_name='lead',
name='status',
field=models.CharField(choices=[('new', 'New'), ('follow_up', 'Follow-up'), ('negotiation', 'Negotiation'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed')], db_index=True, default='new', max_length=50, verbose_name='Status'),
),
migrations.AlterField(
model_name='leadstatushistory',
name='new_status',
field=models.CharField(choices=[('new', 'New'), ('follow_up', 'Follow-up'), ('negotiation', 'Negotiation'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed')], max_length=50, verbose_name='New Status'),
),
migrations.AlterField(
model_name='leadstatushistory',
name='old_status',
field=models.CharField(choices=[('new', 'New'), ('follow_up', 'Follow-up'), ('negotiation', 'Negotiation'), ('won', 'Won'), ('lost', 'Lost'), ('closed', 'Closed')], max_length=50, verbose_name='Old Status'),
),
]

View File

@ -1,19 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-14 10:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0021_alter_lead_status_alter_leadstatushistory_new_status_and_more'),
]
operations = [
migrations.AddField(
model_name='opportunity',
name='expected_revenue',
field=models.DecimalField(decimal_places=2, default=0, max_digits=10, verbose_name='Expected Revenue'),
preserve_default=False,
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-14 10:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0022_opportunity_expected_revenue'),
]
operations = [
migrations.AlterField(
model_name='opportunity',
name='stage',
field=models.CharField(choices=[('discovery', 'Discovery'), ('proposal', 'Proposal'), ('negotiation', 'Negotiation'), ('closed_won', 'Closed Won'), ('closed_lost', 'Closed Lost')], max_length=20, verbose_name='Stage'),
),
]

View File

@ -1,20 +0,0 @@
# Generated by Django 5.1.7 on 2025-05-14 10:59
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'),
('inventory', '0023_alter_opportunity_stage'),
]
operations = [
migrations.AlterField(
model_name='opportunity',
name='customer',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to='django_ledger.customermodel'),
),
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -9,14 +9,16 @@
<form class="form" method="post"> <form class="form" method="post">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<button type="submit" name="add_lead" id="lead-save" class="btn btn-phoenix-primary"> <div class="d-flex justify-content-start">
<i class="fa-solid fa-floppy-disk"></i> {{ _("Save") }} <button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
</button> <!--<i class="bi bi-save"></i> -->
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-phoenix-secondary"> {{ _("Save") }}
<i class="fa-solid fa-ban"></i> {{ _("Cancel") }} </button>
</a> <a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -135,13 +135,13 @@
<!-- Form Actions --> <!-- Form Actions -->
<div class="d-flex justify-content-end gap-3"> <div class="d-flex justify-content-end gap-3">
<button type="reset" class="btn btn-phoenix-danger px-4"> <button type="reset" class="btn btn-phoenix-danger px-4">
<span class="fas fa-redo me-2"></span>{% trans "Reset" %} <span class="fas fa-redo me-1"></span>{% trans "Reset" %}
</button> </button>
<button type="submit" class="btn btn-phoenix-primary px-6"> <button type="submit" class="btn btn-phoenix-primary px-6">
{% if form.instance.pk %} {% if form.instance.pk %}
<span class="fas fa-save me-2"></span>{% trans "Update" %} <span class="fas fa-save me-1"></span>{% trans "Update" %}
{% else %} {% else %}
<span class="fas fa-plus me-2"></span>{% trans "Create" %} <span class="fas fa-plus me-1"></span>{% trans "Create" %}
{% endif %} {% endif %}
</button> </button>
</div> </div>

View File

@ -26,12 +26,11 @@
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<div class="col-12"> <div class="col-12">
<button class="btn btn-phoenix-primary" type="submit"> <button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<i class="fa-solid fa-floppy-disk"></i> {% trans "Save" %} <!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
</button> </button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-phoenix-secondary"> <a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
<i class="fa-solid fa-ban"></i> {{ _("Cancel") }}
</a>
</div> </div>
</form> </form>
</div> </div>

View File

@ -51,12 +51,30 @@
</div> </div>
<!-- Save and Cancel Buttons --> <!-- Save and Cancel Buttons -->
<div class="row g-1 mt-4"> {% comment %} <div class="row g-1 mt-4">
<div class="btn-group"> <div class="btn-group">
<button type="submit" class="btn btn-success btn-sm me-1">{% trans "Save" %}</button> <button type="submit" class="btn btn-sm btn-success me-1"><i class="fa-solid fa-floppy-disk"></i>{% trans "Save" %}</button>
<a href="{% url 'car_detail' car.pk %}" class="btn btn-secondary btn-sm">{% trans "Cancel" %}</a> <a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban"></i>{% trans "Cancel" %}</a>
</div> </div>
</div> {% endcomment %}
{% comment %} <div class="row justify-content-center g-1 mt-4">
<div class="col-auto">
<div class="btn-group shadow-sm">
<button type="submit" class="btn btn-success btn-sm me-2"><i class="fa-solid fa-floppy-disk me-1"></i>{% trans "Save" %}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-danger btn-sm"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</div>
</div> {% endcomment %}
<div class="d-flex justify-content-center mt-4">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div> </div>
</form> </form>
</div> </div>

View File

@ -35,13 +35,30 @@
{{ form|crispy }} {{ form|crispy }}
</div> </div>
</div> </div>
<div class="row g-1"> {% comment %} <div class="row g-1">
<div class="btn-group"> <div class="btn-group">
<button type="submit" class="btn btn-sm btn-success me-1">{% trans "Save" %}</button> <button type="submit" class="btn btn-sm btn-success me-1"><i class="fa-solid fa-floppy-disk"></i>{% trans "Save" %}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger">{% trans "Cancel" %}</a> <a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban"></i>{% trans "Cancel" %}</a>
</div> </div>
</div> {% endcomment %}
<div class="d-flex justify-content-center">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div> </div>
</form> </form>
</div> </div>

View File

@ -103,9 +103,10 @@
</div> </div>
<!-- Save and Cancel Buttons --> <!-- Save and Cancel Buttons -->
<div class="btn-group"> <div class="btn-group">
<button type="submit" class="btn btn-sm btn-success">{% trans "Save" %}</button> <button type="submit" class="btn btn-sm btn-success me-1">{% trans "Save" %}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger">{% trans "Cancel" %}</a> <a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger me-1">{% trans "Cancel" %}</a>
</div> </div>
</main> </main>
</div> </div>
</div> </div>

View File

@ -13,7 +13,14 @@
<form method="post" action=""> <form method="post" action="">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<button type="submit" class="btn btn-primary">{% trans 'Save' %}</button> <!--<button type="submit" class="btn btn-primary">{% trans 'Save' %}</button> -->
{% comment %} <button class="btn btn-sm btn-success me-1" type="submit"><i class="fa-solid fa-floppy-disk"></i>{{ _("Save") }}</button> {% endcomment %}
<div class="d-flex justify-content-start">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form> </form>
</div> </div>
</div> </div>

View File

@ -8,7 +8,8 @@
<div class="d-flex justify-content-between mb-2 p-6"> <div class="d-flex justify-content-between mb-2 p-6">
<span></span> <span></span>
<h3 class="text-center">{% trans "Expenses" %}</h3> <h3 class="text-center">{% trans "Expenses" %}</h3>
<a href="{% url 'item_expense_create' %}" class="btn btn-sm btn-success ">{% trans "Add Expense" %}</a> <a href="{% url 'item_expense_create' %}" class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{% trans "Add Expense" %}</a>
</div> </div>
<div class="mx-n4 px-4 mx-lg-n6 px-lg-6 pt-7 border-y"> <div class="mx-n4 px-4 mx-lg-n6 px-lg-6 pt-7 border-y">

View File

@ -19,7 +19,11 @@
<form method="post" action=""> <form method="post" action="">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}
<button type="submit" class="btn btn-sm btn-primary">{% trans 'Save' %}</button> <div class="d-flex justify-content-start">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i> {{ _("Save") }}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form> </form>
</div> </div>
</div> </div>

View File

@ -8,7 +8,8 @@
<div class="d-flex justify-content-between"> <div class="d-flex justify-content-between">
<h3 class="mb-2">{% trans "Services" %}</h3> <h3 class="mb-2">{% trans "Services" %}</h3>
<a href="{% url 'item_service_create' %}" class="btn btn-sm btn-phoenix-primary ">{% trans "Add Service" %}</a> <a href="{% url 'item_service_create' %}" class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{% trans "Add Service" %}</a>
</div> </div>

View File

@ -26,12 +26,12 @@
{% for error in form.errors %} {% for error in form.errors %}
<div class="text-danger">{{ error }}</div> <div class="text-danger">{{ error }}</div>
{% endfor %} {% endfor %}
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-start">
<button class="btn btn-sm btn-success me-1" type="submit"> <button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> --> <!--<i class="bi bi-save"></i> -->
{{ _("Save") }} {{ _("Save") }}
</button> </button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger">{% trans "Cancel" %}</a> <a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div> </div>
</form> </form>
</div> </div>

View File

@ -8,7 +8,7 @@
<div class="d-flex justify-content-between mb-2"> <div class="d-flex justify-content-between mb-2">
<h3 class="">{% trans "Bank Accounts" %}</h3> <h3 class="">{% trans "Bank Accounts" %}</h3>
<a href="{% url 'bank_account_create' %}" class="btn btn-sm btn-phoenix-primary ">{% trans "Add Bank Account" %}</a> <a href="{% url 'bank_account_create' %}" class="btn btn-md btn-phoenix-primary"><i class="fa fa-plus me-2"></i>{% trans "Add Bank Account" %}</a>
</div> </div>
<div class="table-responsive px-1 scrollbar"> <div class="table-responsive px-1 scrollbar">

View File

@ -37,10 +37,12 @@
</div> </div>
<!-- Buttons --> <!-- Buttons -->
<div class="mt-5 text-center">
<button type="submit" class="btn btn-success me-2" {% if not items %}disabled{% endif %}><i class="fa-solid fa-floppy-disk"></i>{% trans "Save" %}</button> <div class="d-flex mt-5 justify-content-center">
<a href="{% url 'bill_list' %}" class="btn btn-secondary"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</a> <button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div> </div>
</form> </form>
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -13,7 +13,7 @@
<div class="d-flex flex-column min-vh-100"> <div class="d-flex flex-column min-vh-100">
<div class="d-grid gap-2 d-md-flex justify-content-md-end"> <div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a href="{% url 'bill_create' %}" class="btn btn-md btn-phoenix-primary"> <a href="{% url 'bill_create' %}" class="btn btn-md btn-phoenix-primary">
<i class="fa fa-plus"></i> <i class="fa fa-plus me-2"></i>
{% trans 'New Bill' %}</a> {% trans 'New Bill' %}</a>
</div> </div>
<div class="d-flex flex-column flex-sm-grow-1 p-4"> <div class="d-flex flex-column flex-sm-grow-1 p-4">

View File

@ -26,11 +26,15 @@
<div class="text-danger">{{ error }}</div> <div class="text-danger">{{ error }}</div>
{% endfor %} {% endfor %}
<div class="d-flex justify-content-start"> <div class="d-flex justify-content-start">
<button class="btn btn-sm btn-phoenix-success me-1" type="submit">
<i class="fa-solid fa-floppy-disk"></i> {{ _("Save") }} <button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
</button> </button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-phoenix-secondary"><i class="fa-solid fa-ban"></i> {% trans "Cancel"|capfirst %}</a>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>

View File

@ -13,7 +13,7 @@
<div class="row mt-4"> <div class="row mt-4">
<div class="d-grid gap-2 d-md-flex justify-content-md-end"> <div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a href="{% url 'account_create' %}" class="btn btn-md btn-phoenix-primary"> <a href="{% url 'account_create' %}" class="btn btn-md btn-phoenix-primary">
<i class="fa fa-plus"></i> <i class="fa fa-plus me-2"></i>
{% trans 'New Account' %}</a> {% trans 'New Account' %}</a>
</div> </div>
<h3 class="mb-3"> <h3 class="mb-3">

View File

@ -13,8 +13,8 @@
{{ form|crispy }} {{ form|crispy }}
</div> </div>
<div class="mt-5 text-center"> <div class="mt-5 text-center">
<button type="submit" class="btn btn-success me-2"><i class="fa-solid fa-floppy-disk"></i>{% trans "Save" %}</button> <button type="submit" class="btn btn-success me-2"><i class="fa-solid fa-floppy-disk me-1"></i>{% trans "Save" %}</button>
<a href="{% url 'journalentry_list' ledger.pk %}" class="btn btn-secondary"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</a> <a href="{% url 'journalentry_list' ledger.pk %}" class="btn btn-secondary"><i class="fa-solid fa-ban me-1"></i> {% trans "Cancel" %}</a>
</div> </div>
</form> </form>
</div> </div>

View File

@ -12,10 +12,17 @@
<div class="row g-3"> <div class="row g-3">
{{ form|crispy }} {{ form|crispy }}
</div> </div>
<div class="mt-5 text-center"> {% comment %} <div class="mt-5 text-center">
<button type="submit" class="btn btn-success me-2"><i class="fa-solid fa-floppy-disk"></i>{% trans "Save" %}</button> <button type="submit" class="btn btn-success me-2"><i class="fa-solid fa-floppy-disk"></i>{% trans "Save" %}</button>
<a href="{% url 'ledger_list' %}" class="btn btn-secondary"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</a> <a href="{% url 'ledger_list' %}" class="btn btn-danger"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</a>
</div> </div> {% endcomment %}
<div class="d-flex justify-content-center">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form> </form>
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -10,7 +10,7 @@
</div> </div>
<div class="d-grid gap-2 d-md-flex justify-content-md-end"> <div class="d-grid gap-2 d-md-flex justify-content-md-end">
<a href="{% url 'ledger_create' %}" class="btn btn-md btn-phoenix-primary"> <a href="{% url 'ledger_create' %}" class="btn btn-md btn-phoenix-primary">
<i class="fa fa-plus"></i> <i class="fa fa-plus me-2"></i>
{% trans 'Create Ledger' %}</a> {% trans 'Create Ledger' %}</a>
</div> </div>
<div class="table-responsive px-1 scrollbar mt-3"> <div class="table-responsive px-1 scrollbar mt-3">

View File

@ -12,13 +12,8 @@
{% csrf_token %} {% csrf_token %}
{{ redirect_field }} {{ redirect_field }}
{{ form|crispy }} {{ form|crispy }}
<button class="btn btn-phoenix-primary" type="submit"> <button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>{{ _("Save") }}</button>
<i class="fa-solid fa-floppy-disk"></i> <a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
{{ _("Save") }}
</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-phoenix-secondary">
<i class="fa-solid fa-ban"></i> {% trans "Cancel" %}
</a>
</form> </form>
</div> </div>
</div> </div>

View File

@ -50,21 +50,34 @@
<input class="form-control quantity" type="number" placeholder="Quantity" name="quantity[]" required> <input class="form-control quantity" type="number" placeholder="Quantity" name="quantity[]" required>
</div> </div>
<div class="mb-2 col-sm-3 col-md-3"> <div class="mb-2 col-sm-3 col-md-3">
<button class="btn btn-sm btn-danger removeBtn"><i class="fa-solid fa-trash"></i> {{ _("Remove") }}</button> <button class="btn btn-sm btn-danger removeBtn"><i class="fa-solid fa-trash me-1"></i> {{ _("Remove") }}</button>
</div> </div>
</div> </div>
</div> </div>
<div class="col-12"> <div class="col-12">
<button id="addMoreBtn" class="btn btn-sm btn-primary"><i class="fa-solid fa-plus"></i> {{ _("Add More")}}</button> <button id="addMoreBtn" class="btn btn-sm btn-primary"><i class="fa-solid fa-plus me-2"></i> {{ _("Add More")}}</button>
</div> </div>
</div> </div>
</div> </div>
<!-- Buttons --> <!-- Buttons -->
<div class="mt-5 text-center"> {% comment %} <div class="mt-5 text-center">
<button type="submit" class="btn btn-success me-2" {% if not items %}disabled{% endif %}><i class="fa-solid fa-floppy-disk"></i> {% trans "Save" %}</button> <button type="submit" class="btn btn-success me-2" {% if not items %}disabled{% endif %}><i class="fa-solid fa-floppy-disk me-1"></i> {% trans "Save" %}</button>
<a href="{% url 'estimate_list' %}" class="btn btn-secondary"><i class="fa-solid fa-ban"></i> {% trans "Cancel" %}</a> <a href="{% url 'estimate_list' %}" class="btn btn-danger"><i class="fa-solid fa-ban me-1"></i> {% trans "Cancel" %}</a>
</div> </div> {% endcomment %}
<div class="d-flex justify-content-center">
<button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<!--<i class="bi bi-save"></i> -->
{{ _("Save") }}
</button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div>
</form> </form>
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -46,7 +46,7 @@
<td class="align-middle product white-space-nowrap"> <td class="align-middle product white-space-nowrap">
<a href="{% url 'estimate_detail' estimate.pk %}" <a href="{% url 'estimate_detail' estimate.pk %}"
class="btn btn-sm btn-phoenix-success"> class="btn btn-sm btn-phoenix-success">
<i class="fa-regular fa-eye"></i> <i class="fa-regular fa-eye me-1"></i>
{% trans "view"|capfirst %} {% trans "view"|capfirst %}
</a> </a>
</td> </td>

View File

@ -54,13 +54,14 @@
{% endif %} {% endif %}
</td> </td>
<td class="align-middle product white-space-nowrap">{{ invoice.created }}</td> <td class="align-middle product white-space-nowrap">{{ invoice.created }}</td>
<td class="text-center"> <td class="align-middle product white-space-nowrap">
<a href="{% url 'invoice_detail' invoice.pk %}" <a href="{% url 'invoice_detail' invoice.pk %}"
class="btn btn-sm btn-phoenix-success"> class="btn btn-sm btn-phoenix-success">
<i class="fa-regular fa-eye"></i> <i class="fa-regular fa-eye me-1"></i>
{% trans "View" %} {% trans "View" %}
</a> </a>
</td> </td>
</tr> </tr>
{% empty %} {% empty %}
<tr> <tr>

View File

@ -41,8 +41,8 @@
{% endif %} {% endif %}
<td class="align-middle product white-space-nowrap py-0">{{ journal.timestamp }}</td> <td class="align-middle product white-space-nowrap py-0">{{ journal.timestamp }}</td>
<td class="align-middle product white-space-nowrap py-0">{{ journal.description }}</td> <td class="align-middle product white-space-nowrap py-0">{{ journal.description }}</td>
<td class=""> <td class="align-middle product white-space-nowrap">
<a href="{% url 'payment_details' journal.pk %}" class="btn btn-sm btn-phoenix-primary"><i class="fa-solid fa-eye"></i> {% trans "View Tranactions" %}</a> <a href="{% url 'payment_details' journal.pk %}" class="btn btn-sm btn-phoenix-primary"><i class="fa-solid fa-eye me-1"></i> {% trans "View Tranactions"|capfirst %}</a>
</td> </td>
</tr> </tr>
{% empty %} {% empty %}

View File

@ -34,13 +34,14 @@
{% for error in form.errors %} {% for error in form.errors %}
<div class="text-danger">{{ error }}</div> <div class="text-danger">{{ error }}</div>
{% endfor %} {% endfor %}
<div class="d-flex mb-3"> <div class="d-flex justify-content-start">
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-phoenix-primary me-2 px-6">{% trans "Cancel"|capfirst %}</a> <button class="btn btn-sm btn-success me-2" type="submit"><i class="fa-solid fa-floppy-disk me-1"></i>
<button class="btn btn-primary" type="submit">
<!--<i class="bi bi-save"></i> --> <!--<i class="bi bi-save"></i> -->
{{ _("Save") }} {{ _("Save") }}
</button> </button>
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-sm btn-danger"><i class="fa-solid fa-ban me-1"></i>{% trans "Cancel" %}</a>
</div> </div>
</form> </form>
</div> </div>
</div> </div>

View File

@ -15,7 +15,7 @@
<div class="col-auto"> <div class="col-auto">
<div class="d-md-flex justify-content-between"> <div class="d-md-flex justify-content-between">
<div> <div>
<a href="{% url 'vendor_create' %}" class="btn btn-primary me-4"><span class="fas fa-plus me-2"></span>{{ _("Add Vendor") }}</a> <a href="{% url 'vendor_create' %}" class="btn btn-md btn-phoenix-primary"><span class="fas fa-plus me-2"></span>{{ _("Add Vendor") }}</a>
</div> </div>
</div> </div>