This commit is contained in:
Marwan Alwali 2025-01-12 18:51:06 +03:00
commit 00f87799d0
117 changed files with 194543 additions and 161 deletions

18
.idea/dataSources.xml generated
View File

@ -1,14 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="Django default" uuid="18477c7f-9c08-45c1-bea0-3ceeab27df15">
<driver-ref>postgresql</driver-ref>
<data-source source="LOCAL" name="db" uuid="3573a7a1-f2cc-4e7d-8280-f91580f8eeac">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<imported>true</imported>
<remarks>$PROJECT_DIR$/car_inventory/settings.py</remarks>
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
<jdbc-url>jdbc:postgresql://127.0.0.1:5432/murad_haikal</jdbc-url>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/db.sqlite3</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
</library>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
</library>
</libraries>
</data-source>
</component>
</project>

0
.idea/sqldialects.xml generated Normal file
View File

View File

@ -1,4 +1,4 @@
# Generated by Django 5.1.4 on 2025-01-06 23:09
# Generated by Django 5.1.4 on 2025-01-07 22:27
from django.db import migrations, models

2881
car_make01.json Normal file

File diff suppressed because it is too large Load Diff

4012
carmake_backup.json Normal file

File diff suppressed because it is too large Load Diff

45641
carmodel_backup.json Normal file

File diff suppressed because it is too large Load Diff

141095
carserie_backup.json Normal file

File diff suppressed because it is too large Load Diff

View File

Binary file not shown.

0
cartrim_backup.json Normal file
View File

29
create_json.py Normal file
View File

@ -0,0 +1,29 @@
import mysql.connector
import json
# Connect to MySQL
mysql_conn = mysql.connector.connect(
host='localhost',
user='root',
password='Kfsh&rc9788',
database='trucks2db'
)
cursor = mysql_conn.cursor()
# Get list of tables
cursor.execute("SHOW TABLES")
tables = cursor.fetchall()
for table in tables:
table_name = table[0]
cursor.execute(f"SELECT * FROM {table_name}")
rows = cursor.fetchall()
cursor.execute(f"DESCRIBE {table_name}")
columns = [column[0] for column in cursor.fetchall()]
# Convert rows to list of dictionaries
data = [dict(zip(columns, row)) for row in rows]
# Write to JSON file
with open(f'{table_name}.json', 'w') as f:
json.dump(data, f)

View File

@ -1,4 +1,4 @@
# Generated by Django 5.1.4 on 2025-01-06 23:09
# Generated by Django 5.1.4 on 2025-01-07 22:27
from django.db import migrations, models

View File

@ -1,4 +1,4 @@
# Generated by Django 5.1.4 on 2025-01-06 23:09
# Generated by Django 5.1.4 on 2025-01-07 22:27
import django.db.models.deletion
from django.db import migrations, models

View File

@ -14,7 +14,7 @@ admin.site.register(models.CarColors)
admin.site.register(models.CarRegistration)
admin.site.register(models.CustomCard)
admin.site.register(models.CarSpecificationValue)
admin.site.register(models.CarEquipment)
admin.site.register(models.CarOptionValue)
admin.site.register(models.ExteriorColors)
admin.site.register(models.InteriorColors)

BIN
inventory/data/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -9,7 +9,7 @@ class Command(BaseCommand):
def handle(self, *args, **kwargs):
client = OpenAI(api_key=settings.OPENAI_API_KEY)
car_option = CarOption.objects.all()[8820:]
car_option = CarOption.objects.all()[10300:]
total = car_option.count()
print(f'Translating {total} names...')
for index, car_option in enumerate(car_option, start=1):

View File

