add qotation-02
This commit is contained in:
parent
88e81fadf1
commit
51fdc0b31f
Binary file not shown.
@ -1533,7 +1533,7 @@ def decode_vin(vin):
|
||||
# VR3USHNLWRJ521303
|
||||
# KNARH81E8P5194005
|
||||
# Example usage
|
||||
vin_number = 'LGWCBE196SB652802'
|
||||
vin_number = 'LGWEE4A53SK607775'
|
||||
decoded_vin = decode_vin(vin_number)
|
||||
print(decoded_vin)
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -46,7 +46,7 @@ class CarModelAdmin(admin.ModelAdmin):
|
||||
|
||||
@admin.register(models.CarSerie)
|
||||
class CarSeriesAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'arabic_name', 'id_car_model')
|
||||
list_display = ('name', 'arabic_name', 'id_car_model', )
|
||||
search_fields = ('name', 'id_car_model__name')
|
||||
list_filter = ('id_car_model__id_car_make__is_sa_import',
|
||||
'id_car_model__id_car_make__name',)
|
||||
@ -55,18 +55,18 @@ class CarSeriesAdmin(admin.ModelAdmin):
|
||||
verbose_name = "Car Series"
|
||||
|
||||
|
||||
# @admin.register(models.CarTrim)
|
||||
# class CarTrimAdmin(admin.ModelAdmin):
|
||||
# list_display = ('name',
|
||||
# 'id_car_serie__name',
|
||||
# 'id_car_serie__id_car_model__name',
|
||||
# 'id_car_serie__id_car_model__id_car_make__name')
|
||||
# search_fields = ('name', 'arabic_name', 'id_car_serie__id_car_model__name')
|
||||
# list_filter = ('id_car_serie__id_car_model__id_car_make__is_sa_import',
|
||||
# 'id_car_serie__id_car_model__id_car_make__name')
|
||||
@admin.register(models.CarTrim)
|
||||
class CarTrimAdmin(admin.ModelAdmin):
|
||||
list_display = ('name',
|
||||
'id_car_serie__name',
|
||||
'id_car_serie__id_car_model__name',
|
||||
'id_car_serie__id_car_model__id_car_make__name')
|
||||
search_fields = ('name', 'arabic_name', 'id_car_serie__id_car_model__name')
|
||||
list_filter = ('id_car_serie__id_car_model__id_car_make__is_sa_import',
|
||||
'id_car_serie__id_car_model__id_car_make__name')
|
||||
|
||||
# class Meta:
|
||||
# verbose_name = "Car Trim"
|
||||
class Meta:
|
||||
verbose_name = "Car Trim"
|
||||
|
||||
|
||||
@admin.register(models.CarSpecification)
|
||||
|
||||
@ -168,6 +168,7 @@ class QuotationForm(forms.ModelForm):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields['cars'].queryset = Car.objects.filter(
|
||||
finances__isnull=False
|
||||
).distinct()
|
||||
|
||||
BIN
inventory/management/.DS_Store
vendored
BIN
inventory/management/.DS_Store
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
36
inventory/management/commands/translate.py
Normal file
36
inventory/management/commands/translate.py
Normal file
@ -0,0 +1,36 @@
|
||||
from openai import OpenAI
|
||||
from django.core.management.base import BaseCommand
|
||||
from inventory.models import CarSerie
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Translates to Arabic and saves them in arabic_name field.'
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
client = OpenAI(api_key=settings.OPENAI_API_KEY)
|
||||
car_serie = CarSerie.objects.filter(id_car_model__car__id_car_make__is_sa_import=True)[:500]
|
||||
total = car_serie.count()
|
||||
print(f'Translating {total} names...')
|
||||
for index, car_serie in enumerate(car_serie, start=1):
|
||||
try:
|
||||
completion = client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
messages=[
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a translation assistant that translates English to Arabic."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": car_serie.name
|
||||
}
|
||||
],
|
||||
temperature=0.3,
|
||||
)
|
||||
translation = completion.choices[0].message.content.strip()
|
||||
car_serie.arabic_name = translation
|
||||
car_serie.save()
|
||||
print(f"[{index}/{total}] Translated '{car_serie.name}' to '{translation}'")
|
||||
except Exception as e:
|
||||
print(f"Error translating '{car_serie.name}': {e}")
|
||||
@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-10 11:45
|
||||
|
||||
from decimal import Decimal
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0004_remove_carfinance_administration_vat_amount_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='carfinance',
|
||||
options={'verbose_name': 'Car Financial Details'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='carfinance',
|
||||
name='total',
|
||||
field=models.DecimalField(blank=True, decimal_places=2, default=Decimal('0.00'), max_digits=14, null=True),
|
||||
),
|
||||
]
|
||||
18
inventory/migrations/0006_alter_car_status.py
Normal file
18
inventory/migrations/0006_alter_car_status.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-10 14:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0005_alter_carfinance_options_alter_carfinance_total'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='car',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('available', 'Available'), ('sold', 'Sold'), ('hold', 'Hold'), ('damaged', 'Damaged'), ('reserved', 'Reserved')], default='available', max_length=10, verbose_name='Status'),
|
||||
),
|
||||
]
|
||||
@ -0,0 +1,43 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-10 22:52
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0006_alter_car_status'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='salequotation',
|
||||
name='amount',
|
||||
field=models.DecimalField(decimal_places=2, default=100000, max_digits=10, verbose_name='Amount'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='salequotation',
|
||||
name='dealer',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='sales', to='inventory.dealer'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='salequotationcar',
|
||||
name='dealer',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='sale_cars', to='inventory.dealer', verbose_name='Dealer'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='salequotationcar',
|
||||
name='price',
|
||||
field=models.DecimalField(decimal_places=2, default=12000.0, editable=False, max_digits=10, verbose_name='Price'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='salequotationcar',
|
||||
name='quantity',
|
||||
field=models.PositiveIntegerField(default=1, verbose_name='Quantity'),
|
||||
),
|
||||
]
|
||||
19
inventory/migrations/0008_carfinance_vat_amount.py
Normal file
19
inventory/migrations/0008_carfinance_vat_amount.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-10 23:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0007_salequotation_amount_salequotation_dealer_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='carfinance',
|
||||
name='vat_amount',
|
||||
field=models.DecimalField(decimal_places=2, default=2300, editable=False, max_digits=14, verbose_name='Vat Amount'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
19
inventory/migrations/0009_alter_salequotation_amount.py
Normal file
19
inventory/migrations/0009_alter_salequotation_amount.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-11 12:09
|
||||
|
||||
from decimal import Decimal
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0008_carfinance_vat_amount'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='salequotation',
|
||||
name='amount',
|
||||
field=models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=10, verbose_name='Amount'),
|
||||
),
|
||||
]
|
||||
19
inventory/migrations/0010_alter_salequotation_dealer.py
Normal file
19
inventory/migrations/0010_alter_salequotation_dealer.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-11 12:16
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0009_alter_salequotation_amount'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='salequotation',
|
||||
name='dealer',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sales', to='inventory.dealer'),
|
||||
),
|
||||
]
|
||||
17
inventory/migrations/0011_remove_salequotationcar_dealer.py
Normal file
17
inventory/migrations/0011_remove_salequotationcar_dealer.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-11 12:17
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0010_alter_salequotation_dealer'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='salequotationcar',
|
||||
name='dealer',
|
||||
),
|
||||
]
|
||||
17
inventory/migrations/0012_remove_salequotationcar_price.py
Normal file
17
inventory/migrations/0012_remove_salequotationcar_price.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-11 12:18
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0011_remove_salequotationcar_dealer'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='salequotationcar',
|
||||
name='price',
|
||||
),
|
||||
]
|
||||
Binary file not shown.
@ -112,6 +112,7 @@ class CarStatusChoices(models.TextChoices):
|
||||
SOLD = 'sold', _('Sold')
|
||||
HOLD = 'hold', _('Hold')
|
||||
DAMAGED = 'damaged', _('Damaged')
|
||||
RESERVED = 'reserved', _('Reserved')
|
||||
|
||||
|
||||
class CarStockTypeChoices(models.TextChoices):
|
||||
@ -171,13 +172,13 @@ class Car(models.Model):
|
||||
)
|
||||
status = models.CharField(
|
||||
max_length=10,
|
||||
choices=CarStatusChoices.choices,
|
||||
choices=CarStatusChoices,
|
||||
default=CarStatusChoices.AVAILABLE,
|
||||
verbose_name=_("Status")
|
||||
)
|
||||
stock_type = models.CharField(
|
||||
max_length=10,
|
||||
choices=CarStockTypeChoices.choices,
|
||||
choices=CarStockTypeChoices,
|
||||
default=CarStockTypeChoices.NEW,
|
||||
verbose_name=_("Stock Type")
|
||||
)
|
||||
@ -204,6 +205,11 @@ class Car(models.Model):
|
||||
finance = self.finances.first()
|
||||
return finance.selling_price if finance else Decimal('0.00')
|
||||
|
||||
@property
|
||||
def discount_amount(self):
|
||||
finance = self.finances.first()
|
||||
return finance.discount_amount if finance else Decimal('0.00')
|
||||
|
||||
@property
|
||||
def vat_amount(self):
|
||||
finance = self.finances.first()
|
||||
@ -238,6 +244,10 @@ class CarFinance(models.Model):
|
||||
decimal_places=2,
|
||||
verbose_name=_("Profit Margin"),
|
||||
editable=False)
|
||||
vat_amount = models.DecimalField(max_digits=14,
|
||||
decimal_places=2,
|
||||
verbose_name=_("Vat Amount"),
|
||||
editable=False)
|
||||
discount_amount = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Discount Amount"),
|
||||
default=Decimal('0.00'))
|
||||
registration_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Registration Fee"),
|
||||
@ -249,17 +259,19 @@ class CarFinance(models.Model):
|
||||
custom_card_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Custom Card Fee"),
|
||||
default=Decimal('0.00'))
|
||||
vat_rate = models.DecimalField(max_digits=14, decimal_places=2, default=Decimal('0.15'), verbose_name=_("VAT Rate"),)
|
||||
total = models.DecimalField(max_digits=14, decimal_places=2, default=Decimal('0.00'), null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Car Financial Details")
|
||||
def __str__(self):
|
||||
return f"{self.selling_price}"
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.full_clean()
|
||||
try:
|
||||
self.profit_margin = self.selling_price - self.cost_price - self.discount_amount
|
||||
services = self.administration_fee + self.transportation_fee + self.custom_card_fee
|
||||
price_after_discount = self.selling_price - self.discount_amount
|
||||
total_vat_amount = (price_after_discount + services) * self.vat_rate
|
||||
self.vat_amount = self.selling_price * self.vat_rate
|
||||
self.profit_margin = self.selling_price - self.cost_price - self.discount_amount - self.registration_fee
|
||||
self.total = price_after_discount + services + total_vat_amount + self.registration_fee
|
||||
|
||||
except InvalidOperation as e:
|
||||
@ -267,10 +279,14 @@ class CarFinance(models.Model):
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Car Financial Details")
|
||||
|
||||
@property
|
||||
def total_vat_amount(self):
|
||||
return self.total if self.total else Decimal('0.00')
|
||||
services = self.administration_fee + self.transportation_fee + self.custom_card_fee
|
||||
price_after_discount = self.selling_price - self.discount_amount
|
||||
return (price_after_discount + services) * self.vat_rate
|
||||
|
||||
|
||||
class ExteriorColors(models.Model, LocalizedNameMixin):
|
||||
@ -413,6 +429,10 @@ class Customer(models.Model):
|
||||
middle = f" {self.middle_name}" if self.middle_name else ''
|
||||
return f"{self.first_name}{middle} {self.last_name}"
|
||||
|
||||
@property
|
||||
def get_full_name(self):
|
||||
return f"{self.first_name} {self.middle_name} {self.last_name}"
|
||||
|
||||
|
||||
class SaleQuotation(models.Model):
|
||||
STATUS_CHOICES = [
|
||||
@ -420,8 +440,9 @@ class SaleQuotation(models.Model):
|
||||
("CONFIRMED", _("Confirmed")),
|
||||
("CANCELED", _("Canceled")),
|
||||
]
|
||||
|
||||
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='sales', null=True)
|
||||
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="quotations", verbose_name=_("Customer"))
|
||||
amount = models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=10, verbose_name=_("Amount"))
|
||||
remarks = models.TextField(blank=True, null=True, verbose_name=_("Remarks"))
|
||||
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default="DRAFT", verbose_name=_("Status"))
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"))
|
||||
@ -457,6 +478,11 @@ class SaleQuotationCar(models.Model):
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_("Car")
|
||||
)
|
||||
# dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name="sale_cars", verbose_name=_("Dealer"))
|
||||
quantity = models.PositiveIntegerField(default=1, verbose_name=_("Quantity"))
|
||||
# price = models.DecimalField(decimal_places=2, max_digits=10, verbose_name=_("Price"), editable=False)
|
||||
|
||||
|
||||
|
||||
def get_financial_details(self):
|
||||
"""Retrieve financial details dynamically from CarFinance."""
|
||||
@ -488,128 +514,3 @@ class SalesOrder(models.Model):
|
||||
return f"Sales Order #{self.id} from Quotation #{self.quotation.id}"
|
||||
|
||||
|
||||
# Create Entity
|
||||
@receiver(post_save, sender=Dealer)
|
||||
def create_ledger_entity(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
entity = EntityModel.objects.create(
|
||||
name=instance.name,
|
||||
admin=instance.user,
|
||||
address_1=instance.address,
|
||||
fy_start_month=1,
|
||||
accrual_method=True,
|
||||
depth=0,
|
||||
)
|
||||
|
||||
default_coa = entity.create_chart_of_accounts(assign_as_default=True,
|
||||
commit=True,
|
||||
coa_name=_("Chart of Accounts"))
|
||||
if default_coa:
|
||||
entity.populate_default_coa(activate_accounts=True, coa_model=default_coa)
|
||||
print(f"Ledger entity created for Dealer: {instance.name}")
|
||||
|
||||
|
||||
# # Create Vendor
|
||||
@receiver(post_save, sender=Vendor)
|
||||
def create_ledger_vendor(sender, instance, created, **kwargs):
|
||||
|
||||
if created:
|
||||
entity = EntityModel.objects.filter(name=instance.dealer.name).first()
|
||||
|
||||
vendor = VendorModel.objects.update_or_create(
|
||||
entity_model=entity,
|
||||
vendor_name=instance.name,
|
||||
vendor_number=instance.crn,
|
||||
address_1=instance.address,
|
||||
phone=instance.phone_number,
|
||||
tax_id_number=instance.vrn,
|
||||
active=True,
|
||||
hidden=False,
|
||||
additional_info={
|
||||
"arabic_name": instance.arabic_name,
|
||||
"contact_person": instance.contact_person,
|
||||
},
|
||||
)
|
||||
|
||||
print(f"VendorModel created for Vendor: {instance.name}")
|
||||
|
||||
|
||||
@receiver(post_save, sender=Customer)
|
||||
def create_customer(sender, instance, created, **kwargs):
|
||||
|
||||
if created:
|
||||
entity = EntityModel.objects.filter(name=instance.dealer.name).first()
|
||||
name = f"{instance.first_name} {instance.middle_name} {instance.last_name}"
|
||||
|
||||
customer = CustomerModel.objects.create(
|
||||
entity_model=entity,
|
||||
customer_name=name,
|
||||
customer_number=instance.national_id,
|
||||
address_1=instance.address,
|
||||
phone=instance.phone_number,
|
||||
email=instance.email,
|
||||
sales_tax_rate=0.15,
|
||||
)
|
||||
|
||||
print(f"Customer created: {name}")
|
||||
|
||||
|
||||
# # Create Item
|
||||
# @receiver(post_save, sender=Car)
|
||||
# def create_item_model(sender, instance, created, **kwargs):
|
||||
# item_name = f"{instance.year} - {instance.id_car_make} - {instance.id_car_model} - {instance.id_car_trim}"
|
||||
# uom_name = _("Car")
|
||||
# unit_abbr = _("C")
|
||||
#
|
||||
# uom, uom_created = UnitOfMeasureModel.objects.get_or_create(
|
||||
# name=uom_name,
|
||||
# unit_abbr=unit_abbr
|
||||
# )
|
||||
#
|
||||
# if uom_created:
|
||||
# print(f"UOM created: {uom_name}")
|
||||
# else:
|
||||
# print(f"Using existing UOM: {uom_name}")
|
||||
#
|
||||
# entity = EntityModel.objects.filter(name=instance.dealer.name).first()
|
||||
#
|
||||
# inventory_account = AccountModel.objects.first()
|
||||
# cogs_account = AccountModel.objects.first()
|
||||
# earnings_account = AccountModel.objects.first()
|
||||
#
|
||||
# item = ItemModel.objects.create(
|
||||
# entity=entity,
|
||||
# uom=uom,
|
||||
# name=item_name,
|
||||
# item_role=ItemModelAbstract.ITEM_ROLE_INVENTORY,
|
||||
# item_type=ItemModelAbstract.ITEM_TYPE_MATERIAL,
|
||||
# item_id=instance.vin,
|
||||
# sold_as_unit=True,
|
||||
# inventory_received=1.00,
|
||||
# inventory_received_value=0.00,
|
||||
# inventory_account=inventory_account,
|
||||
# for_inventory=True,
|
||||
# is_product_or_service=True,
|
||||
# cogs_account=cogs_account,
|
||||
# earnings_account=earnings_account,
|
||||
# is_active=True,
|
||||
# additional_info={
|
||||
# "remarks": instance.remarks,
|
||||
# "status": instance.status,
|
||||
# "stock_type": instance.stock_type,
|
||||
# "mileage": instance.mileage,
|
||||
# },
|
||||
# )
|
||||
#
|
||||
# print(f"ItemModel {'created' if created else 'updated'} for Car: {item.name}")
|
||||
#
|
||||
#
|
||||
# # update price - CarFinance
|
||||
# @receiver(post_save, sender=CarFinance)
|
||||
# def update_item_model_cost(sender, instance, created, **kwargs):
|
||||
#
|
||||
# ItemModel.objects.filter(item_id=instance.car.vin).update(
|
||||
# inventory_received_value=instance.cost_price,
|
||||
# default_amount=instance.cost_price,
|
||||
# )
|
||||
# print(f"Inventory item updated with CarFinance data for Car: {instance.car}")
|
||||
|
||||
@ -68,3 +68,11 @@ def calculate_stock_value():
|
||||
total_value = sum(car.selling_price for car in cars)
|
||||
return total_value
|
||||
|
||||
|
||||
# from django_ledger.models import EntityModel
|
||||
#
|
||||
# def get_purchase_orders():
|
||||
# entity = EntityModel.objects.get(name='Marwan2')
|
||||
# items = entity.
|
||||
# print(items.values())
|
||||
# return items
|
||||
|
||||
@ -1,20 +1,175 @@
|
||||
# from django.db.models.signals import post_save, post_delete
|
||||
# from django.dispatch import receiver
|
||||
# from . import models
|
||||
#
|
||||
#
|
||||
# @receiver(post_save, sender=models.CarReservation)
|
||||
# def update_car_status_on_reservation(sender, instance, created, **kwargs):
|
||||
# if created:
|
||||
# car = instance.car
|
||||
# car.status = models.CarStatusChoices.RESERVED
|
||||
# car.save()
|
||||
#
|
||||
#
|
||||
# @receiver(post_delete, sender=models.CarReservation)
|
||||
# def update_car_status_on_reservation_delete(sender, instance, **kwargs):
|
||||
# car = instance.car
|
||||
# if not car.get_current_reservation():
|
||||
# car.status = models.CarStatusChoices.AVAILABLE
|
||||
# car.save()
|
||||
from random import randint
|
||||
|
||||
from django.db.models.signals import post_save, post_delete
|
||||
from django.dispatch import receiver
|
||||
from django_ledger.models import EntityModel, VendorModel, CustomerModel, UnitOfMeasureModel
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from . import models
|
||||
|
||||
|
||||
@receiver(post_save, sender=models.CarReservation)
|
||||
def update_car_status_on_reservation(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
car = instance.car
|
||||
car.status = models.CarStatusChoices.RESERVED
|
||||
car.save()
|
||||
|
||||
|
||||
@receiver(post_delete, sender=models.CarReservation)
|
||||
def update_car_status_on_reservation_delete(sender, instance, **kwargs):
|
||||
car = instance.car
|
||||
if not car.get_current_reservation():
|
||||
car.status = models.CarStatusChoices.AVAILABLE
|
||||
car.save()
|
||||
|
||||
|
||||
# Create Entity
|
||||
@receiver(post_save, sender=models.Dealer)
|
||||
def create_ledger_entity(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
entity = EntityModel.objects.create(
|
||||
name=instance.name,
|
||||
admin=instance.user,
|
||||
address_1=instance.address,
|
||||
fy_start_month=1,
|
||||
accrual_method=True,
|
||||
depth=0,
|
||||
)
|
||||
|
||||
default_coa = entity.create_chart_of_accounts(assign_as_default=True,
|
||||
commit=True,
|
||||
coa_name=_("Chart of Accounts"))
|
||||
# entity.create_account(
|
||||
# coa_model=coa,
|
||||
# code=1010,
|
||||
# role='asset_ca_cash',
|
||||
# name=_('Cash'),
|
||||
# balance_type="debit",
|
||||
# )
|
||||
# entity.create_account(
|
||||
# coa_model=coa,
|
||||
# code=1200,
|
||||
# role='asset_ca_inv',
|
||||
# name=_('Inventory'),
|
||||
# balance_type="debit",
|
||||
# active=True)
|
||||
|
||||
|
||||
if default_coa:
|
||||
entity.populate_default_coa(activate_accounts=True, coa_model=default_coa)
|
||||
|
||||
uom_name = _("Unit")
|
||||
unit_abbr = _("U")
|
||||
|
||||
entity.create_uom(uom_name, unit_abbr)
|
||||
|
||||
print(f"Ledger entity created for Dealer: {instance.name}")
|
||||
|
||||
|
||||
# # Create Vendor
|
||||
@receiver(post_save, sender=models.Vendor)
|
||||
def create_ledger_vendor(sender, instance, created, **kwargs):
|
||||
|
||||
if created:
|
||||
entity = EntityModel.objects.filter(name=instance.dealer.name).first()
|
||||
|
||||
entity.create_vendor(
|
||||
vendor_name=instance.name,
|
||||
vendor_number=instance.crn,
|
||||
address_1=instance.address,
|
||||
phone=instance.phone_number,
|
||||
tax_id_number=instance.vrn,
|
||||
active=True,
|
||||
hidden=False,
|
||||
additional_info={
|
||||
"arabic_name": instance.arabic_name,
|
||||
"contact_person": instance.contact_person,
|
||||
})
|
||||
|
||||
|
||||
print(f"VendorModel created for Vendor: {instance.name}")
|
||||
|
||||
|
||||
@receiver(post_save, sender=models.Customer)
|
||||
def create_customer(sender, instance, created, **kwargs):
|
||||
|
||||
if created:
|
||||
entity = EntityModel.objects.filter(name=instance.dealer.name).first()
|
||||
name = f"{instance.first_name} {instance.middle_name} {instance.last_name}"
|
||||
|
||||
entity.create_customer(
|
||||
customer_name=name,
|
||||
customer_number=instance.national_id,
|
||||
address_1=instance.address,
|
||||
phone=instance.phone_number,
|
||||
email=instance.email,
|
||||
sales_tax_rate=0.15,
|
||||
active=True,
|
||||
hidden=False,
|
||||
additional_info={}
|
||||
)
|
||||
|
||||
print(f"Customer created: {name}")
|
||||
|
||||
|
||||
# Create Item
|
||||
@receiver(post_save, sender=models.Car)
|
||||
def create_item_model(sender, instance, created, **kwargs):
|
||||
item_name = f"{instance.year} - {instance.id_car_make} - {instance.id_car_model} - {instance.id_car_trim}"
|
||||
uom_name = _("Car")
|
||||
unit_abbr = _("C")
|
||||
|
||||
uom, uom_created = UnitOfMeasureModel.objects.get_or_create(
|
||||
name=uom_name,
|
||||
unit_abbr=unit_abbr
|
||||
)
|
||||
|
||||
if uom_created:
|
||||
print(f"UOM created: {uom_name}")
|
||||
else:
|
||||
print(f"Using existing UOM: {uom_name}")
|
||||
|
||||
entity = EntityModel.objects.filter(name=instance.dealer.name).first()
|
||||
|
||||
inventory_account = AccountModel.objects.first()
|
||||
cogs_account = AccountModel.objects.first()
|
||||
earnings_account = AccountModel.objects.first()
|
||||
|
||||
entity.create_i
|
||||
|
||||
item = ItemModel.objects.create(
|
||||
entity=entity,
|
||||
uom=uom,
|
||||
name=item_name,
|
||||
item_role=ItemModelAbstract.ITEM_ROLE_INVENTORY,
|
||||
item_type=ItemModelAbstract.ITEM_TYPE_MATERIAL,
|
||||
item_id=instance.vin,
|
||||
sold_as_unit=True,
|
||||
inventory_received=1.00,
|
||||
inventory_received_value=0.00,
|
||||
inventory_account=inventory_account,
|
||||
for_inventory=True,
|
||||
is_product_or_service=True,
|
||||
cogs_account=cogs_account,
|
||||
earnings_account=earnings_account,
|
||||
is_active=True,
|
||||
additional_info={
|
||||
"remarks": instance.remarks,
|
||||
"status": instance.status,
|
||||
"stock_type": instance.stock_type,
|
||||
"mileage": instance.mileage,
|
||||
},
|
||||
)
|
||||
|
||||
print(f"ItemModel {'created' if created else 'updated'} for Car: {item.name}")
|
||||
#
|
||||
#
|
||||
# # update price - CarFinance
|
||||
# @receiver(post_save, sender=CarFinance)
|
||||
# def update_item_model_cost(sender, instance, created, **kwargs):
|
||||
#
|
||||
# ItemModel.objects.filter(item_id=instance.car.vin).update(
|
||||
# inventory_received_value=instance.cost_price,
|
||||
# default_amount=instance.cost_price,
|
||||
# )
|
||||
# print(f"Inventory item updated with CarFinance data for Car: {instance.car}")
|
||||
|
||||
@ -153,7 +153,7 @@ class AjaxHandlerView(LoginRequiredMixin, View):
|
||||
manufacturer_name = vin_info.Make.strip()
|
||||
model_name = vin_info.Model.strip()
|
||||
year_model = vin_info.ModelYear
|
||||
if not manufacturer_name or not year_model:
|
||||
if not manufacturer_name or not model_name or not year_model:
|
||||
raise ValueError('PYVIN returned incomplete data.')
|
||||
elif method_name == 'VIN':
|
||||
manufacturer_name = vin_info.make.strip()
|
||||
@ -164,15 +164,11 @@ class AjaxHandlerView(LoginRequiredMixin, View):
|
||||
elif method_name == 'ELM':
|
||||
elm_data = vin_info.get('data', {})
|
||||
manufacturer_name = elm_data.get('maker', '').strip()
|
||||
print(manufacturer_name)
|
||||
model_name = elm_data.get('model', '').strip()
|
||||
print(model_name)
|
||||
year_model = elm_data.get('modelYear', '').strip()
|
||||
print(year_model)
|
||||
if not manufacturer_name or not model_name or not year_model:
|
||||
raise ValueError('ELM returned incomplete data.')
|
||||
|
||||
# model_name = normalize_name(model_name_before)
|
||||
decoding_method = method_name
|
||||
print(f"decoded by {method_name}")
|
||||
break
|
||||
@ -188,19 +184,27 @@ class AjaxHandlerView(LoginRequiredMixin, View):
|
||||
f"VIN decoded using {decoding_method}: Make={manufacturer_name}, Model={model_name}, Year={year_model}"
|
||||
)
|
||||
regex_make= manufacturer_name.replace(" ", "[- ]?")
|
||||
car_make = models.CarMake.objects.filter(name__iregex=regex_make).first()
|
||||
car_make = (models.CarMake.objects
|
||||
.filter(name__iregex=regex_make, is_sa_import=True)
|
||||
.first())
|
||||
if not car_make:
|
||||
return JsonResponse({'success': False, 'error': 'Manufacturer not found in the database.'}, status=404)
|
||||
|
||||
vin_data['make_id'] = car_make.id_car_make
|
||||
vin_data['name'] = car_make.name
|
||||
vin_data['arabic_name'] = car_make.arabic_name
|
||||
|
||||
# car_model = models.CarModel.objects.filter(id_car_make=car_make.id_car_make, name__contains=model_name).first()
|
||||
regex_pattern = model_name.replace(" ", "[- ]?")
|
||||
car_model = models.CarModel.objects.filter(id_car_make=car_make.id_car_make, name__iregex=regex_pattern).first()
|
||||
car_model = (models.CarModel.objects
|
||||
.filter(id_car_make=car_make.id_car_make,
|
||||
name__iregex=regex_pattern)
|
||||
.first()
|
||||
)
|
||||
|
||||
if not car_model:
|
||||
return JsonResponse({'success': False, 'error': 'Model not found for the given manufacturer.'}, status=404)
|
||||
return JsonResponse(
|
||||
{'success': False,
|
||||
'error': 'Model not found for the given manufacturer.'}, status=404)
|
||||
|
||||
vin_data['model_id'] = car_model.id_car_model
|
||||
vin_data['year'] = year_model
|
||||
@ -208,7 +212,11 @@ class AjaxHandlerView(LoginRequiredMixin, View):
|
||||
|
||||
def get_models(self, request):
|
||||
make_id = request.GET.get('make_id')
|
||||
car_models = models.CarModel.objects.filter(id_car_make=make_id).values('id_car_model', 'name', 'arabic_name')
|
||||
car_models = (models.CarModel.objects
|
||||
.filter(id_car_make=make_id,
|
||||
id_car_make__is_sa_import=True)
|
||||
.values('id_car_model', 'name', 'arabic_name')
|
||||
)
|
||||
return JsonResponse(list(car_models), safe=False)
|
||||
|
||||
def get_series(self, request):
|
||||
@ -685,6 +693,7 @@ class QuotationCreateView(LoginRequiredMixin, CreateView):
|
||||
template_name = 'sales/quotation_form.html'
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.dealer = self.request.user.dealer
|
||||
quotation = form.save()
|
||||
selected_cars = form.cleaned_data.get("cars")
|
||||
for car in selected_cars:
|
||||
|
||||
3
ledger_testing.py
Normal file
3
ledger_testing.py
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
|
||||
BIN
static/images/logos/suppliers/muhammad-yousef-naghi.png
Normal file
BIN
static/images/logos/suppliers/muhammad-yousef-naghi.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
BIN
static/images/logos/suppliers/unnamed.png
Normal file
BIN
static/images/logos/suppliers/unnamed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
BIN
static/images/logos/vendors/Alamjdouie-Hyundai-01_OX3eq7o.png
vendored
Normal file
BIN
static/images/logos/vendors/Alamjdouie-Hyundai-01_OX3eq7o.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
BIN
static/images/logos/vendors/Aljomaih-Automotive-Company-3_3uzBd9i.png
vendored
Normal file
BIN
static/images/logos/vendors/Aljomaih-Automotive-Company-3_3uzBd9i.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
BIN
static/images/logos/vendors/muhammad-yousef-naghi.png
vendored
Normal file
BIN
static/images/logos/vendors/muhammad-yousef-naghi.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
@ -55,9 +55,9 @@ small, .small {
|
||||
<script type="text/javascript" src="{% static 'js/main.js' %}"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
$('.form-select').select2({
|
||||
/* $('.form-select').select2({
|
||||
theme: 'bootstrap4',
|
||||
});
|
||||
});*/
|
||||
'use strict';
|
||||
|
||||
// Fetch all the forms with the "needs-validation" class
|
||||
|
||||
@ -21,12 +21,12 @@
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button type="button"
|
||||
class="btn btn-secondary"
|
||||
class="btn btn-sm btn-secondary"
|
||||
data-bs-dismiss="modal">
|
||||
{% trans 'No' %}
|
||||
</button>
|
||||
<a type="button"
|
||||
class="btn btn-danger"
|
||||
class="btn btn-sm btn-danger"
|
||||
href="{% url 'customer_delete' customer.id %}">
|
||||
{% trans 'Yes' %}
|
||||
</a>
|
||||
@ -56,17 +56,17 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer d-flex ">
|
||||
<a class="btn btn-primary me-1" href="{% url 'customer_update' customer.id %}">
|
||||
<a class="btn btn-sm btn-primary me-1" href="{% url 'customer_update' customer.id %}">
|
||||
<!--<i class="bi bi-pencil-square"></i> -->
|
||||
{{ _("Edit") }}
|
||||
</a>
|
||||
<a class="btn btn-danger me-1"
|
||||
<a class="btn btn-sm btn-danger me-1"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#deleteModal">
|
||||
<!--<i class="bi bi-trash-fill"></i>-->
|
||||
{{ _("Delete") }}
|
||||
</a>
|
||||
<a class="btn btn-secondary"
|
||||
<a class="btn btn-sm btn-secondary"
|
||||
href="{% url 'customer_list' %}">
|
||||
<!--<i class="bi bi-arrow-left-square-fill"></i>-->
|
||||
{% trans "Back to List" %}
|
||||
|
||||
BIN
templates/partials/.DS_Store
vendored
Normal file
BIN
templates/partials/.DS_Store
vendored
Normal file
Binary file not shown.
@ -12,7 +12,7 @@
|
||||
<h5>{% trans "Customer Details" %}</h5>
|
||||
<p>
|
||||
<strong>{% trans "Name" %}:</strong>
|
||||
{{ quotation.customer.first_name }} {{ quotation.customer.last_name_name }}</p>
|
||||
{{ quotation.customer.get_full_name }}</p>
|
||||
<p><strong>{% trans "Address" %}:</strong> {{ quotation.customer.address }}</p>
|
||||
<p><strong>{% trans "VAT No" %}:</strong> {{ quotation.customer.vat_number }}</p>
|
||||
</div>
|
||||
@ -32,7 +32,6 @@
|
||||
<th>Model</th>
|
||||
<th>Selling Price</th>
|
||||
<th>VAT</th>
|
||||
<th>Total Before VAT</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -42,18 +41,17 @@
|
||||
<td>{{ item.car.vin }}</td>
|
||||
<td>{{ item.car.id_car_model.get_local_name }}</td>
|
||||
<td>{{ item.car.selling_price }}</td>
|
||||
<td>{{ item.car.total_vat_amount }}</td>
|
||||
<td>{{ item.car.total_before_vat }}</td>
|
||||
<td>{{ item.car.vat_amount }}</td>
|
||||
<td>{{ item.car.total }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th colspan="3">Totals</th>
|
||||
<th>{{ item.car.total_vat_amount }}</th>
|
||||
<th>{{ item.car.total_before_vat }}</th>
|
||||
<th>{{ item.car.total }}</th>
|
||||
<th colspan="2">Totals</th>
|
||||
<th>{{ item.car.finances.total_vat_amount }}</th>
|
||||
<th>{{ item.car.finances.total_before_vat }}</th>
|
||||
<th>{{ item.car.finances.total }}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
<td>{{ forloop.counter }}</td>
|
||||
<td>{{ quotation.customer.get_full_name }}</td>
|
||||
<td>{{ quotation.quotation_cars.count }}</td>
|
||||
<td>{{ quotation.total }}</td>
|
||||
<td>{{ quotation.quotation_cars.get_financial_details.total_amount }}</td>
|
||||
<td>{{ quotation.created_at|date:"d/m/Y H:i" }}</td>
|
||||
<td>
|
||||
<a href="{% url 'quotation_detail' quotation.id %}" class="btn btn-sm btn-info">
|
||||
|
||||
2
templates/vendors/vendors_list.html
vendored
2
templates/vendors/vendors_list.html
vendored
@ -6,7 +6,7 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid p-3">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card shadow rounded">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-0">{{ _("Vendors")|capfirst }}</h6>
|
||||
<form method="get" class="d-inline-block">
|
||||
|
||||
110
templates/vendors/view_vendor.html
vendored
110
templates/vendors/view_vendor.html
vendored
@ -1,56 +1,74 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "View Vendor" %}{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<!-- Delete Modal -->
|
||||
<div class="modal fade" id="deleteModal"
|
||||
data-bs-backdrop="static"
|
||||
data-bs-keyboard="false"
|
||||
tabindex="-1"
|
||||
aria-labelledby="deleteModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm ">
|
||||
<div class="modal-content rounded">
|
||||
<div class="modal-body d-flex justify-content-center">
|
||||
<h1 class="text-danger me-2"><i class="bi bi-exclamation-diamond-fill"></i></h1>
|
||||
<span class="text-danger">
|
||||
{% trans "Are you sure you want to delete this vendor?" %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button type="button"
|
||||
class="btn btn-secondary"
|
||||
data-bs-dismiss="modal">
|
||||
{% trans 'No' %}
|
||||
</button>
|
||||
<a type="button"
|
||||
class="btn btn-danger"
|
||||
href="{% url 'vendor_delete' vendor.id %}">
|
||||
{% trans 'Yes' %}
|
||||
</a>
|
||||
</div>
|
||||
<!-- Delete Modal -->
|
||||
<div class="modal fade" id="deleteModal"
|
||||
data-bs-backdrop="static"
|
||||
data-bs-keyboard="false"
|
||||
tabindex="-1"
|
||||
aria-labelledby="deleteModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog modal-sm">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-danger text-white">
|
||||
<h5 class="modal-title" id="deleteModalLabel">
|
||||
<i class="bi bi-exclamation-diamond-fill"></i>
|
||||
{% trans "Delete Vendor" %}
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<p class="mb-0 text-danger fw-bold">
|
||||
{% trans "Are you sure you want to delete this vendor?" %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer justify-content-center">
|
||||
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">
|
||||
{% trans "No" %}
|
||||
</button>
|
||||
<a type="button" class="btn btn-danger btn-sm" href="{% url 'vendor_delete' vendor.id %}">
|
||||
{% trans "Yes" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<h1>{% trans "Vendor Details" %}</h1>
|
||||
<ul>
|
||||
<li><strong>{% trans "Name" %}:</strong>
|
||||
|
||||
{{ vendor.get_local_name }}
|
||||
</li>
|
||||
<li><strong>{% trans "Contact Person" %}:</strong> {{ vendor.contact_person }}</li>
|
||||
<li><strong>{% trans "Phone Number" %}:</strong> {{ vendor.phone_number }}</li>
|
||||
<li><strong>{% trans "Email" %}:</strong> {{ vendor.email }}</li>
|
||||
<li><strong>{% trans "Address" %}:</strong> {{ vendor.address }}</li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-primary" href="{% url 'vendor_update' vendor.id %}">{% trans "Edit" %}</a>
|
||||
<a class="btn btn-sm btn-danger me-1"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#deleteModal">
|
||||
<!--<i class="bi bi-trash-fill"></i>-->
|
||||
{{ _("Delete") }}
|
||||
</div>
|
||||
|
||||
<!-- Vendor Details -->
|
||||
<div class="container mt-4">
|
||||
<div class="card shadow rounded">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h4 class="mb-0">{% trans "Vendor Details" %}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
<strong>{% trans "Name" %}:</strong> {{ vendor.get_local_name }}
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>{% trans "Contact Person" %}:</strong> {{ vendor.contact_person }}
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>{% trans "Phone Number" %}:</strong> {{ vendor.phone_number }}
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>{% trans "Email" %}:</strong> {{ vendor.email }}
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<strong>{% trans "Address" %}:</strong> {{ vendor.address }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-footer d-flex justify-content-between">
|
||||
<a class="btn btn-sm btn-primary" href="{% url 'vendor_update' vendor.id %}">
|
||||
{% trans "Edit" %}
|
||||
</a>
|
||||
<button class="btn btn-sm btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">
|
||||
{% trans "Delete" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
52
testapi.py
52
testapi.py
@ -1,20 +1,8 @@
|
||||
|
||||
# from vin import VIN
|
||||
from vin import VIN
|
||||
import requests
|
||||
import json
|
||||
#
|
||||
# vin_no = 'VR7ED9HP6SJ522156'
|
||||
#
|
||||
# details = {
|
||||
# # 'Description': VIN(vin_no).description,
|
||||
# 'make': VIN(vin_no).make,
|
||||
# 'year': VIN(vin_no).model_year,
|
||||
# 'model': VIN(vin_no).model,
|
||||
# 'trim': VIN(vin_no).trim,
|
||||
# 'Series': VIN(vin_no).series,
|
||||
# 'body_class': VIN(vin_no).body_class,
|
||||
# 'Type': VIN(vin_no).vehicle_type,
|
||||
# 'Electrification level': VIN(vin_no).electrification_level,
|
||||
|
||||
# }
|
||||
#
|
||||
# print(details)
|
||||
@ -62,7 +50,7 @@ import json
|
||||
#
|
||||
# from pyvin import VIN
|
||||
#
|
||||
# number_vin = 'VR7ED9HP6SJ522156'
|
||||
# number_vin = '5LMCJ2D93NUL03460'
|
||||
#
|
||||
# vehicle = VIN(number_vin)
|
||||
# if vehicle:
|
||||
@ -84,9 +72,25 @@ import json
|
||||
# print(e)
|
||||
# else:
|
||||
# print("No vehicle found")
|
||||
# vin_info_py(number_vin)
|
||||
|
||||
|
||||
|
||||
|
||||
vin_no = '5LMCJ2D93NUL03460'
|
||||
|
||||
details = {
|
||||
# 'Description': VIN(vin_no).description,
|
||||
'make': VIN(vin_no).make,
|
||||
'year': VIN(vin_no).model_year,
|
||||
'model': VIN(vin_no).model,
|
||||
'trim': VIN(vin_no).trim,
|
||||
'Series': VIN(vin_no).series,
|
||||
'body_class': VIN(vin_no).body_class,
|
||||
'Type': VIN(vin_no).vehicle_type,
|
||||
'Electrification level': VIN(vin_no).electrification_level,
|
||||
}
|
||||
print(details)
|
||||
|
||||
# from vpic import Client
|
||||
#
|
||||
# c = Client()
|
||||
@ -120,11 +124,11 @@ import json
|
||||
#
|
||||
# except Exception as e:
|
||||
# print(e)
|
||||
vin_no = "LS5A3DKR0SA966230"
|
||||
|
||||
|
||||
url = "https://vin17.com/Search/query?vin=+"+vin_no
|
||||
|
||||
response = requests.request("GET", url)
|
||||
car_info = json.loads(response.text)
|
||||
print(car_info)
|
||||
# vin_no = "LS5A3DKR0SA966230"
|
||||
#
|
||||
#
|
||||
# url = "https://vin17.com/Search/query?vin=+"+vin_no
|
||||
#
|
||||
# response = requests.request("GET", url)
|
||||
# car_info = json.loads(response.text)
|
||||
# print(car_info)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user