fix vendor
This commit is contained in:
parent
cb4366f028
commit
9d6d69f1d0
@ -16,7 +16,6 @@ from django.utils.decorators import method_decorator
|
||||
from inventory import models as inventory_models
|
||||
|
||||
|
||||
|
||||
class LoginView(APIView):
|
||||
permission_classes = [permissions.AllowAny,]
|
||||
|
||||
|
||||
@ -58,7 +58,6 @@ import django_tables2 as tables
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class AdditionalServiceForm(forms.ModelForm):
|
||||
"""
|
||||
A form used for creating and updating instances of the
|
||||
@ -292,10 +291,8 @@ class CarForm(
|
||||
self.fields["id_car_model"].choices = [
|
||||
(obj.id_car_model, obj.get_local_name()) for obj in queryset
|
||||
]
|
||||
if "vendor" in self.fields:
|
||||
self.fields["vendor"].queryset = ledger_models.VendorModel.objects.filter(
|
||||
active=True
|
||||
)
|
||||
# if "vendor" in self.fields:
|
||||
# self.fields["vendor"].queryset = dealer.vendors.all()
|
||||
|
||||
|
||||
class CarUpdateForm(forms.ModelForm, AddClassMixin):
|
||||
@ -482,7 +479,18 @@ class VendorForm(forms.ModelForm):
|
||||
:ivar Meta: Inner class to define metadata for the Vendor form.
|
||||
:type Meta: Type[VendorForm.Meta]
|
||||
"""
|
||||
phone_number = forms.CharField(label=_("Phone Number"),min_length=10,max_length=10,validators=[RegexValidator(regex='^05[0-9]{8}$')], required=True)
|
||||
phone_number = forms.CharField(
|
||||
label=_("Phone Number"),
|
||||
min_length=10,
|
||||
max_length=13,
|
||||
validators=[
|
||||
RegexValidator(
|
||||
regex=r'^(\+9665|05)[0-9]{8}$',
|
||||
message=_("Enter a valid Saudi phone number (05XXXXXXXX or +9665XXXXXXXX)")
|
||||
)
|
||||
],
|
||||
required=True
|
||||
)
|
||||
contact_person = forms.CharField(label=_("Contact Person"))
|
||||
|
||||
class Meta:
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.1.7 on 2025-05-04 16:07
|
||||
# Generated by Django 5.1.7 on 2025-05-05 16:32
|
||||
|
||||
import datetime
|
||||
import django.core.validators
|
||||
@ -17,17 +17,11 @@ class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
# ('appointment', '0002_alter_workinghours_options'),
|
||||
('appointment', '0001_initial'),
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
('django_ledger', '0021_alter_bankaccountmodel_account_model_and_more'),
|
||||
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),
|
||||
]
|
||||
|
||||
operations = [
|
||||
@ -92,7 +86,7 @@ class Migration(migrations.Migration):
|
||||
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')),
|
||||
('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')),
|
||||
],
|
||||
@ -120,7 +114,7 @@ class Migration(migrations.Migration):
|
||||
('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')),
|
||||
('item', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='django_ledger.itemmodel', verbose_name='Item')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Additional Services',
|
||||
@ -140,7 +134,7 @@ class Migration(migrations.Migration):
|
||||
('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=settings.DJANGO_LEDGER_VENDOR_MODEL, verbose_name='Vendor')),
|
||||
('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={
|
||||
@ -322,7 +316,7 @@ class Migration(migrations.Migration):
|
||||
('logo', models.ImageField(blank=True, null=True, upload_to='logos/users', verbose_name='Logo')),
|
||||
('joined_at', models.DateTimeField(auto_now_add=True, verbose_name='Joined At')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated At')),
|
||||
('entity', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.DJANGO_LEDGER_ENTITY_MODEL)),
|
||||
('entity', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='django_ledger.entitymodel')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='dealer', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
@ -339,7 +333,7 @@ class Migration(migrations.Migration):
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=100)),
|
||||
('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='auth.group', verbose_name='')),
|
||||
('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='auth.group', verbose_name='Group')),
|
||||
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='groups', to='inventory.dealer')),
|
||||
],
|
||||
),
|
||||
@ -437,13 +431,13 @@ class Migration(migrations.Migration):
|
||||
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)),
|
||||
('bill_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_cash', to='django_ledger.accountmodel')),
|
||||
('bill_prepaid_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_prepaid', to='django_ledger.accountmodel')),
|
||||
('bill_unearned_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bill_unearned', to='django_ledger.accountmodel')),
|
||||
('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)),
|
||||
('invoice_cash_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_cash', to='django_ledger.accountmodel')),
|
||||
('invoice_prepaid_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_prepaid', to='django_ledger.accountmodel')),
|
||||
('invoice_unearned_account', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='invoice_unearned', to='django_ledger.accountmodel')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
@ -485,7 +479,7 @@ class Migration(migrations.Migration):
|
||||
('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=settings.DJANGO_LEDGER_CUSTOMER_MODEL)),
|
||||
('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')),
|
||||
@ -584,12 +578,12 @@ class Migration(migrations.Migration):
|
||||
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)),
|
||||
('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')),
|
||||
('estimate', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sale_orders', to='django_ledger.estimatemodel', verbose_name='Estimate')),
|
||||
('invoice', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sale_orders', to='django_ledger.invoicemodel', verbose_name='Invoice')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['-created'],
|
||||
@ -599,15 +593,15 @@ class Migration(migrations.Migration):
|
||||
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)),
|
||||
('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)),
|
||||
('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)),
|
||||
('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)),
|
||||
('customer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='schedules', to='django_ledger.customermodel')),
|
||||
('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)),
|
||||
],
|
||||
@ -650,9 +644,9 @@ class Migration(migrations.Migration):
|
||||
('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
|
||||
('closed', models.BooleanField(default=False, verbose_name='Closed')),
|
||||
('car', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='inventory.car', verbose_name='Car')),
|
||||
('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='opportunities', to=settings.DJANGO_LEDGER_CUSTOMER_MODEL)),
|
||||
('customer', models.ForeignKey(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')),
|
||||
('estimate', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='opportunity', to=settings.DJANGO_LEDGER_ESTIMATE_MODEL)),
|
||||
('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')),
|
||||
('staff', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='owner', to='inventory.staff', verbose_name='Owner')),
|
||||
],
|
||||
@ -710,6 +704,7 @@ class Migration(migrations.Migration):
|
||||
('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')),
|
||||
('vendor_model', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='django_ledger.vendormodel', verbose_name='Vendor Model')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Vendor',
|
||||
@ -783,6 +778,7 @@ class Migration(migrations.Migration):
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='payments', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Payment History',
|
||||
'verbose_name_plural': 'Payment Histories',
|
||||
'ordering': ['-payment_date'],
|
||||
'indexes': [models.Index(fields=['transaction_id'], name='inventory_p_transac_9469f3_idx'), models.Index(fields=['user'], name='inventory_p_user_id_c31626_idx'), models.Index(fields=['status'], name='inventory_p_status_abcb77_idx'), models.Index(fields=['payment_date'], name='inventory_p_payment_b3068c_idx')],
|
||||
|
||||
20
inventory/migrations/0002_alter_vendor_vendor_model.py
Normal file
20
inventory/migrations/0002_alter_vendor_vendor_model.py
Normal file
@ -0,0 +1,20 @@
|
||||
# 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'),
|
||||
),
|
||||
]
|
||||
19
inventory/migrations/0003_alter_car_vendor.py
Normal file
19
inventory/migrations/0003_alter_car_vendor.py
Normal file
@ -0,0 +1,19 @@
|
||||
# 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'),
|
||||
),
|
||||
]
|
||||
@ -19,7 +19,7 @@ from phonenumber_field.modelfields import PhoneNumberField
|
||||
from django.utils.timezone import now
|
||||
from django.contrib.auth.models import Group
|
||||
|
||||
from inventory.utils import get_user_type
|
||||
from inventory.utils import get_user_type, to_dict
|
||||
from .mixins import LocalizedNameMixin
|
||||
from django_ledger.models import EntityModel, ItemModel,EstimateModel,InvoiceModel,AccountModel,EntityManagementModel
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
@ -376,7 +376,7 @@ class Car(models.Model):
|
||||
)
|
||||
|
||||
vendor = models.ForeignKey(
|
||||
VendorModel,
|
||||
"Vendor",
|
||||
models.DO_NOTHING,
|
||||
related_name="cars",
|
||||
verbose_name=_("Vendor"),
|
||||
@ -1471,6 +1471,9 @@ class Vendor(models.Model, LocalizedNameMixin):
|
||||
vrn = models.CharField(
|
||||
max_length=15, unique=True, verbose_name=_("VAT Registration Number")
|
||||
)
|
||||
vendor_model = models.ForeignKey(
|
||||
VendorModel, on_delete=models.DO_NOTHING, verbose_name=_("Vendor Model"),null=True,blank=True
|
||||
)
|
||||
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"))
|
||||
@ -1491,6 +1494,56 @@ class Vendor(models.Model, LocalizedNameMixin):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def create_vendor_model(self):
|
||||
entity = self.dealer.entity
|
||||
additionals = to_dict(self)
|
||||
if not self.vendor_model:
|
||||
vendor = entity.create_vendor(
|
||||
vendor_model_kwargs={
|
||||
"vendor_name": self.name,
|
||||
"vendor_number": self.crn,
|
||||
"address_1": self.address,
|
||||
"phone": self.phone_number,
|
||||
"email": self.email,
|
||||
"tax_id_number": self.vrn,
|
||||
"active": True,
|
||||
"hidden": False,
|
||||
"additional_info": additionals,
|
||||
}
|
||||
)
|
||||
self.vendor_model = vendor
|
||||
self.save()
|
||||
|
||||
def update_vendor_model(self):
|
||||
additionals = to_dict(self)
|
||||
self.vendor_model.vendor_name = self.name
|
||||
self.vendor_model.vendor_number = self.crn
|
||||
self.vendor_model.address_1 = self.address
|
||||
self.vendor_model.phone = self.phone_number
|
||||
self.vendor_model.email = self.email
|
||||
self.vendor_model.tax_id_number = self.vrn
|
||||
self.vendor_model.additional_info = additionals
|
||||
self.vendor_model.save()
|
||||
|
||||
def create_vendor_account(self,role):
|
||||
entity = self.dealer.entity
|
||||
coa = entity.get_default_coa()
|
||||
last_account = entity.get_all_accounts().filter(role=role).order_by('-created').first()
|
||||
|
||||
if len(last_account.code) == 4:
|
||||
code = f"{int(last_account.code)}{1:03d}"
|
||||
elif len(last_account.code) > 4:
|
||||
code = f"{int(last_account.code)+1}"
|
||||
|
||||
if not entity.get_all_accounts().filter(name=self.name, role=role,coa_model=coa,balance_type="credit",active=True).exists():
|
||||
entity.create_account(
|
||||
name=self.name,
|
||||
code=code,
|
||||
role=role,
|
||||
coa_model=coa,
|
||||
balance_type="credit",
|
||||
active=True
|
||||
)
|
||||
|
||||
class Payment(models.Model):
|
||||
METHOD_CHOICES = [
|
||||
|
||||
@ -190,41 +190,10 @@ def create_ledger_vendor(sender, instance, created, **kwargs):
|
||||
:return: None
|
||||
"""
|
||||
if created:
|
||||
entity = EntityModel.objects.filter(admin=instance.dealer.user).first()
|
||||
additionals = to_dict(instance)
|
||||
vendor = entity.create_vendor(
|
||||
vendor_model_kwargs={
|
||||
"vendor_name": instance.name,
|
||||
"vendor_number": instance.crn,
|
||||
"address_1": instance.address,
|
||||
"phone": instance.phone_number,
|
||||
"email": instance.email,
|
||||
"tax_id_number": instance.vrn,
|
||||
"active": True,
|
||||
"hidden": False,
|
||||
"additional_info": additionals,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
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}"
|
||||
if len(last_account.code) == 4:
|
||||
code = f"{int(last_account.code)}{1:03d}"
|
||||
elif len(last_account.code) > 4:
|
||||
code = f"{int(last_account.code)+1}"
|
||||
|
||||
account = entity.create_account(
|
||||
name=instance.name,
|
||||
code=code,
|
||||
role=roles.LIABILITY_CL_ACC_PAYABLE,
|
||||
coa_model=coa,
|
||||
balance_type="credit",
|
||||
active=True
|
||||
)
|
||||
print(f"VendorModel created for Vendor: {instance.name}")
|
||||
instance.create_vendor_model()
|
||||
instance.create_vendor_account(roles.LIABILITY_CL_ACC_PAYABLE)
|
||||
else:
|
||||
instance.update_vendor_model()
|
||||
|
||||
@receiver(post_save, sender=models.CustomerModel)
|
||||
def create_customer_user(sender, instance, created, **kwargs):
|
||||
|
||||
@ -202,15 +202,15 @@ urlpatterns = [
|
||||
path('crm/calender/', views.EmployeeCalendarView.as_view(), name='calendar_list'),
|
||||
# Vendor URLs
|
||||
path("vendors", views.VendorListView.as_view(), name="vendor_list"),
|
||||
path("vendors/<uuid:pk>/", views.vendorDetailView, name="vendor_detail"),
|
||||
path("vendors/<int:pk>/", views.vendorDetailView, name="vendor_detail"),
|
||||
path("vendors/create/", views.VendorCreateView.as_view(), name="vendor_create"),
|
||||
path(
|
||||
"vendors/<uuid:pk>/update/",
|
||||
"vendors/<int:pk>/update/",
|
||||
views.VendorUpdateView.as_view(),
|
||||
name="vendor_update",
|
||||
),
|
||||
path(
|
||||
"vendors/<uuid:pk>/delete/",
|
||||
"vendors/<int:pk>/delete/",
|
||||
views.delete_vendor,
|
||||
name="vendor_delete",
|
||||
),
|
||||
|
||||
@ -579,7 +579,7 @@ class CarCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
||||
def get_form(self, form_class=None):
|
||||
form = super().get_form(form_class)
|
||||
dealer = get_user_type(self.request)
|
||||
form.fields["vendor"].queryset = dealer.entity.get_vendors().filter(active=True)
|
||||
form.fields["vendor"].queryset = dealer.vendors.all()
|
||||
return form
|
||||
|
||||
def get_success_url(self):
|
||||
@ -595,6 +595,12 @@ class CarCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
||||
messages.success(self.request, _("Car saved successfully"))
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
dealer = get_user_type(self.request)
|
||||
context["vendor_exists"] = dealer.vendors.exists()
|
||||
|
||||
return context
|
||||
|
||||
def car_history(request, pk):
|
||||
"""
|
||||
@ -1323,7 +1329,7 @@ class CarUpdateView(
|
||||
form = super().get_form(form_class)
|
||||
dealer = get_user_type(self.request)
|
||||
print(dealer.get_vendors())
|
||||
form.fields["vendor"].queryset = dealer.get_vendors()
|
||||
form.fields["vendor"].queryset = dealer.vendors.all()
|
||||
return form
|
||||
|
||||
class CarDeleteView(
|
||||
@ -2193,17 +2199,17 @@ class VendorListView(LoginRequiredMixin, ListView):
|
||||
ordered by their creation date in descending order.
|
||||
:type ordering: list
|
||||
"""
|
||||
model = VendorModel
|
||||
model = models.Vendor
|
||||
context_object_name = "vendors"
|
||||
paginate_by = 10
|
||||
template_name = "vendors/vendors_list.html"
|
||||
ordering = ["-created"]
|
||||
# ordering = ["-created"]
|
||||
|
||||
def get_queryset(self):
|
||||
query = self.request.GET.get("q")
|
||||
dealer = get_user_type(self.request)
|
||||
vendors = dealer.entity.get_vendors().filter(active=True)
|
||||
return apply_search_filters(vendors, query)
|
||||
# def get_queryset(self):
|
||||
# query = self.request.GET.get("q")
|
||||
# dealer = get_user_type(self.request)
|
||||
# vendors = dealer.entity.get_vendors().filter(active=True)
|
||||
# return apply_search_filters(vendors, query)
|
||||
|
||||
|
||||
@login_required
|
||||
@ -2295,24 +2301,24 @@ class VendorUpdateView(
|
||||
success_url = reverse_lazy("vendor_list")
|
||||
success_message = _("Vendor updated successfully")
|
||||
|
||||
def get_initial(self):
|
||||
initial = super().get_initial()
|
||||
initial = self.object.additional_info
|
||||
return initial
|
||||
# def get_initial(self):
|
||||
# initial = super().get_initial()
|
||||
# initial = self.object.additional_info
|
||||
# return initial
|
||||
|
||||
def form_valid(self, form):
|
||||
instance = form.save(commit=False)
|
||||
|
||||
instance.vendor_name = self.request.POST["name"]
|
||||
instance.vendor_number = self.request.POST["crn"]
|
||||
instance.address_1 = self.request.POST["address"]
|
||||
instance.phone = self.request.POST["phone_number"]
|
||||
instance.email = self.request.POST["email"]
|
||||
instance.tax_id_number = self.request.POST["vrn"]
|
||||
additionals = form.cleaned_data
|
||||
additionals["phone_number"] = str(additionals["phone_number"])
|
||||
instance.additional_info = additionals
|
||||
instance.save()
|
||||
# instance = form.save(commit=False)
|
||||
print(self.request.POST)
|
||||
# instance.vendor_name = self.request.POST["name"]
|
||||
# instance.vendor_number = self.request.POST["crn"]
|
||||
# instance.address_1 = self.request.POST["address"]
|
||||
# instance.phone = self.request.POST["phone_number"]
|
||||
# instance.email = self.request.POST["email"]
|
||||
# instance.tax_id_number = self.request.POST["vrn"]
|
||||
# additionals = form.cleaned_data
|
||||
# additionals["phone_number"] = str(additionals["phone_number"])
|
||||
# instance.additional_info = additionals
|
||||
# instance.save()
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
|
||||
BIN
static/images/logos/vendors/image.png
vendored
Normal file
BIN
static/images/logos/vendors/image.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
BIN
static/images/logos/vendors/logo-for-the-word-daju-48a980.jpg
vendored
Normal file
BIN
static/images/logos/vendors/logo-for-the-word-daju-48a980.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
@ -20,28 +20,28 @@
|
||||
{% if not car.ready %}
|
||||
<div class="alert alert-outline-warning d-flex align-items-center" role="alert">
|
||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
||||
<p class="mb-0 flex-1">{{ _("This car information is not complete , please add colors and finances before making it ready for sale .") }}</p>
|
||||
<p class="mb-0 flex-1">{{ _("This car information is not complete , please add colors and finances before making it ready for sale .") }}</p>
|
||||
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if car.get_transfer.status == "draft" %}
|
||||
<div class="alert alert-outline-info d-flex align-items-center" role="alert">
|
||||
<div class="alert alert-outline-info d-flex align-items-center" role="alert">
|
||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
||||
<p class="mb-0 flex-1">{{ _("Action Required , Please Approved The Tranfer Request Of This Car .") }}</p>
|
||||
<p class="mb-0 flex-1">{{ _("Action Required , Please Approved The Tranfer Request Of This Car .") }}</p>
|
||||
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if car.get_transfer and car.get_transfer.status == "approved" %}
|
||||
<div class="alert alert-outline-info d-flex align-items-center" role="alert">
|
||||
<div class="alert alert-outline-info d-flex align-items-center" role="alert">
|
||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
||||
<p class="mb-0 flex-1">{{ _("Car Is In Transfer Process To Another Dealer, Please Wait For The Acceptance .") }}</p>
|
||||
<p class="mb-0 flex-1">{{ _("Car Is In Transfer Process To Another Dealer, Please Wait For The Acceptance .") }}</p>
|
||||
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if car.is_reserved %}
|
||||
<div class="alert alert-outline-warning d-flex align-items-center" role="alert">
|
||||
<div class="alert alert-outline-warning d-flex align-items-center" role="alert">
|
||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
||||
<p class="mb-0 flex-1">{{ _("This car is reserved until ") }}{{ car.get_reservation.reserved_until }}</p>
|
||||
<p class="mb-0 flex-1">{{ _("This car is reserved until ") }}{{ car.get_reservation.reserved_until }}</p>
|
||||
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
@ -98,7 +98,7 @@
|
||||
{% if car.vendor %}
|
||||
<tr>
|
||||
<th>{% trans "Vendor"|capfirst %}</th>
|
||||
<td>{{ car.vendor.vendor_name }}</td>
|
||||
<td>{{ car.vendor.name }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
@ -361,7 +361,7 @@
|
||||
<p class="card-header rounded-top fw-bold">{% trans 'Transfer Details' %}</p>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive scrollbar mb-3">
|
||||
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
||||
<table class="table table-sm fs-9 mb-0 overflow-hidden">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Action" %}</th>
|
||||
@ -373,7 +373,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
<td><span class="badge badge-phoenix badge-phoenix-info">Transfer</span></td>
|
||||
<td>
|
||||
@ -396,11 +396,11 @@
|
||||
<a class="btn btn-sm btn-phoenix-success" href="{% url 'transfer_detail' car.get_transfer.pk %}">Approve</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<td>
|
||||
<a class="btn btn-sm btn-phoenix-success" href="{% url 'transfer_detail' car.get_transfer.pk %}?action=cancel">Cancel</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -6,14 +6,24 @@
|
||||
height: auto;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.disabled{
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- JavaScript Section -->
|
||||
|
||||
<script src="{% static 'vendors/zxing/index.min.js' %}"></script>
|
||||
<script src="{% static 'vendors/tesseract/tesseract.min.js' %}"></script>
|
||||
|
||||
<div class=" container-fluid m-0">
|
||||
{% if not vendor_exists %}
|
||||
<div class="alert alert-outline-warning d-flex align-items-center" role="alert">
|
||||
<i class="fa-solid fa-circle-info fs-6"></i>
|
||||
<p class="mb-0 flex-1">{{ _("Please Add A Vendor, Before Adding A Car .") }}</p>
|
||||
<button class="btn-close" type="button" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class=" container-fluid m-0 {% if not vendor_exists %}disabled{% endif %}">
|
||||
<form method="post" id="carForm" class="form needs-validation" novalidate>
|
||||
{% csrf_token %}
|
||||
{% include 'partials/form_errors.html' %}
|
||||
|
||||
2
templates/vendors/vendor_form.html
vendored
2
templates/vendors/vendor_form.html
vendored
@ -27,7 +27,7 @@
|
||||
<div class="row">
|
||||
<div class="col-xl-9">
|
||||
|
||||
<form class="row g-3 mb-9" method="post" class="form" novalidate>
|
||||
<form class="row g-3 mb-9" method="post" class="form" enctype="multipart/form-data" novalidate >
|
||||
{% csrf_token %}
|
||||
{{ redirect_field }}
|
||||
{{ form|crispy }}
|
||||
|
||||
8
templates/vendors/vendors_list.html
vendored
8
templates/vendors/vendors_list.html
vendored
@ -114,7 +114,7 @@
|
||||
<div class="avatar avatar-xl me-3"><img class="rounded-circle" src="{% static 'images/icons/picture.svg' %}" alt="" />
|
||||
{% endif %}
|
||||
</div>
|
||||
<div><a class="fs-8 fw-bold" href="">{{ vendor.vendor_name }}</a>
|
||||
<div><a class="fs-8 fw-bold" href="">{{ vendor.pk }}</a>
|
||||
<div class="d-flex align-items-center">
|
||||
<p class="mb-0 text-body-highlight fw-semibold fs-9 me-2">{{ vendor.vendor_name }}</p><span class="badge badge-phoenix badge-phoenix-primary">{{ vendor.id}}</span>
|
||||
</div>
|
||||
@ -122,11 +122,11 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="email align-middle white-space-nowrap fw-semibold ps-4 border-end border-translucent"><a class="text-body-highlight" href="">{{ vendor.email }}</a></td>
|
||||
<td class="phone align-middle white-space-nowrap fw-semibold ps-4 border-end border-translucent"><a class="text-body-highlight" href="tel:{{ vendor.phone }}">{{ vendor.phone }}</a></td>
|
||||
<td class="phone align-middle white-space-nowrap fw-semibold ps-4 border-end border-translucent"><a class="text-body-highlight" href="tel:{{ vendor.phone }}">{{ vendor.phone_number }}</a></td>
|
||||
<td class="contact align-middle white-space-nowrap ps-4 border-end border-translucent fw-semibold text-body-highlight">{{ vendor.contact_person }}</td>
|
||||
<td class="company align-middle white-space-nowrap text-body-tertiary text-opacity-85 ps-4 border-end border-translucent fw-semibold text-body-highlight">
|
||||
{{ vendor.address_1 }}</td>
|
||||
<td class="date align-middle white-space-nowrap text-body-tertiary text-opacity-85 ps-4 text-body-tertiary">{{ vendor.created|date }}</td>
|
||||
{{ vendor.address }}</td>
|
||||
<td class="date align-middle white-space-nowrap text-body-tertiary text-opacity-85 ps-4 text-body-tertiary">{{ vendor.created_at|date }}</td>
|
||||
<td class="align-middle white-space-nowrap text-end pe-0 ps-4">
|
||||
<div class="btn-reveal-trigger position-static">
|
||||
<button class="btn btn-sm dropdown-toggle dropdown-caret-none transition-none btn-reveal fs-10" type="button" data-bs-toggle="dropdown" data-boundary="window" aria-haspopup="true" aria-expanded="false" data-bs-reference="parent"><span class="fas fa-ellipsis-h fs-10"></span></button>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user