@ -1,4 +1,4 @@
# Generated by Django 5.1.4 on 2025-01-06 23:09
# Generated by Django 5.1.4 on 2025-01-07 22:27
import django.db.models.deletion
import inventory.mixins
@ -57,6 +57,7 @@ class Migration(migrations.Migration):
('arabic_name', models.CharField(blank=True, max_length=255, null=True)),
('logo', models.ImageField(blank=True, null=True, upload_to='car_make', verbose_name='logo')),
('is_sa_import', models.BooleanField(default=False)),
('car_type', models.SmallIntegerField(choices=[(1, 'Car'), (2, 'light commercial'), (3, 'truck trailer'), (4, 'trailer'), (5, 'truck'), (6, 'bus')])),
],
options={
'verbose_name': 'Make',
@ -166,20 +167,6 @@ class Migration(migrations.Migration):
},
bases=(models.Model, inventory.mixins.LocalizedNameMixin),
),
migrations.CreateModel(
name='CarGeneration',
fields=[
('id_car_generation', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(blank=True, max_length=255, null=True)),
('arabic_name', models.CharField(blank=True, max_length=255, null=True)),
('year_begin', models.CharField(blank=True, max_length=255, null=True)),
('year_end', models.CharField(blank=True, max_length=255, null=True)),
('id_car_model', models.ForeignKey(db_column='id_car_model', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmodel')),
],
options={
'verbose_name': 'Generation',
},
),
migrations.AddField(
model_name='car',
name='id_car_model',
@ -204,6 +191,7 @@ class Migration(migrations.Migration):
('id_car_option_value', models.AutoField(primary_key=True, serialize=False)),
('value', models.CharField(max_length=500)),
('unit', models.CharField(blank=True, max_length=255, null=True)),
('is_base', models.IntegerField()),
('id_car_equipment', models.ForeignKey(db_column='id_car_equipment', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carequipment')),
('id_car_option', models.ForeignKey(db_column='id_car_option', on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.caroption')),
],
@ -252,8 +240,8 @@ class Migration(migrations.Migration):
name='CarSpecification',
fields=[
('id_car_specification', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(blank=True, max_length=255, null=True)),
('arabic_name', models.CharField(blank=True, max_length=255, null=True)),
('name', models.CharField(max_length=255)),
('arabic_name', models.CharField(max_length=255)),
('id_parent', models.ForeignKey(blank=True, db_column='id_parent', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carspecification')),
],
options={

View File

@ -1,31 +0,0 @@
# Generated by Django 5.1.4 on 2025-01-07 01:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='caroptionvalue',
name='is_base',
field=models.IntegerField(default=1, max_length=1),
preserve_default=False,
),
migrations.AlterField(
model_name='carspecification',
name='arabic_name',
field=models.CharField(default='-', max_length=255),
preserve_default=False,
),
migrations.AlterField(
model_name='carspecification',
name='name',
field=models.CharField(default='-', max_length=255),
preserve_default=False,
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 5.1.4 on 2025-01-07 01:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('inventory', '0002_caroptionvalue_is_base_and_more'),
]
operations = [
migrations.AlterField(
model_name='caroptionvalue',
name='is_base',
field=models.IntegerField(),
),
]

View File

@ -71,7 +71,7 @@ class VatRate(models.Model):
rate = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal('0.15'))
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"Rate: {self.rate}%"
@ -82,6 +82,7 @@ class CarMake(models.Model, LocalizedNameMixin):
arabic_name = models.CharField(max_length=255, blank=True, null=True)
logo = models.ImageField(_("logo"), upload_to="car_make", blank=True, null=True)
is_sa_import = models.BooleanField(default=False)
car_type = models.SmallIntegerField(choices=CarType.choices)
def __str__(self):
return self.name
@ -103,21 +104,6 @@ class CarModel(models.Model, LocalizedNameMixin):
verbose_name = "Model"
class CarGeneration(models.Model):
id_car_generation = models.AutoField(primary_key=True)
id_car_model = models.ForeignKey(CarModel, models.DO_NOTHING, db_column='id_car_model')
name = models.CharField(max_length=255, blank=True, null=True)
arabic_name = models.CharField(max_length=255, blank=True, null=True)
year_begin = models.CharField(max_length=255, blank=True, null=True)
year_end = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
return self.name
class Meta:
verbose_name = "Generation"
class CarSerie(models.Model, LocalizedNameMixin):
id_car_serie = models.AutoField(primary_key=True)
id_car_model = models.ForeignKey(CarModel, models.DO_NOTHING, db_column="id_car_model")
@ -355,14 +341,14 @@ class CarFinance(models.Model):
default=Decimal('0.00'))
@property
def total(self):
def total(self):
if self.additional_services.count() > 0:
return self.selling_price + sum(x.price for x in self.additional_services.all())
return self.selling_price + sum(x.price for x in self.additional_services.all())
return self.selling_price
@property
def total_discount(self):
if self.discount_amount > 0:
return self.total - self.discount_amount
return self.total - self.discount_amount
return self.total
@property

View File

@ -25,7 +25,7 @@ def get_model(item,make):
r = item.split(" ")
for i in r:
if data:=make.carmodel_set.filter(name__iexact=i).first():
break
break
return data
def normalize_name(name):
@ -36,8 +36,8 @@ def decodevin(vin):
if result:=decode_vin(vin):
return result
# elif result:=decode_vin_haikalna(vin):
# return result
elif result:=decode_vin_haikalna(vin):
return result
elif result:=elm(vin):
return result

View File

@ -99,7 +99,7 @@ def create_ledger_entity(sender, instance, created, **kwargs):
# Cash Account
asset_ca_cash = entity.create_account(
coa_model=coa,
code="1010",
code="1101",
role=roles.ASSET_CA_CASH,
name=_("Cash"),
balance_type="debit",

View File

@ -1,4 +1,3 @@
from decimal import Decimal
from django.shortcuts import redirect
from django.contrib import messages
from django.utils import timezone
@ -118,7 +117,7 @@ def calculate_vat_amount(amount):
def get_financial_values(model):
vat = models.VatRate.objects.filter(is_active=True).first()
if not model.get_itemtxs_data()[0].exists():
return {
"vat_amount": 0,
@ -129,7 +128,7 @@ def get_financial_values(model):
"car_and_item_info": [],
"additional_services": [],
}
data = model.get_itemtxs_data()[0].all()
if isinstance(model, InvoiceModel):

View File

@ -262,6 +262,8 @@ class AjaxHandlerView(LoginRequiredMixin, View):
"get_series": self.get_series,
"get_trims": self.get_trims,
"get_specifications": self.get_specifications,
"get_equipments": self.get_equipments,
"get_options": self.get_options,
}
handler = handlers.get(action)
if handler:
@ -332,17 +334,18 @@ class AjaxHandlerView(LoginRequiredMixin, View):
# Validate inputs
if not model_id or not year:
return JsonResponse(
{"error": "Missing required parameters: model_id or year"}, status=400
)
return JsonResponse({"error": "Missing required parameters: model_id or year"}, status=400)
try:
year = int(year)
except ValueError:
return JsonResponse({"error": "Invalid year format"}, status=400)
series = models.CarSerie.objects.filter(id_car_model=model_id).values(
"id_car_serie", "name", "arabic_name"
series = models.CarSerie.objects.filter(
id_car_model=model_id,
year_begin__lte=year,
year_end__gte=year
).values(
"id_car_serie", "name", "arabic_name", "generation_name"
)
return JsonResponse(list(series), safe=False)
@ -391,6 +394,38 @@ class AjaxHandlerView(LoginRequiredMixin, View):
]
return JsonResponse(serialized_specs, safe=False)
def get_equipments(self, request):
trim_id = request.GET.get('trim_id')
equipments = models.CarEquipment.objects.filter(
id_car_trim=trim_id
).values('id_car_equipment', 'name').order_by('name')
return JsonResponse(list(equipments), safe=False)
def get_options(self, request):
equipment_id = request.GET.get('equipment_id')
car_option_values = models.CarOptionValue.objects.filter(id_car_equipment=equipment_id)
options_by_parent = {}
for value in car_option_values:
option = value.id_car_option
parent = option.id_parent
parent_id = parent.id_car_option if parent else 0
parent_name = parent.name if parent else "Root"
if parent_id not in options_by_parent:
options_by_parent[parent_id] = {'parent_name': parent_name, 'options': []}
option_data = {
'option_id': option.id_car_option,
'option_name': option.name,
'is_base': value.is_base,
'equipment_name': value.id_car_equipment.name
}
options_by_parent[parent_id]['options'].append(option_data)
serialized_options = [
{'parent_name': v['parent_name'], 'options': v['options']}
for v in options_by_parent.values()
]
return JsonResponse(serialized_options, safe=False)
class CarInventory(LoginRequiredMixin, ListView):
model = models.Car

View File

@ -1,5 +1,9 @@
import os
import pymysql
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "car_inventory.settings")
django.setup()
import json
from datetime import datetime
from tqdm import tqdm
@ -11,10 +15,10 @@ from inventory.models import (
# Step 1: Perform MySQL Dump
def dump_mysql_database():
print("Starting MySQL dump...")
db_user = "username"
db_password = "password"
db_name = "haikaldb"
dump_file = f"haikaldb_{datetime.now().strftime('%Y%m%d')}.sql"
db_user = "root"
db_password = "Kfsh&rc9788"
db_name = "trucks2db"
dump_file = f"trucks2db_{datetime.now().strftime('%Y%m%d')}.sql"
os.system(f"mysqldump -u {db_user} -p{db_password} {db_name} > {dump_file}")
print(f"MySQL dump completed: {dump_file}")
@ -23,9 +27,9 @@ def export_database_to_json():
print("Starting export to JSON...")
db_config = {
'host': 'localhost',
'user': 'username',
'password': 'password',
'database': 'haikaldb'
'user': 'root',
'password': 'Kfsh&rc9788',
'database': 'trucks2db',
}
connection = pymysql.connect(**db_config)
@ -41,9 +45,9 @@ def export_database_to_json():
columns = [col[0] for col in cursor.description]
database_json[table_name] = [dict(zip(columns, row)) for row in rows]
json_file_name = "database_export.json"
with open(json_file_name, "w") as json_file:
json.dump(database_json, json_file, indent=4)
json_file_name = "trucks20250101.json"
with open(json_file_name, "w") as file:
json.dump(database_json, file, indent=4, ensure_ascii=False)
connection.close()
print(f"Database exported to JSON successfully: {json_file_name}")
@ -182,7 +186,7 @@ def process_json_data(json_file_name):
def main():
dump_mysql_database() # Step 1: Dump the database
json_file_name = export_database_to_json() # Step 2: Export to JSON
process_json_data(json_file_name) # Step 3: Process the JSON
# process_json_data(json_file_name) # Step 3: Process the JSON
if __name__ == "__main__":
main()

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 B

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Some files were not shown because too many files have changed in this diff Show More