diff --git a/car_inventory/settings.py b/car_inventory/settings.py
index b12b3c77..06a4d1df 100644
--- a/car_inventory/settings.py
+++ b/car_inventory/settings.py
@@ -26,7 +26,7 @@ SECRET_KEY = 'django-insecure-gc9bh4*3=b6hihdnaom0edjsbxh$5t)aap@e8p&340r7)*)qb8
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
-ALLOWED_HOSTS = ['10.10.1.109', 'localhost', '127.0.0.1', '192.168.1.135', '172.20.10.4']
+ALLOWED_HOSTS = ['10.10.1.109',"10.10.1.120", 'localhost', '127.0.0.1', '192.168.1.135', '172.20.10.4']
# Application definition
@@ -110,9 +110,9 @@ WSGI_APPLICATION = 'car_inventory.wsgi.application'
DATABASES = {
"default": {
"ENGINE": "django_prometheus.db.backends.postgresql",
- "NAME": "haikal_app",
- "USER": "f95166",
- "PASSWORD": "Kfsh&rc9788",
+ "NAME": "haikal",
+ "USER": "haikal",
+ "PASSWORD": "haikal",
"HOST": "localhost",
"PORT": 5432,
}
diff --git a/inventory/management/commands/generate_vin.py b/inventory/management/commands/generate_vin.py
new file mode 100644
index 00000000..b7d6ba44
--- /dev/null
+++ b/inventory/management/commands/generate_vin.py
@@ -0,0 +1,38 @@
+from django.core.management.base import BaseCommand
+
+from inventory.services import get_model,decodevin
+
+from bs4 import BeautifulSoup
+import requests
+
+class Command(BaseCommand):
+ help = 'Seed the Customer model with 20 records'
+
+ def handle(self, *args, **kwargs):
+ vin,description = self.generate_vin()
+ result = decodevin(vin)
+ self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
+ self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
+ self.stdout.write(self.style.SUCCESS(f'Generated VIN: {vin}'))
+ self.stdout.write(self.style.SUCCESS(f'Description: {description}'))
+ self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
+ self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
+ self.stdout.write(self.style.SUCCESS(f'Decoded VIN: {result}'))
+ make,model,year_model = result.values()
+ self.stdout.write(self.style.SUCCESS(f'VIN: {vin} - Make {make} - Model {model} - Model Year {year_model}'))
+ m = get_model(model)
+ self.stdout.write(self.style.SUCCESS(f'Make: {m.id_car_make} - Model: {m}'))
+ self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
+ self.stdout.write(self.style.SUCCESS(f'####################################################################################################'))
+
+
+
+ def generate_vin(self):
+ # url = "https://www.vindecoder.org/vin-decoder"
+ url = "https://vingenerator.org/"
+ response = requests.get(url)
+ soup = BeautifulSoup(response.content, "html.parser")
+ vin = soup.find("input", {"name": "vin"})["value"]
+ description = soup.find("div", {"class": "description"}).text
+
+ return vin,description
diff --git a/inventory/migrations/0005_alter_carfinance_options_remove_carfinance_total.py b/inventory/migrations/0005_alter_carfinance_options_remove_carfinance_total.py
new file mode 100644
index 00000000..aa7921b2
--- /dev/null
+++ b/inventory/migrations/0005_alter_carfinance_options_remove_carfinance_total.py
@@ -0,0 +1,21 @@
+# Generated by Django 4.2.17 on 2024-12-10 11:57
+
+from django.db import migrations
+
+
+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.RemoveField(
+ model_name='carfinance',
+ name='total',
+ ),
+ ]
diff --git a/inventory/models.py b/inventory/models.py
index 6188a371..c53cc4f1 100644
--- a/inventory/models.py
+++ b/inventory/models.py
@@ -489,69 +489,69 @@ class SalesOrder(models.Model):
# 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,
- )
+# @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}")
+# 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):
+# # # 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()
+# 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,
- },
- )
+# 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}")
+# print(f"VendorModel created for Vendor: {instance.name}")
-@receiver(post_save, sender=Customer)
-def create_customer(sender, instance, created, **kwargs):
+# @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}"
+# 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,
- )
+# 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}")
+# print(f"Customer created: {name}")
# # Create Item
diff --git a/inventory/services.py b/inventory/services.py
index 07e0eb30..c94f148c 100644
--- a/inventory/services.py
+++ b/inventory/services.py
@@ -1,52 +1,87 @@
"""
Services module
"""
+
import requests
import json
from .utils import get_jwt_token
from pyvin import VIN
from django.conf import settings
from openai import OpenAI
-from .models import Car
+from .models import Car,CarMake,CarModel
+def get_make(item):
+ data = CarMake.objects.filter(name__iexact=item).first()
+ return data
+def get_model(item,make):
+ data = make.carmodel_set.filter(name__iexact=item).first()
+ if not data:
+ r = item.split(" ")
+ for i in r:
+ if data:=make.carmodel_set.filter(name__iexact=i).first():
+ break
+ return data
+
def normalize_name(name):
- return name.replace(' ', '').replace('-', '').lower()
+ return name.replace(" ", "").replace("-", "").lower()
-def decode_vin_pyvin(vin):
- vehicle = VIN(vin)
+def decodevin(vin):
+
+ if result:=decode_vin(vin):
+ return result
+ elif result:=elm(vin):
+ return result
+ else:
+ return None
- data = {
- 'Make': vehicle.Make,
- 'Model': vehicle.Model,
- 'ModelYear': vehicle.ModelYear,
- }
- print(data)
- return data
+
+
+def decode_vin(vin):
+ v = VIN(vin)
+ data = {}
+ if v:
+ data = {
+ "maker": v.Make,
+ "model": v.Model,
+ "modelYear": v.ModelYear,
+ }
+
+ return data if all([x for x in data.values()]) else None
# vehicle-info
# c2729afb
# 6d397471920412d672af1b8a02ca52ea
+
# option-info
# 367974ed
# 046b0412c1b4d3f8c39ec6375d6f3030
def elm(vin):
headers = {
"Content-Type": "application/json",
- 'app-id': 'c2729afb',
- 'app-key': '6d397471920412d672af1b8a02ca52ea',
- 'client-id': '94142c27-2536-47e9-8e28-9ca7728b9442',
+ "app-id": "c2729afb",
+ "app-key": "6d397471920412d672af1b8a02ca52ea",
+ "client-id": "94142c27-2536-47e9-8e28-9ca7728b9442",
}
- url = 'https://vehicle-maintenance.api.elm.sa/api/v1/vehicles/vehicle-info?vin='+vin
+ url = (
+ "https://vehicle-maintenance.api.elm.sa/api/v1/vehicles/vehicle-info?vin=" + vin
+ )
payload = {}
response = requests.request("GET", url, headers=headers, data=payload)
- car_info = json.loads(response.text)
- print(car_info)
- return car_info
+ response = json.loads(response.text)
+ data = {}
+ if response.get("data"):
+ data = {
+ "maker": response["data"]["maker"],
+ "model": response["data"]["model"],
+ "modelYear": response["data"]["modelYear"],
+ }
+
+ return data if all([x for x in data.values()]) else None
def translate(content, *args, **kwargs):
@@ -54,8 +89,11 @@ def translate(content, *args, **kwargs):
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": content}
+ {
+ "role": "system",
+ "content": "You are a translation assistant that translates English to Arabic.",
+ },
+ {"role": "user", "content": content},
],
temperature=0.3,
)
@@ -67,4 +105,3 @@ def calculate_stock_value():
cars = Car.objects.all()
total_value = sum(car.selling_price for car in cars)
return total_value
-
diff --git a/inventory/views.py b/inventory/views.py
index f84de195..23cc9c4b 100644
--- a/inventory/views.py
+++ b/inventory/views.py
@@ -24,7 +24,7 @@ from django.forms import ChoiceField, ModelForm, RadioSelect
from django.urls import reverse, reverse_lazy
from django.contrib import messages
from django.db.models import Sum, F, Count
-from .services import elm, decode_vin_pyvin
+from .services import elm, decodevin,get_make,get_model,normalize_name
from . import models, forms
from django_tables2.export.views import ExportMixin
@@ -133,76 +133,35 @@ class AjaxHandlerView(LoginRequiredMixin, View):
vin_no = request.GET.get('vin_no')
if not vin_no or len(vin_no.strip()) != 17:
return JsonResponse({'success': False, 'error': 'Invalid VIN number provided.'}, status=400)
+
vin_no = vin_no.strip()
vin_data = {}
decoding_method = ''
- decoding_methods = [
- ('PYVIN', decode_vin_pyvin),
- ('VIN', VIN),
- ('ELM', elm)
- ]
-
manufacturer_name = model_name = year_model = None
-
- for method_name, decode_function in decoding_methods:
- try:
- vin_info = decode_function(vin_no)
- if vin_info:
- if method_name == 'PYVIN':
- 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:
- raise ValueError('PYVIN returned incomplete data.')
- elif method_name == 'VIN':
- manufacturer_name = vin_info.make.strip()
- model_name = vin_info.model.strip()
- year_model = vin_info.model_year
- if not manufacturer_name or not model_name or not year_model:
- raise ValueError('VIN returned incomplete data.')
- 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
- else:
- logger.warning(f"{method_name} returned no data for {vin_no}.")
- except Exception as e:
- logger.warning(f"VIN decoding with {method_name} failed for {vin_no}: {e}")
-
- if not manufacturer_name or not model_name or not year_model:
- return JsonResponse({'success': False, 'error': 'VIN not found in all sources.'}, status=404)
-
+ if not (result :=decodevin(vin_no)):
+ return JsonResponse({'success': False, 'error': 'VIN not found in all sources.'}, status=404)
+
+ manufacturer_name,model_name,year_model = result.values()
+ make = get_make(manufacturer_name)
+ model = get_model(model_name,make)
+
logger.info(
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_model = model
+ car_make = make
+
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()
-
+
if not car_model:
- 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['model_id'] = ""
+ else:
+ vin_data['model_id'] = car_model.id_car_model
vin_data['year'] = year_model
return JsonResponse({'success': True, 'data': vin_data})
diff --git a/static/images/logos/vendors/MainAfter.jpg b/static/images/logos/vendors/MainAfter.jpg
new file mode 100644
index 00000000..632e369f
Binary files /dev/null and b/static/images/logos/vendors/MainAfter.jpg differ
diff --git a/templates/base.html b/templates/base.html
index 35106123..162254c8 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -55,9 +55,9 @@ small, .small {
{% endblock %}
\ No newline at end of file