Hajat Kateer
This commit is contained in:
parent
4e63d63c2c
commit
d32ac2ab18
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from django.urls import path, include, re_path
|
||||
from django.conf.urls.static import static
|
||||
from django.conf import settings
|
||||
from django.conf.urls.i18n import i18n_patterns
|
||||
|
||||
3319703
car_specification_value.csv
Normal file
3319703
car_specification_value.csv
Normal file
File diff suppressed because it is too large
Load Diff
31
clean_specs.py
Normal file
31
clean_specs.py
Normal file
@ -0,0 +1,31 @@
|
||||
import pandas as pd
|
||||
|
||||
# Specify the path to your CSV file
|
||||
file_path = 'car_specification_value.csv'
|
||||
|
||||
# Read the file and fix inconsistencies
|
||||
try:
|
||||
with open(file_path, 'r') as file:
|
||||
lines = file.readlines()
|
||||
|
||||
# Fix the problematic lines
|
||||
fixed_lines = []
|
||||
for line in lines:
|
||||
# Remove single quotes and strip whitespace
|
||||
columns = [col.strip().replace("'", "") for col in line.strip().split(',')]
|
||||
if len(columns) >= 8: # Ensure at least 8 fields
|
||||
fixed_line = ','.join(f'"{col}"' for col in columns[:8]) # Truncate to 8 fields and add double quotes
|
||||
fixed_lines.append(fixed_line)
|
||||
|
||||
# Save the cleaned data to a new CSV file
|
||||
cleaned_file_path = 'car_specification_value_cleaned.csv'
|
||||
with open(cleaned_file_path, 'w') as file:
|
||||
file.write('\n'.join(fixed_lines))
|
||||
|
||||
# Load the cleaned data into a DataFrame
|
||||
cleaned_df = pd.read_csv(cleaned_file_path)
|
||||
print("Cleaned data preview:")
|
||||
print(cleaned_df.head())
|
||||
print(f"Cleaned file saved as: {cleaned_file_path}")
|
||||
except Exception as e:
|
||||
print(f"An error occurred: {e}")
|
||||
@ -1533,7 +1533,7 @@ def decode_vin(vin):
|
||||
# VR3USHNLWRJ521303
|
||||
# KNARH81E8P5194005
|
||||
# Example usage
|
||||
vin_number = 'LGWEE4A53SK607775'
|
||||
vin_number = 'VYFED9HP0SJ519559'
|
||||
decoded_vin = decode_vin(vin_number)
|
||||
print(decoded_vin)
|
||||
|
||||
|
||||
BIN
inventory/.DS_Store
vendored
BIN
inventory/.DS_Store
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -17,6 +17,8 @@ admin.site.register(models.ExteriorColors)
|
||||
admin.site.register(models.InteriorColors)
|
||||
admin.site.register(models.CarLocation)
|
||||
admin.site.register(models.CarReservation)
|
||||
admin.site.register(models.Organization)
|
||||
admin.site.register(models.Representative)
|
||||
|
||||
@admin.register(models.CarMake)
|
||||
class CarMakeAdmin(admin.ModelAdmin):
|
||||
|
||||
117672
inventory/data/Final_Merged_Car_Generation_and_Serie_Data.csv
Normal file
117672
inventory/data/Final_Merged_Car_Generation_and_Serie_Data.csv
Normal file
File diff suppressed because it is too large
Load Diff
117672
inventory/data/Merged_CarSerie_Data.csv
Normal file
117672
inventory/data/Merged_CarSerie_Data.csv
Normal file
File diff suppressed because it is too large
Load Diff
15639
inventory/data/Merged_Car_Generation_and_Car_Serie.csv
Normal file
15639
inventory/data/Merged_Car_Generation_and_Car_Serie.csv
Normal file
File diff suppressed because it is too large
Load Diff
117672
inventory/data/Merged_Car_Generation_and_Serie_Data.csv
Normal file
117672
inventory/data/Merged_Car_Generation_and_Serie_Data.csv
Normal file
File diff suppressed because it is too large
Load Diff
15772
inventory/data/Updated_Merged_Car_Generation_and_Car_Serie.csv
Normal file
15772
inventory/data/Updated_Merged_Car_Generation_and_Car_Serie.csv
Normal file
File diff suppressed because it is too large
Load Diff
117672
inventory/data/Updated_Merged_Car_Generation_and_Serie_Data.csv
Normal file
117672
inventory/data/Updated_Merged_Car_Generation_and_Serie_Data.csv
Normal file
File diff suppressed because it is too large
Load Diff
412
inventory/data/car_make.csv
Normal file
412
inventory/data/car_make.csv
Normal file
@ -0,0 +1,412 @@
|
||||
id_car_make,name
|
||||
1,AC
|
||||
2,Acura
|
||||
3,Alfa Romeo
|
||||
4,Alpine
|
||||
5,AM General
|
||||
6,Ariel
|
||||
7,Aro
|
||||
8,Asia
|
||||
9,Aston Martin
|
||||
10,Audi
|
||||
11,Austin
|
||||
12,Autobianchi
|
||||
13,Baltijas Dzips
|
||||
14,Beijing
|
||||
15,Bentley
|
||||
16,Bertone
|
||||
17,Bitter
|
||||
18,BMW
|
||||
20,Brabus
|
||||
21,Brilliance
|
||||
22,Bristol
|
||||
23,Bufori
|
||||
24,Bugatti
|
||||
25,Buick
|
||||
26,BYD
|
||||
27,Byvin
|
||||
28,Cadillac
|
||||
29,Callaway
|
||||
30,Carbodies
|
||||
31,Caterham
|
||||
32,Changan
|
||||
33,ChangFeng
|
||||
34,Chery
|
||||
35,Chevrolet
|
||||
36,Chrysler
|
||||
37,Citroen
|
||||
38,Cizeta
|
||||
39,Coggiola
|
||||
40,Dacia
|
||||
41,Dadi
|
||||
42,Daewoo
|
||||
44,Daihatsu
|
||||
45,Daimler
|
||||
46,Dallas
|
||||
47,Datsun
|
||||
48,De Tomaso
|
||||
49,DeLorean
|
||||
50,Derways
|
||||
51,Dodge
|
||||
52,DongFeng
|
||||
53,Doninvest
|
||||
54,Donkervoort
|
||||
55,E-Car
|
||||
56,Eagle
|
||||
57,Eagle Cars
|
||||
59,FAW
|
||||
60,Ferrari
|
||||
61,Fiat
|
||||
62,Fisker
|
||||
63,Ford
|
||||
64,Foton
|
||||
65,FSO
|
||||
66,Fuqi
|
||||
67,Geely
|
||||
68,Geo
|
||||
69,GMC
|
||||
70,Gonow
|
||||
71,Great Wall
|
||||
72,Hafei
|
||||
73,Haima
|
||||
74,Hindustan
|
||||
75,Holden
|
||||
76,Honda
|
||||
77,HuangHai
|
||||
78,Hummer
|
||||
79,Hyundai
|
||||
80,Infiniti
|
||||
81,Innocenti
|
||||
82,Invicta
|
||||
83,Iran Khodro
|
||||
84,Isdera
|
||||
85,Isuzu
|
||||
86,IVECO
|
||||
87,JAC
|
||||
88,Jaguar
|
||||
89,Jeep
|
||||
90,Jensen
|
||||
91,JMC
|
||||
92,Kia
|
||||
93,Koenigsegg
|
||||
95,Lamborghini
|
||||
96,Lancia
|
||||
97,Land Rover
|
||||
98,Landwind
|
||||
99,Lexus
|
||||
100,Liebao Motor
|
||||
101,Lifan
|
||||
102,Lincoln
|
||||
103,Lotus
|
||||
104,LTI
|
||||
105,Luxgen
|
||||
106,Mahindra
|
||||
107,Marcos
|
||||
108,Marlin
|
||||
109,Marussia
|
||||
110,Maruti
|
||||
111,Maserati
|
||||
112,Maybach
|
||||
113,Mazda
|
||||
114,McLaren
|
||||
115,Mega
|
||||
116,Mercedes-Benz
|
||||
117,Mercury
|
||||
118,Metrocab
|
||||
119,MG
|
||||
120,Microcar
|
||||
121,Minelli
|
||||
122,Mini
|
||||
123,Mitsubishi
|
||||
124,Mitsuoka
|
||||
125,Morgan
|
||||
126,Morris
|
||||
127,Nissan
|
||||
128,Noble
|
||||
129,Oldsmobile
|
||||
130,Opel
|
||||
131,Osca
|
||||
132,Pagani
|
||||
133,Panoz
|
||||
134,Perodua
|
||||
135,Peugeot
|
||||
136,Piaggio
|
||||
137,Plymouth
|
||||
138,Pontiac
|
||||
139,Porsche
|
||||
140,Premier
|
||||
141,Proton
|
||||
142,PUCH
|
||||
143,Puma
|
||||
144,Qoros
|
||||
145,Qvale
|
||||
146,Reliant
|
||||
147,Renault
|
||||
148,Samsung
|
||||
149,Rolls-Royce
|
||||
150,Ronart
|
||||
151,Rover
|
||||
152,Saab
|
||||
153,Saleen
|
||||
154,Santana
|
||||
155,Saturn
|
||||
156,Scion
|
||||
157,SEAT
|
||||
158,ShuangHuan
|
||||
159,Skoda
|
||||
160,Smart
|
||||
161,Soueast
|
||||
162,Spectre
|
||||
163,Spyker
|
||||
165,SsangYong
|
||||
166,Subaru
|
||||
167,Suzuki
|
||||
168,Talbot
|
||||
169,Tata
|
||||
170,Tatra
|
||||
171,Tazzari
|
||||
172,Tesla
|
||||
173,Tianma
|
||||
174,Tianye
|
||||
175,Tofas
|
||||
176,Toyota
|
||||
177,Trabant
|
||||
178,Tramontana
|
||||
179,Triumph
|
||||
180,TVR
|
||||
181,Vauxhall
|
||||
182,Vector
|
||||
183,Venturi
|
||||
184,Volkswagen
|
||||
185,Volvo
|
||||
186,Vortex
|
||||
187,Wartburg
|
||||
188,Westfield
|
||||
189,Wiesmann
|
||||
190,Xin Kai
|
||||
191,Zastava
|
||||
192,Zotye
|
||||
193,ZX
|
||||
211,Yo-mobil
|
||||
212,Autocam
|
||||
215,VAZ (Lada)
|
||||
216,GAZ
|
||||
217,ZAZ
|
||||
218,ZIL
|
||||
219,IZH
|
||||
221,Kanonir
|
||||
222,LuAZ
|
||||
223,Moskvich
|
||||
224,SMZ
|
||||
226,TagAZ
|
||||
227,UAZ
|
||||
280,Ultima
|
||||
282,Hawtai
|
||||
284,Renaissance Cars
|
||||
286,Paykan
|
||||
289,Gordon
|
||||
290,Haval
|
||||
291,Alpina
|
||||
3589,DS
|
||||
3590,PGO
|
||||
3591,Zenvo
|
||||
3619,Rezvani
|
||||
3620,Rimac
|
||||
3664,Adler
|
||||
3665,DeSoto
|
||||
3666,Packard
|
||||
3667,Willys
|
||||
3668,Combat
|
||||
3676,Borgward
|
||||
3689,Ravon
|
||||
3690,ZiS
|
||||
3705,AMC
|
||||
3706,Zenos
|
||||
3728,W Motors
|
||||
3739,Hudson
|
||||
3749,Austin Healey
|
||||
3751,BAW
|
||||
3752,Chana
|
||||
3753,Changhe
|
||||
3754,DFSK
|
||||
3755,Efini
|
||||
3756,Excalibur
|
||||
3757,Groz
|
||||
3760,Hurtan
|
||||
3761,Jiangnan
|
||||
3762,Jinbei
|
||||
3764,Maxus
|
||||
3765,Monte Carlo
|
||||
3767,Nysa
|
||||
3771,Shifeng
|
||||
3772,SMA
|
||||
3774,Wuling
|
||||
3815,Genesis
|
||||
3816,International
|
||||
3821,Zibar
|
||||
3822,Other car
|
||||
4142,RAM
|
||||
4144,Aurus
|
||||
4145,Trumpchi
|
||||
4146,Abarth
|
||||
4147,Baic
|
||||
4148,DFM
|
||||
4149,Saipa
|
||||
4154,Apal
|
||||
4155,Bajaj
|
||||
4156,Batmobile
|
||||
4157,Bilenkin
|
||||
4158,Cord
|
||||
4159,Delage
|
||||
4160,DKW
|
||||
4162,DW Hower
|
||||
4163,Flanker
|
||||
4164,GAC
|
||||
4165,GP
|
||||
4166,Hanomag
|
||||
4167,Hispano-Suiza
|
||||
4168,Horch
|
||||
4169,KTM AG
|
||||
4170,Ligier
|
||||
4171,Lucid
|
||||
4172,Nash
|
||||
4173,Rambler
|
||||
4174,Renaissance
|
||||
4175,Renault Samsung
|
||||
4176,Rinspeed
|
||||
4177,Shanghai Maple
|
||||
4178,Simca
|
||||
4179,Steyr
|
||||
4180,Studebaker
|
||||
4181,Think
|
||||
4182,Wanderer
|
||||
4183,Racing car
|
||||
4184,Logem
|
||||
4186,Dallara
|
||||
4187,Heinkel
|
||||
4188,Yulon
|
||||
4189,Bio auto
|
||||
4190,Deco Rides
|
||||
4191,Sears
|
||||
4192,Xpeng
|
||||
4195,Roewe
|
||||
4196,CheryExeed
|
||||
4197,LiXiang
|
||||
4198,Nio
|
||||
4199,Hennessey
|
||||
4200,Polestar
|
||||
4201,Auburn
|
||||
4202,Weltmeister
|
||||
4203,Cupra
|
||||
4204,Goggomobil
|
||||
4205,HSV
|
||||
4206,Matra
|
||||
4207,Messerschmitt
|
||||
4208,Pierce-Arrow
|
||||
4209,VUHL
|
||||
4210,Ciimo
|
||||
4211,Everus
|
||||
4212,Facel Vega
|
||||
4213,Hongqi
|
||||
4214,Hozon
|
||||
4215,Aion
|
||||
4216,Blaval
|
||||
4217,Skywell
|
||||
4307,Voyah
|
||||
4308,Rivian
|
||||
4309,Zeekr
|
||||
4310,Leapmotor
|
||||
4311,Tank
|
||||
4312,Arcfox
|
||||
4313,Auto Union
|
||||
4314,Denza
|
||||
4315,Evolute
|
||||
4316,HiPhi
|
||||
4317,Kaiyi
|
||||
4318,Omoda
|
||||
4319,DR
|
||||
4320,Mobilize
|
||||
4321,Oshan
|
||||
4322,Aito
|
||||
4323,Baojun
|
||||
4324,Jetour
|
||||
4325,Jetta
|
||||
4326,Lynk & Co
|
||||
4327,Seres
|
||||
4361,ORA
|
||||
4362,WEY
|
||||
4363,Avatr
|
||||
4364,Dongfeng Forthing
|
||||
4365,Rising Auto
|
||||
4366,IM Motors (Zhiji)
|
||||
4367,VinFast
|
||||
4368,Livan
|
||||
4369,SWM
|
||||
4947,EXEED
|
||||
4948,Changan Kuayue (KYC)
|
||||
4949,VGV
|
||||
4950,Russo-Balt
|
||||
4951,Aiways
|
||||
4952,KYC
|
||||
4953,Skyworth
|
||||
4954,Yema
|
||||
5037,Overland
|
||||
5038,Belgee
|
||||
5039,Dayun
|
||||
5040,Enoreve
|
||||
5041,Enovate
|
||||
5042,Jaecoo
|
||||
5043,JMEV
|
||||
5044,Jonway
|
||||
5045,KG Mobility
|
||||
5046,Qiantu
|
||||
5047,Qingling
|
||||
5048,Radar
|
||||
5049,Rox
|
||||
5050,Sollers
|
||||
5051,Thairung
|
||||
5052,Venucia
|
||||
5053,ATOM
|
||||
5128,Hycan
|
||||
5129,Qiyuan
|
||||
5130,XiaoPaoChe (SSC)
|
||||
5233,Fengon
|
||||
5234,M-Hero
|
||||
5235,Oting
|
||||
5236,Rossa
|
||||
5238,Huazi
|
||||
5239,iCar
|
||||
5240,Luxeed
|
||||
5241,XEV
|
||||
5242,Xiaomi
|
||||
5305,Hanteng
|
||||
5306,Kawei
|
||||
5335,Ineos
|
||||
5336,Karma
|
||||
5337,Seres Aito
|
||||
5338,Solaris
|
||||
5339,Yipai
|
||||
5340,Amberauto
|
||||
5341,Polar Stone (Jishi)
|
||||
5342,Xcite
|
||||
5343,Coda
|
||||
5405,Aixam
|
||||
5406,Ambertruck
|
||||
5407,Huaihai (Hoann)
|
||||
5408,Maple
|
||||
5409,Maxeed
|
||||
5410,Volga
|
||||
5481,Exlantix
|
||||
5482,LEVC
|
||||
5483,Rayton Fissore
|
||||
5484,Stelato
|
||||
5542,Franklin
|
||||
5543,Jidu
|
||||
5544,GMA
|
||||
5545,Knewstar
|
||||
5586,lingxi
|
||||
5609,Hyperion
|
||||
5610,Punk
|
||||
5611,Radford
|
||||
5612,Sandstorm
|
||||
5613,Scout
|
||||
|
5296
inventory/data/car_model.csv
Normal file
5296
inventory/data/car_model.csv
Normal file
File diff suppressed because it is too large
Load Diff
105
inventory/data/car_specification.csv
Normal file
105
inventory/data/car_specification.csv
Normal file
@ -0,0 +1,105 @@
|
||||
id_car_specification,name,id_parent
|
||||
1,Bodywork,
|
||||
2,Body type,1
|
||||
3,Number of doors,1549
|
||||
4,Number of seater,1
|
||||
5,Length,1
|
||||
6,Width,1
|
||||
7,Height,1
|
||||
8,Wheelbase,1
|
||||
9,Front track,1
|
||||
10,Rear track,1
|
||||
11,Engine,
|
||||
12,Engine type,11
|
||||
13,Capacity,11
|
||||
14,Engine power,11
|
||||
15,Max power at RPM,11
|
||||
16,Maximum torque,11
|
||||
17,Injection type,11
|
||||
18,Overhead camshaft,11
|
||||
19,Cylinder layout,11
|
||||
20,Number of cylinders,11
|
||||
21,Compression ratio,11
|
||||
22,Fuel,31
|
||||
23,Gearbox and handling,
|
||||
24,Gearbox type,23
|
||||
26,Number of gear,23
|
||||
27,Drive wheels,23
|
||||
29,Front brakes,40
|
||||
30,Rear brakes,40
|
||||
31,Operating characteristics,
|
||||
32,Max speed,31
|
||||
33,Acceleration (0-100 km/h),31
|
||||
34,Curb weight,1
|
||||
35,Fuel tank capacity,31
|
||||
36,Wheel size,1
|
||||
37,Emission standards,31
|
||||
38,Ground clearance,1
|
||||
39,Valves per cylinder,11
|
||||
40,Suspension and brakes,
|
||||
41,Front suspension,40
|
||||
42,Back suspension,40
|
||||
44,Max trunk capacity,1
|
||||
45,Min trunk capacity,1
|
||||
46,Boost type,11
|
||||
47,Cylinder bore,11
|
||||
48,Stroke cycle,11
|
||||
49,Bore/stroke ratio,23
|
||||
50,City driving fuel consumption per 100 km,31
|
||||
51,Highway driving fuel consumption per 100 km,31
|
||||
52,Mixed driving fuel consumption per 100 km,31
|
||||
53,Steering,
|
||||
54,Steering type,53
|
||||
55,Engine model,11
|
||||
56,Electric motor power,11
|
||||
57,Turning circle,23
|
||||
58,Full weight,1
|
||||
59,Disc size,31
|
||||
60,Total power output,11
|
||||
61,Engine placement,11
|
||||
62,Cruising range,31
|
||||
63,Full cycle charge,31
|
||||
66,Car width with mirrors,1
|
||||
1521,Cylinder bore and stroke cycle,11
|
||||
1549,General information,
|
||||
1550,Volume and weight,
|
||||
1551,Security,
|
||||
1552,Country,1549
|
||||
1553,Car class,1549
|
||||
1554,Clearance,1
|
||||
1555,Front track width,1
|
||||
1556,Back track width,1
|
||||
1558,Max power (h.p.),11
|
||||
1559,Max power (kW),11
|
||||
1560,Model assembly,1549
|
||||
1561,CO2 emissions,31
|
||||
1562,Safety assessment,1551
|
||||
1563,Rating name,1551
|
||||
1564,Turnover of maximum torque,11
|
||||
1565,Payload,1
|
||||
1566,Presence of intercooler,11
|
||||
1567,Trailer load (with brakes),1
|
||||
1568,Front/rear axle load,1
|
||||
1569,Loading height,1
|
||||
1570,Cargo compartment (Length x Width x Height),1
|
||||
1571,Cargo compartment volume,1
|
||||
1631,Accumulator battery,
|
||||
1632,Battery capacity,1631
|
||||
1634,Electric power reserve,1631
|
||||
1635,Charging time,1631
|
||||
1636,Fuel consumption city/highway/mixed l',31
|
||||
1641,Rudder location,53
|
||||
1642,Dimensions,1
|
||||
1644,Pitch Circle Diameter,1
|
||||
1645,Engine code,11
|
||||
1646,Disc sizes,1
|
||||
1647,Battery type,1631
|
||||
1648,Timing belt,11
|
||||
1649,Flow calculation method,11
|
||||
1650,Battery temperature,1631
|
||||
1651,Fast charge time,1631
|
||||
1652,Description of fast charging,1631
|
||||
1653,Charging connector type,1631
|
||||
1654,Consumption,1631
|
||||
1655,Maximum charging power,1631
|
||||
1656,Battery capacity (available),1631
|
||||
|
3319703
inventory/data/car_specification_value.csv
Normal file
3319703
inventory/data/car_specification_value.csv
Normal file
File diff suppressed because it is too large
Load Diff
4
inventory/data/car_specification_value1.csv
Normal file
4
inventory/data/car_specification_value1.csv
Normal file
@ -0,0 +1,4 @@
|
||||
id_car_specification_value,id_car_trim,id_car_specification,value,unit,date_create,date_update,id_car_type
|
||||
7278893,12743,52,10,l,1400481796,1400481796,1
|
||||
7278894,12743,34,1582,kg,1400481796,1400481796,1
|
||||
7420800,18896,2,Cabriolet,NULL,1402348874,1402348874,1
|
||||
|
86803
inventory/data/car_trim.csv
Normal file
86803
inventory/data/car_trim.csv
Normal file
File diff suppressed because it is too large
Load Diff
84305
inventory/data/filters.csv
Normal file
84305
inventory/data/filters.csv
Normal file
File diff suppressed because it is too large
Load Diff
117672
inventory/data/final_merged_car_serie.csv
Normal file
117672
inventory/data/final_merged_car_serie.csv
Normal file
File diff suppressed because it is too large
Load Diff
502
inventory/data/generation.json
Normal file
502
inventory/data/generation.json
Normal file
@ -0,0 +1,502 @@
|
||||
[
|
||||
{
|
||||
"id_car_generation": 1,
|
||||
"id_car_model": 2123,
|
||||
"name": "2 generation",
|
||||
"year_begin": "2013",
|
||||
"year_end": "2020",
|
||||
"date_create": 1403453052,
|
||||
"date_update": 1629665942,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 4,
|
||||
"id_car_model": 7,
|
||||
"name": "2 generation",
|
||||
"year_begin": "2001",
|
||||
"year_end": "2003",
|
||||
"date_create": 1403637064,
|
||||
"date_update": 1568054401,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 5,
|
||||
"id_car_model": 7,
|
||||
"name": "1 generation",
|
||||
"year_begin": "1997",
|
||||
"year_end": "2001",
|
||||
"date_create": 1403637064,
|
||||
"date_update": 1461884287,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 6,
|
||||
"id_car_model": 9,
|
||||
"name": "3 generation",
|
||||
"year_begin": "1993",
|
||||
"year_end": "2001",
|
||||
"date_create": 1403637072,
|
||||
"date_update": 1586337762,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 7,
|
||||
"id_car_model": 9,
|
||||
"name": "2 generation",
|
||||
"year_begin": "1989",
|
||||
"year_end": "1993",
|
||||
"date_create": 1403637072,
|
||||
"date_update": 1586337723,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 8,
|
||||
"id_car_model": 9,
|
||||
"name": "1 generation",
|
||||
"year_begin": "1991",
|
||||
"year_end": "2002",
|
||||
"date_create": 1403637072,
|
||||
"date_update": 1586390460,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 9,
|
||||
"id_car_model": 10,
|
||||
"name": "2 generation",
|
||||
"year_begin": "1990",
|
||||
"year_end": "1996",
|
||||
"date_create": 1403637075,
|
||||
"date_update": 1461884289,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 10,
|
||||
"id_car_model": 10,
|
||||
"name": "1 generation",
|
||||
"year_begin": "1986",
|
||||
"year_end": "1990",
|
||||
"date_create": 1403637075,
|
||||
"date_update": 1461884290,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 11,
|
||||
"id_car_model": 11,
|
||||
"name": "3 generation",
|
||||
"year_begin": "2013",
|
||||
"year_end": "2020",
|
||||
"date_create": 1403637079,
|
||||
"date_update": 1629662287,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 12,
|
||||
"id_car_model": 11,
|
||||
"name": "2 generation",
|
||||
"year_begin": "2006",
|
||||
"year_end": "2009",
|
||||
"date_create": 1403637079,
|
||||
"date_update": 1568054401,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 13,
|
||||
"id_car_model": 11,
|
||||
"name": "1 generation",
|
||||
"year_begin": "2001",
|
||||
"year_end": "2006",
|
||||
"date_create": 1403637079,
|
||||
"date_update": 1568054401,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 14,
|
||||
"id_car_model": 13,
|
||||
"name": "2 generation",
|
||||
"year_begin": "2012",
|
||||
"year_end": "2020",
|
||||
"date_create": 1403637086,
|
||||
"date_update": 1629662290,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 15,
|
||||
"id_car_model": 13,
|
||||
"name": "1 generation",
|
||||
"year_begin": "2006",
|
||||
"year_end": "2010",
|
||||
"date_create": 1403637086,
|
||||
"date_update": 1568054402,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 16,
|
||||
"id_car_model": 14,
|
||||
"name": "KB2",
|
||||
"year_begin": "2008",
|
||||
"year_end": "2010",
|
||||
"date_create": 1403637090,
|
||||
"date_update": 1577311082,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 17,
|
||||
"id_car_model": 14,
|
||||
"name": "KA9",
|
||||
"year_begin": "1999",
|
||||
"year_end": "2004",
|
||||
"date_create": 1403637090,
|
||||
"date_update": 1577311083,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 18,
|
||||
"id_car_model": 18,
|
||||
"name": "4 generation",
|
||||
"year_begin": "2008",
|
||||
"year_end": "2011",
|
||||
"date_create": 1403637129,
|
||||
"date_update": 1568054402,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 19,
|
||||
"id_car_model": 18,
|
||||
"name": "3 generation",
|
||||
"year_begin": "2003",
|
||||
"year_end": "2008",
|
||||
"date_create": 1403637129,
|
||||
"date_update": 1568054402,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 20,
|
||||
"id_car_model": 18,
|
||||
"name": "2 generation",
|
||||
"year_begin": "1998",
|
||||
"year_end": "2003",
|
||||
"date_create": 1403637129,
|
||||
"date_update": 1568054402,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 21,
|
||||
"id_car_model": 18,
|
||||
"name": "1 generation",
|
||||
"year_begin": "1995",
|
||||
"year_end": "1998",
|
||||
"date_create": 1403637129,
|
||||
"date_update": 1568054402,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 22,
|
||||
"id_car_model": 19,
|
||||
"name": "2 generation",
|
||||
"year_begin": "2008",
|
||||
"year_end": "2010",
|
||||
"date_create": 1403637132,
|
||||
"date_update": 1568054402,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 23,
|
||||
"id_car_model": 19,
|
||||
"name": "1 generation",
|
||||
"year_begin": "2003",
|
||||
"year_end": "2008",
|
||||
"date_create": 1403637132,
|
||||
"date_update": 1568054402,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 27,
|
||||
"id_car_model": 28,
|
||||
"name": "1 generation [restyling]",
|
||||
"year_begin": "2003",
|
||||
"year_end": "2007",
|
||||
"date_create": 1403637189,
|
||||
"date_update": 1461877031,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 28,
|
||||
"id_car_model": 28,
|
||||
"name": "936",
|
||||
"year_begin": "1998",
|
||||
"year_end": "2007",
|
||||
"date_create": 1403637189,
|
||||
"date_update": 1568054404,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 29,
|
||||
"id_car_model": 29,
|
||||
"name": "907",
|
||||
"year_begin": "1990",
|
||||
"year_end": "1994",
|
||||
"date_create": 1403637192,
|
||||
"date_update": 1568054404,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 30,
|
||||
"id_car_model": 29,
|
||||
"name": "905",
|
||||
"year_begin": "1983",
|
||||
"year_end": "1986",
|
||||
"date_create": 1403637193,
|
||||
"date_update": 1461877033,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 35,
|
||||
"id_car_model": 40,
|
||||
"name": "116",
|
||||
"year_begin": "1977",
|
||||
"year_end": "1981",
|
||||
"date_create": 1403637463,
|
||||
"date_update": 1568054405,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 36,
|
||||
"id_car_model": 47,
|
||||
"name": "939",
|
||||
"year_begin": "2006",
|
||||
"year_end": "2010",
|
||||
"date_create": 1403637573,
|
||||
"date_update": 1568054406,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 37,
|
||||
"id_car_model": 47,
|
||||
"name": "916",
|
||||
"year_begin": "1995",
|
||||
"year_end": "2006",
|
||||
"date_create": 1403637573,
|
||||
"date_update": 1568054406,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 38,
|
||||
"id_car_model": 47,
|
||||
"name": "115",
|
||||
"year_begin": "1990",
|
||||
"year_end": "1993",
|
||||
"date_create": 1403637573,
|
||||
"date_update": 1568054406,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 43,
|
||||
"id_car_model": 63,
|
||||
"name": "1 generation [restyling]",
|
||||
"year_begin": "2008",
|
||||
"year_end": "2012",
|
||||
"date_create": 1403637672,
|
||||
"date_update": 1568054407,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 46,
|
||||
"id_car_model": 67,
|
||||
"name": "1 generation [restyling]",
|
||||
"year_begin": "2013",
|
||||
"year_end": "2021",
|
||||
"date_create": 1403637687,
|
||||
"date_update": 1653251495,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 47,
|
||||
"id_car_model": 67,
|
||||
"name": "1 generation",
|
||||
"year_begin": "2009",
|
||||
"year_end": "2012",
|
||||
"date_create": 1403637687,
|
||||
"date_update": 1568054408,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 48,
|
||||
"id_car_model": 69,
|
||||
"name": "2 generation",
|
||||
"year_begin": "2012",
|
||||
"year_end": "2020",
|
||||
"date_create": 1403637695,
|
||||
"date_update": 1653251496,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 49,
|
||||
"id_car_model": 69,
|
||||
"name": "1 generation",
|
||||
"year_begin": "2001",
|
||||
"year_end": "2007",
|
||||
"date_create": 1403637695,
|
||||
"date_update": 1568054408,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 52,
|
||||
"id_car_model": 74,
|
||||
"name": "2 generation",
|
||||
"year_begin": "2011",
|
||||
"year_end": "2012",
|
||||
"date_create": 1403637969,
|
||||
"date_update": 1461877095,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 53,
|
||||
"id_car_model": 74,
|
||||
"name": "1 generation",
|
||||
"year_begin": "2011",
|
||||
"year_end": "2012",
|
||||
"date_create": 1403637969,
|
||||
"date_update": 1568054408,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 54,
|
||||
"id_car_model": 78,
|
||||
"name": "8C/B4",
|
||||
"year_begin": "1991",
|
||||
"year_end": "1996",
|
||||
"date_create": 1403638037,
|
||||
"date_update": 1568054409,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 55,
|
||||
"id_car_model": 78,
|
||||
"name": "8A/B3",
|
||||
"year_begin": "1986",
|
||||
"year_end": "1991",
|
||||
"date_create": 1403638037,
|
||||
"date_update": 1568054409,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 56,
|
||||
"id_car_model": 78,
|
||||
"name": "B2",
|
||||
"year_begin": "1978",
|
||||
"year_end": "1986",
|
||||
"date_create": 1403638037,
|
||||
"date_update": 1579480971,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 57,
|
||||
"id_car_model": 78,
|
||||
"name": "B1 [restyling]",
|
||||
"year_begin": null,
|
||||
"year_end": null,
|
||||
"date_create": 1403638037,
|
||||
"date_update": 1568054410,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 59,
|
||||
"id_car_model": 82,
|
||||
"name": "8V",
|
||||
"year_begin": "2012",
|
||||
"year_end": "2016",
|
||||
"date_create": 1403638083,
|
||||
"date_update": 1579480982,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 61,
|
||||
"id_car_model": 82,
|
||||
"name": "8P",
|
||||
"year_begin": "2003",
|
||||
"year_end": "2005",
|
||||
"date_create": 1403638083,
|
||||
"date_update": 1579480988,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 62,
|
||||
"id_car_model": 84,
|
||||
"name": "B8/8K [restyling]",
|
||||
"year_begin": "2011",
|
||||
"year_end": "2016",
|
||||
"date_create": 1403638088,
|
||||
"date_update": 1568054413,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 63,
|
||||
"id_car_model": 84,
|
||||
"name": "B8/8K",
|
||||
"year_begin": "2007",
|
||||
"year_end": "2011",
|
||||
"date_create": 1403638088,
|
||||
"date_update": 1568054413,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 64,
|
||||
"id_car_model": 84,
|
||||
"name": "B7",
|
||||
"year_begin": "2004",
|
||||
"year_end": "2008",
|
||||
"date_create": 1403638088,
|
||||
"date_update": 1579480998,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 65,
|
||||
"id_car_model": 84,
|
||||
"name": "B6",
|
||||
"year_begin": "2000",
|
||||
"year_end": "2005",
|
||||
"date_create": 1403638088,
|
||||
"date_update": 1579481000,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 66,
|
||||
"id_car_model": 84,
|
||||
"name": "B5 [restyling]",
|
||||
"year_begin": "1997",
|
||||
"year_end": "2001",
|
||||
"date_create": 1403638089,
|
||||
"date_update": 1568054414,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 68,
|
||||
"id_car_model": 85,
|
||||
"name": "8T [restyling]",
|
||||
"year_begin": "2011",
|
||||
"year_end": "2016",
|
||||
"date_create": 1403638091,
|
||||
"date_update": 1579481007,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 70,
|
||||
"id_car_model": 86,
|
||||
"name": "4F,C6",
|
||||
"year_begin": "2006",
|
||||
"year_end": "2008",
|
||||
"date_create": 1403638093,
|
||||
"date_update": 1560774955,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_generation": 71,
|
||||
"id_car_model": 86,
|
||||
"name": "4B/C5",
|
||||
"year_begin": "2000",
|
||||
"year_end": "2005",
|
||||
"date_create": 1403638093,
|
||||
"date_update": 1568054415,
|
||||
"id_car_type": 1
|
||||
}
|
||||
]
|
||||
85843
inventory/data/mappings.csv
Normal file
85843
inventory/data/mappings.csv
Normal file
File diff suppressed because it is too large
Load Diff
452
inventory/data/serie.json
Normal file
452
inventory/data/serie.json
Normal file
@ -0,0 +1,452 @@
|
||||
[
|
||||
{
|
||||
"id_car_serie": 457,
|
||||
"id_car_model": 350,
|
||||
"id_car_generation": 7840,
|
||||
"name": "Crossover",
|
||||
"date_create": 1399138514,
|
||||
"date_update": 1586393837,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 458,
|
||||
"id_car_model": 351,
|
||||
"id_car_generation": 7841,
|
||||
"name": "Sedan",
|
||||
"date_create": 1399138516,
|
||||
"date_update": 1568054502,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 461,
|
||||
"id_car_model": 353,
|
||||
"id_car_generation": 7842,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399138520,
|
||||
"date_update": 1568054502,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 464,
|
||||
"id_car_model": 356,
|
||||
"id_car_generation": 7151,
|
||||
"name": "Crossover",
|
||||
"date_create": 1399139415,
|
||||
"date_update": 1568054503,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 465,
|
||||
"id_car_model": 357,
|
||||
"id_car_generation": 7152,
|
||||
"name": "SUV 5-doors",
|
||||
"date_create": 1399139417,
|
||||
"date_update": 1461877213,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 471,
|
||||
"id_car_model": 361,
|
||||
"id_car_generation": 7847,
|
||||
"name": "Fastback",
|
||||
"date_create": 1399139422,
|
||||
"date_update": 1568054505,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 477,
|
||||
"id_car_model": 365,
|
||||
"id_car_generation": 7850,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399139427,
|
||||
"date_update": 1568054506,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 478,
|
||||
"id_car_model": 366,
|
||||
"id_car_generation": 7851,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399139710,
|
||||
"date_update": 1568054506,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 479,
|
||||
"id_car_model": 367,
|
||||
"id_car_generation": 7852,
|
||||
"name": "Hatchback 5-doors",
|
||||
"date_create": 1399139713,
|
||||
"date_update": 1461884968,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 480,
|
||||
"id_car_model": 368,
|
||||
"id_car_generation": 7853,
|
||||
"name": "Minivan",
|
||||
"date_create": 1399139715,
|
||||
"date_update": 1568054506,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 486,
|
||||
"id_car_model": 372,
|
||||
"id_car_generation": 7856,
|
||||
"name": "Hatchback 5-doors",
|
||||
"date_create": 1399139722,
|
||||
"date_update": 1461884971,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 494,
|
||||
"id_car_model": 376,
|
||||
"id_car_generation": 7858,
|
||||
"name": "Minivan",
|
||||
"date_create": 1399140313,
|
||||
"date_update": 1568054521,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 498,
|
||||
"id_car_model": 378,
|
||||
"id_car_generation": 7860,
|
||||
"name": "Moroder Coupe",
|
||||
"date_create": 1399140317,
|
||||
"date_update": 1568054522,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 505,
|
||||
"id_car_model": 382,
|
||||
"id_car_generation": 7863,
|
||||
"name": "Coupe",
|
||||
"date_create": 1399140323,
|
||||
"date_update": 1461885011,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 506,
|
||||
"id_car_model": 383,
|
||||
"id_car_generation": 7864,
|
||||
"name": "Compactvan",
|
||||
"date_create": 1399140325,
|
||||
"date_update": 1555412782,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 508,
|
||||
"id_car_model": 385,
|
||||
"id_car_generation": 7865,
|
||||
"name": "Compactvan Stepway",
|
||||
"date_create": 1399140328,
|
||||
"date_update": 1461885013,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 511,
|
||||
"id_car_model": 387,
|
||||
"id_car_generation": 7866,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399141253,
|
||||
"date_update": 1586460721,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 513,
|
||||
"id_car_model": 389,
|
||||
"id_car_generation": 7867,
|
||||
"name": "Sedan",
|
||||
"date_create": 1399141257,
|
||||
"date_update": 1568054523,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 515,
|
||||
"id_car_model": 391,
|
||||
"id_car_generation": 7868,
|
||||
"name": "SUV",
|
||||
"date_create": 1399141261,
|
||||
"date_update": 1568054523,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 534,
|
||||
"id_car_model": 404,
|
||||
"id_car_generation": 7156,
|
||||
"name": "Sedan",
|
||||
"date_create": 1399142733,
|
||||
"date_update": 1568054525,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 535,
|
||||
"id_car_model": 405,
|
||||
"id_car_generation": 7878,
|
||||
"name": "Sedan",
|
||||
"date_create": 1399142735,
|
||||
"date_update": 1568054525,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 536,
|
||||
"id_car_model": 406,
|
||||
"id_car_generation": 7879,
|
||||
"name": "Sedan",
|
||||
"date_create": 1399143306,
|
||||
"date_update": 1568054525,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 538,
|
||||
"id_car_model": 408,
|
||||
"id_car_generation": 7880,
|
||||
"name": "SUV",
|
||||
"date_create": 1399143310,
|
||||
"date_update": 1568054526,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 542,
|
||||
"id_car_model": 411,
|
||||
"id_car_generation": 7881,
|
||||
"name": "Sedan",
|
||||
"date_create": 1399143315,
|
||||
"date_update": 1568054529,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 545,
|
||||
"id_car_model": 413,
|
||||
"id_car_generation": 7883,
|
||||
"name": "Minivan",
|
||||
"date_create": 1399143318,
|
||||
"date_update": 1568054530,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 546,
|
||||
"id_car_model": 414,
|
||||
"id_car_generation": 7884,
|
||||
"name": "Minivan",
|
||||
"date_create": 1399143320,
|
||||
"date_update": 1568054530,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 547,
|
||||
"id_car_model": 415,
|
||||
"id_car_generation": 7885,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399143321,
|
||||
"date_update": 1568054530,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 548,
|
||||
"id_car_model": 416,
|
||||
"id_car_generation": 7886,
|
||||
"name": "Sedan",
|
||||
"date_create": 1399145110,
|
||||
"date_update": 1568054530,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 559,
|
||||
"id_car_model": 423,
|
||||
"id_car_generation": 7159,
|
||||
"name": "Crossover",
|
||||
"date_create": 1399145121,
|
||||
"date_update": 1568054531,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 560,
|
||||
"id_car_model": 424,
|
||||
"id_car_generation": 7888,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399145123,
|
||||
"date_update": 1568054531,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 561,
|
||||
"id_car_model": 425,
|
||||
"id_car_generation": 7889,
|
||||
"name": "Hatchback 5-doors",
|
||||
"date_create": 1399145124,
|
||||
"date_update": 1461885078,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 582,
|
||||
"id_car_model": 432,
|
||||
"id_car_generation": 7892,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399146016,
|
||||
"date_update": 1568054532,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 585,
|
||||
"id_car_model": 434,
|
||||
"id_car_generation": 7161,
|
||||
"name": "Minivan",
|
||||
"date_create": 1399146019,
|
||||
"date_update": 1568054532,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 588,
|
||||
"id_car_model": 436,
|
||||
"id_car_generation": 7895,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399146907,
|
||||
"date_update": 1568054533,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 589,
|
||||
"id_car_model": 437,
|
||||
"id_car_generation": 6922,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399146909,
|
||||
"date_update": 1568054533,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 594,
|
||||
"id_car_model": 441,
|
||||
"id_car_generation": 7897,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399146914,
|
||||
"date_update": 1568054534,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 598,
|
||||
"id_car_model": 443,
|
||||
"id_car_generation": 6947,
|
||||
"name": "Compactvan",
|
||||
"date_create": 1399146917,
|
||||
"date_update": 1461885130,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 602,
|
||||
"id_car_model": 446,
|
||||
"id_car_generation": 7901,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399147804,
|
||||
"date_update": 1568054534,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 603,
|
||||
"id_car_model": 447,
|
||||
"id_car_generation": 134600,
|
||||
"name": "Hatchback",
|
||||
"date_create": 1399147806,
|
||||
"date_update": 1568054534,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 604,
|
||||
"id_car_model": 448,
|
||||
"id_car_generation": 7903,
|
||||
"name": "SUV 3-doors",
|
||||
"date_create": 1399147807,
|
||||
"date_update": 1461885134,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 618,
|
||||
"id_car_model": 461,
|
||||
"id_car_generation": 7911,
|
||||
"name": "Coupe",
|
||||
"date_create": 1399149015,
|
||||
"date_update": 1461885141,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 619,
|
||||
"id_car_model": 462,
|
||||
"id_car_generation": 9293,
|
||||
"name": "SUV",
|
||||
"date_create": 1399149016,
|
||||
"date_update": 1568054535,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 620,
|
||||
"id_car_model": 463,
|
||||
"id_car_generation": 7912,
|
||||
"name": "Coupe",
|
||||
"date_create": 1399149017,
|
||||
"date_update": 1461885141,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 621,
|
||||
"id_car_model": 464,
|
||||
"id_car_generation": 7913,
|
||||
"name": "Pickup One-and-a-half cabin",
|
||||
"date_create": 1399149018,
|
||||
"date_update": 1461885183,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 647,
|
||||
"id_car_model": 472,
|
||||
"id_car_generation": 124181,
|
||||
"name": "Sedan 2-doors",
|
||||
"date_create": 1399149612,
|
||||
"date_update": 1461885189,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 648,
|
||||
"id_car_model": 473,
|
||||
"id_car_generation": 7169,
|
||||
"name": "Cabriolet",
|
||||
"date_create": 1399149614,
|
||||
"date_update": 1568054535,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 651,
|
||||
"id_car_model": 475,
|
||||
"id_car_generation": 7171,
|
||||
"name": "Coupe",
|
||||
"date_create": 1399149615,
|
||||
"date_update": 1568054536,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 652,
|
||||
"id_car_model": 476,
|
||||
"id_car_generation": 7172,
|
||||
"name": "Coupe",
|
||||
"date_create": 1399150203,
|
||||
"date_update": 1461877265,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 653,
|
||||
"id_car_model": 477,
|
||||
"id_car_generation": 7173,
|
||||
"name": "Coupe",
|
||||
"date_create": 1399150204,
|
||||
"date_update": 1461877265,
|
||||
"id_car_type": 1
|
||||
},
|
||||
{
|
||||
"id_car_serie": 657,
|
||||
"id_car_model": 481,
|
||||
"id_car_generation": 7921,
|
||||
"name": "SUV",
|
||||
"date_create": 1399150208,
|
||||
"date_update": 1568054536,
|
||||
"id_car_type": 1
|
||||
}
|
||||
]
|
||||
@ -14,10 +14,16 @@ from .models import (
|
||||
ExteriorColors,
|
||||
InteriorColors,
|
||||
SaleQuotation,
|
||||
CarLocation
|
||||
CarLocation,
|
||||
Organization,
|
||||
Representative,
|
||||
SaleQuotationCar
|
||||
|
||||
)
|
||||
from django.forms import ModelMultipleChoiceField
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import django_tables2 as tables
|
||||
from django.forms import formset_factory
|
||||
|
||||
|
||||
# Dealer Form
|
||||
@ -190,3 +196,35 @@ class QuotationForm(forms.ModelForm):
|
||||
self.fields['cars'].queryset = Car.objects.filter(
|
||||
finances__isnull=False
|
||||
).distinct()
|
||||
|
||||
|
||||
class OrganizationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Organization
|
||||
fields = [
|
||||
'name', 'arabic_name', 'crn', 'vrn',
|
||||
'phone_number', 'address', 'logo',
|
||||
]
|
||||
def __init__(self, *args, **kwargs):
|
||||
dealer = kwargs.pop('dealer', None)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
class RepresentativeForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Representative
|
||||
fields = [
|
||||
'name', 'arabic_name', 'id_number',
|
||||
'phone_number', 'address', 'organization'
|
||||
]
|
||||
def __init__(self, *args, **kwargs):
|
||||
dealer = kwargs.pop('dealer', None)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class CarSelectionTable(tables.Table):
|
||||
select = tables.CheckBoxColumn(accessor="pk", orderable=False)
|
||||
|
||||
class Meta:
|
||||
model = Car
|
||||
fields = ['vin', 'year', 'id_car_make', 'id_car_model']
|
||||
template_name = "django_tables2/bootstrap4.html"
|
||||
|
||||
Binary file not shown.
56
inventory/management/commands/add_id_car_model.py
Normal file
56
inventory/management/commands/add_id_car_model.py
Normal file
@ -0,0 +1,56 @@
|
||||
import csv
|
||||
import os
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import connection
|
||||
from inventory.models import CarTrim
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Add id_car_model column to CarTrim model and populate it using a CSV file.'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# Define the file path relative to the project directory
|
||||
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
file_path = os.path.join(base_dir, 'data/mappings.csv')
|
||||
|
||||
# Step 1: Add the new column if it does not exist
|
||||
with connection.cursor() as cursor:
|
||||
try:
|
||||
cursor.execute("ALTER TABLE inventory_cartrim ADD COLUMN id_car_model INTEGER")
|
||||
self.stdout.write(self.style.SUCCESS("Column 'id_car_model' added successfully."))
|
||||
except Exception as e:
|
||||
self.stdout.write(self.style.WARNING(f"Column 'id_car_model' might already exist: {e}"))
|
||||
|
||||
# Step 2: Read and process the CSV file
|
||||
try:
|
||||
with open(file_path, mode='r', encoding='utf-8-sig') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
|
||||
for row in reader:
|
||||
# Extract id_car_serie and id_car_model from the current row
|
||||
id_car_serie = row.get('id_car_serie')
|
||||
id_car_model = row.get('id_car_model')
|
||||
|
||||
if not id_car_serie or not id_car_model:
|
||||
self.stdout.write(self.style.WARNING(f"Skipping row with missing data: {row}"))
|
||||
continue
|
||||
|
||||
# Step 3: Update CarTrim rows based on the id_car_serie
|
||||
updated_count = CarTrim.objects.filter(id_car_serie=id_car_serie).update(id_car_model=id_car_model)
|
||||
|
||||
# Output progress
|
||||
if updated_count > 0:
|
||||
self.stdout.write(self.style.SUCCESS(
|
||||
f"Updated {updated_count} rows for id_car_serie={id_car_serie} with id_car_model={id_car_model}."
|
||||
))
|
||||
else:
|
||||
self.stdout.write(self.style.WARNING(
|
||||
f"No rows found for id_car_serie={id_car_serie}."
|
||||
))
|
||||
|
||||
self.stdout.write(self.style.SUCCESS("All rows have been processed successfully!"))
|
||||
|
||||
except FileNotFoundError:
|
||||
self.stdout.write(self.style.ERROR(f"File not found: {file_path}"))
|
||||
except Exception as e:
|
||||
self.stdout.write(self.style.ERROR(f"An error occurred: {e}"))
|
||||
39
inventory/management/commands/serie_up.py
Normal file
39
inventory/management/commands/serie_up.py
Normal file
@ -0,0 +1,39 @@
|
||||
import os
|
||||
import csv
|
||||
from django.core.management.base import BaseCommand
|
||||
from inventory.models import CarSerie, CarModel
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Update or add CarSerie entries from a merged CSV file"
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
# Path to the merged CSV file
|
||||
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
file_path = os.path.join(base_dir, "../../data/Updated_Merged_Car_Generation_and_Serie_Data.csv") # Adjust the path if needed
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
self.stdout.write(self.style.ERROR(f"File not found: {file_path}"))
|
||||
return
|
||||
|
||||
with open(file_path, newline='', encoding='utf-8') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
try:
|
||||
car_model = CarModel.objects.get(pk=row['id_car_model'])
|
||||
except CarModel.DoesNotExist:
|
||||
self.stdout.write(self.style.WARNING(f"CarModel with ID {row['id_car_model']} not found"))
|
||||
continue
|
||||
|
||||
car_serie, created = CarSerie.objects.update_or_create(
|
||||
id_car_serie=row['id_car_serie'],
|
||||
defaults={
|
||||
'id_car_model': car_model,
|
||||
'name': row['name'],
|
||||
'arabic_name': "-",
|
||||
'year_begin': int(float(row['year_begin'])) if row['year_begin'] else None,
|
||||
'year_end': int(float(row['year_end'])) if row['year_end'] else None,
|
||||
},
|
||||
)
|
||||
|
||||
action = "Created" if created else "Updated"
|
||||
self.stdout.write(self.style.SUCCESS(f"{action} CarSerie with ID {car_serie.id_car_serie}"))
|
||||
@ -1,6 +1,6 @@
|
||||
from openai import OpenAI
|
||||
from django.core.management.base import BaseCommand
|
||||
from inventory.models import CarSerie
|
||||
from inventory.models import CarSerie, CarModel, CarMake, CarTrim, CarSpecification, CarSpecificationValue
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
@ -9,10 +9,10 @@ class Command(BaseCommand):
|
||||
|
||||
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()
|
||||
car_make = CarMake.objects.all()
|
||||
total = car_make.count()
|
||||
print(f'Translating {total} names...')
|
||||
for index, car_serie in enumerate(car_serie, start=1):
|
||||
for index, car_make in enumerate(car_make, start=1):
|
||||
try:
|
||||
completion = client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
@ -23,14 +23,14 @@ class Command(BaseCommand):
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": car_serie.name
|
||||
"content": car_make.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}'")
|
||||
car_make.arabic_name = translation
|
||||
car_make.save()
|
||||
print(f"[{index}/{total}] Translated '{car_make.name}' to '{translation}'")
|
||||
except Exception as e:
|
||||
print(f"Error translating '{car_serie.name}': {e}")
|
||||
print(f"Error translating '{car_make.name}': {e}")
|
||||
|
||||
34
inventory/management/commands/update_car_make.py
Normal file
34
inventory/management/commands/update_car_make.py
Normal file
@ -0,0 +1,34 @@
|
||||
import os
|
||||
import csv
|
||||
from django.core.management.base import BaseCommand
|
||||
from inventory.models import CarMake
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Update or add CarMake entries from a CSV file"
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
# Path to the car_make CSV file
|
||||
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
file_path = os.path.join(base_dir, "../../data/car_make.csv")
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
self.stdout.write(self.style.ERROR(f"File not found: {file_path}"))
|
||||
return
|
||||
|
||||
with open(file_path, newline='', encoding='utf-8') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
car_make, created = CarMake.objects.get_or_create(
|
||||
id_car_make=row['id_car_make'],
|
||||
defaults={
|
||||
'name': row['name'],
|
||||
'arabic_name': row.get('arabic_name', ''),
|
||||
'logo': row.get('logo', None),
|
||||
'is_sa_import': row.get('is_sa_import', False) in ['1', 'True', 'true'],
|
||||
},
|
||||
)
|
||||
|
||||
if created:
|
||||
self.stdout.write(self.style.SUCCESS(f"Added CarMake with ID {car_make.id_car_make}"))
|
||||
else:
|
||||
self.stdout.write(self.style.WARNING(f"CarMake with ID {car_make.id_car_make} already exists"))
|
||||
37
inventory/management/commands/update_car_model.py
Normal file
37
inventory/management/commands/update_car_model.py
Normal file
@ -0,0 +1,37 @@
|
||||
import os
|
||||
import csv
|
||||
from django.core.management.base import BaseCommand
|
||||
from inventory.models import CarModel, CarMake
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Update or add CarModel entries from a CSV file"
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
# Path to the car_model CSV file
|
||||
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
file_path = os.path.join(base_dir, "../../data/car_model.csv") # Adjust path if needed
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
self.stdout.write(self.style.ERROR(f"File not found: {file_path}"))
|
||||
return
|
||||
|
||||
with open(file_path, newline='', encoding='utf-8') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
try:
|
||||
car_make = CarMake.objects.get(pk=row['id_car_make'])
|
||||
except CarMake.DoesNotExist:
|
||||
self.stdout.write(self.style.WARNING(f"CarMake with ID {row['id_car_make']} not found"))
|
||||
continue
|
||||
|
||||
car_model, created = CarModel.objects.update_or_create(
|
||||
id_car_model=row['id_car_model'],
|
||||
defaults={
|
||||
'id_car_make': car_make,
|
||||
'name': row['name'],
|
||||
'arabic_name': row.get('arabic_name', ''),
|
||||
},
|
||||
)
|
||||
|
||||
action = "Created" if created else "Updated"
|
||||
self.stdout.write(self.style.SUCCESS(f"{action} CarModel with ID {car_model.id_car_model}"))
|
||||
@ -0,0 +1,44 @@
|
||||
import os
|
||||
import csv
|
||||
from django.core.management.base import BaseCommand
|
||||
from inventory.models import CarSpecificationValue, CarSpecification, CarTrim
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Update or add CarSpecificationValue entries from a CSV file"
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
# Path to the car_specification_value CSV file
|
||||
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
file_path = os.path.join(base_dir, "../../data/car_specification_value.csv") # Adjust this path if needed
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
self.stdout.write(self.style.ERROR(f"File not found: {file_path}"))
|
||||
return
|
||||
|
||||
with open(file_path, newline='', encoding='utf-8') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
try:
|
||||
car_trim = CarTrim.objects.get(pk=row['id_car_trim'])
|
||||
except CarTrim.DoesNotExist:
|
||||
self.stdout.write(self.style.WARNING(f"CarTrim with ID {row['id_car_trim']} not found"))
|
||||
continue
|
||||
|
||||
try:
|
||||
car_specification = CarSpecification.objects.get(pk=row['id_car_specification'])
|
||||
except CarSpecification.DoesNotExist:
|
||||
self.stdout.write(self.style.WARNING(f"CarSpecification with ID {row['id_car_specification']} not found"))
|
||||
continue
|
||||
|
||||
car_specification_value, created = CarSpecificationValue.objects.update_or_create(
|
||||
id_car_specification_value=row['id_car_specification_value'],
|
||||
defaults={
|
||||
'id_car_trim': car_trim,
|
||||
'id_car_specification': car_specification,
|
||||
'value': row['value'],
|
||||
'unit': row.get('unit', ''),
|
||||
},
|
||||
)
|
||||
|
||||
action = "Created" if created else "Updated"
|
||||
self.stdout.write(self.style.SUCCESS(f"{action} CarSpecificationValue with ID {car_specification_value.id_car_specification_value}"))
|
||||
47
inventory/management/commands/update_car_trim.py
Normal file
47
inventory/management/commands/update_car_trim.py
Normal file
@ -0,0 +1,47 @@
|
||||
import os
|
||||
import csv
|
||||
from django.core.management.base import BaseCommand
|
||||
from inventory.models import CarTrim, CarSerie, CarModel
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Update or add CarTrim entries from a CSV file"
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
# Path to the car_trim CSV file
|
||||
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
file_path = os.path.join(base_dir, "../../data/car_trim.csv") # Adjust path if needed
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
self.stdout.write(self.style.ERROR(f"File not found: {file_path}"))
|
||||
return
|
||||
|
||||
with open(file_path, newline='', encoding='utf-8') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
try:
|
||||
car_serie = CarSerie.objects.get(pk=row['id_car_serie'])
|
||||
except CarSerie.DoesNotExist:
|
||||
self.stdout.write(self.style.WARNING(f"CarSerie with ID {row['id_car_serie']} not found"))
|
||||
continue
|
||||
|
||||
car_model = None
|
||||
if row['id_car_model']:
|
||||
try:
|
||||
car_model = CarModel.objects.get(pk=row['id_car_model'])
|
||||
except CarModel.DoesNotExist:
|
||||
self.stdout.write(self.style.WARNING(f"CarModel with ID {row['id_car_model']} not found"))
|
||||
|
||||
car_trim, created = CarTrim.objects.update_or_create(
|
||||
id_car_trim=row['id_car_trim'],
|
||||
defaults={
|
||||
'id_car_serie': car_serie,
|
||||
'id_car_model': car_model,
|
||||
'name': row['name'],
|
||||
'arabic_name': row.get('arabic_name', ''),
|
||||
'start_production_year': int(float(row['start_production_year'])) if row['start_production_year'] else None,
|
||||
'end_production_year': int(float(row['end_production_year'])) if row['end_production_year'] else None,
|
||||
},
|
||||
)
|
||||
|
||||
action = "Created" if created else "Updated"
|
||||
self.stdout.write(self.style.SUCCESS(f"{action} CarTrim with ID {car_trim.id_car_trim}"))
|
||||
53
inventory/migrations/0017_organization_representative.py
Normal file
53
inventory/migrations/0017_organization_representative.py
Normal file
@ -0,0 +1,53 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-12 12:44
|
||||
|
||||
import django.db.models.deletion
|
||||
import inventory.mixins
|
||||
import phonenumber_field.modelfields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0016_alter_carfinance_car_alter_customcard_car'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Organization',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, verbose_name='Name')),
|
||||
('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')),
|
||||
('crn', models.CharField(max_length=15, verbose_name='Commercial Registration Number')),
|
||||
('vrn', models.CharField(max_length=15, verbose_name='VAT Registration Number')),
|
||||
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')),
|
||||
('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Address')),
|
||||
('logo', models.ImageField(blank=True, null=True, upload_to='logos', verbose_name='Logo')),
|
||||
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='organizations', to='inventory.dealer')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Organization',
|
||||
'verbose_name_plural': 'Organizations',
|
||||
},
|
||||
bases=(models.Model, inventory.mixins.LocalizedNameMixin),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Representative',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=255, verbose_name='Name')),
|
||||
('arabic_name', models.CharField(max_length=255, verbose_name='Arabic Name')),
|
||||
('id_number', models.CharField(max_length=10, verbose_name='ID Number')),
|
||||
('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region='SA', verbose_name='Phone Number')),
|
||||
('address', models.CharField(blank=True, max_length=200, null=True, verbose_name='Address')),
|
||||
('dealer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='representatives', to='inventory.dealer')),
|
||||
('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='representatives', to='inventory.organization')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Representative',
|
||||
'verbose_name_plural': 'Representatives',
|
||||
},
|
||||
bases=(models.Model, inventory.mixins.LocalizedNameMixin),
|
||||
),
|
||||
]
|
||||
@ -0,0 +1,22 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-12 12:51
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0017_organization_representative'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='representative',
|
||||
name='organization',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='representative',
|
||||
name='organization',
|
||||
field=models.ManyToManyField(related_name='representatives', to='inventory.organization'),
|
||||
),
|
||||
]
|
||||
17
inventory/migrations/0019_remove_carfinance_total.py
Normal file
17
inventory/migrations/0019_remove_carfinance_total.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-15 14:41
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0018_remove_representative_organization_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='carfinance',
|
||||
name='total',
|
||||
),
|
||||
]
|
||||
@ -0,0 +1,45 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-16 01:33
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0019_remove_carfinance_total'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='carfinance',
|
||||
name='administration_fee',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='carfinance',
|
||||
name='custom_card_fee',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='carfinance',
|
||||
name='registration_fee',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='carfinance',
|
||||
name='transportation_fee',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cartrim',
|
||||
name='id_car_model',
|
||||
field=models.ForeignKey(blank=True, db_column='id_car_model', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmodel'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='carfinance',
|
||||
name='car',
|
||||
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='financial_details', to='inventory.car'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='carfinance',
|
||||
name='vat_amount',
|
||||
field=models.DecimalField(decimal_places=2, editable=False, max_digits=14, verbose_name='VAT Amount'),
|
||||
),
|
||||
]
|
||||
@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-16 10:17
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0020_remove_carfinance_administration_fee_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='carserie',
|
||||
name='year_begin',
|
||||
field=models.IntegerField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='carserie',
|
||||
name='year_end',
|
||||
field=models.IntegerField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
@ -0,0 +1,49 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-16 12:54
|
||||
|
||||
import django.db.models.deletion
|
||||
from decimal import Decimal
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0021_carserie_year_begin_carserie_year_end'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='cartrim',
|
||||
name='id_car_model',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='carfinance',
|
||||
name='administration_fee',
|
||||
field=models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=14, verbose_name='Administration Fee'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='carfinance',
|
||||
name='custom_card_fee',
|
||||
field=models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=14, verbose_name='Custom Card Fee'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='carfinance',
|
||||
name='registration_fee',
|
||||
field=models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=14, verbose_name='Registration Fee'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='carfinance',
|
||||
name='transportation_fee',
|
||||
field=models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=14, verbose_name='Transportation Fee'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='carfinance',
|
||||
name='car',
|
||||
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='finances', to='inventory.car'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='carfinance',
|
||||
name='vat_amount',
|
||||
field=models.DecimalField(decimal_places=2, editable=False, max_digits=14, verbose_name='Vat Amount'),
|
||||
),
|
||||
]
|
||||
19
inventory/migrations/0023_cartrim_id_car_model.py
Normal file
19
inventory/migrations/0023_cartrim_id_car_model.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.1.4 on 2024-12-16 19:55
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0022_remove_cartrim_id_car_model_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='cartrim',
|
||||
name='id_car_model',
|
||||
field=models.ForeignKey(blank=True, db_column='id_car_model', null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='inventory.carmodel'),
|
||||
),
|
||||
]
|
||||
@ -17,6 +17,7 @@ from django_ledger.models import (
|
||||
ItemModelQuerySet,
|
||||
|
||||
)
|
||||
from django.db.models import Sum
|
||||
from decimal import Decimal, InvalidOperation
|
||||
from django.core.exceptions import ValidationError
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
@ -58,6 +59,8 @@ class CarSerie(models.Model, LocalizedNameMixin):
|
||||
id_car_model = models.ForeignKey(CarModel, models.DO_NOTHING, db_column='id_car_model')
|
||||
name = models.CharField(max_length=255)
|
||||
arabic_name = models.CharField(max_length=255)
|
||||
year_begin = models.IntegerField(blank=True, null=True)
|
||||
year_end = models.IntegerField(blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@ -73,6 +76,7 @@ class CarTrim(models.Model, LocalizedNameMixin):
|
||||
arabic_name = models.CharField(max_length=255)
|
||||
start_production_year = models.IntegerField(blank=True, null=True)
|
||||
end_production_year = models.IntegerField(blank=True, null=True)
|
||||
id_car_model = models.ForeignKey(CarModel, models.DO_NOTHING, db_column='id_car_model', blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@ -202,26 +206,89 @@ class Car(models.Model):
|
||||
active_reservations = self.reservations.filter(reserved_until__gt=now())
|
||||
return active_reservations.exists()
|
||||
|
||||
@property
|
||||
def finance(self):
|
||||
"""Fetch the first related CarFinance object, or return None."""
|
||||
return self.finances # Assuming a related_name of 'finances'
|
||||
|
||||
def _get_financial_value(self, attribute):
|
||||
"""Reusable method to safely get financial values."""
|
||||
finance = self.finance
|
||||
return getattr(finance, attribute, Decimal('0.00')) if finance else Decimal('0.00')
|
||||
|
||||
def _calculate_vat(self, value):
|
||||
"""Helper to calculate VAT dynamically for a given value."""
|
||||
vat_rate = getattr(settings, 'VAT_RATE', Decimal('0.15')) # Default VAT rate
|
||||
return (value * vat_rate).quantize(Decimal('0.01'))
|
||||
|
||||
@property
|
||||
def cost_price(self):
|
||||
return self._get_financial_value('cost_price')
|
||||
|
||||
@property
|
||||
def selling_price(self):
|
||||
finance = self.finances
|
||||
return finance.selling_price if finance else Decimal('0.00')
|
||||
return self._get_financial_value('selling_price')
|
||||
|
||||
@property
|
||||
def registration_fee(self):
|
||||
return self._get_financial_value('registration_fee')
|
||||
|
||||
@property
|
||||
def administration_fee(self):
|
||||
return self._get_financial_value('administration_fee')
|
||||
|
||||
@property
|
||||
def transportation_fee(self):
|
||||
return self._get_financial_value('transportation_fee')
|
||||
|
||||
@property
|
||||
def custom_card_fee(self):
|
||||
return self._get_financial_value('custom_card_fee')
|
||||
|
||||
@property
|
||||
def discount_amount(self):
|
||||
finance = self.finances
|
||||
return finance.discount_amount if finance else Decimal('0.00')
|
||||
return self._get_financial_value('discount_amount')
|
||||
|
||||
@property
|
||||
def vat_amount(self):
|
||||
finance = self.finances
|
||||
return finance.vat_amount if finance else Decimal('0.00')
|
||||
"""Dynamically calculate VAT for the selling price after discount."""
|
||||
price_after_discount = self.selling_price - self.discount_amount
|
||||
return self._calculate_vat(price_after_discount)
|
||||
|
||||
@property
|
||||
def administration_fee_vat(self):
|
||||
return self._calculate_vat(self.administration_fee)
|
||||
|
||||
@property
|
||||
def transportation_fee_vat(self):
|
||||
return self._calculate_vat(self.transportation_fee)
|
||||
|
||||
@property
|
||||
def custom_card_fee_vat(self):
|
||||
return self._calculate_vat(self.custom_card_fee)
|
||||
|
||||
@property
|
||||
def total_vat_amount(self):
|
||||
"""Sum up the VAT for all applicable fields."""
|
||||
return (
|
||||
self.vat_amount +
|
||||
self.administration_fee_vat +
|
||||
self.transportation_fee_vat +
|
||||
self.custom_card_fee_vat
|
||||
)
|
||||
|
||||
@property
|
||||
def total(self):
|
||||
finance = self.finances
|
||||
return finance.total if finance else Decimal('0.00')
|
||||
|
||||
"""Calculate the total amount including VAT."""
|
||||
price_after_discount = self.selling_price - self.discount_amount
|
||||
subtotal = (
|
||||
price_after_discount +
|
||||
self.registration_fee +
|
||||
self.administration_fee +
|
||||
self.transportation_fee +
|
||||
self.custom_card_fee
|
||||
)
|
||||
return subtotal + self.total_vat_amount
|
||||
|
||||
# class CarData(models.Model):
|
||||
# vin = models.CharField(max_length=17, unique=True, verbose_name=_("VIN"))
|
||||
@ -232,6 +299,7 @@ class Car(models.Model):
|
||||
# year = models.IntegerField(verbose_name=_("Year"))
|
||||
# series = models.CharField(max_length=255,verbose_name=_("Series"))
|
||||
# trim = models.CharField(max_length=255,verbose_name=_("Trim"))
|
||||
# specs = models.JsonField
|
||||
# status = models.CharField(
|
||||
# max_length=10,
|
||||
# choices=CarStatusChoices,
|
||||
@ -289,32 +357,20 @@ class CarFinance(models.Model):
|
||||
default=Decimal('0.00'))
|
||||
custom_card_fee = models.DecimalField(max_digits=14, decimal_places=2, verbose_name=_("Custom Card Fee"),
|
||||
default=Decimal('0.00'))
|
||||
total = models.DecimalField(max_digits=14, decimal_places=2, default=Decimal('0.00'), null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"Car: {self.car}, Selling Price: {self.selling_price}"
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
vat_rate = settings.VAT_RATE
|
||||
# vat_rate = settings.VAT_RATE
|
||||
self.full_clean()
|
||||
try:
|
||||
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) * vat_rate
|
||||
self.vat_amount = price_after_discount * 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
|
||||
self.profit_margin = price_after_discount - self.cost_price
|
||||
except InvalidOperation as e:
|
||||
raise ValidationError(_("Invalid decimal operation: %s") % str(e))
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
@property
|
||||
def total_vat_amount(self):
|
||||
vat_rate = settings.VAT_RATE
|
||||
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) * vat_rate
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Car Financial Details")
|
||||
verbose_name_plural = _("Car Financial Details")
|
||||
@ -514,6 +570,40 @@ class Customer(models.Model):
|
||||
return f"{self.first_name} {self.middle_name} {self.last_name}"
|
||||
|
||||
|
||||
class Organization(models.Model, LocalizedNameMixin):
|
||||
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='organizations')
|
||||
name = models.CharField(max_length=255, verbose_name=_("Name"))
|
||||
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
|
||||
crn = models.CharField(max_length=15, verbose_name=_("Commercial Registration Number"))
|
||||
vrn = models.CharField(max_length=15, verbose_name=_("VAT Registration Number"))
|
||||
phone_number = PhoneNumberField(region='SA', verbose_name=_("Phone Number"))
|
||||
address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
|
||||
logo = models.ImageField(upload_to="logos", blank=True, null=True, verbose_name=_("Logo"))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Organization")
|
||||
verbose_name_plural = _("Organizations")
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Representative(models.Model, LocalizedNameMixin):
|
||||
dealer = models.ForeignKey(Dealer, on_delete=models.CASCADE, related_name='representatives')
|
||||
name = models.CharField(max_length=255, verbose_name=_("Name"))
|
||||
arabic_name = models.CharField(max_length=255, verbose_name=_("Arabic Name"))
|
||||
id_number = models.CharField(max_length=10, verbose_name=_("ID Number"))
|
||||
phone_number = PhoneNumberField(region='SA', verbose_name=_("Phone Number"))
|
||||
address = models.CharField(max_length=200, blank=True, null=True, verbose_name=_("Address"))
|
||||
organization = models.ManyToManyField(Organization, related_name='representatives')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Representative")
|
||||
verbose_name_plural = _("Representatives")
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class SaleQuotation(models.Model):
|
||||
STATUS_CHOICES = [
|
||||
("DRAFT", _("Draft")),
|
||||
@ -528,6 +618,11 @@ class SaleQuotation(models.Model):
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created At"))
|
||||
updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated At"))
|
||||
|
||||
@property
|
||||
def total_quantity(self):
|
||||
total_quantity = self.quotation_cars.aggregate(total=Sum('quantity'))['total']
|
||||
return total_quantity or 0
|
||||
|
||||
def confirm(self):
|
||||
"""Confirm the quotation and lock financial details."""
|
||||
if self.status != "DRAFT":
|
||||
@ -558,15 +653,15 @@ 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."""
|
||||
car_finance = self.car.finances.first()
|
||||
@property
|
||||
def financial_details(self):
|
||||
"""
|
||||
Retrieve financial details dynamically from CarFinance.
|
||||
Returns a dictionary with all financial fields for better access.
|
||||
"""
|
||||
car_finance = self.car.finances
|
||||
if not car_finance:
|
||||
return None
|
||||
|
||||
@ -576,11 +671,20 @@ class SaleQuotationCar(models.Model):
|
||||
"transportation_fee": car_finance.transportation_fee,
|
||||
"custom_card_fee": car_finance.custom_card_fee,
|
||||
"registration_fee": car_finance.registration_fee,
|
||||
"vat_rate": car_finance.vat_rate,
|
||||
"discount_amount": car_finance.discount_amount,
|
||||
"total_amount": car_finance.total,
|
||||
"vat_amount": car_finance.vat_amount,
|
||||
# "total_amount": car_finance.total,
|
||||
}
|
||||
|
||||
@property
|
||||
def total_price(self):
|
||||
"""
|
||||
Calculate total price dynamically based on quantity and selling price.
|
||||
"""
|
||||
car_finance = self.car.finances
|
||||
if not car_finance:
|
||||
return Decimal("0.00")
|
||||
return car_finance.selling_price * self.quantity
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.car} - Quotation #{self.quotation.id}"
|
||||
|
||||
|
||||
@ -4,6 +4,9 @@ Services module
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
from django_ledger.models import EntityModel
|
||||
|
||||
from .utils import get_jwt_token
|
||||
from pyvin import VIN
|
||||
from django.conf import settings
|
||||
@ -75,3 +78,8 @@ def elm(vin):
|
||||
|
||||
return data if all([x for x in data.values()]) else None
|
||||
|
||||
|
||||
def get_ledger_data(request):
|
||||
entity = EntityModel.objects.filter(name="Marwan2").first()
|
||||
data = entity.get_items_all()
|
||||
print(data)
|
||||
@ -2,9 +2,16 @@ 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, AccountModel, \
|
||||
from django_ledger.models import (EntityModel,
|
||||
VendorModel,
|
||||
CustomerModel,
|
||||
UnitOfMeasureModel,
|
||||
AccountModel,
|
||||
ItemModelAbstract
|
||||
)
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
@ -46,21 +53,21 @@ def update_car_status_on_reservation_delete(sender, instance, **kwargs):
|
||||
|
||||
|
||||
# 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"))
|
||||
@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,
|
||||
accrual_method=False,
|
||||
fy_start_month=1,
|
||||
# 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,
|
||||
@ -108,15 +115,15 @@ def update_car_status_on_reservation_delete(sender, instance, **kwargs):
|
||||
# active=True)
|
||||
|
||||
|
||||
# if default_coa:
|
||||
# entity.populate_default_coa(activate_accounts=True, coa_model=default_coa)
|
||||
#
|
||||
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}")
|
||||
|
||||
print(f"Ledger entity created for Dealer: {instance.name}")
|
||||
|
||||
|
||||
# Create Vendor
|
||||
|
||||
@ -2,8 +2,10 @@ from django.utils.html import format_html
|
||||
|
||||
from django.conf import settings
|
||||
from . import models
|
||||
import django_tables2 as tables
|
||||
from django_tables2.utils import A
|
||||
import django_tables2 as tables
|
||||
from django import forms
|
||||
from inventory.models import Car, SaleQuotation, SaleQuotationCar
|
||||
|
||||
|
||||
class ImageColumn(tables.Column):
|
||||
@ -16,3 +18,4 @@ class CustomerTable(tables.Table):
|
||||
model = models.Customer
|
||||
first_name = tables.Column()
|
||||
|
||||
|
||||
|
||||
@ -64,13 +64,27 @@ urlpatterns = [
|
||||
path('reservations/<int:reservation_id>/', views.manage_reservation, name='reservations'),
|
||||
path('cars/<int:car_pk>/add-custom-card/', views.CustomCardCreateView.as_view(), name='add_custom_card'),
|
||||
|
||||
# Sales URLs
|
||||
# Sales URLs quotation_create
|
||||
path('sales/quotations/create/', views.QuotationCreateView.as_view(), name='quotation_create'),
|
||||
path('sales/quotations/<int:pk>/', views.QuotationDetailView.as_view(), name='quotation_detail'),
|
||||
path('sales/quotations/', views.QuotationListView.as_view(), name='quotation_list'),
|
||||
path('sales/quotations/<int:pk>/confirm/', views.confirm_quotation, name='confirm_quotation'),
|
||||
path('sales/orders/detail/<int:order_id>/', views.SalesOrderDetailView.as_view(), name='order_detail'),
|
||||
|
||||
# Organization URLs
|
||||
path('organizations/', views.OrganizationListView.as_view(), name='organization_list'),
|
||||
path('organizations/<int:pk>/', views.OrganizationDetailView.as_view(), name='organization_detail'),
|
||||
path('organizations/create/', views.OrganizationCreateView.as_view(), name='organization_create'),
|
||||
path('organizations/<int:pk>/update/', views.OrganizationUpdateView.as_view(), name='organization_update'),
|
||||
path('organizations/<int:pk>/delete/', views.OrganizationDeleteView.as_view(), name='organization_delete'),
|
||||
|
||||
# Representative URLs
|
||||
path('representatives/', views.RepresentativeListView.as_view(), name='representative_list'),
|
||||
path('representatives/<int:pk>/', views.RepresentativeDetailView.as_view(), name='representative_detail'),
|
||||
path('representatives/create/', views.RepresentativeCreateView.as_view(), name='representative_create'),
|
||||
path('representatives/<int:pk>/update/', views.RepresentativeUpdateView.as_view(), name='representative_update'),
|
||||
path('representatives/<int:pk>/delete/', views.RepresentativeDeleteView.as_view(), name='representative_delete'),
|
||||
|
||||
]
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import logging
|
||||
import json
|
||||
from decimal import Decimal
|
||||
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from vin import VIN
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
@ -24,11 +26,12 @@ 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, decodevin,get_make,get_model,normalize_name
|
||||
from .services import elm, decodevin, get_make, get_model, normalize_name, get_ledger_data
|
||||
from . import models, forms
|
||||
from django_tables2.export.views import ExportMixin
|
||||
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
@ -63,6 +66,7 @@ def switch_language(request):
|
||||
class HomeView(LoginRequiredMixin, TemplateView):
|
||||
template_name = 'index.html'
|
||||
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not hasattr(request.user, 'dealer') or not request.user.is_authenticated:
|
||||
messages.error(request, _('You are not associated with any dealer.'))
|
||||
@ -138,7 +142,7 @@ class AjaxHandlerView(LoginRequiredMixin, View):
|
||||
vin_data = {}
|
||||
decoding_method = ''
|
||||
|
||||
# manufacturer_name = model_name = year_model = None
|
||||
manufacturer_name = model_name = year_model = None
|
||||
if not (result :=decodevin(vin_no)):
|
||||
return JsonResponse({'success': False, 'error': 'VIN not found in all sources.'}, status=404)
|
||||
|
||||
@ -174,16 +178,29 @@ class AjaxHandlerView(LoginRequiredMixin, View):
|
||||
|
||||
def get_series(self, request):
|
||||
model_id = request.GET.get('model_id')
|
||||
year = request.GET.get('year')
|
||||
|
||||
# Validate inputs
|
||||
if not model_id or not year:
|
||||
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')
|
||||
id_car_model=model_id).values(
|
||||
'id_car_serie', 'name', 'arabic_name'
|
||||
)
|
||||
|
||||
return JsonResponse(list(series), safe=False)
|
||||
|
||||
def get_trims(self, request):
|
||||
serie_id = request.GET.get('serie_id')
|
||||
model_id = request.GET.get('model_id')
|
||||
trims = models.CarTrim.objects.filter(
|
||||
id_car_serie=serie_id
|
||||
).values('id_car_trim', 'name', 'arabic_name')
|
||||
id_car_serie=serie_id, id_car_model=model_id).values('id_car_trim', 'name', 'arabic_name')
|
||||
return JsonResponse(list(trims), safe=False)
|
||||
|
||||
def get_specifications(self, request):
|
||||
@ -674,7 +691,7 @@ class QuotationCreateView(LoginRequiredMixin, CreateView):
|
||||
quotation = form.save()
|
||||
selected_cars = form.cleaned_data.get("cars")
|
||||
for car in selected_cars:
|
||||
car_finance = car.finances.first()
|
||||
car_finance = car.finances
|
||||
if car_finance:
|
||||
models.SaleQuotationCar.objects.create(
|
||||
quotation=quotation,
|
||||
@ -704,6 +721,32 @@ class QuotationDetailView(LoginRequiredMixin, DetailView):
|
||||
template_name = "sales/quotation_detail.html"
|
||||
context_object_name = "quotation"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
quotation = self.object
|
||||
|
||||
# Totals Calculation
|
||||
context['vat_rate'] = settings.VAT_RATE
|
||||
context['total_sales_before_vat'] = sum(item.car.selling_price * item.quantity for item in quotation.quotation_cars.all())
|
||||
context['vat_amount'] = sum(item.car.vat_amount * item.quantity for item in quotation.quotation_cars.all())
|
||||
context['total_sales_after_vat'] = context['total_sales_before_vat'] + context['vat_amount']
|
||||
|
||||
# Additional Costs
|
||||
total_quantity = quotation.total_quantity
|
||||
context['administration_fee'] = sum(item.car.administration_fee for item in quotation.quotation_cars.all())
|
||||
context['transportation_fee'] = sum(item.car.transportation_fee for item in quotation.quotation_cars.all())
|
||||
context['custom_card_fee'] = sum(item.car.custom_card_fee for item in quotation.quotation_cars.all())
|
||||
context['registration_fee'] = sum(item.car.registration_fee for item in quotation.quotation_cars.all())
|
||||
context['administration_fee_vat'] = sum(item.car.administration_fee_vat for item in quotation.quotation_cars.all())
|
||||
context['transportation_fee_vat'] = sum(item.car.transportation_fee_vat for item in quotation.quotation_cars.all())
|
||||
context['custom_card_fee_vat'] = sum(item.car.custom_card_fee_vat for item in quotation.quotation_cars.all())
|
||||
context['administration_fee_total'] = sum(item.car.administration_fee + context['administration_fee_vat'] for item in quotation.quotation_cars.all())
|
||||
context['transportation_fee_total'] = sum(item.car.transportation_fee + context['transportation_fee_vat'] for item in quotation.quotation_cars.all())
|
||||
context['custom_card_fee_total'] = sum(item.car.custom_card_fee + context['custom_card_fee_vat'] for item in quotation.quotation_cars.all())
|
||||
context['registration_fee_total'] = sum(item.car.registration_fee * total_quantity for item in quotation.quotation_cars.all())
|
||||
|
||||
return context
|
||||
|
||||
|
||||
@login_required
|
||||
def confirm_quotation(request, pk):
|
||||
@ -724,3 +767,91 @@ class SalesOrderDetailView(LoginRequiredMixin, DetailView):
|
||||
model = models.SalesOrder
|
||||
template_name = "sales/sales_order_detail.html"
|
||||
context_object_name = "sales_order"
|
||||
|
||||
|
||||
class OrganizationListView(LoginRequiredMixin, ListView):
|
||||
model = models.Organization
|
||||
template_name = 'organizations/organization_list.html'
|
||||
context_object_name = 'organizations'
|
||||
|
||||
|
||||
class OrganizationDetailView(DetailView):
|
||||
model = models.Organization
|
||||
template_name = 'organizations/organization_detail.html'
|
||||
context_object_name = 'organization'
|
||||
|
||||
|
||||
class OrganizationCreateView(LoginRequiredMixin, CreateView):
|
||||
model = models.Organization
|
||||
form_class = forms.OrganizationForm
|
||||
template_name = 'organizations/organization_form.html'
|
||||
success_url = reverse_lazy('organization_list')
|
||||
|
||||
def form_valid(self, form):
|
||||
if form.is_valid():
|
||||
form.instance.dealer = self.request.user.dealer
|
||||
form.save()
|
||||
success_message = "Organization created successfully."
|
||||
return super().form_valid(form)
|
||||
else:
|
||||
return form.errors
|
||||
|
||||
|
||||
class OrganizationUpdateView(LoginRequiredMixin, UpdateView):
|
||||
model = models.Organization
|
||||
form_class = forms.OrganizationForm
|
||||
template_name = 'organizations/organization_form.html'
|
||||
success_url = reverse_lazy('organization_list')
|
||||
success_message = "Organization updated successfully."
|
||||
|
||||
|
||||
class OrganizationDeleteView(LoginRequiredMixin, DeleteView):
|
||||
model = models.Organization
|
||||
template_name = 'organizations/organization_confirm_delete.html'
|
||||
success_url = reverse_lazy('organization_list')
|
||||
success_message = "Organization deleted successfully."
|
||||
|
||||
|
||||
class RepresentativeListView(LoginRequiredMixin, ListView):
|
||||
model = models.Representative
|
||||
template_name = 'representatives/representative_list.html'
|
||||
context_object_name = 'representatives'
|
||||
|
||||
|
||||
class RepresentativeDetailView(DetailView):
|
||||
model = models.Representative
|
||||
template_name = 'representatives/representative_detail.html'
|
||||
context_object_name = 'representative'
|
||||
|
||||
|
||||
class RepresentativeCreateView(LoginRequiredMixin, CreateView):
|
||||
model = models.Representative
|
||||
form_class = forms.RepresentativeForm
|
||||
template_name = 'representatives/representative_form.html'
|
||||
success_url = reverse_lazy('representative_list')
|
||||
|
||||
def form_valid(self, form):
|
||||
if form.is_valid():
|
||||
form.instance.dealer = self.request.user.dealer
|
||||
form.save()
|
||||
success_message = "Representative created successfully."
|
||||
return super().form_valid(form)
|
||||
else:
|
||||
return form.errors
|
||||
|
||||
|
||||
class RepresentativeUpdateView(LoginRequiredMixin, UpdateView):
|
||||
model = models.Representative
|
||||
form_class = forms.RepresentativeForm
|
||||
template_name = 'representatives/representative_form.html'
|
||||
success_url = reverse_lazy('representative_list')
|
||||
success_message = "Representative updated successfully."
|
||||
|
||||
|
||||
class RepresentativeDeleteView(LoginRequiredMixin, DeleteView):
|
||||
model = models.Representative
|
||||
template_name = 'representatives/representative_confirm_delete.html'
|
||||
success_url = reverse_lazy('representative_list')
|
||||
success_message = "Representative deleted successfully."
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
28
merge_db.py
Normal file
28
merge_db.py
Normal file
@ -0,0 +1,28 @@
|
||||
import pymysql
|
||||
from sqlalchemy import create_engine
|
||||
import pandas as pd
|
||||
|
||||
# Database connection
|
||||
engine = create_engine("mysql+pymysql://root:Kfsh&rc9788@localhost/car2db_01112024")
|
||||
|
||||
try:
|
||||
# Load car_generation table
|
||||
car_generation_query = "SELECT * FROM car_generation;"
|
||||
car_generation_df = pd.read_sql(car_generation_query, engine)
|
||||
|
||||
# Load car_serie table
|
||||
car_serie_query = "SELECT * FROM car_serie;"
|
||||
car_serie_df = pd.read_sql(car_serie_query, engine)
|
||||
|
||||
# Merge tables on the appropriate column (e.g., generation_id)
|
||||
merged_df = pd.merge(car_generation_df, car_serie_df, on="id_car_generation", how="inner")
|
||||
|
||||
# Select only the desired columns
|
||||
final_df = merged_df[["id_car_serie", "id_car_model_y", "name_x", "name_y", "year_begin", "year_end"]]
|
||||
|
||||
# Save the filtered data to a JSON file
|
||||
final_df.to_json("merged_car_data.json", orient="records", indent=4)
|
||||
print("Filtered merged data saved to 'merged_car_data.json'.")
|
||||
|
||||
except Exception as e:
|
||||
print("Error:", e)
|
||||
126106
merged_car_data.json
Normal file
126106
merged_car_data.json
Normal file
File diff suppressed because it is too large
Load Diff
1340
new_wmis.py
1340
new_wmis.py
File diff suppressed because it is too large
Load Diff
@ -76,6 +76,58 @@
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle"
|
||||
href="#" id="customerDropdown"
|
||||
role="button" data-bs-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
{% trans 'organizations' %}
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="customerDropdown">
|
||||
<li>
|
||||
<a href="{% url 'organization_create' %}"
|
||||
class="dropdown-item fw-lighter">
|
||||
<small>
|
||||
{% trans "add organization" %}
|
||||
</small>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'organization_list' %}"
|
||||
class="dropdown-item fw-lighter">
|
||||
<small>
|
||||
{% trans "organizations" %}
|
||||
</small>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle"
|
||||
href="#" id="customerDropdown"
|
||||
role="button" data-bs-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
{% trans 'sales' %}
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="customerDropdown">
|
||||
<li>
|
||||
<a href="{% url 'quotation_create' %}"
|
||||
class="dropdown-item fw-lighter">
|
||||
<small>
|
||||
{% trans "create quotation" %}
|
||||
</small>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'quotation_list' %}"
|
||||
class="dropdown-item fw-lighter">
|
||||
<small>
|
||||
{% trans "quotations" %}
|
||||
</small>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle"
|
||||
|
||||
@ -467,7 +467,7 @@ async function updateFields(vinData) {
|
||||
if (vinData.model_id) {
|
||||
modelSelect.value = vinData.model_id;
|
||||
document.getElementById("model-check").innerHTML = '✓';
|
||||
await loadSeries(vinData.model_id);
|
||||
await loadSeries(vinData.model_id, vinData.year);
|
||||
}
|
||||
if (vinData.year) {
|
||||
yearSelect.value = vinData.year;
|
||||
@ -483,7 +483,7 @@ async function startScanner() {
|
||||
if (result) {
|
||||
vinInput.value = result.text;
|
||||
closeModal();
|
||||
decodeVin();
|
||||
await decodeVin();
|
||||
}
|
||||
}).catch(console.error);
|
||||
}
|
||||
@ -540,11 +540,11 @@ async function loadModels(makeId) {
|
||||
|
||||
|
||||
|
||||
async function loadSeries(modelId){
|
||||
async function loadSeries(modelId, year){
|
||||
resetDropdown(serieSelect, '{% trans "Select" %}');
|
||||
resetDropdown(trimSelect, '{% trans "Select" %}');
|
||||
specificationsContent.innerHTML = '';
|
||||
const response = await fetch(`${ajaxUrl}?action=get_series&model_id=${modelId}`, {
|
||||
const response = await fetch(`${ajaxUrl}?action=get_series&model_id=${modelId}&year=${year}`, {
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'X-CSRFToken': csrfToken
|
||||
|
||||
10
templates/organizations/organization_confirm_delete.html
Normal file
10
templates/organizations/organization_confirm_delete.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
21
templates/organizations/organization_detail.html
Normal file
21
templates/organizations/organization_detail.html
Normal file
@ -0,0 +1,21 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Organization Details" %}{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="container my-4">
|
||||
<h2>{{ organization.get_local_name }}</h2>
|
||||
<ul class="list-group mb-4">
|
||||
<li class="list-group-item"><strong>{% trans "CRN" %}:</strong> {{ organization.crn }}</li>
|
||||
<li class="list-group-item"><strong>{% trans "VRN" %}:</strong> {{ organization.vrn }}</li>
|
||||
<li class="list-group-item"><strong>{% trans "Phone" %}:</strong> {{ organization.phone_number }}</li>
|
||||
<li class="list-group-item"><strong>{% trans "Address" %}:</strong> {{ organization.address }}</li>
|
||||
</ul>
|
||||
<div class="d-flex">
|
||||
<a href="{% url 'organization_update' organization.id %}" class="btn btn-sm btn-warning me-2">{% trans "Edit" %}</a>
|
||||
<form method="post" action="{% url 'organization_delete' organization.id %}">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-danger">{% trans "Delete" %}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
16
templates/organizations/organization_form.html
Normal file
16
templates/organizations/organization_form.html
Normal file
@ -0,0 +1,16 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% block title %}{% trans "Add Organization" %}{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="container my-4">
|
||||
<h2>{% trans "Add Organization" %}</h2>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
|
||||
<button type="submit" class="btn btn-sm btn-primary">{% trans "Save" %}</button>
|
||||
<a href="{% url 'organization_list' %}" class="btn btn-sm btn-secondary">{% trans "Cancel" %}</a>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
43
templates/organizations/organization_list.html
Normal file
43
templates/organizations/organization_list.html
Normal file
@ -0,0 +1,43 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Organizations" %}{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="container my-4">
|
||||
<h2>{% trans "Organizations" %}</h2>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<form method="get" class="d-flex">
|
||||
<input type="text" name="q" class="form-control form-control-sm" placeholder="{% trans 'Search' %}" value="{{ request.GET.q }}">
|
||||
<button type="submit" class="btn btn-sm btn-secondary ms-2">{% trans "Search" %}</button>
|
||||
</form>
|
||||
<a href="{% url 'organization_create' %}" class="btn btn-sm btn-primary">{% trans "Add Organization" %}</a>
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Name" %}</th>
|
||||
<th>{% trans "CRN" %}</th>
|
||||
<th>{% trans "VRN" %}</th>
|
||||
<th>{% trans "Phone" %}</th>
|
||||
<th>{% trans "Actions" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for org in organizations %}
|
||||
<tr>
|
||||
<td>{{ org.get_local_name }}</td>
|
||||
<td>{{ org.crn }}</td>
|
||||
<td>{{ org.vrn }}</td>
|
||||
<td>{{ org.phone_number }}</td>
|
||||
<td>
|
||||
<a href="{% url 'organization_detail' org.id %}" class="btn btn-sm btn-success">{% trans "view" %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="5" class="text-center">{% trans "No organizations found." %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
10
templates/representatives/representative_confirm_delete.html
Normal file
10
templates/representatives/representative_confirm_delete.html
Normal file
@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
20
templates/representatives/representative_detail.html
Normal file
20
templates/representatives/representative_detail.html
Normal file
@ -0,0 +1,20 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Representative Details" %}{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="container my-4">
|
||||
<h2>{{ representative.get_local_name }}</h2>
|
||||
<ul class="list-group mb-4">
|
||||
<li class="list-group-item"><strong>{% trans "ID Number" %}:</strong> {{ representative.id_number }}</li>
|
||||
<li class="list-group-item"><strong>{% trans "Phone" %}:</strong> {{ representative.phone_number }}</li>
|
||||
<li class="list-group-item"><strong>{% trans "Address" %}:</strong> {{ representative.address }}</li>
|
||||
</ul>
|
||||
<div class="d-flex">
|
||||
<a href="{% url 'representative_update' representative.id %}" class="btn btn-sm btn-warning me-2">{% trans "Edit" %}</a>
|
||||
<form method="post" action="{% url 'representative_delete' representative.id %}">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-danger">{% trans "Delete" %}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
15
templates/representatives/representative_form.html
Normal file
15
templates/representatives/representative_form.html
Normal file
@ -0,0 +1,15 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_filters %}
|
||||
{% block title %}{% trans "Add Representative" %}{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="container my-4">
|
||||
<h2>{% trans "Add Representative" %}</h2>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<button type="submit" class="btn btn-sm btn-primary">{% trans "Save" %}</button>
|
||||
<a href="{% url 'representative_list' %}" class="btn btn-sm btn-secondary">{% trans "Cancel" %}</a>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
41
templates/representatives/representative_list.html
Normal file
41
templates/representatives/representative_list.html
Normal file
@ -0,0 +1,41 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Representatives" %}{% endblock title %}
|
||||
{% block content %}
|
||||
<div class="container my-4">
|
||||
<h2>{% trans "Representatives" %}</h2>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<form method="get" class="d-flex">
|
||||
<input type="text" name="q" class="form-control form-control-sm" placeholder="{% trans 'Search' %}" value="{{ request.GET.q }}">
|
||||
<button type="submit" class="btn btn-sm btn-secondary ms-2">{% trans "Search" %}</button>
|
||||
</form>
|
||||
<a href="{% url 'representative_create' %}" class="btn btn-sm btn-primary">{% trans "Add Representative" %}</a>
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Name" %}</th>
|
||||
<th>{% trans "ID Number" %}</th>
|
||||
<th>{% trans "Phone" %}</th>
|
||||
<th>{% trans "Actions" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for rep in representatives %}
|
||||
<tr>
|
||||
<td>{{ rep.get_local_name }}</td>
|
||||
<td>{{ rep.id_number }}</td>
|
||||
<td>{{ rep.phone_number }}</td>
|
||||
<td>
|
||||
<a href="{% url 'representative_detail' rep.id %}" class="btn btn-sm btn-success">{% trans "view" %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="4" class="text-center">{% trans "No representatives found." %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -1,4 +1,5 @@
|
||||
{% extends "base.html" %}
|
||||
{% load custom_filters %}
|
||||
{% load i18n %}
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
@ -28,11 +29,13 @@
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>VIN</th>
|
||||
<th>Model</th>
|
||||
<th>Selling Price</th>
|
||||
<th>VAT</th>
|
||||
<th>Total</th>
|
||||
<th>{% trans "VIN" %}</th>
|
||||
<th>{% trans "Model" %}</th>
|
||||
<th>{% trans "Year" %}</th>
|
||||
<th>{% trans "Quantity" %}</th>
|
||||
<th>{% trans "Price" %}</th>
|
||||
<th>{% trans "VAT" %}</th>
|
||||
<th>{% trans "Total" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -40,6 +43,8 @@
|
||||
<tr>
|
||||
<td>{{ item.car.vin }}</td>
|
||||
<td>{{ item.car.id_car_model.get_local_name }}</td>
|
||||
<td>{{ item.car.year }}</td>
|
||||
<td>{{ item.quantity }}</td>
|
||||
<td>{{ item.car.selling_price }}</td>
|
||||
<td>{{ item.car.vat_amount }}</td>
|
||||
<td>{{ item.car.total }}</td>
|
||||
@ -48,28 +53,51 @@
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<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>
|
||||
<th colspan="3">{% trans "Totals" %}</th>
|
||||
<th>{{ quotation.total_quantity }}</th>
|
||||
<th>{{ total_sales_before_vat }}</th>
|
||||
<th>{{ vat_amount }}</th>
|
||||
<th>{{ total_sales_after_vat }}</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</table>
|
||||
|
||||
<h5 class="mt-4">{% trans "Summary" %}</h5>
|
||||
<h5 class="mt-4">{% trans "Additional Costs" %}</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Total Sales Before VAT" %}</th>
|
||||
<td>{{ quotations.total_sales_before_vat }}</td>
|
||||
<th>{% trans "Additions" %}</th>
|
||||
<th>{% trans "Cost" %}</th>
|
||||
<th>{% trans "VAT" %}</th>
|
||||
<th>{% trans "Total Cost with VAT" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{% trans "Administration Fee" %}</td>
|
||||
<td>{{ administration_fee }}</td>
|
||||
<td>{{ administration_fee_vat }}</td>
|
||||
<td>{{ administration_fee_total }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "VAT Amount" %}</th>
|
||||
<td>{{ quotations.vat_amount }}</td>
|
||||
<td>{% trans "Transportation Fee" %}</td>
|
||||
<td>{{ transportation_fee }}</td>
|
||||
<td>{{ transportation_fee_vat }}</td>
|
||||
<td>{{ transportation_fee_total }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Total Sales After VAT" %}</th>
|
||||
<td>{{ quotations.total_sales_after_vat }}</td>
|
||||
<td>{% trans "Custom Card Fee" %}</td>
|
||||
<td>{{ custom_card_fee }}</td>
|
||||
<td>{{ custom_card_fee_vat }}</td>
|
||||
<td>{{ custom_card_fee_total }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{% trans "Registration Fee (No VAT)" %}</td>
|
||||
<td>{{ registration_fee }}</td>
|
||||
<td>{% trans "N/A" %}</td>
|
||||
<td>{{ registration_fee_total }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card-footer text-end">
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
<tbody>
|
||||
{% for quotation in quotations %}
|
||||
<tr>
|
||||
|
||||
<td>{{ forloop.counter }}</td>
|
||||
<td>{{ quotation.customer.get_full_name }}</td>
|
||||
<td>{{ quotation.quotation_cars.count }}</td>
|
||||
@ -28,7 +29,7 @@
|
||||
<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">
|
||||
{% trans "View" %}
|
||||
{% trans "view" %}
|
||||
</a>
|
||||
|
||||
</td>
|
||||
|
||||
108
testapi.py
108
testapi.py
@ -1,5 +1,5 @@
|
||||
|
||||
from vin import VIN
|
||||
# from vin import VIN
|
||||
import requests
|
||||
import json
|
||||
|
||||
@ -7,45 +7,45 @@ import json
|
||||
#
|
||||
# print(details)
|
||||
|
||||
# from vininfo import Vin
|
||||
#
|
||||
#
|
||||
# def vin_info_py(vin_no):
|
||||
#
|
||||
# # vin_no = 'VR3FDAHD1S3023105'
|
||||
# vin_dic = {}
|
||||
# vin_info = Vin(vin_no)
|
||||
# vin_dic['country'] = vin_info.country
|
||||
# vin_dic['manufacturer'] = vin_info.manufacturer
|
||||
# vin_dic['region'] = vin_info.region
|
||||
# vin_dic['produce_year'] = vin_info.years
|
||||
# vin_dic['model_year'] = vin_info.years
|
||||
#
|
||||
# details = vin_info.details
|
||||
# if details:
|
||||
# vin_dic['details'] = True
|
||||
# vin_dic['body'] = str(details.body)
|
||||
# # vin_dic['engine'] = f"{details.engine}"
|
||||
# vin_dic['model'] = f"{details.model}"
|
||||
# vin_dic['plant'] = f"{details.plant}"
|
||||
# vin_dic['serial'] = f"{details.serial}"
|
||||
# vin_dic['transmission'] = f"{details.transmission}"
|
||||
#
|
||||
# for key, value in vin_dic.items():
|
||||
# print(f'\t{key}:\t{value}')
|
||||
#
|
||||
# print("Decoded By ****vin_info****")
|
||||
# print(vin_info.vds)
|
||||
#
|
||||
# else:
|
||||
# print(vin_info.country)
|
||||
# print(vin_info.manufacturer)
|
||||
# print(vin_info.region)
|
||||
# print(vin_info.years)
|
||||
# print(vin_info.wmi)
|
||||
# print(vin_info.vds)
|
||||
# print(vin_info.vis)
|
||||
# print('vin_info but no details')
|
||||
from vininfo import Vin
|
||||
|
||||
|
||||
# def vin_info_py():
|
||||
|
||||
vin_no = 'VYFED9HP0SJ519559'
|
||||
vin_dic = {}
|
||||
vin_info = Vin(vin_no)
|
||||
vin_dic['country'] = vin_info.country
|
||||
vin_dic['manufacturer'] = vin_info.manufacturer
|
||||
vin_dic['region'] = vin_info.region
|
||||
vin_dic['produce_year'] = vin_info.years
|
||||
vin_dic['model_year'] = vin_info.years
|
||||
|
||||
details = vin_info.details
|
||||
if details:
|
||||
vin_dic['details'] = True
|
||||
vin_dic['body'] = str(details.body)
|
||||
# vin_dic['engine'] = f"{details.engine}"
|
||||
vin_dic['model'] = f"{details.model}"
|
||||
vin_dic['plant'] = f"{details.plant}"
|
||||
vin_dic['serial'] = f"{details.serial}"
|
||||
vin_dic['transmission'] = f"{details.transmission}"
|
||||
|
||||
for key, value in vin_dic.items():
|
||||
print(f'\t{key}:\t{value}')
|
||||
|
||||
print("Decoded By ****vin_info****")
|
||||
print(vin_info.vds)
|
||||
|
||||
else:
|
||||
print(vin_info.country)
|
||||
print(vin_info.manufacturer)
|
||||
print(vin_info.region)
|
||||
print(vin_info.years)
|
||||
print(vin_info.wmi)
|
||||
print(vin_info.vds)
|
||||
print(vin_info.vis)
|
||||
print('vin_info but no details')
|
||||
#
|
||||
#
|
||||
# from pyvin import VIN
|
||||
@ -76,20 +76,20 @@ import json
|
||||
|
||||
|
||||
|
||||
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)
|
||||
# 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
|
||||
#
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user